https://github.com/eneas-almeida/people
📜 Serviço de gerenciamento de usuários baseado em gRPC que consome dados de APIs públicas (DummyJSON ou JSONPlaceholder). O projeto foi desenvolvido utilizando Spring Boot e segue princípios de Clean Architecture com suporte a múltiplas fontes de dados.
https://github.com/eneas-almeida/people
clean-architecture grpc java microservice springboot strategy-pattern webflux
Last synced: 27 days ago
JSON representation
📜 Serviço de gerenciamento de usuários baseado em gRPC que consome dados de APIs públicas (DummyJSON ou JSONPlaceholder). O projeto foi desenvolvido utilizando Spring Boot e segue princípios de Clean Architecture com suporte a múltiplas fontes de dados.
- Host: GitHub
- URL: https://github.com/eneas-almeida/people
- Owner: eneas-almeida
- Created: 2025-12-16T13:10:23.000Z (6 months ago)
- Default Branch: master
- Last Pushed: 2025-12-26T18:41:46.000Z (6 months ago)
- Last Synced: 2025-12-28T02:44:25.092Z (6 months ago)
- Topics: clean-architecture, grpc, java, microservice, springboot, strategy-pattern, webflux
- Language: Java
- Homepage:
- Size: 120 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# People Service
Serviço de gerenciamento de usuários baseado em gRPC que consome dados de APIs públicas (DummyJSON ou JSONPlaceholder). O projeto foi desenvolvido utilizando Spring Boot e segue princípios de Clean Architecture com suporte a múltiplas fontes de dados.
## 📋 Índice
- [Visão Geral](#-visão-geral)
- [Arquitetura](#-arquitetura)
- [Tecnologias](#-tecnologias)
- [Estrutura do Projeto](#-estrutura-do-projeto)
- [Pré-requisitos](#-pré-requisitos)
- [Configuração](#-configuração)
- [Como Executar](#-como-executar)
- [API gRPC](#-api-grpc)
- [APIs Externas Suportadas](#-apis-externas-suportadas)
- [Detalhes Técnicos](#-detalhes-técnicos)
- [Build e Deploy](#-build-e-deploy)
## 🎯 Visão Geral
O **People Service** é um microserviço que expõe uma API gRPC para consulta de informações de usuários. O serviço atua como um intermediário entre clientes gRPC e APIs REST públicas (DummyJSON ou JSONPlaceholder), aplicando os conceitos de Clean Architecture e o padrão Strategy para permitir troca fácil entre diferentes fontes de dados.
### Funcionalidades Principais
- **Buscar pessoa por ID**: Retorna informações detalhadas de uma pessoa específica
- **Listar todas as pessoas**: Retorna uma lista com todas as pessoas disponíveis
- **Múltiplas fontes de dados**: Suporte a DummyJSON e JSONPlaceholder via padrão Strategy
- **Comunicação reativa**: Utiliza WebFlux para chamadas HTTP não-bloqueantes
- **Interface gRPC**: API de alto desempenho para comunicação entre serviços
- **Logging estruturado**: Sistema de logs com correlation IDs e contexto de requisição
- **Tratamento robusto de erros**: Hierarquia de exceções customizadas e retry com backoff
## 🏗 Arquitetura
O projeto segue os princípios da **Clean Architecture**, organizando o código em camadas bem definidas:
```
┌─────────────────────────────────────────┐
│ Entrypoint (gRPC Service) │
│ - PeopleServiceGrpcImpl │
└─────────────┬───────────────────────────┘
│
┌─────────────▼───────────────────────────┐
│ Application Layer │
│ - PeopleService (interface) │
│ - PeopleServiceImpl │
└─────────────┬───────────────────────────┘
│
┌─────────────▼───────────────────────────┐
│ Domain Layer │
│ - People (Entity) │
│ - PeopleClient (Interface) │
│ - PeopleRepository (Interface) │
│ - DataSource (Enum) │
└─────────────┬───────────────────────────┘
│
┌─────────────▼───────────────────────────┐
│ Infrastructure Layer │
│ Repository: │
│ - PeopleRepositoryImpl (Strategy) │
│ │
│ Clients: │
│ - DummyClientImpl │
│ - TypiCodeClientImpl │
│ │
│ Configs: │
│ - RepositoryConfig │
│ - DummyClientConfig │
│ - TypiCodeClientConfig │
└─────────────────────────────────────────┘
```
### Camadas
1. **Domain** (`org.people.domain`)
- Contém as entidades de negócio (`People`)
- Interfaces de cliente (`PeopleClient`) e repositório (`PeopleRepository`)
- Exceções de negócio (`PeopleException`, `PeopleNotFoundException`, etc.)
- Enums (`DataSource`)
- Livre de dependências externas
2. **Application** (`org.people.application`)
- Implementa a lógica de negócio da aplicação
- DTOs de aplicação (`PeopleResponse`)
- Services (`PeopleService`, `PeopleServiceImpl`)
- Orquestra as interações entre domain e infrastructure
3. **Infrastructure** (`org.people.infrastructure`)
- **Clients**: Implementações concretas dos clientes de API
- `dummy/`: Cliente para DummyJSON API
- `typicode/`: Cliente para JSONPlaceholder API
- **Repository**: Implementação do padrão Strategy (`PeopleRepositoryImpl`)
- **Entrypoints**: Pontos de entrada da aplicação (gRPC)
- **Config**: Configurações e beans do Spring
- **Exception**: Exceções de infraestrutura
- **Logging**: Sistema de logging estruturado
## 🚀 Tecnologias
### Core
- **Java 21**: Versão LTS mais recente com recursos modernos
- **Spring Boot 3.3.3**: Framework principal para desenvolvimento
- **Maven**: Gerenciamento de dependências e build
### Comunicação
- **gRPC 1.59.0**: Framework RPC de alto desempenho
- **Protocol Buffers 3.24.4**: Serialização de dados
- **Spring WebFlux**: Cliente HTTP reativo e não-bloqueante
- **Reactor gRPC 1.2.4**: gRPC Reativo
### Utilitários
- **Lombok**: Redução de boilerplate code
- **MapStruct 1.5.5**: Mapeamento automático entre objetos
- **Logstash Logback Encoder 7.4**: Logging estruturado em JSON
- **Datadog Trace API 1.30.1**: Observabilidade e tracing distribuído
### Programação Reativa
- **Project Reactor**: Implementação do Reactive Streams
- `Mono`: Para operações que retornam 0 ou 1 elemento
- `Flux`: Para operações que retornam 0 a N elementos
## 📁 Estrutura do Projeto
```
people/
├── src/
│ ├── main/
│ │ ├── java/org/people/
│ │ │ ├── PeopleApplication.java
│ │ │ │
│ │ │ ├── domain/
│ │ │ │ ├── client/
│ │ │ │ │ └── PeopleClient.java # Interface do cliente
│ │ │ │ ├── entity/
│ │ │ │ │ └── People.java # Entidade de domínio
│ │ │ │ ├── enums/
│ │ │ │ │ └── DataSource.java # Enum de fontes de dados
│ │ │ │ ├── exception/
│ │ │ │ │ ├── PeopleException.java
│ │ │ │ │ ├── BusinessRuleException.java
│ │ │ │ │ ├── ValidationException.java
│ │ │ │ │ └── PeopleNotFoundException.java
│ │ │ │ └── repository/
│ │ │ │ └── PeopleRepository.java # Interface do repositório
│ │ │ │
│ │ │ ├── application/
│ │ │ │ ├── dto/
│ │ │ │ │ └── PeopleResponse.java # DTO de resposta
│ │ │ │ └── service/
│ │ │ │ ├── PeopleService.java # Interface do serviço
│ │ │ │ └── PeopleServiceImpl.java # Implementação do serviço
│ │ │ │
│ │ │ └── infrastructure/
│ │ │ ├── client/
│ │ │ │ ├── dummy/
│ │ │ │ │ ├── DummyClientImpl.java
│ │ │ │ │ ├── DummyMapper.java
│ │ │ │ │ ├── DummyResponse.java
│ │ │ │ │ └── DummyListResponse.java
│ │ │ │ └── typicode/
│ │ │ │ ├── TypiCodeClientImpl.java
│ │ │ │ ├── TypiCodeMapper.java
│ │ │ │ └── TypiCodeResponse.java
│ │ │ │
│ │ │ ├── repository/
│ │ │ │ └── PeopleRepositoryImpl.java # Padrão Strategy
│ │ │ │
│ │ │ ├── config/
│ │ │ │ ├── client/
│ │ │ │ │ ├── DummyClientConfig.java
│ │ │ │ │ └── TypiCodeClientConfig.java
│ │ │ │ └── RepositoryConfig.java # Config do repository
│ │ │ │
│ │ │ ├── entrypoint/grpc/
│ │ │ │ └── PeopleServiceGrpcImpl.java
│ │ │ │
│ │ │ ├── exception/
│ │ │ │ ├── GlobalGrpcExceptionHandler.java
│ │ │ │ ├── ExternalServiceException.java
│ │ │ │ └── InternalServerException.java
│ │ │ │
│ │ │ └── logging/
│ │ │ ├── Logger.java
│ │ │ ├── LogContext.java
│ │ │ ├── RequestContext.java
│ │ │ └── GrpcLoggingInterceptor.java
│ │ │
│ │ ├── proto/
│ │ │ └── person.proto # Definição do serviço gRPC
│ │ │
│ │ └── resources/
│ │ └── application.yml # Configurações da aplicação
│ │
│ └── test/
│ └── java/org/people/
│ └── PeopleApplicationTests.java
│
├── target/ # Arquivos compilados
├── pom.xml # Configuração Maven
├── mvnw # Maven Wrapper (Unix)
└── mvnw.cmd # Maven Wrapper (Windows)
```
## 📋 Pré-requisitos
- **Java Development Kit (JDK) 21** ou superior
- **Maven 3.6+** (ou utilize o Maven Wrapper incluído no projeto)
- **Git** (para clonar o repositório)
- Conexão com a internet (para acessar as APIs externas)
### Verificar Instalações
```bash
# Verificar versão do Java
java -version
# Verificar versão do Maven
mvn -version
```
## ⚙ Configuração
### Arquivo application.yml
```yaml
spring:
application:
name: people
profiles:
active: ${SPRING_PROFILE:local}
grpc:
server:
port: 9090
client:
active-datasource: TYPICODE # Options: TYPICODE, DUMMY
typicode:
base-url: https://jsonplaceholder.typicode.com
dummy:
base-url: https://dummyjson.com
logging:
level:
root: INFO
org.people: DEBUG
io.grpc: INFO
net.devh: INFO
```
### Seleção de Fonte de Dados
A aplicação suporta duas APIs externas. Para alterar a fonte de dados, modifique a propriedade `client.active-datasource`:
```yaml
# Para usar DummyJSON
client:
active-datasource: DUMMY
# Para usar JSONPlaceholder
client:
active-datasource: TYPICODE
```
Ou defina via variável de ambiente:
```bash
export ACTIVE_DATASOURCE=DUMMY
```
## 🏃 Como Executar
### Usando Maven Wrapper (Recomendado)
#### Windows
```cmd
# Limpar e compilar o projeto
.\mvnw.cmd clean install
# Executar a aplicação
.\mvnw.cmd spring-boot:run
```
#### Unix/Linux/MacOS
```bash
# Limpar e compilar o projeto
./mvnw clean install
# Executar a aplicação
./mvnw spring-boot:run
```
### Usando Maven Local
```bash
# Limpar e compilar
mvn clean install
# Executar
mvn spring-boot:run
```
### Executando o JAR Gerado
```bash
# Gerar o JAR
mvn clean package
# Executar o JAR
java -jar target/people-0.0.1-SNAPSHOT.jar
```
### Verificar Execução
Após iniciar a aplicação, você verá logs indicando que o servidor gRPC está rodando:
```
gRPC Server started, listening on address: *, port: 9090
```
## 🔌 API gRPC
### Endpoints Disponíveis
#### 1. GetPeople
Busca uma pessoa específica por ID.
**Exemplo de Uso com grpcurl:**
```bash
grpcurl -plaintext -d '{"id": 1}' localhost:9090 grpcservice.PeopleService/GetPeople
```
**Resposta Esperada:**
```json
{
"id": 1,
"name": "Leanne Graham",
"email": "Sincere@april.biz"
}
```
#### 2. ListPeople
Lista todas as pessoas disponíveis.
**Exemplo de Uso com grpcurl:**
```bash
grpcurl -plaintext localhost:9090 grpcservice.PeopleService/ListPeople
```
### Testando com grpcurl
```bash
# Listar serviços disponíveis
grpcurl -plaintext localhost:9090 list
# Descrever um serviço
grpcurl -plaintext localhost:9090 describe grpcservice.PeopleService
```
## 🌐 APIs Externas Suportadas
### DummyJSON (Fonte: DUMMY)
- **URL Base:** `https://dummyjson.com`
- **Usuários disponíveis:** ~200
- **Documentação:** https://dummyjson.com/docs/users
### JSONPlaceholder (Fonte: TYPICODE)
- **URL Base:** `https://jsonplaceholder.typicode.com`
- **Usuários disponíveis:** 10
- **Documentação:** https://jsonplaceholder.typicode.com/guide/
## 🔧 Detalhes Técnicos
### Padrão Service
O projeto utiliza **PeopleService** como camada de aplicação:
```java
@Service
@RequiredArgsConstructor
public class PeopleServiceImpl implements PeopleService {
private final PeopleRepository peopleRepository;
@Override
public Mono getById(Integer id) {
return peopleRepository.findById(id);
}
@Override
public Flux listAll() {
return peopleRepository.findAll();
}
}
```
### Padrão Strategy
O projeto utiliza o **padrão Strategy** via `PeopleRepositoryImpl` para permitir troca dinâmica entre diferentes APIs externas:
```java
@RequiredArgsConstructor
public class PeopleRepositoryImpl implements PeopleRepository {
private final Map clientStrategies;
private final DataSource activeDataSource;
@Override
public Mono findById(Integer id) {
return getActiveClient().getPeopleById(id);
}
private PeopleClient getActiveClient() {
return clientStrategies.get(activeDataSource);
}
}
```
### Inversão de Dependência
O gRPC Service injeta a interface do serviço:
```java
@GrpcService
@RequiredArgsConstructor
public class PeopleServiceGrpcImpl extends ReactorPeopleServiceGrpc.PeopleServiceImplBase {
private final PeopleService peopleService; // Interface!
@Override
public Mono getPeople(Mono request) {
return request.flatMap(req -> peopleService.getById(req.getId()))
.map(people -> PeopleResponseGrpc.newBuilder()
.setId(people.getId())
.setName(people.getName())
.setEmail(people.getEmail())
.build());
}
}
```
### MapStruct
O MapStruct é utilizado para conversão type-safe:
```java
@Mapper(
componentModel = "spring",
implementationName = "DummyMapperImpl"
)
public interface DummyMapper {
@Mapping(target = "name",
expression = "java(response.firstName() + \" \" + response.lastName())")
PeopleResponse toPeopleResponse(DummyResponse response);
}
```
### Lombok
Construtores são gerados automaticamente via Lombok:
```java
@Service
@RequiredArgsConstructor // Gera construtor com campos final
public class PeopleServiceImpl implements PeopleService {
private final PeopleRepository peopleRepository;
}
```
## 📦 Build e Deploy
### Gerar Artefato de Produção
```bash
mvn clean package -DskipTests
```
### Docker (Exemplo)
```dockerfile
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY target/people-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 9090
ENV ACTIVE_DATASOURCE=TYPICODE
ENV SPRING_PROFILE=prod
ENTRYPOINT ["java", "-jar", "app.jar"]
```
**Build e Run:**
```bash
docker build -t people-service:latest .
docker run -p 9090:9090 people-service:latest
```
## 📝 Licença
Este projeto é um exemplo educacional e está disponível para uso livre.