The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.
Edit this Page

Extensão para Spring Data REST

Embora os usuários sejam incentivados a usar o REST Data with Panache para a geração de endpoints de acesso a dados REST, o Quarkus fornece uma camada de compatibilidade para o Spring Data REST na forma da extensão spring-data-rest .

Pré-requisitos

Para concluir este guia, você precisa:

  • Cerca de 15 minutos

  • Um IDE

  • JDK 17+ instalado com JAVA_HOME configurado corretamente

  • Apache Maven 3.9.15

  • Opcionalmente, o Quarkus CLI se você quiser usá-lo

  • Opcionalmente, Mandrel ou GraalVM instalado e configurado apropriadamente se você quiser criar um executável nativo (ou Docker se você usar uma compilação de contêiner nativo)

Solução

Recomendamos que siga as instruções nas seções seguintes e crie a aplicação passo a passo. No entanto, você pode ir diretamente para o exemplo completo.

Clone o repositório Git: git clone https://github.com/quarkusio/quarkus-quickstarts.git, ou baixe um arquivo.

A solução está localizada no spring-data-rest-quickstart diretório.

Criar o projeto Maven

Primeiro, precisamos de um novo projeto. Crie um novo projeto com o seguinte comando:

CLI
quarkus create app org.acme:spring-data-rest-quickstart \
    --extension='spring-data-rest,rest-jackson,quarkus-jdbc-postgresql' \
    --no-code
cd spring-data-rest-quickstart

Para criar um projeto Gradle, adicione a opção --gradle ou --gradle-kotlin-dsl.

Para obter mais informações sobre como instalar e usar a CLI do Quarkus, consulte o guia Quarkus CLI.

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.35.2:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=spring-data-rest-quickstart \
    -Dextensions='spring-data-rest,rest-jackson,quarkus-jdbc-postgresql' \
    -DnoCode
cd spring-data-rest-quickstart

Para criar um projeto Gradle, adicione a opção '-DbuildTool=gradle' ou '-DbuildTool=gradle-kotlin-dsl'.

