Accueil > Intranet Michel Buffa > Web 2.0 2010 > Seance1 : Intro au web 2.0 et web services REST > Web services REST : jersey + serveur Grizzly embarqué

Web services REST : jersey + serveur Grizzly embarqué

De $1

Introduction

Ce premier TP propose d'étudier un projet fournissant une application web sous forme de web services REST. Elle embarque un "mini serveur" grizzly configuré uniquement pour exposer des web services REST au travers du framework jersey, standard dans java EE6. Nous verrons dans un prochain TP une version améliorée de ce TP dans lequel cette fois-ci Grizzly sera "augmenté" pour pouvoir servir des pages HTML classiques, contenant images, CSS, javascript etc.

Supports de cours

  • Transparents utilisés en cours (code camp REST par Carol Mc Donald) : REST_Carol.odp (c'est de l'open office !) ou en PDF : restfulwebservices.pdf
  • Compléments pour ceux qui veulent en savoir plus (comparaison avec SOAP, historique, use cases)
    • Regarder cette présentation qui rentre plus dans les détails : restws.pdf
    • Regarder les supports et vidéo postés sur la page du cours de l'an dernier , il y a notamment un screencast du cours + création de web services REST complets, avec persistence dans base données via JPA, à l'aide de netbeans, comme montré en cours.

Travaux pratiques

Etude et compréhension d'un web service RESTFUL en Java EE6 : un serveur de bookmarks semblable à celui de delicious.com

Dans ce TP vous allez étudier un projet complet de web service REST, vous l'ouvrirez avec Eclipse ou Netbeans, l'exécuterez, puis vous essaierez de comprendre sa conception. Ce projet a quelques particularités intéressantes...

Récupérer l'archive suivante et la décompresser dans votre workspace Eclipse ou Netbeans

Version Eclipse

Attention, il faut que le projet tourne sous un JDK >  1.6_13, avec des versions inférieures vous n'aurez pas les bonnes bibliothèques JAXB..., au moment de l'importation du projet, veillez à indiquer le bon JRE !!!

  • BMServ_TP.rar
  • Version en .zip pour ceux qui travaillent sous linux sur les machines du département info (où il n'y a visiblement pas unrar d'installé !) : BMServ_TP.zip 
  • Je le répète : il est recommandé d'être en JDK 1.6_13 ou supérieur et Eclipse Ganymède ou Galliléo, si vous avez un vieux JDK ou un Eclipse ancestral, on ne peut rien pour vous ;-). NB. Pour lancer Eclipse en spécifiant la jvm à utiliser (certains plugins nécessitent de lancer Eclipse à partir du bon jdk): /path/to/eclipse -vm /path/to/jvm/bin/java

Version netbeans (là aussi, JDK récent please !) :

Utilisation d'un serveur web embarqué dans l'application

Le projet utilise un serveur web (un container web dans le jargon) embarqué dans l'application. nul besoin de Tomcat, Glassfish, Jetty, JBoss ou autre serveur à installer ! Ce container web s'appelle Grizzly et on le retrouve comme "plugin" du serveur Glassfish v3 de Sun. Le TP utilise la version de Grizzly d'il y a un an, il se peut que depuis que quelques trucs aient changé (voir le site officiel qui contient des tutoriaux et un user's guide : http://grizzly.java.net/)

Regardez en particulier dans le projet du TP le code de la classe bmserv/Server.java :

// definition de l'URL de base du serveur et du port a ecouter
final String baseUri = "http://localhost:9998/";

// renseigne Grizzly sur l'emplacement des classes a deployer
final Map<String, String> initParams = new HashMap<String, String>();
initParams.put("com.sun.jersey.config.property.packages", "bmserv.resources"); 
		
