Criando um micro-serviço com Spring Boot, Docker e MariaDB na Azure - Parte 1

bgsantos86

Bruno Gonzaga Santos

Posted on March 3, 2023

Criando um micro-serviço com Spring Boot, Docker e MariaDB na Azure - Parte 1

Nota: O código deste tutorial pode ser acessado via https://github.com/obrunogonzaga/Imovel

Você já pensou em criar um micro-serviço escalável e flexível? Se a resposta é sim, você está no lugar certo! Neste guia, vamos criar juntos um micro-serviço usando o poderoso ecossistema de tecnologias Spring Boot, Docker e MariaDB, tudo isso executado na nuvem da plataforma Azure. Acompanhe os passos a seguir e descubra como é fácil criar um aplicativo robusto baseado em micro-serviços.

Escopo do projeto

O objetivo deste projeto é criar o micro-serviço "Imovel" como parte do sistema "House Flipping", que gerencia as informações dos imóveis disponíveis para compra e venda. O micro-serviço, desenvolvido em Spring Boot e Java 17, se integra com um banco de dados MariaDB e permite aos usuários visualizar, buscar, salvar e criar/editar listas de imóveis para venda. Após ser desenvolvido e testado, o micro-serviço será implantado em um contêiner Docker na Azure, podendo ser integrado a outros micro-serviços e no sistema maior.

Pré-requisitos

Para seguir este tutorial e criar um micro-serviço de gerenciamento de imóveis usando Spring Boot e Java 17, configurar um banco de dados MariaDB em um contêiner Docker dentro da Azure, e implantar a aplicação em um contêiner Docker na Azure, você precisa ter conhecimentos básicos em programação em Java, desenvolvimento web e API REST, contêineres e sua utilização em desenvolvimento e implantação de aplicativos, SQL e bancos de dados relacionais como o MariaDB, além de familiaridade com o uso de um sistema de controle de versão, como o Git, para gerenciar o código-fonte da aplicação. Além disso, é necessário ter as seguintes ferramentas: Java 17, Maven, Docker, Azure CLI e MariaDB.

Objetivos

O objetivo desta parte é criar um micro-serviço chamado Imovel utilizando Spring Boot e Maven. Para isso, será necessário criar uma entidade "Imovel" com as características de um imóvel, um repositório para realizar as operações de CRUD na entidade, um serviço para implementar a lógica de negócios relacionada a imóveis e um controlador para expor os serviços REST da aplicação.

Configurando o banco de dados

Agora, vamos configurar o banco de dados MariaDB. Para isso, você pode criar um container Docker com a imagem oficial do MariaDB. Abra um terminal e execute o seguinte comando:

docker run -p 3306:3306 --name mariadb 
-e MYSQL_ROOT_PASSWORD=senha -d mariadb
Enter fullscreen mode Exit fullscreen mode

Esse comando irá baixar a imagem do MariaDB e criar um container com o nome "mariadb". O parâmetro "-p" indica que a porta 3306 do container será mapeada para a porta 3306 da máquina local. O parâmetro "-e" define a senha do usuário root do banco de dados.

Para verificar se o container foi criado com sucesso, execute o comando:

docker ps
Enter fullscreen mode Exit fullscreen mode

Você deverá ver a linha referente ao container do MariaDB com o status "Up".

Criando um projeto Spring Boot

Para criar um projeto Spring Boot para gerenciar imóveis, vamos utilizar o Spring Initializr. Acesse o site https://start.spring.io/ e preencha as informações do projeto, como o nome, o tipo de projeto e a versão do Spring Boot. Além disso, adicione as seguintes dependências:

  • Spring Web
  • Spring Data JPA
  • Spring Cloud Azure

Após preencher as informações do projeto, clique em "Generate" para baixar um arquivo ZIP contendo o projeto inicial.

Para gerenciar imóveis, vamos criar uma classe de Application que inicializa a aplicação Spring Boot. Por exemplo, crie a classe ImovelApplication no pacote br.com.houseflipping.imoveis:

package br.com.houseflipping.imoveis;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ImovelApplication {

    public static void main(String[] args) {
        SpringApplication.run(ImovelApplication.class, args);
    }

}
Enter fullscreen mode Exit fullscreen mode

