$ npx rulesync-cli pull✓ Wrote CLAUDE.md (2 rulesets)# Coding Standards- Always use async/await- Prefer named exports
Rule Writing

CLAUDE.md for Spring Boot

Spring Boot auto-configures everything — AI overrides it with manual config. Rules for auto-configuration, Spring Data JPA, Spring Security, and actuator.

8 min read·July 14, 2025

Spring Boot auto-configures everything — AI manually overrides it all

Auto-configuration, Spring Data JPA, Spring Security, and @ConfigurationProperties

Why Spring Boot Needs Rules That Trust Auto-Configuration

Spring Boot's magic is auto-configuration — add a dependency, and Spring Boot configures it correctly. Add spring-boot-starter-data-jpa and you get a DataSource, EntityManager, and transaction management without writing a single line of config. AI assistants don't trust this magic — they manually configure everything Spring Boot would handle automatically, creating verbose, fragile, and redundant code.

The most common AI failures: defining @Bean DataSource when Spring Boot auto-configures it from application.yml, writing custom security configurations that duplicate Spring Security defaults, creating manual transaction management instead of @Transactional, and generating XML configuration (Spring 3 era) instead of Java/Kotlin config.

These rules target Spring Boot 3.2+ with Java 21+ (or Kotlin). Spring Boot 3 requires Jakarta EE (jakarta.* not javax.*) — AI trained on Spring Boot 2 generates the wrong import namespace constantly.

Rule 1: Trust Auto-Configuration

The rule: 'Let Spring Boot auto-configure. Don't define @Bean for anything Spring Boot configures from starter dependencies. Configure through application.yml (or application.properties) — not @Configuration classes — for: database connections, JPA settings, server port, logging levels, cache configuration, and message broker connections. Only write @Configuration for truly custom beans.'

For application.yml: 'Use YAML for configuration (application.yml, not .properties — YAML supports hierarchy and is more readable). Use Spring profiles: application-dev.yml, application-prod.yml. Use environment-specific overrides: spring.datasource.url in each profile. Never hardcode values that vary between environments.'

For @ConfigurationProperties: 'Use @ConfigurationProperties for typed configuration: @ConfigurationProperties(prefix = "app") record AppConfig(String apiKey, int maxRetries, Duration timeout). This is type-safe, validated, and auto-documented — better than @Value for anything beyond a single property.'

  • Don't @Bean what auto-config provides — DataSource, EntityManager, WebClient, etc.
  • application.yml for standard config — profiles for environment-specific
  • @ConfigurationProperties for typed config — not @Value for complex config
  • @Configuration only for genuinely custom beans — not for overriding defaults
  • jakarta.* imports (Spring Boot 3) — never javax.* from Spring Boot 2
💡 Don't Fight Auto-Config

AI defines @Bean DataSource when application.yml handles it automatically. Spring Boot's auto-configuration is correct 95% of the time. Configure through YAML, not @Configuration — save @Bean for genuinely custom components.

Rule 2: Spring Data JPA Repositories

The rule: 'Use Spring Data JPA repository interfaces — never write DAO implementations manually. Extend JpaRepository<Entity, ID> for full CRUD + pagination + sorting. Use derived query methods for simple queries: findByEmail(String email), findByStatusAndCreatedAtAfter(Status status, LocalDateTime date). Use @Query for complex queries. Use Specification for dynamic queries.'

For entities: 'Use JPA annotations: @Entity, @Id, @GeneratedValue, @Column, @ManyToOne, @OneToMany. Use @Table only when the table name differs from the entity name. Use UUID or Long for IDs — never String. Use @Auditing with @CreatedDate, @LastModifiedDate for timestamps. Use Hibernate's @NaturalId for business keys.'

For performance: 'Use @EntityGraph or JOIN FETCH for eager loading specific associations. Default to LAZY fetch — never EAGER on @OneToMany (loads all children on every query). Use Pageable for all list endpoints. Use @Query with projections (interfaces or DTOs) for read-only queries that don't need full entities.'

Rule 3: Spring Security

The rule: 'Use Spring Security for all authentication and authorization. Define a SecurityFilterChain @Bean — never extend WebSecurityConfigurerAdapter (deprecated in Spring Security 5.7, removed in 6.0). Use method security (@PreAuthorize, @Secured) for fine-grained authorization. Use OAuth2 resource server for JWT validation. Use BCryptPasswordEncoder for password hashing.'

