Exercício – Criar recursos do Azure e um aplicativo Java Spring

Concluído

Nesta unidade, você criará um aplicativo Spring Boot básico. Você usará a CLI do Azure e um IDE (ambiente de desenvolvimento integrado) de sua escolha para editar o código. Use um terminal de sua preferência para executar o código.

Preparar o ambiente de trabalho

Configure algumas variáveis de ambiente usando os seguintes comandos:

AZ_RESOURCE_GROUP=azure-spring-workshop
AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
AZ_LOCATION=<YOUR_AZURE_REGION>
AZ_MYSQL_USERNAME=spring
AZ_MYSQL_PASSWORD=<YOUR_MYSQL_PASSWORD>
AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>

No código, substitua os espaços reservados pelos valores da tabela a seguir. Esses valores são usados em todo este módulo.

Variável Descrição
<YOUR_DATABASE_NAME> O nome do servidor MySQL. O nome deve ser exclusivo em todo o Azure.
<YOUR_AZURE_REGION> A região do Azure que você usará. Você pode usar eastus por padrão, mas é recomendável usar uma região perto de onde você mora. Para ver a lista completa de regiões disponíveis, insira az account list-locations
<YOUR_MYSQL_PASSWORD> A senha do servidor de banco de dados MySQL. A senha deve ter pelo menos oito caracteres. Os caracteres devem ser de três das seguintes categorias: Letras maiúsculas em inglês, letras minúsculas em inglês, números de 0 a 9 e caracteres não alfanuméricos (!, $, #,% e assim por diante).
<YOUR_LOCAL_IP_ADDRESS> O endereço IP do computador local em que você executará o aplicativo Spring Boot. Para encontrar o endereço IP, direcione o navegador para whatismyip.akamai.com.

Em seguida, crie um grupo de recursos:

az group create \
    --name $AZ_RESOURCE_GROUP \
    --location $AZ_LOCATION \
    | jq

Observação

Esse módulo usa a ferramenta jq, que é instalada por padrão no Azure Cloud Shell para exibir dados JSON e torná-los mais legíveis.

Se não quiser usar a ferramenta jq, você poderá remover com segurança a parte | jq de todos os comandos deste módulo.

Criar uma instância do Banco de Dados do Azure para MySQL

Agora você criará um servidor MySQL gerenciado.

Observação

Para saber mais sobre o Banco de dados do Azure para MySQL, no final deste módulo, acesse o link para a documentação relevante.

Execute o script a seguir para criar uma pequena instância do Banco de Dados do Azure para MySQL. O banco de dados tem 1 CPU e 2 GB de RAM.

az mysql server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME \
    --location $AZ_LOCATION \
    --sku-name B_Gen5_1 \
    --storage-size 5120 \
    --admin-user $AZ_MYSQL_USERNAME \
    --admin-password $AZ_MYSQL_PASSWORD \
    | jq

Esse script cria um servidor MySQL pequeno que usa as variáveis que você configurou anteriormente.

Configurar uma regra de firewall para o servidor MySQL

O Banco de Dados do Azure para MySQL é protegido por padrão. O firewall dele não permite conexões de entrada. Portanto, adicione uma regra de firewall que permita ao endereço IP local acessar o servidor de banco de dados.

Execute o seguinte comando para abrir o firewall do servidor:

az mysql server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_NAME-database-allow-local-ip \
    --server-name $AZ_DATABASE_NAME \
    --start-ip-address $AZ_LOCAL_IP_ADDRESS \
    --end-ip-address $AZ_LOCAL_IP_ADDRESS \
    | jq

Execute o seguinte comando para permitir o acesso ao firewall pelos recursos do Azure:

az mysql server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name allAzureIPs \
    --server-name $AZ_DATABASE_NAME \
    --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0 \
    | jq

Configurar um banco de dados MySQL

O servidor MySQL que você criou anteriormente está vazio. Ele não tem nenhum banco de dados que possa ser usado com o aplicativo Spring boot. Criar um banco de dados chamado demo:

az mysql db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name demo \
    --server-name $AZ_DATABASE_NAME \
    | jq

Gerar o aplicativo usando o Spring Initializr

O Spring Initializr é um aplicativo Web que gera uma estrutura de projeto Spring Boot para você. O Spring Initializr não gera códigos de aplicativo, mas fornece uma estrutura básica de projeto e uma especificação de build do Maven.

Você vai gerar um scaffold de aplicativo com três dependências: web, mysql e data-jpa. Observe que você não precisa especificar as dependências do Azure, pois executará o aplicativo localmente.

Em um prompt de comando, gere o aplicativo:

curl https://start.spring.io/starter.tgz -d type=maven-project -d dependencies=web,data-jpa,mysql -d baseDir=azure-spring-workshop -d bootVersion=3.1.5.RELEASE -d javaVersion=17 | tar -xzvf -

Configurar o Spring Boot para usar o Banco de Dados do Azure para MySQL

Abra o arquivo src/main/resources/application.properties e adicione algumas propriedades. Substitua as duas variáveis $AZ_DATABASE_NAME e a variável $AZ_MYSQL_PASSWORD pelos valores que você configurou anteriormente.

logging.level.org.hibernate.SQL=DEBUG

spring.datasource.url=jdbc:mysql://$AZ_DATABASE_NAME.mysql.database.azure.com:3306/demo?serverTimezone=UTC
spring.datasource.username=spring@$AZ_DATABASE_NAME
spring.datasource.password=$AZ_MYSQL_PASSWORD

spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop

Aviso

A propriedade de configuração spring.jpa.hibernate.ddl-auto=create-drop significa que o Spring Boot criará automaticamente um esquema de banco de dados na inicialização do aplicativo e tentará excluir o esquema de banco de dados quando for desligado. Essa propriedade é ótima para testes, mas não deve ser usada em produção.

Observação

Você acrescenta ?serverTimezone=UTC à propriedade de configuração spring.datasource.url. Essa configuração informará ao driver JDBC (Java Database Connectivity) para usar o formato de data UTC (Tempo Universal Coordenado) quando você se conectar ao banco de dados. Caso contrário, o servidor Java não usará o mesmo formato de data que o banco de dados, o que resultará em erro.

Agora, inicie seu aplicativo usando o wrapper Maven fornecido:

./mvnw spring-boot:run

Esta captura de tela mostra o aplicativo em execução pela primeira vez:

Screenshot showing the running application.

Codificar o aplicativo

Então, adicione o código Java a seguir. Ele usa a JPA (API de Persistência de Java) para armazenar e recuperar dados do servidor MySQL.

Você usará uma classe de entidade JPA para mapear um objeto Java Todo diretamente na tabela Todo do MySQL.

Ao lado da classe DemoApplication, crie uma classe de entidade Todo. Em seguida, adicione o seguinte código:

package com.example.demo;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Todo {

    public Todo() {
    }

    public Todo(String description, String details, boolean done) {
        this.description = description;
        this.details = details;
        this.done = done;
    }

    @Id
    @GeneratedValue
    private Long id;

    private String description;

    private String details;

    private boolean done;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDetails() {
        return details;
    }

    public void setDetails(String details) {
        this.details = details;
    }

    public boolean isDone() {
        return done;
    }

    public void setDone(boolean done) {
        this.done = done;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof Todo)) {
            return false;
        }
        return id != null && id.equals(((Todo) o).id);
    }

    @Override
    public int hashCode() {
        return 31;
    }
}

