# Como Integrar a API de CPF em uma Aplicação Quarkus

> Aprenda a integrar a API de CPF em uma aplicação Quarkus com REST Client, CDI, fault tolerance e compilação nativa com GraalVM.

**Publicado:** 01/10/2024
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/integrar-api-cpf-aplicacao-quarkus

---


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.

```java
// 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.

```java
// 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.

```java
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.

```java
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](https://quarkus.io/guides/building-native-image) detalha os requisitos de configuração para compilação nativa com GraalVM.

```dockerfile
# 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.

### Leia também

- [Diferença entre validação de CPF e consulta de CPF: quando usar cada uma](https://cpfhub.io/blog/diferenca-entre-validacao-de-cpf-e-consulta-de-cpf-quando-usar-cada-uma)
- [API de CPF grátis para desenvolvedores: como começar em 5 minutos](https://cpfhub.io/blog/api-cpf-gratis-desenvolvedores-comecar-5-minutos)
- [Onboarding digital em fintechs: como validar CPF em menos de 30 segundos](https://cpfhub.io/blog/onboarding-digital-em-fintechs-como-validar-cpf-em-menos-de-30-segundos)
- [KYC no Brasil: quais setores são obrigados a validar CPF por lei](https://cpfhub.io/blog/kyc-no-brasil-quais-setores-sao-obrigados-a-validar-cpf-por-lei)

---

## 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](https://www.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.

