SuperAPI AI Directory

spring-boot-4

Coding & development

View repository

Updated 10-15 23:33

About this skill

Spring Boot 4.0 Patterns

Quick Reference

Jakarta EE Migration

Antes (javax) Ahora (jakarta)
javax.persistence.* jakarta.persistence.*
javax.validation.* jakarta.validation.*
javax.servlet.* jakarta.servlet.*
javax.annotation.* jakarta.annotation.*

Security Configuration

// ✅ Spring Security 6.4+
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http
        .csrf(csrf -> csrf.disable())
        .sessionManagement(session -> session
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/api/public/**").permitAll()
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated())
        .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
        .build();
}

Virtual Threads

# application.yml
spring:
  threads:
    virtual:
      enabled: true

Records as DTOs

public record UserDTO(
    @NotNull UUID id,
    @NotBlank String name,
    @Email String email
) {}

Problem Details

@ExceptionHandler(EntityNotFoundException.class)
public ProblemDetail handleNotFound(EntityNotFoundException ex) {
    ProblemDetail problem = ProblemDetail.forStatusAndDetail(
        HttpStatus.NOT_FOUND, ex.getMessage());
    problem.setTitle("Entity Not Found");
    return problem;
}

HTTP Interface (Declarative Client)

public interface UserClient {
    @GetExchange("/users/{id}")
    User getUser(@PathVariable UUID id);
}

@Bean
public UserClient userClient(RestClient.Builder builder) {
    return HttpServiceProxyFactory
        .builderFor(RestClientAdapter.create(builder.baseUrl("http://api").build()))
        .build()
        .createClient(UserClient.class);
}

@ConfigurationProperties with Records

@ConfigurationProperties(prefix = "app")
public record AppProperties(
    String name,
    Duration timeout,
    CacheProperties cache
) {
    public record CacheProperties(boolean enabled, Duration ttl) {}
}

Observability

@Observed(name = "user.service", contextualName = "findUser")
public User findById(UUID id) {
    return repository.findById(id).orElseThrow();
}

TestContainers with @ServiceConnection

@SpringBootTest
@Testcontainers
class UserRepositoryIT {

    @Container
    @ServiceConnection
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16");

    // Auto-configures datasource from container
}

Anti-Patterns

❌ WebSecurityConfigurerAdapter (deprecated)

// ❌ No usar
public class Config extends WebSecurityConfigurerAdapter { }

// ✅ Usar SecurityFilterChain bean

❌ antMatchers (removed)

// ❌ No existe
.antMatchers("/api/**")

// ✅ Usar
.requestMatchers("/api/**")

❌ javax imports

// ❌ Ya no funciona
import javax.persistence.Entity;

// ✅ Jakarta
import jakarta.persistence.Entity;

Related Skills

  • apigen-architecture: Arquitectura APiGen
  • testcontainers: Testing integration
  • gradle-multimodule: Build config