🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
As a Java developer working on real-world backend systems, you’ve probably created objects with multiple fields — some required, some optional.
Maybe you’ve seen classes like this:
new User("John", "john@example.com", null, null, null);
Not only is this hard to read, it’s easy to mess up the order of parameters or forget which field is which.
This is where the Builder Pattern is useful.
In this article, we’ll look at:
- What the Builder Pattern is (without theory overload)
- Why it’s useful in real Spring Boot projects
- 2 practical examples: building a response DTO and a complex configuration object
- Best practices for using builders in day-to-day backend work
Let’s keep it simple and focused on what matters in real code.
What Is the Builder Pattern?
The Builder Pattern helps you construct complex objects step-by-step without writing multiple constructors or using long parameter lists.
Instead of this:
new Order("John", "MOBILE", 1, "123 Street", false, "note", null);
You write:
Order order = Order.builder()
.customerName("John")
.productType("MOBILE")
.quantity(1)
.shippingAddress("123 Street")
.build();
It’s clean, readable, and safe.
How to Use Builder Pattern in Java
You don’t need to write the boilerplate yourself. Use Lombok.
Add to pom.xml:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
Make sure annotation processing is enabled in your IDE.
Example 1: Building Response DTOs (Order Confirmation)
Let’s say you’re working on an e-commerce platform.
When a customer places an order, you need to return an API response with:
- orderId
- customerName
- shippingAddress
- estimatedDelivery
- couponApplied (optional)
- deliveryInstructions (optional)
✅ Create a DTO with Builder
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class OrderResponse {
private String orderId;
private String customerName;
private String shippingAddress;
private String estimatedDelivery;
private boolean couponApplied;
private String deliveryInstructions;
}
✅ Use Builder in Service
public OrderResponse buildResponse(Order order) {
return OrderResponse.builder()
.orderId(order.getId())
.customerName(order.getCustomerName())
.shippingAddress(order.getShippingAddress())
.estimatedDelivery("3-5 business days")
.couponApplied(order.hasCoupon())
.deliveryInstructions(order.getDeliveryNote())
.build();
}
✅ Controller Usage
@PostMapping("/checkout")
public ResponseEntity<OrderResponse> checkout(@RequestBody OrderRequest request) {
Order order = orderService.placeOrder(request);
OrderResponse response = orderService.buildResponse(order);
return ResponseEntity.ok(response);
}
Why Use Builder Here?
| Benefit | How It Helps |
|---|---|
| Optional fields | Don’t need multiple constructors |
| Readable | Easy to see which value is being set |
| Safe | Avoids mistakes with parameter ordering |
| Flexible | You can skip fields without errors |
In real-world APIs, response payloads often have many optional values. Using builders keeps your code clean.
Example 2: Building Configuration Objects (Notification Settings)
Imagine you're writing a feature to send notifications to users. You want to let different modules configure how notifications are sent.
You might have a config object like this:
- channel (email, sms, push)
- retryCount (default: 3)
- priority (default: normal)
- delaySeconds (optional)
- failSilently (optional)
✅ Define Config with Builder
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class NotificationConfig {
private String channel;
private int retryCount;
private String priority;
private Integer delaySeconds;
private boolean failSilently;
}
✅ Use It in Notification Service
@Service
public class NotificationService {
public void send(String to, String message, NotificationConfig config) {
System.out.println("Sending via: " + config.getChannel());
System.out.println("Priority: " + config.getPriority());
System.out.println("Retries: " + config.getRetryCount());
// Simulate actual send logic
}
}
✅ Build Config Based on Context
NotificationConfig config = NotificationConfig.builder()
.channel("email")
.priority("high")
.retryCount(5)
.failSilently(true)
.build();
notificationService.send("user@example.com", "Welcome!", config);
Now, different modules (order, billing, alerts) can configure notifications however they want — no need to overload constructors or use long method params.
💡 Why Use Builder Here?
- Lets you create config once and pass it around
- Supports default + optional values easily
- Keeps the
send()method simple and focused - Encourages clear setup logic per feature
Common Use Cases in Spring Boot Projects
You’ll see the Builder Pattern used in many parts of a real app:
| Use Case | Example |
|---|---|
| API Response Objects | UserResponse, OrderSummary, PaymentStatus |
| Request Payloads | SearchRequest, FilterOptions |
| Config Objects | NotificationConfig, CacheSettings, ReportOptions |
| Logging/Tracing | LogEvent.builder().context("checkout").type("error").build() |
| Domain Aggregates | When combining multiple objects into one result |
Tips for Using Builder Pattern in Java Projects
- Use Lombok – No need to write builder code manually
- Mark classes with
@Builderand@Datafor simplicity - Keep field names clear – builder methods are based on field names
- Use builder in tests – great for setting up test data quickly
- Avoid mixing builder + setters – use one style for consistency
⚠️ When Not to Use Builder
- For very simple classes with 1–2 fields
- If object is truly immutable and doesn’t have optional fields
- If you don’t control the class (e.g. from third-party library)
In these cases, a constructor or a simple setter might be fine.
Summary
| Pattern | Builder |
|---|---|
| Use When | You need to build objects with many fields (some optional) |
| Pros | Clean, readable, safe, avoids constructor overload |
| In Spring Boot | Perfect for DTOs, config objects, test data |
| Tool | Lombok makes it super easy to use |
Final Thoughts
The Builder Pattern is one of the most practical design patterns for backend developers — especially when you're working with APIs, configuration objects, or complex domain data.
In Spring Boot projects, builders help you:
- Keep your service and controller layers clean
- Avoid brittle constructors
- Make your code easier to read and maintain
If you’ve ever passed
null, null, nullinto a constructor — it’s time to start using builders.
My Top and Bestseller Udemy Courses. The sale is going on with a 70 - 80% discount. The discount coupon has been added to each course below:
Build REST APIs with Spring Boot 4, Spring Security 7, and JWT
[NEW] Learn Apache Maven with IntelliJ IDEA and Java 25
ChatGPT + Generative AI + Prompt Engineering for Beginners
Spring 7 and Spring Boot 4 for Beginners (Includes 8 Projects)
Available in Udemy for Business
Building Real-Time REST APIs with Spring Boot - Blog App
Available in Udemy for Business
Building Microservices with Spring Boot and Spring Cloud
Available in Udemy for Business
Java Full-Stack Developer Course with Spring Boot and React JS
Available in Udemy for Business
Build 5 Spring Boot Projects with Java: Line-by-Line Coding
Testing Spring Boot Application with JUnit and Mockito
Available in Udemy for Business
Spring Boot Thymeleaf Real-Time Web Application - Blog App
Available in Udemy for Business
Master Spring Data JPA with Hibernate
Available in Udemy for Business
Spring Boot + Apache Kafka Course - The Practical Guide
Available in Udemy for Business
Comments
Post a Comment
Leave Comment