@Builder Pattern in Spring Boot

In software engineering, translating conceptual design to functional clean code requires patterns and principles to be applied in application.
Design Patterns offer established development paradigms, allowing developers to save time by leveraging proven solutions instead of creating new patterns for each recurring problem, one of Design Patterns is Builder Pattern.
The Builder Pattern is a creational design pattern that separates the construction of a complex object from its representation. It provides a way to construct an object step by step, allowing you to set its properties individually and ultimately obtain the fully-constructed object.
Here is an implementation example of Builder Pattern in Java:
// User.java
public class User {
private String name;
private String surname;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", surname='" + surname + '\'' +
'}';
}
public User(Builder builder) {
this.name = builder.name;
this.surname = builder.surname;
}
public String getName() {
return name;
}
public String getSurname() {
return surname;
}
public static class Builder {
private String name;
private String surname;
public Builder() {
}
public static Builder builder()
{
return new Builder();
}
public Builder setName(String name) {
this.name = name;
return this;
}
public Builder setSurname(String surname) {
this.surname = surname;
return this;
}
public User build(){
return new User(this);
}
}
}
// Main.java
public class Main {
public static void main(String[] args) {
User user = User.Builder.builder()
.setName("Foo")
.setSurname("Bar")
.build();
System.out.println(user.toString());
}
}
This code demonstrates how to create User objects with optional parameters using the builder pattern, making the construction process more readable and maintainable. It allows you to set attributes step by step and create a User object with the desired properties.
Why should we use Builder Pattern?
Use the builder pattern to avoid creating a large number of subclasses, to avoid having a constructor with a large number of attributes, to avoid the telescopic constructor anti-pattern, and to avoid creating too many constructors.
How can we use Builder Pattern in our Spring Boot application?
Imagine we have a User entity class and a UserDto class:
// User.java
@Entity
@Table(name = "users")
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "user_name", nullable = false)
private String username;
@Column(name = "email", nullable = false)
private String email;
@Column(name = "password", nullable = false)
private String password;
In User entity class we have the following attributes:
- id: Primary key of User object with integer type and auto-generated value when saved in database.
- username: The username column of User object with string type.
- email: The email column of User object with string type.
- password: The password column of User object with string type.
// UserDto.java
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDto {
private Integer id;
private String username;
private String email;
}
In UserDto class we have three main attributes:
- id: The id variable with Integer type.
- username: The username variable with String type.
- email: The email variable with String type.
And we want to map User entity class attributes with UserDto class attributes so that we can send only required attributes in our RESTful API request.
As one solution you can use MapStruct to automatically map attributes of User entity class with UserDto class, but as it is a third party library it may cause problems in using of other built-in libraries or third party libraries of Java.
Builder Pattern can help us in mapping these attributes by building a UserDto with parameters set from User entity class.
If you are using Lombok in your Spring Boot application, you can use @Builder annotation to initialize Concrete Builder to your Java classes or you can create your Concrete Builder as in example above.
Here is an example of Builder Pattern in Java Spring Boot:
Firstly, we create a UserMapper class that will serve as a mapper to map attributes of objects. As we will map attributes of User entity class with UserDto class, we create a convertToDto function with UserDto class type and a parameter with User entity class.
// UserMapper.java
@Component
public class UserMapper {
public UserDto convertToDto(User user) {
return UserDto.builder()
.id(user.getId())
.username(user.getUsername())
.email(user.getEmail())
.build();
}
This function will create a UserDto object with builder pattern by setting it’s attributes from User entity class attributes that will be passed as parameter.
We need to create a UserService class that will handle our business logic for User entity. We want to find a User entity by it’s ID and return to client as a UserDto.
We will create a getUserById function that returns a UserDto and has an integer paremeter named id.
// UserService.java
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final UserMapper userMapper;
public UserDto getUserById(Integer id) {
final User user = userRepository.findById(id)
.orElseThrow(() -> new ApiException(ErrorEnum.USER_NOT_FOUND));
return userMapper.convertToDto(user);
}
This function will use UserRepository that uses JPA Repository’s built-in function findById to find a user by it’s id from database. This function will return a User entity if it exists in database otherwise it will throw a custom exception created in application that will throw an error that USER_NOT_FOUND with status code 404.
I will write an article about Exception Handling in Java Spring Boot and will explain about creating custom exception handlers in later times and pass the link here if you want to read about it.
Let’s say we found a User, as we will return as UserDto we should map User entity with UserDto with our convertToDto function created in UserMapper class.
As we created our service that will find a user by id and return it as UserDto, let’s create a controller that will use this service.
// UserController.java
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping("/{id}")
public ResponseEntity<UserDto> getUserById(@PathVariable Integer id) {
return ResponseEntity.ok(userService.getUserById(id));
}
UserController class will serve as a controller to handle requests and endpoints that will come to our RESTful API.
We create a getUserById function that will be a GET request with endpoint (“/api/users/{id}”), our id will be a path variable that will be given by client when sending a request and it will be passed to our getUserById function created in UserService class.
Let’s send a request from Postman to test our request.

As seen in picture, we sent a request to our endpoint http://localhost:8080/api/users/ with id value of 1 and returned a User with UserDto type as a response.
You can use Builder Pattern to map attributes between two objects in your RESTful API application and return them without of need to install any third-party libraries to your application.
Thank you for reading. :)
Stackademic 🎓
Thank you for reading until the end. Before you go:
- Please consider clapping and following the writer! 👏
- Follow us X | LinkedIn | YouTube | Discord
- Visit our other platforms: In Plain English | CoFeed | Differ
- More content at Stackademic.com