Skip to content

Conversation

@jaggervlad
Copy link

Summary

Implementation of the Yape Code Challenge: a single Spring Boot 3.5.10 application (Java 17) with hexagonal architecture containing two bounded contexts — Transaction and
Anti-Fraud — communicating asynchronously via Apache Kafka.

Features Implemented

Core

  • REST APIPOST /api/transactions (create) and GET /api/transactions/{id} (retrieve with resolved status)
  • Kafka async flow — Transaction publishes to transaction-created, Anti-Fraud validates and publishes result to transaction-status
  • Anti-Fraud rule — Transactions with value > 1000 are rejected, all others approved
  • PostgreSQL persistence with Spring Data JPA

Production Readiness

  • Idempotent Kafka consumers — Safe retries: duplicate messages are no-ops, only real conflicts throw exceptions
  • Redis caching for transaction lookups
  • Structured JSON logging — Human-readable in dev, JSON (LogstashEncoder) in prod via SPRING_PROFILES_ACTIVE=prod
  • Docker Compose with healthchecks on postgres, kafka, and redis + app service with depends_on: service_healthy
  • Global exception handling with proper HTTP status codes and validation error responses
  • Kafka DLT (Dead Letter Topic) for failed messages
  • Spring Actuator health endpoint

Documentation & Quality

  • OpenAPI / Swagger UI at /api/swagger-ui.html
  • 28 tests — Unit tests (domain model, application services), integration tests (EmbeddedKafka + H2)
  • Hexagonal architecture — Domain logic is framework-agnostic with clear port/adapter separation

Tech Stack

Component Technology
Language Java 17
Framework Spring Boot 3.5.10
Build Maven (with wrapper)
Database PostgreSQL 14
Cache Redis 7
Messaging Apache Kafka
Testing JUnit 5, EmbeddedKafka, H2, Awaitility
Logging Logback + logstash-logback-encoder
Docs springdoc-openapi
Containerization Docker multi-stage build

How to Run

# Start everything (postgres, kafka, redis, app)
docker-compose up --build

# Verify
curl http://localhost:8080/api/actuator/health

# Create a transaction
curl -X POST http://localhost:8080/api/transactions \
  -H "Content-Type: application/json" \
  -d '{
    "accountExternalIdDebit": "550e8400-e29b-41d4-a716-446655440000",
    "accountExternalIdCredit": "550e8400-e29b-41d4-a716-446655440001",
    "tranferTypeId": 1,
    "value": 120
  }'

# Retrieve (use the transactionExternalId from the response above)
curl http://localhost:8080/api/transactions/{id}

Test Plan

- 28 unit and integration tests passing (./mvnw clean test)
- docker-compose up --build — all services start healthy
- POST /api/transactions with value ≤ 1000 → status becomes approved
- POST /api/transactions with value > 1000 → status becomes rejected
- GET /api/transactions/{id} returns resolved transaction with correct status

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant