Spring Boot best practices
Turn Spring Boot implementation requests into high-quality Java applications with domain-oriented packages, explicit dependencies, externalized configuration, validated APIs, transactional services, safe persistence, structured logging, and focused tests.
When to invoke
- "Show Spring Boot best practices for this service."
- "Refactor this controller, service, and repository."
- "How should I structure a Spring Boot application?"
- "Add validation, error handling, and tests to this Spring Boot endpoint."
Project setup and package structure
| Concern |
Preferred approach |
Avoid |
| Build tool |
Maven pom.xml or Gradle build.gradle. |
Manual dependency jars. |
| Dependencies |
Spring Boot starters such as spring-boot-starter-web and spring-boot-starter-data-jpa. |
Hand-picking transitive Spring libraries. |
| Packages |
feature/domain packages such as com.example.app.order and com.example.app.user. |
Layer-only packages such as com.example.app.controller, com.example.app.service, and repository for every domain. |
| Boundaries |
Keep controller DTOs, service logic, repository contracts, and persistence models explicit. |
Letting web, persistence, and domain concerns leak into each other. |
Components and dependency injection
| Need |
Use |
| Required dependencies |
constructor-based injection with private final fields. |
| General bean |
@Component. |
| Business operation |
@Service. |
| Persistence adapter |
@Repository. |
| MVC page controller |
@Controller. |
| REST endpoint |
@RestController. |
Do not use field injection for required collaborators. Constructor injection makes dependencies explicit, testable, and immutable.
Configuration and secrets
| Concern |
Rule |
| Files |
Use application.yml or application.properties; prefer YAML for hierarchical settings when the project already uses it. |
| Type safety |
Bind settings with @ConfigurationProperties to strongly-typed Java objects instead of scattering @Value keys. |
| Environments |
Use Spring Profiles such as application-dev.yml and application-prod.yml for environment-specific configuration. |
| Secrets |
Do not hardcode secrets. Use environment variables, HashiCorp Vault, AWS Secrets Manager, or the platform's secret store. |
Web, validation, and error handling
| Area |
Practice |
| REST API |
Use clear resource-oriented endpoints and consistent status codes. |
| DTOs |
Expose and consume DTOs; do not return JPA entities directly to clients. |
| Validation |
Use Java Bean Validation / JSR 380 annotations such as @Valid, @NotNull, and @Size on request DTOs. |
| Errors |
Centralize responses with @ControllerAdvice and @ExceptionHandler. |
| Sanitization |
Prevent SQL injection with Spring Data JPA or parameterized queries; encode output to prevent Cross-Site Scripting (XSS). |
Services and data access
| Area |
Practice |
| Business logic |
Put business rules in @Service classes, not controllers or repositories. |
| Statelessness |
Keep services stateless except for injected dependencies. |
| Transactions |
Apply @Transactional at the most granular service method that owns the unit of work. |
| Repositories |
Extend JpaRepository or CrudRepository for standard persistence. |
| Complex queries |
Use @Query, the JPA Criteria API, or projections. |
| Read models |
Use DTO projections to fetch only needed columns. |
Logging, tests, and security
| Topic |
Rule |
| Logging API |
Use SLF4J. Declare private static final Logger logger = LoggerFactory.getLogger(MyClass.class);. |
| Log messages |
Prefer parameterized logging: logger.info("Processing user {}...", userId);. |
| Unit tests |
Use JUnit 5 with Mockito for services and components. |
| Integration tests |
Use @SpringBootTest when the full application context is required. |
| Test slices |
Use @WebMvcTest for controllers and @DataJpaTest for repositories. |
| External dependencies in tests |
Consider Testcontainers for real databases or brokers. |
| Authentication |
Use Spring Security for authentication and authorization. |
| Passwords |
Encode passwords with BCrypt. |
Gotchas
- Do not expose JPA entities from controllers: lazy-loading, over-posting, and accidental schema coupling follow.
- Do not put transactions on controllers: service methods should own business transaction boundaries.
- Do not concatenate user input into queries: rely on Spring Data JPA, bound parameters, or criteria APIs.
- Do not log secrets or raw PII: parameterized logging helps performance, not data safety.
Output template
## Spring Boot implementation guidance
**Target:** <feature, class, or endpoint>
| Area | Recommendation | Concrete API or file |
| --- | --- | --- |
| Structure | <package/module choice> | `<package>` |
| Web | <controller/DTO/validation rule> | `@RestController`, `@Valid` |
| Service | <business logic and transaction boundary> | `@Service`, `@Transactional` |
| Data | <repository/query/projection rule> | `JpaRepository`, `@Query` |
| Tests | <unit/slice/integration strategy> | `@WebMvcTest`, `@DataJpaTest`, `@SpringBootTest` |
### Risks to avoid
- <anti-pattern and correction>
Quality gate
1---2name: java-springboot3description: Apply Spring Boot best practices for project structure, dependency injection, configuration, REST controllers, DTO validation, services, transactions, Spring Data JPA, logging, testing, and security. Use when asked for Spring Boot guidance or to implement Java backend code.4---56<!-- Generated from harness/github-copilot/skills/java-springboot/SKILL.md by harness/claude-code/scripts/convert_from_copilot.py. Edit the source, not this file. -->78# Spring Boot best practices910Turn Spring Boot implementation requests into high-quality Java applications with domain-oriented packages, explicit dependencies, externalized configuration, validated APIs, transactional services, safe persistence, structured logging, and focused tests.1112## When to invoke1314- "Show Spring Boot best practices for this service."15- "Refactor this controller, service, and repository."16- "How should I structure a Spring Boot application?"17- "Add validation, error handling, and tests to this Spring Boot endpoint."1819## Project setup and package structure2021| Concern | Preferred approach | Avoid |22| --- | --- | --- |23| Build tool | Maven `pom.xml` or Gradle `build.gradle`. | Manual dependency jars. |24| Dependencies | Spring Boot starters such as `spring-boot-starter-web` and `spring-boot-starter-data-jpa`. | Hand-picking transitive Spring libraries. |25| Packages | `feature/domain` packages such as `com.example.app.order` and `com.example.app.user`. | Layer-only packages such as `com.example.app.controller`, `com.example.app.service`, and `repository` for every domain. |26| Boundaries | Keep controller DTOs, service logic, repository contracts, and persistence models explicit. | Letting web, persistence, and domain concerns leak into each other. |2728## Components and dependency injection2930| Need | Use |31| --- | --- |32| Required dependencies | `constructor-based` injection with `private final` fields. |33| General bean | `@Component`. |34| Business operation | `@Service`. |35| Persistence adapter | `@Repository`. |36| MVC page controller | `@Controller`. |37| REST endpoint | `@RestController`. |3839Do not use field injection for required collaborators. Constructor injection makes dependencies explicit, testable, and immutable.4041## Configuration and secrets4243| Concern | Rule |44| --- | --- |45| Files | Use `application.yml` or `application.properties`; prefer YAML for hierarchical settings when the project already uses it. |46| Type safety | Bind settings with `@ConfigurationProperties` to strongly-typed Java objects instead of scattering `@Value` keys. |47| Environments | Use Spring Profiles such as `application-dev.yml` and `application-prod.yml` for environment-specific configuration. |48| Secrets | Do not hardcode secrets. Use environment variables, HashiCorp Vault, AWS Secrets Manager, or the platform's secret store. |4950## Web, validation, and error handling5152| Area | Practice |53| --- | --- |54| REST API | Use clear resource-oriented endpoints and consistent status codes. |55| DTOs | Expose and consume DTOs; do not return JPA entities directly to clients. |56| Validation | Use Java Bean Validation / JSR 380 annotations such as `@Valid`, `@NotNull`, and `@Size` on request DTOs. |57| Errors | Centralize responses with `@ControllerAdvice` and `@ExceptionHandler`. |58| Sanitization | Prevent SQL injection with Spring Data JPA or parameterized queries; encode output to prevent Cross-Site Scripting (XSS). |5960## Services and data access6162| Area | Practice |63| --- | --- |64| Business logic | Put business rules in `@Service` classes, not controllers or repositories. |65| Statelessness | Keep services stateless except for injected dependencies. |66| Transactions | Apply `@Transactional` at the most granular service method that owns the unit of work. |67| Repositories | Extend `JpaRepository` or `CrudRepository` for standard persistence. |68| Complex queries | Use `@Query`, the JPA Criteria API, or projections. |69| Read models | Use DTO projections to fetch only needed columns. |7071## Logging, tests, and security7273| Topic | Rule |74| --- | --- |75| Logging API | Use SLF4J. Declare `private static final Logger logger = LoggerFactory.getLogger(MyClass.class);`. |76| Log messages | Prefer parameterized logging: `logger.info("Processing user {}...", userId);`. |77| Unit tests | Use JUnit 5 with Mockito for services and components. |78| Integration tests | Use `@SpringBootTest` when the full application context is required. |79| Test slices | Use `@WebMvcTest` for controllers and `@DataJpaTest` for repositories. |80| External dependencies in tests | Consider Testcontainers for real databases or brokers. |81| Authentication | Use Spring Security for authentication and authorization. |82| Passwords | Encode passwords with BCrypt. |8384## Gotchas8586- **Do not expose JPA entities from controllers**: lazy-loading, over-posting, and accidental schema coupling follow.87- **Do not put transactions on controllers**: service methods should own business transaction boundaries.88- **Do not concatenate user input into queries**: rely on Spring Data JPA, bound parameters, or criteria APIs.89- **Do not log secrets or raw PII**: parameterized logging helps performance, not data safety.9091## Output template9293```markdown94## Spring Boot implementation guidance9596**Target:** <feature, class, or endpoint>9798| Area | Recommendation | Concrete API or file |99| --- | --- | --- |100| Structure | <package/module choice> | `<package>` |101| Web | <controller/DTO/validation rule> | `@RestController`, `@Valid` |102| Service | <business logic and transaction boundary> | `@Service`, `@Transactional` |103| Data | <repository/query/projection rule> | `JpaRepository`, `@Query` |104| Tests | <unit/slice/integration strategy> | `@WebMvcTest`, `@DataJpaTest`, `@SpringBootTest` |105106### Risks to avoid107- <anti-pattern and correction>108```109110## Quality gate111112- [ ] Dependencies use Maven or Gradle and Spring Boot starters where appropriate.113- [ ] Required dependencies use constructor injection and `private final` fields.114- [ ] Configuration is externalized through `application.yml` or `application.properties`, with secrets outside source code.115- [ ] Controllers use DTOs, validation, and centralized error handling.116- [ ] Business logic and transactions live in services, with `@Transactional` at the right boundary.117- [ ] Data access uses Spring Data repositories, safe queries, and projections when useful.118- [ ] Tests use the smallest appropriate level: unit, test slice, or integration.