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
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.
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
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