A anotação @SpringBootApplication indica que esta é uma classe de configuração para o Spring Boot. Ela inclui as seguintes anotações:

  • @Configuration: indica que esta classe é uma classe de configuração Spring.
  • @EnableAutoConfiguration: permite que o Spring Boot configure automaticamente a aplicação com base nas dependências adicionadas ao projeto.
  • @ComponentScan: instrui o Spring a procurar e carregar todos os componentes anotados com @Component no pacote atual e em seus subpacotes. Note que a classe ImovelApplication é definida no pacote br.com.houseflipping.imoveis. Isso significa que todas as classes do projeto devem ser definidas dentro do pacote br.com.houseflipping.imoveis ou em subpacotes deste.

Por fim, adicione as seguintes dependências ao arquivo pom.xml para incluir as dependências do Spring Web, Spring Data JPA e Spring Cloud Azure:

<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.microsoft.azure</groupId>
        <artifactId>spring-cloud-azure-appconfiguration-config</artifactId>
        <version>2.4.1</version>
    </dependency>

    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-storage</artifactId>
        <version>8.6.6</version>
    </dependency>

    <dependency>
        <groupId>org.mariadb.jdbc</groupId>
        <artifactId>mariadb-java-client</artifactId>
        <version>2.7.2</version>
   </dependency>

</dependencies>
Enter fullscreen mode Exit fullscreen mode

Com essas dependências adicionadas, você estará pronto para começar a desenvolver o seu projeto para gerenciar imóveis utilizando o Spring Boot e a Azure.

Criando a entidade Imovel

Agora, vamos criar a entidade Imovel com os principais atributos de um imóvel. Crie uma nova classe chamada Imovel na pasta src/main/java com o seguinte código:

package br.com.houseflipping.entity;

import javax.persistence.*;

@Entity
@Table(name = "imoveis")
public class Imovel {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String tipo;

    private String endereco;

    private Integer numeroQuartos;

    private Integer numeroBanheiros;

    private Double area;

    private Double preco;

    // getters e setters
}
Enter fullscreen mode Exit fullscreen mode

Essa classe representa a tabela imoveis no banco de dados. As anotações @Entity e @Table definem a tabela correspondente e a anotação @Id define o campo id como chave primária com auto-incremento. Os demais atributos correspondem às colunas da tabela.

Os novos atributos incluem:

  • tipo: o tipo de imóvel (casa ou apartamento, por exemplo)
  • endereco: o endereço do imóvel
  • numeroQuartos: o número de quartos do imóvel
  • numeroBanheiros: o número de banheiros do imóvel
  • area: a área do imóvel em metros quadrados
  • preco: o preço do imóvel em reais

Esses atributos representam características físicas e financeiras do imóvel e podem ser utilizados para filtrar e buscar imóveis por diferentes critérios. Vamos adicionar outros atributos, como número de vagas na garagem, área externa, piscina, etc., de acordo com as necessidades do projeto.

Criando o repositório

O repositório é responsável por manipular as entidades em um banco de dados. No Spring Boot, é possível criar um repositório facilmente utilizando a interface JpaRepository do Spring Data JPA. Essa interface define operações básicas de CRUD (Create, Read, Update, Delete) para a entidade correspondente.

Para criar um repositório para a entidade Imovel, vamos criar uma nova interface chamada ImovelRepository. Essa interface deve estender a interface JpaRepository e informar o tipo da entidade e o tipo da chave primária. No nosso caso, a entidade é Imovel e a chave primária é do tipo "Long".

@Repository
public interface ImovelRepository extends JpaRepository<Imovel, Long> {
}
Enter fullscreen mode Exit fullscreen mode

A anotação @Repository indica que essa interface é um componente Spring e será gerenciada pelo contêiner. Com essa interface, já é possível utilizar as operações básicas de CRUD no banco de dados para a entidade Imovel. Por exemplo, para salvar um novo objeto Imovel, basta chamar o método "save" do repositório:

Imovel imovel = new Imovel();
imovel.setTipo("Casa");
imovel.setEndereco("Rua dos Bobos, 0");
imovel.setPreco(100000.0);

ImovelRepository imovelRepository = ...; // obter instância do repositório
Imovel imovelSalvo = imovelRepository.save(imovel);
Enter fullscreen mode Exit fullscreen mode

O método save retorna o objeto Imovel salvo no banco de dados, com o ID gerado automaticamente pelo banco (se a estratégia de geração de ID for "IDENTITY" ou "SEQUENCE").

