Spring Data REST
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 / 40
Plan
1 Introduction
2 @RepositoryRestResource
3 Configuration avec [Link]
4 @Param
5 @RestResource
6 Cas d’une association
7 RepositoryRestConfiguration
8 @Projection
9 @Value
10 Extrait
H & H: Research and Training 2 / 40
Introduction
Spring Data REST
Rappel
H I ©
EL
Dans une application Spring MVC, le contrôleur, annoté par
U
O
@RestController, utilise le repository pour assurer le service
REST.
f E LM
ch r e
Avec Spring Data REST, il est possible d’omettre le contrôleur et
©A
d’annoter directement le repository pour exposer les données.
H & H: Research and Training 3 / 40
Introduction
Spring Data REST
Spring Data REST supporte uniquement les projets suivants
Spring Data JPA
H I ©
Spring Data MongoDB UEL
O
Spring Data Neo4j
f E LM
ch r e
A
Spring Data GemFire
©
Spring Data Cassandra
H & H: Research and Training 4 / 40
Introduction
Spring Data REST
Création de projet Spring Boot
Aller dans File > New > Other
Chercher Spring, dans Spring Boot sélectionner Spring Starter Project et
cliquer sur Next >
H I ©
EL
Saisir
cours-spring-data-rest dans Name,
O U
[Link] dans Group,
f E LM
r e
cours-spring-data-rest dans Artifact,
ch
©A
[Link] dans Package
Cliquer sur Next >
Chercher et cocher les cases correspondantes aux Spring Data JPA, MySQL Driver,
Spring Boot DevTools, Lombok et Rest Repositories puis cliquer sur Next >
Valider en cliquant sur Finish
H & H: Research and Training 5 / 40
Introduction
Spring Data REST
Explication
Le package contenant le point d’entrée de notre application (la classe contenant
le puclic static void main) est [Link]
H I ©
EL
Tous les autres packages dao, model... doivent être dans le package demo.
U
O
f E LM
ch r e
©A
H & H: Research and Training 6 / 40
Introduction
Spring Data REST
Explication
Le package contenant le point d’entrée de notre application (la classe contenant
le puclic static void main) est [Link]
H I ©
EL
Tous les autres packages dao, model... doivent être dans le package demo.
U
O
f E LM
h r
cérons e
A
Pour la suite, nous consid
©
une entité Personne à définir dans [Link]
une interface DAO PersonneRepository à définir dans
[Link]
H & H: Research and Training 6 / 40
Introduction
Spring Boot & REST
Créons une entité Personne dans [Link]
package [Link];
import [Link];
import [Link];
import [Link];
©
import [Link];
import [Link];
H I
EL
import [Link];
import [Link];
import
import
[Link];
[Link];
O U
@NoArgsConstructor
f E LM
@AllArgsConstructor
@Data
@Entity
ch r e
©A
@RequiredArgsConstructor
public class Personne {
@Id
@GeneratedValue(strategy = [Link])
private Long num;
@NonNull
private String nom;
@NonNull
private String prenom;
}
H & H: Research and Training 7 / 40
Introduction
Spring Boot & REST
Préparons notre interface DAO PersonneRepository
package [Link];
H I ©
EL
import [Link];
U
O
LM
import [Link];
r e f E
public interface PersonneRepository extends JpaRepository<Personne,
Long> {
ch
} ©A
H & H: Research and Training 8 / 40
Introduction
Spring Data REST
Dans [Link], ajoutons les données permettant la connexion à la base de données et la
configuration de Hibernate
[Link] = jdbc:mysql://localhost:3306/cours_data_rest?createDatabaseIfNotExist=
true
[Link] = root
H I ©
EL
[Link] = root
[Link]-auto = update
[Link]-sql = true
O U
LM
[Link] = [Link]
[Link]-strategy = [Link].
PhysicalNamingStrategyStandardImpl
r e f E
ch
©A
L’ajout de la propriété [Link]-strategy permet de forcer Hibernate à utiliser les
mêmes noms pour les tables et les colonnes que les entités et les attributs.
H & H: Research and Training 9 / 40
@RepositoryRestResource
Spring Data REST
Pour déclarer un repository comme étant une API REST, il faut ajouter l’annotation
@RepositoryRestResource
package [Link];
H I ©
EL
import [Link];
import [Link].
RepositoryRestResource;
O U
import [Link];
f E LM
ch r e
©A
@RepositoryRestResource
public interface PersonneRepository extends JpaRepository<Personne,
Long> {
H & H: Research and Training 10 / 40
@RepositoryRestResource
Spring Data REST
Pour alimenter la base de données avec quelques données au démarrage de l’application
@SpringBootApplication
public class CoursSpringDataRestApplication implements ApplicationRunner {
@Autowired
private PersonneRepository personneRepository;
H I ©
public static void main(String[] args) {
U EL
O
[Link]([Link], args);
LM
}
@Override
r e f E
public void run(ApplicationArguments args) throws Exception {
ch
Personne personne1 = new Personne("wick", "john");
©A
Personne personne2 = new Personne("dalton", "jack");
Personne personne3 = new Personne("maggio", "carol");
Personne personne4 = new Personne("cohen", "sophie");
[Link]([Link](personne1, personne2, personne3, personne4));
}
}
H & H: Research and Training 11 / 40
@RepositoryRestResource
Spring Data REST
Pour tester, il faut aller sur
[Link] pour récupérer la liste des personnes
l’identifiant 1
H I ©
ou sur [Link] pour consulter la personne ayant
UEL
O
ou sur [Link] pour consulter les deux
LM
premiers tuples (la première page)
e f E
ou sur [Link] pour consulter la
r
page 2 de taille 2
ch
©A
ou sur [Link] pour trier le résultat selon le
nom
ou sur [Link] pour trier le résultat
selon le nom dans l’ordre descendant
H & H: Research and Training 12 / 40
@RepositoryRestResource
Spring Data REST
Pour ajouter une personne, utilisons Postman
Saisissez l’URL [Link]
Choisissez le verbe POST
H I ©
EL
Dans Headers, précisez la clé Content-Type et la valeur
application/json
O U
L M
Dans Body, cochez raw et sélectionnez JSON(application/json)
e f E
A chr
©
H & H: Research and Training 13 / 40
@RepositoryRestResource
Spring Data REST
Pour ajouter une personne, utilisons Postman
Saisissez l’URL [Link]
Choisissez le verbe POST
H I ©
EL
Dans Headers, précisez la clé Content-Type et la valeur
application/json
O U
L M
Dans Body, cochez raw et sélectionnez JSON(application/json)
e f E
A chr
© à persister
Exemple de valeurs
{
"nom": "el mouelhi",
"prenom": "achref"
}
H & H: Research and Training 13 / 40
Configuration avec [Link]
Spring Data REST
Définissons une base pour tous les repository exposés comme des ressources REST
[Link]=/ws
H I ©
U EL
O
f E LM
ch r e
©A
H & H: Research and Training 14 / 40
Configuration avec [Link]
Spring Data REST
Définissons une base pour tous les repository exposés comme des ressources REST
[Link]=/ws
H I ©
EL
Nouvelles URLs pour les tests
O U
[Link] pour récupérer la liste des personnes
f E LM
ou sur [Link] pour consulter la personne ayant l’identifiant 1
ch r e
ou sur [Link] pour consulter les deux premiers tuples (la première
©A
page)
ou sur [Link] pour consulter la page 2 de taille 2
ou sur [Link] pour trier le résultat selon le nom
ou sur [Link] pour trier le résultat selon le nom dans l’ordre
descendant
H & H: Research and Training 14 / 40
Configuration avec [Link]
Spring Data REST
Autres propriétés possibles pour Spring Data REST
returnBodyOnCreate : spécifie si un corps doit être renvoyé lors de la
création d’une entité
H I ©
EL
returnBodyOnUpdate : spécifie si un corps doit être renvoyé lors de la mise à
jour d’une entité
O U
f E LM
maxPageSize : indique le nombre maximum d’éléments dans une seule page
ch r e
pageParamName : modifie le nom du paramètre de requête pour sélectionner
A
les pages (par défaut page)
©
sortParamName : modifie le nom du paramètre de requête pour trier les
données (par défaut sort)
...
H & H: Research and Training 15 / 40
@Param
Spring Data REST
Pour définir une méthode personnalisée
package [Link];
import [Link];
import [Link];
import [Link];
H I ©
import [Link];
import [Link];
U EL
O
LM
@RepositoryRestResource
E
public interface PersonneRepository extends JpaRepository<Personne, Long> {
}
r e f
List<Personne> findByNom(@Param("nom") String nom);
ch
©A
H & H: Research and Training 16 / 40
@Param
Spring Data REST
Pour définir une méthode personnalisée
package [Link];
import [Link];
import [Link];
import [Link];
H I ©
import [Link];
import [Link];
U EL
O
LM
@RepositoryRestResource
E
public interface PersonneRepository extends JpaRepository<Personne, Long> {
}
r e f
List<Personne> findByNom(@Param("nom") String nom);
ch
©A
URL pour tester
[Link]
H & H: Research and Training 16 / 40
@Param
Spring Data REST
On peut aussi chercher les personnes dont le nom contient une certaine sous-chaı̂ne
package [Link];
import [Link];
import [Link];
import
import
[Link];
[Link];
H I ©
EL
import [Link];
@RepositoryRestResource
O U
LM
public interface PersonneRepository extends JpaRepository<Personne, Long> {
List<Personne> findByNomContains(@Param("nom") String nom);
}
r e f E
ch
©A
H & H: Research and Training 17 / 40
@Param
Spring Data REST
On peut aussi chercher les personnes dont le nom contient une certaine sous-chaı̂ne
package [Link];
import [Link];
import [Link];
import
import
[Link];
[Link];
H I ©
EL
import [Link];
@RepositoryRestResource
O U
LM
public interface PersonneRepository extends JpaRepository<Personne, Long> {
List<Personne> findByNomContains(@Param("nom") String nom);
}
r e f E
ch
URL pour tester
©A
[Link]
nom=i
H & H: Research and Training 17 / 40
@RestResource
Spring Data REST
Pour renommer le chemin vers la méthode précédente, on utilise @RestResource
package [Link];
import [Link];
import [Link];
©
import [Link];
import [Link];
H I
EL
import [Link];
import [Link];
O U
LM
@RepositoryRestResource
@RestResource(path="nom")
r e E
public interface PersonneRepository extends JpaRepository<Personne, Long> {
f
ch
List<Personne> findByNomContains(@Param("nom") String nom);
}
©A
H & H: Research and Training 18 / 40
@RestResource
Spring Data REST
Pour renommer le chemin vers la méthode précédente, on utilise @RestResource
package [Link];
import [Link];
import [Link];
©
import [Link];
import [Link];
H I
EL
import [Link];
import [Link];
O U
LM
@RepositoryRestResource
@RestResource(path="nom")
r e E
public interface PersonneRepository extends JpaRepository<Personne, Long> {
f
ch
List<Personne> findByNomContains(@Param("nom") String nom);
}
©A
URL pour tester
[Link]
H & H: Research and Training 18 / 40
@RestResource
Spring Data REST
Pour effectuer une recherche selon le nom et paginer le résultat
package [Link];
import [Link];
import [Link];
import [Link];
import
import
[Link];
H I ©
[Link];
EL
import [Link];
U
import [Link];
O
LM
@RepositoryRestResource
public interface PersonneRepository extends JpaRepository<Personne, Long> {
@RestResource(path="nom")
r e f E
List<Personne> findByNomContains(@Param("nom") String nom, Pageable pageable);
ch
}
©A
H & H: Research and Training 19 / 40
@RestResource
Spring Data REST
Pour effectuer une recherche selon le nom et paginer le résultat
package [Link];
import [Link];
import [Link];
import [Link];
import
import
[Link];
H I ©
[Link];
EL
import [Link];
U
import [Link];
O
LM
@RepositoryRestResource
public interface PersonneRepository extends JpaRepository<Personne, Long> {
@RestResource(path="nom")
r e f E
List<Personne> findByNomContains(@Param("nom") String nom, Pageable pageable);
ch
}
©A
URL pour tester
[Link]
H & H: Research and Training 19 / 40
@RestResource
Spring Data REST
Exercice 1
Testez, avec Postman, les deux méthodes HTTP PUT et DELETE qui
permettront de modifier ou supprimer une personne.
H I ©
UEL
O
f E LM
ch r e
©A
H & H: Research and Training 20 / 40
@RestResource
Spring Data REST
Exercice 1
Testez, avec Postman, les deux méthodes HTTP PUT et DELETE qui
permettront de modifier ou supprimer une personne.
H I ©
UEL
O
f E LM
Exercice 2
ch r e
©A
Créer une application Angular qui permet à un utilisateur, via des
interfaces graphiques) la gestion de personnes (ajout, modification,
suppression, consultation et recherche) en utilisant les Web Services
définis par Spring Data REST.
H & H: Research and Training 20 / 40
Cas d’une association
Spring Data REST
Créons une entité Adresse dans [Link]
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
H I ©
EL
@RequiredArgsConstructor
public class Adresse {
O U
LM
@Id
private Long id;
r e E
@GeneratedValue(strategy = [Link])
f
@NonNull
ch
©A
private String rue;
@NonNull
private String codePostal;
@NonNull
private String ville;
}
H & H: Research and Training 21 / 40
Cas d’une association
Spring Data REST
Préparons notre interface DAO AdresseRepository
package [Link];
import [Link];
H I ©
import [Link].
RepositoryRestResource;
UEL
O
import [Link];
f E LM
@RepositoryRestResource
ch r e
©A
public interface AdresseRepository extends JpaRepository <Adresse, Long
> {
H & H: Research and Training 22 / 40
Cas d’une association
Spring Data REST
Dans Personne, ajoutons l’association avec Adresse
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@RequiredArgsConstructor
H I ©
public class Personne {
UEL
@Id
O
private Long num;
f E LM
@GeneratedValue(strategy = [Link])
@NonNull
ch r e
©A
private String nom;
@NonNull
private String prenom;
@NonNull
@ManyToMany(cascade = [Link])
private List <Adresse>adresses;
}
H & H: Research and Training 23 / 40
Cas d’une association
Pour alimenter la base de données avec quelques données au démarrage de l’application,
modifions la classe de démarrage
@Override
public void run(ApplicationArguments args) throws Exception {
Personne personne1 = new Personne("wick", "john", [Link](
new Adresse("paradis", "13015", "Marseille"),
new Adresse("lacanau", "13700", "Marignane")
));
H I ©
Personne personne2 = new Personne("dalton", "jack", [Link](
new Adresse("défense", "75000", "Paris"),
UEL
new Adresse("five", "59000", "Lille"),
O
LM
new Adresse("corum", "34000", "Montpellier")
));
r e f E
Personne personne3 = new Personne("maggio", "carol", [Link](
ch
new Adresse("gabriel péri", "69008", "Lyon"),
)); ©A
new Adresse("gerland", "69007", "Lyon")
Personne personne4 = new Personne("cohen", "sophie", [Link](
new Adresse("prado", "13008", "Marseille")
));
[Link]([Link](personne1, personne2,
personne3, personne4));
}
H & H: Research and Training 24 / 40
Cas d’une association
Spring Data REST
Pour tester, il faut aller sur
[Link] pour récupérer la liste des personnes
adresses de la personne ayant l’identifiant 1
H I ©
ou sur [Link] pour consulter les
UEL
ou sur [Link] pour consulter la liste des adresses
O
f E LM
ch r e
©A
H & H: Research and Training 25 / 40
Cas d’une association
Spring Data REST
Pour tester, il faut aller sur
[Link] pour récupérer la liste des personnes
adresses de la personne ayant l’identifiant 1
H I ©
ou sur [Link] pour consulter les
UEL
ou sur [Link] pour consulter la liste des adresses
O
f E LM
ch r e
Remarques ©A
Pas d’accès aux personnes depuis adresses
La relation n’est pas bidirectionnelle
H & H: Research and Training 25 / 40
Cas d’une association
Spring Data REST
Ajoutons Personne dans Adresse pour avoir une association bidirectionnelle
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@RequiredArgsConstructor
H I ©
public class Adresse {
@Id
UEL
O
LM
@GeneratedValue(strategy = [Link])
private Long id;
@NonNull
r e f E
private String rue;
ch
©A
@NonNull
private String codePostal;
@NonNull
private String ville;
@ManyToMany(mappedBy = "adresses")
private List<Personne> personnes;
}
H & H: Research and Training 26 / 40
Cas d’une association
Spring Data REST
Pour tester, il faut aller sur
H I ©
EL
[Link] pour récupérer la
liste des adresses
O U
ou sur
f E LM
ch r e
[Link] pour
©A
consulter les personnes associées à l’adresse ayant l’identifiant 1
H & H: Research and Training 27 / 40
Cas d’une association
Spring Data REST
Utilisons @RestResource pour modifier le chemin d’accès aux personnes depuis une
adresse
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@RequiredArgsConstructor
H I ©
public class Adresse {
UEL
@Id
O
LM
@GeneratedValue(strategy = [Link])
private Long id;
@NonNull
r e f E
private String rue;
ch
@NonNull
©A
private String codePostal;
@NonNull
private String ville;
@RestResource(path = "per")
@ManyToMany(mappedBy = "adresses")
private List<Personne> personnes;
}
H & H: Research and Training 28 / 40
Cas d’une association
Spring Data REST
Pour tester, il faut aller sur
H I ©
EL
[Link] pour récupérer la
U
liste des adresses O
f E LM
ou sur [Link] pour
ch r e
consulter les personnes associées à l’adresse ayant l’identifiant 1
©A
H & H: Research and Training 29 / 40
Cas d’une association
Spring Data REST
Pour charger les données relatives aux personnes dans chaque adresse
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@RequiredArgsConstructor
H I ©
EL
public class Adresse {
@Id
O U
@GeneratedValue(strategy = [Link])
private Long id;
@NonNull
f E LM
private String rue;
ch r e
©A
@NonNull
private String codePostal;
@NonNull
private String ville;
@RestResource(exported = false)
@ManyToMany(mappedBy = "adresses")
private List<Personne> personnes;
}
H & H: Research and Training 30 / 40
Cas d’une association
Spring Data REST
Attention, ceci déclenche une boucle infinie
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@RequiredArgsConstructor
H I ©
EL
public class Personne {
@Id
O U
LM
@GeneratedValue(strategy = [Link])
private Long num;
@NonNull
r e f E
ch
©A
private String nom;
@NonNull
private String prenom;
@NonNull
@ManyToMany(cascade = [Link])
@RestResource(exported = false)
private List <Adresse>adresses;
}
H & H: Research and Training 31 / 40
RepositoryRestConfiguration
Spring Data REST
Par défaut
H I ©
Spring Data REST n’expose pas l’identifiant
U EL
Pour le faire, on peut injecterLet M
O
r e f
RepositoryRestConfiguration
E utiliser
dans la classe de démarrage
c h
©A
H & H: Research and Training 32 / 40
RepositoryRestConfiguration
Spring Data REST
Pour exposer l’identifiant d’une entité, on utilise RepositoryRestConfiguration
@SpringBootApplication
public class CoursSpringDataRestApplication implements ApplicationRunner {
@Autowired
private PersonneRepository personneRepository;
H I ©
@Autowired
U EL
O
private RepositoryRestConfiguration repositoryRestConfiguration;
public static void main(String[] args) {
f E LM
[Link]([Link], args);
}
ch r e
©A
@Override
public void run(ApplicationArguments args) throws Exception {
[Link]([Link], [Link]);
// + le code précédent
}
}
H & H: Research and Training 33 / 40
@Projection
Spring Data REST
Projection
H I ©
Si dans certains cas, je veux seulement exposer quelques
EL
attributs de ma classe (par exemple ville et codePostal pour
Adresse.
M OU
E L (getters) à exposer dans une
On peut indiquer les méthodes
f
chr e
interface annotée par Projection.
A
©de projection doit être dans le même package que le
L’interface
modèle (entité)
H & H: Research and Training 34 / 40
@Projection
Spring Data REST
Définissons l’interface de projection AdresseProjection
package [Link];
H I ©
U EL
import [Link];
L MO
@Projection(types = { [Link] }, name = "a1")
e f E
public interface AdresseProjection
r
{
public A ch getVille();
public String getCodePostal();
} © String
H & H: Research and Training 35 / 40
@Projection
Spring Data REST
Pour tester
Allez sur
[Link]
H I ©
Vérifiez que seuls le code postal et la villeE
U L exposés.
sont
L MO
r e f E
A ch
©
H & H: Research and Training 36 / 40
@Projection
Spring Data REST
Pour tester
Allez sur
[Link]
H I ©
Vérifiez que seuls le code postal et la villeE
U L exposés.
sont
L MO
r e f E
Remarque © A
ch
Une projection permet d’exposer même les attributs annotés par
@JsonIgnore.
H & H: Research and Training 36 / 40
@Value
Spring Data REST
On peut aussi utiliser une projection et l’annotation @Value pour
fusionner les attributs
package [Link];
I ©
import [Link].
H
Value;
UEL
O
import [Link].
Projection;
f E LM
r e
ch = { [Link] }, name = "a1")
© A
@Projection(types
public interface AdresseProjection {
@Value("#{ [Link] + ' ' + target.
codePostal }")
String getVilleDetails();
}
H & H: Research and Training 37 / 40
Extrait
Spring Data REST
Extrait (Excerpts)
H I ©
une projection automatiquement appliquU EàLun repository REST
ée
M O
E L
On le précise dans l’annotation
f
@RepositoryRestResource
r e
avec l’attribut excerptProjection
ch
© A
H & H: Research and Training 38 / 40
Extrait
Spring Data REST
Exemple
package [Link];
H I ©
EL
import [Link];
U
import [Link];
O
LM
import [Link];
import [Link];
r e f E
@RepositoryRestResource(excerptProjection = [Link])
ch
public interface AdresseRepository extends JpaRepository <Adresse, Long> {
}
©A
H & H: Research and Training 39 / 40
Extrait
Spring Data REST
Remarque
H I ©
En allant sur
UEL
O
[Link]
f E LM
on obtient une seule clé villeDetails
ch r e
En allant sur [Link] on
©A
obtient une seule clé villeDetails
H & H: Research and Training 40 / 40