Web services REST avec JAX-RS · Java pour les services web RESTful (JAX-RS) dont la version...

Preview:

Citation preview

Web services REST avec JAX-RS

Hyacinthe MENIET

3 août 2019

Développer des web services RESTful en Java est possible depuis les débuts de REST, notammentgrâce à l’API Servlet. En effet, cette API est suffisamment proche du protocole HTTP pour per-mettre à chaque développeur de transférer et de récupérer ce qu’il veut dans une réponse HTTP oudepuis une requête HTTP. Dans la documentation Web services REST avec Java (JAXB) j’expliquecomment faire. Reportez-vous au même article pour une courte introduction sur les architecturesREST.Ceci dit, malgré son expressivité, l’API Servlet reste loin du niveau de commodité atteint par JAX-WS pour les web services SOAP (voir l’article Web services SOAP avec Java (JAX-WS) pour plusde détails). C’est pourquoi, la Java Specification Request 311 a été déposée auprès du Java Com-munity Process (JCP) et approuvée à l’unanimité. A la suite de quoi, un groupe d’experts a entamédes travaux afin de concevoir une API flexible, facile à utiliser et qui encouragerait les dévelop-peurs à monter des architectures REST. Le résultat de ce travail a été finalisé sous le nom d’APIJava pour les services web RESTful (JAX-RS) dont la version courante est 2.1.Dans cet article je vais indiquer comment développer un Web service REST en utilisant JAX-RS2.1. Puis j’expliquerai comment le consommer. Pour le mapping Objet-Relationnel, j’utiliserai laJava Persistence API (JPA 2.1). Enfin, la sérialisation Java vers XML sera assurée par la Java APIfor XML Binding (JAXB 2.2).

1. Pré-requis

— Vous êtes familier de Java 8 et de sa syntaxe.— Vous êtes familier des Web services REST.— Vous disposez du JDK 8 minimum.— Vous êtes familier de Tomcat et vous avez installé et configuré sa version 8 minimum.— Vous êtes familier de MariaDB (ou MySQL) et vous avez installé et configuré sa version

10 minimum (ou MySQL 5.7 minimum).— Vous êtes familier de Maven et vous avez installé et configuré sa version 3.3 minimum.

2. Vue d’ensemble

2.1 Vue d’ensemble de JAX-RS

JAX-RS est une API récente mais déjà bien fournie : Elle propose notamment des annotations spé-cifiques pour lier une URI et des verbes HTTP à des méthodes d’une classe Java. JAX-RS disposeégalement d’annotations capables d’injecter et de récupérer des données dans les entêtes d’uneréponse ou depuis celles d’une requête. De même l’API JAX-RS fournit ce qu’il faut pour extraireet écrire ce que vous voulez dans le corps d’une requête/réponse HTTP. Enfin, en cas d’exceptionJava, JAX-RS est capable de produire une réponse avec le code HTTP le plus pertinent.

1

Comme souvent dans le monde Java, il existe de nombreuses implémentations de JAX-RS. Laplupart de ces implémentations sont open source et libres. Dans ce document, je n&rsquo ;en pré-senterai qu&rsquo ;une : Jersey. Pour rappel, Jersey est un morceau de GlassFish. En particulier,c&#039 ;est Jersey qui fournit l&#039 ;implémentation de référence de JAX-RS.

2.2 Vue d’ensemble de JPA

La Java Persistence API (JPA) est une API légère à base de POJO pour la persistance d’objetsJava. Cette API a été développée dans le cadre de la JSR 220. JPA est très souple car elle peut êtreutilisée dans une webapp, dans une application J2EE et même dans une simple application JavaSE.Comme JAX-RS, JPA dispose de nombreuses implémentations. Pour cet article, j’ai choisi l’unedes implémentations les plus populaires : Hibernate.

2.3 Vue d’ensemble de JAXB

La Java API for XML Binding (JAXB) est un ensemble d’annotations qui aident à la sérialisa-tion/désérialisation d’objets Java en XML. Cette API est extrêmement utile, car elle permet de sepasser des représentations abstraites d’un document XML pour se concentrer sur de simples POJOannotés. Dans l’article Sérialisation et désérialisation XML avec Java (JAXB), j’explique plus endétail comment fonctionne JAXB. L’implémentation de référence de JAXB est intégrée au JDK.

2.4 Vue d’ensemble de l’article

Pour rentre cet article le plus didactique possible, je vais parcourir les capacités de JAX-RS àtravers le système d’information d’une association de troc de services. Cette association met enrelation des personnes qui proposent des services en échange d’autres services. Une fois mis enrelation et sous réserve d’un accord mutuel, une personne peut, par exemple, recevoir une leçonde cuisine thaïlandaise en échange d’un dépannage de la plomberie.Dans cet article, je ne modéliserai que la relation entre une personne et ses services. Concrètement,je réaliserai un Web service REST qui expose les 6 actions suivantes :

URI HTTP Description Sortie Entrée/persons/{pId} GET Retourne des informations

sur la personnela per-sonne

N/A

/persons/{pId}/services GET Retourne les services de lapersonne

Unecollec-tion deservices

N/A

/persons/{pId}/services POST Ajoute un service à la per-sonne

l’URI duservice

Unservice

/persons/{pId}/services/{sId} GET Retourne des informationssur le service

Unservice

N/A

/persons/{pId}/services/{sId} PUT Modifie un service N/A Unservice

/persons/{pId}/services/{sId} DELETE Supprime un service N/A N/AVous pouvez télécharger le code source des projets Maven de web service REST (i.e. serveur et

2

client).

3. Le Web service

3.1 La base de données

La base de données bartering correspond au schéma suivant :

J’ai réalisé ce schéma avec Workbench. Créez la base de données correspondante ainsi que sonpropriétaire grâce au script Bartering-grant.sql :

CREATE DATABASE ‘ b a r t e r i n g ‘ CHARACTER SET u t f 8 COLLATEu t f 8 _ g e n e r a l _ c i ;

CREATE USER b a r t u s e r @ l o c a l h o s t IDENTIFIED BY ’ bar tpwd ’ ;GRANT ALL PRIVILEGES ON b a r t e r i n g . * TO b a r t u s e r @ l o c a l h o s t ;FLUSH PRIVILEGES ;

Créez les tables person et service à l’aide du script Bartering-schema.sql :

−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Tab le ‘ pe r son ‘−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−CREATE TABLE IF NOT EXISTS ‘ person ‘ (‘ id ‘ INT UNSIGNED NOT NULL AUTO_INCREMENT ,‘ name ‘ VARCHAR( 4 5 ) NOT NULL ,‘ f i r s t n a m e ‘ VARCHAR( 4 5 ) NULL ,‘ l o c a t i o n ‘ VARCHAR( 4 5 ) NULL ,PRIMARY KEY ( ‘ id ‘ ) )ENGINE = InnoDB ;−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Tab le ‘ s e r v i c e ‘−− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−CREATE TABLE IF NOT EXISTS ‘ s e r v i c e ‘ (‘ id ‘ INT UNSIGNED NOT NULL AUTO_INCREMENT ,‘ p e r s o n _ i d ‘ INT UNSIGNED NOT NULL ,

3

‘ d e s c r i p t i o n ‘ LONGTEXT NULL ,PRIMARY KEY ( ‘ id ‘ ) ,INDEX ‘ f k _ s e r v i c e _ p e r s o n ‘ ( ‘ p e r s o n _ i d ‘ ASC) ,CONSTRAINT ‘ f k _ s e r v i c e _ p e r s o n ‘FOREIGN KEY ( ‘ p e r s o n _ i d ‘ )REFERENCES ‘ person ‘ ( ‘ id ‘ )ON DELETE NO ACTIONON UPDATE NO ACTION)ENGINE = InnoDB ;

Insérez les personnes et les services en exécutant le script Bartering-data.sql :

INSERT INTO ‘ person ‘ VALUES ( 1 , ’ Gates ’ , ’ B i l l ’ , ’ Q u a r t i e r S a i n tBruno ’ ) , ( 2 , ’ Jobs ’ , ’ S teve ’ , ’ Rue de l a pomme ’ ) ;

