Utiliser Spring Data R2DBC avec Azure Database pour PostgreSQL

Cet article décrit la création d’un exemple d’application qui utilise Spring Data R2DBC pour stocker et récupérer des informations dans une base de données Azure Database pour PostgreSQL. L’exemple utilise l’implémentation R2DBC pour PostgreSQL disponible dans le dépôt GitHub r2dbc-postgresql.

R2DBC permet d’utiliser des API réactives avec les bases de données relationnelles classiques. Vous pouvez l’utiliser avec Spring WebFlux pour créer des applications Spring Boot entièrement réactives qui utilisent des API non bloquantes. Il offre une meilleure scalabilité que l’approche classique « un thread par connexion ».

Prérequis

  • Client de ligne de commande PostgreSQL.

  • cURL ou un utilitaire HTTP similaire pour tester la fonctionnalité.

Voir l’exemple d’application

Dans cet article, vous allez coder un exemple d’application. Si vous souhaitez aller plus vite, cette application est déjà codée et disponible sur https://github.com/Azure-Samples/quickstart-spring-data-r2dbc-postgresql.

Préparer l’environnement de travail

Tout d’abord, configurez certaines variables d’environnement en exécutant les commandes suivantes :

export AZ_RESOURCE_GROUP=database-workshop
export AZ_DATABASE_SERVER_NAME=<YOUR_DATABASE_SERVER_NAME>
export AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
export AZ_LOCATION=<YOUR_AZURE_REGION>
export AZ_POSTGRESQL_ADMIN_USERNAME=spring
export AZ_POSTGRESQL_ADMIN_PASSWORD=<YOUR_POSTGRESQL_ADMIN_PASSWORD>
export AZ_POSTGRESQL_NON_ADMIN_USERNAME=nonspring
export AZ_POSTGRESQL_NON_ADMIN_PASSWORD=<YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>
export AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>

