Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build Spring Boot 3.x REST APIs, microservices, and reactive WebFlux apps with Spring Security 6 and JPA.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
SKILL.md
1---2name: spring-boot-engineer3description: Generates Spring Boot 3.x configurations, creates REST controllers, implements Spring Security 6 authentication flows, sets up Spring Data JPA repositories, and configures reactive WebFlux endpoints. Use when building Spring Boot 3.x applications, microservices, or reactive Java applications; invoke for Spring Data JPA, Spring Security 6, WebFlux, Spring Cloud integration, Java REST API design, or Microservices Java architecture.4license: MIT5metadata:6author: https://github.com/Jeffallan7version: "1.1.0"8domain: backend9triggers: Spring Boot, Spring Framework, Spring Cloud, Spring Security, Spring Data JPA, Spring WebFlux, Microservices Java, Java REST API, Reactive Java10role: specialist11scope: implementation12output-format: code13related-skills: java-architect, database-optimizer, microservices-architect, devops-engineer14---1516# Spring Boot Engineer1718## Core Workflow19201. **Analyze requirements** — Identify service boundaries, APIs, data models, security needs212. **Design architecture** — Plan microservices, data access, cloud integration, security; confirm design before coding223. **Implement** — Create services with constructor injection and layered architecture (see Quick Start below)234. **Secure** — Add Spring Security, OAuth2, method security, CORS configuration; verify security rules compile and pass tests. If compilation or tests fail: review error output, fix the failing rule or configuration, and re-run before proceeding245. **Test** — Write unit, integration, and slice tests; run `./mvnw test` (or `./gradlew test`) and confirm all pass before proceeding. If tests fail: review the stack trace, isolate the failing assertion or component, fix the issue, and re-run the full suite256. **Deploy** — Configure health checks and observability via Actuator; validate `/actuator/health` returns `UP`. If health is `DOWN`: check the `components` detail in the response, resolve the failing component (e.g., datasource, broker), and re-validate2627## Reference Guide2829Load detailed guidance based on context:3031| Topic | Reference | Load When |32|-------|-----------|-----------|33| Web Layer | `references/web.md` | Controllers, REST APIs, validation, exception handling |34| Data Access | `references/data.md` | Spring Data JPA, repositories, transactions, projections |35| Security | `references/security.md` | Spring Security 6, OAuth2, JWT, method security |36| Cloud Native | `references/cloud.md` | Spring Cloud, Config, Discovery, Gateway, resilience |37| Testing | `references/testing.md` | @SpringBootTest, MockMvc, Testcontainers, test slices |3839## Quick Start — Minimal Working Structure4041A standard Spring Boot feature consists of these layers. Use these as copy-paste starting points.4243### Entity4445```java46@Entity47@Table(name = "products")48public class Product {49@Id50@GeneratedValue(strategy = GenerationType.IDENTITY)51private Long id;5253@NotBlank54private String name;5556@DecimalMin("0.0")57private BigDecimal price;5859// getters / setters or use @Data (Lombok)60}61```6263### Repository6465```java66public interface ProductRepository extends JpaRepository<Product, Long> {67List<Product> findByNameContainingIgnoreCase(String name);68}69```7071### Service (constructor injection)7273```java74@Service75public class ProductService {76private final ProductRepository repo;7778public ProductService(ProductRepository repo) { // constructor injection — no @Autowired79this.repo = repo;80}8182@Transactional(readOnly = true)83public List<Product> search(String name) {84return repo.findByNameContainingIgnoreCase(name);85}8687@Transactional88public Product create(ProductRequest request) {89var product = new Product();90product.setName(request.name());91product.setPrice(request.price());92return repo.save(product);93}94}95```9697### REST Controller9899```java100@RestController101@RequestMapping("/api/v1/products")102@Validated103public class ProductController {104private final ProductService service;105106public ProductController(ProductService service) {107this.service = service;108}109110@GetMapping111public List<Product> search(@RequestParam(defaultValue = "") String name) {112return service.search(name);113}114115@PostMapping116@ResponseStatus(HttpStatus.CREATED)117public Product create(@Valid @RequestBody ProductRequest request) {118return service.create(request);119}120}121```122123### DTO (record)124125```java126public record ProductRequest(127@NotBlank String name,128@DecimalMin("0.0") BigDecimal price129) {}130```131132### Global Exception Handler133134```java135@RestControllerAdvice136public class GlobalExceptionHandler {137@ExceptionHandler(MethodArgumentNotValidException.class)138@ResponseStatus(HttpStatus.BAD_REQUEST)139public Map<String, String> handleValidation(MethodArgumentNotValidException ex) {140return ex.getBindingResult().getFieldErrors().stream()141.collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));142}143144@ExceptionHandler(EntityNotFoundException.class)145@ResponseStatus(HttpStatus.NOT_FOUND)146public Map<String, String> handleNotFound(EntityNotFoundException ex) {147return Map.of("error", ex.getMessage());148}149}150```151152### Test Slice153154```java155@WebMvcTest(ProductController.class)156class ProductControllerTest {157@Autowired MockMvc mockMvc;158@MockBean ProductService service;159160@Test161void createProduct_validRequest_returns201() throws Exception {162var product = new Product(); product.setName("Widget"); product.setPrice(BigDecimal.TEN);163when(service.create(any())).thenReturn(product);164165mockMvc.perform(post("/api/v1/products")166.contentType(MediaType.APPLICATION_JSON)167.content("""{"name":"Widget","price":10.0}"""))168.andExpect(status().isCreated())169.andExpect(jsonPath("$.name").value("Widget"));170}171}172```173174## Constraints175176### MUST DO177178| Rule | Correct Pattern |179|------|----------------|180| Constructor injection | `public MyService(Dep dep) { this.dep = dep; }` |181| Validate API input | `@Valid @RequestBody MyRequest req` on every mutating endpoint |182| Type-safe config | `@ConfigurationProperties(prefix = "app")` bound to a record/class |183| Appropriate stereotype | `@Service` for business logic, `@Repository` for data, `@RestController` for HTTP |184| Transaction scope | `@Transactional` on multi-step writes; `@Transactional(readOnly = true)` on reads |185| Hide internals | Catch domain exceptions in `@RestControllerAdvice`; return problem details, not stack traces |186| Externalize secrets | Use environment variables or Spring Cloud Config — never `application.properties` |187188### MUST NOT DO189- Use field injection (`@Autowired` on fields)190- Skip input validation on API endpoints191- Use `@Component` when `@Service`/`@Repository`/`@Controller` applies192- Mix blocking and reactive code (e.g., calling `.block()` inside a WebFlux chain)193- Store secrets or credentials in `application.properties`/`application.yml`194- Hardcode URLs, credentials, or environment-specific values195- Use deprecated Spring Boot 2.x patterns (e.g., `WebSecurityConfigurerAdapter`)196197[Documentation](https://jeffallan.github.io/claude-skills/skills/backend/spring-boot-engineer/)198