INSERT INTO ‘ s e r v i c e ‘ VALUES ( 1 , 1 , ’ I n s t a l l a t i o n de Windows 7 ’ ), ( 2 , 1 , ’ Fo rma t ion d \ ’ 1 h e u r e en Economie ’ ) ;

3.2 Projet Maven

Créez un nouveau projet de type webapp avec Maven (commande à taper à la racine de votreworkspace) :

$ mvn a r c h e t y p e : g e n e r a t e −DgroupId= n e t . d o t m y s e l f . b a r t e r i n g −D a r t i f a c t I d = b a r t e r i n g −D v e r s i o n =1 .0 −Dpackage= n e t . d o t m y s e l f .b a r t e r i n g −D a r c h e t y p e A r t i f a c t I d =maven−a r c h e t y p e−webapp −D i n t e r a c t i v e M o d e = f a l s e

Ecrasez le pom.xml généré, dans le dossier bartering, par ce pom.xml.

< p r o j e c t xmlns =" h t t p : / / maven . apache . o rg /POM/ 4 . 0 . 0 " xmlns : x s i ="h t t p : / / www. w3 . org / 2 0 0 1 / XMLSchema−i n s t a n c e "

x s i : s chemaLoca t ion =" h t t p : / / maven . apache . o rg /POM/ 4 . 0 . 0 h t t p : / /maven . apache . o rg / maven−v4_0_0 . xsd ">

<modelVers ion > 4 . 0 . 0 < / modelVers ion >< groupId > n e t . d o t m y s e l f . b a r t e r i n g < / groupId >< a r t i f a c t I d > b a r t e r i n g < / a r t i f a c t I d >< packag ing >war < / packag ing >< v e r s i o n >1 .0 < / v e r s i o n ><name> b a r t e r i n g Maven Webapp </ name>< u r l > h t t p : / / maven . apache . org < / u r l >< p r o p e r t i e s >< p r o j e c t . b u i l d . sou rceEncod ing >UTF−8</ p r o j e c t . b u i l d . sou rceEncod ing

><maven . c o m p i l e r . sou rce >1 .7 < / maven . c o m p i l e r . sou rce ><maven . c o m p i l e r . t a r g e t >1 .7 < / maven . c o m p i l e r . t a r g e t ></ p r o p e r t i e s >< d e p e n d e n c i e s ><dependency >

4

< groupId > org . g l a s s f i s h . j e r s e y . i n j e c t < / g roupId >< a r t i f a c t I d > j e r s e y −hk2 </ a r t i f a c t I d >< v e r s i o n >2 .26 </ v e r s i o n ></ dependency ><dependency >< groupId > org . g l a s s f i s h . j e r s e y . c o n t a i n e r s < / groupId >< a r t i f a c t I d > j e r s e y −c o n t a i n e r −s e r v l e t < / a r t i f a c t I d >< v e r s i o n >2 .26 </ v e r s i o n ></ dependency ><dependency >< groupId > org . h i b e r n a t e < / groupId >< a r t i f a c t I d > h i b e r n a t e −core < / a r t i f a c t I d >< v e r s i o n > 5 . 2 . 1 2 . F i n a l < / v e r s i o n ></ dependency ><dependency >< groupId > j a v a x . ws . r s < / groupId >< a r t i f a c t I d > j a v a x . ws . r s−ap i < / a r t i f a c t I d >< v e r s i o n >2 .1 < / v e r s i o n ></ dependency ><dependency >< groupId > org . mar iadb . jdbc < / groupId >< a r t i f a c t I d >mariadb−j ava−c l i e n t < / a r t i f a c t I d >< v e r s i o n > 2 . 2 . 1 < / v e r s i o n ></ dependency ><dependency >< groupId > j u n i t < / g roupId >< a r t i f a c t I d > j u n i t < / a r t i f a c t I d >< v e r s i o n > 3 . 8 . 1 < / v e r s i o n ><scope > t e s t < / scope ></ dependency ></ d e p e n d e n c i e s >< b u i l d ><f inalName > b a r t e r i n g < / f ina lName ></ b u i l d ></ p r o j e c t >

Le pom.xml ci-dessous est paramétré pour récupérer les classes JDBC pour MariaDB. Si vousutilisez MySQL alors remplacez-y la dépendance à MariaDB par celle-ci :

< groupId >mysql < / groupId >< a r t i f a c t I d >mysql−c o n n e c t o r−j ava < / a r t i f a c t I d >< v e r s i o n > 5 . 1 . 4 5 < / v e r s i o n >

Depuis la racine de votre projet Maven, créez manuellement le dossier src/main/java/net/dotmyself/file/source/_13.

3.3 Les flux XML

Les objets Java que vous sérialiserez en XML ressembleront aux flux XML suivant :

5

<?xml v e r s i o n = " 1 . 0 " e n c o d i n g ="UTF−8" s t a n d a l o n e =" yes "? >< p e r s o n i d ="1" ><name>Gates < / name>< f i r s t n a m e > B i l l < / f i r s t n a m e >< l o c a t i o n > Q u a r t i e r S a i n t Bruno </ l o c a t i o n >< s e r v i c e s >< s e r v i c e i d ="1" >< d e s c r i p t i o n > I n s t a l l a t i o n de Windows 7 </ d e s c r i p t i o n ></ s e r v i c e >< s e r v i c e i d ="2" >< d e s c r i p t i o n > Forma t ion d ’1 h e u r e en Economie < / d e s c r i p t i o n ></ s e r v i c e ></ s e r v i c e s ></ per son >

Ce flux XML pouvant être validé par le schéma XSD suivant :

<?xml v e r s i o n = " 1 . 0 " e n c o d i n g =" u t f −8"?><xsd : schema t a r g e t N a m e s p a c e =" h t t p : / / f i l e . d o t m y s e l f . n e t / s o u r c e / 1 3 /

model "xmlns : xsd =" h t t p : / / www. w3 . org / 2 0 0 1 / XMLSchema" e l e m e n t F o r m D e f a u l t ="

q u a l i f i e d "xmlns =" h t t p : / / f i l e . d o t m y s e l f . n e t / s o u r c e / 1 3 / model "><xsd : e l e m e n t name=" p e r s o n "><xsd : complexType ><xsd : sequence ><xsd : e l e m e n t name="name " t y p e =" xsd : s t r i n g " / ><xsd : e l e m e n t name=" f i r s t n a m e " t y p e =" xsd : s t r i n g " / ><xsd : e l e m e n t name=" l o c a t i o n " t y p e =" xsd : s t r i n g " / ><xsd : e l e m e n t name=" s e r v i c e s "><xsd : complexType ><xsd : sequence ><xsd : e l e m e n t maxOccurs =" unbounded " r e f =" s e r v i c e " / ></ xsd : sequence ></ xsd : complexType ></ xsd : e lement ></ xsd : sequence ><xsd : a t t r i b u t e name=" i d " t y p e =" xsd : i n t " / ></ xsd : complexType ></ xsd : e lement ><xsd : e l e m e n t name=" s e r v i c e "><xsd : complexType ><xsd : sequence ><xsd : e l e m e n t name=" d e s c r i p t i o n " t y p e =" xsd : s t r i n g " / ></ xsd : sequence ><xsd : a t t r i b u t e name=" i d " t y p e =" xsd : i n t " / ></ xsd : complexType ></ xsd : e lement >

6

</ xsd : schema >

3.4 La couche persistance

Les classes de la couche persistance appartiennent toutes au package net.dotmyself.file.source._13.model,et contiennent des annotations :

— JAXB (i.e. javax.xml.bind.annotation.*) : Pour la sérialisation java vers XML (et viceversa).

— JPA (i.e. javax.persistence.*) : Pour le mapping Objet-RelationnelCréez la classe Service.java :

