services rest & jersey
DESCRIPTION
Introduction au paradigme REST et à son implémentation via le framework JerseyTRANSCRIPT
![Page 1: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/1.jpg)
REST & Jersey
![Page 2: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/2.jpg)
REST ?De diou - Qu'es aquò ?
![Page 3: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/3.jpg)
REST ?
Style d'architecture
HTTP
SOA : REST vs SOAP
![Page 4: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/4.jpg)
Principes RESTLes 5 commandements
![Page 5: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/5.jpg)
Aucun état tu n'aurasStateless
Historiquement avec le web, maintien de la session côté client
Aujourd'hui les clients sont capables de gérer un état de session
![Page 6: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/6.jpg)
Adressables tes ressources serontAdressabilité
Utiliser la spécification HTTP
Une ressource = une URI
![Page 7: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/7.jpg)
Uniforme l'accès à tes ressources sera - 1Accès via un sous ensemble des verbes HTTP
GETPUT
DELETEPOSTHEAD
![Page 8: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/8.jpg)
Uniforme l'accès à tes ressources sera - 22 notions permettant de distinguer PUT et POST
Sûr : L’invocation d’une méthode sûre ne change pas l’état du serveur
Idempotent : signifie que le résultat d’une action sera le même quel que soit le nombre d’exécutions de cette action.
![Page 9: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/9.jpg)
Uniforme l'accès à tes ressources sera - 3GETSur & Idempotent
Obtenir la représentation d’une ressource
![Page 10: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/10.jpg)
Uniforme l'accès à tes ressources sera - 4PUTIdempotent
Correspond à un Create ou bien un Update
![Page 11: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/11.jpg)
Uniforme l'accès à tes ressources sera - 5DELETEIdempotent
Supprimer une ressource du serveur
![Page 12: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/12.jpg)
Uniforme l'accès à tes ressources sera - 6POSTNON Idempotent
Modifier une ressource du serveur. Seule opération non idempotente de la spécification HTTP
Correspond à un Create ou bien un Update
![Page 13: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/13.jpg)
Uniforme l'accès à tes ressources sera - 7HEADSur et idempotent
Similaire à un GET, mais ne retourne pas le corps de la réponse (seulement code retour + éventuels en-têtes)
![Page 14: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/14.jpg)
Orienté représentation tu seras
exemple :
GET sur une URI => représentation de la ressource en XML ou JSON (ou autre) suivant la phase de Content Negotiation
![Page 15: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/15.jpg)
HATEOAS tu respecterasHypermedia As The Engine Of Application State
Navigation via des liens inclus dans la représentation des ressources
![Page 16: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/16.jpg)
Spécification d'une ressourceMiam des specs
![Page 17: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/17.jpg)
Contrat d'interface
Choix des ressources+
Choix des verbes+
Choix des codes retour=
Description du contrat
![Page 18: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/18.jpg)
Et en Java ?
![Page 19: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/19.jpg)
JSR 311JAX-RS
@Path@GET @PUT @POST @DELETE @HEAD@Produces@Consumes
![Page 20: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/20.jpg)
Frameworks sur le marchéJersey *RESTEasyRESTLetCXF
![Page 21: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/21.jpg)
Donc, Jersey
![Page 22: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/22.jpg)
Jersey
Implémentation de référence de la JSR
Des fonctionnalités supplémentaires
![Page 23: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/23.jpg)
(une prez encore mieux...)
http://matthewturland.com/slides/jersey/
Si j'avais vu ça avant j'aurai pas fait ces slides...
![Page 24: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/24.jpg)
JerseyMise en place du projet
Dépendances maven (v1.17.1)
Attention à asm.jar (collisions dépendances Hibernate ou tout autre projet utilisant CGLIB)
http://mathieuhicauber-java.blogspot.fr/2012/12/jax-rs-jersey-on-was-61-asm-classreader.html
![Page 25: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/25.jpg)
Jersey Contrôleurweb.xmlDéclaration dans le web.xml du package à scanner<servlet> <description>Jersey Servlet</description> <display-name>ServletContainer</display-name> <servlet-name>ServletContainer</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <!-- le package scanné par Jersey à la recherche d'annotations --> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>fr.laposte.intra.courrier.recif.rest</param-value> </init-param> ...</servlet> <!-- Le mapping d'URL voulu--><servlet-mapping> <servlet-name>ServletContainer</servlet-name> <url-pattern>/resources/*</url-pattern></servlet-mapping>
![Page 26: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/26.jpg)
Jersey Contrôleur @Path
@Path("/artists")
public class ArtistResource {…}
... Et notre ressource est exposée !
(Comparer ça à un cycle de développement SOAP...)
![Page 27: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/27.jpg)
@Path : Définir le chemin d'accès@[VERB] : Définir le verbe autorisé
@Path("helloWorld")@GETpublic String helloMyFriend() {...}
Jersey Contrôleur @Path @[VERB]
![Page 28: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/28.jpg)
@PathParam : injecter un paramètre dans la signature de la méthode défini dans @Path
@Path("hello/{aName}")@GETpublic String getCustomizedHelloWorld(
@PathParam("aName") String name) {...}
Jersey Contrôleur@PathParam - 1
![Page 29: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/29.jpg)
Possibilité d'injecter plusieurs paramètres ou de spécifier une regexp pour la partie dynamique
@Path("date/{year}-{month}-{date}") // plusieurs params
@Path("{id : \\d+}") // numériques seulement
@Path("username/{username : [a-z]+}") //alpha minuscules seulement
Jersey Contrôleur@PathParam - 2
![Page 30: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/30.jpg)
Permet d'injecter les valeurs provenant des paramètres de requête
@Path("hello")@GETpublic String getResponseWithQueryParam(
@QueryParam("name") String nameQueryParameter) {...}
URI : http://[JAX-RS-URI]/hello?name=Mathieu
Jersey Contrôleur@QueryParam
![Page 31: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/31.jpg)
Permet d'injecter les valeurs provenant des en-têtes de la requête HTTP
@Path("hello")@GETpublic String getResponseWithHeaderParam(
@HeaderParam("headerParam") String someHeaderParam) {...}
Jersey Contrôleur@HeaderParam
![Page 32: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/32.jpg)
Permet d'injecter les valeurs extraites des cookies
@Path("hello")@GETpublic String getResponseWithCookieParam(
@CookieParam("cookieParam") String aParamInjectedFromCookies) {...}
Jersey Contrôleur@CookieParam
![Page 33: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/33.jpg)
Permet d'injecter les valeurs de champs de formulaire
@Path("handleForm")@POSTpublic String handleForm(
@FormParam("username") String userName,@FormParam("password") String password) {...}
Jersey Contrôleur@FormParam - 1
![Page 34: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/34.jpg)
Problème : avec un gros formulaire, les signatures deviennent illisibles
@Path("handleForm")@POSTpublic String handleForm(
@FormParam("value1") String value1,@FormParam("value2") String value2,@FormParam("value3") String value3,@FormParam("value4") String value4,...) {...}
Jersey Contrôleur@FormParam - 2
![Page 35: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/35.jpg)
Jersey permet d'injecter un bean
@Path("handleForm")@POSTpublic String handleForm(
@InjectParam CustomFormValuesHandlerType form) {...}
Le type CustomFormValuesHandlerType est un POJO reprenant les valeurs du form en attribut.
Les attributs sont annotés avec @FormParam
Jersey Contrôleur@InjectParam* - 1
![Page 36: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/36.jpg)
@Produces@Consumes
Indique le type de représentation qu'est capable de consommer ou de produire la méthode
Utilisé par le moteur Jersey en conjonction avec le header Accept envoyé par le client pour choisir la bonne méthode et le bon type de retour
Jersey ContrôleurContent Negotiation - 1
![Page 37: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/37.jpg)
Header client : @Accept
Accept: application/json; q=1.0, application/xml; q=0.8, text/html; q=0.6, text/plain; q=0.4, text/*; q=0.2, */*; q=0.1
Jersey ContrôleurContent Negotiation - 2
![Page 38: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/38.jpg)
Retourner une javax.ws.core.Response
@Path("/id/{artistId}") @GET @Produces({ MediaType.APPLICATION_JSON }) public Response getArtistByIdJavaxResponse (
@PathParam("artistId") Integer artistId)*throws ArtistDoesNotExistException {
Artist artist = service.getArtistById(artistId); return Response.ok().entity(artist).build(); }
Jersey ContrôleurRetourner la ressource - 1
![Page 39: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/39.jpg)
... ou bien une entité ou liste d'entités
@Path("/id/{artistId}") @GET @Produces({ MediaType.APPLICATION_JSON }) public Artist getArtistByIdEntityResponse(
@PathParam("artistId") Integer artistId) throws ArtistDoesNotExistException {
Artist artist = service.getArtistById(artistId);
return artist; }
Jersey ContrôleurRetourner la ressource - 2
![Page 40: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/40.jpg)
Fluent Interface idiom (ou EDL)
return Response.ok().entity(artist).header("HeaderName","headerValue").lastModified(lastModified).expires(expiresDate).build();
Jersey ContrôleurRetourner la ressource - 3
![Page 41: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/41.jpg)
Déclaration dans le web.xml
<init-param><param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name><param-value>fr.laposte.intra.courrier.recif.rest.filters.AccreditationFilter;com.sun.jersey.api.container.filter.LoggingFilter</param-value>
</init-param>
<init-param><param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name><param-value>com.sun.jersey.api.container.filter.LoggingFilter ; fr.laposte.intra.courrier.recif.rest.filters.CORSFilter</param-value>
</init-param>
Jersey Filters - 1
![Page 42: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/42.jpg)
Filtres de Request ou Response
Existence de filtres prédéfinis
Possibilité de créer ses filtres
Jersey Filters - 2
![Page 43: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/43.jpg)
Permet de lancer des codes erreurs HTTP spécifique en fonction d'un type d'exception
public class ArtistDoesNotExistExceptionMapper implements ExceptionMapper<ArtistDoesNotExistException> { @Override public Response toResponse(ArtistDoesNotExistException exception) { return Response.status(Response.Status. NOT_FOUND) .entity(exception.getMessage()).type(MediaType. TEXT_PLAIN) .build(); } }
Jersey Exception mapping
![Page 44: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/44.jpg)
Classe de support : étendre JerseyTest
@Override public WebAppDescriptor configure() { return new WebAppDescriptor.Builder("com.foo.workshops.jersey").build(); } @Override public TestContainerFactory getTestContainerFactory() { return new GrizzlyWebTestContainerFactory(); }
JerseyTUAs
![Page 45: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/45.jpg)
Cross Origin Resource Sharing
Ajax XDomain => Interdit, mais cas fréquent dans le cadre d'une API REST
Solutions : jsonP, proxy, CORS
CORS (mode simple) : permettre au client de récupérer des ressources en Ajax provenant d'un autre domaine
JerseyCORS - 1
![Page 46: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/46.jpg)
Requête simple (GET)
Client POST /cors HTTP/1.1Origin: http://api.bob.comHost: api.bob.com
Serveur Access-Control-Allow-Origin: http://api.bob.comAccess-Control-Expose-Headers: FooBarContent-Type: text/html; charset=utf-8
JerseyCORS - 2
![Page 47: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/47.jpg)
Requête complexes (PUT - DELETE)
http://www.html5rocks.com/en/tutorials/cors/?redirect_from_locale=fr
JerseyCORS - 3
![Page 48: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/48.jpg)
Evolutions => exige une montée de version a minima si perte de compatibilité ascendente. 3 courants se dégagent :
Versioning dans l'URL
GET http://....../v1/resource/id/12345GET http://....../v2/resource/id/12345
++ Simple !- casse le principe d'unicité d'URI pour une ressource- expose un paramètre technique dans l'URI
RESTVersioning -1
![Page 49: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/49.jpg)
Versioning via Custom Header
client Header :Version : 1.0
++ Simple-- peut poser problème derrière des proxies
RESTVersioning - 2
![Page 50: Services rest & jersey](https://reader033.vdocuments.net/reader033/viewer/2022052905/558695c5d8b42ab7308b45a4/html5/thumbnails/50.jpg)
Versioning via Content Negotiation
http://barelyenough.org/blog/2008/05/versioning-rest-web-services
++ HATEOAS compliant-- plus complexe à mettre en oeuvre, nécessite des vendor MIME Media Types
RESTVersioning - 3