Além das operações básicas de CRUD, é possível definir outras consultas personalizadas no repositório utilizando o recurso de Query Methods do Spring Data JPA. Por exemplo, para buscar todos os objetos "Imovel" cujo tipo seja "Casa", basta definir um método na interface com o nome adequado:

@Repository
public interface ImovelRepository extends JpaRepository<Imovel, Long> {
    List<Imovel> findByTipo(String tipo);
}
Enter fullscreen mode Exit fullscreen mode

Esse método retorna uma lista de objetos "Imovel" cujo atributo tipo seja igual ao parâmetro informado. Para utilizá-lo, basta chamar o método findByTipo do repositório:

ImovelRepository imovelRepository = ...; // obter instância do repositório
List<Imovel> imoveisCasa = imovelRepository.findByTipo("Casa");
Enter fullscreen mode Exit fullscreen mode

Para configurar o banco de dados MariaDB no Spring Boot, você pode adicionar as propriedades de configuração do banco de dados no arquivo application.properties. A seção de configuração do banco de dados pode ficar assim:

# Configurações do banco de dados
spring.datasource.url=jdbc:mariadb://localhost:3306/imoveis
spring.datasource.username=seu_usuario
spring.datasource.password=sua_senha
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver

# Configurações do Hibernate
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect
Enter fullscreen mode Exit fullscreen mode

Criando o serviço

O serviço é a camada responsável por orquestrar as chamadas ao repositório e implementar regras de negócio específicas. No nosso caso, o serviço será responsável por manipular os objetos Imovel e fazer a integração com o banco de dados.

Para criar o serviço, crie uma nova classe chamada ImovelService na pasta src/main/java com o seguinte código:

@Service
public class ImovelService {

    @Autowired
    private ImovelRepository imovelRepository;

    public Imovel salvar(Imovel imovel) {
        return imovelRepository.save(imovel);
    }

    public List<Imovel> listar() {
        return imovelRepository.findAll();
    }

    public Imovel buscarPorId(Long id) {
        Optional<Imovel> imovel = imovelRepository.findById(id);
        if (imovel.isPresent()) {
            return imovel.get();
        } else {
            throw new RuntimeException("Imóvel não encontrado");
        }
    }

    public void excluir(Long id) {
        imovelRepository.deleteById(id);
    }
}
Enter fullscreen mode Exit fullscreen mode

Nesse código, utilizamos a anotação @Service para indicar que essa classe é um componente Spring que será gerenciado pelo contêiner. Também utilizamos a anotação @Autowired para injetar o repositório ImovelRepository.

O método "salvar" recebe um objeto Imovel como parâmetro e utiliza o método save do repositório para salvar o objeto no banco de dados. O método listar utiliza o método findAll do repositório para listar todos os objetos Imovel no banco de dados.

O método buscarPorId recebe um ID como parâmetro e utiliza o método findById do repositório para buscar um objeto Imovel no banco de dados. Caso o objeto não seja encontrado, lançamos uma exceção personalizada.

O método excluir recebe um ID como parâmetro e utiliza o método deleteById do repositório para excluir o objeto correspondente no banco de dados.

Com o serviço implementado, agora podemos utilizá-lo no controlador para expor os endpoints REST.

Criando o controlador

Um controlador é responsável por mapear as requisições HTTP para métodos Java que processam essas requisições e retornam uma resposta. No nosso caso, vamos criar um controlador para expor os serviços REST da nossa aplicação.

Para criar um controlador em Spring Boot, você pode criar uma classe Java anotada com @RestController. Essa anotação indica que a classe é um controlador Spring que retorna objetos em formato JSON.

Além disso, você pode usar outras anotações para definir as URLs dos endpoints e os métodos HTTP suportados. Algumas anotações comuns são @RequestMapping, @PostMapping, @GetMapping, @PutMapping e @DeleteMapping.

Vamos criar um controlador para expor os serviços REST da nossa entidade Imovel. Abra uma nova classe chamada ImovelController na pasta src/main/java com o seguinte código:

@RestController
@RequestMapping("/imoveis")
public class ImovelController {
    @Autowired
    private ImovelService imovelService;

    @PostMapping
    public Imovel salvar(@RequestBody Imovel imovel) {
        return imovelService.salvar(imovel);
    }