package n e t . d o t m y s e l f . f i l e . s o u r c e . _13 . model ;i m p o r t j a v a . i o . S e r i a l i z a b l e ;i m p o r t j a v a x . p e r s i s t e n c e . Column ;i m p o r t j a v a x . p e r s i s t e n c e . E n t i t y ;i m p o r t j a v a x . p e r s i s t e n c e . Fe tchType ;i m p o r t j a v a x . p e r s i s t e n c e . G e n e r a t e d V a l u e ;i m p o r t j a v a x . p e r s i s t e n c e . G e n e r a t i o n T y p e ;i m p o r t j a v a x . p e r s i s t e n c e . Id ;i m p o r t j a v a x . p e r s i s t e n c e . JoinColumn ;i m p o r t j a v a x . p e r s i s t e n c e . Lob ;i m p o r t j a v a x . p e r s i s t e n c e . ManyToOne ;i m p o r t j a v a x . p e r s i s t e n c e . NamedQuery ;i m p o r t j a v a x . p e r s i s t e n c e . Tab le ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlAccessType ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlAccessorType ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . X m l A t t r i b u t e ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlElement ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlRootElement ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . X m l T r a n s i e n t ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlType ;/ * ** The p e r s i s t e n t c l a s s f o r t h e s e r v i c e d a t a b a s e t a b l e .** @author H y a c i n t h e MENIET* /@XmlAccessorType ( XmlAccessType . FIELD )@XmlType ( name = " " , p ropOrde r = {" d e s c r i p t i o n "} )@XmlRootElement ( name = " s e r v i c e " )@Enti ty@Table ( name = " s e r v i c e " )@NamedQuery ( name = S e r v i c e . FIND_BY_PERSON ,que ry = "SELECT s FROM S e r v i c e s WHERE s . i d = : s e r v i c e I d AND s .

p e r s o n . i d = : p e r s o n I d " )p u b l i c c l a s s S e r v i c e implemen t s S e r i a l i z a b l e {

7

p r i v a t e s t a t i c f i n a l l ong s e r i a l V e r s i o n U I D = 1L ;p u b l i c s t a t i c f i n a l S t r i n g FIND_BY_PERSON = " S e r v i c e . f i n B y P e r s o n

" ;@XmlElement ( r e q u i r e d = t r u e )@Lob ( )@Column ( n u l l a b l e = f a l s e )p r o t e c t e d S t r i n g d e s c r i p t i o n ;@XmlAtt r ibute ( name = " i d " )@Id@GeneratedValue ( s t r a t e g y = G e n e r a t i o n T y p e . IDENTITY )p r o t e c t e d i n t i d ;/ / b i−d i r e c t i o n a l many−to−one a s s o c i a t i o n t o Member@XmlTransient@ManyToOne ( f e t c h = FetchType .LAZY)@JoinColumn ( name = " p e r s o n _ i d " )p r o t e c t e d Pe r so n p e r s o n ;p u b l i c S e r v i c e ( ) {}/ * ** Gets t h e v a l u e o f t h e d e s c r i p t i o n p r o p e r t y .** @return* p o s s i b l e o b j e c t i s* { @link S t r i n g }** /p u b l i c S t r i n g g e t D e s c r i p t i o n ( ) {r e t u r n d e s c r i p t i o n ;}/ * ** S e t s t h e v a l u e o f t h e d e s c r i p t i o n p r o p e r t y .** @param v a l u e* a l l o w e d o b j e c t i s* { @link S t r i n g }** /p u b l i c vo id s e t D e s c r i p t i o n ( S t r i n g v a l u e ) {t h i s . d e s c r i p t i o n = v a l u e ;}/ * ** Gets t h e v a l u e o f t h e i d p r o p e r t y .** @return* p o s s i b l e v a l u e t y p e i s* { @link i n t }** /p u b l i c i n t g e t I d ( ) {

8

r e t u r n i d ;}/ * ** S e t s t h e v a l u e o f t h e i d p r o p e r t y .** @param v a l u e* a l l o w e d v a l u e t y p e i s* { @link i n t }** /p u b l i c vo id s e t I d ( i n t v a l u e ) {t h i s . i d = v a l u e ;}/ * ** Gets t h e v a l u e o f t h e P e r s on p r o p e r t y .** @return* p o s s i b l e o b j e c t i s* { @link P e r so n }** /p u b l i c P e r son g e t P e r s o n ( ) {r e t u r n p e r s o n ;}/ * ** S e t s t h e v a l u e o f t h e Pe r s on p r o p e r t y .** @param v a l u e* a l l o w e d o b j e c t i s* { @link P e r so n }** /p u b l i c vo id s e t P e r s o n ( P e r so n v a l u e ) {t h i s . p e r s o n = v a l u e ;}}

Créez la classe Person.java :

package n e t . d o t m y s e l f . f i l e . s o u r c e . _13 . model ;i m p o r t j a v a . i o . S e r i a l i z a b l e ;i m p o r t j a v a . u t i l . L i s t ;i m p o r t j a v a x . p e r s i s t e n c e . CascadeType ;i m p o r t j a v a x . p e r s i s t e n c e . Column ;i m p o r t j a v a x . p e r s i s t e n c e . E n t i t y ;i m p o r t j a v a x . p e r s i s t e n c e . Fe tchType ;i m p o r t j a v a x . p e r s i s t e n c e . G e n e r a t e d V a l u e ;i m p o r t j a v a x . p e r s i s t e n c e . G e n e r a t i o n T y p e ;i m p o r t j a v a x . p e r s i s t e n c e . Id ;

9

