Angular JS, épisode 3 : il fait le REST (ou comment marier Angular et CXF)

Commençons par un résumé des épisodes précédents : après une présentation succincte d’Angular, nous avons développé une petite application de type « grille et détail » permettant d’éditer des objets téléphones.

Dans cet article, Henri Darmet, toujours lui, vous propose de connecter cette mini-réalisation à un véritable back-end en utilisant la technologie de communication phare du RIA : les services REST.

Angular JSLe tutoriel officiel d’Angular expose deux solutions, une « basique », à usage général, juste REST, et l’autre, plus spécialisée dans l’édition de données (la solution RESTful). L’ambition,  à moyen terme, étant de faire une application CRUD, intéressons nous tout de suite à la seconde, plus adaptée.

L’idée derrière tout ça ? Mesurer l’effort nécessaire pour avoir une chaine qui fonctionne de bout en bout dans un vrai environnement, c’est-à-dire avec de vrais services REST servis par un vrai serveur Java WEB. Et comme on pouvait s’y attendre, c’est bien plus délicat que d’exécuter les exemples du tutoriel, affutés pour gommer les difficultés.

Lire la suite

Ecrire un client WebService avec CXF

Cet article, proposé par Henri Darmet, présente une méthode presque générique pour écrire la partie cliente d’un Web Service en utilisant CXF.

On peut légitimement se demander en quoi cet article est légitime, vu qu’il existe de multiples tutoriels proposant un exercice de ce genre. Certes, mais tous se concentrent sur les premiers pas pour newbies. Et aucun ne vous propose la démarche complète qui intègre la transmission de pièces jointes au format binaire (en utilisant MTOM) et la sécurisation via WS-Security. C’est donc d’un client « professionnel » qu’il est question ici.

Je laisse à d’autres (ou à un autre article) le soin d’expliquer comment implémenter le service lui-même. Il s’avère que ce second exercice est en général bien mieux maîtrisé et mieux documenté.

Première étape : écrire un client simple

La première idée, celle qui nous vient tout de suite à l’esprit est de faire générer ce client par Eclipse. Mauvaise idée : celle-ci se basera sur le WSDL de votre Web Service, et l’exploitera ensuite dynamiquement. Conséquence : des appels frénétiques pour lire et exploiter ce WSDL, d’où

–          une grande difficulté pour les tester,

–          des performances dégradées,

–          pas de souplesse d’emploi.

En particulier, il est très difficile de préciser dynamiquement, sans venir altérer le code généré, l’URL  permettant d’atteindre le Web Service. Si bien que lorsqu’on doit changer d’environnement, le Web Service lui-même (pour passer d’une machine de développement pour aller en recette puis en production), il faut modifier le WSDL et régénérer le client : absurde.

Seconde solution : utiliser l’API CXF et là tout devient facile, ou presque. A titre d’exemple, je propose ici un Web Service d’envoi de mail (pour une application qui, par exemple, permet de s’adresser au SMTP de l’entreprise afin d’envoyer un mail au nom de l’entreprise). L’intérêt de cet exemple sera, bien sûr, qu’on peut y ajouter des pièces jointes et qu’il faudra le sécuriser (afin que n’importe qui, sur internet ne puisse spammer au nom de votre entreprise).

Voici le premier jet de l’interface de notre service :

package com.objetdirect.mailer;

import javax.jws.WebService;

@WebService

public interface Mailer {

 void send(Mail mail);

}

L’objet Mail contient toutes les informations qui doivent être contenues dans le mail, à savoir : une adresse d’origine (from), une série de déstinataires (to), un sujet (topic) et un contenu (message). Je vous propose l’implémentation triviale suivante :

package com.objetdirect.mailer;

 

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlRootElement;

 

@XmlRootElement

@XmlAccessorType(XmlAccessType.FIELD)

publicclass Mail {

String from;

String to;

String topic;

String message;

public Mail(String from, String to, String topic, String message) {

super();

this.from = from;

this.to = to;

this.topic = topic;

this.message = message;

}

public String getFrom() {

return from;

}

public String getTo() {

return to;

}

public String getTopic() {

return topic;

}

public String getMessage() {

returnmessage;

}

}

Passons à ce qui est le vrai sujet de cet exercice, l’écriture du bout de code qui nous permet d’accéder à un client de ce service :

package com.objetdirect.mailer;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;

import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;

 

publicclass MailerClient {

 publicstatic Mailer getClient(String url) {

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

factory.getInInterceptors().add(new LoggingInInterceptor());

factory.getOutInterceptors().add(new LoggingOutInterceptor());

factory.setServiceClass(Mailer.class);

factory.setAddress(url);

Mailer client = (Mailer) factory.create();

return client;

}

}

Eh, oui, c’est tout. Pas besoin d’une phase de génération. Notez, qu’à part la mention de son interface (la classe d’interface elle-même), il n’y a aucune adhérence entre cette méthode et le code du service. Il est donc possible de réécrire cette méthode pour qu’elle soit entièrement générique. Je vous laisse le soin de tenter l’exercice, cela vous permettra de vous dégourdir les jambes dans l’utilisation des generics J.

La seule donnée passée en paramètre est l’URL du WebService qui est donc bien définie dynamiquement. Il devient alors possible (et facile) de changer d’environnement.

L’implémentation proposée ici incluse l’appel d’intercepteur de log afin de journaliser, à toute fins utiles, les appels et les réponses. On aurait pu, à la rigueur la simplifier donc de deux lignes. Obtenir un client nécessite donc un minimum de quatre lignes…

Pour l’appeler, c’est encore plus simple :

publicstaticvoid main(String[] argv) {

Mailer mailer = MailerClient.getClient(

« http://www.acme.com/ws/mailer »

mailer.send(new Mail(

« noanswer@acme.com »,

« bigboss@goyoo.com »,

« New Webservice »,

« The new Web Service is ready ! »));

}

Comme on peut le constater, l’aide d’éclipse – vu la complexité très, très relative de l’exercice – ne s’impose en aucune manière.

Dans le prochain article, nous verrons comment sécuriser l’accès avec WS-Security.