Introdução

Neste tutorial, vamos explorar a construção de uma aplicação de microserviços utilizando a arquitetura Janus com o framework Spring Boot e orquestração via Kubernetes. A arquitetura Janus é projetada para gerenciar múltiplos serviços e suas interações de forma eficiente, proporcionando vantagens como escalabilidade, manutenção facilitada e melhor gerenciamento de APIs. Este guia é indicado para desenvolvedores que já possuem familiaridade com Java e Spring Boot, mas que buscam expandir suas habilidades em microserviços e na gestão de APIs em um ambiente Kubernetes. Vamos abordar desde a configuração do ambiente até a implementação real da aplicação, incluindo exemplos práticos e códigos que podem ser facilmente integrados em um projeto real.

Etapas

  1. Configuração do Ambiente de Desenvolvimento

    Certifique-se de que você possui o JDK (Java Development Kit) e o Maven instalados. Além disso, você precisará do Docker e do Kubernetes. Verifique as instalações executando os seguintes comandos:

    commands
    # Verifique as versões instaladas do JDK e Maven
    java -version
    mvn -version
    # Verifique a instalação do Docker
    docker --version
    # Verifique a instalação do Kubernetes
    kubectl version --client

  2. Criação do Projeto Spring Boot

    Utilize o Spring Initializr (https://start.spring.io/) para criar um novo projeto Spring Boot. Escolha as seguintes opções: **Project**: Maven, **Language**: Java, **Spring Boot**: última versão estável, **Packaging**: Jar, **Java**: 11 ou superior. Adicione as dependências: ‘Spring Web’, ‘Spring Boot DevTools’, ‘Spring Data JPA’, e ‘H2 Database’. Após gerar o projeto, faça o download e extraia 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.microservicos</groupId>
      <artifactId>microservicos-api</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <name>microservicos-api</name>
      <description>Aplicação 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 web para visualização dos dados.

    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 `Produto`

    Implemente a classe modelo `Produto` que representará os produtos na aplicação. Utilize anotações JPA para mapear a classe à tabela do banco de dados.

    Produto.java
    package com.example.microservicos.model;
    
    import javax.persistence.*;
    
    @Entity
    @Table(name = "produtos")
    public class Produto {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(nullable = false)
        private String nome;
    
        @Column(nullable = false)
        private Double preco;
    
        // Getters e Setters
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getNome() {
            return nome;
        }
    
        public void setNome(String nome) {
            this.nome = nome;
        }
    
        public Double getPreco() {
            return preco;
        }
    
        public void setPreco(Double preco) {
            this.preco = preco;
        }
    }

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

    Implemente a interface `ProdutoRepository`, que estende `JpaRepository` para gerenciamento dos dados de produtos.

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

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

    Crie a classe `ProdutoService`, que contém a lógica de negócios e utiliza o `ProdutoRepository` para interagir com o banco de dados.

    ProdutoService.java
    package com.example.microservicos.service;
    
    import com.example.microservicos.model.Produto;
    import com.example.microservicos.repository.ProdutoRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    import java.util.Optional;
    
    @Service
    public class ProdutoService {
        @Autowired
        private ProdutoRepository produtoRepository;
    
        public List<Produto> findAll() {
            return produtoRepository.findAll();
        }
    
        public Optional<Produto> findById(Long id) {
            return produtoRepository.findById(id);
        }
    
        public Produto save(Produto produto) {
            return produtoRepository.save(produto);
        }
    
        public Produto update(Long id, Produto produtoDetails) {
            Produto produto = produtoRepository.findById(id).orElseThrow(() -> new RuntimeException("Produto não encontrado"));
            produto.setNome(produtoDetails.getNome());
            produto.setPreco(produtoDetails.getPreco());
            return produtoRepository.save(produto);
        }
    
        public void deleteById(Long id) {
            produtoRepository.deleteById(id);
        }
    }

  7. Implementação do Controlador `ProdutoController`

    Crie a classe `ProdutoController` para expor os endpoints da API, permitindo operações CRUD de produtos.

    ProdutoController.java
    package com.example.microservicos.controller;
    
    import com.example.microservicos.model.Produto;
    import com.example.microservicos.service.ProdutoService;
    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/produtos")
    public class ProdutoController {
        @Autowired
        private ProdutoService produtoService;
    
        @GetMapping
        public List<Produto> getAllProdutos() {
            return produtoService.findAll();
        }
    
        @GetMapping("/{id}")
        public ResponseEntity<Produto> getProdutoById(@PathVariable Long id) {
            return produtoService.findById(id)
                    .map(ResponseEntity::ok)
                    .orElse(ResponseEntity.notFound().build());
        }
    
        @PostMapping
        public Produto createProduto(@RequestBody Produto produto) {
            return produtoService.save(produto);
        }
    
        @PutMapping("/{id}")
        public ResponseEntity<Produto> updateProduto(@PathVariable Long id, @RequestBody Produto produtoDetails) {
            return ResponseEntity.ok(produtoService.update(id, produtoDetails));
        }
    
        @DeleteMapping("/{id}")
        public ResponseEntity<Void> deleteProduto(@PathVariable Long id) {
            produtoService.deleteById(id);
            return ResponseEntity.noContent().build();
        }
    }

  8. Implementação de Testes Unitários

    Crie a classe de testes `ProdutoServiceTest` para validar a lógica de negócios da aplicação.

    ProdutoServiceTest.java
    package com.example.microservicos.service;
    
    import com.example.microservicos.model.Produto;
    import com.example.microservicos.repository.ProdutoRepository;
    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 ProdutoServiceTest {
        @InjectMocks
        private ProdutoService produtoService;
    
        @Mock
        private ProdutoRepository produtoRepository;
    
        @BeforeEach
        public void init() {
            MockitoAnnotations.openMocks(this);
        }
    
        @Test
        public void testFindAll() {
            Produto produto1 = new Produto();
            produto1.setId(1L);
            produto1.setNome("Produto 1");
            produto1.setPreco(10.0);
    
            Produto produto2 = new Produto();
            produto2.setId(2L);
            produto2.setNome("Produto 2");
            produto2.setPreco(20.0);
    
            when(produtoRepository.findAll()).thenReturn(Arrays.asList(produto1, produto2));
    
            List<Produto> produtos = produtoService.findAll();
            assertEquals(2, produtos.size());
            verify(produtoRepository, times(1)).findAll();
        }
    
        // Adicione testes para os métodos findById, save, update e deleteById
    }

  9. Preparação do Ambiente Kubernetes

    Crie um arquivo de configuração `deployment.yaml` para implementar seu microserviço no Kubernetes. O arquivo deve definir como a aplicação deve rodar no cluster Kubernetes.

    deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: microservicos-api
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: microservicos-api
      template:
        metadata:
          labels:
            app: microservicos-api
        spec:
          containers:
          - name: microservicos-api
            image: seu_usuario/microservicos-api:latest
            ports:
            - containerPort: 8080
    

  10. Implementação e Testes no Kubernetes

    Utilize o Kompose ou kubectl para converter e implementar seus serviços no Kubernetes. Teste a API utilizando ferramentas como Postman ou cURL após a execução no cluster.

    commands
    # Aplicar a configuração no Kubernetes
    kubectl apply -f deployment.yaml
    # Teste o endpoint da API criada
    curl -X GET http://localhost:8080/api/produtos

    curl_examples
    # Listar todos os produtos
    curl -X GET http://localhost:8080/api/produtos
    # Criar um novo produto
    curl -X POST -H "Content-Type: application/json" -d '{"nome":"Novo Produto", "preco":99.99}' http://localhost:8080/api/produtos

Conclusão

Neste tutorial, cobrimos a construção de uma aplicação de microserviços utilizando a arquitetura Janus com Spring Boot e gerenciamento de APIs via Kubernetes. Aprendemos a configurar o ambiente de desenvolvimento, a criar entidades, repositórios, serviços e controladores, assim como a implementar e testar a aplicação. Com esse conhecimento, você está preparado para desenvolver e gerenciar suas próprias aplicações de microserviços no Kubernetes, explorando os conceitos avançados da arquitetura Janus e otimizando a gestão de APIs em suas futuras aplicações.

Hashtags

#Microserviços #SpringBoot #Kubernetes #ArquiteturaJanus #APIs #DesenvolvimentoDeSoftware