i m p o r t j a v a x . p e r s i s t e n c e . JoinColumn ;i m p o r t j a v a x . p e r s i s t e n c e . NamedAt t r ibu teNode ;i m p o r t j a v a x . p e r s i s t e n c e . NamedEnt i tyGraph ;i m p o r t j a v a x . p e r s i s t e n c e . OneToMany ;i m p o r t j a v a x . p e r s i s t e n c e . OrderBy ;i m p o r t j a v a x . p e r s i s t e n c e . Tab le ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlAccessType ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlAccessorType ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . X m l A t t r i b u t e ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlElement ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlElementWrapper ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlRootElement ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlType ;/ * ** The p e r s i s t e n t c l a s s f o r t h e p e r s o n d a t a b a s e t a b l e .** @author H y a c i n t h e MENIET* /@XmlAccessorType ( XmlAccessType . FIELD )@XmlType ( name = " " , p ropOrde r = {" name " ," f i r s t n a m e " ," l o c a t i o n " ," s e r v i c e s "} )@XmlRootElement ( name = " p e r s o n " )@Enti ty@NamedEntityGraph ( name = " graph . P e r s on . s e r v i c e s " ,a t t r i b u t e N o d e s = @NamedAttributeNode ( " s e r v i c e s " ) )@Table ( name = " p e r s o n " )p u b l i c c l a s s P e r so n implemen t s S e r i a l i z a b l e {p r i v a t e s t a t i c f i n a l l ong s e r i a l V e r s i o n U I D = 1L ;p u b l i c s t a t i c f i n a l S t r i n g PERSISTENCE_UNIT = " B a r t e r i n g P U " ;@XmlElement ( r e q u i r e d = t r u e )@Column ( n u l l a b l e = f a l s e )p r o t e c t e d S t r i n g name ;@XmlElement ( r e q u i r e d = f a l s e )@Column ( n u l l a b l e = t r u e )p r o t e c t e d S t r i n g f i r s t n a m e ;@XmlElement ( r e q u i r e d = f a l s e )@Column ( n u l l a b l e = t r u e )p r o t e c t e d S t r i n g l o c a t i o n ;/ / b i−d i r e c t i o n a l many−to−one a s s o c i a t i o n t o S e r v i c e@XmlElement ( name = " s e r v i c e " , r e q u i r e d = t r u e )@XmlElementWrapper ( name = " s e r v i c e s " , r e q u i r e d = t r u e )@OneToMany ( f e t c h = FetchType . LAZY, c a s c a d e = CascadeType . ALL)@JoinColumn ( name = " p e r s o n _ i d " , i n s e r t a b l e = t r u e , u p d a t a b l e =

t r u e )@OrderBy ( " i d ASC" )

10

p r o t e c t e d L i s t < S e r v i c e > s e r v i c e s ;@XmlAtt r ibute ( name = " i d " )@Id@GeneratedValue ( s t r a t e g y = G e n e r a t i o n T y p e . IDENTITY )p r o t e c t e d i n t i d ;p u b l i c P e r son ( ) {}/ * ** Gets t h e v a l u e o f t h e name p r o p e r t y .** @return* p o s s i b l e o b j e c t i s* { @link S t r i n g }** /p u b l i c S t r i n g getName ( ) {r e t u r n name ;}/ * ** S e t s t h e v a l u e o f t h e name p r o p e r t y .** @param v a l u e* a l l o w e d o b j e c t i s* { @link S t r i n g }** /p u b l i c vo id setName ( S t r i n g v a l u e ) {t h i s . name = v a l u e ;}/ * ** Gets t h e v a l u e o f t h e f i r s t n a m e p r o p e r t y .** @return* p o s s i b l e o b j e c t i s* { @link S t r i n g }** /p u b l i c S t r i n g g e t F i r s t n a m e ( ) {r e t u r n f i r s t n a m e ;}/ * ** S e t s t h e v a l u e o f t h e f i r s t n a m e p r o p e r t y .** @param v a l u e* a l l o w e d o b j e c t i s* { @link S t r i n g }** /p u b l i c vo id s e t F i r s t n a m e ( S t r i n g v a l u e ) {

11

t h i s . f i r s t n a m e = v a l u e ;}/ * ** Gets t h e v a l u e o f t h e l o c a t i o n p r o p e r t y .** @return* p o s s i b l e o b j e c t i s* { @link S t r i n g }** /p u b l i c S t r i n g g e t L o c a t i o n ( ) {r e t u r n l o c a t i o n ;}/ * ** S e t s t h e v a l u e o f t h e l o c a t i o n p r o p e r t y .** @param v a l u e* a l l o w e d o b j e c t i s* { @link S t r i n g }** /p u b l i c vo id s e t L o c a t i o n ( S t r i n g v a l u e ) {t h i s . l o c a t i o n = v a l u e ;}/ * ** Gets a r e f e r e n c e t o t h e l i s t o f s e r v i c e s p r o p e r t y .** @return* p o s s i b l e o b j e c t s o f t h e f o l l o w i n g t y p e ( s )* { @link S e r v i c e }** /p u b l i c L i s t < S e r v i c e > g e t S e r v i c e s ( ) {r e t u r n s e r v i c e s ;}/ * ** S e t s t h e v a l u e o f t h e l i s t o f s e r v i c e s p r o p e r t y .** @param v a l u e* O b j e c t s o f t h e f o l l o w i n g t y p e ( s ) a r e a l l o w e d i n t h e l i s t* { @link S e r v i c e }** /p u b l i c vo id s e t S e r v i c e s ( L i s t < S e r v i c e > v a l u e ) {t h i s . s e r v i c e s = v a l u e ;}/ * ** Gets t h e v a l u e o f t h e i d p r o p e r t y .*

12

* @return* p o s s i b l e v a l u e t y p e i s* { @link i n t }** /p u b l i c i n t g e t I d ( ) {r e t u r n i d ;}/ * ** S e t s t h e v a l u e o f t h e i d p r o p e r t y .** @param v a l u e* a l l o w e d v a l u e t y p e i s* { @link i n t }** /p u b l i c vo id s e t I d ( i n t v a l u e ) {t h i s . i d = v a l u e ;}}

3.5 La couche service

Les classes de la couche service appartiennent toutes au package net.dotmyself.bartering.service.Créez la classe ServiceResource.java :

package n e t . d o t m y s e l f . b a r t e r i n g . s e r v i c e ;i m p o r t j a v a . n e t . URI ;i m p o r t j a v a . u t i l . HashMap ;i m p o r t j a v a . u t i l . L i s t ;i m p o r t j a v a . u t i l . Map ;i m p o r t j a v a x . p e r s i s t e n c e . E n t i t y G r a p h ;i m p o r t j a v a x . p e r s i s t e n c e . E n t i t y M a n a g e r ;i m p o r t j a v a x . p e r s i s t e n c e . E n t i t y M a n a g e r F a c t o r y ;i m p o r t j a v a x . p e r s i s t e n c e . E n t i t y T r a n s a c t i o n ;i m p o r t j a v a x . p e r s i s t e n c e . P e r s i s t e n c e ;i m p o r t j a v a x . ws . r s . Consumes ;i m p o r t j a v a x . ws . r s . DELETE ;i m p o r t j a v a x . ws . r s . GET;i m p o r t j a v a x . ws . r s . NotFoundExcep t ion ;i m p o r t j a v a x . ws . r s . POST ;i m p o r t j a v a x . ws . r s . PUT ;i m p o r t j a v a x . ws . r s . Pa th ;i m p o r t j a v a x . ws . r s . PathParam ;i m p o r t j a v a x . ws . r s . P r o d u c e s ;i m p o r t j a v a x . ws . r s . c o r e . MediaType ;i m p o r t j a v a x . ws . r s . c o r e . Response ;i m p o r t n e t . d o t m y s e l f . f i l e . s o u r c e . _13 . model . S e r v i c e ;

13

