Table des matières

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

<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>

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:

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:

<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 :

<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:

<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):

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

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