Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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.
.claude/skills/jeffallan-spring-boot-engineer/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 355% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 248% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 106% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 112% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 104% | 0% |
./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 suite/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-validateLoad detailed guidance based on context:
| Topic | Reference | Load When | |-------|-----------|-----------| | Web Layer | references/web.md | Controllers, REST APIs, validation, exception handling | | Data Access | references/data.md | Spring Data JPA, repositories, transactions, projections | | Security | references/security.md | Spring Security 6, OAuth2, JWT, method security | | Cloud Native | references/cloud.md | Spring Cloud, Config, Discovery, Gateway, resilience | | Testing | references/testing.md | @SpringBootTest, MockMvc, Testcontainers, test slices |
A standard Spring Boot feature consists of these layers. Use these as copy-paste starting points.
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 or use @Data (Lombok) }
javapublic interface ProductRepository extends JpaRepository<Product, Long> { List<Product> findByNameContainingIgnoreCase(String name); }
java@Service public class ProductService { private final ProductRepository repo; public ProductService(ProductRepository repo) { // constructor injection — no @Autowired this.repo = repo; } @Transactional(readOnly = true) 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); } }
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); } }
javapublic record ProductRequest( @NotBlank String name, @DecimalMin("0.0") BigDecimal price ) {}
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, FieldError::getDefaultMessage)); } @ExceptionHandler(EntityNotFoundException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public Map<String, String> handleNotFound(EntityNotFoundException ex) { return Map.of("error", ex.getMessage()); } }
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"); product.setPrice(BigDecimal.TEN); 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")); } }
| Rule | Correct Pattern | |------|----------------| | Constructor injection | public MyService(Dep dep) { this.dep = dep; } | | Validate API input | @Valid @RequestBody MyRequest req on every mutating endpoint | | Type-safe config | @ConfigurationProperties(prefix = "app") bound to a record/class | | Appropriate stereotype | @Service for business logic, @Repository for data, @RestController for HTTP | | Transaction scope | @Transactional on multi-step writes; @Transactional(readOnly = true) on reads | | Hide internals | Catch domain exceptions in @RestControllerAdvice; return problem details, not stack traces | | Externalize secrets | Use environment variables or Spring Cloud Config — never application.properties |
@Autowired on fields)@Component when @Service/@Repository/@Controller applies.block() inside a WebFlux chain)application.properties/application.ymlWebSecurityConfigurerAdapter)| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 3,244 | 6,780 | +109% | 1 | 1 | 0% | 602 | 2,741 | +355% | 0 | 0 | — |
case-02 | pass→pass | 5,985 | 4,289 | -28% | 1 | 1 | 0% | 1,176 | 2,404 | +104% | 0 | 0 | — |
case-03 | pass→pass | 11,887 | 8,025 | -32% | 1 | 1 | 0% | 2,264 | 3,203 | +41% | 0 | 0 | — |
case-04 | pass→pass | 9,906 | 8,216 | -17% | 1 | 1 | 0% | 2,030 | 3,219 | +59% | 0 | 0 | — |
case-05 | pass→pass | 9,003 | 8,297 | -8% | 1 | 1 | 0% | 2,101 | 3,333 | +59% | 0 | 0 | — |
case-06 | fail→pass | 5,895 | 11,246 | +91% | 1 | 1 | 0% | 1,101 | 3,835 | +248% | 0 | 0 | — |
case-07 | pass→pass | 7,070 | 5,697 | -19% | 1 | 1 | 0% | 1,503 | 2,714 | +81% | 0 | 0 | — |
case-08 | pass→pass | 8,743 | 7,498 | -14% | 1 | 1 | 0% | 1,837 | 3,038 | +65% | 0 | 0 | — |
case-09 | pass→pass | 10,455 | 8,860 | -15% | 1 | 1 | 0% | 2,257 | 3,376 | +50% | 0 | 0 | — |
case-10 | pass→pass | 7,546 | 3,316 | -56% | 1 | 1 | 0% | 1,714 | 2,197 | +28% | 0 | 0 | — |
case-11 | pass→pass | 10,268 | 13,749 | +34% | 1 | 1 | 0% | 2,528 | 4,646 | +84% | 0 | 0 | — |
case-12 | pass→pass | 5,087 | 4,121 | -19% | 1 | 1 | 0% | 875 | 2,270 | +159% | 0 | 0 | — |
case-13 | fail→fail | 3,433 | 3,216 | -6% | 1 | 1 | 0% | 612 | 2,094 | +242% | 0 | 0 | — |
case-14 | fail→pass | 7,752 | 7,446 | -4% | 1 | 1 | 0% | 1,486 | 3,063 | +106% | 0 | 0 | — |
case-15 | fail→pass | 5,981 | 5,579 | -7% | 1 | 1 | 0% | 1,302 | 2,757 | +112% | 0 | 0 | — |
case-16 | pass→pass | 4,877 | 5,622 | +15% | 1 | 1 | 0% | 1,203 | 2,926 | +143% | 0 | 0 | — |
case-17 | pass→pass | 10,117 | 7,219 | -29% | 1 | 1 | 0% | 2,076 | 3,135 | +51% | 0 | 0 | — |
case-18 | pass→pass | 6,082 | 6,606 | +9% | 1 | 1 | 0% | 1,251 | 2,889 | +131% | 0 | 0 | — |
case-19 | pass→pass | 7,637 | 6,563 | -14% | 1 | 1 | 0% | 1,486 | 2,827 | +90% | 0 | 0 | — |
case-20 | fail→fail | 2,164 | 2,561 | +18% | 1 | 1 | 0% | 328 | 1,978 | +503% | 0 | 0 | — |
case-21 | pass→pass | 10,607 | 12,729 | +20% | 1 | 1 | 0% | 2,609 | 4,587 | +76% | 0 | 0 | — |
case-22 | pass→pass | 7,060 | 6,873 | -3% | 1 | 1 | 0% | 1,377 | 2,969 | +116% | 0 | 0 | — |
case-23 | pass→pass | 4,681 | 3,507 | -25% | 1 | 1 | 0% | 922 | 2,198 | +138% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +17 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.