try {
    // Création du serveur embarqué
    // On deploie les ressource a baseURI, indique où sont les ressources (initParams)
    // et on retourne un SelectorThread, qui permettra d'enregistrer des listeners pour
    // afficher l'état du serveur
    SelectorThread threadSelector = GrizzlyWebContainerFactory.create(baseUri, initParams);

   ServerStateListener ssl = new ServerStateListener(); // Creation d'un listener pour suivre l'etat du serveur
   threadSelector.getController().addStateListener(ssl); // Enregistrement du listener
   ...

Si vous regardez attentivement le main() qui se trouve dans Server.java et que vous suivez le fil du code, vous verrez qu'on associe aussi une console de commandes (un shell) au serveur, pour pouvoir l'arrêter, etc.

Lancez l'application et regardez ce qu'il se passe lorsque vous cliquez sur les différents liens de la page d'accueil

Faites run sur la classe Server.java, et dans firefox ouvrez l'url : http://localhost:9998 cliquez sur les différents URLs de la page qui s'affiche, remarquez les résultats.

Les modèles de données et leurs contrôleurs

Les modèles (package bmserv.model)

le projet consiste en un serveur de Bookmarks (favoris web). Un Bookmark est associé à un utilisateur, à son URI, il a une description etc... Voici le constructeur de la classe modele/Bookmarks.java

public Bookmark(final String title, final String urlstr, final String descr, final String authid) {
	this.title = title;
	this.urlstr = urlstr;
	this.authid = authid;
	this.description = descr;
	this.id = createBmId(authid, urlstr);
}

De même, on retrouve une classe pour décrire un utilisateur (User.java) et une classe pour décrire un Tag (un mot-clé). La classe la plus importante est la classe Tagging.java qui décrit l'association d'un User, d'un Bookmark et d'un Tag. On peut avoir plusieurs Taggings pour décrire un seul Bookmarks ou pour associer plusieurs Tags à un Bookmark.

Exemple (chaque ligne correspond à un tagging):

On se retrouve avec un modèle ressemblant à un modèle relationnel classique...

Etudiez donc les classes des modèles. Pour le moment, ignorez les annotations de code commençant par "@"...

Les contrôleurs (package bmserv.model.handlers)

A chaque modèle on va associer une "façade" proposant des fonctionnalités pour les manipuler : creer un tag, chercher un tag, lister tous les tags etc... Ce  sont les fameux "gestionnaires", "handlers", "managers", "DAO", etc.

Exemple pour la création d'un Tagging :

public class TaggingHandler {
    ...
    private static List<Tagging> taggings = new ArrayList<Tagging>();
    ...

    public void createTagging(final String authorid, final String bmid, final String tagid){
	GregorianCalendar dateGreg = new GregorianCalendar();
	java.util.Date dateDate = dateGreg.getTime();		 

	DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-ddTHH:mm:ss.SSSZ");
	String datestr = dateFormat.format(dateDate);
		 
	taggings.add(new Tagging(datestr, authorid, bmid, tagid));
        ...
    }
}

Etudiez donc les différents contrôleurs de manière à avoir une vue d'ensemble.

 La définition du service REST

Ca se passe dans le package bmserv. Le paradigme REST suppose qu'une donnée (un tag, un user, un bookmark, un bookmarking) est une donnée qui doit avoir un URL unique. On peut aussi associer des URLs pour afficher un ensemble de données (équivalent des "select" de SQL). Par ailleurs, selon qu'on utilise ces URLs via du HTTP GET, POST, PUT ou DELETE, on va faire des recherches, des ajouts, des modifications ou de la suppression de ces données.

Pour associer des URls aux contrôleurs, regardez les classes du package bmserv.resources. Par exemple :

package bmserv.resources;
...

@Path("/bookmark")
public class BookmarkResource {
	@GET
	@Path("/id/{bmid}")
	@Produces("text/xml")
	public bmserv.model.Bookmark getBookmarkFromId(@PathParam("bmid") String bmid) {
		Bookmark bm = Server.bmh.getBookmarkFromId(bmid);
		return bm;
	}
	
	@GET
	@Path("/all")
	@Produces("text/xml")
	public bmserv.model.handlers.BookmarkHandler getAllBookmarks() {
		return Server.bmh;
	}
}

Remarquez l'utilisation des annotations de code pour définir les URIs associés aux méthodes qui seront appelées lorsqu'ils seront invoqués. Dans cet exemple les réponses seront toutes en XML mais on aurait pu tout aussi bien indiquer qu'on les renvoie aussi en JSON...

La sérialisation / Désérialisation / Persistence des données en XML 

Les formats d'échange des web services REST sont XML ou JSON (objets sérialisés en Javascript, vous verrez ça lors de la prochaine séance). Dans ce projet, on a utilisé une API Java très pratique : JAXB, pour transformer automatiquement des objets en XML et vice versa, pour transformer un flux XML en objets.

Pour indiquer comment on veut transformer en XML un objet, on ajoute des annotations de code aux modèles. Regardez à nouveau les modèles et remarquez les annotations@XmlElement, @XmlAttribute, etc

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "taggings")
public class TaggingHandler {
	@XmlElement(name = "tagging", required=true)
	private static List<Tagging> taggings = new ArrayList<Tagging>();

Signifie que les taggings seront sérialisés entre <taggings> ... </taggings> et qu'entre ces deux balises, chaque élément sera un <tagging>...</tagging> au singulier. La manière dont les éléments seront transformés est spécifié dans les classes des modèles, par exemple dans Tagging.java (notez que la plupart des @XmlElement ont ici des valeurs par défaut, si on les enlève, le code fonctionne pareil) :

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="tagging", propOrder={
		"id",
		"authorid",
		"tagid",
		"bmid",
		"date"
	}
)
@XmlRootElement(name = "tagging")
public class Tagging {
	@XmlElement(name = "id")
	private String id;
	@XmlElement(name = "tagid")
	private String tagid;
	@XmlElement(name = "bmid")
	private String bmid;
	@XmlElement(name = "authorid")
	private String authorid;
	@XmlElement(name = "date")
	private String date;

Persistence sous forme de fichiers XML

Les classes Loader et Writer du package bmserv sont utilisées pour la persistence sous forme de fichiers XML. Regardez comment elles fonctionnent. Elles sont utilisées par le main() dans la classe Server.java pour charger des fichiers lors du lancement de l'application et reconstruire les Collections de Tags, Users, etc. à partir du XML, et aussi pour sauvegarder les fichiers lorsqu'on quitte le serveur (cf ServerStateListener.java, méthode onStop) :

@Override
	public void onStopped() {
		System.out.println("==> Server stopped !\n");
		try {
			Writer.serialize();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

 

Ajout de fonctionnalités

Maintenant, on va vous demander de rajouter de la fonctionnalité au projet :

  1. Ajouter un web service de consultation des Taggings en format HTML, l'url sera http://localhost:9998/tagging/all/html et devra renvoyer sous la forme d'une table HTML l'ensemble des Taggings, avec évidemment les Ids des relations (User id, Tag Id, Bookmark id). Vous vous inspirez des autres web services qui renvoient par exemple les Bookmarks ou les Users
  2. Créer une classe de formulaire permettant de rajouter un Bookmark. Vous utiliserez la méthode POST pour appeler l'URL http://localhost:9998/form/bookmark/add en "postant" le contenu du formulaire. La méthode appelée devra rajouter le bookmark à la liste des bookmarks existants.
  3. Bonus pour les bons :
    1. créer un web service pour ajouter un Tagging (liant un Bookmark Id à un tag id et au user courant), 
    2. Modifier le code pour respecter vraiment la norme REST en renvoyant dans le XML non pas les Ids des relations, mais les URi complets. Regarder le cours concernant l'utilisation des classes Jersey (page 41 des transparents du cours de Carols Mc Donald) + exemples d'utilisation dans les projets Netbeans  vus en cours.

En-tête (sans les annotations de code) de la méthode à implémenter dans la classe BoomarkResource.java :

public String create(@Context HttpServletRequest req, MultivaluedMap<String, String> formParams){

 

 

 

Mots clés:
FichierTailleDateAttaché par 
 BMServ_TP.rar
Aucune description
9.73 Mo10:22, 4 Fév 2010MichelBuffaActions
BMServ_TP.zip
Aucune description
10.05 Mo15:07, 4 Fév 2010MichelBuffaActions
 restfulwebservices.pdf
Aucune description
1255.65 Ko10:42, 4 Fév 2010MichelBuffaActions
 restws.pdf
Aucune description
245.45 Ko10:48, 4 Fév 2010MichelBuffaActions
REST_Carol.odp
Aucune description
1623 Ko08:32, 9 Nov 2011MichelBuffaActions
 webserv_tp1.zip
Aucune description
10.65 Mo15:03, 4 Fév 2010MichelBuffaActions
Images (0)
 
Commentaires (0)
Vous devez être connecté pour poster un commentaire.