Spring Boot Skill
Enterprise Spring Boot 3.x development with focus on clean architecture and production-ready code.
Core Workflow
- Analyze - Understand requirements, identify service boundaries, APIs, data models
- Design - Plan architecture, confirm design before coding
- Implement - Build with constructor injection and layered architecture
- Secure - Add Spring Security, OAuth2, method security; verify tests pass
- Test - Write unit, integration tests; run
./mvnw testand confirm all pass - Deploy - Configure health checks via Actuator; validate
/actuator/healthreturns UP
Quick Start Templates
Entity
java@Entity @Table(name = "products") public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotBlank private String name; @DecimalMin("0.0") private BigDecimal price; // Getters/Setters (no Lombok) }
Repository
javapublic interface ProductRepository extends JpaRepository<Product, Long> { List<Product> findByNameContainingIgnoreCase(String name); }
Service
java@Service @Transactional(readOnly = true) public class ProductService { private final ProductRepository repo; public ProductService(ProductRepository repo) { this.repo = repo; } public List<Product> search(String name) { return repo.findByNameContainingIgnoreCase(name); } @Transactional public Product create(ProductRequest request) { var product = new Product(); product.setName(request.name()); product.setPrice(request.price()); return repo.save(product); } }
REST Controller
java@RestController @RequestMapping("/api/v1/products") @Validated public class ProductController { private final ProductService service; public ProductController(ProductService service) { this.service = service; } @GetMapping public List<Product> search(@RequestParam(defaultValue = "") String name) { return service.search(name); } @PostMapping @ResponseStatus(HttpStatus.CREATED) public Product create(@Valid @RequestBody ProductRequest request) { return service.create(request); } }
DTO (Record)
javapublic record ProductRequest( @NotBlank String name, @DecimalMin("0.0") BigDecimal price ) {}
Global Exception Handler
java@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public Map<String, String> handleValidation(MethodArgumentNotValidException ex) { return ex.getBindingResult().getFieldErrors().stream() .collect(Collectors.toMap(FieldError::getField, error -> error.getDefaultMessage() != null ? error.getDefaultMessage() : "Invalid")); } @ExceptionHandler(EntityNotFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public Map<String, String> handleNotFound(EntityNotFoundException ex) { return Map.of("error", ex.getMessage()); } }
Test Slice
java@WebMvcTest(ProductController.class) class ProductControllerTest { @Autowired MockMvc mockMvc; @MockBean ProductService service; @Test void createProduct_validRequest_returns201() throws Exception { var product = new Product(); product.setName("Widget"); when(service.create(any())).thenReturn(product); mockMvc.perform(post("/api/v1/products") .contentType(MediaType.APPLICATION_JSON) .content("""{"name":"Widget","price":10.0}""")) .andExpect(status().isCreated()) .andExpect(jsonPath("$.name").value("Widget")); } }
Reference Guide
Load detailed patterns based on context:
| Topic | Reference | When to Load |
|---|---|---|
| Web/REST | references/web.md | Controllers, validation, exception handling |
| Data Access | references/data.md | JPA, repositories, transactions, queries |
| Security | references/security.md | Spring Security 6, OAuth2, JWT, auth |
| Cloud/Config | references/cloud.md | Config server, discovery, resilience |
| Testing | references/testing.md | Unit, integration, slice tests |
Constraints
MUST DO
- Constructor injection (no field injection)
@Validon all request bodies@Transactionalfor multi-step writes@Transactional(readOnly = true)for reads- Type-safe config with
@ConfigurationProperties - Global exception handling with
@RestControllerAdvice - Externalize secrets (use env vars, not properties files)
MUST NOT DO
- Field injection (
@Autowiredon fields) - Skip input validation on endpoints
- Mix blocking and reactive code
- Store secrets in application.properties
- Use deprecated Spring Boot 2.x patterns
- Hardcode URLs, credentials, environment values
Architecture Patterns
Project Structure:
src/main/java/pl/piomin/services/ ├── controller/ # REST endpoints ├── service/ # Business logic ├── repository/ # Data access ├── model/ # Entities ├── dto/ # Request/Response DTOs ├── config/ # Configuration └── exception/ # Custom exceptions + handler
Layering:
- Controller → Service → Repository
- Controller handles HTTP, validation
- Service handles business logic, transactions
- Repository handles data persistence
Clean Architecture Principles:
- Domain models independent of frameworks
- Use case driven design
- Dependency inversion (interfaces)
- Clear boundaries between layers
Common Annotations
| Annotation | Purpose |
|---|---|
@RestController | REST controller (combines @Controller + @ResponseBody) |
@Service | Business logic component |
@Repository | Data access component |
@Transactional | Transaction management |
@Valid | Trigger validation |
@ConfigurationProperties | Bind properties to class |
@EnableMethodSecurity | Enable method security |
Reactive WebFlux Endpoint
java@RestController @RequestMapping("/api/v1/orders") public class OrderController { private final OrderService orderService; public OrderController(OrderService orderService) { this.orderService = orderService; } @GetMapping("/{id}") public Mono<ResponseEntity<OrderDto>> getOrder(@PathVariable UUID id) { return orderService.findById(id) .map(ResponseEntity::ok) .defaultIfEmpty(ResponseEntity.notFound().build()); } @PostMapping @ResponseStatus(HttpStatus.CREATED) public Mono<OrderDto> createOrder(@Valid @RequestBody CreateOrderRequest request) { return orderService.create(request); } }
Spring Security JWT
java@Configuration @EnableMethodSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .csrf(AbstractHttpConfigurer::disable) .sessionManagement(s -> s.sessionCreationPolicy(STATELESS)) .authorizeHttpRequests(auth -> auth .requestMatchers("/actuator/health").permitAll() .anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())) .build(); } }
Knowledge Base
Spring Boot 3.x, Java 21, Spring WebFlux, Project Reactor, Spring Data JPA, Spring Security 6, OAuth2/JWT, Hibernate, R2DBC, Spring Cloud, Resilience4j, Micrometer, JUnit 5, TestContainers, Mockito, Maven/Gradle


