Skip to content

bearcode-dev/reto_tecnico_idm

Repository files navigation

Reto Tecnico Microservicios - Arquitectura Hexagonal

Este proyecto muestra la implementacion de dos microservicios independientes utilizando Arquitectura Hexagonal, destacando el uso de programacion reactiva y trazabilidad distribuida con Spring Boot 3.x.

Resumen de la Arquitectura

El sistema se divide en dos servicios que utilizan diferentes enfoques tecnologicos para demostrar versatilidad, ambos corriendo sobre Java 17:

Product Service (Reactivo)

  • Enfoque: Alto rendimiento y manejo de flujos de datos no bloqueantes.
  • Stack: Java 17, Spring WebFlux, R2DBC (SQL Reactivo) y Gradle.

Order Service (Tradicional)

  • Enfoque: Simplicidad y robustez en logica de negocio.
  • Stack: Java 17, Spring MVC, JPA (Tradicional) y Maven.

Comparativa Tecnica

Caracteristica Product Service Order Service
Java Version 17 17
Gestor/Build Gradle Maven
Framework Web WebFlux (Reactivo) MVC (Imperativo)
Acceso a Datos R2DBC Spring Data JPA
Cliente HTTP WebClient RestClient + @HttpExchange
Arquitectura Hexagonal Hexagonal

Caracteristicas Principales

  1. Arquitectura Hexagonal: Separacion total de la logica de negocio del framework y la infraestructura (Puertos y Adaptadores).
  2. Trazabilidad Distribuida: Integracion con Zipkin y Micrometer Tracing para rastrear peticiones entre servicios.
  3. Programacion Moderna: Uso de Java Records para inmutabilidad, Streams API y Programacion Funcional.
  4. Validacion y Errores: Manejo global de excepciones con respuestas estandarizadas y validacion de tipos.
  5. Integracion Reactiva con APIs Externas: Uso de WebClient reactivo para consumir servicios externos como FakeStore API.

Integracion con FakeStore API

El Product Service incluye una integracion reactiva con la FakeStore API para demostrar el consumo de APIs externas utilizando Spring WebFlux.

Caracteristicas de la Integracion

  • Cliente HTTP Reactivo: Utiliza WebClient de Spring WebFlux para llamadas no bloqueantes.
  • Sincronizacion Programada: Job programado que ejecuta la sincronizacion cada 3 minutos (configurable).
  • Procesamiento de Flujo: Maneja respuestas como Flux<FakeStoreProductResponse> y limita el procesamiento a los primeros 5 productos.
  • Logging Estructurado: Registra informacion detallada de productos incluyendo ID, nombre, precio, categoria y rating.
  • Manejo de Errores: Gestion apropiada de errores durante la sincronizacion.

Configuracion

La integracion se configura automaticamente al iniciar el servicio:

fakestore:
  sync:
    interval: 180000  # Intervalo en milisegundos (3 minutos)

Componentes Principales

ProductSyncPort

Interfaz de puerto de salida que define el contrato para sincronización de productos desde fuentes externas.

FakeStoreProductSyncAdapter

Adaptador de infraestructura que implementa ProductSyncPort:

  • Utiliza WebClient para llamadas HTTP reactivas
  • Realiza peticiones GET a /products
  • Procesa el flujo reactivo de productos
  • Registra información de productos en logs

FakeStoreSyncUseCase

Caso de uso de aplicacion que coordina la sincronizacion:

  • Depende del puerto ProductSyncPort (no de infraestructura concreta)
  • Maneja la logica de negocio de sincronizacion
  • Puede ser reutilizado con diferentes implementaciones del puerto

FakeStoreSyncScheduler

Adaptador de entrada programado que ejecuta la sincronización de forma automática:

  • Ubicado en infrastructure/adapter/input/scheduler
  • Dispara el servicio de aplicación de forma programada

WebClientConfig

Configura el cliente HTTP reactivo con la URL base de FakeStore API.

FakeStoreProductResponse

