Stop Writing Your Own CodeβββUse These Java Libraries Instead
In this article, we’ll show you 15 things you should stop building from scratchβββand which modern Java tools and libraries to use instead.
π Hey Java developers,
Let’s admit it: we’ve all reinvented the wheel at some point.
- Manually parsing JSON
- Crafting object mappers line by line
- Manually creating a Utility for String Handling
- Manually creating a Utility for Date Handling
- Manually creating a Utility for Collections Handling
- Writing custom HTTP clients
- Coding retry logic from scratch
- Handling nulls manually
- Logging withΒ
System.out.println()
But in 2025, there’s no excuse.
Java has evolved. The ecosystem has matured. Libraries are battle-tested. And now, modern Java features like records, HttpClient, new String methods, and Optional make it easier than ever to write clean, concise code β without doing everything yourself.
In this article, we’ll show you 15 things you should stop building from scratch β and which modern Java tools and libraries to use instead.
β 1. Writing Your Own JSON Parser
β Use: Jackson or Gson
If you’re still building JSON with string concatenation, stop now.
Use Jackson to write and read the JSON:
CopyObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(new Product("Laptop", 899.99));
Or, to read:
CopyProduct product = mapper.readValue(json, Product.class);
β Jackson supports:
- Records (Java 14+)
- Optional fields
- Date/time support
- Custom serializers
π‘ Modern Tip: Use @JsonInclude
, @JsonProperty
and Java Records for clean JSON mapping.
Jackson ObjectMapper: The Complete Guide
Jackson is a widely used Java library for converting Java objects to/from JSON. Convert Java Object to JSON and JSON toβ¦
Google GSON Tutorial
Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used toβ¦
β 2. Manually Mapping Entities to DTOs
β Use: MapStruct
Writing this is a productivity killer:
CopyProductDTO dto = new ProductDTO(product.getId(), product.getName());
Instead, use MapStruct:
Copy@Mapper
public interface ProductMapper {
ProductDTO toDto(Product product);
}
π‘ Bonus: MapStruct now supports mapping to Java Records out of the box.
Spring Boot MapStruct Tutorial
In this tutorial, we will demonstrate how to use MapStruct in a Spring Boot application to handle CRUD (Create, Readβ¦
β 3. Building Custom HTTP Clients
β Use: Java 11+ HttpClient
In the past, we needed OkHttp or Apache HttpClient. But now?
CopyHttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.body());
β Built-in, non-blocking, supports async and HTTP/2. β No external library needed for 80% of use cases.
Java HttpClient POST Request Example
In this tutorial, we will see how to use Java 11 HTTP Client API to submit form data and also Java 11 HTTP Client APIβ¦
β 4. Writing Getters, Setters, Equals, HashCode
β Use: Lombok or Java Records
Still writing boilerplate? Use Lombok:
Copy@Data
public class User {
private Long id;
private String name;
}
Or just switch to records:
Copypublic record User(Long id, String name) {}
β Java Records are immutable, concise, and perfect for DTOs.
Lombok vs Java Records: Which One Will Win the Future?
π This is a Medium member-only article. If youβre not a Medium member, you can read the full article for free on myβ¦m
β 5. Writing Your Own Retry Logic
β Use: Resilience4j
Stop doing this:
Copyfor (int i = 0; i < 3; i++) {
try {
callApi();
break;
} catch (Exception ignored) {}
}
Use this instead:
CopyRetry retry = Retry.ofDefaults("backend");
Supplier<String> supplier = Retry.decorateSupplier(retry, () -> api.call());
String result = Try.ofSupplier(supplier).get();
β Includes backoff, circuit breaker, rate limiter, fallback. π§ Production-ready resilience.
β 6. Logging with System.out.println()
β Use: SLF4J + Logback or Log4j2
Copyprivate static final Logger log = LoggerFactory.getLogger(MyApp.class);
log.info("Starting application...");
β Structured logs, levels, log files, and integrations with ELK/Grafana.
π‘ Bonus: Use parameterized logs to avoid string concatenation:
Copylog.info("User {} logged in", username);
SLF4J Tutorial
SLF4J (Simple Logging Facade for Java) is a logging facade that provides a simple abstraction for various loggingβ¦
β 7. Writing String Utilities
β Use: Apache Commons Lang
CopyStringUtils.isBlank(" "); // true
StringUtils.capitalize("java"); // Java
β Includes DateUtils, ArrayUtils, NumberUtils β save time and reduce bugs.
Guide to Apache Commons Lang3 in Java
This guide will cover installation, basic usage, advanced features, and various use cases of Apache Commons Lang3 usingβ¦
β 8. Creating Fake Data for Testing
β Use: Java Faker or Datafaker
CopyFaker faker = new Faker();
String email = faker.internet().emailAddress();
String name = faker.name().fullName();
β Great for tests, demos, or DB seeding.
β 9. Building Your Own Date/Time Helpers
β Use: java.time (Java 8+)
CopyLocalDate date = LocalDate.now();
String iso = date.format(DateTimeFormatter.ISO_DATE);
β
Use Period
, Duration
, ZonedDateTime
, ChronoUnit
β all built-in.
π‘ Bonus: No more Date
/Calendar
bugs or timezone nightmares.
β 10. Rolling Your Own Database Migrations
β Use: Flyway or Liquibase
Version-controlled migrations:
Copysrc/main/resources/db/migration
βββ V1__create_users.sql
βββ V2__add_email_column.sql
Then run:
Copymvn flyway:migrate
β Auto-applies changes across all environments, CI/CD friendly.
β 11. Manually Handling Null Checks
β Use: Optional
CopyOptional<User> userOpt = repository.findById(id);
userOpt.map(User::getEmail).ifPresent(this::sendEmail);
β
No NullPointerException
. Express intent clearly.
π‘ Combine with records or pattern matching in Java 21+.
Avoid null in Java: Use Optional for Safer and Cleaner Code
Learn why you should use Javaβs Optional instead of returning null. Improve code safety, reduce NullPointerExceptionβ¦
β 12. Manually Writing Validation Logic
β Use: Hibernate Validator (JSR 380)
Copypublic record SignupRequest(
@NotNull @Email String email,
@NotBlank String password
) {}
Add to controller:
Copy@PostMapping("/signup")
public ResponseEntity<?> signup(@Valid @RequestBody SignupRequest request) {
// already validated!
}
β Cleaner input validation, integrates with Spring Boot out of the box.
Spring Boot DTO Validation Example
In this tutorial, we will learn how to validate Spring boot REST API DTO requests using Hibernate validator.
β 13. Writing Manual CSV Parsers
β Use: OpenCSV
CopyCSVReader reader = new CSVReader(new FileReader("users.csv"));
List<String[]> records = reader.readAll();
β Also supports bean mapping:
CopyColumnPositionMappingStrategy<User> strategy = new ColumnPositionMappingStrategy<>();
strategy.setType(User.class);
β 14. Managing Object Pools Yourself
β Use: Apache Commons Pool2
If you build expensive resources (like FTP connections or parsers), use object pools.
CopyGenericObjectPool<MyExpensiveService> pool = new GenericObjectPool<>(new MyFactory());
MyExpensiveService service = pool.borrowObject();
β Handles lifecycle, errors, and efficient reuse.
β 15. Implementing Your Own Dependency Injection
β Use: Spring Boot
No need to wire objects by hand:
Copy@Service
public class OrderService {
private final PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
β Clean constructor injection, lifecycle management, profiles, environments.
π‘ Spring Boot 3.1+ supports native images and AOT-optimized apps too.
π§Ύ Summary β What to Use Instead

β Final Thoughts
Modern Java isn’t about writing everything yourself β it’s about knowing where to plug in the right tool.
These libraries:
- Save you time
- Reduce bugs
- Are tested in production
- Let you focus on business logic, not plumbing
10x developers aren’t superheroes β they just don’t build what they can borrow.
Start using the right libraries, pair them with modern Java features like records, sealed types, HttpClient, and let your codebase evolve from “just working” to “production-grade.”