skills/emvnuel/skill.md/lombok-patterns

lombok-patterns

SKILL.md

Lombok Patterns

This skill provides guidance on using Project Lombok to reduce boilerplate code in Java applications, covering annotations, best practices, and integration patterns.

Note: This guide targets Java 21+ projects. Some Lombok features are now obsolete due to modern Java features (Records, var, try-with-resources). See Java 21+ Considerations below.

Overview

Lombok is a Java library that automatically generates common code like getters, setters, constructors, builders, and more during compilation. It helps create cleaner, more maintainable code.

Java 21+ Considerations

Some Lombok features are now redundant with modern Java:

Lombok Feature Java Alternative Recommendation
val/var var (Java 10+) Use Java var
@Value record (Java 16+) Prefer records for simple value objects
@Data record (Java 16+) Prefer records for simple DTOs
@Cleanup try-with-resources (Java 7+) Use try-with-resources
@With record wither methods Records can define wither methods

When Lombok Still Adds Value

  • JPA Entities: Records don't work with JPA (need no-arg constructor, mutable state)
  • @Builder: Records don't have built-in builder support
  • @Slf4j: No Java equivalent for logger generation
  • @RequiredArgsConstructor: Useful for Spring dependency injection
  • Inheritance: Records can't extend classes

Annotation Categories

Core Annotations (Still Valuable)

Annotation Purpose Use Case
@Getter/@Setter Accessor methods JPA entities, mutable classes
@NoArgsConstructor No-argument constructor JPA entities, serialization
@AllArgsConstructor All-fields constructor Dependency injection
@RequiredArgsConstructor Constructor for final/@NonNull fields Spring services
@Builder Builder pattern implementation Complex object construction

Consider Java Records Instead

Lombok Use Java Record When
@Value Simple immutable data carriers
@Data Simple DTOs without inheritance
// ✅ Prefer Java Record for simple value objects
public record Money(BigDecimal amount, String currency) {}

// ✅ Prefer Java Record for simple DTOs
public record CustomerDTO(String name, String email) {}

// ✅ Use Lombok for JPA entities (records don't work with JPA)
@Entity
@Getter
@Setter
@NoArgsConstructor
public class Customer {
    @Id private Long id;
    private String name;
}

Logging Annotations

Annotation Logger Type
@Slf4j SLF4J (recommended)
@Log4j2 Log4j 2
@Log java.util.logging
@CommonsLog Apache Commons Logging

Field & Method Annotations

Annotation Purpose
@NonNull Null checks on parameters/fields
@With Immutable setters (creates new instance)
@SneakyThrows Throw checked exceptions without declaration
@Synchronized Thread-safe method synchronization
@ToString Customizable toString() generation
@EqualsAndHashCode Customizable equals/hashCode

Quick Reference

JPA Entities (Lombok Recommended)

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Product {
    @Id
    @EqualsAndHashCode.Include
    private Long id;

    private String name;
    private BigDecimal price;
}

Spring Services

@Service
@RequiredArgsConstructor
@Slf4j
public class OrderService {
    private final OrderRepository orderRepository;
    private final PaymentService paymentService;

    public Order process(Order order) {
        log.info("Processing order: {}", order.getId());
        return orderRepository.save(order);
    }
}

Builder Pattern (Lombok Adds Value)

// Records don't have builder support - use Lombok
@Builder
public record Email(
    String to,
    String subject,
    String body,
    @Singular List<String> attachments
) {}

// Usage
Email email = Email.builder()
    .to("user@example.com")
    .subject("Hello")
    .body("Content")
    .attachment("file1.pdf")
    .build();

Best Practices

✅ Do

  • Use Java Records for simple value objects and DTOs
  • Use @RequiredArgsConstructor with final fields for dependency injection
  • Use @Slf4j for logging instead of manual logger creation
  • Use @Builder for classes with many optional fields
  • Be explicit with @EqualsAndHashCode on JPA entities

❌ Avoid

  • Using @Data or @Value when a Java Record would suffice
  • Using @Data on JPA entities (use individual annotations)
  • Using @EqualsAndHashCode with lazy-loaded JPA relationships
  • Overusing @SneakyThrows (makes exception handling unclear)

Common Pitfalls

Pitfall Problem Solution
@Data on entities Includes mutable setters, problematic equals/hashCode Use @Getter, @Setter, explicit @EqualsAndHashCode
Missing @NoArgsConstructor JPA/Jackson need no-arg constructor Always add with @AllArgsConstructor
Circular @ToString StackOverflow with bidirectional relationships Use @ToString.Exclude on one side
Using Lombok for simple DTOs Adds unnecessary dependency Use Java Records instead

Cookbook Index

Core Annotations

Field & Method Annotations

Integration Patterns

Weekly Installs
20
GitHub Stars
1
First Seen
Jan 27, 2026
Installed on
gemini-cli19
github-copilot18
codex16
opencode16
cursor15
amp14