For the filter chain: 'Define security per path: http.authorizeHttpRequests(auth -> auth.requestMatchers("/api/public/**").permitAll().requestMatchers("/api/admin/**").hasRole("ADMIN").anyRequest().authenticated()). Use .csrf(csrf -> csrf.disable()) for stateless APIs. Use .cors(Customizer.withDefaults()) with a CorsConfiguration bean. Use .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt) for JWT.'

AI generates Spring Security 4/5 patterns: WebSecurityConfigurerAdapter, manual JWT parsing, custom authentication filters. Spring Security 6 has a cleaner, functional API — the filter chain builder replaces all of this with less code and fewer security mistakes.

⚠️ No WebSecurityConfigurerAdapter

AI generates WebSecurityConfigurerAdapter from Spring Security 5 training data. It was deprecated in 5.7, removed in 6.0. Spring Security 6 uses SecurityFilterChain beans — a cleaner, functional API.

Rule 4: Service Layer and Transactions

The rule: 'Use @Service classes for business logic. Controllers delegate to services, services use repositories. Annotate service methods that modify data with @Transactional. Use @Transactional(readOnly = true) on read-only methods (optimizes JPA flush mode and database connection). Never manage transactions manually — Spring's declarative transactions handle commit/rollback.'

For DTOs: 'Use Java records for DTOs: record CreateUserRequest(String name, String email) {}. Use records for responses: record UserResponse(Long id, String name, String email, Instant createdAt). Use MapStruct for entity ↔ DTO mapping. Never expose JPA entities in API responses — entities contain lazy-loaded proxies, internal IDs, and bidirectional relationships that break serialization.'

For validation: 'Use Bean Validation (Jakarta Validation) on DTOs: record CreateUserRequest(@NotBlank String name, @Email String email) {}. Spring validates automatically with @Valid in controller parameters. Custom validators implement ConstraintValidator<A, T>. Return structured error responses with @ExceptionHandler for ConstraintViolationException.'

  • @Service for business logic — @Transactional on data-modifying methods
  • @Transactional(readOnly = true) on read methods — optimizes JPA + DB
  • Java records for DTOs — MapStruct for entity ↔ DTO mapping
  • Never expose entities in responses — records filter output explicitly
  • @Valid + Bean Validation on DTOs — @ExceptionHandler for validation errors
ℹ️ Records for DTOs

Java records are perfect DTOs: immutable, compact, auto-generated equals/hashCode/toString. Never expose JPA entities in responses — they contain lazy proxies and bidirectional references that break serialization.

Rule 5: Actuator, Observability, and Production Readiness

The rule: 'Enable Spring Boot Actuator for production readiness: management.endpoints.web.exposure.include=health,info,metrics,prometheus. Use /actuator/health for load balancer probes. Use /actuator/prometheus for metrics scraping. Configure health indicators for dependencies: database, Redis, external services. Never expose all actuator endpoints — whitelist only what's needed.'

For logging: 'Use SLF4J with Logback (Spring Boot default). Use structured logging: log.info("User created", kv("userId", user.getId()), kv("email", user.getEmail())). Never use System.out.println. Use MDC (Mapped Diagnostic Context) for request-scoped context: requestId, userId, traceId. Configure log levels per package in application.yml.'

For testing: 'Use @SpringBootTest for integration tests (loads full context). Use @WebMvcTest for controller tests (loads only web layer). Use @DataJpaTest for repository tests (loads only JPA). Use MockMvc for HTTP testing. Use Testcontainers for database integration tests with real databases. Use @MockBean for mocking dependencies in the Spring context.'

Complete Spring Boot Rules Template

Consolidated rules for Spring Boot 3.2+ projects.

  • Trust auto-config: application.yml for standard settings — @Bean only for custom
  • @ConfigurationProperties for typed config — profiles for environments — never hardcoded
  • Spring Data JPA: repository interfaces, derived queries, @EntityGraph — never manual DAO
  • SecurityFilterChain bean — never WebSecurityConfigurerAdapter — @PreAuthorize for methods
  • @Service + @Transactional — records for DTOs — MapStruct for mapping — never expose entities
  • Bean Validation on DTOs: @Valid + @NotBlank/@Email — @ExceptionHandler for errors
  • Actuator: health + metrics + prometheus — structured SLF4J logging — MDC for context
  • @SpringBootTest, @WebMvcTest, @DataJpaTest — Testcontainers — MockMvc — @MockBean