Para integrar a API de CPF da CPFHub.io em uma aplicação Quarkus, utilize o REST Client declarativo com a interface anotada @RegisterRestClient, adicione fault tolerance via MicroProfile e compile nativamente com GraalVM para startup em milissegundos. O processo leva menos de uma hora e entrega um microsserviço de validação de CPF pronto para ambientes containerizados e serverless.
Introdução
O Quarkus é um framework Java otimizado para containers e GraalVM, oferecendo tempo de startup em milissegundos e consumo mínimo de memória. Para microsserviços de validação de CPF, essas características são especialmente valiosas: o serviço inicia instantaneamente, escala rapidamente e consome poucos recursos.
Configuração do projeto
Configure as dependências e propriedades do Quarkus.
// pom.xml (extensões Quarkus relevantes)
// quarkus-resteasy-reactive-jackson
// quarkus-rest-client-reactive-jackson
// quarkus-smallrye-fault-tolerance
// quarkus-smallrye-health
// quarkus-smallrye-metrics
// quarkus-container-image-docker
// application.properties
// quarkus.rest-client.cpfhub-api.url=https://api.cpfhub.io
// quarkus.rest-client.cpfhub-api.scope=jakarta.inject.Singleton
// cpfhub.api-key=${CPFHUB_API_KEY}
// quarkus.http.port=8080
| Extensão | Propósito |
|---|---|
| resteasy-reactive-jackson | Endpoints REST reativos com JSON |
| rest-client-reactive-jackson | Cliente REST declarativo reativo |
| smallrye-fault-tolerance | Circuit breaker, retry, timeout |
| smallrye-health | Health checks (liveness, readiness) |
| smallrye-metrics | Métricas MicroProfile |
| container-image-docker | Build de imagem Docker |
REST client declarativo
O Quarkus permite definir clientes REST com interfaces anotadas, eliminando código boilerplate.
// CpfHubApiClient.java
package com.cpfservice.client;
import io.quarkus.rest.client.reactive.ClientHeaderParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
@Path("/cpf")
@RegisterRestClient(configKey = "cpfhub-api")
@ClientHeaderParam(
name = "x-api-key",
value = "${cpfhub.api-key}"
)
public interface CpfHubApiClient {
@GET
@Path("/{cpf}")
CpfApiResponse consultar(@PathParam("cpf") String cpf);
}
// CpfApiResponse.java
package com.cpfservice.client;
import com.fasterxml.jackson.annotation.JsonProperty;
public class CpfApiResponse {
private boolean success;
private CpfData data;
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public CpfData getData() { return data; }
public void setData(CpfData data) { this.data = data; }
public static class CpfData {
private String cpf;
private String name;
private String nameUpper;
private String gender;
private String birthDate;
private int day;
private int month;
private int year;
// Getters e setters
public String getCpf() { return cpf; }
public void setCpf(String cpf) { this.cpf = cpf; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getNameUpper() { return nameUpper; }
public void setNameUpper(String n) { this.nameUpper = n; }
public String getGender() { return gender; }
public void setGender(String gender) { this.gender = gender; }
public String getBirthDate() { return birthDate; }
public void setBirthDate(String d) { this.birthDate = d; }
public int getDay() { return day; }
public void setDay(int day) { this.day = day; }
public int getMonth() { return month; }
public void setMonth(int month) { this.month = month; }
public int getYear() { return year; }
public void setYear(int year) { this.year = year; }
}
}
Service com fault tolerance
O service utiliza anotações do MicroProfile Fault Tolerance para resiliência.
package com.cpfservice.service;
import com.cpfservice.client.CpfApiResponse;
import com.cpfservice.client.CpfHubApiClient;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.faulttolerance.Retry;
import org.eclipse.microprofile.faulttolerance.Timeout;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import java.time.temporal.ChronoUnit;
import java.util.Map;
@ApplicationScoped
public class CpfValidationService {
@Inject
@RestClient
CpfHubApiClient apiClient;
@Timeout(value = 10, unit = ChronoUnit.SECONDS)
@Retry(maxRetries = 3, delay = 1, delayUnit = ChronoUnit.SECONDS)
@CircuitBreaker(
requestVolumeThreshold = 10,
failureRatio = 0.5,
delay = 30,
delayUnit = ChronoUnit.SECONDS
)
@Fallback(fallbackMethod = "consultarFallback")
public Map<String, Object> consultar(String cpf) {
String cpfLimpo = cpf.replaceAll("\\D", "");
if (!validarAlgoritmo(cpfLimpo)) {
return Map.of(
"sucesso", false,
"fonte", "algoritmo",
"erro", "CPF invalido"
);
}
CpfApiResponse response = apiClient.consultar(cpfLimpo);
if (response.isSuccess()) {
CpfApiResponse.CpfData data = response.getData();
return Map.of(
"sucesso", true,
"fonte", "api",
"dados", Map.of(
"cpf", data.getCpf(),
"name", data.getName(),
"nameUpper", data.getNameUpper(),
"gender", data.getGender(),
"birthDate", data.getBirthDate(),
"day", data.getDay(),
"month", data.getMonth(),
"year", data.getYear()
)
);
}
return Map.of(
"sucesso", false,
"fonte", "api",
"erro", "CPF nao encontrado"
);
}
public Map<String, Object> consultarFallback(String cpf) {
String cpfLimpo = cpf.replaceAll("\\D", "");
boolean valido = validarAlgoritmo(cpfLimpo);
return Map.of(
"sucesso", valido,
"fonte", "fallback",
"mensagem", "API indisponivel. Validacao algoritmica: "
+ (valido ? "valido" : "invalido")
);
}
private boolean validarAlgoritmo(String cpf) {
if (cpf.length() != 11) return false;
if (cpf.chars().distinct().count() == 1) return false;
int soma = 0;
for (int i = 0; i < 9; i++) {
soma += Character.getNumericValue(cpf.charAt(i))
* (10 - i);
}
int resto = (soma * 10) % 11;
if (resto == 10) resto = 0;
if (resto != Character.getNumericValue(cpf.charAt(9)))
return false;
soma = 0;
for (int i = 0; i < 10; i++) {
soma += Character.getNumericValue(cpf.charAt(i))
* (11 - i);
}
resto = (soma * 10) % 11;
if (resto == 10) resto = 0;
return resto == Character.getNumericValue(cpf.charAt(10));
}
}
| Anotação | Configuração | Comportamento |
|---|---|---|
| @Timeout | 10 segundos | Cancela requisição lenta |
| @Retry | 3 tentativas, 1s delay | Retenta em caso de falha |
| @CircuitBreaker | 50% falha em 10 req, 30s delay | Abre circuito |
| @Fallback | consultarFallback | Método alternativo quando tudo falha |
Endpoint REST reativo
O controller usa RESTEasy Reactive para endpoints non-blocking.
package com.cpfservice.resource;
import com.cpfservice.service.CpfValidationService;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.List;
import java.util.Map;
@Path("/api/v1/cpf")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class CpfResource {
@Inject
CpfValidationService service;
@GET
@Path("/{cpf}")
public Response validar(@PathParam("cpf") String cpf) {
Map<String, Object> resultado = service.consultar(cpf);
boolean sucesso = (boolean) resultado.get("sucesso");
int status = sucesso ? 200 : 404;
return Response.status(status).entity(resultado).build();
}
@POST
@Path("/lote")
public Response validarLote(List<String> cpfs) {
List<Map<String, Object>> resultados = cpfs.stream()
.map(service::consultar)
.toList();
long validos = resultados.stream()
.filter(r -> (boolean) r.get("sucesso"))
.count();
return Response.ok(Map.of(
"total", cpfs.size(),
"validos", validos,
"invalidos", cpfs.size() - validos,
"resultados", resultados
)).build();
}
}
Compilação nativa com GraalVM
O Quarkus permite compilar a aplicação em binário nativo para startup instantâneo. A documentação oficial do Quarkus detalha os requisitos de configuração para compilação nativa com GraalVM.
# Dockerfile para imagem nativa
FROM quay.io/quarkus/ubi-quarkus-mandrel-builder-image:jdk-21 AS builder
WORKDIR /app
COPY . .
RUN ./mvnw package -Dnative -DskipTests
FROM quay.io/quarkus/quarkus-micro-image:2.0
WORKDIR /app
COPY --from=builder /app/target/*-runner /app/application
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
| Métrica | JVM Mode | Native Mode |
|---|---|---|
| Tempo de startup | ~1.5s | ~0.02s |
| Memória RSS | ~150MB | ~30MB |
| Tamanho da imagem | ~200MB | ~80MB |
| Throughput | Alto | Alto |
| Tempo de build | ~30s | ~5min |
JVM mode -- desenvolvimento e ambientes onde o tempo de build é prioridade.
Native mode -- produção com serverless, scaling rápido e economia de recursos.
Perguntas frequentes
O Quarkus REST Client declarativo suporta autenticação via header customizado?
Sim. A anotação @ClientHeaderParam permite definir headers fixos ou dinâmicos diretamente na interface do cliente. Para a API da CPFHub.io, basta declarar @ClientHeaderParam(name = "x-api-key", value = "${cpfhub.api-key}") na interface, apontando para a propriedade configurada no application.properties. O valor é injetado em tempo de compilação, sem expor a chave no código-fonte.
Como o MicroProfile Fault Tolerance lida com falhas temporárias na API de CPF?
A combinação de @Retry (3 tentativas com 1s de intervalo) e @CircuitBreaker (abre após 50% de falhas em 10 requisições) protege a aplicação contra falhas transitórias e sobrecarga. Quando o circuit breaker está aberto, o método consultarFallback assume, retornando uma validação algorítmica local para garantir disponibilidade mesmo sem acesso à API.
A compilação nativa com GraalVM é compatível com o REST Client reativo do Quarkus?
Sim, com configuração adequada. O Quarkus gera automaticamente os metadados de reflexão necessários para o GraalVM ao usar as extensões oficiais. Para classes de resposta personalizadas como CpfApiResponse, anote-as com @RegisterForReflection caso o build nativo apresente erros de desserialização em tempo de execução.
Qual é a latência esperada para consultas de CPF em modo nativo?
A latência da consulta depende principalmente do tempo de resposta da API da CPFHub.io, que é de aproximadamente 900ms. O overhead do Quarkus em modo nativo é mínimo (< 1ms por requisição), então o tempo total de uma consulta completa fica em torno de 900ms a 1.1s dependendo da rede. O timeout recomendado para o REST Client é de 10 segundos.
Conclusão
Integrar a API de CPF em uma aplicação Quarkus oferece o melhor da plataforma Java com as vantagens de frameworks cloud-native. O REST Client declarativo elimina boilerplate, o MicroProfile Fault Tolerance adiciona resiliência com anotações simples, e a compilação nativa com GraalVM entrega startup em milissegundos e consumo mínimo de memória. Essa combinação torna o Quarkus uma escolha excelente para microsserviços de validação de CPF em ambientes containerizados e serverless.
Cadastre-se em cpfhub.io — 50 consultas mensais gratuitas, sem cartão de crédito — e integre a validação de CPF na sua aplicação Quarkus hoje mesmo.
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



