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 camel.
  • 2012-12-14:
    • Nouvelle version de vysper-run (serveur jabber) 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 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: 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. tiw5-2012-tp-base.zip a été mis à jour.

<note important>Pour la faire fonctionner, il faut exécuter dans servicemix la commande features:install activemq-spring avant l'installation du nouveau service assembly</note> <note important>Dans la configuration du composant cxf-provider1), 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.</note>

  • 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 GET2). 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 tiw5-2012-fourni.zip, dans le projet rapidbank.com.

<note tip>Si il n'y a pas de service implémentant rapidbank.com/src/main/resources/Approvisionne.wsdl, l'approvisionnement échoue. Un mockup3) 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).</note>

<note tip> Pour utiliser un autre port, éditer ApprovisionneMockup.java4), 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.</note>

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.

<note tip>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.0machin est l'utilisateur dont on veut approvisionner le compte et 2.0 les le montant à approvisionner. </note>

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 ;-)).

<note tip>Pour le lancer:

java -jar mabanque.com/target/mabanque.com-2012.0-jar-with-dependencies.jar

Ajouter –help pour les options.

Interface d'administration: http://localhost:8082/admin </note>

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 (4store) accessible via http://localhost:8085/status et qui peut être lancé via 4store-web5). Ce point d'accès contient des données sur les films issus de freebase.com.
  • Installation d'un serveur Jabber (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.

<note important>Nouvelle version fournie pour le serveur Jabber vysper-run-2012.1-jar-with-dependencies.jar. Cette version enregistre automatiquement rapidodvd@localhost comme contact de tous les autres utilisateurs.</note>

Projet de base

Le projet de base disponible via Mercurial ici https://forge.univ-lyon1.fr/hg/inf2018m-2012-tpbase (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/HelloImplService6). <note tip>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</note>

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/. <note important>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</note>

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 ODE7) avec le composant d'interface http (smix-cxf), tout en affichant les messages dans le log.

<note important>Pour pouvoir utiliser le routage dynamique (composant dynamicRouter, cf cours et page Camel) il faut passer à la version 2.6 de Camel8). Pour cela, changer les dépendances dans le pom.xml du projet smix-camel:

    <dependency>
      <groupId>org.apache.servicemix</groupId>
      <artifactId>servicemix-camel</artifactId>
      <version>2010.01</version>
      <exclusions>
      	<exclusion>
      		<artifactId>camel-core</artifactId>
      		<groupId>org.apache.camel</groupId>
      	</exclusion>
      	<exclusion>
      		<artifactId>camel-spring</artifactId>
      		<groupId>org.apache.camel</groupId>
      	</exclusion>
      </exclusions>
    </dependency>
    <dependency>
    	<groupId>org.apache.activemq</groupId>
    	<artifactId>activemq-camel</artifactId>
    	<version>5.4.2</version>
    	<exclusions>
    		<exclusion>
    			<artifactId>camel-core</artifactId>
    			<groupId>org.apache.camel</groupId>
    		</exclusion>
    		<exclusion>
    			<artifactId>camel-spring</artifactId>
    			<groupId>org.apache.camel</groupId>
    		</exclusion>
    		<exclusion>
    			<artifactId>camel-jms</artifactId>
    			<groupId>org.apache.camel</groupId>
    		</exclusion>
    	</exclusions>
    </dependency>
    <dependency>
    	<groupId>org.apache.camel</groupId>
    	<artifactId>camel-jms</artifactId>
    	<version>2.6.0</version>
    </dependency>

</note> <note tip>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.

TestingDynamicRouter.java
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:

		<route>
			<from
				uri="jbi:endpoint:http://www.univ-lyon1.fr/M2TI/services/xmpp/salut/ep" />
			<to uri="bean:myRouter?method=changeHeaderRoute" />
			<to uri="log:testroute" />
			<recipientList>
				<header>myHeader</header>
			</recipientList>
			<!-- to uri="xmpp://toto@localhost/titi@localhost?password=toto" / -->
		</route>
 
...
 
	<bean id="myRouter" class="tiw5.smix.camel.TestingDynamicRouter" />

</note>

<note tip>Nouvelle version qui fait un routage XMPP et extrait le message du XML

TestingDynamicRouter.java
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);
	}
 
}

</note>

smix-sa

Ce projet sert simplement à regrouper les 3 précédents en une archive à déployer dans servicemix. <note important>Bien déployer l'archive .zip. L'archive .jar ne fonctionne pas.</note>

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

<note tip>Pour trouver quel processus occupe le port 8085:

lsof -i :8085

</note> <note important>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.</note> <note tip>Tuer les processus lancés par 4store-web:

killall 4s-httpd
killall 4s-backend

</note> <note tip>Lien vers la procédure de réinstallation de 4store : http://liris.cnrs.fr/~ecoquery/dokuwiki/doku.php?id=enseignement:sw:installation_4store</note>

1)
projet smix-cxf
2)
une transmission en POST est également acceptée
3)
faux service
4)
approvisionne-mockup/src/main/java/tiw5/fourni/mockup/ApprovisionneMockup.java
5)
alias bash
6)
à déployer sur JBoss
7)
i.e. le moteur BPEL
8)
qui est celle déployée dans servicemix