Quarkus para desenvolvedores Spring: Java nativo com startup em milissegundos
1. Por que Quarkus? O contexto para desenvolvedores Spring
1.1. O problema da latência em microsserviços com Spring Boot tradicional
Desenvolvedores Spring conhecem bem o custo do ecossistema: uma aplicação Spring Boot típica consome 200-400 MB de RAM e leva de 5 a 15 segundos para iniciar. Em ambientes serverless ou com containers efêmeros (Kubernetes com escala automática), esse overhead se torna um gargalo real. Cada vez que um pod é criado, a JVM precisa carregar classes, processar annotations e inicializar o contexto — um luxo que sistemas modernos não podem pagar.
1.2. Quarkus como alternativa: foco em startup rápida e baixo consumo de memória
Quarkus foi projetado para resolver exatamente esse problema. Com compilação Ahead-of-Time (AOT) e integração nativa com GraalVM, uma aplicação Quarkus pode iniciar em 10-50 milissegundos e consumir 10-50 MB de RAM no modo nativo. Para quem vem do Spring, a curva de aprendizado é curta: a sintaxe é familiar, o ecossistema é maduro e a produtividade é comparável.
1.3. Compatibilidade com o ecossistema Java e familiaridade para quem vem do Spring
Quarkus não reinventa a roda. Ele utiliza padrões Jakarta EE (CDI, JAX-RS, Bean Validation) e oferece extensões que mapeiam diretamente os starters do Spring. Se você conhece Spring Boot, consegue escrever um microsserviço Quarkus produtivo em menos de um dia.
2. Arquitetura e conceitos fundamentais do Quarkus
2.1. Compilação Ahead-of-Time (AOT) vs Just-in-Time (JIT): o segredo da inicialização em milissegundos
No Spring Boot tradicional, a JVM interpreta bytecode e otimiza em tempo de execução (JIT). No Quarkus, a compilação AOT transforma o bytecode em binário nativo durante o build. Isso elimina o tempo de warm-up e reduz drasticamente a pegada de memória.
# Modo JVM tradicional (Spring Boot):
# 1. JVM inicia → 2. Carrega classes → 3. Interpreta bytecode → 4. JIT otimiza
# Tempo total: 5-15 segundos
# Modo nativo (Quarkus + GraalVM):
# 1. Binário nivo executa diretamente → 2. Sem interpretação, sem JIT
# Tempo total: 10-50 milissegundos
2.2. Extensões Quarkus: substituindo starters do Spring por dependências modulares
Assim como o Spring Boot tem starters (spring-boot-starter-web), o Quarkus tem extensões. A diferença é que elas são ativadas apenas no build, reduzindo o classpath em runtime.
<!-- Spring Boot: spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Quarkus: resteasy-reactive -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive</artifactId>
</dependency>
2.3. Modo dev e live reload: produtividade comparada ao Spring Boot DevTools
Quarkus oferece quarkus:dev (Maven) ou quarkusDev (Gradle) que faz live reload automático — sem necessidade de reiniciar a JVM. É mais rápido que o Spring Boot DevTools porque usa classloading otimizado.
# Terminal 1: Iniciar modo dev
./mvnw quarkus:dev
# Terminal 2: Alterar código → reload em < 1 segundo
# Acessar http://localhost:8080/hello
3. Mapeando o Spring para o Quarkus: injeção de dependência e configuração
3.1. CDI (Contexts and Dependency Injection) vs Spring IoC: semelhanças e diferenças práticas
A injeção de dependência no Quarkus usa CDI (Jakarta Contexts and Dependency Injection). As anotações são quase idênticas:
// Spring
@Service
public class MeuServico {
@Autowired
private Repositorio repositorio;
}
// Quarkus (CDI)
@ApplicationScoped
public class MeuServico {
@Inject
Repositorio repositorio;
}
3.2. Configuração com application.properties e application.yml: reaproveitando conhecimento
Quarkus usa o mesmo formato de configuração do Spring Boot. Você pode copiar seu application.properties e ajustar apenas os prefixos:
# Spring Boot
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.jpa.hibernate.ddl-auto=update
# Quarkus
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/mydb
quarkus.hibernate-orm.database.generation=update
3.3. Profiles e ambiente: como gerenciar configurações por estágio (dev, test, prod)
O sistema de profiles do Quarkus é idêntico ao do Spring:
# application.properties (padrão)
quarkus.http.port=8080
# application-dev.properties
quarkus.http.port=8081
quarkus.log.level=DEBUG
# application-prod.properties
quarkus.http.port=80
quarkus.log.level=WARN
Ative com -Dquarkus.profile=dev ou variável de ambiente QUARKUS_PROFILE=prod.
4. Construindo uma API REST: do Spring MVC ao JAX-RS
4.1. Anotações REST: @Path e @GET (JAX-RS) vs @RequestMapping e @GetMapping (Spring)
A transição é direta. O Quarkus usa JAX-RS (Jakarta RESTful Web Services), que é o padrão Java EE:
// Spring MVC
@RestController
@RequestMapping("/api")
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring!";
}
}
// JAX-RS (Quarkus)
@Path("/api")
public class HelloResource {
@GET
@Path("/hello")
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello, Quarkus!";
}
}
4.2. Tratamento de exceções e respostas HTTP: ExceptionMapper vs @ControllerAdvice
No Spring, usamos @ControllerAdvice com @ExceptionHandler. No Quarkus, implementamos ExceptionMapper<RuntimeException>:
// Spring
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<String> handleNotFound(ResourceNotFoundException ex) {
return ResponseEntity.status(404).body(ex.getMessage());
}
}
// Quarkus
@Provider
public class NotFoundExceptionMapper implements ExceptionMapper<ResourceNotFoundException> {
@Override
public Response toResponse(ResourceNotFoundException exception) {
return Response.status(404).entity(exception.getMessage()).build();
}
}
4.3. Validação de entrada com Bean Validation: compatibilidade total com Jakarta Validation
A validação é idêntica — ambos usam Jakarta Bean Validation:
// Válido tanto no Spring quanto no Quarkus
public class UsuarioDTO {
@NotNull
@Size(min = 3, max = 50)
private String nome;
@Email
private String email;
}
5. Persistência de dados: Hibernate Panache vs Spring Data JPA
5.1. Panache Repository: menos boilerplate que Spring Data JPA
Panache oferece uma abordagem mais enxuta, com métodos estáticos e padrão Active Record:
// Spring Data JPA
public interface UsuarioRepository extends JpaRepository<Usuario, Long> {
List<Usuario> findByNome(String nome);
}
// Quarkus Panache (Active Record)
public class Usuario extends PanacheEntity {
public String nome;
public String email;
public static List<Usuario> findByNome(String nome) {
return find("nome", nome).list();
}
}
// Uso no serviço
List<Usuario> usuarios = Usuario.findByNome("João");
5.2. Configuração de datasources e pooling: Quarkus com Agroal vs HikariCP
Quarkus usa Agroal como pool de conexões padrão, mas é totalmente compatível com HikariCP:
# Configuração de datasource no Quarkus
quarkus.datasource.db-kind=postgresql
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/mydb
quarkus.datasource.jdbc.max-size=20
quarkus.datasource.jdbc.min-size=5
# Pool HikariCP (opcional)
quarkus.datasource.jdbc.pool-type=HikariCP
5.3. Migrações com Flyway ou Liquibase: integração nativa e scripts SQL reaproveitáveis
Ambas as ferramentas são suportadas nativamente. Basta adicionar a extensão e criar os scripts:
<!-- Adicionar extensão Flyway -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-flyway</artifactId>
</dependency>
<!-- Script SQL: src/main/resources/db/migration/V1__create_usuario.sql -->
CREATE TABLE usuario (
id BIGSERIAL PRIMARY KEY,
nome VARCHAR(100) NOT NULL,
email VARCHAR(150) UNIQUE NOT NULL
);
6. Geração de imagem nativa com GraalVM
6.1. Pré-requisitos e instalação do GraalVM
Instale o GraalVM 22+ e configure a variável GRAALVM_HOME:
# Instalar via SDKMAN (recomendado)
sdk install java 22.3.0.r17-grl
# Verificar instalação
java -version
# Saída esperada: OpenJDK 64-Bit Server VM (build 22.3.0, mixed mode, sharing)
6.2. Compilando o primeiro binário nativo: comandos Maven/Gradle e resultados de desempenho
# Compilar imagem nativa (Maven)
./mvnw package -Pnative
# Executar binário nativo
./target/quarkus-app-runner
# Resultado esperado:
# -- Quarkus started in 0.015s (startup em 15 milissegundos!)
# -- Listening on: http://0.0.0.0:8080
6.3. Limitações e cuidados: reflexão, recursos dinâmicos e bibliotecas incompatíveis
Algumas bibliotecas usam reflexão em tempo de execução, o que não funciona em modo nativo. Soluções:
# Registrar classes para reflexão no application.properties
quarkus.native.additional-build-args=\
--initialize-at-build-time=com.minha.biblioteca,\
-H:ReflectionConfigurationFiles=reflection-config.json
# Evitar: Class.forName(), Proxy dinâmico, serialização Java padrão
7. Observabilidade e produção: métricas, logs e health checks
7.1. Micrometer no Quarkus: métricas compatíveis com Prometheus, similar ao Spring Actuator
<!-- Adicionar extensão Micrometer -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-micrometer-registry-prometheus</artifactId>
</dependency>
# Configuração
quarkus.micrometer.export.prometheus.enabled=true
quarkus.micrometer.binder.http-server.enabled=true
# Endpoint: http://localhost:8080/q/metrics
7.2. Logging estruturado com Logback ou JBoss Logging: adaptando configurações existentes
Quarkus usa JBoss Logging por padrão, mas aceita Logback:
# Configuração básica de logging
quarkus.log.level=INFO
quarkus.log.console.enable=true
quarkus.log.console.format=%d{HH:mm:ss} %-5p [%c{2.}] (%t) %s%e%n
# Para JSON estruturado (compatível com ELK)
quarkus.log.console.json=true
7.3. Health checks e readiness/liveness probes: endpoints prontos para Kubernetes
<!-- Adicionar extensão de health -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
# Endpoints automáticos:
# /q/health/live → Liveness probe
# /q/health/ready → Readiness probe
# /q/health → Health check completo
8. Quando migrar (e quando não migrar) do Spring para o Quarkus
8.1. Cenários ideais: serverless, containers efêmeros e ambientes com restrição de memória
- Serverless (AWS Lambda, Azure Functions): startup em milissegundos é essencial
- Kubernetes com escala automática: pods que iniciam e morrem rapidamente
- Edge computing: dispositivos com pouca RAM (Raspberry Pi, gateways)
- Microsserviços de alta rotatividade: dezenas de instâncias com tráfego variável
8.2. Cenários desfavoráveis: aplicações monolíticas complexas com muitas bibliotecas proprietárias
- Aplicações monolíticas com 50+ módulos: o build nativo pode falhar por reflexão
- Bibliotecas proprietárias que usam serialização Java: incompatível com GraalVM
- Equipes sem experiência em GraalVM: a curva de debugging em modo nativo é mais íngreme
- Projetos com dependências de runtime dinâmicas: Class.forName() ou service loaders
8.3. Estratégia de migração gradual: coexistência de módulos Spring e Quarkus no mesmo projeto
É possível manter ambos os frameworks no mesmo repositório, usando módulos Maven:
meu-projeto/
├── modulo-spring/ # Microsserviços legados em Spring Boot
│ └── pom.xml
├── modulo-quarkus/ # Novos microsserviços em Quarkus
│ └── pom.xml
└── modulo-comum/ # Classes compartilhadas (DTOs, entidades)
└── pom.xml
A comunicação entre módulos pode ser feita via REST, mensageria (Kafka/RabbitMQ) ou banco de dados compartilhado. A migração é incremental: comece pelos endpoints de baixa complexidade e alto benefício (serverless, APIs de consulta).
Referências
- Documentação oficial do Quarkus para desenvolvedores Spring — Guia oficial comparando injeção de dependência Spring vs Quarkus, com exemplos práticos de migração.
- Quarkus: Supersonic Subatomic Java — Site oficial com documentação completa, tutoriais e referência de extensões para o ecossistema Quarkus.
- GraalVM Native Image Documentation — Documentação oficial do GraalVM sobre compilação nativa, incluindo configuração de reflexão e recursos avançados.
- Spring Boot vs Quarkus: Performance Comparison — Artigo técnico do InfoQ comparando métricas de desempenho entre Spring Boot e Quarkus em cenários reais.
- Migrating from Spring Boot to Quarkus: A Practical Guide — Tutorial passo a passo no Baeldung cobrindo migração de APIs REST, persistência e configuração.
- Quarkus Hibernate Panache Guide — Guia oficial sobre Hibernate Panache, com exemplos de repositórios ativos e reativos.
- Quarkus Micrometer Metrics — Documentação oficial sobre métricas com Micrometer e Prometheus, similar ao Spring Actuator.