MORASSUT - GMIN30F - 2014 - TD-TP - Partie 2

PARTIE 2
Mise en place de la persistance JAVA EE JPA & définition du métier
Présentation
Durant cette partie, nous allons explorer le standard JAVA EE « JPA » qui définit une harmonisation du
mode de création d’objets métiers, de gestion des transactions, d’accès aux ressources de persistance.
Le mode de persistance ainsi mis en place, nous l’utiliserons pour définir des services REST
déclenchant des opérations persistantes.
Adresses utiles :
-
-
JPA :
o JSR-220 : https://jcp.org/en/jsr/detail?id=220
o JSR-317 : https://jcp.org/en/jsr/detail?id=317
Hibernate : http://hibernate.org/
Junit : http://junit.org/
Étapes de mise en place
Définition de JPA
-
Intégrer un nouveau fichier « persistence.xml » dans le classpath, à la racine, dans un
répertoire « META-INF »
o « META-INF » est un répertoire normé, présent dans les JAR, WAR, … qui permet de
spécifier des propriétés globales, par properties, XML, …
o Utiliser le fichier fourni. L’arborescence doit avoir cette structure :
GMIN30F/MORASSUT
Page 15
Définition des objets métiers
La mise en place des objets métiers va se faire en deux étapes :
-
Définir la super classe des objets métiers, leur contrat commun
Définir les objets concrètement et décider de leurs modalités de mapping sur la base de
données relationnelle.
Superclasse des objets métiers
La mise en place d’une « super classe » des objets métiers va nous permettre de mettre en commun
des mécanismes et des comportements. Dans le cas de ce TP, nous voulons mettre en commun la
gestion du champ identifiant afin qu’il soit traité de manière uniforme dans tous les objets métiers.
Créer un package « common », il regroupera les définitions de classes-mère
Intégrer une interface « IPersistentObject » étendant « java.io.Serializable ».
Cette interface reste vide.
Intégrer une implémentation « PersistentObjectImpl » de l’interface définie au point
précédent. Intégrer l’annotation de classe « @MappedSuperClass »
Intégrer le champ suivant :
@Id
@GeneratedValue
@Column(name = "id", unique = true, nullable = false)
private Integer id;
Créer les accesseurs de ce champ (get/set)
Objets métiers
Créer un package « model », il regroupera toutes les définitions d’objet métier
Définir les classes « MBookmark », « MTag », « MUser » (préfixe « M » pour simplifier les
recherches de classes via Eclipse, utile dans les grands projets)
A respecter :
o Utiliser les annotations JPA : @Entity, @Table, @Column, @ManyToOne,
@ManyToMany
o Vous pouvez utiliser des annotations de validation (ex : @NotNull, etc.)
o Intégrer explicitement un constructeur sans arguments
o Intégrer un « toString » affichant ID/Version
Fourniture d’une classe exemple
Si vous republiez le projet au niveau du serveur d’applications, cela vous permettra de valider
que vos déclarations sont statiquement correctes.
GMIN30F/MORASSUT
Page 16
Définition des services
Dans cette partie, nous allons créer un premier service que nous injecterons dans notre service REST
« helloworld »
Création du service
-
Créer un package « service », avec un sous package « impl »
Créer une interface « IServiceHelloworld » dans le package « service ». Vide.
Définir une opération « String getHtml() » dans cette interface
Créer une classe implémentant l’interface précédemment définie, placée dans le package
« impl » et nommée « ServiceHelloworld »
Implémenter la méthode créée avec un contenu arbitraire
Injection du service dans le service REST
-
Déclarer un attribut d’injection du service créé précédemment dans la classe Helloworld
gérant le service REST :
@InjectParam
private IServiceBookmark serviceBookmark;
-
Utiliser cet attribut dans votre implémentation de service REST, remplacer l’implémentation
précédente par un appel à la méthode définie dans ce service
Tester.
Remarque : si vous rencontrez des problèmes de déploiement, effectuez la partie « Ajout de
SLF4J » pour disposer de traces étendues. Ces traces permettent d’avoir toutes les
informations sur les soucis éventuels de déploiement.
Premier services : enregistrement et listing
Intégrer à votre service les méthodes suivantes :
public MBookmark save(final MBookmark newInstance) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("tp");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(newInstance);
em.flush();
em.getTransaction().commit();
em.close();
emf.close();
return newInstance;
}
GMIN30F/MORASSUT
Page 17
public List<MBookmark> getAll() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("tp");
EntityManager em = emf.createEntityManager();
List<MBookmark> list = em.createQuery("from MBookmark").getResultList();
em.close();
emf.close();
}
On peut remarquer notamment :
-
-
La gestion de transactions (em.getTransaction). Dans notre cas, elle est très simple.
La création d’un entityManagerFactory : voir que le nom défini dans notre
« persistence.xml » pour le « persistence unit » est ici réutilisé pour faire référence à la
configuration que nous désirons utiliser.
La création d’un entityManager
La création d’une requête. Dans le cas de la requête exposée, on peut remarquer :
o L’utilisation du nom objet « MBookmark »
o L’absence de clause « SELECT » car JPQL supporte la translation relationnel vers objet
automatiquement
Ces deux exemples de méthodes vont vous permettre d’exposer deux services REST :
-
Ajout d’enregistrement dans la table bookmark
Récupération de toutes les lignes de la table bookmark
Ainsi, vous pouvez utiliser ces deux services pour vérifier que votre persistance fonctionne bien :
-
Un service pour ajouter une entité
Un service retournant la liste des entités ou le nombre des entités présentes
Ajout de SLF4J
Log4j/SLF4J vont nous permettre d’avoir un canal de log reconnu par le serveur d’application. Ainsi,
les messages seront configurables globalement.
Ajouter le fragment suivant au pom :
pom.xml
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
<scope>runtime</scope>
</dependency>
Ajouter le fichier « log4j.properties » dans le répertoire « classes »
GMIN30F/MORASSUT
Page 18
Nb. Le répertoire « classes » est le répertoire père du « META-INF » où nous avions mis le fichier
« persistence.xml »
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L \u2013
%m%n
log4j.rootLogger=debug, stdout
Dans les traces du serveur, nous pourrons désormais voir les informations de debug de JPA et des
autres composants. Vous observerez notamment la création automatique de schéma.
Finalisation des travaux
Nous avons à présent un serveur REST fonctionnel sur une source de données relationnelles à travers
une pile JPA. Nos entités métier sont définies en indépendance de la source de données et les classes
de service permettent de découpler le code de gestion du code de prise en charge des informations
métier.
Pour la suite, vous devez définir :
-
Les services REST additionnels : BookmarkResouce, TagResource. Ils vous serviront à définir
les services REST à implémenter (cf. liste proposée au début du document)
Les services réalisant les opérations de persistance
GMIN30F/MORASSUT
Page 19