Essa classe é um modelo de domínio mapeado na tabela Todo. Ela será criada automaticamente pela JPA.

Para gerenciar essa classe, você precisará de um repositório. Defina uma nova interface TodoRepository no mesmo pacote:

package com.example.demo;

import org.springframework.data.jpa.repository.JpaRepository;

public interface TodoRepository extends JpaRepository<Todo, Long> {
}

Esse é um repositório JPA gerenciado pelo Spring Data JPA. Ao estender JpaRepository, você obtém vários métodos CRUD (Create, Read, Update e Delete) genéricos para o tipo. Portanto, você pode fazer coisas como salvar e excluir objetos Todo.

Finalize o aplicativo criando um RestController que possa publicar interfaces REST para armazenar e recuperar dados via HTTP. Implemente uma classe TodoController no mesmo pacote. Em seguida, adicione o seguinte código:

package com.example.demo;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/")
public class TodoController {

    private final TodoRepository todoRepository;

    public TodoController(TodoRepository todoRepository) {
        this.todoRepository = todoRepository;
    }

    @PostMapping("/")
    @ResponseStatus(HttpStatus.CREATED)
    public Todo createTodo(@RequestBody Todo todo) {
        return todoRepository.save(todo);
    }

    @GetMapping("/")
    public Iterable<Todo> getTodos() {
        return todoRepository.findAll();
    }
}

Por fim, interrompa o aplicativo e, em seguida, inicie-o novamente usando o seguinte comando:

./mvnw spring-boot:run

O aplicativo Spring Boot deverá ser iniciado e conectado ao seu banco de dados.

Esta captura de tela mostra o aplicativo se conectando ao banco de dados:

Screenshot showing the running application connecting to database.

Testar o aplicativo

Para testar o aplicativo, você pode usar cURL.

Primeiro, crie um item da lista de tarefas pendentes no banco de dados:

curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"description":"configuration","details":"congratulations, you have set up your Spring Boot application correctly!","done": "true"}' \
    http://127.0.0.1:8080

Este comando deve retornar o item criado:

{"id":1,"description":"configuration","details":"congratulations, you have set up your Spring Boot application correctly!","done":true}

Em seguida, recupere os dados usando uma nova solicitação cURL:

curl http://127.0.0.1:8080

Esse comando retorna a lista de itens de tarefas pendentes, incluindo o item que você criou:

[{"id":1,"description":"configuration","details":"congratulations, you have set up your Spring Boot application correctly!","done":true}]