agentleFS
motola10motola10/claude-code-base/.claude/skills/java-standards/SKILL.md

java-standards

Skill1 starsChanged 5 months agoMITView on GitHub

Best-practice coding standards for Java code (manifests: pom.xml, build.gradle). Agnostic core plus a Spring Boot overlay. Covers types/records, null safety, error handling, concurrency, security, logging, tooling, testing, plus Spring constructor injection, layering, validation, exception handling, JPA, security. Used by the review agents on Java/Spring projects. Do NOT use for other languages.

The file

Show its rules and text

We split this skill into the rules it gives an agent

25 rules. About 0 are common, 8 are distinctive, and 17 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈8

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 17

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    MUST cite the rule ID: Never renumber.

    line 36
  2. Very specific:

    Target: all Java source. The core JAVA-* rules apply to any Java code.

    line 50
  3. Very specific:

    Modern Java: Use current language features (records, sealed types, switch expressions, var, virtual threads) on a supported LTS.

    line 54
  4. Very specific:

    JAVA-BASE-2 (MUST): Use a declarative build tool — Maven or Gradle — with a committed lockfile/wrapper (mvnw/gradlew) so builds are …

    line 64
  5. Very specific:

    JAVA-BASE-4 (SHOULD): Keep the happy path shallow: handle errors/edge cases early with guard clauses and early return/throw, rather than …

    line 68
  6. Very specific:

    JAVA-TYPE-1 (SHOULD): Prefer immutability — final fields, no setters where avoidable.

    line 75
  7. Very specific:

    JAVA-TYPE-4 (SHOULD): Use var for local variables only when the initializer makes the type obvious.

    line 81
  8. Very specific:

    JAVA-TYPE-5 (SHOULD NOT): Add an equals/hashCode by hand where a record would do.

    line 83
  9. Very specific:

    JAVA-NULL-1 (SHOULD): Don't return null for "absent" — return Optional<T> from methods whose result may be missing.

    line 90
  10. Very specific:

    JAVA-NULL-3 (SHOULD NOT): Call Optional.get() without isPresent().

    line 94
  11. Distinctive:

    JAVA-ERR-3 (SHOULD): Prefer unchecked exceptions for programming/contract errors.

    line 105
  12. Very specific:

    JAVA-CONC-1 (MUST): Prefer java.util.concurrent (executors, CompletableFuture, concurrent collections) over raw Thread/synchronized …

    line 128
  13. Distinctive:

    JAVA-CONC-3 (SHOULD): Use virtual threads (Java 21+) for high-concurrency blocking I/O rather than large platform-thread pools.

    line 133
  14. Very specific:

    JAVA-CONC-4 (MUST): Always shut executors down (shutdown/try-with-resources on Java 21+ ExecutorService) — no leaked thread pools.

    line 135
  15. Very specific:

    JAVA-LOG-2 (MUST): Use parameterized logging (log.info("user {} ...", id)), include a level, and MUST NOT log secrets, tokens, or PII.

    line 157
  16. Very specific:

    JAVA-LINT-2 (SHOULD): Treat warnings as errors where practical.

    line 168
  17. Distinctive:

    JAVA-TEST-1 (MUST): Test with JUnit 5 (Jupiter) + AssertJ assertions and Mockito for collaborators.

    line 175
  18. Distinctive:

    JAVA-TEST-3 (SHOULD): Follow the test pyramid — many fast unit tests, fewer integration, few end-to-end.

    line 180
  19. Distinctive:

    Don't assert on incidental details (log text, private state).

    line 184
  20. Distinctive:

    JAVA-DOC-1 (SHOULD): Write Javadoc on public API (classes and non-trivial public methods) — what it does, params, return, thrown exceptions …

    line 190
  21. Very specific:

    JAVA-SPRING-1 (MUST): Use constructor injection (a single constructor, final fields) for dependencies.

    line 200
  22. Very specific:

    JAVA-SPRING-2 (MUST): Keep the layering clean: @RestController thin (HTTP mapping + validation only), @Service owns business logic, …

    line 203
  23. Distinctive:

    MUST NOT serialize JPA entities directly out of controllers (leaks the schema and lazy-loading pitfalls).

    line 207
  24. Very specific:

    JAVA-SPRING-10 (SHOULD): Test with Spring's test slices — @WebMvcTest (controllers, via MockMvc/MockMvcTester), @DataJpaTest …

    line 232
  25. Very specific:

    JAVA-SPRING-11 (SHOULD): Default web stack is Spring MVC (servlet.

    line 235

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Java Coding Standard (v1.0)

Status: Locked v1.0. Same structure as the locked nodejs.md: an agnostic core (JAVA-*, the language + general practices) plus a framework overlay (JAVA-SPRING-*) for the default backend stack — Spring Boot — exactly as nodejs.md layers a NestJS overlay on its core. The overlay mechanically enforces the core and stays cross-platform consistent with nodejs.md, fastapi.md, and go.md on auth, API versioning, and the data layer.

On adoption this becomes .claude/skills/java-standards/SKILL.md + references/*.md.

Toolchain verified current as of 2026-06-13 (via Context7 + Maven Central/Adoptium): Java LTS 21 & 25 (25 is current LTS), Spring Boot 4.1.x. Rules are written version-agnostically; these are reference points, not pins.


How to read this document

Constraint language (RFC 2119)

  • MUST / MUST NOT — hard requirement; a violation is a blocking issue.
  • SHOULD / SHOULD NOT — strong recommendation; deviate only with a written // Justification:.
  • MAY — optional.

Rule IDs

Stable JAVA-AREA-NUMBER (e.g. JAVA-ERR-3); Spring overlay uses JAVA-SPRING-N. The reviewer MUST cite the rule ID. Never renumber.

Severity mapping

This document says…Reviewer severityGate
MUST/MUST NOT affecting safety / securityCriticalBlocks merge
MUST/MUST NOT elsewhereCritical / Warning (by impact)Blocks if it risks correctness
SHOULD without justificationWarningShould fix
MAY / stylisticSuggestionNice to have

Scope & Assumptions

  1. Target: all Java source. The core JAVA-* rules apply to any Java code; the JAVA-SPRING-* overlay applies to Spring Boot services (the default backend stack).
  2. Backend default is Spring Boot — named, not mandated for non-service code (libraries, CLIs, batch jobs follow the core only).
  3. Modern Java. Use current language features (records, sealed types, switch expressions, var, virtual threads) on a supported LTS.
  4. Custom overrides: the project's custom-standards skill overrides this document on conflict.

1. Language Baseline & Build

  • JAVA-BASE-1 (MUST): Target a supported LTS (currently 21 or 25). Declare it via the build tool's release/toolchain so source, target, and bytecode agree.
  • JAVA-BASE-2 (MUST): Use a declarative build tool — Maven or Gradle — with a committed lockfile/wrapper (mvnw/gradlew) so builds are reproducible. Pin plugin and dependency versions.
  • JAVA-BASE-3 (MUST): Code MUST be auto-formatted by a committed formatter (Spotless with google-java-format or Palantir) enforced in CI — formatting is not reviewed by hand.
  • JAVA-BASE-4 (SHOULD): Keep the happy path shallow: handle errors/edge cases early with guard clauses and early return/throw, rather than deep if/else nesting.

2. Types & Object Design

  • JAVA-TYPE-1 (SHOULD): Prefer immutability — final fields, no setters where avoidable. Use record for immutable data carriers (DTOs, value objects, events) instead of hand-written POJOs.
  • JAVA-TYPE-2 (SHOULD): Model closed hierarchies with sealed interfaces/classes + pattern- matching switch so the compiler enforces exhaustiveness when a case is added.
  • JAVA-TYPE-3 (SHOULD): Program to interfaces for collaborators; keep them small and defined by the consumer's need. Don't expose mutable collections — return unmodifiable/List.copyOf views.
  • JAVA-TYPE-4 (SHOULD): Use var for local variables only when the initializer makes the type obvious; keep explicit types on fields, method signatures, and public API.
  • JAVA-TYPE-5 (SHOULD NOT): Add an equals/hashCode by hand where a record would do; if you do override them, override both (and toString) consistently.

3. Null Safety

  • JAVA-NULL-1 (SHOULD): Don't return null for "absent" — return Optional<T> from methods whose result may be missing. MUST NOT use Optional for fields or method parameters.
  • JAVA-NULL-2 (SHOULD): Validate arguments at public boundaries (Objects.requireNonNull, or Bean Validation in Spring) and document nullability; keep internal code null-free by construction.
  • JAVA-NULL-3 (SHOULD NOT): Call Optional.get() without isPresent(); prefer map/orElse/ orElseThrow.

4. Error Handling

  • JAVA-ERR-1 (MUST): Throw specific exceptions; MUST NOT catch Exception/Throwable broadly and swallow it. An empty or log-only catch that hides a failure is a blocking issue.
  • JAVA-ERR-2 (MUST): Manage resources with try-with-resources (any AutoCloseable) — never rely on manual finally close. Don't leak streams, connections, or clients.
  • JAVA-ERR-3 (SHOULD): Prefer unchecked exceptions for programming/contract errors; use checked exceptions only when the caller can realistically recover. When wrapping, preserve the cause (throw new XException("...", e)) — never drop the stack trace.
  • JAVA-ERR-4 (SHOULD): Define a small set of domain exception types the application maps to consistent responses (see JAVA-SPRING-6). Don't use exceptions for normal control flow.
  • JAVA-ERR-5 (MUST NOT): Log-and-rethrow the same exception at every layer — log it once, where it's handled, to avoid duplicate stack traces.
// ✅ JAVA-ERR-2/3: try-with-resources + preserve cause
public String read(Path path) {
    try (var reader = Files.newBufferedReader(path)) {
        return reader.lines().collect(Collectors.joining("\n"));
    } catch (IOException e) {
        throw new ConfigLoadException("failed to read " + path, e); // cause preserved
    }
}

5. Concurrency

  • JAVA-CONC-1 (MUST): Prefer java.util.concurrent (executors, CompletableFuture, concurrent collections) over raw Thread/synchronized hand-rolling. MUST NOT share mutable state without synchronization or confinement.
  • JAVA-CONC-2 (SHOULD): Favor immutable objects and stateless services for thread-safety; document any class that is not thread-safe.
  • JAVA-CONC-3 (SHOULD): Use virtual threads (Java 21+) for high-concurrency blocking I/O rather than large platform-thread pools; keep CPU-bound work on a bounded pool.
  • JAVA-CONC-4 (MUST): Always shut executors down (shutdown/try-with-resources on Java 21+ ExecutorService) — no leaked thread pools.

6. Security

  • JAVA-SEC-1 (MUST NOT): Build SQL/HQL/JPQL by string concatenation. Use parameterized queries / bound parameters (JAVA-SPRING-7).
  • JAVA-SEC-2 (MUST NOT): Hard-code secrets. Externalize credentials/keys to environment or a secret manager; never commit them.
  • JAVA-SEC-3 (MUST): Hash passwords with a memory-hard KDF (bcrypt/argon2 via Spring Security's PasswordEncoder); use SecureRandom (never java.util.Random) for tokens/salts.
  • JAVA-SEC-4 (MUST): Scan dependencies for known CVEs (OWASP Dependency-Check or equivalent) in CI; keep them patched. MUST NOT deserialize untrusted data with native Java serialization.

7. Logging & Observability

  • JAVA-LOG-1 (MUST): Log via the SLF4J API (backed by Logback/Log4j2). MUST NOT use System.out/System.err or printStackTrace() for application logging.
  • JAVA-LOG-2 (MUST): Use parameterized logging (log.info("user {} ...", id)), include a level, and MUST NOT log secrets, tokens, or PII. (Consistent with NODE-LOG-2.)
  • JAVA-LOG-3 (SHOULD): Carry a correlation/trace ID (MDC) and expose health/readiness + metrics (Spring Boot Actuator). (Consistent with NODE-LOG-3.)

8. Tooling & Static Analysis

  • JAVA-LINT-1 (MUST): Static analysis MUST pass in CI — at least Error Prone or SpotBugs, plus Checkstyle (or Spotless's checks) for conventions.
  • JAVA-LINT-2 (SHOULD): Treat warnings as errors where practical; suppress a single finding inline with a justified @SuppressWarnings("...") // reason, never blanket-disable a check.

9. Testing

  • JAVA-TEST-1 (MUST): Test with JUnit 5 (Jupiter) + AssertJ assertions and Mockito for collaborators. New or changed behavior ships with tests; changed logic with no test is insufficient coverage.
  • JAVA-TEST-2 (MUST): Tests are deterministic and isolated — no real external network in unit tests (mock at the boundary), no order dependency, no shared mutable state.
  • JAVA-TEST-3 (SHOULD): Follow the test pyramid — many fast unit tests, fewer integration, few end-to-end. Target ≥ 80% coverage on changed code (not whole-repo) via JaCoCo; coverage is a floor, not the goal. (Consistent with NODE-TEST-3 / PY-TEST-4.)
  • JAVA-TEST-4 (SHOULD): Name tests by behavior; use parameterized tests for table-style cases. Don't assert on incidental details (log text, private state).

10. Documentation

  • JAVA-DOC-1 (SHOULD): Write Javadoc on public API (classes and non-trivial public methods) — what it does, params, return, thrown exceptions — not restatements of the signature.

Spring Boot Overlay (JAVA-SPRING-*)

Applies when the service is a Spring Boot app. These rules mechanically enforce the core and keep the service consistent with nodejs.md / fastapi.md / go.md.

  • JAVA-SPRING-1 (MUST): Use constructor injection (a single constructor, final fields) for dependencies. MUST NOT use field injection (@Autowired on fields) — it hides dependencies and breaks testability/immutability.
  • JAVA-SPRING-2 (MUST): Keep the layering clean: @RestController thin (HTTP mapping + validation only), @Service owns business logic, @Repository owns data access. No business logic in controllers; no HTTP types in the service layer.
  • JAVA-SPRING-3 (MUST): Expose DTOs (prefer records — JAVA-TYPE-1) at the API boundary; MUST NOT serialize JPA entities directly out of controllers (leaks the schema and lazy-loading pitfalls). For DTO↔entity mapping, MapStruct (compile-time, type-safe) is the recommended default — recommended not mandated; explicit hand-written mapping is also fine. Avoid reflection-based runtime mappers.
  • JAVA-SPRING-4 (MUST): Validate request bodies/params with Jakarta Bean Validation — @Valid @RequestBody + constraints (@NotNull, @Email, …). Treat all request input as untrusted.
  • JAVA-SPRING-5 (SHOULD): Externalize config via @ConfigurationProperties (typed, @Validated) and profiles; never hard-code environment values. Secrets come from env/secret manager (JAVA-SEC-2).
  • JAVA-SPRING-6 (MUST): Handle errors centrally with @ControllerAdvice + @ExceptionHandler, mapping domain exceptions (JAVA-ERR-4) to consistent ResponseEntity payloads with correct status codes. MUST NOT leak stack traces or internal messages to clients.
  • JAVA-SPRING-7 (MUST): Access data through Spring Data JPA repositories (or JDBC) with bound parameters — never string-built queries (JAVA-SEC-1). Manage schema with versioned migrations via Flyway or Liquibase (both first-class Spring Boot auto-configured peers — Flyway is the common pick for SQL-first projects; neither is mandated over the other); never ddl-auto: update in production. (Consistent with the repo-layer + migrations default in NODE-NEST-16 / FASTAPI-STRUCT-5 / GO-API-6.)
  • JAVA-SPRING-8 (SHOULD): Secure endpoints with Spring Security; default scheme is stateless JWT bearer (resource-server / Authorization: Bearer), checking authorization (roles/scopes), not just authentication. Sanctioned alternatives by context: httpOnly session cookies (browser-first) or an external IdP / OAuth2 provider. (Consistent with NODE-NEST-14 / FASTAPI-SEC-1 / GO-API-4.)
  • JAVA-SPRING-9 (SHOULD): Version public APIs with URI versioning /v1 on the controller base path. (Consistent with NODE-NEST-15 / FASTAPI-DOC-2 / GO-API-5.)
  • JAVA-SPRING-10 (SHOULD): Test with Spring's test slices — @WebMvcTest (controllers, via MockMvc/MockMvcTester), @DataJpaTest (repositories), @SpringBootTest only for true integration — rather than booting the whole context for every test.
  • JAVA-SPRING-11 (SHOULD): Default web stack is Spring MVC (servlet; pairs well with virtual threads — JAVA-CONC-3). WebFlux (reactive, Reactor Netty) is a sanctioned alternative for streaming or high-concurrency non-blocking workloads — don't adopt reactive types (Mono/Flux) without that need, as they add real complexity.
// ✅ JAVA-SPRING-1/2/3/4: constructor injection, thin controller, DTO record, @Valid
@RestController
@RequestMapping("/v1/users")               // JAVA-SPRING-9
public class UserController {
    private final UserService users;        // JAVA-SPRING-1 (final, constructor-injected)

    public UserController(UserService users) {
        this.users = users;
    }

    @PostMapping
    public ResponseEntity<UserResponse> create(@Valid @RequestBody CreateUserRequest req) {
        var user = users.create(req.name(), req.email());   // logic lives in the service
        return ResponseEntity.status(HttpStatus.CREATED).body(UserResponse.from(user));
    }
}

public record CreateUserRequest(@NotBlank String name, @Email String email) {}  // JAVA-SPRING-3/4

Resolved Decisions (v1.0)

#QuestionDecisionRule(s)
1Build toolGradle and Maven both sanctioned as equal-tier peers — not a default+fallback. Matches the un-ranked-peers pattern (GO-API-6 goose/golang-migrate; NODE-TEST-4 runner set)JAVA-BASE-2
2Web stackSpring MVC default (servlet, virtual-thread-friendly); WebFlux sanctioned for reactive/high-concurrency non-blocking. Matches NODE-NEST-14 "named default + sanctioned-by-context"JAVA-SPRING-11
3MappingMapStruct (compile-time) recommended default for DTO↔entity, recommended not mandated; hand-written mapping fine; avoid reflection-based mappers. Matches GO-API-6 / FASTAPI-STRUCT-5 formJAVA-SPRING-3
4MigrationsFlyway + Liquibase both sanctioned first-class peers (Flyway common for SQL-first; neither mandated). Matches GO-API-6 two-un-ranked precedent — not the single-Alembic case (Alembic is singular only as THE SQLAlchemy tool)JAVA-SPRING-7

Toolchain reference (verified 2026-06-13): MapStruct 1.6.3, Flyway 11.8.2, Liquibase 4.32.0 — alongside Java LTS 21/25 and Spring Boot 4.1.x.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.