Controle de entrada e Saida de veículos estacionamento.
Este projeto utiliza a arquitetura hexagonal (também conhecida como Ports and Adapters) para organizar o código de forma que seja fácil de manter, testar e escalar. A arquitetura hexagonal promove a separação de preocupações, permitindo que a lógica de negócios seja independente de frameworks, bancos de dados e outros detalhes de implementação.
A estrutura do projeto é organizada da seguinte forma:
parking
├── ParkingApplication.java
├── adapters
│ ├── inbound
│ │ └── http
│ │ ├── config
│ │ │ └── SwaggerConfig.java
│ │ ├── controllers
│ │ │ ├── CarController.java
│ │ │ ├── CheckinController.java
│ │ │ └── CheckoutController.java
│ │ ├── dtos
│ │ │ ├── CarRequestDTO.java
│ │ │ ├── CarResponseDTO.java
│ │ │ ├── CheckinRequestDTO.java
│ │ │ ├── CheckinResponseDTO.java
│ │ │ ├── CheckoutRequestDTO.java
│ │ │ └── CheckoutResponseDTO.java
│ │ ├── handlers
│ │ │ ├── ApiError.java
│ │ │ └── GlobalExceptionHandler.java
│ │ └── mappers
│ │ ├── CarMapper.java
│ │ └── CheckinMapper.java
│ └── outbound
│ ├── database
│ │ └── jpa
│ │ ├── mappers
│ │ │ ├── CarMapper.java
│ │ │ ├── CheckinMapper.java
│ │ │ ├── CheckoutMapper.java
│ │ │ └── SlotMapper.java
│ │ ├── models
│ │ │ ├── CarModel.java
│ │ │ ├── CheckinModel.java
│ │ │ ├── CheckoutModel.java
│ │ │ └── SlotModel.java
│ │ └── repositories
│ │ ├── CarRepositoryAdapter.java
│ │ ├── CheckinRepositoryAdapter.java
│ │ ├── CheckoutRepositoryAdapter.java
│ │ ├── JpaRepositoryCar.java
│ │ ├── JpaRepositoryCheckin.java
│ │ ├── JpaRepositoryCheckout.java
│ │ ├── JpaRepositorySlot.java
│ │ └── SlotRepositoryAdapter.java
│ └── messaging
│ ├── config
│ │ └── RabbitMQConfig.java
│ └── producers
│ └── CheckoutProducerAdapter.java
├── config
│ └── BeanConfiguration.java
└── core
├── entities
│ ├── Car.java
│ ├── Checkin.java
│ ├── Checkout.java
│ └── Slot.java
├── exceptions
│ ├── CarNotFoundException.java
│ ├── CheckinNotFoundException.java
│ ├── CheckinTimeMissingException.java
│ ├── ErrorMessages.java
│ ├── ExistPlateException.java
│ ├── InvalidCheckinException.java
│ ├── InvalidPlateException.java
│ ├── ParkingFullException.java
│ └── SlotOccupiedException.java
├── ports
│ ├── inbound
│ │ └── services
│ │ ├── CarServicePort.java
│ │ ├── CheckinServicePort.java
│ │ ├── CheckoutServicePort.java
│ │ └── SlotServicePort.java
│ └── outbound
│ └── repositories
│ ├── CarRepositoryPort.java
│ ├── CheckinRepositoryPort.java
│ ├── CheckoutRepositoryPort.java
│ └── SlotRepositoryPort.java
├── services
│ ├── CarService.java
│ ├── CheckinService.java
│ ├── CheckoutService.java
│ └── SlotService.java
├── utils
│ └── StringUtils.java
└── valueobjects
└── Plate.java
Este é o ponto de entrada da aplicação Spring Boot. Ele configura a aplicação e inicia o contexto do Spring.
Os adapters são responsáveis por conectar a aplicação com o mundo externo. Eles são divididos em inbound
e outbound
.
-
Inbound Adapters: Recebem as requisições externas e as encaminham para a lógica de negócios.
http.config
: Contém configurações específicas para os endpoints HTTP, como o SwaggerConfig.http.controllers
: Contém os controladores REST que expõem as APIs HTTP.http.dtos
: Contém os Data Transfer Objects usados para transferir dados entre a camada de apresentação e a lógica de negócios.http.handlers
: Contém manipuladores globais de exceções e erros.http.mappers
: Contém os mapeadores que convertem entre entidades de domínio e DTOs.
-
Outbound Adapters: Conectam a aplicação a sistemas externos, como bancos de dados e sistemas de mensageria.
database.jpa.mappers
: Converte entre entidades de domínio e entidades de persistência.database.jpa.models
: Contém os modelos de persistência.database.jpa.repositories
: Contém os repositórios JPA para acesso ao banco de dados.messaging.config
: Configurações de mensageria, como RabbitMQConfig.messaging.producers
: Contém os produtores de mensagens para sistemas de mensageria, como RabbitMQ.
BeanConfiguration
: é usada para definir beans personalizados que serão gerenciados pelo Spring. Esta classe foi criada para garantir que os serviços de negócios não dependam diretamente de um framework específico, como o Spring. Isso mantém a lógica de negócios independente e alinhada aos princípios da arquitetura hexagonal.
O núcleo da aplicação contém a lógica de negócios e é independente de frameworks e detalhes de implementação.
-
Entities: Contém as entidades de domínio.
Car.java
,Checkin.java
,Checkout.java
,Slot.java
-
Services: Contém os serviços de negócios que implementam a lógica de negócios.
CarService.java
,CheckinService.java
,CheckoutService.java
,SlotService.java
-
Exceptions: Contém as exceções de domínio.
CarNotFoundException.java
,CheckinNotFoundException.java
,InvalidPlateException.java
-
Ports: Define as interfaces para os serviços e repositórios.
inbound.services
: Interfaces para os serviços de negócios.outbound.repositories
: Interfaces para os repositórios.
-
Utils: Contém utilitários auxiliares.
StringUtils.java
-
Value Objects: Contém os objetos de valor do domínio.
Plate.java
As configurações da aplicação estão nos arquivos application-dev.yml
e application-prod.yml
, que definem as configurações para os ambientes de desenvolvimento e produção, respectivamente.
- Requisição HTTP: Uma requisição HTTP é recebida por um controlador REST (
controllers
). - DTO: O controlador converte a requisição em um DTO (
dtos
). - Mapper: O DTO é convertido em uma entidade de domínio por um mapper (
mappers
). - Serviço: A entidade de domínio é passada para um serviço de negócios (
services
), que contém a lógica de negócios. - Repositório: O serviço interage com os repositórios (
repositories
) para acessar o banco de dados. - Resposta: O serviço retorna uma entidade de domínio que é convertida em um DTO por um mapper e enviada de volta pelo controlador.
A aplicação utiliza RabbitMQ para enviar mensagens de checkout. O CheckoutProducerAdapter
é responsável por serializar a mensagem e enviá-la para a fila RabbitMQ.
As exceções de domínio são lançadas quando ocorrem erros específicos do domínio, como CarNotFoundException
e InvalidPlateException
.
A arquitetura hexagonal utilizada neste projeto promove a separação de preocupações, facilitando a manutenção, testes e escalabilidade da aplicação. A lógica de negócios é mantida independente de frameworks e detalhes de implementação, permitindo que a aplicação seja facilmente adaptável a mudanças.
Certifique-se de ter os seguintes softwares instalados em sua máquina:
- Clone o repositório
git clone https://github.com/pablords/parking-hexagonal-java.git
cd parking-hexagonal-java
- Compile o projeto e baixe as dependências
mvn clean install
- Suba o container do RabbitMQ
docker compose up -d rabbitmq
- Execute a aplicação
mvn spring-boot:run
- Acesse a aplicação
A aplicação estará disponível em http://localhost:8080.
Documentação da API
- A documentação interativa da API gerada pelo Swagger estará disponível em http://localhost:8080/api/v1/swagger-ui/index.html.
Banco de Dados
- Por padrão o profile habilitado é o
dev
e com isso sobe automaticamente um banco em memoriah2
e o console dele estará disponível em http://localhost:8080/api/v1/h2-console
Variáveis de Ambiente
- Você pode configurar variáveis de ambiente específicas no arquivo application.properties ou application.yml localizado em resources.
- Testes
Rodando testes unitários:
- Testamos nossos serviços, onde o núcleo da nossa lógica de negócios vive, mas é independente de qualquer tipo de persistência ou transporte
mvn test -Punit-test
Rodando testes de componentes:
- Testamos toda a pilha da nossa camada de Http/API, pelos serviços e repositórios, validando nosso sistema mockando todos detalhes de infra e sistemas externos.
mvn test -Pcomponent-test
Rodando testes de contratos:
- Validamos se a comunicação entre consumidores e provedores da API está alinhada, garantindo que mudanças na API não quebrem a integração. O provider verifica os contratos esperados pelos consumers, utilizando pactos armazenados no Pact Broker.
mvn test -Pcontract-tests
Rodando testes de integração:
- Testamos toda a pilha da nossa camada de Http/API, pelos serviços, repositórios, fontes de dados e serviços externos atingidos. Essas especificações testam se "conectamos" tudo corretamente.
mvn test -Pintegration-test