Arquitetura Hexagonal Blueprint

Arquitetura Hexagonal

Ports & Adapters — Alistair Cockburn (2005)

Definição

A Arquitetura Hexagonal — também chamada de Ports & Adapters — organiza o software em torno de um núcleo de domínio isolado. Seu princípio central é que a lógica de negócio nunca deve depender de detalhes de infraestrutura: banco de dados, frameworks web, serviços de e-mail, filas de mensagens, etc.

A ideia foi publicada por Alistair Cockburn em 2005 e tornou-se a base para Clean Architecture (Martin) e Onion Architecture (Palermo) — todas variações do mesmo princípio fundamental: inversão de dependência em favor do domínio.

Por que "hexagonal"? O hexágono não tem significado geométrico especial. Cockburn o escolheu por ter lados suficientes para representar múltiplas portas, sem remeter visualmente à arquitetura em camadas convencional (que usa retângulos empilhados verticalmente).

Objetivos

Isolar o Domínio

A lógica de negócio fica em Java puro — sem @Entity, sem @Inject, sem imports de frameworks.

Substituição Livre

Trocar MySQL por MongoDB, REST por eventos? Basta trocar o adaptador. O domínio permanece intocado.

Testabilidade Máxima

O serviço pode ser testado com new BooksService(fakeRepo, fakeNotify) — zero CDI, zero banco.

Fronteiras Explícitas

Cada componente tem uma responsabilidade clara. Adaptadores traduzem; o domínio decide.

O Hexágono — Diagrama Interativo

Clique nos componentes para ver detalhes sobre cada camada da arquitetura.

DOMÍNIO Book · BooksService PORTAS (interfaces) AddBookUseCase BookRepository EmailNotification BookResource CLI / Tests gRPC / Events Panache BookRepo LogEmail Notif. Cache Mensageria ApplicationBeans Domínio Portas Adapt. Entrada Adapt. Saída
Clique em um componente do diagrama para ver detalhes sobre a camada.

Componentes em Detalhe

1. Domíniocore
Núcleo da aplicação — Java puro

Contém: a entidade Book (com fábrica estática Book.of() que valida ISBN, campos obrigatórios e exemplares), as interfaces de porta (AddBookUseCase, BookRepository, EmailNotification…) e o serviço BooksService. Zero imports de Quarkus, JPA ou CDI.

2. Portas de Entradadriving ports
O que o domínio oferece

Interfaces definidas no domínio que expõem as operações disponíveis: AddBookUseCase, ListBookUseCase, UpdateBookUseCase, DeleteBookUseCase. Todos os adaptadores de entrada dependem dessas interfaces — nunca de BooksService diretamente.

3. Portas de Saídadriven ports
O que o domínio precisa

Interfaces que o domínio define e os adaptadores implementam: BookRepository (persistência) e EmailNotification (notificação). BooksService depende dessas interfaces — nunca de PanacheBookRepository diretamente.

4. Adaptadores de Entradadriving adapters
Conduzem o domínio a partir do mundo externo

BookResource (JAX-RS): recebe a requisição HTTP, deserializa o JSON para BookRequest, cria o objeto Book via Book.of() e chama a porta de entrada. Todas as anotações @Path, @POST, @Inject ficam aqui — o domínio não as conhece.

5. Adaptadores de Saídadriven adapters
São acionados pelo domínio através das portas

PanacheBookRepository: implementa BookRepository com Hibernate Reactive (Panache) e MySQL. Usa BookMapper (MapStruct) para converter Book ↔ BookEntity. LogEmailNotification: implementa EmailNotification simulando e-mail via log.

6. Composition Rootconfig
O único ponto de conexão entre domínio e adaptadores

ApplicationBeans: instancia BooksService com new (Java puro), recebendo os adaptadores via @Inject CDI, e expõe cada instância como porta de entrada via @Produces. O domínio não tem nenhuma anotação CDI e não sabe que esse arquivo existe.

Regra de Dependência

Todas as setas de import apontam para dentro do hexágono. BookResource importa AddBookUseCase (domínio). PanacheBookRepository importa BookRepository (domínio). O domínio não importa nada dos adaptadores. Esta é a Inversão de Dependência (DIP) — o princípio SOLID que fundamenta toda a arquitetura.

Fluxo — POST /books

Vantagens e Quando Usar

Vantagem Contexto ideal Custo
Domínio 100% testável sem banco ou servidorLógica de negócio complexaMais arquivos e interfaces
Troca de tecnologia sem reescrita do domínioMúltiplos canais (REST + CLI + eventos)Curva de aprendizado inicial
Fronteiras explícitas entre módulosTimes grandes e projetos de longo prazoDisciplina da equipe necessária
Facilita DDD, CQRS e Event SourcingMicrosserviços com domínio ricoExcesso em CRUDs simples

Simulador Interativo

Acompanhe passo a passo o fluxo de uma requisição POST /books através da arquitetura hexagonal.

Passo 1/13

Arquivo:

    

Referências e Código

Repositório, execução e materiais de aprofundamento

Repositório do Projeto

pw2 — exemplos/hexagonal

Implementação completa em Java 25 + Quarkus 3.x com MySQL, JAX-RS, Hibernate Reactive (Panache), MapStruct e CDI.

github.com/rodrigoprestesmachado/pw2/tree/dev/exemplos/hexagonal

Stack de Tecnologias

Java 25Quarkus 3.xMySQL JAX-RSHibernate Reactive (Panache)MapStruct CDIMutiny (Reactive)Maven

Como Executar

Pré-requisitos

  • Java 21+ (recomendado Java 25 para corresponder ao projeto)
  • Maven 3.8+
  • Docker e Docker Compose (para o MySQL)
# 1. Clone o repositório git clone https://github.com/rodrigoprestesmachado/pw2.git cd pw2/exemplos/hexagonal # 2. Inicie o MySQL com Docker Compose docker compose up -d # 3. Execute em modo desenvolvimento (live reload ativo) ./mvnw quarkus:dev # A API estará disponível em: http://localhost:8080/books

Estrutura de Pastas

src/main/java/dev/ifrs/hexagonal/ ├── domain/ ← Java puro, zero framework │ ├── model/ │ │ └── Book.java ← Entidade + Book.of() (validação) │ ├── ports/ │ │ ├── in/ │ │ │ ├── AddBookUseCase.java ← Porta de entrada │ │ │ ├── ListBookUseCase.java │ │ │ ├── UpdateBookUseCase.java │ │ │ └── DeleteBookUseCase.java │ │ └── out/ │ │ ├── BookRepository.java ← Porta de saída (persistência) │ │ └── EmailNotification.java ← Porta de saída (notificação) │ └── service/ │ └── BooksService.java ← Use Case (Java puro, sem CDI) ├── adapters/ │ ├── in/rest/ │ │ ├── BookResource.java ← Adaptador JAX-RS (entrada) │ │ ├── BookRequest.java │ │ └── BookResponse.java │ ├── out/ │ │ ├── persistence/ │ │ │ ├── PanacheBookRepository.java ← Adaptador de persistência │ │ │ ├── BookEntity.java │ │ │ └── BookMapper.java ← MapStruct: Book ↔ BookEntity │ │ └── notification/ │ │ └── LogEmailNotification.java ← Adaptador de notificação │ └── config/ │ └── ApplicationBeans.java ← Composition Root (wiring CDI)

Materiais de Aprofundamento