Agent skill
spring-boot-coding-standards
Guide for Spring Boot coding best practices including dependency injection, error handling, and API design. Use this when writing or reviewing Spring Boot code.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/spring-boot-coding-standards
SKILL.md
Spring Boot Coding Standards
Follow these coding standards when developing Spring Boot applications.
Constructor Injection (Required)
ALWAYS use constructor injection instead of field injection:
// ✅ CORRECT: Constructor injection
@Service
public class AppointmentService {
private final AppointmentRepository appointmentRepository;
private final CustomerService customerService;
public AppointmentService(AppointmentRepository appointmentRepository,
CustomerService customerService) {
this.appointmentRepository = appointmentRepository;
this.customerService = customerService;
}
}
// ❌ WRONG: Field injection
@Service
public class AppointmentService {
@Autowired
private AppointmentRepository appointmentRepository;
@Autowired
private CustomerService customerService;
}
DTOs and Value Objects
Create immutable DTOs when possible:
// Request DTO with validation
public class AppointmentRequestDTO {
@NotNull(message = "Customer ID is required")
private Long customerId;
@NotNull(message = "Employee ID is required")
private Long employeeId;
@NotNull(message = "Service type is required")
private Long serviceTypeId;
@FutureOrPresent(message = "Appointment time must be in the future")
private LocalDateTime appointmentTime;
// Getters and setters
}
// Response DTO (immutable pattern)
public final class AppointmentResponseDTO {
private final Long id;
private final String customerName;
private final String employeeName;
private final String serviceType;
private final LocalDateTime appointmentTime;
private final String status;
// Constructor and getters only
}
Error Handling
Implement global exception handling:
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {
logger.error("Resource not found: {}", ex.getMessage());
return new ResponseEntity<>(
new ErrorResponse("NOT_FOUND", ex.getMessage()),
HttpStatus.NOT_FOUND
);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
String message = ex.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
return new ResponseEntity<>(
new ErrorResponse("VALIDATION_ERROR", message),
HttpStatus.BAD_REQUEST
);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGeneric(Exception ex) {
logger.error("Unexpected error", ex);
return new ResponseEntity<>(
new ErrorResponse("INTERNAL_ERROR", "An unexpected error occurred"),
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
Optional Handling
Never use .get() without checking:
// ✅ CORRECT
public User getUser(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("User not found: " + id));
}
// ❌ WRONG - Can throw NoSuchElementException
public User getUser(Long id) {
return userRepository.findById(id).get();
}
RESTful API Design
Follow REST conventions:
@RestController
@RequestMapping("/api/appointments")
public class AppointmentController {
@GetMapping // GET all
public List<AppointmentDTO> getAll() { }
@GetMapping("/{id}") // GET by ID
public AppointmentDTO getById(@PathVariable Long id) { }
@PostMapping // CREATE
public ResponseEntity<AppointmentDTO> create(@Valid @RequestBody AppointmentRequestDTO dto) {
AppointmentDTO created = service.create(dto);
return ResponseEntity.status(HttpStatus.CREATED).body(created);
}
@PutMapping("/{id}") // UPDATE
public AppointmentDTO update(@PathVariable Long id, @Valid @RequestBody AppointmentRequestDTO dto) { }
@DeleteMapping("/{id}") // DELETE
public ResponseEntity<Void> delete(@PathVariable Long id) {
service.delete(id);
return ResponseEntity.noContent().build();
}
}
Lombok Usage
Use Lombok judiciously:
@Data // For entities with caution (equals/hashCode issues)
@NoArgsConstructor // Required for JPA
@AllArgsConstructor // Useful for testing
@Builder // For complex object construction
public class Appointment {
// fields
}
// For DTOs, prefer explicit immutable pattern or:
@Getter
@AllArgsConstructor
public class AppointmentResponseDTO {
private final Long id;
private final String name;
}
Input Validation
Always validate user input:
@PostMapping
public ResponseEntity<CustomerDTO> createCustomer(
@Valid @RequestBody CustomerRequest request) {
// Process validated input
}
public class CustomerRequest {
@NotBlank(message = "Name is required")
@Size(min = 2, max = 100, message = "Name must be 2-100 characters")
private String name;
@Email(message = "Invalid email format")
private String email;
@Pattern(regexp = "^\\+?[1-9]\\d{1,14}$", message = "Invalid phone number")
private String phone;
}
Transaction Management
@Service
@Transactional(readOnly = true) // Default read-only for safety
public class OrderService {
@Transactional // Override for write operations
public Order placeOrder(OrderRequest request) {
Order order = new Order();
// ... set order details
return orderRepository.save(order);
}
// Read operation uses class-level readOnly = true
public Order getOrder(Long id) {
return orderRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Order not found"));
}
}
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?