Pular para conteúdo

Etapa 08 — Modernização: Java 25 + Micronaut 5 e RFC 7807

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-08-11

Delta de modernização sobre a base Java 21 / Micronaut 4.7.6. Nenhum comportamento observável mudou (status HTTP dos contratos 409/404/503 intactos); o único ganho outward-facing é o corpo de erro do /api/** virar application/problem+json.

1. Contexto

O projeto estava uma major atrás (Micronaut 4.7.6, Java 21) e o corpo de erro da API saía no formato Hateoas default ({message, _links}). Esta etapa moderniza a stack e padroniza o contrato de erro, em passos verificados contra a suíte completa (incl. @Tag("docker") Testcontainers).

2. Stack: Java 25 + Gradle 9.5.1 + Micronaut 5.0.2

  • Toolchain JDK 25 (JavaLanguageVersion.of(25); GraalVM 25 via SDKMAN no WSL). O Gradle 9.5.1 roda em Java 25 — exigência do plugin io.micronaut.application 5.0.0. Dockerfile passa a eclipse-temurin:25; docs/app.json declara toolchain.java=25.
  • Micronaut 4.7.6 → 5.0.2. Breaking changes do salto e como foram resolvidos (decisão 0016):
  • micronaut-jackson-databind (reflexivo, removido do BOM do MN5) → micronaut-serde-jackson (serde build-time, Jackson 3 tools.jackson.*). Exigiu @Serdeable nos DTOs serializados e migração de CoolifyClient + ConformidadeTest para Jackson 3.
  • ViewModelProcessor virou 2-arg (GlobalViewModel).
  • ConnectionOperations ganhou managesConnection.
  • Testcontainers precisa de versão explícita (o BOM parou de propagar).
  • AWS SDK ≥2.30 liga flexible checksums que o Garage rejeita → WHEN_REQUIRED no S3ClientFactory (etapa 04).

Nota: o artefato de baseline que a §6 da constituição nomeia é o docs/app.json (não existe um matriz-baseline.json concreto).

3. Contrato de erro da API — RFC 7807

Todo erro do /api/** passa a sair como application/problem+json, portado do bi-transporte (decisão 0015):

flowchart LR
    erro["Exceção no /api/**"] --> proc["xadm-comum-web<br/>UnifiedErrorResponseProcessor<br/>@Replaces Hateoas default"]
    authx["Falha de auth"] --> ah["security/<br/>AuthExceptionHandler"]
    proc --> pd["xadm-comum-web<br/>ProblemDetail<br/>@Serdeable"]
    ah --> pd
    pd --> body["application/problem+json"]
  • O processor @Replaces o Hateoas + o ProblemDetail (@Serdeable) vêm da lib br.com.xadm:xadm-comum-web (spec 009 / ADR 0019; antes cópias locais em exception/+dto/); security/AuthExceptionHandler é local e importa o ProblemDetail da lib.
  • Status HTTP preservados: os contratos 409/404/503 do cliente da API seguem idênticos — só o corpo mudou de {message, _links} para problem+json.
  • Teste de contrato: api/RfcProblemDetailTest.

Outward-facing: avisar consumidores da API que o corpo de erro mudou de {message, _links} para application/problem+json (os status não mudaram).

4. Package layout — mantido de propósito

api//service//repository/ (package-by-layer, em inglês) não foi migrado para feature-slices: é alinhamento cross-project deliberado com o bi-transporte (~42 classes rastreadas para extração para bi-commons; quatro fatias já saíram — auth (xadm-seguranca, decisão 0018), infra web (xadm-comum-web), object storage (xadm-comum-storage) e utilitários (xadm-comum-util)); renomear divergiria os dois sem ganho funcional. O ArchitectureTest (ArchUnit) já trava o pior (controller não fala com repository direto). Decisão consciente de manter (REGRA Nº 3 — declarada, não silenciosa).

5. Decisões

Nº Decisão
0015 Contrato de erro da API em RFC 7807
0016 Bump major Java 25 + Micronaut 5

6. Riscos

  • Mudanças de CI/Docker para Java 25 só se confirmam num run real de CI — validar no primeiro PR antes do merge em master.
  • Consumidores da API parseando o formato Hateoas antigo quebram no problem+json — comunicar a troca de contrato de corpo.
  • Jackson 3 (tools.jackson.*) coexistindo com Jackson 2 no uber-jar → resolvido removendo as classes duplicadas; conferir no shadowJar.