Lombok Basics
Project Lombok generates boilerplate code at compile time via annotations — getters, setters, constructors, builders, and logging — keeping source files clean and readable.
Setup
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
Enable annotation processing in your IDE (IntelliJ: install Lombok plugin).
Core Annotations
@Data
Generates getters, setters, toString, equals, hashCode, and a required-args constructor:
@Data
public class User {
private Long id;
private String name;
private String email;
}
// Equivalent to ~40 lines of boilerplate
@Getter / @Setter
Field-level or class-level:
@Getter
@Setter
public class Product {
private String sku;
@Setter(AccessLevel.NONE)
private Instant createdAt; // no setter
}
@Builder
Fluent builder pattern:
@Builder
@Data
public class Order {
private Long id;
private String customerId;
private BigDecimal total;
private List<OrderItem> items;
}
Order order = Order.builder()
.customerId("C-123")
.total(new BigDecimal("99.99"))
.items(List.of(new OrderItem("SKU-1", 2)))
.build();
@NoArgsConstructor / @AllArgsConstructor
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Address {
private String street;
private String city;
private String zipCode;
}
Required by JPA entities and Jackson deserialization.
Logging Annotations
@Slf4j
@Service
public class OrderService {
public void processOrder(Long id) {
log.info("Processing order {}", id);
log.debug("Order details: {}", order);
}
}
Generates: private static final Logger log = LoggerFactory.getLogger(OrderService.class);
Also available: @Log4j2, @CommonsLog, @JBossLog.
Advanced Annotations
@RequiredArgsConstructor
Constructor for final fields (enables constructor injection):
@RequiredArgsConstructor
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final PaymentService paymentService;
// constructor generated automatically
}
@Value (Immutable)
@Value
public class Point {
int x;
int y;
// all fields private final, getters only, no setters
}
@With (Immutable copies)
@With
@Value
public class User {
Long id;
String name;
String email;
}
User updated = user.withName("Alice Smith"); // new instance
@SneakyThrows
Bypasses checked exception declaration:
@SneakyThrows
public void readFile(String path) {
Files.readString(Path.of(path)); // no throws IOException needed
}
Use sparingly — hides exception contracts.
@UtilityClass
@UtilityClass
public class StringUtils {
public static boolean isBlank(String s) {
return s == null || s.trim().isEmpty();
}
}
// private constructor, all methods static
JPA Entity Example
@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(unique = true)
private String email;
}
Lombok vs Records (Java 16+)
| Feature | Lombok @Value | Java Record |
|---|---|---|
| Mutability | Immutable | Immutable |
| Boilerplate | Annotation needed | Built-in |
| Inheritance | Supported | Not supported |
| JPA entity | Works | Limited |
| Builder | @Builder | Manual |
Use records for DTOs and value objects; Lombok for JPA entities and complex classes.
Best Practices
- Use
@RequiredArgsConstructorfor Spring service injection - Combine
@Builderwith@NoArgsConstructor+@AllArgsConstructorfor JPA - Prefer
@Slf4jover manual logger declaration - Avoid
@Dataon JPA entities — use@Getter/@Setter(@Datagenerates equals/hashCode including lazy fields) - Use Java records for simple immutable DTOs instead of Lombok when possible