Record que representa la estructura de respuesta de la API externa, incluyendo rating anidado.

Ejemplo de Salida en Logs

Starting synchronization with Fake Store API
📦 Product ID: 1
📦 Name: Fjallraven - Foldsack No. 1 Backpack
📦 Price: $109.95
📦 Category: men's clothing
📦 Rating: 3.9 (120 reviews)
---
✅ Synchronization completed - fetched and displayed 5 products from Fake Store API

Pruebas

La integracion incluye pruebas unitarias completas que cubren:

  • Sincronizacion exitosa
  • Respuestas vacias
  • Manejo de errores del cliente HTTP
  • Productos sin rating
  • Limitacion de procesamiento a 5 productos

Estructura del Proyecto

Product Service (Arquitectura Hexagonal)

product-service/
├── src/
│   ├── main/
│   │   ├── java/com/cardenascode/product/
│   │   │   ├── ProductServiceApplication.java
│   │   │   ├── domain/
│   │   │   │   ├── exception/
│   │   │   │   │   ├── DomainException.java
│   │   │   │   │   └── ProductNotFoundException.java
│   │   │   │   ├── model/
│   │   │   │   │   └── Product.java
│   │   │   │   └── port/
│   │   │   │       ├── input/
│   │   │   │       │   └── ProductUseCase.java
│   │   │   │       └── output/
│   │   │   │           ├── ProductRepository.java
│   │   │   │           └── ProductSyncPort.java
│   │   │   ├── application/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── CreateProductRequest.java
│   │   │   │   │   ├── UpdateProductRequest.java
│   │   │   │   │   └── ProductResponse.java
│   │   │   │   ├── mapper/
│   │   │   │   │   └── ProductMapper.java
│   │   │   │   └── usecase/
│   │   │   │       ├── FakeStoreSyncUseCase.java
│   │   │   │       └── ProductUseCaseImpl.java
│   │   │   └── infrastructure/
│   │   │       ├── adapter/
│   │   │       │   ├── input/
│   │   │       │   │   ├── scheduler/
│   │   │       │   │   │   └── FakeStoreSyncScheduler.java
│   │   │       │   │   └── web/
│   │   │       │   │       ├── FakeStoreProductResponse.java
│   │   │       │   │       └── ProductController.java
│   │   │       │   └── output/
│   │   │       │       ├── client/
│   │   │       │       │   └── FakeStoreProductSyncAdapter.java
│   │   │       │       └── persistence/
│   │   │       │           ├── entity/
│   │   │       │           │   └── ProductEntity.java
│   │   │       │           ├── ProductEntityMapper.java
│   │   │       │           ├── ProductRepositoryAdapter.java
│   │   │       │           └── R2dbcProductRepository.java
│   │   │       ├── config/
│   │   │       │   ├── DatabaseConfig.java
│   │   │       │   ├── SchedulingConfig.java
│   │   │       │   ├── SwaggerConfig.java
│   │   │       │   └── WebClientConfig.java
│   │   │       └── exception/
│   │   │           ├── ErrorResponse.java
│   │   │           ├── GlobalExceptionHandler.java
│   │   │           └── ProductNotFoundException.java
│   │   └── resources/
│   │       ├── application.yml
│   │       ├── data.sql
│   │       └── schema.sql
│   └── test/
│       └── java/com/cardenascode/product/
│           ├── ProductIntegrationTest.java
│           ├── adapter/
│           │   ├── ProductEntityMapperTest.java
│           │   └── ProductRepositoryAdapterTest.java
│           ├── controller/
│           ├── mapper/
│           │   └── ProductMapperTest.java
│           └── usecase/
│               ├── FakeStoreProductResponseTest.java
│               ├── FakeStoreSyncSchedulerTest.java
│               ├── FakeStoreSyncUseCaseTest.java
│               ├── ProductUseCaseImplTest.java
│               └── WebClientConfigTest.java
├── build.gradle
├── gradlew
├── gradlew.bat
├── settings.gradle
├── Dockerfile
├── bin/
└── gradle/

