5. Aucun état tu n'auras
Stateless
Historiquement avec le web, maintien de la
session côté client
Aujourd'hui les clients sont capables de gérer
un état de session
7. Uniforme l'accès à tes
ressources sera - 1
Accès via un sous ensemble des verbes HTTP
GET
PUT
DELETE
POST
HEAD
8. Uniforme l'accès à tes
ressources sera - 2
2 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.
9. Uniforme l'accès à tes
ressources sera - 3
GET
Sur & Idempotent
Obtenir la représentation d’une ressource
10. Uniforme l'accès à tes
ressources sera - 4
PUT
Idempotent
Correspond à un Create ou bien un Update
11. Uniforme l'accès à tes
ressources sera - 5
DELETE
Idempotent
Supprimer une ressource du serveur
12. Uniforme l'accès à tes
ressources sera - 6
POST
NON Idempotent
Modifier une ressource du serveur. Seule
opération non idempotente de la spécification
HTTP
Correspond à un Create ou bien un Update
13. Uniforme l'accès à tes
ressources sera - 7
HEAD
Sur et idempotent
Similaire à un GET, mais ne retourne pas le
corps de la réponse (seulement code retour +
éventuels en-têtes)
14. 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
15. HATEOAS tu respecteras
Hypermedia As The Engine Of Application
State
Navigation via des liens inclus dans la
représentation des ressources
23. (une prez encore mieux...)
http://matthewturland.com/slides/jersey/
Si j'avais vu ça avant j'aurai pas fait ces
slides...
24. Jersey
Mise 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
25. Jersey Contrôleur
web.xml
Dé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>
26. Jersey Contrôleur
@Path
@Path("/artists")
public class ArtistResource {…}
... Et notre ressource est exposée !
(Comparer ça à un cycle de développement
SOAP...)
27. Jersey Contrôleur
@Path @[VERB]
@Path : Définir le chemin d'accès
@[VERB] : Définir le verbe autorisé
@Path("helloWorld")
@GET
public String helloMyFriend() {...}
28. Jersey Contrôleur
@PathParam - 1
@PathParam : injecter un paramètre dans la
signature de la méthode défini dans @Path
@Path("hello/{aName}")
@GET
public String getCustomizedHelloWorld(
@PathParam("aName") String name) {...}
29. Jersey Contrôleur
@PathParam - 2
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
30. Jersey Contrôleur
@QueryParam
Permet d'injecter les valeurs provenant des
paramètres de requête
@Path("hello")
@GET
public String getResponseWithQueryParam(
@QueryParam("name") String nameQueryParameter) {...}
URI : http://[JAX-RS-URI]/hello?name=Mathieu
31. Jersey Contrôleur
@HeaderParam
Permet d'injecter les valeurs provenant des en-têtes
de la requête HTTP
@Path("hello")
@GET
public String getResponseWithHeaderParam(
@HeaderParam("headerParam") String someHeaderParam) {...}
32. Jersey Contrôleur
@CookieParam
Permet d'injecter les valeurs extraites des cookies
@Path("hello")
@GET
public String getResponseWithCookieParam(
@CookieParam("cookieParam") String aParamInjectedFromCookies)
{...}
33. Jersey Contrôleur
@FormParam - 1
Permet d'injecter les valeurs de champs de
formulaire
@Path("handleForm")
@POST
public String handleForm(
@FormParam("username") String userName,
@FormParam("password") String password) {...}
34. Jersey Contrôleur
@FormParam - 2
Problème : avec un gros formulaire, les signatures
deviennent illisibles
@Path("handleForm")
@POST
public String handleForm(
@FormParam("value1") String value1,
@FormParam("value2") String value2,
@FormParam("value3") String value3,
@FormParam("value4") String value4,
...) {...}
35. Jersey Contrôleur
@InjectParam* - 1
Jersey permet d'injecter un bean
@Path("handleForm")
@POST
public 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
36. Jersey Contrôleur
Content Negotiation - 1
@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
38. Jersey Contrôleur
Retourner la ressource - 1
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();
}
39. Jersey Contrôleur
Retourner la ressource - 2
... 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;
}
40. Jersey Contrôleur
Retourner la ressource - 3
Fluent Interface idiom (ou EDL)
return Response.ok()
.entity(artist)
.header("HeaderName","headerValue")
.lastModified(lastModified)
.expires(expiresDate)
.build();
41. Jersey
Filters - 1
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>
42. Jersey
Filters - 2
Filtres de Request ou Response
Existence de filtres prédéfinis
Possibilité de créer ses filtres
43. 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
44. Jersey
TUAs
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();
}
45. Jersey
CORS - 1
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
46. Jersey
CORS - 2
Requête simple (GET)
Client
POST /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.bob.com
Serveur
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
47. Jersey
CORS - 3
Requête complexes (PUT - DELETE)
http://www.html5rocks.com/en/tutorials/cors/?
redirect_from_locale=fr
48. REST
Versioning -1
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/12345
GET http://....../v2/resource/id/12345
++ Simple !
- casse le principe d'unicité d'URI pour une ressource
- expose un paramètre technique dans l'URI
49. REST
Versioning - 2
Versioning via Custom Header
client Header :
Version : 1.0
++ Simple
-- peut poser problème derrière des proxies
50. REST
Versioning - 3
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