i m p o r t n e t . d o t m y s e l f . f i l e . s o u r c e . _13 . model . P e r so n ;/ * *** The S e r v i c e r e s o u r c e t h a t r e t u r n s s e r v i c e ’ s i n f o r m a t i o n s .** @author H y a c i n t h e MENIET* /p u b l i c c l a s s S e r v i c e R e s o u r c e {p r i v a t e f i n a l i n t p e r s o n I d ;p u b l i c S e r v i c e R e s o u r c e ( i n t p i d ) {t h i s . p e r s o n I d = p i d ;}@GET@Produces ( MediaType . APPLICATION_XML)p u b l i c L i s t < S e r v i c e > g e t S e r v i c e s ( ) {E n t i t y M a n a g e r F a c t o r y emf = P e r s i s t e n c e. c r e a t e E n t i t y M a n a g e r F a c t o r y ( Pe r so n . PERSISTENCE_UNIT ) ;E n t i t y M a n a g e r em = emf . c r e a t e E n t i t y M a n a g e r ( ) ;E n t i t y G r a p h graph = em . g e t E n t i t y G r a p h ( " g raph . Pe r so n . s e r v i c e s " ) ;Map h i n t s = new HashMap ( ) ;h i n t s . p u t ( " j a v a x . p e r s i s t e n c e . f e t c h g r a p h " , g raph ) ;Pe r s on p = em . f i n d ( P e r s on . c l a s s , t h i s . p e r s o n I d , h i n t s ) ;i f ( n u l l == p ) {emf . c l o s e ( ) ;th row new NotFoundExcep t ion ( " p e r s o n wi th p e r s o n I d =" + t h i s .

p e r s o n I d+ " does n o t e x i s t ! " ) ;}emf . c l o s e ( ) ;r e t u r n p . g e t S e r v i c e s ( ) ;}@GET@Path ( " { i d : \ \ d +}" )@Produces ( MediaType . APPLICATION_XML)p u b l i c S e r v i c e g e t S e r v i c e ( @PathParam ( " i d " ) i n t i d ) {S e r v i c e s ;E n t i t y M a n a g e r F a c t o r y emf ;emf = P e r s i s t e n c e. c r e a t e E n t i t y M a n a g e r F a c t o r y ( Pe r so n . PERSISTENCE_UNIT ) ;s = ( S e r v i c e ) emf . c r e a t e E n t i t y M a n a g e r ( ) . c rea teNamedQuery ( S e r v i c e .

FIND_BY_PERSON) . s e t P a r a m e t e r ( " s e r v i c e I d " , i d ). s e t P a r a m e t e r ( " p e r s o n I d " , t h i s . p e r s o n I d ) . g e t S i n g l e R e s u l t ( ) ;emf . c l o s e ( ) ;r e t u r n s ;}@POST@Consumes ( MediaType . APPLICATION_XML)p u b l i c Response c r e a t e S e r v i c e ( S e r v i c e s ) {E n t i t y M a n a g e r F a c t o r y emf = P e r s i s t e n c e

14

. c r e a t e E n t i t y M a n a g e r F a c t o r y ( Pe r so n . PERSISTENCE_UNIT ) ;E n t i t y M a n a g e r em = emf . c r e a t e E n t i t y M a n a g e r ( ) ;E n t i t y T r a n s a c t i o n t x = em . g e t T r a n s a c t i o n ( ) ;t x . b e g i n ( ) ;Pe r s on p = em . f i n d ( P e r s on . c l a s s , t h i s . p e r s o n I d ) ;s . s e t I d ( 0 ) ;s . s e t P e r s o n ( p ) ;em . p e r s i s t ( s ) ;t x . commit ( ) ;em . c l o s e ( ) ;emf . c l o s e ( ) ;r e t u r n Response . c r e a t e d ( URI . c r e a t e ( " / b a r t e r i n g / a p i / p e r s o n s / " + t h i s

. p e r s o n I d+ " / s e r v i c e s / " + s . g e t I d ( ) ) ) . b u i l d ( ) ;}@PUT@Path ( " { i d : \ \ d +}" )@Consumes ( MediaType . APPLICATION_XML)p u b l i c vo id u p d a t e S e r v i c e ( @PathParam ( " i d " ) i n t id , S e r v i c e

e x t S e r v i c e ) {E n t i t y M a n a g e r F a c t o r y emf = P e r s i s t e n c e. c r e a t e E n t i t y M a n a g e r F a c t o r y ( Pe r so n . PERSISTENCE_UNIT ) ;E n t i t y M a n a g e r em = emf . c r e a t e E n t i t y M a n a g e r ( ) ;E n t i t y T r a n s a c t i o n t x = em . g e t T r a n s a c t i o n ( ) ;t x . b e g i n ( ) ;S e r v i c e i n t S e r v i c e = em . f i n d ( S e r v i c e . c l a s s , i d ) ;i f ( n u l l == i n t S e r v i c e ) {throw new NotFoundExcep t ion ( " s e r v i c e wi th p e r s o n I d ="+ t h i s . p e r s o n I d + " and s e r v i c e I d =" + i d + " n o t found " ) ;}i n t S e r v i c e . s e t D e s c r i p t i o n ( e x t S e r v i c e . g e t D e s c r i p t i o n ( ) ) ;em . merge ( i n t S e r v i c e ) ;t x . commit ( ) ;em . c l o s e ( ) ;emf . c l o s e ( ) ;}@DELETE@Path ( " { i d : \ \ d +}" )p u b l i c vo id d e l e t e S e r v i c e ( @PathParam ( " i d " ) i n t i d ) {E n t i t y M a n a g e r F a c t o r y emf = P e r s i s t e n c e. c r e a t e E n t i t y M a n a g e r F a c t o r y ( Pe r so n . PERSISTENCE_UNIT ) ;E n t i t y M a n a g e r em = emf . c r e a t e E n t i t y M a n a g e r ( ) ;E n t i t y T r a n s a c t i o n t x = em . g e t T r a n s a c t i o n ( ) ;t x . b e g i n ( ) ;S e r v i c e s = em . f i n d ( S e r v i c e . c l a s s , i d ) ;i f ( n u l l != s ) {em . remove ( s ) ;}t x . commit ( ) ;

15

em . c l o s e ( ) ;emf . c l o s e ( ) ;}}

Créez la classe PersonResource.java :

package n e t . d o t m y s e l f . b a r t e r i n g . s e r v i c e ;i m p o r t j a v a . u t i l . HashMap ;i m p o r t j a v a . u t i l . Map ;i m p o r t j a v a x . p e r s i s t e n c e . E n t i t y G r a p h ;i m p o r t j a v a x . p e r s i s t e n c e . E n t i t y M a n a g e r ;i m p o r t j a v a x . p e r s i s t e n c e . E n t i t y M a n a g e r F a c t o r y ;i m p o r t j a v a x . p e r s i s t e n c e . P e r s i s t e n c e ;i m p o r t j a v a x . ws . r s . GET;i m p o r t j a v a x . ws . r s . NotFoundExcep t ion ;i m p o r t j a v a x . ws . r s . Pa th ;i m p o r t j a v a x . ws . r s . PathParam ;i m p o r t j a v a x . ws . r s . P r o d u c e s ;i m p o r t j a v a x . ws . r s . c o r e . MediaType ;i m p o r t n e t . d o t m y s e l f . f i l e . s o u r c e . _13 . model . P e r so n ;/ * *** The P e r s on r e s o u r c e t h a t r e t u r n s person ’ s i n f o r m a t i o n s .** @author H y a c i n t h e MENIET* /@Path ( " / p e r s o n s " )p u b l i c c l a s s P e r s o n R e s o u r c e {

@GET@Path ( " { i d : \ \ d +}" )@Produces ( MediaType . APPLICATION_XML)p u b l i c P e r son g e t P e r s o n ( @PathParam ( " i d " ) i n t i d ) {E n t i t y M a n a g e r F a c t o r y emf = P e r s i s t e n c e. c r e a t e E n t i t y M a n a g e r F a c t o r y ( Pe r so n . PERSISTENCE_UNIT ) ;E n t i t y M a n a g e r em = emf . c r e a t e E n t i t y M a n a g e r ( ) ;E n t i t y G r a p h graph = em . g e t E n t i t y G r a p h ( " g raph . Pe r so n . s e r v i c e s " ) ;Map h i n t s = new HashMap ( ) ;h i n t s . p u t ( " j a v a x . p e r s i s t e n c e . f e t c h g r a p h " , g raph ) ;Pe r s on p = em . f i n d ( P e r s on . c l a s s , id , h i n t s ) ;i f ( n u l l == p ) {emf . c l o s e ( ) ;th row new NotFoundExcep t ion ( " p e r s o n wi th p e r s o n I d =" + i d+ " does n o t e x i s t ! " ) ;}emf . c l o s e ( ) ;r e t u r n p ;}@Path ( " { i d : \ \ d +} / s e r v i c e s " )

16

p u b l i c S e r v i c e R e s o u r c e g e t R e s o u r c e s ( @PathParam ( " i d " ) i n t i d ) {r e t u r n new S e r v i c e R e s o u r c e ( i d ) ;}}

Terminez par la classe BarteringApplication.java qui indique à la Servlet de Jersey quelles classesresources charger :

package n e t . d o t m y s e l f . b a r t e r i n g . s e r v i c e ;i m p o r t j a v a . u t i l . HashSet ;i m p o r t j a v a . u t i l . S e t ;i m p o r t j a v a x . ws . r s . A p p l i c a t i o n P a t h ;i m p o r t j a v a x . ws . r s . c o r e . A p p l i c a t i o n ;/ * ** Used t o t e l l s e r v e r c o n t a i n e r which R e s t f u l web s e r v i c e s ( @Path

a n n o t a t e d* c l a s s e s ) we want d e p l o y e d .** @author H y a c i n t h e MENIET* /@ A p p l i c a t i o n P a t h ( " a p i " )p u b l i c c l a s s B a r t e r i n g A p p l i c a t i o n e x t e n d s A p p l i c a t i o n {@Overridep u b l i c Set < Class <?>> g e t C l a s s e s ( ) {Set < Class <?>> c l a s s e s = new HashSet < >() ;c l a s s e s . add ( n e t . d o t m y s e l f . b a r t e r i n g . s e r v i c e . P e r s o n R e s o u r c e . c l a s s )

;r e t u r n c l a s s e s ;}}

3.6 Fichiers de configuration

Ecrasez le fichier src/main/webapp/WEB-INF/web.xml avec celui-ci :