Order Service (Arquitectura Hexagonal)

order-service/
├── src/
│   ├── main/
│   │   ├── java/com/cardenascode/order/
│   │   │   ├── OrderServiceApplication.java
│   │   │   ├── domain/
│   │   │   │   ├── exception/
│   │   │   │   │   ├── DomainException.java
│   │   │   │   │   ├── InsufficientStockException.java
│   │   │   │   │   ├── OrderNotFoundException.java
│   │   │   │   │   └── ProductNotFoundException.java
│   │   │   │   ├── model/
│   │   │   │   │   ├── Order.java
│   │   │   │   │   ├── OrderItem.java
│   │   │   │   │   └── OrderStatus.java
│   │   │   │   ├── port/
│   │   │   │   │   ├── input/
│   │   │   │   │   │   └── OrderUseCase.java
│   │   │   │   │   └── output/
│   │   │   │   │       ├── OrderRepository.java
│   │   │   │   │       └── ProductClient.java
│   │   │   │   └── service/
│   │   │   │       └── OrderCalculationService.java
│   │   │   ├── application/
│   │   │   │   ├── dto/
│   │   │   │   │   ├── CreateOrderRequest.java
│   │   │   │   │   ├── OrderItemRequest.java
│   │   │   │   │   ├── OrderItemResponse.java
│   │   │   │   │   ├── OrderResponse.java
│   │   │   │   │   └── ProductDTO.java
│   │   │   │   ├── mapper/
│   │   │   │   │   └── OrderMapper.java
│   │   │   │   └── usecase/
│   │   │   │       └── OrderUseCaseImpl.java
│   │   │   └── infrastructure/
│   │   │       ├── adapter/
│   │   │       │   ├── input/web/
│   │   │       │   │   └── OrderController.java
│   │   │       │   └── output/
│   │   │       │       ├── client/
│   │   │       │       │   ├── ProductClientAdapter.java
│   │   │       │       │   └── ProductServiceClient.java
│   │   │       │       └── persistence/
│   │   │       │           ├── entity/
│   │   │       │           │   ├── OrderEntity.java
│   │   │       │           │   └── OrderItemEntity.java
│   │   │       │           ├── OrderEntityMapper.java
│   │   │       │           ├── OrderRepositoryAdapter.java
│   │   │       │           └── JpaOrderRepository.java
│   │   │       ├── config/
│   │   │       │   ├── DomainConfig.java
│   │   │       │   ├── RestClientConfig.java
│   │   │       │   └── SwaggerConfig.java
│   │   │       └── exception/
│   │   │           ├── ErrorResponse.java
│   │   │           ├── ExternalServiceException.java
│   │   │           └── GlobalExceptionHandler.java
│   │   └── resources/
│   │       └── application.yml
│   └── test/
│       └── java/com/cardenascode/order/
│           ├── OrderIntegrationTest.java
│           ├── controller/
│           │   └── OrderControllerTest.java
│           ├── service/
│           │   └── OrderCalculationServiceTest.java
│           └── usecase/
│               └── OrderUseCaseImplTest.java
├── pom.xml
├── Dockerfile
└── target/

Configuracion Compartida

config/
├── checkstyle/
│   ├── checkstyle.xml
│   └── suppressions.xml
└── spotbugs/
    └── spotbugs-exclude.xml

Documentacion de APIs

Swagger/OpenAPI

Una vez que los servicios esten en ejecucion, puedes acceder a la documentacion interactiva de las APIs:

Product Service:

Order Service:

Coleccion de Postman

El proyecto incluye una coleccion de Postman con casos de prueba completos:

📄 TECH.postman_collection.json

Importa esta coleccion en Postman para probar todos los endpoints con ejemplos predefinidos.

Ejecucion y Pruebas

Para instrucciones detalladas sobre como compilar, ejecutar y probar el proyecto, consulta la guia rapida:

Guia QUICKSTART

Contacto

cardenascode7@gmail.com

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published