Présentation du framework Jersey — sans slide — par paire en 2 heures.
Parallèlement à l'essor de la mobilité et des clients JavaScript, le style d'architecture REST a vu sa popularité s'affirmer. Nombreux sont les ouvrages consacrés au sujet mais peu traitent de son implémentation. Ce slot est l'occasion — pour tout public — de mettre en oeuvre Jersey, l'implémentation JAX-RS de référence, et de revenir sur les fondamentaux de REST. Constitué en grande partie de programmation en TDD par paire, c'est l'occasion d'identifier les ressources d'un système, de définir les représentations échangées entre client et serveur, de naviguer entre ressources et d'aborder les nombreuses problématiques relatives à l'architecture du web (interface unifiée HTTP, application sans état, cache, sécurité, concurrence, etc).
Cloner ce repo git puis l'importer dans un IDE. L'annotation @ClassRule en tête des tests déploye un servlet Jersey
sur un serveur Grizzly
ou Jetty
afin de lancer des tests junit via http sur la ressource ProductResource
. Cette dernière définit les méthodes suivantes, GET
, POST
-> /product
et GET
, DELETE
-> /product/{id}
. Elle produit et consomme la représentation suivante, {id:long, name:string, price:int}
.
Le Server
déployé par défaut est Grizzly
, sa configuration s'effectue dans sa classe. Jetty
peut également être utilisé, sa configuration s'effectue via le web.xml.
- Lancer les tests, ils échouent : la console affiche les échanges http
- Afin d'activer le marshalling JAXB sur l'objet Product, l'annoter avec
@XmlRootElement
et@XmlAccessorType
- ProductResource est déjà annotée, regarder rapidement l'utilisation des annotation
@Path
,@GET
et@PathParam
- Lancer les tests de nouveau, ils passent
--> Regarder la représentation retournéee par le serveur lors du POST, il lui manque des attributs (nous y reviendrons)
- Lancer les tests, ils passent
--> Jersey utilise JAXB pour le marshalling XML et JSON par défaut
- Lancer les tests, ils échouent
- Modifier les accès de JAXB sur
Product
en configurant l'annotation@XmlAccessorType
- Lancer les tests,
List
pose problème - Utiliser
GenericType
côté client etGenericEntity
côté serveur afin de résoudre le problème - Lancer les tests,
List
fonctionne, seule la suppression pose problème - Modifier la méthode
delete({/id})
avec une réponse construite à l'aide du builder deResponse
- Lancer les tests, seule la suppression d'un id inexistant ne fonction pas
- Modifier la méthode
delete({/id})
afin qu'elle retourne un status 404,Not Found
, lors de la demande de suppression d'un id inexistant - Supprimer le code du point 6 et gérer l'erreur via une
NotFoundException
. Et, afin que Jersey soit en mesure de la capturer, créer la classeNotFoundExceptionMapper
implémentantExceptionMapper
. L'annoter@Provider
.
--> La gestion d'exceptions de Jersey à l'aide de Providers
suit l'arbre d'héritage à partir des feuilles
- Lancer les tests, le premier passe et pas le second pourtant l'assertion est correcte
- Configurer le serveur Jersey afin qu'il utilise Jackson pour le marshalling Json au lieu de Jaxb (dans
Grizzly
et/ouJetty
) - Configurer le client Jersey afin qu'il fasse de même à l'aide d'une
ClientConfig
- Attention à bien utiliser un client standard
Client.createClient()
pour le premier test et un client avecClientConfig
pour les autres - Corriger l'assertion du premier test, Jaxb est en mesure de marshaller du JSON standard (même s'il n'en produit pas par défaut)
- Lancer les tests, ils passent
- Supprimer les annotations de la représentation
Product
- Lancer les tests, ils échouent. Cel signifie que Jackson utilisait les annotations JAXB
- Annoter
JacksonMapperProvider
avec@Provider
- Lancer les tests, le POST fonctionne, mais pas le GET : le client n'arrive pas à accèder aux propriétés du produit
- Ajouter le
JacksonMapperProvider
auClientConfig
du client - Lancer les tests, ils passent
--> Identifier à quel moment le mapper Jackson custom est instancié
--> Rechercher comment customiser le mapper Jaxb de la même manière
- Lancer les tests, ils échouent
- Ajouter un header
Cache-Control
sur les méthodesget({id})
etpost()
- Lancer les tests, ils passent
- Supprimer le code du point 2 et utiliser une instance de
FilterFactory
dans le mapper Jackson custom - Lancer les tests, ils passent
--> Identifier pourquoi CacheControlFilter
doit implèmenter deux interfaces
--> Rechercher comment cette technique peut produire du JSONP sans modifier la ressource
- Jersey configuration correspondance web.xml <-> code : http://blogs.oracle.com/PavelBucek/entry/jersey_server_and_client_side
- Jaxb plus en détails : http://blog.xebia.fr/2011/03/17/jaxb-le-parsing-xml-objet
- Jackson documentation : http://wiki.fasterxml.com/JacksonDocumentation
- JavaScript/Jersey du xke de novembre : https://github.com/yamsellem/Backbone-Jersey