<?xml v e r s i o n = " 1 . 0 " e n c o d i n g ="UTF−8"?><web−app xmlns =" h t t p : / / j a v a . sun . com / xml / ns / j a v a e e "xmlns : x s i =" h t t p : / / www. w3 . org / 2 0 0 1 / XMLSchema−i n s t a n c e "x s i : s chemaLoca t ion =" h t t p : / / j a v a . sun . com / xml / ns / j a v a e eh t t p : / / j a v a . sun . com / xml / ns / j a v a e e / web−app_3_0 . xsd "v e r s i o n ="3 .0" >< d i s p l a y −name> B a r t e r i n g web a p p l i c a t i o n < / d i s p l a y −name>< s e r v l e t >< s e r v l e t −name> n e t . d o t m y s e l f . b a r t e r i n g . s e r v i c e .

B a r t e r i n g A p p l i c a t i o n < / s e r v l e t −name></ s e r v l e t ></web−app >

17

Créez le fichier src/main/resources/META-INF/persistence.xml suivant :

<?xml v e r s i o n = " 1 . 0 " e n c o d i n g ="UTF−8"?>< p e r s i s t e n c e v e r s i o n = " 2 . 1 " xmlns =" h t t p : / / xmlns . j c p . o rg / xml / ns /

p e r s i s t e n c e "xmlns : x s i =" h t t p : / / www. w3 . org / 2 0 0 1 / XMLSchema−i n s t a n c e "x s i : s chemaLoca t ion =" h t t p : / / xmlns . j c p . o rg / xml / ns / p e r s i s t e n c eh t t p : / / xmlns . j c p . o rg / xml / ns / p e r s i s t e n c e / p e r s i s t e n c e _ 2 _ 1 . xsd ">< p e r s i s t e n c e −u n i t name=" B a r t e r i n g P U ">< p r o v i d e r > org . h i b e r n a t e . j p a . H i b e r n a t e P e r s i s t e n c e P r o v i d e r < /

p r o v i d e r >< p r o p e r t i e s >< p r o p e r t y name=" j a v a x . p e r s i s t e n c e . j d b c . d r i v e r " v a l u e =" org . mar iadb

. j d b c . D r i v e r " / >< p r o p e r t y name=" j a v a x . p e r s i s t e n c e . j d b c . u s e r " v a l u e =" b a r t u s e r " / >< p r o p e r t y name=" j a v a x . p e r s i s t e n c e . j d b c . password " v a l u e =" bar tpwd "

/ >< p r o p e r t y name=" j a v a x . p e r s i s t e n c e . j d b c . u r l " v a l u e =" j d b c : mar iadb

: / / l o c a l h o s t : 3 3 0 6 / b a r t e r i n g " / >< p r o p e r t y name=" h i b e r n a t e . hbm2ddl . a u t o " v a l u e =" u p d a t e " / >< p r o p e r t y name=" h i b e r n a t e . d i a l e c t " v a l u e =" org . h i b e r n a t e . d i a l e c t .

Mar iaDB53Dia lec t " / >< p r o p e r t y name=" h i b e r n a t e . use_sq l_comments " v a l u e =" t r u e " / >< p r o p e r t y name=" h i b e r n a t e . show_sql " v a l u e =" t r u e " / ></ p r o p e r t i e s ></ p e r s i s t e n c e −u n i t ></ p e r s i s t e n c e >

Le fichier persistence.xml ci-dessus est paramétré pour se connecter à MariaDB. Si vous utilisezMySQL alors remplacez les 3 lignes spécifiques à MariaDB par leurs équivalentes MySQL :

< p r o p e r t y name=&quo t ; j a v a x . p e r s i s t e n c e . j d b c . d r i v e r&quo t ; v a l u e=&quo t ; o rg . h i b e r n a t e . d i a l e c t . MySQL57InnoDBDialect&#039;& quo t ; / >

< p r o p e r t y name=&quo t ; j a v a x . p e r s i s t e n c e . j d b c . u r l&quo t ; v a l u e=&quo t; j d b c : mysql : / / l o c a l h o s t : 3 3 0 6 / b a r t e r i n g&quo t ; / >

< p r o p e r t y name=&quo t ; h i b e r n a t e . d i a l e c t&quo t ; v a l u e=&quo t ; com .mysql . j d b c . D r i v e r&quo t ; / >

4. Déploiement et test du Web service

4.1 Configuration et déploiement

Générez le war de votre projet maven. Quand vous avez terminé poussez simplement votre wardans $CATALINA_HOME/webapps/ et redémarrez Tomcat. Vous pouvez consulter l’applicationweb en vous connectant à l’adresse http://localhost:8080/bartering/. En particulier, vous pouvezconsulter le flux XML de la personne 1 à l’adresse http://localhost:8080/bartering/api/persons/1

18

5. Le client

5.1 Projet Maven

Créez un nouveau projet Maven (commande à taper à la racine de votre workspace) :

$ mvn a r c h e t y p e : g e n e r a t e −DgroupId= n e t . d o t m y s e l f . b a r t e r i n g −D a r t i f a c t I d = b a r t e r i n g −c l i e n t −D v e r s i o n =1 .0 −Dpackage= n e t .d o t m y s e l f . b a r t e r i n g −D a r c h e t y p e A r t i f a c t I d =maven−a r c h e t y p e−q u i c k s t a r t −D i n t e r a c t i v e M o d e = f a l s e

Ecrasez le pom.xml généré, dans le dossier bartering-client, par ce pom.xml.

< p r o j e c t xmlns =" h t t p : / / maven . apache . o rg /POM/ 4 . 0 . 0 " xmlns : x s i ="h t t p : / / www. w3 . org / 2 0 0 1 / XMLSchema−i n s t a n c e "

x s i : s chemaLoca t ion =" h t t p : / / maven . apache . o rg /POM/ 4 . 0 . 0 h t t p : / /maven . apache . o rg / maven−v4_0_0 . xsd ">

<modelVers ion > 4 . 0 . 0 < / modelVers ion >< groupId > n e t . d o t m y s e l f . b a r t e r i n g < / groupId >< a r t i f a c t I d > b a r t e r i n g −c l i e n t < / a r t i f a c t I d >< packag ing > j a r < / packag ing >< v e r s i o n >1 .0 < / v e r s i o n ><name> b a r t e r i n g −c l i e n t < / name>< u r l > h t t p : / / maven . apache . org < / u r l >< p r o p e r t i e s >< p r o j e c t . b u i l d . sou rceEncod ing >UTF−8</ p r o j e c t . b u i l d . sou rceEncod ing

><maven . c o m p i l e r . sou rce >1 .7 < / maven . c o m p i l e r . sou rce ><maven . c o m p i l e r . t a r g e t >1 .7 < / maven . c o m p i l e r . t a r g e t ></ p r o p e r t i e s >< d e p e n d e n c i e s ><dependency >< groupId > org . g l a s s f i s h . j e r s e y . core < / groupId >< a r t i f a c t I d > j e r s e y −c l i e n t < / a r t i f a c t I d >< v e r s i o n >2 .26 </ v e r s i o n ></ dependency ><dependency >< groupId > org . g l a s s f i s h . j e r s e y . i n j e c t < / g roupId >< a r t i f a c t I d > j e r s e y −hk2 </ a r t i f a c t I d >< v e r s i o n >2 .26 </ v e r s i o n ></ dependency ><dependency >< groupId > org . g l a s s f i s h . j e r s e y . media < / groupId >< a r t i f a c t I d > j e r s e y −media−j axb < / a r t i f a c t I d >< v e r s i o n >2 .26 </ v e r s i o n ></ dependency ><dependency >< groupId > j u n i t < / g roupId >< a r t i f a c t I d > j u n i t < / a r t i f a c t I d >

19

< v e r s i o n > 3 . 8 . 1 < / v e r s i o n ><scope > t e s t < / scope ></ dependency ></ d e p e n d e n c i e s ></ p r o j e c t >

5.2 Programme client

Pour désérialiser votre flux XML en java, vous aurez besoin de classes munies d’annotationsJAXB. Créez la classe Service.java :

