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/**virarapplication/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 pluginio.micronaut.application5.0.0.Dockerfilepassa aeclipse-temurin:25;docs/app.jsondeclaratoolchain.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 3tools.jackson.*). Exigiu@Serdeablenos DTOs serializados e migração deCoolifyClient+ConformidadeTestpara Jackson 3.ViewModelProcessorvirou 2-arg (GlobalViewModel).ConnectionOperationsganhoumanagesConnection.- Testcontainers precisa de versão explícita (o BOM parou de propagar).
- AWS SDK ≥2.30 liga flexible checksums que o Garage rejeita →
WHEN_REQUIREDnoS3ClientFactory(etapa 04).
Nota: o artefato de baseline que a §6 da constituição nomeia é o
docs/app.json(não existe ummatriz-baseline.jsonconcreto).
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
@Replaceso Hateoas + oProblemDetail(@Serdeable) vêm da libbr.com.xadm:xadm-comum-web(spec 009 / ADR 0019; antes cópias locais emexception/+dto/);security/AuthExceptionHandleré local e importa oProblemDetailda 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}paraapplication/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.