Remplacez les espaces réservés par les valeurs suivantes, qui sont utilisées dans cet article :

  • <YOUR_DATABASE_SERVER_NAME> : nom de votre serveur PostgreSQL, qui doit être unique dans Azure.
  • <YOUR_DATABASE_NAME> : Le nom de la base de données du serveur PostgreSQL, qui doit être unique dans Azure.
  • <YOUR_AZURE_REGION>: région Azure que vous allez utiliser. Vous pouvez utiliser eastus par défaut, mais nous vous recommandons de configurer une région plus proche de l’endroit où vous vivez. Vous pouvez voir la liste complète des régions disponibles à l’aide az account list-locationsde .
  • <YOUR_POSTGRESQL_ADMIN_PASSWORD> et <YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>: mot de passe de votre serveur de base de données PostgreSQL, qui doit comporter au moins huit caractères. Il doit contenir des caractères de trois des catégories suivantes : Lettres majuscules, lettres minuscules, chiffres (0-9) et caractères non alphanumériques (comme !, $, #, %, etc.).
  • <YOUR_LOCAL_IP_ADDRESS>: adresse IP de votre ordinateur local, à partir duquel vous exécuterez l’application Spring Boot. Un moyen pratique de le trouver est d’ouvrir whatismyip.akamai.com.

Ensuite, créez un groupe de ressources à l’aide de la commande suivante :

az group create \
    --name $AZ_RESOURCE_GROUP \
    --location $AZ_LOCATION \
    --output tsv

Créer une instance Azure Database pour PostgreSQL et configurer l’utilisateur administrateur

La première chose que vous allez créer est un serveur PostgreSQL managé avec un utilisateur administrateur.

Notes

Vous trouverez des informations plus détaillées sur la création de serveurs PostgreSQL dans l’article Création d’un serveur Azure Database pour PostgreSQL à l’aide du portail Azure.

az postgres flexible-server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME \
    --location $AZ_LOCATION \
    --admin-user $AZ_POSTGRESQL_ADMIN_USERNAME \
    --admin-password $AZ_POSTGRESQL_ADMIN_PASSWORD \
    --yes \
    --output tsv

Configurer une base de données PostgreSQL

Le serveur PostgreSQL que vous avez créé précédemment est vide. Créez une base de données avec la commande suivante.

az postgres flexible-server db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --database-name $AZ_DATABASE_NAME \
    --server-name $AZ_DATABASE_SERVER_NAME \
    --output tsv

Configurer une règle de pare-feu pour votre serveur PostgreSQL

Les instances Azure Database pour PostgreSQL sont sécurisées par défaut. Elles ont un pare-feu qui n’autorise aucune connexion entrante. Pour pouvoir utiliser notre base de données, vous devez ajouter une règle de pare-feu qui permet à l’adresse IP locale d’accéder au serveur de base de données.

Comme vous avez configuré votre adresse IP locale au début de cet article, vous pouvez ouvrir le pare-feu du serveur en exécutant la commande suivante :

az postgres flexible-server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME \
    --rule-name $AZ_DATABASE_SERVER_NAME-database-allow-local-ip \
    --start-ip-address $AZ_LOCAL_IP_ADDRESS \
    --end-ip-address $AZ_LOCAL_IP_ADDRESS \
    --output tsv

Si vous vous connectez à votre serveur PostgreSQL à partir de Sous-système Windows pour Linux (WSL) sur un ordinateur Windows, vous devez ajouter l’ID d’hôte WSL à votre pare-feu.

Obtenez l’adresse IP de votre ordinateur hôte en exécutant la commande suivante dans WSL :

cat /etc/resolv.conf

Copiez l’adresse IP suivant le terme nameserver, puis utilisez la commande suivante pour définir une variable d’environnement pour l’adresse IP de WSL :

export AZ_WSL_IP_ADDRESS=<the-copied-IP-address>

Ensuite, utilisez la commande suivante pour ouvrir le pare-feu du serveur sur votre application WSL :

az postgres flexible-server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME \
    --rule-name $AZ_DATABASE_SERVER_NAME-database-allow-local-ip \
    --start-ip-address $AZ_WSL_IP_ADDRESS \
    --end-ip-address $AZ_WSL_IP_ADDRESS \
    --output tsv

Créer un utilisateur non administrateur PostgreSQL et accorder des autorisations

Ensuite, créez un utilisateur non-administrateur et accordez toutes les autorisations à la base de données.

Notes

Vous pouvez lire des informations plus détaillées sur la création d’utilisateurs PostgreSQL dans Créer des utilisateurs dans Azure Database pour PostgreSQL.

Créez un script SQL appelé create_user.sql pour créer un utilisateur non administrateur. Ajoutez le contenu suivant et enregistrez-le localement :

cat << EOF > create_user.sql
CREATE ROLE "$AZ_POSTGRESQL_NON_ADMIN_USERNAME" WITH LOGIN PASSWORD '$AZ_POSTGRESQL_NON_ADMIN_PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE $AZ_DATABASE_NAME TO "$AZ_POSTGRESQL_NON_ADMIN_USERNAME";
EOF

Utilisez ensuite la commande suivante pour exécuter le script SQL pour créer l’utilisateur non administrateur Microsoft Entra :

psql "host=$AZ_DATABASE_SERVER_NAME.postgres.database.azure.com user=$AZ_POSTGRESQL_ADMIN_USERNAME dbname=$AZ_DATABASE_NAME port=5432 password=$AZ_POSTGRESQL_ADMIN_PASSWORD sslmode=require" < create_user.sql

Utilisez maintenant la commande suivante pour supprimer le fichier de script SQL temporaire :

rm create_user.sql

Créer une application Spring Boot réactive

Pour créer une application Spring Boot réactive, nous allons utiliser Spring Initializr. L’application que nous allons créer utilise :

  • Spring Boot 2.7.11.
  • Les dépendances suivantes : Spring React Web (également appelé Spring WebFlux) et Spring Data R2DBC.

Générer l’application à l’aide de Spring Initializr

Générez l’application sur la ligne de commande à l’aide de la commande suivante :

curl https://start.spring.io/starter.tgz -d dependencies=webflux,data-r2dbc -d baseDir=azure-database-workshop -d bootVersion=2.7.11 -d javaVersion=17 | tar -xzvf -

Ajouter l’implémentation du pilote PostgreSQL réactif

Ouvrez le fichier pom.xml du projet généré, puis ajoutez le pilote PostgreSQL réactif à partir du dépôt r2dbc-postgresql sur GitHub. Après la dépendance spring-boot-starter-webflux, ajoutez le texte suivant :

<dependency>
    <groupId>io.r2dbc</groupId>
    <artifactId>r2dbc-postgresql</artifactId>
    <version>0.8.12.RELEASE</version>
    <scope>runtime</scope>
</dependency>

Configurer Spring Boot pour qu’il utilise Azure Database pour PostgreSQL

Ouvrez le fichier src/main/resources/application.properties et ajoutez le texte suivant :

logging.level.org.springframework.data.r2dbc=DEBUG

spring.r2dbc.url=r2dbc:pool:postgres://$AZ_DATABASE_SERVER_NAME.postgres.database.azure.com:5432/$AZ_DATABASE_NAME
spring.r2dbc.username=nonspring
spring.r2dbc.password=$AZ_POSTGRESQL_NON_ADMIN_PASSWORD
spring.r2dbc.properties.sslMode=REQUIRE

Remplacez les $AZ_DATABASE_SERVER_NAMEvariables , $AZ_DATABASE_NAMEet $AZ_POSTGRESQL_NON_ADMIN_PASSWORD les variables par les valeurs que vous avez configurées au début de cet article.

Avertissement

Pour des raisons de sécurité, Azure Database pour PostgreSQL demande d’utiliser des connexions SSL. C’est pourquoi vous devez ajouter la propriété de configuration spring.r2dbc.properties.sslMode=REQUIRE, sinon le pilote R2DBC PostgreSQL tentera de se connecter à l’aide d’une connexion non sécurisée qui échouera.

Remarque

Pour de meilleures performances, la propriété spring.r2dbc.url est configurée de manière à utiliser un pool de connexions avec r2dbc-pool.

Vous devez maintenant être en mesure de démarrer votre application à l’aide du wrapper Maven fourni comme suit :

./mvnw spring-boot:run

Voici une capture d’écran de l’application s’exécutant pour la première fois :

Screenshot of the running application.

Créer le schéma de la base de données

Dans la classe principale DemoApplication, configurez un nouveau bean Spring qui créera le schéma de base de données, à l’aide du code suivant :

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.r2dbc.connectionfactory.init.ConnectionFactoryInitializer;
import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator;

import io.r2dbc.spi.ConnectionFactory;

@SpringBootApplication
public class DemoApplication {

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

    @Bean
    public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {
        ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
        initializer.setConnectionFactory(connectionFactory);
        ResourceDatabasePopulator populator = new ResourceDatabasePopulator(new ClassPathResource("schema.sql"));
        initializer.setDatabasePopulator(populator);
        return initializer;
    }
}

Ce bean Spring utilise un fichier nommé schema.sql. Créez ce fichier dans le dossier src/main/resources et ajoutez le texte suivant :

DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id SERIAL PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BOOLEAN);