package n e t . d o t m y s e l f . f i l e . s o u r c e . _13 . model ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlAccessType ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlAccessorType ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . X m l A t t r i b u t e ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlElement ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlRootElement ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlType ;/ * ** The j a x b c l a s s f o r a s e r v i c e .** @author H y a c i n t h e MENIET* /@XmlAccessorType ( XmlAccessType . FIELD )@XmlType ( name = " " , p ropOrde r = {" d e s c r i p t i o n "} )@XmlRootElement ( name = " s e r v i c e " )p u b l i c c l a s s S e r v i c e {@XmlElement ( r e q u i r e d = t r u e )p r o t e c t e d S t r i n g d e s c r i p t i o n ;@XmlAtt r ibute ( name = " i d " )p r o t e c t e d I n t e g e r i d ;p u b l i c S e r v i c e ( ) {}p u b l i c S e r v i c e ( S t r i n g d e s c r i p t i o n ) {t h i s . d e s c r i p t i o n = d e s c r i p t i o n ;}/ * ** Gets t h e v a l u e o f t h e d e s c r i p t i o n p r o p e r t y .** @return* p o s s i b l e o b j e c t i s* { @link S t r i n g }** /p u b l i c S t r i n g g e t D e s c r i p t i o n ( ) {r e t u r n d e s c r i p t i o n ;

20

}/ * ** S e t s t h e v a l u e o f t h e d e s c r i p t i o n p r o p e r t y .** @param v a l u e* a l l o w e d o b j e c t i s* { @link S t r i n g }** /p u b l i c vo id s e t D e s c r i p t i o n ( S t r i n g v a l u e ) {t h i s . d e s c r i p t i o n = v a l u e ;}/ * ** Gets t h e v a l u e o f t h e i d p r o p e r t y .** @return* p o s s i b l e o b j e c t i s* { @link I n t e g e r }** /p u b l i c I n t e g e r g e t I d ( ) {r e t u r n i d ;}/ * ** S e t s t h e v a l u e o f t h e i d p r o p e r t y .** @param v a l u e* a l l o w e d o b j e c t i s* { @link I n t e g e r }** /p u b l i c vo id s e t I d ( I n t e g e r v a l u e ) {t h i s . i d = v a l u e ;}@Overridep u b l i c S t r i n g t o S t r i n g ( ) {r e t u r n " S e r v i c e {" + " d e s c r i p t i o n =" + d e s c r i p t i o n + " , i d =" + i d +

’ } ’ ;}}

Créez la classe Person.java :

package n e t . d o t m y s e l f . f i l e . s o u r c e . _13 . model ;i m p o r t j a v a . u t i l . A r r a ys ;i m p o r t j a v a . u t i l . C o l l e c t i o n s ;i m p o r t j a v a . u t i l . L i s t ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlAccessType ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlAccessorType ;

21

i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . X m l A t t r i b u t e ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlElement ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlElementWrapper ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlRootElement ;i m p o r t j a v a x . xml . b ind . a n n o t a t i o n . XmlType ;/ * ** The j a x b c l a s s f o r a p e r s o n .** @author H y a c i n t h e MENIET* /@XmlAccessorType ( XmlAccessType . FIELD )@XmlType ( name = " " , p ropOrde r = {" name " ," f i r s t n a m e " ," l o c a t i o n " ," s e r v i c e s "} )@XmlRootElement ( name = " p e r s o n " )p u b l i c c l a s s P e r so n {@XmlElement ( r e q u i r e d = t r u e )p r o t e c t e d S t r i n g name ;@XmlElement ( r e q u i r e d = f a l s e )p r o t e c t e d S t r i n g f i r s t n a m e ;@XmlElement ( r e q u i r e d = f a l s e )p r o t e c t e d S t r i n g l o c a t i o n ;@XmlElement ( name = " s e r v i c e " , r e q u i r e d = t r u e )@XmlElementWrapper ( name = " s e r v i c e s " , r e q u i r e d = t r u e )p r o t e c t e d L i s t < S e r v i c e > s e r v i c e s ;@XmlAtt r ibute ( name = " i d " )p r o t e c t e d i n t i d ;p u b l i c P e r son ( ) {}/ * ** Gets t h e v a l u e o f t h e name p r o p e r t y .** @return p o s s i b l e o b j e c t i s { @link S t r i n g }** /p u b l i c S t r i n g getName ( ) {r e t u r n name ;}/ * ** S e t s t h e v a l u e o f t h e name p r o p e r t y .** @param v a l u e a l l o w e d o b j e c t i s { @link S t r i n g }** /p u b l i c vo id setName ( S t r i n g v a l u e ) {t h i s . name = v a l u e ;

22

}/ * ** Gets t h e v a l u e o f t h e f i r s t n a m e p r o p e r t y .** @return p o s s i b l e o b j e c t i s { @link S t r i n g }** /p u b l i c S t r i n g g e t F i r s t n a m e ( ) {r e t u r n f i r s t n a m e ;}/ * ** S e t s t h e v a l u e o f t h e f i r s t n a m e p r o p e r t y .** @param v a l u e a l l o w e d o b j e c t i s { @link S t r i n g }** /p u b l i c vo id s e t F i r s t n a m e ( S t r i n g v a l u e ) {t h i s . f i r s t n a m e = v a l u e ;}/ * ** Gets t h e v a l u e o f t h e l o c a t i o n p r o p e r t y .** @return p o s s i b l e o b j e c t i s { @link S t r i n g }** /p u b l i c S t r i n g g e t L o c a t i o n ( ) {r e t u r n l o c a t i o n ;}/ * ** S e t s t h e v a l u e o f t h e l o c a t i o n p r o p e r t y .** @param v a l u e a l l o w e d o b j e c t i s { @link S t r i n g }** /p u b l i c vo id s e t L o c a t i o n ( S t r i n g v a l u e ) {t h i s . l o c a t i o n = v a l u e ;}/ * ** Gets a r e f e r e n c e t o t h e l i s t o f s e r v i c e s p r o p e r t y .** @return p o s s i b l e o b j e c t s o f t h e f o l l o w i n g t y p e ( s ) { @link

S e r v i c e }** /p u b l i c L i s t < S e r v i c e > g e t S e r v i c e s ( ) {r e t u r n s e r v i c e s ;}/ * ** S e t s t h e v a l u e o f t h e l i s t o f s e r v i c e s p r o p e r t y .

23

** @param v a l u e O b j e c t s o f t h e f o l l o w i n g t y p e ( s ) a r e a l l o w e d i n

t h e l i s t* { @link S e r v i c e }** /p u b l i c vo id s e t S e r v i c e s ( L i s t < S e r v i c e > v a l u e ) {t h i s . s e r v i c e s = v a l u e ;}/ * ** Gets t h e v a l u e o f t h e i d p r o p e r t y .** @return p o s s i b l e v a l u e t y p e i s { @link i n t }** /p u b l i c i n t g e t I d ( ) {r e t u r n i d ;}/ * ** S e t s t h e v a l u e o f t h e i d p r o p e r t y .** @param v a l u e a l l o w e d v a l u e t y p e i s { @link i n t }** /p u b l i c vo id s e t I d ( i n t v a l u e ) {t h i s . i d = v a l u e ;}@Overridep u b l i c S t r i n g t o S t r i n g ( ) {r e t u r n " P e r son {" + " name=" + name + " , f i r s t n a m e =" + f i r s t n a m e +

" , l o c a t i o n =" + l o c a t i o n +" , s e r v i c e s =" + s e r v i c e s + " , i d =" + i d + ’ } ’ ;}}

Ecrasez la classe net.dotmyself.bartering.App par celle-ci :

package n e t . d o t m y s e l f . b a r t e r i n g ;i m p o r t j a v a . n e t . URI ;i m p o r t j a v a . u t i l . L i s t ;i m p o r t j a v a x . ws . r s . c l i e n t . C l i e n t ;i m p o r t j a v a x . ws . r s . c l i e n t . C l i e n t B u i l d e r ;i m p o r t j a v a x . ws . r s . c l i e n t . E n t i t y ;i m p o r t j a v a x . ws . r s . c l i e n t . WebTarget ;i m p o r t j a v a x . ws . r s . c o r e . Gener icType ;i m p o r t j a v a x . ws . r s . c o r e . MediaType ;i m p o r t j a v a x . ws . r s . c o r e . Response ;i m p o r t n e t . d o t m y s e l f . f i l e . s o u r c e . _13 . model . P e r so n ;i m p o r t n e t . d o t m y s e l f . f i l e . s o u r c e . _13 . model . S e r v i c e ;

