====== Projet commun TI1-CAHD et TIW5-SW ====== Le projet est à réaliser en groupe en prenant les groupes TI5. Pensez à bien vous répartir le travail. ===== Mise à jour ===== * 2012-12-21: Exemple de code pour le bean transformation + routage dans la section [[#smix-camel|camel]]. * 2012-12-14: * Nouvelle version de vysper-run (serveur jabber) [[http://liris.cnrs.fr/~ecoquery/files/vysper-run-2012.1-jar-with-dependencies.jar|disponible ici]]. Cette version ajoute automatiquement rapidodvd@localhost comme contact de tous les autres utilisateurs et réciproquement. Requis pour une bonne communication entre les utilisateurs (en particulier pour la réception des messages à destination de //RapidoDVD// via servicemix). * Mise à jour de la section [[#smix-camel|camel]] sur l'utilisation des beans. Concerne la transformation de message et le routage dynamique. * 2012-12-13: Ajout de tips pour l'utilisation de beans dans servicemix: utile pour les transformations de messages et le routage dynamique. * 2012-12-05: projet fourni pour le dispositif de paiement. Archive: {{:enseignement:sw:projet:tiw5-2012-fourni.zip|}}. Voir les détails sur le paiement. * 2012-11-30: ajout de JMS dans l'exemple Camel. Bugfix pour le processus BPEL. Nouvelle version disponible sur la forge. {{:enseignement:sw:projet:tiw5-2012-tp-base.zip|}} a été mis à jour. Pour la faire fonctionner, il faut exécuter dans servicemix la commande ''features:install activemq-spring'' avant l'installation du nouveau //service assembly// Dans la configuration du composant ''cxf-provider''((projet smix-cxf)), l'attribut ''useJBIWrapper=false'' est indispensable pour faire fonctionner BPEL/ODE avec le composant CXF qui permet de communiquer en http pour appeler les services JBoss. * 2012-11-29: précisions sur la partie CAHD ===== Introduction ===== L'objectif de ce projet est de développer un petit système d'informations à base de services et de composants ayant pour objectif de gérer un système de location de DVDs: //RapidoDVD//. On considérera les acteurs suivants: * les clients qui désirent louer des DVDs * le magasin (virtuel) de location de DVDs //RapidoDVD// * le prestataire de paiement en ligne //Rapid'Bank.com// * un institut bancaire qui gère les comptes des clients //mabanque.com// * un fournisseur de données de films //IMDB// * un transporteur //ScootDVD// ==== Principe d'une location ==== Chaque client de //RapidoDVD// possède un compte de location sur le site du magasin virtuel. Son compte doit être approvisionné pour pouvoir louer un DVD. Il peut recharger son compte en ligne, en passant par le prestataire //Rapid'Banque.com// (voir plus loin). === Fonctionnement de la location === Un client s'authentifie sur le magasin virtuel //RapidoDVD// puis consulte le catalogue des films disponibles à la location en DVD. Les descriptions des films sont enrichies à l'aide d'//IMDB//. Lorsqu'il a choisi un film, il valide la location pour indiquer au site qu'il souhaite louer ce DVD. Celui-ci tente de débiter son compte. Si son compte est suffisamment approvisionné, le site débite le compte et enregistre la location, et le DVD lui est apporté physiquement par //ScootDVD//. Dans le cas contraire, la location est bloquée tant que le solde du client n'est pas suffisant, et débloquée dès que le compte est réapprovisionné. Si une location est bloquée pendant plus de 30 minutes, elle est annulée. Une fois le DVD livré, le client est prévenu par messagerie Jabber (XMPP). Lorsqu'il veut rendre le DVD, le client le signale par un message Jabber ou sur le site web de //RapidoDVD//. //ScootDVD// vient chercher le DVD. Lorsque cela est fait, le DVD est considéré comme rendu. === Fonctionnement du paiement en ligne === Lorsqu'une location vient d'être bloquée ou lorsqu'il consulte son compte sur le site de //RapidoDVD//, le client peut recharger son compte. Pour cela, il est redirigé sur le site du prestataire de paiement en ligne //Rapid'Banque.com//, qui gère les transactions financières pour le compte de //RapidoDVD//. Le site de //Rapid'Banque.com// demande au client d'entrer le montant à débiter, son numéro de carte et son code confidentiel et se connecte à la banque du client : //mabanque.com// pour réaliser la transaction. Si cette dernière accepte le paiement, //Rapid'Banque.com// valide la transaction et redirige le client sur le site de //RapidoDVD//. Dans le cas contraire, aucune transaction n'est réalisée. Le client peut également se connecter sur l'interface Web de sa banque (//mabanque.com//), à l'aide d'un login et d'un mot de passe spécifiques. De là, il peut consulter son compte en banque (différent du compte de location //RapidoDVD//) ou le recharger en indiquant la somme qu'il souhaite rajouter (pratique ;-)). **Mise à jour:** L'application fournie plus haut diffère légèrement du comportement ci-dessus: * Le site de //Rapid'Bank// ne redirige pas vers le site de //RapidoDVD// en fin de transaction. De plus, il attend un paramètre ''user'' et un paramètre ''valeur'', transmis via e.g. l'URL en paramètres GET((une transmission en POST est également acceptée)). Le premier correspond à l'utilisateur de RapidoDVD ayant un compte à approvisionner, le second à la valeur de l'approvisionnement. * Le site //mabanque.com// fourni une interface de gestion des comptes unique. * Le //Rapid'Bank// prévient //RapidoDVD// que la transaction a bien été effectuée en lui envoyant un message directement. Le WSDL (''Approvisionne.wsdl'') du service à implémenter pour recevoir ce message est fourni dans l'archive {{:enseignement:sw:projet:tiw5-2012-fourni.zip|}}, dans le projet ''rapidbank.com''. Si il n'y a pas de service implémentant ''rapidbank.com/src/main/resources/Approvisionne.wsdl'', l'approvisionnement échoue. Un mockup((faux service)) peut être lancé via java -jar approvisionne-mockup/target/approvisionne-mockup-2012.0-jar-with-dependencies.jar à condition d'avoir stoppé servicemix (vu que tous les deux utilisent le port 8081). Pour utiliser un autre port, éditer ''ApprovisionneMockup.java''((approvisionne-mockup/src/main/java/tiw5/fourni/mockup/ApprovisionneMockup.java)), changer le port 8081 en autre chose, e.g. 8086. Recompiler et lancer le serveur de //Rapid'Bank// avec ''--rapidodvd http://localhost:8086/services/approvisionne''. ===== Implémentation demandée ===== ==== Site web de RapidoDVD ==== Ce site contient un catalogue de DVDs alimenté par la base de films de //RapidoDVD// pour savoir quels films sont disponibles et par //IMDB// (voir la description plus bas) pour le descriptif des films. Il permet à un client de s'enregistrer (login, password, id Jabber), de consulter son compte, ainsi que sa liste de locations en cours. Il contient également une partie administration réservée au gérant et permettant d'ajouter un nouvel exemplaire de DVD pour un film en utilisant la référence du film sur //IMDB// comme point de repère. ==== rapidodvd@localhost ==== Ajouter un compte Jabber pour //RapidoDVD//. Ce compte pourra recevoir des messages de la part des clients de //RapidoDVD// pour rendre un DVD, consulter leur solde et consulter la liste des DVDs qu'ils ont loué. C'est aussi ce compte Jabber qui prévient le client lorsque le DVD commandé est arrivé. ==== Site web de ScootDVD ==== Ce site est utilisé par les livreurs de ScootDVD. Il leur permet de préciser quand ils prennent ou déposent un DVD chez //RapidoDVD// ou chez un client. ===== Composants fournis ===== ==== Site web de Rapid'Banque.com ==== Ce site possède une interface Web permettant aux clients de faire un virement vers le compte d'un site marchand. Pour cela, il consomme le service de transactions bancaires proposé par //mabanque.com//. Lorsqu'une transaction est acceptée, il envoie un message au site marchand indiquant l'identifiant du client et la somme qui a été transférée et redirige le client sur ce site. Lorsqu'une transaction est refusée, il notifie également le site. Pour le lancer:java -jar rapidbank.com/target/rapidbank.com-2012.0-jar-with-dependencies.jar ajouter ''--help'' pour les options URL vers laquelle rediriger pour le paiement: http://localhost:8083/?user=machin&valeur=2.0 où ''machin'' est l'utilisateur dont on veut approvisionner le compte et ''2.0'' les le montant à approvisionner. ==== Site web de mabanque.com ==== Ce site réalise une gestion basique du compte en banque du client. Le site de //mabanque.com// possède deux interfaces : * Une interface de service qui permet aux prestataires comme //Rapid'Banque.com// d'effectuer des débits à l'aide du numéro de carte du client et du code confidentiel associé. Si le compte en banque du client est approvisionné, //mabanque.com// accepte la transaction et débite le compte en banque. Sinon, le service génère une faute. * Une interface Web qui permet au client, après authentification, de consulter et de recharger son compte en banque en indiquant la somme qu'il souhaite rajouter (pratique ;-)). Pour le lancer:java -jar mabanque.com/target/mabanque.com-2012.0-jar-with-dependencies.jarAjouter ''--help'' pour les options. Interface d'administration: http://localhost:8082/admin ==== Architecture ==== === RapidoDVD === Les informations transiteront entre les différents acteurs en passant par un bus de service (ServiceMix). Le cas échéant, il sera possible d'utiliser un ou plusieurs processus BPEL. Les services implémentés en Java ainsi que les sites Web de l'application //RapidoDVD// tourneront en parallèle sur un serveur JBoss. La communication Jabber se fera par l'intermédiaire d'un serveur XMPP local (fourni). === ScootDVD === L'application //ScootDVD// tournera sur un autre port de la VM, et sera réalisée en Spring. === IMDB === Les données d'IMDB seront disponibles //via// un point d'accès SPARQL (fourni). La partie de l'application Web qui consiste à enrichir la description des films à l'aide des données IMDB sera de préférence réalisée en Linked Data côté client (en JavaScript). ===== Environnement de travail ===== Une nouvelle mouture de la machine vituelle TI1_TIW5 sera fournie jeudi 29/11 matin. Les changements par rapport à la version actuelle sont les suivants: * Installation et configuration d'un serveur servicemix 4.3.0 pouvant faire tourner des process BPEL et pouvant interagir avec un serveur Jabber. * Installation d'un point d'accès SPARQL ([[http://4store.org/|4store]]) accessible via http://localhost:8085/status et qui peut être lancé via ''4store-web''((alias bash)). Ce point d'accès contient des [[http://download.freebase.com/datadumps/latest/browse/film/|données sur les films]] issus de [[http://www.freebase.com/view/film|freebase.com]]. * Installation d'un serveur Jabber ([[http://mina.apache.org/vysper-project/index.html|vysper]]) qui peut être lancé via ''(cd apps/jabber; java -jar vysper-run.jar)''. L'ajout des utilisateurs se fait via modification du fichier ''users.properties''. L'outil //Internet -> Pidgin// peut être utilisé pour interagir directement avec le serveur. Nouvelle version fournie pour le serveur Jabber [[http://liris.cnrs.fr/~ecoquery/files/vysper-run-2012.1-jar-with-dependencies.jar|vysper-run-2012.1-jar-with-dependencies.jar]]. Cette version enregistre automatiquement rapidodvd@localhost comme contact de tous les autres utilisateurs. ===== Projet de base ===== Le projet de base disponible via Mercurial ici https://forge.univ-lyon1.fr/hg/inf2018m-2012-tpbase ({{:enseignement:sw:projet:tiw5-2012-tp-base.zip|zip}}) a été mis-à-jour. Il intègre un projet servicemix (''smix'') divisé en plusieurs sous-projet. Ces sous-projets ont pour objectif de servir à la fois d'exemples et de configuration de départ, l'idée étant de modifier les fichiers de configuration de ces sous-projets sans ajouter d'autres sous-projets. ==== smix-cxf ==== Ce projet est un //binding component// permettant d'interfacer les messages du service avec HTTP. Il est configuré via le fichier ''src/main/resources/xbean.xml'' qui fait référence au fichier ''hello.wsdl''. Il permet au service de recevoir des requêtes http://localhost:8081/services/HelloImplService et http://localhost:8081/services/XMPPService. Il permet au bus d'utiliser le service disponible à l'adresse http://localhost:8080/services/HelloImplService((à déployer sur JBoss)). On peut remaquer qu'on a utilisé le port 8081 pour les services exposés par servicemix afin de garder le 8080 disponible pour JBoss ==== smix-bpel ==== Ce projet défini un processus BPEL qui agit comme un simple proxy vers un service de type HelloService. Les fichiers à étudier sont dans ''./src/main/resources/''. L'utilisation d'un service exterieur au bus nécessite d'être configuré directement au niveau du fichier ''deploy.xml''. Dans l'exemple fourni, on ne passe donc pas par smix-cxf dans le process BPEL pour accéder au service tournant sous JBoss ==== smix-camel ==== Ce projet défini les routes camel utilisées pour connecter les composants précédents. Elles sont configurées dans le fichier ''src/main/resources/camel-context.xml''. Les routes sont les suivantes (bien regarder comment le lien est fait en terme de nommage des services): * La première route prend les messages reçu via smix-cxf sur http://localhost:8081/services/HelloImplService, l'affiche dans le log, l'envoie au processus BPEL défini dans smix-bpel, affiche la réponse dans le log et renvoie implicitement le résultat via smix-cxf. * La seconde route lit les messages provenant de Jabber pour le compte ''toto@localhost'', les affiche dans le log puis les envoie sur la file JMS XMPPQueue.Test * La troisième route prend les messages de la file JMS XMPPQueue.Test et les affiche dans le log. Les messages envoyés à ''toto@localhost'' apparaissent donc 2 fois dans le log. * La quatrième route reçoit des messages via smix-cxf sur http://localhost:8081/services/XMPPService et les envoie via Jabber à titi@localhost pour le compte de toto@localhost. * La cinquième route permet de connecter ODE((i.e. le moteur BPEL)) avec le composant d'interface http (smix-cxf), tout en affichant les messages dans le log. Pour pouvoir utiliser le routage dynamique (composant ''dynamicRouter'', cf {{:enseignement:sw:tiw5-composition.pdf|cours}} et [[http://camel.apache.org/dynamic-router.html|page Camel]]) il faut passer à la version 2.6 de Camel((qui est celle déployée dans servicemix)). Pour cela, changer les dépendances dans le pom.xml du projet smix-camel: org.apache.servicemix servicemix-camel 2010.01 camel-core org.apache.camel camel-spring org.apache.camel org.apache.activemq activemq-camel 5.4.2 camel-core org.apache.camel camel-spring org.apache.camel camel-jms org.apache.camel org.apache.camel camel-jms 2.6.0 Pour transformer le format des message le long d'une route Camel (utile pour fabriquer du XML à partir des messages XMPP), il est possible d'utiliser un bean Spring déployé dans smix-camel. Voir http://camel.apache.org/bean.html, http://camel.apache.org/bean-binding.html et http://camel.apache.org/maven/current/camel-core/apidocs/index.html. Une méthode prennant un Message et renvoyant un Message devrait être appropriée.Une méthode ''void'' prenant en argument un ''Exchange'' devrait être appropriée. Ci-dessous un exemple qui utilise un bean pour ajouter dynamiquement un header nommé ''myHeader'', ce header étant utilisé ensuite par un ''recipientList'' dans la route Camel pour faire du routage dynamique.package tiw5.smix.camel; import java.util.logging.Logger; import org.apache.camel.Exchange; public class TestingDynamicRouter { private static final Logger LOG = Logger .getLogger(TestingDynamicRouter.class.getCanonicalName()); private int courant = 0; public void changeHeaderRoute(Exchange exchange) { exchange.getOut().setBody(exchange.getIn().getBody()); exchange.getOut().setHeaders(exchange.getIn().getHeaders()); String dest = "log:test" + courant; // calcule dynamiquement courant++; exchange.getOut().setHeader("myHeader", dest); LOG.info("Ajout du header 'myHeader' au message " + exchange.getOut().getMessageId() + ": " + dest); } } Dans le ''camel-context.xml'':
myHeader
...
Nouvelle version qui fait un routage XMPP et extrait le message du XML package tiw5.smix.camel; import java.io.StringReader; import java.io.StringWriter; import java.util.logging.Logger; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import org.apache.camel.Exchange; public class TestingDynamicRouter { private static final Logger LOG = Logger .getLogger(TestingDynamicRouter.class.getCanonicalName()); private static Transformer copy; static { try { copy = TransformerFactory.newInstance().newTransformer(); } catch (Exception e) { e.printStackTrace(); copy = null; } } public void changeHeaderRoute(Exchange exchange) throws TransformerException, XMLStreamException { // Copie du body dans une string Source inBody = exchange.getIn().getBody(Source.class); StringWriter sw = new StringWriter(); copy.transform(inBody, new StreamResult(sw)); // Utilisation d'un XMLStreamReader (API StAX) pour lire le XML depuis // la string // Rmq: le parsing de document pour faire du DOM semble buggé (document // avec un corps vide) // Rmq: La fabrication directe du XMLStreamReader depuis la Source // (sans passer par la String intermédiaire) échoue XMLStreamReader reader = XMLInputFactory.newInstance() .createXMLStreamReader(new StringReader(sw.toString())); String txt = null; // Boucle qui cherche un tag appelé "in" while (reader.hasNext()) { int type = reader.next(); if (type == XMLStreamReader.START_ELEMENT && "in".equals(reader.getLocalName())) break; } // Utilisation du texte dans le tag "in" pour le message if (reader.hasNext() && XMLStreamReader.CHARACTERS == reader.next()) { txt = reader.getText(); } reader.close(); // On fait un setBody avec une String pour envoyer à Jabber exchange.getOut().setBody("Message: " + txt); // Headers pour le routage dynamique exchange.getOut().setHeaders(exchange.getIn().getHeaders()); String destinataire = "titi@localhost"; // normalement calculé dynamiquement String dest = "log:toxmpp,xmpp://rapidodvd@localhost/" + destinataire + "?password=rapidomdp"; exchange.getOut().setHeader("myHeader", dest); LOG.info("Ajout du header 'myHeader' au message " + exchange.getOut().getMessageId() + ": " + dest); } } ==== smix-sa ==== Ce projet sert simplement à regrouper les 3 précédents en une archive à déployer dans servicemix. Bien déployer l'archive .zip. L'archive .jar ne fonctionne pas. ===== Utilisation de servicemix ===== La commande ''bin/servicemix'' lance le serveur et fourni une interface textuelle de gestion. Bien que l'on récupère rapidement la main du côté de l'interface texte, le serveur est en fait assez long à démarrer -> vérifier l'utilisation CPU avec ''top''. * ''log:display -n 20'' affiche les 20 dernières entrées du log * ''list'' liste les bundles installés * ''install file:///chemin/vers/le/fichier/a/deployer.zip'' permet d'installer un fichier et indique le numéro correspondant au bundle. * ''start xxx'' démarre le bundle xxx * ''stop xxx'' arrête le bundle indiqué * ''uninstall xxx'' déinstalle le bundle indiqué. * ''nmr:list'' liste les point d'accès connus dans servicemix * ''activemq:browse --amqurl tcp://localhost:61616 XMPPQueue.Test'' affiche le contenu de la file ''XMPPQueue.Test'' ===== Trucs & astuces ===== Pour trouver quel processus occupe le port 8085:lsof -i :8085 Avant de lancer ''4store-web'', changer les permissions de ''/var/lib/4store/films/''sudo chmod -R a+rxw /var/lib/4store/films/ Editer également le fichier ''/etc/xdg/autostart/gnome-keyring-pkcs11.desktop'' (en sudo) et y ajouter ''LXDE;'' après ''OnlyShowIn=GNOME;Unity;''. Merci à Nathalie pour l'astuce. Tuer les processus lancés par 4store-web:killall 4s-httpd killall 4s-backend Lien vers la procédure de réinstallation de 4store : [[http://liris.cnrs.fr/~ecoquery/dokuwiki/doku.php?id=enseignement:sw:installation_4store]]