Exercício - Criar um aplicativo Quarkus
Nesta unidade, você cria um aplicativo Quarkus básico. Você usa o Maven para inicializar o aplicativo e um ambiente de desenvolvimento integrado (IDE) de sua escolha para editar o código. Utilize um terminal à sua escolha para executar o código. Você usa o Docker para iniciar um banco de dados PostgreSQL local para que possa executar e testar o aplicativo localmente.
Gerar o aplicativo Quarkus usando o Maven
Há várias maneiras de gerar uma estrutura de projeto Quarkus. Você pode usar a interface web do Quarkus, um plug-in IDE ou o plug-in do Quarkus Maven. Vamos usar o plugin Maven para gerar a estrutura do projeto.
Você gera seu aplicativo com várias dependências:
- A
resteasy
dependência para expor um ponto de extremidade REST - A
jackson
dependência para serializar e desserializar JSON - A
hibernate
dependência para interagir com o banco de dados - A
postgresql
dependência para se conectar ao banco de dados PostgreSQL - A
docker
dependência para criar uma imagem do Docker
Você não precisa especificar as dependências do Azure porque primeiro executa seu aplicativo localmente e, em seguida, implanta uma versão em contêiner dele nos Aplicativos de Contêiner do Azure.
Em um prompt de comando, gere o aplicativo de tarefas:
mvn -U io.quarkus:quarkus-maven-plugin:3.7.3:create \
-DplatformVersion=3.7.3 \
-DprojectGroupId=com.example.demo \
-DprojectArtifactId=todo \
-DclassName="com.example.demo.TodoResource" \
-Dpath="/api/todos" \
-DjavaVersion=17 \
-Dextensions="resteasy-jackson, hibernate-orm-panache, jdbc-postgresql, docker"
Este comando cria um novo projeto Quarkus. Ele gera uma estrutura de diretórios Maven (src/main/java
para código-fonte e src/test/java
para testes). Ele cria algumas classes Java, alguns testes e alguns Dockerfiles. Ele também gera um arquivo pom.xml com todas as dependências necessárias (Hibernate, RESTEasy, Jackson, PostgreSQL e Docker):
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-panache</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-container-image-docker</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Nota
Todas as dependências no arquivo pom.xml são definidas na lista técnica do Quarkus (lista de materiais). io.quarkus.platform:quarkus-bom
Codificar a aplicação
Em seguida, renomeie a classe MyEntity.java gerada para Todo.java (localizada na mesma pasta que o arquivo TodoResource.java). Substitua o código existente pelo seguinte código Java. Ele usa Java Persistence API (jakarta.persistence.*
pacote) para armazenar e recuperar dados do seu servidor PostgreSQL. Ele também usa Hibernate ORM com Panache (herdando de ) para simplificar a camada de io.quarkus.hibernate.orm.panache.PanacheEntity
persistência.
Você usa uma entidade JPA (@Entity
) para mapear o objeto Java Todo
diretamente para a tabela PostgreSQL Todo
. Em seguida, o TodoResource
ponto de extremidade REST cria uma nova Todo
classe de entidade e a persiste. Esta classe é um modelo de domínio mapeado na tabela Todo
. A tabela é criada automaticamente pela JPA.
A extensão PanacheEntity
fornece uma série de métodos genéricos de criação, leitura, atualização e exclusão (CRUD) para seu tipo. Assim, você pode fazer coisas como salvar e excluir Todo
objetos em apenas uma linha de código Java.
Adicione o seguinte código à Todo
entidade:
package com.example.demo;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.Entity;
import java.time.Instant;
@Entity
public class Todo extends PanacheEntity {
public String description;
public String details;
public boolean done;
public Instant createdAt = Instant.now();
@Override
public String toString() {
return "Todo{" +
"id=" + id + '\'' +
", description='" + description + '\'' +
", details='" + details + '\'' +
", done=" + done +
", createdAt=" + createdAt +
'}';
}
}
Para gerenciar essa classe, atualize o TodoResource
para que ele possa publicar interfaces REST para armazenar e recuperar dados usando HTTP. Abra a TodoResource
classe e substitua o código pelo seguinte:
package com.example.demo;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;
import jakarta.ws.rs.core.UriInfo;
import org.jboss.logging.Logger;
import java.util.List;
@Path("/api/todos")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public class TodoResource {
@Inject
Logger logger;
@Inject
UriInfo uriInfo;
@POST
@Transactional
public Response createTodo(Todo todo) {
logger.info("Creating todo: " + todo);
Todo.persist(todo);
UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder().path(todo.id.toString());
return Response.created(uriBuilder.build()).entity(todo).build();
}
@GET
public List<Todo> getTodos() {
logger.info("Getting all todos");
return Todo.listAll();
}
}
Executar a aplicação
Quando você executa o aplicativo no modo de desenvolvimento, o Docker precisa estar em execução. Isso porque o Quarkus deteta que você precisa de um banco de dados PostgreSQL (por causa da dependência quarkus-jdbc-postgresql
do PostgreSQL declarada no arquivo pom.xml), baixa a imagem do Docker PostgreSQL e inicia um contêiner com o banco de dados. Em seguida, ele cria automaticamente a Todo
tabela no banco de dados.
Verifique se o Docker está sendo executado localmente em sua máquina e execute o aplicativo de tarefas usando este comando:
cd todo
./mvnw quarkus:dev # On Mac or Linux
mvnw.cmd quarkus:dev # On Windows
O aplicativo Quarkus deve iniciar e se conectar ao seu banco de dados. Deverá ver o seguinte resultado:
[io.qua.dat.dep.dev.DevServicesDatasourceProcessor] Dev Services for the default datasource (postgresql) started.
[io.qua.hib.orm.dep.HibernateOrmProcessor] Setting quarkus.hibernate-orm.database.generation=drop-and-create to initialize Dev Services managed database
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) SQL Warning Code: 0, SQLState: 00000
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) table "todo" does not exist, skipping
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) SQL Warning Code: 0, SQLState: 00000
[org.hib.eng.jdb.spi.SqlExceptionHelper] (JPA Startup Thread) sequence "hibernate_sequence" does not exist, skipping
[io.quarkus] (Quarkus Main Thread) todo 1.0.0-SNAPSHOT on JVM (powered by Quarkus) started in 4.381s. Listening on: http://localhost:8080
[io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
[io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, jdbc-postgresql, narayana-jta, resteasy, resteasy-jackson, smallrye-context-propagation, vertx]
--
Tests paused
Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>
Pode utilizar o cURL para testar a aplicação.
Em um terminal separado, crie um novo item de tarefa no banco de dados com o seguinte comando. Você deve ver o log no console do Quarkus:
curl --header "Content-Type: application/json" \
--request POST \
--data '{"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done": "true"}' \
http://127.0.0.1:8080/api/todos
Este comando deve retornar o item criado (com um identificador):
{"id":1,"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done":true,"createdAt":"2022-12-30T15:17:20.280203Z"}
Crie uma segunda tarefa usando o seguinte comando cURL:
curl --header "Content-Type: application/json" \
--request POST \
--data '{"description":"Take Azure Container Apps MS Learn","details":"Take the ACA Learn module","done": "false"}' \
http://127.0.0.1:8080/api/todos
Em seguida, recupere os dados usando uma nova solicitação cURL:
curl http://127.0.0.1:8080/api/todos
Este comando retorna a lista de itens pendentes, incluindo os itens que você criou:
[
{"id":1,"description":"Take Quarkus MS Learn","details":"Take the MS Learn on deploying Quarkus to Azure Container Apps","done":true},
{"id":2,"description":"Take Azure Container Apps MS Learn","details":"Take the ACA Learn module","done":false}
]
Testar a aplicação
Para testar o aplicativo, você pode usar a classe existente TodoResourceTest
. Ele precisa testar o ponto de extremidade REST. Para testar o ponto de extremidade, ele usa RESTAssured. Substitua o código na TodoResourceTest
classe com o seguinte código:
package com.example.demo;
import io.quarkus.test.junit.QuarkusTest;
import static io.restassured.RestAssured.given;
import static jakarta.ws.rs.core.HttpHeaders.CONTENT_TYPE;
import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import org.junit.jupiter.api.Test;
@QuarkusTest
class TodoResourceTest {
@Test
void shouldGetAllTodos() {
given()
.when().get("/api/todos")
.then()
.statusCode(200);
}
@Test
void shouldCreateATodo() {
Todo todo = new Todo();
todo.description = "Take Quarkus MS Learn";
todo.details = "Take the MS Learn on deploying Quarkus to Azure Container Apps";
todo.done = true;
given().body(todo)
.header(CONTENT_TYPE, APPLICATION_JSON)
.when().post("/api/todos")
.then()
.statusCode(201);
}
}
Quando você testa o aplicativo, o Docker Desktop precisa estar em execução porque o Quarkus deteta que ele precisa do banco de dados PostgreSQL para teste. Teste o aplicativo usando este comando:
./mvnw clean test # On Mac or Linux
mvnw.cmd clean test # On Windows
Deverá ver uma saída semelhante à seguinte:
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.example.demo.TodoResourceTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------