{"id":50329069,"url":"https://github.com/eneas-almeida/people","last_synced_at":"2026-05-29T08:30:39.909Z","repository":{"id":329013767,"uuid":"1117542110","full_name":"eneas-almeida/people","owner":"eneas-almeida","description":"📜 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.","archived":false,"fork":false,"pushed_at":"2025-12-26T18:41:46.000Z","size":123,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-12-28T02:44:25.092Z","etag":null,"topics":["clean-architecture","grpc","java","microservice","springboot","strategy-pattern","webflux"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eneas-almeida.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-16T13:10:23.000Z","updated_at":"2025-12-26T18:48:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/eneas-almeida/people","commit_stats":null,"previous_names":["eneas-almeida/people"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/eneas-almeida/people","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eneas-almeida%2Fpeople","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eneas-almeida%2Fpeople/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eneas-almeida%2Fpeople/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eneas-almeida%2Fpeople/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eneas-almeida","download_url":"https://codeload.github.com/eneas-almeida/people/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eneas-almeida%2Fpeople/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33644076,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clean-architecture","grpc","java","microservice","springboot","strategy-pattern","webflux"],"created_at":"2026-05-29T08:30:39.131Z","updated_at":"2026-05-29T08:30:39.902Z","avatar_url":"https://github.com/eneas-almeida.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# People Service\n\nServiç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.\n\n## 📋 Índice\n\n- [Visão Geral](#-visão-geral)\n- [Arquitetura](#-arquitetura)\n- [Tecnologias](#-tecnologias)\n- [Estrutura do Projeto](#-estrutura-do-projeto)\n- [Pré-requisitos](#-pré-requisitos)\n- [Configuração](#-configuração)\n- [Como Executar](#-como-executar)\n- [API gRPC](#-api-grpc)\n- [APIs Externas Suportadas](#-apis-externas-suportadas)\n- [Detalhes Técnicos](#-detalhes-técnicos)\n- [Build e Deploy](#-build-e-deploy)\n\n## 🎯 Visão Geral\n\nO **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.\n\n### Funcionalidades Principais\n\n- **Buscar pessoa por ID**: Retorna informações detalhadas de uma pessoa específica\n- **Listar todas as pessoas**: Retorna uma lista com todas as pessoas disponíveis\n- **Múltiplas fontes de dados**: Suporte a DummyJSON e JSONPlaceholder via padrão Strategy\n- **Comunicação reativa**: Utiliza WebFlux para chamadas HTTP não-bloqueantes\n- **Interface gRPC**: API de alto desempenho para comunicação entre serviços\n- **Logging estruturado**: Sistema de logs com correlation IDs e contexto de requisição\n- **Tratamento robusto de erros**: Hierarquia de exceções customizadas e retry com backoff\n\n## 🏗 Arquitetura\n\nO projeto segue os princípios da **Clean Architecture**, organizando o código em camadas bem definidas:\n\n```\n┌─────────────────────────────────────────┐\n│      Entrypoint (gRPC Service)          │\n│   - PeopleServiceGrpcImpl               │\n└─────────────┬───────────────────────────┘\n              │\n┌─────────────▼───────────────────────────┐\n│       Application Layer                 │\n│   - PeopleService (interface)           │\n│   - PeopleServiceImpl                   │\n└─────────────┬───────────────────────────┘\n              │\n┌─────────────▼───────────────────────────┐\n│       Domain Layer                      │\n│   - People (Entity)                     │\n│   - PeopleClient (Interface)            │\n│   - PeopleRepository (Interface)        │\n│   - DataSource (Enum)                   │\n└─────────────┬───────────────────────────┘\n              │\n┌─────────────▼───────────────────────────┐\n│      Infrastructure Layer               │\n│   Repository:                           │\n│   - PeopleRepositoryImpl (Strategy)     │\n│                                         │\n│   Clients:                              │\n│   - DummyClientImpl                     │\n│   - TypiCodeClientImpl                  │\n│                                         │\n│   Configs:                              │\n│   - RepositoryConfig                    │\n│   - DummyClientConfig                   │\n│   - TypiCodeClientConfig                │\n└─────────────────────────────────────────┘\n```\n\n### Camadas\n\n1. **Domain** (`org.people.domain`)\n   - Contém as entidades de negócio (`People`)\n   - Interfaces de cliente (`PeopleClient`) e repositório (`PeopleRepository`)\n   - Exceções de negócio (`PeopleException`, `PeopleNotFoundException`, etc.)\n   - Enums (`DataSource`)\n   - Livre de dependências externas\n\n2. **Application** (`org.people.application`)\n   - Implementa a lógica de negócio da aplicação\n   - DTOs de aplicação (`PeopleResponse`)\n   - Services (`PeopleService`, `PeopleServiceImpl`)\n   - Orquestra as interações entre domain e infrastructure\n\n3. **Infrastructure** (`org.people.infrastructure`)\n   - **Clients**: Implementações concretas dos clientes de API\n     - `dummy/`: Cliente para DummyJSON API\n     - `typicode/`: Cliente para JSONPlaceholder API\n   - **Repository**: Implementação do padrão Strategy (`PeopleRepositoryImpl`)\n   - **Entrypoints**: Pontos de entrada da aplicação (gRPC)\n   - **Config**: Configurações e beans do Spring\n   - **Exception**: Exceções de infraestrutura\n   - **Logging**: Sistema de logging estruturado\n\n## 🚀 Tecnologias\n\n### Core\n- **Java 21**: Versão LTS mais recente com recursos modernos\n- **Spring Boot 3.3.3**: Framework principal para desenvolvimento\n- **Maven**: Gerenciamento de dependências e build\n\n### Comunicação\n- **gRPC 1.59.0**: Framework RPC de alto desempenho\n- **Protocol Buffers 3.24.4**: Serialização de dados\n- **Spring WebFlux**: Cliente HTTP reativo e não-bloqueante\n- **Reactor gRPC 1.2.4**: gRPC Reativo\n\n### Utilitários\n- **Lombok**: Redução de boilerplate code\n- **MapStruct 1.5.5**: Mapeamento automático entre objetos\n- **Logstash Logback Encoder 7.4**: Logging estruturado em JSON\n- **Datadog Trace API 1.30.1**: Observabilidade e tracing distribuído\n\n### Programação Reativa\n- **Project Reactor**: Implementação do Reactive Streams\n  - `Mono\u003cT\u003e`: Para operações que retornam 0 ou 1 elemento\n  - `Flux\u003cT\u003e`: Para operações que retornam 0 a N elementos\n\n## 📁 Estrutura do Projeto\n\n```\npeople/\n├── src/\n│   ├── main/\n│   │   ├── java/org/people/\n│   │   │   ├── PeopleApplication.java\n│   │   │   │\n│   │   │   ├── domain/\n│   │   │   │   ├── client/\n│   │   │   │   │   └── PeopleClient.java           # Interface do cliente\n│   │   │   │   ├── entity/\n│   │   │   │   │   └── People.java                 # Entidade de domínio\n│   │   │   │   ├── enums/\n│   │   │   │   │   └── DataSource.java             # Enum de fontes de dados\n│   │   │   │   ├── exception/\n│   │   │   │   │   ├── PeopleException.java\n│   │   │   │   │   ├── BusinessRuleException.java\n│   │   │   │   │   ├── ValidationException.java\n│   │   │   │   │   └── PeopleNotFoundException.java\n│   │   │   │   └── repository/\n│   │   │   │       └── PeopleRepository.java       # Interface do repositório\n│   │   │   │\n│   │   │   ├── application/\n│   │   │   │   ├── dto/\n│   │   │   │   │   └── PeopleResponse.java         # DTO de resposta\n│   │   │   │   └── service/\n│   │   │   │       ├── PeopleService.java          # Interface do serviço\n│   │   │   │       └── PeopleServiceImpl.java      # Implementação do serviço\n│   │   │   │\n│   │   │   └── infrastructure/\n│   │   │       ├── client/\n│   │   │       │   ├── dummy/\n│   │   │       │   │   ├── DummyClientImpl.java\n│   │   │       │   │   ├── DummyMapper.java\n│   │   │       │   │   ├── DummyResponse.java\n│   │   │       │   │   └── DummyListResponse.java\n│   │   │       │   └── typicode/\n│   │   │       │       ├── TypiCodeClientImpl.java\n│   │   │       │       ├── TypiCodeMapper.java\n│   │   │       │       └── TypiCodeResponse.java\n│   │   │       │\n│   │   │       ├── repository/\n│   │   │       │   └── PeopleRepositoryImpl.java   # Padrão Strategy\n│   │   │       │\n│   │   │       ├── config/\n│   │   │       │   ├── client/\n│   │   │       │   │   ├── DummyClientConfig.java\n│   │   │       │   │   └── TypiCodeClientConfig.java\n│   │   │       │   └── RepositoryConfig.java       # Config do repository\n│   │   │       │\n│   │   │       ├── entrypoint/grpc/\n│   │   │       │   └── PeopleServiceGrpcImpl.java\n│   │   │       │\n│   │   │       ├── exception/\n│   │   │       │   ├── GlobalGrpcExceptionHandler.java\n│   │   │       │   ├── ExternalServiceException.java\n│   │   │       │   └── InternalServerException.java\n│   │   │       │\n│   │   │       └── logging/\n│   │   │           ├── Logger.java\n│   │   │           ├── LogContext.java\n│   │   │           ├── RequestContext.java\n│   │   │           └── GrpcLoggingInterceptor.java\n│   │   │\n│   │   ├── proto/\n│   │   │   └── person.proto                        # Definição do serviço gRPC\n│   │   │\n│   │   └── resources/\n│   │       └── application.yml                     # Configurações da aplicação\n│   │\n│   └── test/\n│       └── java/org/people/\n│           └── PeopleApplicationTests.java\n│\n├── target/                                         # Arquivos compilados\n├── pom.xml                                         # Configuração Maven\n├── mvnw                                            # Maven Wrapper (Unix)\n└── mvnw.cmd                                        # Maven Wrapper (Windows)\n```\n\n## 📋 Pré-requisitos\n\n- **Java Development Kit (JDK) 21** ou superior\n- **Maven 3.6+** (ou utilize o Maven Wrapper incluído no projeto)\n- **Git** (para clonar o repositório)\n- Conexão com a internet (para acessar as APIs externas)\n\n### Verificar Instalações\n\n```bash\n# Verificar versão do Java\njava -version\n\n# Verificar versão do Maven\nmvn -version\n```\n\n## ⚙ Configuração\n\n### Arquivo application.yml\n\n```yaml\nspring:\n  application:\n    name: people\n  profiles:\n    active: ${SPRING_PROFILE:local}\n\ngrpc:\n  server:\n    port: 9090\n\nclient:\n  active-datasource: TYPICODE  # Options: TYPICODE, DUMMY\n  typicode:\n    base-url: https://jsonplaceholder.typicode.com\n  dummy:\n    base-url: https://dummyjson.com\n\nlogging:\n  level:\n    root: INFO\n    org.people: DEBUG\n    io.grpc: INFO\n    net.devh: INFO\n```\n\n### Seleção de Fonte de Dados\n\nA aplicação suporta duas APIs externas. Para alterar a fonte de dados, modifique a propriedade `client.active-datasource`:\n\n```yaml\n# Para usar DummyJSON\nclient:\n  active-datasource: DUMMY\n\n# Para usar JSONPlaceholder\nclient:\n  active-datasource: TYPICODE\n```\n\nOu defina via variável de ambiente:\n\n```bash\nexport ACTIVE_DATASOURCE=DUMMY\n```\n\n## 🏃 Como Executar\n\n### Usando Maven Wrapper (Recomendado)\n\n#### Windows\n```cmd\n# Limpar e compilar o projeto\n.\\mvnw.cmd clean install\n\n# Executar a aplicação\n.\\mvnw.cmd spring-boot:run\n```\n\n#### Unix/Linux/MacOS\n```bash\n# Limpar e compilar o projeto\n./mvnw clean install\n\n# Executar a aplicação\n./mvnw spring-boot:run\n```\n\n### Usando Maven Local\n\n```bash\n# Limpar e compilar\nmvn clean install\n\n# Executar\nmvn spring-boot:run\n```\n\n### Executando o JAR Gerado\n\n```bash\n# Gerar o JAR\nmvn clean package\n\n# Executar o JAR\njava -jar target/people-0.0.1-SNAPSHOT.jar\n```\n\n### Verificar Execução\n\nApós iniciar a aplicação, você verá logs indicando que o servidor gRPC está rodando:\n\n```\ngRPC Server started, listening on address: *, port: 9090\n```\n\n## 🔌 API gRPC\n\n### Endpoints Disponíveis\n\n#### 1. GetPeople\nBusca uma pessoa específica por ID.\n\n**Exemplo de Uso com grpcurl:**\n```bash\ngrpcurl -plaintext -d '{\"id\": 1}' localhost:9090 grpcservice.PeopleService/GetPeople\n```\n\n**Resposta Esperada:**\n```json\n{\n  \"id\": 1,\n  \"name\": \"Leanne Graham\",\n  \"email\": \"Sincere@april.biz\"\n}\n```\n\n#### 2. ListPeople\nLista todas as pessoas disponíveis.\n\n**Exemplo de Uso com grpcurl:**\n```bash\ngrpcurl -plaintext localhost:9090 grpcservice.PeopleService/ListPeople\n```\n\n### Testando com grpcurl\n\n```bash\n# Listar serviços disponíveis\ngrpcurl -plaintext localhost:9090 list\n\n# Descrever um serviço\ngrpcurl -plaintext localhost:9090 describe grpcservice.PeopleService\n```\n\n## 🌐 APIs Externas Suportadas\n\n### DummyJSON (Fonte: DUMMY)\n- **URL Base:** `https://dummyjson.com`\n- **Usuários disponíveis:** ~200\n- **Documentação:** https://dummyjson.com/docs/users\n\n### JSONPlaceholder (Fonte: TYPICODE)\n- **URL Base:** `https://jsonplaceholder.typicode.com`\n- **Usuários disponíveis:** 10\n- **Documentação:** https://jsonplaceholder.typicode.com/guide/\n\n## 🔧 Detalhes Técnicos\n\n### Padrão Service\n\nO projeto utiliza **PeopleService** como camada de aplicação:\n\n```java\n@Service\n@RequiredArgsConstructor\npublic class PeopleServiceImpl implements PeopleService {\n\n    private final PeopleRepository peopleRepository;\n\n    @Override\n    public Mono\u003cPeopleResponse\u003e getById(Integer id) {\n        return peopleRepository.findById(id);\n    }\n\n    @Override\n    public Flux\u003cPeopleResponse\u003e listAll() {\n        return peopleRepository.findAll();\n    }\n}\n```\n\n### Padrão Strategy\n\nO projeto utiliza o **padrão Strategy** via `PeopleRepositoryImpl` para permitir troca dinâmica entre diferentes APIs externas:\n\n```java\n@RequiredArgsConstructor\npublic class PeopleRepositoryImpl implements PeopleRepository {\n\n    private final Map\u003cDataSource, PeopleClient\u003e clientStrategies;\n    private final DataSource activeDataSource;\n\n    @Override\n    public Mono\u003cPeopleResponse\u003e findById(Integer id) {\n        return getActiveClient().getPeopleById(id);\n    }\n\n    private PeopleClient getActiveClient() {\n        return clientStrategies.get(activeDataSource);\n    }\n}\n```\n\n### Inversão de Dependência\n\nO gRPC Service injeta a interface do serviço:\n\n```java\n@GrpcService\n@RequiredArgsConstructor\npublic class PeopleServiceGrpcImpl extends ReactorPeopleServiceGrpc.PeopleServiceImplBase {\n\n    private final PeopleService peopleService;  // Interface!\n\n    @Override\n    public Mono\u003cPeopleResponseGrpc\u003e getPeople(Mono\u003cPeopleRequestGrpc\u003e request) {\n        return request.flatMap(req -\u003e peopleService.getById(req.getId()))\n            .map(people -\u003e PeopleResponseGrpc.newBuilder()\n                .setId(people.getId())\n                .setName(people.getName())\n                .setEmail(people.getEmail())\n                .build());\n    }\n}\n```\n\n### MapStruct\n\nO MapStruct é utilizado para conversão type-safe:\n\n```java\n@Mapper(\n    componentModel = \"spring\",\n    implementationName = \"DummyMapperImpl\"\n)\npublic interface DummyMapper {\n\n    @Mapping(target = \"name\",\n        expression = \"java(response.firstName() + \\\" \\\" + response.lastName())\")\n    PeopleResponse toPeopleResponse(DummyResponse response);\n}\n```\n\n### Lombok\n\nConstrutores são gerados automaticamente via Lombok:\n\n```java\n@Service\n@RequiredArgsConstructor  // Gera construtor com campos final\npublic class PeopleServiceImpl implements PeopleService {\n    private final PeopleRepository peopleRepository;\n}\n```\n\n## 📦 Build e Deploy\n\n### Gerar Artefato de Produção\n\n```bash\nmvn clean package -DskipTests\n```\n\n### Docker (Exemplo)\n\n```dockerfile\nFROM eclipse-temurin:21-jre-alpine\n\nWORKDIR /app\nCOPY target/people-0.0.1-SNAPSHOT.jar app.jar\n\nEXPOSE 9090\n\nENV ACTIVE_DATASOURCE=TYPICODE\nENV SPRING_PROFILE=prod\n\nENTRYPOINT [\"java\", \"-jar\", \"app.jar\"]\n```\n\n**Build e Run:**\n```bash\ndocker build -t people-service:latest .\ndocker run -p 9090:9090 people-service:latest\n```\n\n## 📝 Licença\n\nEste projeto é um exemplo educacional e está disponível para uso livre.\n\n\u003chr /\u003e\n\n\u003cdiv\u003e\n  \u003csub\u003eConteúdo criado por \u003ca href=\"https://github.com/eneas-almeida\"\u003eEnéas Almeida\u003c/a\u003e\u003c/sub\u003e\n\u003c/div\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feneas-almeida%2Fpeople","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feneas-almeida%2Fpeople","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feneas-almeida%2Fpeople/lists"}