Pular para conteúdo

Java — app simples / CLI / worker

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-09-12

Aplica-se a: perfil app e lib, stack java. Build, checkstyle, logging e exit codes valem para todo Java da casa; o servidor soma Java/Micronaut.

O arquétipo Java puro (sem framework) — uma ferramenta, um job, um cliente de API de linha de comando.

Organização do código

Package-by-feature (Stack): cada funcionalidade é um pacote de topo que carrega suas camadas; o compartilhado em comum/core. Pipeline genérico no kernel + uma estratégia (interface) para o que varia — feature-first ingênuo vira "core monolítico + features anêmicas". Pacote base: br.com.xadm.<cliente>.<app>.

Build — Gradle (Kotlin DSL)

  • Gradle invólucro versionado (./gradlew, nunca Maven); pin de dependências; gate único ./gradlew check (compila + checkstyle + testes). No agente, ./gradlew test --quiet --console=plain (higiene de saída).
  • Checkstyle: o checkstyle.xml e o suppressions.xml vêm do kit, em config/checkstyle/, e a versão do Checkstyle é exata e a mesma em toda a frota:
plugins { checkstyle }
checkstyle { toolVersion = "10.26.1"; configDirectory.set(file("config/checkstyle")) }
  • Nome do jar: CLI publica <app>-<versão>.jar (fat jar quando distribuído); app.jar é só o do fallback JVM de servidor. A versão vem do project.version, nunca de literal (Versionamento).

Logging — Logback por arquétipo

  • CLI/worker cujo stdout é consumido: stdout = dados e contrato; stderr + arquivo = logs. Um logback.xml que loga no console corrompe a saída.
  • Servidor: loga em stdout, que o container captura; o contrato é HTTP.

Cada arquétipo tem o seu logback.xml; não se copia de um para o outro.

Tipos

BigDecimal para valor monetário ou fiscal — nunca double/float.

CLI (picocli)

  • picocli para parsing; o --version lê de um IVersionProvider que carrega o project.version, nunca @Command(version = "…") literal.
  • Exceção → exit code, contrato canônico da casa: 0 ok · 1 parcial · 2 config/auth · 3 externo · 4 ocupado (lock de execução concorrente; nada feito, seguro repetir). O app não inventa código — desfecho novo entra pela linha de feedback — e documenta o comportamento de saída no runbook de operacao/.
  • Sem flags valida a config e imprime o help.
  • Log de observabilidade por requisição (envio → resposta → processado); segredo nunca logado.

Testes

  • JUnit 5. Cliente de API REST: unit (normalização, mapeamento) + integração com WireMock sobre fixtures anonimizadas. Fixtures e Testcontainers seguem Java/Micronaut; gate e níveis em CI, gates e testes.
  • Não desabilite teste por OS (@DisabledOnOs(OS.WINDOWS)): ele some do pré-flight da release, que roda no Windows, e só falha na CI Linux, depois da tag. Prefira teste cross-OS; se for Linux-only, rode o gate num container Linux antes de taggar (gate cego).