Spring Boot : services web GraphQL
Achref El Mouelhi
Docteur de l’université d’Aix-Marseille
Chercheur en programmation par contrainte (IA)
Ingénieur en génie logiciel
[Link]@[Link]
H & H: Research and Training 1 / 38
Plan
1 Introduction
2 Création et préparation du projet avec Spring Boot
3 GraphQL : query
@QueryMapping
type de [Link]
@Argument
4 GraphQL : mutation
@MutationMapping
input de [Link]
5 Variables
Exemple avec Mutation
Exemple avec Query
H & H: Research and Training 2 / 38
Introduction
Spring Boot
Service web (WS pour Web Service) ?
Un programme (ensemble de fonctionnalités exposées en temps réel et sans
intervention humaine)
H I ©
Accessible via internet, Intranet, réseaux privés...
U EL
O
LM
Indépendant de tout système d’exploitation
r e f E
Indépendant de tout langage de programmation
ch
©A
Utilisant un système standard d’échange (XML ou JSON), ces messages sont
généralement transportés par des protocoles internet connus HTTP (ou autres
comme FTP, SMTP...)
Pouvant communiquer avec d’autres WS
H & H: Research and Training 3 / 38
Introduction
Spring Boot
Les WS peuvent utiliser les technologies web suivantes :
HTTP (Hypertext Transfer Protocol) : le protocole, connu, utilisé par le
World Wide Web et inventé par Roy Fiedling.
H I ©
EL
REST (Representational State Transfer) : une architecture de services Web,
U
créée aussi par Roy Fielding en 2000 dans sa thèse de doctorat.
O
M
L : unla transmission
SOAP (Simple object Access Protocol)
r e E
ensuite standarisé par W3C,fpermettant
protocole, défini par Microsoft et IBM
de messages entre
h
Ac Description Language) : est un langage de description de
objets distants (physiquement distribués).
WSDL (Web © Services
service web utilisant le format XML (standardisé par le W3C depuis 2007).
UDDI (Universal Description, Discovery and Integration) : un annuaire de WS.
H & H: Research and Training 4 / 38
Introduction
Spring Boot
GraphQL
Langage de requête
H I ©
EL 2015
Créé par Facebook en 2012 puis rendu open-source depuis
U
Respectant l’architecture client/serveurMO
Alternative aux API RESTef
E L
Permettant auxA
chr
© clients de spécifier exactement quelles données ils souhaitent
recevoir dans une seule requête ⇒ réduction de sur-fetching/sous-fetching de
données
H & H: Research and Training 5 / 38
Création et préparation du projet avec Spring Boot
Spring Boot
Création de projet Spring Boot
Aller dans File > New > Other
Chercher Spring, dans Spring Boot sélectionner Spring Starter Project et cli-
quer sur Next >
H I ©
Saisir
UEL
spring-graphql dans Name,
O
[Link] dans Group,
f E LM
ch r e
spring-graphql dans Artifact
©A
[Link] dans Package
Cliquer sur Next
Chercher et cocher les cases correspondantes aux Spring Data JPA, MySQL Driver,
Lombok, Spring Web, Spring for GraphQL et Spring Boot DevTools
Cliquer sur Next puis sur Finish
H & H: Research and Training 6 / 38
Création et préparation du projet avec Spring Boot
Spring Boot
Explication
Le package contenant le point d’entrée de notre application (la classe contenant le
puclic static void main) est [Link]
H I ©
Tous les autres packages dao, model... doivent être dans le package demo.
UEL
O
f E LM
ch r e
©A
H & H: Research and Training 7 / 38
Création et préparation du projet avec Spring Boot
Spring Boot
Explication
Le package contenant le point d’entrée de notre application (la classe contenant le
puclic static void main) est [Link]
H I ©
Tous les autres packages dao, model... doivent être dans le package demo.
UEL
O
f E LM
Pour la suite, nous considérons
ch r e
©A
une entité Personne à définir dans [Link]
une interface DAO PersonneRepository à créer dans [Link]
un contrôleur PersonneGraphQlController à créer dans
[Link]
H & H: Research and Training 7 / 38
Création et préparation du projet avec Spring Boot
Spring Boot & REST
Créons une entité Personne dans [Link]
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@RequiredArgsConstructor
H I ©
public class Personne {
UEL
O
LM
@Id
private Long num;
r e E
@GeneratedValue(strategy = [Link])
f
@NonNull
ch
©A
private String nom;
@NonNull
private String prenom;
@NonNull
@ManyToMany(cascade = [Link])
private List<Adresse> adresses;
}
H & H: Research and Training 8 / 38
Création et préparation du projet avec Spring Boot
Spring Boot & REST
Et une entité Adresse
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@RequiredArgsConstructor
H I ©
EL
public class Adresse {
@Id
O U
@GeneratedValue(strategy = [Link])
private Long id;
f E LM
@NonNull
ch r e
©A
private String rue;
@NonNull
private String codePostal;
@NonNull
private String ville;
@ManyToMany(mappedBy = "adresses")
private List<Personne> personnes = new ArrayList<Personne>();
}
H & H: Research and Training 9 / 38
Création et préparation du projet avec Spring Boot
Spring Boot & REST
Préparons notre interface DAO PersonneRepository
package [Link];
import [Link];
import [Link];
H I
public interface PersonneRepository extends JpaRepository<Personne, Long> {©
}
UEL
O
f E LM
ch r e
©A
H & H: Research and Training 10 / 38
Création et préparation du projet avec Spring Boot
Spring Boot & REST
Préparons notre interface DAO PersonneRepository
package [Link];
import [Link];
import [Link];
H I
public interface PersonneRepository extends JpaRepository<Personne, Long> {©
}
UEL
O
f E LM
Et une interface AdresseRepositoty
ch r e
©A
package [Link];
import [Link];
import [Link];
public interface AdresseRepositoty extends JpaRepository<Adresse, Long> {
H & H: Research and Training 10 / 38
Création et préparation du projet avec Spring Boot
Spring Boot
Dans [Link], ajoutons les données permettant la connexion à la base de données et la
configuration de Hibernate
[Link]=root
H I ©
[Link]=jdbc:mysql://localhost:3306/cours_graphql?createDatabaseIfNotExist=true
EL
[Link]=
U
[Link]-auto=create-drop
[Link]-sql=true
O
LM
[Link]=[Link]
r e f E
ch
©A
H & H: Research and Training 11 / 38
Création et préparation du projet avec Spring Boot
Spring Boot
Dans [Link], ajoutons les données permettant la connexion à la base de données et la
configuration de Hibernate
[Link]=root
H I ©
[Link]=jdbc:mysql://localhost:3306/cours_graphql?createDatabaseIfNotExist=true
EL
[Link]=
U
[Link]-auto=create-drop
[Link]-sql=true
O
LM
[Link]=[Link]
r e f E
ch
©A
Ajoutons aussi une propriété pour activé l’interface GraphQL qui nous permettra d’envoyer les requêtes au serveur
[Link]=true
H & H: Research and Training 11 / 38
Création et préparation du projet avec Spring Boot
Spring Boot
Préparons la classe de démarrage pour alimenter la base de données avec de données de test
@AllArgsConstructor
@SpringBootApplication
public class SpringQraphqlApplication implements ApplicationRunner {
private PersonneRepository personneRepository;
public static void main(String[] args) {
H I ©
}
[Link]([Link], args);
U EL
O
LM
@Override
r e E
public void run(ApplicationArguments args) throws Exception {
f
Adresse a1 = new Adresse("paradis", "Marseille", "13000");
ch
Adresse a2 = new Adresse("plantes", "Paris", "75000");
©A
Adresse a3 = new Adresse("Salengro", "Marseille", "13000");
Personne personne1 = new Personne("wick", "john", [Link](a1));
Personne personne2 = new Personne("dalton", "jack", [Link](a2, a3));
[Link](personne1);
[Link](personne2);
}
}
H & H: Research and Training 12 / 38
GraphQL : query
Spring Boot
Créons le contrôleur PersonneGraphQlController dans lequel nous injectons
PersonneRepository
H I ©
@Controller
@AllArgsConstructor
U EL
O
LM
public class PersonneGraphQlController {
e f E
private PersonneRepository personneRepository;
r
ch
©A
}
H & H: Research and Training 13 / 38
GraphQL : query @QueryMapping
Spring Boot
Préparons la méthode suivante qui permet de retourner la liste des personnes stockées
dans la base de données
@Controller
H I ©
EL
@AllArgsConstructor
public class PersonneGraphQlController {
O U
f E LM
private PersonneRepository personneRepository;
@QueryMapping
ch r
List<Personne> personnes() {
e
}
} ©A
return [Link]();
H & H: Research and Training 14 / 38
GraphQL : query @QueryMapping
Spring Boot
Explication
H I ©
U
@QueryMapping : utilisée pour mapper une méthode ELqui gère une opération de
lecture (query) dans GraphQL
L MO
@MutationMapping : utilisf ée E
ch r e
opération d’écriture (mutation)
pour mapper une méthode qui gère une
dans GraphQL
© A
H & H: Research and Training 15 / 38
GraphQL : query type de [Link]
Spring Boot
Créons un fichier [Link] dans graphql de src/main/resources
type Query {
personnes: [Personne]
H I ©
}
U EL
O
type Personne {
f E LM
num: Int,
nom: String,
ch r e
} ©A
prenom: String
H & H: Research and Training 16 / 38
GraphQL : query type de [Link]
Spring Boot
Explication
type Query : permet de définir une requête GraphQL.
H I ©
U EL
personnes: [Personne] : signifie que la requête personnes retournera
O
f E LM
une liste ([]) d’objets de type Personne.
r e
type Personne : décrit le type d’objet Personne à retourner.
ch
©A
En GraphQL, les types commencent généralement par une majuscule Int,
String, Float...
H & H: Research and Training 17 / 38
GraphQL : query type de [Link]
Spring Boot
Pour tester le Web Service, il faut
1 lancer l’application,
2 aller à [Link]
H I ©
U EL
3 saisir la requête suivante :
O
f E LM
query {
ch r
personnes { nom, prenom } e
}
©A
4 envoyer la requête et vérifier qu’on récupère les données relatives aux colonnes
demandées (nom et prenom) au format JSON.
H & H: Research and Training 18 / 38
GraphQL : query type de [Link]
Spring Boot
Pour tester depuis Postman, il faut
saisir l’URL [Link]
choisir la méthode POST,
H I ©
cocher raw et sélectionner JSON,
U EL
O
ajouter l’objet JSON suivant
f E LM
{
ch r e
}
©A
"query": "{ personnes { nom prenom } }"
envoyer la requête et vérifier qu’on récupère les données relatives
aux colonnes demandées (nom et prenom) au format JSON.
H & H: Research and Training 19 / 38
GraphQL : query type de [Link]
Spring Boot
Modifions le fichier [Link] pour récupérer les adresses
type Query {
personnes: [Personne]
}
H I ©
EL
type Personne {
num: Int,
nom: String,
O U
prenom: String,
adresses : [Adresse]
f E LM
}
ch r e
type Adresse {
id: Int,
rue: String,
©A
ville: String,
codePostal: String
}
H & H: Research and Training 20 / 38
GraphQL : query type de [Link]
Spring Boot
Pour tester le Web Service, il faut
1 lancer l’application,
2 aller à [Link]
H I ©
U EL
3 saisir la requête suivante :
O
f E LM
query {
ch r e
personnes {nom, prenom, adresses {rue}}
}
©A
4 envoyer la requête et vérifier qu’on récupère les données relatives aux colonnes
demandées au format JSON.
H & H: Research and Training 21 / 38
GraphQL : query @Argument
Spring Boot
Ajoutons une méthode permettant de retourner une seule Personne selon l’identifiant
(num)
@Controller
@AllArgsConstructor
public class PersonneGraphQlController {
H I ©
private PersonneRepository personneRepository;
U EL
O
LM
@QueryMapping
List<Personne> personnes() {
e f E
return [Link]();
r
}
ch
@QueryMapping ©A
Personne personneById(@Argument Long id) {
return [Link](id).orElseThrow(
() -> new NotFoundException(id, "Personne"));
}
}
H & H: Research and Training 22 / 38
GraphQL : query @Argument
Spring Boot
Définissons NotFoundException
package [Link];
H I ©
public class NotFoundException extends RuntimeException {
U EL
O
LM
public NotFoundException(Long id, String type) {
r e E
super([Link]("%s avec l'identifiant %s n'existe pas", type, id));
f
}
ch
©A
H & H: Research and Training 23 / 38
GraphQL : query @Argument
Spring Boot
Mettons à jour le fichier [Link]
type Query {
personnes: [Personne]
personneById(id: Int): Personne
}
H I ©
type Personne {
num: Int,
U EL
O
LM
nom: String,
prenom: String,
adresses : [Adresse]
r e f E
}
ch
type Adresse {
id: Int,
©A
rue: String,
ville: String,
codePostal: String
}
H & H: Research and Training 24 / 38
GraphQL : query @Argument
Spring Boot
Pour tester le Web Service, il faut
1 lancer l’application,
2 aller à [Link]
H I ©
U EL
3 saisir la requête suivante :
O
f E LM
query {
ch r e
personneById(id: 2) { nom, prenom }
}
©A
4 envoyer la requête et vérifier qu’on récupère les données relatives aux colonnes
demandées (nom et prenom) au format JSON.
H & H: Research and Training 25 / 38
GraphQL : query @Argument
Spring Boot
Pour tester le Web Service, il faut
1 lancer l’application,
2 aller à [Link]
H I ©
U EL
3 saisir la requête suivante :
O
f E LM
query {
ch r e
personneById(id: 5) { nom, prenom }
}
©A
4 envoyer la requête et vérifier que le message d’erreur qu’on a définie pour les
personnes inexistantes ne s’affiche pas.
H & H: Research and Training 26 / 38
GraphQL : query @Argument
Spring Boot
©
Créons la classe GraphQLExceptionHandler pour permettre d’afficher les messages d’erreur personnalisés
H I
EL
package [Link];
O U
import [Link];
f E LM
public class GraphQLExceptionHandler extends DataFetcherExceptionResolverAdapter {
ch r e
©A
H & H: Research and Training 27 / 38
GraphQL : query @Argument
Spring Boot
Implémentons la méthode resolveToSingleError de la classe DataFetcherExceptionResolverAdapter
package [Link];
I ©
import [Link];
import [Link];
H
import [Link];
U EL
import [Link];
O
@Component
f E LM
public class GraphQLExceptionHandler extends DataFetcherExceptionResolverAdapter {
@Override
ch r e
©A
protected GraphQLError resolveToSingleError(Throwable ex, DataFetchingEnvironment env) {
return [Link](ex, env);
}
H & H: Research and Training 28 / 38
GraphQL : query @Argument
Spring Boot
Modifions le code de la méthode resolveToSingleError
package [Link];
import [Link];
import [Link];
import [Link];
import
import
[Link];
[Link];
H I ©
import
import
[Link];
[Link];
U EL
O
LM
@Component
E
public class GraphQLExceptionHandler extends DataFetcherExceptionResolverAdapter {
@Override
r e f
ch
protected GraphQLError resolveToSingleError(Throwable ex, DataFetchingEnvironment env) {
©A
if (ex instanceof NotFoundException) {
return toGraphQLError(ex);
} else {
[Link](ex, env);
}
}
private GraphQLError toGraphQLError(Throwable ex) {
return [Link]().message([Link]()).errorType(ErrorType.
DataFetchingException).build();
}
}
H & H: Research and Training 29 / 38
GraphQL : query @Argument
Spring Boot
Pour tester le Web Service, il faut
1 lancer l’application,
2 aller à [Link]
H I ©
U EL
3 saisir la requête suivante :
O
f E LM
query {
ch r e
personneById(id: 5) { nom, prenom }
}
©A
4 envoyer la requête et vérifier que le message "Personne ayant
l’identifiant 5 n’existe pas" s’affiche dans la réponse.
H & H: Research and Training 30 / 38
GraphQL : mutation @MutationMapping
Spring Boot
Préparons la méthode suivante qui permet d’ajouter une nouvelle Personne dans la base de données
@Controller
@AllArgsConstructor
public class PersonneGraphQlController {
private PersonneRepository personneRepository;
H I ©
EL
@QueryMapping
List<Personne> personnes() {
return [Link]();
O U
LM
}
@QueryMapping
r e f E
Personne personneById(@Argument Long id) {
ch
return [Link](id).orElseThrow(
©A
() -> new NotFoundException(id, "Personne"));
}
@MutationMapping
Personne addPersonne(@Argument Personne personne) {
return [Link](personne);
}
}
H & H: Research and Training 31 / 38
GraphQL : mutation input de [Link]
Spring Boot
Déclarons addPersonne dans [Link] : Le paramètre d’entrée doit être déclaré
avec le mot-clé input
type Mutation {
addPersonne(personne: PersonneRequest): Personne
}
H I ©
type Personne {
U EL
O
LM
num: Int,
nom: String,
prenom: String,
r e f E
ch
adresses : [Adresse]
©A
}
input PersonneRequest {
nom: String,
prenom: String,
}
H & H: Research and Training 32 / 38
GraphQL : mutation input de [Link]
Spring Boot
Pour tester le Web Service, il faut
1 lancer l’application,
2 aller à [Link]
3 saisir la requête suivante :
H I ©
U EL
mutation {
O
addPersonne(personne: {
nom: "Maggio",
f E LM
prenom: "Sophie"
ch r e
©A
}) {
num, nom, prenom
}
}
4 envoyer la requête et vérifier qu’on ajoute et récupère les données relatives aux colonnes
demandées (num, nom et prenom) au format JSON.
H & H: Research and Training 33 / 38
Variables
Spring Boot
Notion de variable dans GraphQL
H I ©
U
Utilisée pour passer des valeurs dynamiques aux requ ELêtes GraphQL,
L MO
Préfixée par le symbole $ dans la définition d’une Query ou d’une Mutation,
f E
revaleurs des arguments de la requête elle-même.
c h
Permettant de séparer les
©A
H & H: Research and Training 34 / 38
Variables Exemple avec Mutation
Spring Boot
Pour tester le Web Service, il faut
1 saisir la requête suivante :
mutation($nom: String, $prenom: String) {
addPersonne(personne: {
H I ©
EL
nom: $nom,
prenom: $prenom
}) {
O U
}
num, nom, prenom
f E LM
}
ch r e
2
©A
saisir les variables :
{"nom": "Linus", "prenom": "Benjamin" }
3 envoyer la requête et vérifier qu’on ajoute et récupère les données relatives aux colonnes
demandées (num, nom et prenom) au format JSON.
H & H: Research and Training 35 / 38
Variables Exemple avec Query
Spring Boot
Pour tester le Web Service, il faut
1 saisir la requête suivante :
H I ©
EL
query($id: Int) {
personneById(id: $id) { nom, prenom }
}
O U
f E LM
2 saisir les variables :
ch r e
{"id": 2}
©A
3 envoyer la requête et vérifier qu’on récupère les données relatives aux colonnes
demandées (nom et prenom) de la personne ayant l’identifiant 2 au format JSON.
H & H: Research and Training 36 / 38
Variables Exemple avec Query
Spring Boot
Exercice 1 H I ©
U EL
O
LM
Écrire puis tester les deux méthodes qui permettront de modifier ou
supprimer une personne.
r e f E
ch
©A
H & H: Research and Training 37 / 38
Variables Exemple avec Query
Spring Boot
Exercice 2
H I ©
EL
Développer une application utilisant les frameworks Angular, [Link]
U
O
ou [Link], offrant à l’utilisateur des interfaces graphiques pour la ges-
f E LM
tion des données relatives aux personnes. Ces fonctionnalités incluent
r e
l’ajout, la modification, la suppression, la consultation et la recherche
ch
©A
des informations, en se basant sur le service web existant.
H & H: Research and Training 38 / 38