spring-boot-patterns — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited spring-boot-patterns (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Core patterns for building production-ready Spring Boot applications.
Use the correct annotation for each architectural layer. Spring applies different behaviors to each.
@Repository // Data access -- translates persistence exceptions
public class UserRepository {
private final JdbcTemplate jdbc;
public UserRepository(JdbcTemplate jdbc) { this.jdbc = jdbc; }
public Optional<User> findById(Long id) {
return jdbc.query("SELECT * FROM users WHERE id = ?",
new BeanPropertyRowMapper<>(User.class), id).stream().findFirst();
}
}
@Service // Business logic -- transactional boundaries live here
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) { this.userRepository = userRepository; }
@Transactional
public User createUser(CreateUserRequest request) {
return userRepository.save(new User(request.name(), request.email()));
}
}
@RestController // Web layer -- handles HTTP requests
@RequestMapping("/api/v1/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) { this.userService = userService; }
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public UserResponse createUser(@Valid @RequestBody CreateUserRequest request) {
return UserResponse.from(userService.createUser(request));
}
}Always use constructor injection. It makes dependencies explicit, supports immutability, and works with final fields. Avoid field injection with @Autowired.
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final PaymentGateway paymentGateway;
private final NotificationService notificationService;
// Single constructor -- @Autowired is implicit, no annotation needed
public OrderService(
OrderRepository orderRepository,
PaymentGateway paymentGateway,
NotificationService notificationService) {
this.orderRepository = orderRepository;
this.paymentGateway = paymentGateway;
this.notificationService = notificationService;
}
}Use profiles to swap implementations and configuration per environment.
# application.yml -- shared defaults
spring:
application:
name: my-service
---
# application-dev.yml
spring:
datasource:
url: jdbc:h2:mem:devdb
driver-class-name: org.h2.Driver
jpa:
show-sql: true
---
# application-prod.yml
spring:
datasource:
url: jdbc:postgresql://${DB_HOST}:5432/${DB_NAME}
username: ${DB_USER}
password: ${DB_PASSWORD}
jpa:
show-sql: falseProfile-specific beans:
@Configuration
public class StorageConfig {
@Bean
@Profile("dev")
public StorageService localStorageService() {
return new LocalFileStorageService("/tmp/uploads");
}
@Bean
@Profile("prod")
public StorageService s3StorageService(S3Client s3Client) {
return new S3StorageService(s3Client);
}
}Bind external configuration to strongly-typed POJOs. Prefer this over scattered @Value annotations.
@ConfigurationProperties(prefix = "app.mail")
public record MailProperties(
String host,
int port,
String fromAddress,
Duration timeout,
RetryProperties retry
) {
public record RetryProperties(int maxAttempts, Duration delay) {}
}app:
mail:
host: smtp.example.com
port: 587
from-address: [email protected]
timeout: 5s
retry:
max-attempts: 3
delay: 2sEnable it:
@SpringBootApplication
@EnableConfigurationProperties(MailProperties.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}Expose health checks, metrics, and application info for monitoring systems.
# application.yml
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: when-authorized
health:
db:
enabled: true
redis:
enabled: trueCustom health indicator:
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {
private final PaymentGateway gateway;
public PaymentGatewayHealthIndicator(PaymentGateway gateway) { this.gateway = gateway; }
@Override
public Health health() {
try {
return gateway.ping()
? Health.up().withDetail("gateway", "reachable").build()
: Health.down().withDetail("gateway", "unreachable").build();
} catch (Exception e) { return Health.down(e).build(); }
}
}@ControllerAdvice with @ExceptionHandler for centralized exception handling.Stereotype annotations:
@Component -- Generic Spring-managed bean
@Service -- Business logic layer
@Repository -- Data access layer (exception translation)
@Controller -- Web layer (returns views)
@RestController -- Web layer (returns JSON)
Configuration:
@ConfigurationProperties -- Type-safe config binding
@Value("${key}") -- Single value injection
@Profile("dev") -- Environment-specific bean
Actuator endpoints:
/actuator/health -- Application health
/actuator/info -- Application info
/actuator/metrics -- Micrometer metrics
/actuator/prometheus -- Prometheus-format metrics~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.