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
│ │ ├── Constants.java
│ │ ├── config
│ │ │ ├── JacksonConfig.java
│ │ │ └── SwaggerConfig.java
│ │ ├── controllers
│ │ │ ├── CarController.java
│ │ │ ├── CheckinController.java
│ │ │ ├── CheckoutController.java
│ │ │ ├── SwaggerCar.java
│ │ │ ├── SwaggerCheckin.java
│ │ │ └── SwaggerCheckout.java
│ │ ├── dtos
│ │ │ ├── CarRequestDTO.java
│ │ │ ├── CarResponseDTO.java
│ │ │ ├── CheckinRequestDTO.java
│ │ │ ├── CheckinResponseDTO.java
│ │ │ ├── CheckoutRequestDTO.java
│ │ │ └── CheckoutResponseDTO.java
│ │ ├── handlers
│ │ │ ├── ApiErrorDTO.java
│ │ │ ├── ApiErrorFactory.java
│ │ │ ├── ExceptionStatusMapper.java
│ │ │ └── GlobalExceptionHandler.java
│ │ └── mappers
│ │ ├── CarMapper.java
│ │ ├── CheckinMapper.java
│ │ └── CheckoutMapper.java
│ └── outbound
│ ├── database
│ │ └── jpa
│ │ ├── mappers
│ │ │ ├── CarMapper.java
│ │ │ ├── CheckinMapper.java
│ │ │ ├── CheckoutMapper.java
│ │ │ └── SlotMapper.java
│ │ ├── models
│ │ │ ├── CarModel.java
│ │ │ ├── CheckinModel.java
│ │ │ ├── CheckoutModel.java
│ │ │ └── SlotModel.java
│ │ └── repositories
│ │ ├── adapters
│ │ │ ├── CarRepositoryAdapter.java
│ │ │ ├── CheckinRepositoryAdapter.java
│ │ │ ├── CheckoutRepositoryAdapter.java
│ │ │ └── SlotRepositoryAdapter.java
│ │ └── springdata
│ │ ├── JpaCarRepository.java
│ │ ├── JpaCheckinRepository.java
│ │ ├── JpaCheckoutRepository.java
│ │ └── JpaSlotRepository.java
│ └── messaging
│ ├── config
│ │ └── RabbitMQConfig.java
│ └── producers
│ └── CheckoutProducerAdapter.java
├── config
│ ├── BeanConfiguration.java
│ └── ClockConfig.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
│ ├── producers
│ │ └── CheckoutProducerPort.java
│ └── 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
deve com isso sobe automaticamente um banco em memoriah2e 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-testRodando 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-testRodando 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-testsRodando 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