Arrêtez l’application en cours d’exécution, puis redémarrez-la à l’aide de la commande suivante. L’application utilise désormais la base de données demo que vous avez créée précédemment et crée une table todo dans cette base de données.

./mvnw spring-boot:run

Voici une capture d’écran de la table de base de données en cours de création :

Screenshot of the creation of the database table.

Coder l’application

Ensuite, ajoutez le code Java qui utilisera R2DBC pour stocker et récupérer des données à partir de votre serveur PostgreSQL.

Créez une classe Java Todo parallèlement à la classe DemoApplication en utilisant le code suivant :

package com.example.demo;

import org.springframework.data.annotation.Id;

public class Todo {

    public Todo() {
    }

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

    @Id
    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;
    }
}

Cette classe est un modèle de domaine mappé sur la table todo que vous avez créée précédemment.

Pour gérer cette classe, vous avez besoin d’un référentiel. Définissez une nouvelle interface TodoRepository dans le même package en utilisant le code suivant :

package com.example.demo;

import org.springframework.data.repository.reactive.ReactiveCrudRepository;

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

Ce dépôt est un dépôt réactif géré par Spring Data R2DBC.

Terminez l’application en créant un contrôleur pouvant stocker et récupérer des données. Implémentez une classe TodoController dans le même package, puis ajoutez le code suivant :

package com.example.demo;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

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

    private final TodoRepository todoRepository;

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

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

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

Pour finir, arrêtez l’application et redémarrez-la à l’aide de la commande suivante :

./mvnw spring-boot:run

Test de l’application

Pour tester l’application, vous pouvez utiliser cURL.

Tout d’abord, créez un élément « todo » dans la base de données à l’aide de la commande suivante :

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

Cette commande doit retourner l’élément créé, comme illustré ici :

{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}

Ensuite, récupérez les données à l’aide d’une nouvelle requête cURL avec la commande suivante :

curl http://127.0.0.1:8080

Cette commande retourne la liste des éléments « todo », y compris celui que vous avez créé, comme illustré ici :

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

Voici une capture d’écran de ces requêtes cURL :

Screenshot of the cURL test.

Félicitations ! Vous avez créé une application Spring Boot entièrement réactive, qui utilise R2DBC pour stocker et récupérer des données à partir d’Azure Database pour PostgreSQL.

Nettoyer les ressources

Pour propre toutes les ressources utilisées pendant ce guide de démarrage rapide, supprimez le groupe de ressources à l’aide de la commande suivante :

az group delete \
    --name $AZ_RESOURCE_GROUP \
    --yes

Étapes suivantes

Pour en savoir plus sur le déploiement d’une application Spring Data sur Azure Spring Apps et l’utilisation d’une identité managée, consultez Tutoriel : Déployer une application Spring sur Azure Spring Apps avec une connexion sans mot de passe à une base de données Azure.

Pour en savoir plus sur Spring et Azure, poursuivez vers le centre de documentation Spring sur Azure.

Voir aussi

Pour plus d’informations sur Spring Data R2DBC, consultez la documentation de référence de Spring.

Pour plus d’informations sur l’utilisation d’Azure avec Java, consultez Azure pour les développeurs Java et Utilisation d’Azure DevOps et Java.