From java-development
Use whenever writing or reviewing Java code that contains boilerplate — getters/setters, constructors, equals/hashCode/toString, builders, logger fields, try-with-resources, null checks. Triggers on phrases like "use lombok", "lombokify", "remove this boilerplate", "add a builder", "add getters", and on any Java file containing manual accessor methods, manual builder classes, or `private static final Logger log = LoggerFactory.getLogger(...)`. Decision flow: detect Lombok in the project; if present, use it; if absent, ask the user before adding the dependency. Never silently introduce or remove Lombok.
How this skill is triggered — by the user, by Claude, or both
Slash command
/java-development:lombokThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
[Project Lombok](https://projectlombok.org/) eliminates Java boilerplate via annotation-driven code generation. The point of this skill is twofold: (1) when Lombok is already in the project, use it consistently instead of hand-rolling boilerplate; (2) when it isn't, never sneak it in — the dependency choice is the user's, not yours.
Project Lombok eliminates Java boilerplate via annotation-driven code generation. The point of this skill is twofold: (1) when Lombok is already in the project, use it consistently instead of hand-rolling boilerplate; (2) when it isn't, never sneak it in — the dependency choice is the user's, not yours.
Is Lombok already a dependency in this project?
├── Yes → use Lombok-first patterns below. Refactor adjacent boilerplate when touching a file.
└── No → ASK: "this project doesn't use Lombok. Want to add it and lombokify the existing boilerplate?"
├── Yes → add the dependency, then run the lombokify pass.
└── No → write boilerplate by hand. Don't import lombok.* anywhere.
The ask is mandatory. Don't introduce Lombok as a side-effect of "while I'm here" cleanup. Don't remove it without asking either.
In this priority order:
pom.xml, build.gradle, build.gradle.kts for org.projectlombok (group id) or lombok (artifact id). This is the authoritative signal.git grep "^import lombok\." (or equivalent). If anything in the codebase imports a Lombok class, Lombok is in use.target/generated-sources/annotations or IDE config is weaker — only treat as a hint, confirm via 1 or 2.If you find Lombok via the imports but not in the build file, something is broken — flag it to the user instead of guessing.
Use the annotation, not the boilerplate. Manual code generated for the same purpose adds noise, drifts from the rest of the file, and makes refactors (e.g. renaming a field) split-brain.
| Hand-written boilerplate | Lombok equivalent | Notes |
|---|---|---|
getX() / setX() pairs on plain fields | @Getter / @Setter (field- or class-level) | Use field-level when only some fields need it. |
Manual equals + hashCode | @EqualsAndHashCode | For entities, use onlyExplicitlyIncluded = true and mark the id field with @EqualsAndHashCode.Include. |
Manual toString | @ToString | Use @ToString.Exclude on lazy/circular fields (JPA relations, big payloads). |
| All-args / no-args / required-args constructors | @AllArgsConstructor / @NoArgsConstructor / @RequiredArgsConstructor | @RequiredArgsConstructor generates a ctor over final and @NonNull fields — the right default for constructor injection. |
| Hand-rolled builder class | @Builder (or @SuperBuilder for inheritance) | See pitfalls below before reaching for it on entities. |
| Immutable value class with all of the above | @Value | Makes the class final and all fields private final. Don't use on Spring-proxied components, JPA entities, or anything Mockito spies on — proxying needs non-final classes, and @Value's finality silently breaks @Transactional, lazy entity proxies, and @Spy-on-real-instance. |
private static final Logger log = LoggerFactory.getLogger(<Class>.class); | @Slf4j (or matching annotation per logging API) | Covered in the java-logging skill. |
if (x == null) throw new NullPointerException(...) at method entry | @NonNull on the parameter | Generates the same NPE; cleaner signature. |
@Data — use with caution@Data bundles @Getter, @Setter, @ToString, @EqualsAndHashCode, and @RequiredArgsConstructor. Convenient for plain data carriers (DTOs, simple records-before-records). Avoid @Data on:
equals/hashCode/toString walk every field, including lazy associations — this triggers LazyInitializationExceptions, infinite loops on bidirectional relations, and N+1 problems just from logging. Prefer @Getter @Setter plus manual equals/hashCode on the id (or @EqualsAndHashCode(onlyExplicitlyIncluded = true)).@Data generates a setter that hands out the live reference.@Value instead.When in doubt on a domain class, prefer the explicit set: @Getter, @Setter, @EqualsAndHashCode(of = "id"), @ToString(of = {"id", "name"}).
@Builder pitfalls@Builder won't include the parent's fields. Use @SuperBuilder on both parent and child.@OneToMany, the builder's collection field is null by default — initialize via @Builder.Default (e.g. @Builder.Default private List<Item> items = new ArrayList<>();) or use @Singular for a builder-side addItem API.@Builder on a constructor is often clearer than @Builder on a class — it makes the build target explicit.@SneakyThrows — almost never@SneakyThrows swallows checked exceptions into the runtime layer at compile time. It can be useful for genuinely unrecoverable cases in tests or scripts. In production code it hides real failure modes from callers and the type system. Default: don't use it. If a caller can't handle IOException, wrap it explicitly in your own runtime exception.
@RequiredArgsConstructor
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final PaymentClient paymentClient;
// Lombok generates the constructor; Spring autowires it.
}
This is the modern preferred pattern: no @Autowired field injection, no manual constructor, all collaborators final.
If the project doesn't use Lombok and a refactor would benefit from it:
import lombok.* or modifying the build file.Don't ask repeatedly. Once is enough; the answer applies to the whole project until the user says otherwise.
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
Pin a recent version (check latest — current at time of writing is in the 1.18.x line). For Maven projects also configure the compiler plugin's annotationProcessorPaths if it doesn't pick up Lombok automatically.
compileOnly("org.projectlombok:lombok:1.18.x")
annotationProcessor("org.projectlombok:lombok:1.18.x")
testCompileOnly("org.projectlombok:lombok:1.18.x")
testAnnotationProcessor("org.projectlombok:lombok:1.18.x")
The compileOnly / annotationProcessor pair is required — implementation alone won't trigger the annotation processor.
Mention to the user that IDEs need the Lombok plugin installed (IntelliJ: bundled since 2020.3; Eclipse: run lombok.jar). Without it, the IDE flags Lombok-generated code as missing.
After adoption (or any time the user says "lombokify"), do a sweep across the relevant scope:
getX() / setX() pairs whose body is just return x; / this.x = ...;.equals / hashCode / toString that don't have custom logic.private static final Logger log = LoggerFactory.getLogger(...).if (x == null) throw new NullPointerException(...).@Data reflexively — see its caveats.equals does anything non-default, don't replace it; leave a comment-free explicit method.equals/hashCode/toString.@Data on JPA entities (see above).@SneakyThrows to dodge checked exceptions in production code.delombok and then re-lombokify as a refactor strategy — diff churn for no value.@Data with @Builder on classes with default field values without @Builder.Default — defaults silently disappear in builder-constructed instances.java-logging skill — when Lombok is present, @Slf4j is the default rather than a hand-declared Logger field.javadoc skill — Lombok-generated methods (from @Getter, @Data, @RequiredArgsConstructor, etc.) have no source location to attach Javadoc to anyway, and the javadoc skill's rule 1 / rule 7 mean that's the right outcome: a generated getOrderId() returning orderId has nothing useful to document. Don't try to delombok purely so you can attach Javadoc.Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub pgatzka/pgatzka-skills