Skip to content

Bank as a service for bank transfer. Built with Java 21 and Spring.

Notifications You must be signed in to change notification settings

angelicamarttins/baas-java

Repository files navigation

Bank as a service para transferência entre contas

O presente projeto visa disponibilizar REST APIs para realizar transferências entre contas bancárias.

Tecnologias

  • Java 21
  • Spring Boot
  • Spring MVC
  • Spring Data JPA
  • Spring Data Redis
  • Spring Validation
  • Spring Kafka
  • PostgreSQL
  • Okhttp3
  • Resilience4j
  • Schema Registry
  • Avro
  • JUnit 5
  • Lombok

Setup

Para utilizar o projeto, realize os passos a seguir:

  1. Clone o repositório que mocka os serviços terceiros e siga as orientações presentes no README do projeto;
  2. Clone o presente repositório seguindo os comandos:
  git clone https://github.com/angelicamarttins/baas-java.git

  cd baas-java
  1. Certifique-se de que está configurado e em uso na sua máquina a versão 21 do Java e rode o projeto com os seguintes comandos:
  docker-compose up -d

  ./gradlew bootRun
  1. Uma vez que a aplicação esteja rodando, requisite o endpoint http://localhost:8080/transferencia com o body:
  {
    "idCliente": "2ceb26e9-7b5c-417e-bf75-ffaa66e3a76f",
    "valor": 500.00,
    "conta": {
        "idOrigem": "d0d32142-74b7-4aca-9c68-838aeacef96b",
        "idDestino": "41313d7b-bd75-4c75-9dea-1f4be434007f"
    }
  }
  1. Você receberá um retorno similar a esse:
    {
      "id_transferencia": "07b327f0-eea9-49ce-b693-12f096396cbe"
    }

System design

Link para visualizar melhor o desenho arquitetural

Logo

Principais decisões

Design Patterns

Strategy

Utilizei o padrão Strategy em razão das diferentes necessidades de transferência entre contas de pessoas física e jurídica. Por exemplo, em uma transferência entre pessoas jurídicas, poderia ser preciso verificar se o cliente que está executando a transferência pertence ao Quadro Societário da empresa titular dessa conta. Esse tipo de validação e outros dados a serem processados não caberiam a uma conta de pessoa física e tornaria o código confuso e de difícil manutenibilidade.

Builder

Além do Strategy, usei o padrão Builder na entidade Transfer a fim de facilitar a instanciação desse objeto, sem precisar criar inúmeros construtores para atender cada caso de uso.

Comunicação com serviços terceiros

Em razão dependermos de serviços externos, criei um client com Okhttp3 para realizar as requisições e um interceptador para transformar as exceções recebidas em exceções conhecidas do sistema.

Por disponibilidade de tempo, optei por mapear todas as exceções em uma exceção genérica chamada ClientException. Apenas um caso foge a essa generalidade: exceções com status 429, pois as transformo em TooManyRequestClientException. Fiz isso para demonstrar que o retry configurado com Resiliense4j não iria seguir requisitando o serviço terceiro, comento sobre isso melhor abaixo.

Bacen indisponível e retorno da requisição

A fim de garantir resiliência, optei por não retentar comunicação com o Bacen quando a exceção retornada fosse 429, dado que o rate limit desse serviço teria sido atingido.

Para cenários como esse ou quando todas as retentativas foram realizadas sem sucesso, retorno 200 para diminiuir a espera do client e publico o id dessa transferência em um tópico do Kafka que irá tentar uma nova comunicação com o Bacen. Essa estratégia só é possível porque já realizei a comunicação com serviço de saldo e obtive sucesso, ou seja, do nosso lado do banco, a transação foi realizada com sucesso e podemos comunicar com o Bacen posteriormente.

Resiliência

Pensando em resiliência com os serviços terceiros, decidi adotar três estratégias: retry com backoff exponencial, timelimiter para derrubar comunicações demoradas e circuit breaker para impedir que novas requisições sejam feitas e retentadas em serviços que demonstraram estar fora do ar. Tais estratégias nos permite ser resilientes a falhas das dependências ao passo que não nos deixa esperando tempo demais por uma resposta.

Cache

Adotei o uso de cache para acelerar determinadas consultas a dados que foram obtidos e, caso nossa aplicação caia e o cliente realize uma transferência em sequência, a aplicação não demorará a responder, pois os dados sobre o cliente recebedor e a transferência criada - quando houver falha no Bacen - estarão disponíveis por 30 minutos no Redis.

Testes

Normalmente, eu teria testado todas as classes existentes no projeto. Por disponibilidade de tempo, decidi fazer testes unitários nas principais classes do sistema: TransferService e TransferNaturalPersonStrategy a fim de garantir o principal fluxo.

About

Bank as a service for bank transfer. Built with Java 21 and Spring.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages