home / skills / gentleman-programming / gentleman-skills / spring-boot-3

spring-boot-3 skill

/community/spring-boot-3

This skill helps you apply Spring Boot 3 configuration, DI, and REST patterns to build robust services with validated properties and transactional services.

npx playbooks add skill gentleman-programming/gentleman-skills --skill spring-boot-3

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
3.6 KB
---
name: spring-boot-3
description: >
  Spring Boot 3 patterns for configuration, DI, and web services.
  Trigger: When building or refactoring Spring Boot 3 applications.
metadata:
  author: diegnghrmr
  version: "1.0"
---

## When to Use

Load this skill when:
- Building a Spring Boot 3.3+ service or API
- Wiring beans with dependency injection
- Defining configuration properties and validation
- Implementing REST controllers and service layers

## Critical Patterns

### Pattern 1: Constructor injection only

Always use constructor injection; avoid field injection.

### Pattern 2: Typed configuration properties

Use @ConfigurationProperties with validation, not scattered @Value.

### Pattern 3: Transaction boundaries at service layer

Apply @Transactional on application services, not controllers.

## Code Examples

### Example 1: Configuration properties with validation

```java
package com.acme.config;

import jakarta.validation.constraints.NotBlank;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@Validated
@ConfigurationProperties(prefix = "payment")
public record PaymentProperties(
  @NotBlank String provider,
  @NotBlank String apiKey
) { }
```

```java
package com.acme;

import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@ConfigurationPropertiesScan
public class Application { }
```

### Example 2: Service with constructor injection + transaction

```java
package com.acme.order.application;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public final class OrderService {
  private final OrderRepository repository;

  public OrderService(OrderRepository repository) {
    this.repository = repository;
  }

  @Transactional
  public void placeOrder(OrderCommand command) {
    repository.save(command.toEntity());
  }
}
```

### Example 3: REST controller with DTO records

```java
package com.acme.order.api;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/orders")
public final class OrderController {
  private final OrderService service;

  public OrderController(OrderService service) {
    this.service = service;
  }

  @PostMapping
  public ResponseEntity<OrderResponse> place(@RequestBody OrderRequest request) {
    service.placeOrder(request.toCommand());
    return ResponseEntity.ok(new OrderResponse("ok"));
  }

  public record OrderRequest(String sku, int qty) {
    public OrderCommand toCommand() { return new OrderCommand(sku, qty); }
  }

  public record OrderResponse(String status) { }
}
```

## Anti-Patterns

### Don't: Use field injection

```java
// BAD: field injection
@Service
public class OrderService {
  @org.springframework.beans.factory.annotation.Autowired
  private OrderRepository repository;
}
```

### Don't: Scatter configuration with @Value

```java
// BAD: hard to validate and test
@Service
public class PaymentService {
  @org.springframework.beans.factory.annotation.Value("${payment.apiKey}")
  private String apiKey;
}
```

## Quick Reference

| Task | Pattern |
|------|---------|
| Inject dependencies | Constructor injection only |
| Read config | @ConfigurationProperties + @Validated |
| Transactions | @Transactional on services |

## Resources

- Spring Boot Reference: https://docs.spring.io/spring-boot/docs/current/reference/html/
- Spring Framework Reference: https://docs.spring.io/spring-framework/reference/

Overview

This skill captures recommended Spring Boot 3 patterns for configuration, dependency injection, transaction management, and web APIs. It codifies practical conventions to make services testable, validated, and easy to maintain. Use it as a quick guide when building or refactoring Spring Boot 3.3+ applications.

How this skill works

The skill inspects common design areas and prescribes focused patterns: prefer constructor injection, centralize configuration with @ConfigurationProperties plus validation, and place transaction boundaries on service-layer methods. It also shows lightweight controller patterns using records for DTOs and recommends avoiding field injection and scattered @Value usage. Follow the patterns to improve testability, validation, and separation of concerns.

When to use it

  • When creating or refactoring a Spring Boot 3.3+ service or API
  • When wiring beans to ensure clear dependencies and testability
  • When externalizing configuration that needs validation and type safety
  • When defining transactional behavior for business operations
  • When designing REST controllers and request/response DTOs

Best practices

  • Always use constructor injection to make dependencies explicit and mockable
  • Define configuration with @ConfigurationProperties and @Validated for typed, testable settings
  • Annotate business services (not controllers) with @Transactional to bound transactions
  • Represent simple DTOs with Java records for concise, immutable data carriers
  • Centralize configuration scanning (e.g., @ConfigurationPropertiesScan) rather than sprinkling @Value

Example use cases

  • Create a PaymentProperties record with @ConfigurationProperties(prefix="payment") and validation annotations to hold provider and apiKey
  • Implement OrderService with constructor injection and @Transactional for placeOrder business logic
  • Build REST endpoints where controllers delegate to services and map request records to commands
  • Refactor legacy code that uses field injection and multiple @Value-annotated fields into constructor-injected services and configuration properties
  • Add validation for configuration early to fail fast on bad deployments

FAQ

Why prefer constructor injection over field injection?

Constructor injection makes dependencies explicit, supports immutability, and is easier to unit test without container wiring.

When should I use @Value instead of @ConfigurationProperties?

Use @Value only for one-off simple values; prefer @ConfigurationProperties for grouped, typed, and validated configuration.