====== Web services: première mise en œuvre ====== :!: Mise à jour bugfix simplestorecal et version SAAJ Ce TP est à rendre pour le 14/11/2010 23:30 via [[http://spiral.univ-lyon1.fr/entree.asp?id=9055&objet=echangedocs|spiral]]. Il faudra rendre un zip contenant les projets commentés. Il est également demandé de créer un ensemble de tests pour chaque fonctionnalité. Lorsque cela est possible, on s'appuiera sur JUnit ([[enseignement:aide:apis#junit|Voir ici]]) pour la mise en place des tests. Il peut être utile pour déboguer d'utiliser [[http://liris.cnrs.fr/~ecoquery/tp-reseaux/tcpmon.jar|TCPMon]]. Il s'agit d'une application graphique qui agit comme un proxy espion permettant de voir le contenu échangé avec un serveur. ===== Utilisation d'un service ===== ==== Mise en place du service ==== Dans tous les cas s'assurer que c'est la version 6 du JDK qui est utilisée, par exemple en mettant les bonnes valeurs dans le ''PATH'' et dans ''JAVA_HOME'' Une implémentation du service est disponible ici: {{:enseignement:sw:simplestorecal.jar}}. (Sources: {{:enseignement:sw:simplestorecal-src.zip}}) Pour lancer le service, il suffit d'utiliser la commande: java -jar simplestorecal.jar Les calendriers sont stockés dans un répertoire ''docs'' dans un fichier portant leur nom. L'adresse du service est http://localhost:8079/sw et le wsdl est accessible ici: http://localhost:8079/store-cal.wsdl. ==== Test avec soapUI ==== [[http://www.soapui.org/|soapUI]] est une application permettant de tester des services. Installer soapUI ou le lancer avec Java Web Start. Créer un nouveau projet en spécifiant l'emplacement suivant pour le WSDL:[[http://localhost:8079/store-cal.wsdl]] (Disponible directement ici: {{:enseignement:sw:store-cal.wsdl}}, XML Schema associé: {{:enseignement:sw:simplecalendar.xsd}}). Par défaut, soapUI crée des requêtes de test à compléter pour chaque opération. Une fois le projet créé, éditer chaque requête pour remplir le contenu du message SOAP à envoyer. Modifier si besoin l'adresse du service sous la barre de titre. Lancer l'exécution des tests avec {{:enseignement:sw:soap-ui-run.png}}. Il est possible de combiner plusieurs requêtes dans un "TestCase", lui même intégré dans une "TestSuite" par clic droit sur une requête. Pour passer des valeurs d'une réponse à la requête suivante, on peut utiliser un [[http://www.soapui.org/userguide/functional/propertytransfers.html|property transfert]] (qui par ailleurs est semblable à un ''assign'' en WS-BPEL). Créer un TestCase qui envoie un calendrier au service via ''storeCalOperation'' puis le récupère via ''getCalOperation''. ===== Un programme pour gérer les calendriers ===== ==== Projet Maven ==== Utiliser le projet maven préconfiguré suivant: {{:enseignement:sw:clientsimple-src.zip}}. Ce projet dépend du projet du TP précédent. On remplacera dans ce projet toutes les occurences de ''COQUERY'' par les noms des deux binômes (:!: bien utiliser les mêmes nom que dans le TP précédent, en particulier dans la dépendance). Il est très fortment conseillé de lire le pom.xml et de comprendre les différentes déclarations afin de pouvoir les modifier au besoin. Remarque: si le projet du TP1 n'est pas trouvé par maven, il suffit normalement de l'installer en lançant mvn install depuis le répertoire du projet du tp1. ==== Récupération de calendrier ==== Ajouter la classe abstraite suivante à votre projet: package m2ti.ti3.clientsimple; import java.net.URL; import javax.xml.transform.Source; public abstract class CalendarRetriever { public abstract Source getCalendar(URL serviceEndpoint, String calendarName); public abstract int storeCalendar(URL serviceEndpoint, Source calendar); public static CalendarRetriever newInstance() { throw new UnsupportedOperationException("Non implementee"); } } Étendre ''CalendarRetriever'' avec une classe concrète et renvoyer une nouvelle instance de cette classe au lieu de lever une exception dans ''newInstance''. La méthode getCalendar devra, étant donné un identifiant (String), récupérer le calendrier correspondant stocké dans le service ''storeCalService'' utilisé ci-dessus, via l'utilisation de l'opération ''getCalOperation''. Pour ce faire, on utilisera au choix la bibliothèque [[http://ws.apache.org/axis2/|Axis2]] ou la bibliothèque [[https://saaj.dev.java.net/|SAAJ]]. Si cette dernière est utilisée, on pourra commenter la dépendance sur axis2 dans le fichier ''pom.xml'' car SAAJ est fournie avec le JDK 1.6. :!: Le service ''simplestorecal'' fonctionne en SOAP 1.2. Pour forcer à utiliser cette version avec SAAJ, il faut créer le message factory comme suit: factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL); On créera ensuite une application Java (i.e. une méthode ''main'' dans la classe App) qui utilisera la méthode précédente pour au choix (en fonction des arguments en ligne de commande): * afficher le calendrier sur la sortie standard (option par défaut) * stocker le résultat dans un fichier xml (dont le nom est passé en argument de la ligne de commande) Pour générer le .jar à exécuter: mvn package Ensuite, pour lancer l'application: java -jar target/ClientSimple-1.0-SNAPSHOT-jar-with-dependencies.jar Pour implémenter la méthode ''storeCalendar'', dans le cas de l'utilisation de SAAJ, l'insersion du calendrier dans le message doit se faire par copie. Il existe pour cela la classe ''javax.xml.soap.SAAJResult'' qui pourra être utilisée comme réceptacle de la copie. On peut par exemple s'inspirer du code suivant: public static int invokeStore(String name, Source cal, URL endpoint) { ... SOAPElement mainEl = body.addBodyElement(StoreCalConstants.STORE_CAL_INPUT_EL); ... SAAJResult mainElRes = new SAAJResult(mainEl); Transformer copy = TransformerFactory.newInstance().newTransformer(); copy.transform(cal, mainElRes); ... } Modifier l'application afin de pouvoir prendre un nom de fichier de calendrier ical et optionnellement un nom à associer au calendrier en arguments de la ligne de commande et utilisera le service pour stocker le calendrier. ===== Client sur serveur d'application ===== Utiliser l'archive {{:enseignement:sw:calendarwebapp-src.zip}} pour comme base pour un nouveau projet Maven. Ajouter la dépendance maven correspondant au projet ''ClientSimple'' avec la bonne version. Lors du développement de projets Web et/ou de service webs, il est conseillé d'utiliser des bibliothèques de logging (comme [[enseignement:aide:apis#log4j|Log4j]] ou les classes du package ''java.util.logging'') pour le deboggage. ==== Un fichier de propriétés ==== Dans ''Other Sources/resources''((i.e. ''src/main/resources'')), créer un fichier ''calwebapp.properties'' contenant ce qui suit: calservice.endpointurl=http://localhost:8079/sw Il est ensuite possible de récupérer les informations stockées dans ce fichier via un objet ''java.util.Properties'' qui va récupérer ces informations dans fichier via la méthode ''load''((On chargera ce fichier via le ''ClassLoader'')). Ce fichier sera utilisé pour récupérer l'adresse du service. ==== Une servlet qui s'interface avec le service ==== Ajouter la dépendance suivante à votre projet((scope: provided indique que le jar sera en pratique fourni par l'environnement d'exécution et qu'il n'y a donc pas lieu de le placer dans le ''.war'')): javax.servlet servlet-api 2.4 provided Créer une nouvelle servlet ''ViewCalendar'' dans le projet((ne pas oublier de spécifier un package pour la servlet)), dans laquelle on implémentera la méthode ''processRequest(HttpServletRequest request,HttpServletResponse response)''. Cette servlet aura le comportement suivant: * récupérer la valeur du paramètre ''calno'' (via ''request.getParameter(...)'') * appel a l'opération ''getCalOperation'' du web service ''storeCalService'' en utilisant la valeur de ''calno''. * si tout va bien: * envoi d'un header "Content-type: text/xml" via la méthode ''response.setContentType("text/xml")'' * envoi du fichier XML représentant le calendrier via son écriture sur ''response.get.getOutputStream()'' * Sinon: * envoi d'un content-type "text/html" * écriture sur ''response.getWriter()'' d'une page HTML décrivant l'erreur Pour lancer l'application, utiliser mvn tomcat:run -Dmaven.tomcat.port=8081 Remarque: cette commande lance l'application sur le port 8081, ce qui évite un conflit avec un serveur d'application lancé sur le port 8080. Tester ensuite la servlet via une URL du type [[http://localhost:8081/CalendarWebApp/ViewCalendar?calno=0]] ((on peut remplacer 0 par tout numéro de calendrier valide)). Remarque: Cette servlet constitue un premier exemple de service Web "léger". ==== Quelques évolutions ==== Modifier la servlet pour obtenir le comportement suivant, en fonction de la valeur du paramètre ''type'': * ''xml'' comportement précédent * ''html'' renvoie le formattage HTML du calendrier (//c.f.// [[sw-tp1-xml|TP 1]]). Le content-type doit être "text/html". * ''rss'' renvoie le formattage RSS du calendrier (//c.f.// [[sw-tp1-xml|TP 1]]). Le content-type doit être "application/rss+xml". Tester avec comme précédement avec votre navigateur Web.