Pular para conteúdo

b. Controller

A interface do microsserviço Account é definida no módulo account, que contém a definição da API e os objetos de transferência de dados (DTOs) do microsserviço Account.

O objetivo principal desta seção é criar os seguintes endpoints da API:

classDiagram
    namespace account {
        class AccountController {
            +create(AccountIn in): Void
            +findAll(): List<AccountOut>
            +delete(String id): Void
            +healthCheck(): Void
            +findById(String id): AccountOut
        }
        class AccountIn {
            -String name
            -String email
            -String password
        }
        class AccountOut {
            -String id
            -String name
            -String email
        }
    }

1. Repositório

  • a. No GitHub, crie um novo repositório para a interface Account. Exemplo: account.

  • b. Em seguida, clone esse repositório como um submódulo na sua máquina local. Para isso, execute os seguintes comandos na raiz do projeto:

    git submodule add <repository_url> api/account
    

Isso cria um novo diretório chamado account dentro do diretório api, que conterá o código da interface Account. A estrutura de diretórios resultante ficará assim:

📁 platform/
└── 📁 api/
    └── 📁 account/

2. Código

Para codificar esse módulo de interface, vamos usar o framework Spring Boot, por meio do Spring Initializr, em [https://start.spring.io/], uma ferramenta web que permite gerar um projeto Spring Boot com as dependências e configurações necessárias.

Spring Initializr
Spring Initializr

Observe:

  • Project: Maven
  • Language: Java
  • Spring Boot: 4.1.0 (versão estável no momento)
  • Group: store (o nome da empresa, por exemplo)
  • Artifact: account (o nome do microsserviço)
  • Package name: store.account
  • Packaging: Jar
  • Configuration: YAML
  • Java: 25 (versão LTS no momento)

Além disso, precisamos adicionar as seguintes dependências:

  • Lombok: uma biblioteca Java que ajuda a reduzir código repetitivo (boilerplate), gerando getters, setters, construtores e outros métodos comuns em tempo de compilação por meio de anotações.

  • OpenFeign: um cliente declarativo de serviços web que simplifica o envio de requisições HTTP para outros microsserviços. Ele permite definir interfaces para os nossos clientes de API e gera automaticamente a implementação em tempo de execução.

Depois, baixe o arquivo zip e extraia-o no diretório api/account. A estrutura de diretórios resultante ficará assim:

📁 api/
└── 📁 account/
    ├── 📁 src/
    │   ├── 📁 main/
    │   │   └── 📁 java/
    │   │       └── 📁 store/
    │   │           └── 📁 account/
    │   │               └──  AccountApplication.java
    │   └── 📁 resources/
    │       └── YAML application.yaml
    └──  pom.xml

Neste caso, a classe AccountApplication é inútil, já que este módulo serve apenas para a interface e não será executado como uma aplicação independente. Portanto, podemos excluir essa classe e o arquivo application.yaml. Também podemos excluir o diretório src/test, pois não vamos escrever testes para este módulo. Além disso, não precisamos do diretório src/main/resources, já que não vamos adicionar nenhum recurso a este módulo; portanto, podemos excluí-lo também. A estrutura de diretórios resultante ficará assim:

Agora é hora de codificar a interface, que consiste na classe AccountController, que define os endpoints da API do microsserviço Account, e nas classes AccountIn e AccountOut, que são os DTOs de entrada e de saída dos endpoints da API, respectivamente. A estrutura de diretórios resultante ficará assim:

📁 api/
└── 📁 account/
    ├── 📁 src/
    │   └── 📁 main/
    │       └── 📁 java/
    │           └── 📁 store/
    │               └── 📁 account/
    │                   ├──  AccountController.java
    │                   ├──  AccountIn.java
    │                   └──  AccountOut.java
    └──  pom.xml

Uma possível implementação das classes AccountController, AccountIn e AccountOut é mostrada abaixo:

Código-fonte

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>4.1.0</version>
    </parent>
    <groupId>store</groupId>
    <artifactId>account</artifactId>
    <version>1.0.0</version>

    <properties>
        <java.version>25</java.version>
        <spring-cloud.version>2025.1.3</spring-cloud.version>
        <maven.compiler.proc>full</maven.compiler.proc>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </path>
                    </annotationProcessorPaths>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <release>${java.version}</release>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
AccountController.java
package store.account;

import java.util.List;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

@FeignClient(
    name="account",
    url="http://account:8080"
)
public interface AccountController {

    @PostMapping("/accounts")
    public ResponseEntity<Void> create(
        @RequestBody AccountIn in
    );

    @GetMapping("/accounts")
    public ResponseEntity<List<AccountOut>> findAll();

    @DeleteMapping("/accounts/{id}")
    public ResponseEntity<Void> delete(
        @PathVariable String id
    );

    @GetMapping("/accounts/health-check")
    public ResponseEntity<Void> healthCheck();

    @GetMapping("/accounts/{id}")
    public ResponseEntity<AccountOut> findById(
        @PathVariable String id
    );

}
AccountIn.java
package store.account;

import lombok.Builder;
import lombok.experimental.Accessors;

@Builder
@Accessors(fluent = true)
public record AccountIn(

    String name,
    String email,
    String password

) {

}
AccountOut.java
package store.account;

import lombok.Builder;
import lombok.experimental.Accessors;

@Builder
@Accessors(fluent = true)
public record AccountOut(

    String id,
    String name,
    String email

) {

}

Os DTOs são records do Java com o @Builder do Lombok; o @Accessors(fluent = true) mantém os acessores sem o prefixo get (in.email(), e não in.getEmail()), o mesmo estilo usado pelas classes do account-service.

Mais um endpoint depois

No hands-on 3, esta interface ganha o POST /accounts/login, que o serviço de autenticação chama para conferir um email e uma senha.

3. Empacotar e instalar

Depois de codificar a interface, precisamos instalar o pacote no repositório Maven local, para que ele possa ser usado por outros módulos do projeto. Para isso, execute o seguinte comando na raiz do projeto:

mvn clean install

Pronto! A interface Account agora está pronta para ser usada por outros módulos do projeto.

Vamos para a próxima seção, na qual implementaremos o microsserviço Account usando a interface que acabamos de criar.

Serviço