Introdução

Nos últimos anos, o desenvolvimento de aplicações baseadas em microserviços tem se tornado uma abordagem popular para construção de sistemas escaláveis e manuteníveis. O Mercury surge como uma proposta promissora para facilitar a construção desses serviços. Este tutorial tem como objetivo explorar os principais frameworks e ferramentas disponíveis no ecossistema Java, com ênfase no uso do Spring Boot. Vamos abordar a criação de uma aplicação de microserviços do zero, incluindo desde a definição do projeto até os testes unitários, promovendo um entendimento profundo dos conceitos e boas práticas no desenvolvimento com Java. Se você está pronto para criar aplicações robustas e eficientes, este guia prático é para você!

Etapas

  1. Configuração do Ambiente de Desenvolvimento

    Certifique-se de que o JDK e o Maven estão instalados em sua máquina. Use os comandos `java -version` e `mvn -version` para verificar as versões instaladas. Caso não tenha, siga as orientações de instalação do Java e Maven em seus sites oficiais.

    commands
    # Verificar as versões instaladas
    java -version
    mvn -version

  2. Criação do Projeto Spring Boot

    Utilize o Spring Initializr para criar um novo projeto. Configure-o com as opções: **Project**: Maven, **Language**: Java, **Spring Boot**: versão mais recente, **Packaging**: Jar, **Java**: 11 ou superior. Adicione as dependências ‘Spring Web’, ‘Spring Data JPA’, ‘H2 Database’ e ‘Spring Boot Starter Test’. Baixe e descompacte o projeto em seu ambiente.

    pom.xml
    <?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>
      <groupId>com.example</groupId>
      <artifactId>microservicos-example</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <name>microservicos-example</name>
      <description>Exemplo de Microserviços com Spring Boot</description>
      <properties>
        <java.version>11</java.version>
      </properties>
      <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
          <scope>runtime</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
        </dependency>
      </dependencies>
      <build>
        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
        </plugins>
      </build>
    </project>

  3. Configuração do Banco de Dados H2

    Edite o arquivo `application.properties` para configurar o banco de dados H2 e habilitar o console H2 para que você possa visualizar os dados no navegador.

    application.properties
    spring.h2.console.enabled=true
    spring.datasource.url=jdbc:h2:mem:testdb
    spring.datasource.driverClassName=org.h2.Driver
    spring.datasource.username=sa
    spring.datasource.password=
    spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
    spring.jpa.hibernate.ddl-auto=update

  4. Criação da Entidade `User`

    Implemente a classe modelo `User` que representará os usuários em nossa aplicação. Utilize anotações JPA para mapear a classe à tabela do banco de dados.

    User.java
    package com.example.microservicos.model;
    
    import javax.persistence.*;
    
    @Entity
    @Table(name = "users")
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(nullable = false)
        private String username;
    
        @Column(nullable = false)
        private String email;
    
        // Getters e Setters
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }

  5. Criação do Repositório `UserRepository`

    Implemente a interface `UserRepository` que estende `JpaRepository` para fornecer métodos CRUD para a entidade User.

    UserRepository.java
    package com.example.microservicos.repository;
    
    import com.example.microservicos.model.User;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface UserRepository extends JpaRepository<User, Long> {
        // Métodos adicionais podem ser definidos aqui
    }

  6. Implementação do Serviço `UserService`

    Crie a classe `UserService`, que contém a lógica de negócios e interage com o `UserRepository` para operar sobre a entidade User.

    UserService.java
    package com.example.microservicos.service;
    
    import com.example.microservicos.model.User;
    import com.example.microservicos.repository.UserRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    import java.util.Optional;
    
    @Service
    public class UserService {
        @Autowired
        private UserRepository userRepository;
    
        public List<User> findAll() {
            return userRepository.findAll();
        }
    
        public Optional<User> findById(Long id) {
            return userRepository.findById(id);
        }
    
        public User save(User user) {
            return userRepository.save(user);
        }
    
        public User update(Long id, User userDetails) {
            User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User não encontrado"));
            user.setUsername(userDetails.getUsername());
            user.setEmail(userDetails.getEmail());
            return userRepository.save(user);
        }
    
        public void deleteById(Long id) {
            userRepository.deleteById(id);
        }
    }

  7. Implementação do Controlador `UserController`

    Crie a classe `UserController` para expor os endpoints da API, permitindo operações CRUD para usuários.

    UserController.java
    package com.example.microservicos.controller;
    
    import com.example.microservicos.model.User;
    import com.example.microservicos.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController
    @RequestMapping("/api/users")
    public class UserController {
        @Autowired
        private UserService userService;
    
        @GetMapping
        public List<User> getAllUsers() {
            return userService.findAll();
        }
    
        @GetMapping("/{id}")
        public ResponseEntity<User> getUserById(@PathVariable Long id) {
            return userService.findById(id)
                    .map(ResponseEntity::ok)
                    .orElse(ResponseEntity.notFound().build());
        }
    
        @PostMapping
        public User createUser(@RequestBody User user) {
            return userService.save(user);
        }
    
        @PutMapping("/{id}")
        public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User userDetails) {
            return ResponseEntity.ok(userService.update(id, userDetails));
        }
    
        @DeleteMapping("/{id}")
        public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
            userService.deleteById(id);
            return ResponseEntity.noContent().build();
        }
    }

  8. Implementação de Testes Unitários

    Crie a classe de testes `UserServiceTest` para validar a lógica de negócios da aplicação, assegurando que todas as operações funcionam corretamente.

    UserServiceTest.java
    package com.example.microservicos.service;
    
    import com.example.microservicos.model.User;
    import com.example.microservicos.repository.UserRepository;
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    import org.mockito.MockitoAnnotations;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Optional;
    
    import static org.junit.jupiter.api.Assertions.*;
    import static org.mockito.Mockito.*;
    
    public class UserServiceTest {
        @InjectMocks
        private UserService userService;
    
        @Mock
        private UserRepository userRepository;
    
        @BeforeEach
        public void init() {
            MockitoAnnotations.openMocks(this);
        }
    
        @Test
        public void testFindAll() {
            User user1 = new User();
            user1.setId(1L);
            user1.setUsername("user1");
            user1.setEmail("user1@example.com");
    
            User user2 = new User();
            user2.setId(2L);
            user2.setUsername("user2");
            user2.setEmail("user2@example.com");
    
            when(userRepository.findAll()).thenReturn(Arrays.asList(user1, user2));
    
            List<User> users = userService.findAll();
            assertEquals(2, users.size());
            verify(userRepository, times(1)).findAll();
        }
    
        // Testes adicionais para os métodos findById, save, update e deleteById
    }

  9. Executando a Aplicação e Testes

    Compile e execute a aplicação usando Maven. Em seguida, utilize ferramentas como Postman ou cURL para testar os endpoints da API.

    commands
    # Compilar e executar a aplicação
    mvn spring-boot:run
    # Executar os testes unitários
    mvn test

    curl_examples
    # Listar todos os usuários
    curl -X GET http://localhost:8080/api/users
    # Criar um novo usuário
    curl -X POST -H "Content-Type: application/json" -d '{"username":"Novato", "email":"novato@example.com"}' http://localhost:8080/api/users

Conclusão

Neste tutorial, exploramos como desenvolver uma aplicação de microserviços utilizando Java e Spring Boot, abrangendo desde a configuração do ambiente até a implementação de testes unitários. Através de uma abordagem prática, você aprendeu a criar os componentes necessários para operar uma API RESTful, mantendo boas práticas de desenvolvimento. Com essas habilidades adquiridas, você poderá expandir suas aplicações e explorar outras áreas do desenvolvimento de microserviços, aumentando sua capacidade técnica e entregando produtos mais robustos.

Hashtags

#Java #SpringBoot #Microserviços #APIs #JUnit #DesenvolvimentoDeSoftware