Claude-skill-registry lombok-patterns

Lombok annotations and best practices for Java 21+ projects. Use when reducing boilerplate, configuring builders, or choosing between Lombok and Records.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/lombok-patterns" ~/.claude/skills/majiayu000-claude-skill-registry-lombok-patterns && rm -rf "$T"
manifest: skills/data/lombok-patterns/SKILL.md
source content

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 FeatureJava AlternativeRecommendation
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)

AnnotationPurposeUse Case
@Getter
/
@Setter
Accessor methodsJPA entities, mutable classes
@NoArgsConstructor
No-argument constructorJPA entities, serialization
@AllArgsConstructor
All-fields constructorDependency injection
@RequiredArgsConstructor
Constructor for final/@NonNull fieldsSpring services
@Builder
Builder pattern implementationComplex object construction

Consider Java Records Instead

LombokUse 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

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

Field & Method Annotations

AnnotationPurpose
@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

PitfallProblemSolution
@Data
on entities
Includes mutable setters, problematic equals/hashCodeUse
@Getter
,
@Setter
, explicit
@EqualsAndHashCode
Missing
@NoArgsConstructor
JPA/Jackson need no-arg constructorAlways add with
@AllArgsConstructor
Circular
@ToString
StackOverflow with bidirectional relationshipsUse
@ToString.Exclude
on one side
Using Lombok for simple DTOsAdds unnecessary dependencyUse Java Records instead

Cookbook Index

Core Annotations

Field & Method Annotations

Integration Patterns