services rest & jersey

50
REST & Jersey

Upload: mathieu-hicauber

Post on 21-Jun-2015

446 views

Category:

Software


7 download

DESCRIPTION

Introduction au paradigme REST et à son implémentation via le framework Jersey

TRANSCRIPT

Page 1: Services rest & jersey

REST & Jersey

Page 2: Services rest & jersey

REST ?De diou - Qu'es aquò ?

Page 3: Services rest & jersey

REST ?

Style d'architecture

HTTP

SOA : REST vs SOAP

Page 4: Services rest & jersey

Principes RESTLes 5 commandements

Page 5: Services rest & jersey

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

Adressables tes ressources serontAdressabilité

Utiliser la spécification HTTP

Une ressource = une URI

Page 7: Services rest & jersey

Uniforme l'accès à tes ressources sera - 1Accès via un sous ensemble des verbes HTTP

GETPUT

DELETEPOSTHEAD

Page 8: Services rest & jersey

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

Uniforme l'accès à tes ressources sera - 3GETSur & Idempotent

Obtenir la représentation d’une ressource

Page 10: Services rest & jersey

Uniforme l'accès à tes ressources sera - 4PUTIdempotent

Correspond à un Create ou bien un Update

Page 11: Services rest & jersey

Uniforme l'accès à tes ressources sera - 5DELETEIdempotent

Supprimer une ressource du serveur

Page 12: Services rest & jersey

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

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

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

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

Spécification d'une ressourceMiam des specs

Page 17: Services rest & jersey

Contrat d'interface

Choix des ressources+

Choix des verbes+

Choix des codes retour=

Description du contrat

Page 18: Services rest & jersey

Et en Java ?

Page 19: Services rest & jersey

JSR 311JAX-RS

@Path@GET @PUT @POST @DELETE @HEAD@Produces@Consumes

Page 20: Services rest & jersey

Frameworks sur le marchéJersey *RESTEasyRESTLetCXF

Page 21: Services rest & jersey

Donc, Jersey

Page 22: Services rest & jersey

Jersey

Implémentation de référence de la JSR

Des fonctionnalités supplémentaires

Page 23: Services rest & jersey

(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

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

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

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

@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

@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

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

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

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

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

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

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

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

@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

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

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

... 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

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

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

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

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

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

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

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 48: Services rest & jersey

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

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

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