Para usuários do Windows:

  • Se estiver usando cmd, (não use barra invertida '\' e coloque tudo na mesma linha)

  • Se estiver usando o Powershell, envolva os parâmetros '-D' entre aspas duplas, por exemplo, '"-DprojectArtifactId=spring-data-rest-quickstart"'

Esse comando gera um projeto com a extensão spring-data-rest .

Se você já tem seu projeto Quarkus configurado, pode adicionar a extensão spring-data-rest ao projeto executando o seguinte comando no diretório base do projeto:

CLI
quarkus extension add spring-data-rest
Maven
./mvnw quarkus:add-extension -Dextensions='spring-data-rest'
Gradle
./gradlew addExtension --extensions='spring-data-rest'

Isto irá adicionar o seguinte trecho no seu arquivo de build:

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-spring-data-rest</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-spring-data-rest")

Além disso, a seguinte dependência precisa ser adicionada

Para os testes, você também precisará do REST Assured. Adicione-o ao arquivo de build:

pom.xml
<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <scope>test</scope>
</dependency>
build.gradle
testImplementation("io.rest-assured:rest-assured")

Observação: tanto resteasy-jackson quanto resteasy-jsonb são suportadas e podem ser usadas de forma intercambiável.

Definir a entidade

Ao longo deste guia, a seguinte Entidade JPA será utilizada:

package org.acme.spring.data.rest;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;

@Entity
public class Fruit {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    private String color;


    public Fruit() {
    }

    public Fruit(String name, String color) {
        this.name = name;
        this.color = color;
    }

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}

Configure as propriedades de acesso ao banco de dados

Adicione as seguintes propriedades a application.properties para configurar o acesso a uma instância local do PostgreSQL.

quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=quarkus_test
quarkus.datasource.password=quarkus_test
quarkus.datasource.jdbc.url=jdbc:postgresql:quarkus_test
quarkus.datasource.jdbc.max-size=8
quarkus.hibernate-orm.schema-management.strategy=drop-and-create

Esta configuração assume que o PostgreSQL será executado localmente.

Uma maneira muito fácil de fazer isso é usando o seguinte comando do Docker:

docker run -it --rm=true --name quarkus_test -e POSTGRES_USER=quarkus_test -e POSTGRES_PASSWORD=quarkus_test -e POSTGRES_DB=quarkus_test -p 5432:5432 docker.io/library/postgres:18

Se você planeja usar uma configuração diferente, altere o application.properties de acordo.

Preparar os dados

Para facilitar a demonstração de algumas funcionalidades do Spring Data REST no Quarkus, alguns dados de teste devem ser inseridos no banco de dados adicionando o seguinte conteúdo a um novo arquivo chamado src/main/resources/import.sql :

INSERT INTO fruit(id, name, color) VALUES (1, 'Cherry', 'Red');
INSERT INTO fruit(id, name, color) VALUES (2, 'Apple', 'Red');
INSERT INTO fruit(id, name, color) VALUES (3, 'Banana', 'Yellow');
INSERT INTO fruit(id, name, color) VALUES (4, 'Avocado', 'Green');
INSERT INTO fruit(id, name, color) VALUES (5, 'Strawberry', 'Red');

O Hibernate ORM executará essas queries na inicialização do aplicação.

Definir o repositório

Agora é hora de definir a repository que será usada para acessar Fruit. Seguindo o padrão típico do Spring Data, crie uma repository da seguinte forma:

package org.acme.spring.data.rest;

import org.springframework.data.repository.CrudRepository;

public interface FruitsRepository extends CrudRepository<Fruit, Long> {
}

O FruitsRepository acima estende o org.springframework.data.repository.CrudRepository do Spring Data, o que significa que todos os métodos deste último estão disponíveis para o FruitsRepository .

A extensão spring-data-jpa gerará uma implementação para essa repository. Em seguida, a extensão spring-data-rest gerará um recurso REST CRUD para ele.

Atualize o teste

Para testar os funcionalidades do FruitsRepository, atualize o conteúdo de FruitsRepositoryTest para:

package org.acme.spring.data.rest;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.core.IsNot.not;

@QuarkusTest
class FruitsRepositoryTest {

    @Test
    void testListAllFruits() {
        //List all, should have all 3 fruits the database has initially:
        given()
                .accept("application/json")
                .when().get("/fruits")
                .then()
                .statusCode(200)
                .body(
                        containsString("Cherry"),
                        containsString("Apple"),
                        containsString("Banana")
                );

        //Delete the Cherry:
        given()
                .when().delete("/fruits/1")
                .then()
                .statusCode(204);

        //List all, cherry should be missing now:
        given()
                .accept("application/json")
                .when().get("/fruits")
                .then()
                .statusCode(200)
                .body(
                        not(containsString("Cherry")),
                        containsString("Apple"),
                        containsString("Banana")
                );

        //Create a new Fruit
        given()
                .contentType("application/json")
                .accept("application/json")
                .body("{\"name\": \"Orange\", \"color\": \"Orange\"}")
                .when().post("/fruits")
                .then()
                .statusCode(201)
                .body(containsString("Orange"))
                .body("id", notNullValue())
                .extract().body().jsonPath().getString("id");

        //List all, Orange should be present now:
        given()
                .accept("application/json")
                .when().get("/fruits")
                .then()
                .statusCode(200)
                .body(
                        not(containsString("Cherry")),
                        containsString("Apple"),
                        containsString("Orange")
                );
    }
}

O teste pode ser facilmente executado com o comando:

Maven
./mvnw test
Gradle
./gradlew test

Empacote e execute a aplicação

O modo de desenvolvimento do Quarkus funciona com as repositories definidos da mesma forma que com qualquer outra extensão do Quarkus, aumentando significativamente sua produtividade durante o ciclo de desenvolvimento. A aplicação pode ser iniciada no modo de desenvolvimento normalmente usando:

CLI
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

Execute a aplicação como um binário nativo

Você pode criar um executável nativo seguindo as instruções do guia Construindo executáveis nativos .

Funcionalidades suportadas do Spring Data REST

O Quarkus atualmente suporta um subconjunto de funcionalidades do Spring Data REST, especificamente as mais úteis e mais comumente utilizadas.

O que é suportado

As seções a seguir descrevem os funcionalidades suportados mais importantes do Spring Data REST.

Geração automática de endpoints REST

Interfaces que estendem qualquer um das seguintes repositories do Spring Data têm endpoints REST gerados automaticamente:

  • org.springframework.data.repository.CrudRepository

  • org.springframework.data.repository.PagingAndSortingRepository

  • org.springframework.data.jpa.repository.JpaRepository

Os endpoints gerados a partir das repositories acima expõem cinco operações REST comuns:

  • GET /fruits - lista todas as entidades ou retorna uma página se PagingAndSortingRepository ou JpaRepository for utilizada.

  • GET /fruits/:id - retorna uma entidade por ID.

  • POST /fruits - cria uma nova entidade.

  • PUT /fruits/:id - atualiza uma entidade existente ou cria uma nova entidade com um ID especificado (se permitido pela definição da entidade).

  • DELETE /fruits/:id - exclui uma entidade por ID.

Existem dois tipos de dados suportados: application/json e application/hal+json. O primeiro é usado por padrão, mas é altamente recomendável especificar qual você prefere com um cabeçalho Accept.

Expondo muitas entidades

Se um banco de dados contém muitas entidades, pode não ser uma boa ideia retorná-las todas de uma vez. O PagingAndSortingRepository permite que a extensão spring-data-rest acesse os dados em partes.

Assim, você pode estender o PagingAndSortingRepository :

package org.acme.spring.data.rest;

import org.springframework.data.repository.PagingAndSortingRepository;

public interface FruitsRepository extends CrudRepository<Fruit, Long>, PagingAndSortingRepository<Fruit, Long> {
}

Agora o GET /fruits aceitará três novos parâmetros de consulta: sort, page e size.

Parâmetro de consulta Descrição Valor padrão Valores de exemplo

sort

Ordena as entidades que são retornadas pela operação de listagem

""

?sort=name (nome ascendente), ?sort=name,-color (nome ascendente e cor descendente)

page

Número de página índice zero. Um valor inválido é interpretado como 0.

0

0, 11, 100

size

Tamanho da página. O valor mínimo aceito é 1. Qualquer valor inferior é interpretado como 1.

20

1, 11, 100

Para respostas paginadas, o spring-data-rest também retorna um conjunto de cabeçalhos de links que podem ser usados para acessar outras páginas: primeira, anterior, próxima e última.

Além disso, em vez de estender tanto PagingAndSortingRepository quanto CrudRepository, você pode usar o JpaRepository, que é uma abstração de nível mais alto voltada para JPA. Como o JpaRepository já estende tanto PagingAndSortingRepository quanto CrudRepository, ele pode substituir o CrudRepository diretamente.

package org.acme.spring.data.rest;

import org.springframework.data.repository.PagingAndSortingRepository;

public interface FruitsRepository extends JpaRepository<Fruit, Long> {
}

Ajuste fino na geração de endpoints

Isso permite ao usuário especificar quais métodos devem ser expostos e qual caminho deve ser usado para acessá-los. O Spring Data REST fornece duas anotações que podem ser utilizadas: @RepositoryRestResource e @RestResource. A extensão spring-data-rest suporta os atributos exported, path e collectionResourceRel dessas anotações.

Suponha, por exemplo, que fruits repository deva ser acessível pelo caminho /my-fruits e permitir apenas a operação GET. Nesse caso, a FruitsRepository ficaria assim:

package org.acme.spring.data.rest;

import java.util.Optional;

import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.data.rest.core.annotation.RestResource;

@RepositoryRestResource(exported = false, path = "/my-fruits")
public interface FruitsRepository extends CrudRepository<Fruit, Long> {

    @RestResource(exported = true)
    Optional<Fruit> findById(Long id);

    @RestResource(exported = true)
    Iterable<Fruit> findAll();
}

spring-data-rest utiliza apenas um subconjunto dos métodos da repository para acesso a dados. É importante anotar o método correto para personalizar seu endpoint REST:

Operação REST CrudRepository PagingAndSortingRepository e JpaRepository

Obter por ID

Optional<T> findById(ID id)

Optional<T> findById(ID id)

List

Iterable<T> findAll()

Page<T> findAll(Pageable pageable)

Criar

<S extends T> S save(S entity)

<S extends T> S save(S entity)

Atualização

<S extends T> S save(S entity)

<S extends T> S save(S entity)

Excluir

void deleteById(ID id)

void deleteById(ID id)

Segurança de endpoints

Esta extensão usará automaticamente as anotações de segurança no pacote jakarta.annotation.security que estão definidas nas suas interfaces de recursos:

import jakarta.annotation.security.DenyAll;
import jakarta.annotation.security.RolesAllowed;

@DenyAll
public interface FruitResource extends CrudRepository<Fruit, Long> {
    @RolesAllowed("superuser")
    Iterable<Fruit> findAll();
}

Observe que essa funcionalidade é fornecida pela extensão REST Data with Panache que esta extensão utiliza internamente. Portanto, aplicação Spring Boot puras podem não se comportar da mesma forma.

O que atualmente não é suportado

  • Apenas os métodos da repository listados acima são suportados. Não há suporte para outros métodos padrão ou personalizados.

  • Apenas as propriedades de anotação exposed, path e collectionResourceRel são suportadas.

Nota técnica importante

Por favor, observe que o suporte do Spring no Quarkus não inicia um Spring Application Context nem executa nenhuma classe de infraestrutura do Spring. As classes e anotações do Spring são usadas apenas para leitura metadados e/ou são utilizadas como tipos de retorno ou tipos de parâmetro nos métodos do código do usuário.

Related content