    @GetMapping
    public List<Imovel> listar() {
        return imovelService.listar();
    }

    @GetMapping("/{id}")
    public Imovel buscarPorId(@PathVariable Long id) {
        return imovelService.buscarPorId(id);
    }

    @DeleteMapping("/{id}")
    public void excluir(@PathVariable Long id) {
        imovelService.excluir(id);
    }
}
Enter fullscreen mode Exit fullscreen mode

Vamos entender o que esse código faz:

  • A anotação @RestController indica que essa classe é um controlador Spring que retorna objetos em formato JSON.
  • A anotação @RequestMapping define o prefixo da URL para acessar os endpoints.
  • A anotação @Autowired injeta a dependência do serviço ImovelService criado anteriormente.
  • O método salvar é mapeado para a URL /imoveis com o método HTTP POST. Ele recebe um objeto Imovel no formato JSON no corpo da requisição e chama o método salvar do serviço ImovelService.
  • O método listar é mapeado para a URL /imoveis com o método HTTP GET. Ele chama o método "listar" do serviço ImovelService e retorna a lista de objetos Imovel no formato JSON.
  • O método buscarPorId é mapeado para a URL /imoveis/{id} com o método HTTP GET. Ele recebe um parâmetro id na URL e chama o método buscarPorId do serviço ImovelService para buscar o objeto Imovel correspondente. Se o objeto não for encontrado, retorna uma resposta HTTP com código 404.
  • O método excluir é mapeado para a URL /imoveis/{id} com o método HTTP DELETE. Ele recebe um parâmetro id na URL e chama o método excluir do serviço ImovelService para excluir o objeto Imovel correspondente. Se o objeto não for encontrado, retorna uma resposta HTTP com código 404.

Agora, podemos testar nossa aplicação acessando os endpoints criados por esse controlador. Para isso, abra um navegador ou um cliente REST (como o Postman) e acesse as URLs:

Por exemplo, para salvar um novo objeto Imovel via REST, você pode enviar um POST com o seguinte corpo:

{
  "tipo": "Apartamento",
  "endereco": "Rua A, 123",
  "numeroQuartos": 3,
  "numeroBanheiros": 2,
  "area": 75.0,
  "preco": 100000.0
}
Enter fullscreen mode Exit fullscreen mode

E receber uma resposta no formato JSON com o objeto salvo:

{
  "id": 1,
  "tipo": "Apartamento",
  "endereco": "Rua A, 123",
  "numeroQuartos": 3,
  "numeroBanheiros": 2,
  "area": 75.0,
  "preco": 100000.0
}
Enter fullscreen mode Exit fullscreen mode

Para listar todos os objetos Imovel, você pode enviar um GET para a URL /imoveis e receber uma resposta no formato JSON com uma lista de objetos Imovel.

Para buscar um objeto Imovel por ID, você pode enviar um GET para a URL /imoveis/{id} e receber uma resposta no formato JSON com o objeto correspondente. Se o objeto não for encontrado, você receberá uma resposta com código HTTP 404.

Para excluir um objeto Imovel por ID, você pode enviar um DELETE para a URL /imoveis/{id} e receber uma resposta vazia com código HTTP 204. Se o objeto não for encontrado, você receberá uma resposta com código HTTP 404.

Com esses endpoints, você pode manipular os objetos Imovel da sua aplicação por meio de uma API RESTful simples e eficiente.

Conclusão

Neste post, vimos como criar um microserviço para gerenciar imóveis utilizando o Spring Boot e a Azure. Começamos criando um projeto Spring Boot com as dependências necessárias para a nossa aplicação. Em seguida, criamos a classe Imovel para representar um imóvel e mapeamos essa classe para o banco de dados usando o Spring Data JPA.

Depois, criamos o controlador ImovelController para lidar com as requisições HTTP e acessar o repositório ImovelRepository para realizar as operações no banco de dados. Por fim, configuramos o banco de dados MariaDB no Spring Boot e vimos como criar um repositório utilizando a interface JpaRepository do Spring Data JPA.

Com a nossa aplicação funcionando corretamente, podemos agora fazer o deploy em um container Docker na Azure e deixar nosso microserviço disponível na nuvem para acesso externo. O que iremos fazer na parte 2 desse tutorial.

💖 💪 🙅 🚩
bgsantos86
Bruno Gonzaga Santos

Posted on March 3, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related