Exercício – Criar recursos do Azure e uma aplicação Java do Spring

Concluído

Nesta unidade, irá criar uma aplicação básica do Spring Boot. Irá utilizar a CLI do Azure e um ambiente de desenvolvimento integrado (IDE) à sua escolha para editar o código. Utilize um terminal à sua escolha para executar o código.

Preparar o ambiente de trabalho

Configure algumas variáveis de ambiente ao utilizar 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 seu código, substitua os marcadores de posição pelos valores na tabela abaixo. Estes valores são utilizados ao longo deste módulo.

Variável Description
<YOUR_DATABASE_NAME> O nome do seu servidor MySQL. Deve ser um nome exclusivo no Azure.
<YOUR_AZURE_REGION> A região do Azure que irá utilizar. Pode utilizar a região eastus por predefinição, mas recomendamos que utilize uma região mais próxima do local onde vive. Para ver a lista completa de regiões disponíveis, introduza az account list-locations.
<YOUR_MYSQL_PASSWORD> A palavra-passe do seu servidor de bases de dados MySQL. A palavra-passe deve ter pelo menos oito carateres. 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 a partir do qual irá executar a aplicação do Spring Boot. Para encontrar o endereço IP, aponte o browser para o endereço whatismyip.akamai.com.

Depois, crie um grupo de recursos:

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

Nota

Este módulo utiliza a ferramenta jq, que está instalada por predefinição no Azure Cloud Shell, para apresentar dados JSON e torná-los mais legíveis.

Se não quiser utilizar a ferramenta jq, pode remover com segurança a parte | jq de todos os comandos neste módulo.

Criar uma instância da Base de Dados do Azure para MySQL

Agora, vai criar um servidor MySQL gerido.

Nota

Para saber mais sobre a Base de Dados do Azure para MySQL, siga a ligação para a documentação relevante no final deste módulo.

Execute o seguinte script para criar uma pequena instância da Base de Dados do Azure para MySQL. A base 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

Este script cria um pequeno servidor MySQL que utiliza as variáveis que configurou anteriormente.

Configurar uma regra de firewall para o servidor MySQL

A Base de Dados do Azure para MySQL está protegida por predefinição. A respetiva firewall não permite ligações de entrada. Por isso, adicione uma regra de firewall para permitir que o endereço IP local aceda ao servidor de bases de dados.

Execute o seguinte comando para abrir a 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 que os recursos do Azure acedam à firewall:

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 uma base de dados MySQL

O servidor MySQL que criou anteriormente está vazio. Não tem nenhuma base de dados que possa utilizar com a aplicação do Spring Boot. Crie uma nova base de dados chamada demo:

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

Gerar a aplicação com o Spring Initializr

O Spring Initializr é uma aplicação Web que gera automaticamente uma estrutura de projeto do Spring Boot. O Spring Initializr não gera código de aplicação, mas dá-lhe uma estrutura de projeto básica e uma especificação de compilação do Maven.

Vai gerar a estrutura da sua aplicação com três dependências: web, mysql e data-jpa. Não precisa de especificar dependências do Azure porque vai executar a sua aplicação localmente.

Numa linha de comandos, vai gerar a aplicação:

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 utilizar a Base de Dados do Azure para MySQL

Abra o ficheiro src/main/resources/application.properties e adicione algumas propriedades. Certifique-se de que substitui as duas variáveis $AZ_DATABASE_NAME e a variável $AZ_MYSQL_PASSWORD pelos valores que 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 base de dados no arranque da aplicação e tentará eliminar o esquema da base de dados no encerramento. Esta propriedade é útil para fins de teste, mas não deve ser utilizada na fase de produção!

Nota

Vai acrescentar ?serverTimezone=UTC à propriedade de configuração spring.datasource.url. Esta configuração indica ao controlador do Java Database Connectivity (JDBC) que utilize o formato de data UTC (Hora Universal Coordenada) quando ligar à base de dados. Caso contrário, o seu servidor Java não vai utilizar o mesmo formato de data que a base de dados, o que irá resultar num erro.

Agora, inicie a sua aplicação com o wrapper do Maven fornecido:

./mvnw spring-boot:run

Esta captura de ecrã mostra a aplicação em execução pela primeira vez:

Captura de ecrã a mostrar a aplicação em execução.

Codificar a aplicação

Em seguida, adicione o código Java abaixo. Este código utiliza a JPA (API de Persistência em Java) para armazenar e obter dados do seu servidor MySQL.

Irá utilizar uma classe de entidade JPA para mapear um objeto Todo Java diretamente à tabela Todo MySQL.

Junto à classe DemoApplication, crie uma nova 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;
    }
}

Esta classe é um modelo de domínio mapeado na tabela Todo. Será automaticamente criada pela JPA.

Para gerir essa classe, precisa 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> {
}

Este é um repositório JPA gerido pelo Spring Data JPA. Ao expandir o JpaRepository, obtém vários métodos genéricos de criação, leitura, atualização e eliminação (CRUD) para o seu tipo. Assim, pode realizar ações como guardar e eliminar objetos Todo.

Conclua a aplicação ao criar um RestController que consiga publicar interfaces REST para armazenar e obter dados através de 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 último, pare a aplicação e inicie-a novamente com o seguinte comando:

./mvnw spring-boot:run

A aplicação do Spring Boot deverá ser iniciada e ligada à base de dados.

Esta captura de ecrã mostra a aplicação a ligar-se à base de dados:

Captura de ecrã a mostrar a aplicação em execução a ligar-se à base de dados.

Testar a aplicação

Para testar a aplicação, pode utilizar o cURL.

Comece por criar um novo item de lista de tarefas na base 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 deverá devolver o item criado:

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

Depois, obtenha os dados ao utilizar um novo pedido de cURL:

curl http://127.0.0.1:8080

Este comando devolve a lista de itens de tarefas, incluindo o item que criou:

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