24

/ * ** Java c l i e n t f o r t h e B a r t e r i n g ’ s r e s t f u l web s e r v i c e** @author h y a c i n t h e MENIET* /p u b l i c c l a s s App {p r i v a t e s t a t i c f i n a l S t r i n g REST_URL = " h t t p : / / l o c a l h o s t : 8 0 8 0 /

b a r t e r i n g / a p i / p e r s o n s " ;p r i v a t e s t a t i c f i n a l S t r i n g BGID = " 1 " ;p r i v a t e s t a t i c f i n a l S t r i n g SJID = " 2 " ;p r i v a t e s t a t i c f i n a l S t r i n g SERVICE_URI = " s e r v i c e s " ;p u b l i c s t a t i c vo id main ( S t r i n g [ ] a r g s ) {C l i e n t c l i e n t = C l i e n t B u i l d e r . n e w C l i e n t ( ) ;WebTarget t a r g e t = c l i e n t . t a r g e t (REST_URL) ;S e r v i c e c r e a t e d S e r v i c e ;URI C r e a t e d S e r v i c e U r i ;WebTarget c r e a t e d S e r v i c e T a r g e t ;Pe r s on S t e v e J o b s ;System . o u t . p r i n t l n ( " Reading t h e p e r s o n B i l l Ga tes . . . " ) ;t r y ( Response r e s p o n s e = t a r g e t . p a t h (BGID) . r e q u e s t ( MediaType .

APPLICATION_XML) . g e t ( ) ) {Pe r s on B i l l G a t e s = r e s p o n s e . r e a d E n t i t y ( P e r son . c l a s s ) ;System . o u t . p r i n t l n ( r e s p o n s e . g e t S t a t u s ( ) ) ;System . o u t . p r i n t l n ( B i l l G a t e s ) ;System . o u t . p r i n t l n ( ) ;}System . o u t . p r i n t l n ( " Reading t h e p e r s o n S t e v e Jobs . . . " ) ;t r y ( Response r e s p o n s e = t a r g e t . p a t h ( SJID ) . r e q u e s t ( MediaType .

APPLICATION_XML) . g e t ( ) ) {S t e v e J o b s = r e s p o n s e . r e a d E n t i t y ( Pe r so n . c l a s s ) ;System . o u t . p r i n t l n ( r e s p o n s e . g e t S t a t u s ( ) ) ;System . o u t . p r i n t l n ( S t e v e J o b s ) ;System . o u t . p r i n t l n ( ) ;}System . o u t . p r i n t l n ( " Adding a S e r v i c e t o t h e p e r s o n S t e v e Jobs

. . . " ) ;c r e a t e d S e r v i c e = new S e r v i c e ( " T e l e c h a r g e m e n t de 3 morceaux s u r l ’

Apple Music S t o r e " ) ;t r y ( Response r e s p o n s e = t a r g e t . p a t h ( SJID ) . p a t h ( SERVICE_URI ) .

r e q u e s t ( MediaType . APPLICATION_XML). p o s t ( E n t i t y . e n t i t y ( c r e a t e d S e r v i c e , MediaType . APPLICATION_XML) ) )

{C r e a t e d S e r v i c e U r i = r e s p o n s e . g e t L o c a t i o n ( ) ;System . o u t . p r i n t l n ( r e s p o n s e . g e t S t a t u s ( ) ) ;System . o u t . p r i n t l n ( ) ;}System . o u t . p r i n t l n ( " Reading t h e l i s t o f s e r v i c e s from t h e p e r s o n

S t e v e Jobs . . . " ) ;t r y ( Response r e s p o n s e = t a r g e t . p a t h ( SJID ) . p a t h ( SERVICE_URI ) .

25

r e q u e s t ( MediaType . APPLICATION_XML) . g e t ( ) ) {L i s t < S e r v i c e > s e r v i c e s = r e s p o n s e . r e a d E n t i t y ( new Gener icType < L i s t

< S e r v i c e > >() {} ) ;System . o u t . p r i n t l n ( r e s p o n s e . g e t S t a t u s ( ) ) ;System . o u t . p r i n t l n ( s e r v i c e s ) ;System . o u t . p r i n t l n ( ) ;}System . o u t . p r i n t l n ( " Reading one s e r v i c e from t h e p e r s o n S t e v e

Jobs . . . " ) ;c r e a t e d S e r v i c e T a r g e t = c l i e n t . t a r g e t ( C r e a t e d S e r v i c e U r i ) ;t r y ( Response r e s p o n s e = c r e a t e d S e r v i c e T a r g e t . r e q u e s t ( MediaType .

APPLICATION_XML) . g e t ( ) ) {c r e a t e d S e r v i c e = r e s p o n s e . r e a d E n t i t y ( S e r v i c e . c l a s s ) ;System . o u t . p r i n t l n ( r e s p o n s e . g e t S t a t u s ( ) ) ;System . o u t . p r i n t l n ( c r e a t e d S e r v i c e ) ;System . o u t . p r i n t l n ( ) ;}System . o u t . p r i n t l n ( " Upda t ing one s e r v i c e from t h e p e r s o n S t e v e

Jobs . . . " ) ;c r e a t e d S e r v i c e = new S e r v i c e ( " 1 E n t r e e pour l e c o n c e r t : F l a s h

H a t e r s " ) ;t r y ( Response r e s p o n s e = c r e a t e d S e r v i c e T a r g e t . r e q u e s t ( MediaType .

APPLICATION_XML). p u t ( E n t i t y . e n t i t y ( c r e a t e d S e r v i c e , MediaType . APPLICATION_XML) ) ) {System . o u t . p r i n t l n ( r e s p o n s e . g e t S t a t u s ( ) ) ;System . o u t . p r i n t l n ( ) ;}System . o u t . p r i n t l n ( " Re−r e a d i n g one s e r v i c e from t h e p e r s o n S t e v e

Jobs . . . " ) ;t r y ( Response r e s p o n s e = c r e a t e d S e r v i c e T a r g e t . r e q u e s t ( MediaType .

APPLICATION_XML) . g e t ( ) ) {c r e a t e d S e r v i c e = r e s p o n s e . r e a d E n t i t y ( S e r v i c e . c l a s s ) ;System . o u t . p r i n t l n ( r e s p o n s e . g e t S t a t u s ( ) ) ;System . o u t . p r i n t l n ( c r e a t e d S e r v i c e ) ;System . o u t . p r i n t l n ( ) ;}System . o u t . p r i n t l n ( " D e l e t i n g one s e r v i c e from t h e p e r s o n S t e v e

Jobs . . . " ) ;t r y ( Response r e s p o n s e = c r e a t e d S e r v i c e T a r g e t . r e q u e s t ( MediaType .

APPLICATION_XML) . d e l e t e ( ) ) {System . o u t . p r i n t l n ( r e s p o n s e . g e t S t a t u s ( ) ) ;System . o u t . p r i n t l n ( ) ;}System . o u t . p r i n t l n ( " Re−r e a d i n g t h e p e r s o n S t e v e Jobs . . . " ) ;t r y ( Response r e s p o n s e = t a r g e t . p a t h ( SJID ) . r e q u e s t ( MediaType .

APPLICATION_XML) . g e t ( ) ) {S t e v e J o b s = r e s p o n s e . r e a d E n t i t y ( Pe r so n . c l a s s ) ;System . o u t . p r i n t l n ( r e s p o n s e . g e t S t a t u s ( ) ) ;

26

System . o u t . p r i n t l n ( S t e v e J o b s ) ;System . o u t . p r i n t l n ( ) ;}}}

Compilez et exécutez cette classe via la commande ci-dessous (à taper à la racine de votre projetMaven client) :

$ mvn −q c l e a n compi l e exec : j a v a −Dexec . ma inCla s s =" n e t . d o t m y s e l f .b a r t e r i n g . App"

27

Recommended