NB : cet article fait partie d’une série de présentation et de tutorials pour démystifier Mule ESB : http://net-progress.blogspot.com/)
Dans l’exemple présenté dans cette partie, nous allons explorer les capacités d’un ESB : Protocol de transport, transformation et gestion des exceptions
L’exemple a pour objectif de répondre à une demande de résultat dans un examen pour un étudiant donnée. Les aspects suivants seront traités
1. Réception de l’invocation par deux méthodes (VM et http)
2. Développement et Utilisation de transformateurs spéciaux
3. Utilisation d’une stratégie de gestion des exceptions
4. Réponse synchrone par http et affichage directe dans la page web
Il s’agit d’un service en ligne de suivi des résultats des examens nationaux.
Un utilisateur pourra trouver les résultats de ses examens à travers une interface web dans son portail favoris.
Ce portail communique avec le serveur de l’université via un protocole de son choix : Mule est capable de varier le protocole d’exposition d’un service indépendamment de son implémentation
Créer un projet Mule vide et définir le fichier de configuration : resultat-examen-http-config.xml
Les Pojo en relation avec le projet sont :
Etudiant (sous sa forme la plus simple, pour les besoins du tutorial)
1: package com.oxia.att.mule.intro.beans;
2: import java.io.Serializable;
3: public class Etudiant implements Serializable {
4: private static final long serialVersionUID = 7010138636008560022L;
5: private String nom;
6: private String universite;
7: // getter & setter …
8: public boolean isValid() {
9: if (nom == null)
10: return false;
11: // accépter seulement si le nom a plus de 2 caractère
12: if (nom.length() > 1)
13: return true;
14: return false;
15: }
16: }
ResultatExamen : objet contenant le résultat de l’étudiant (sous sa forme la plus simple, pour les besoins du tutorial)
1: package com.oxia.att.mule.intro.beans;
2: import java.io.Serializable;
3: public class ResultatExamen implements Serializable {
4: private static final long serialVersionUID = -3140370545357738491L;
5: private StringBuffer resultat = new StringBuffer();
6: public StringBuffer append(String str) {
7: return resultat.append(str);
8: }
9: public StringBuffer append(StringBuffer sb) {
10: return resultat.append(sb);
11: }
12: public String toString() {
13: return resultat.toString();
14: }
15: }
Le projet se présente sous cette forme :
Le prologue :
1: <?xml version="1.0" encoding="UTF-8"?>
Fixer les namspaces à utiliser
1: <mule xmlns="http://www.mulesource.org/schema/mule/core/2.2"
2: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:spring="http://www.springframework.org/schema/beans"
3: xmlns:http="http://www.mulesource.org/schema/mule/http/2.2" xmlns:vm="http://www.mulesource.org/schema/mule/vm/2.2"
4: xmlns:stdio="http://www.mulesource.org/schema/mule/stdio/2.2"
5: xsi:schemaLocation="
6: http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7: http://www.mulesource.org/schema/mule/core/2.2 http://www.mulesource.org/schema/mule/core/2.2/mule.xsd
8: http://www.mulesource.org/schema/mule/http/2.2 http://www.mulesource.org/schema/mule/http/2.2/mule-http.xsd
9: http://www.mulesource.org/schema/mule/vm/2.2 http://www.mulesource.org/schema/mule/vm/2.2/mule-vm.xsd
10: http://www.mulesource.org/schema/mule/stdio/2.2 http://www.mulesource.org/schema/mule/stdio/2.2/mule-stdio.xsd">
Définir les transformateurs à utiliser
1: <custom-transformer name="StringToEtudiant"
2: class="com.oxia.att.mule.intro.transofrmer.StringToEtudiant" />
3: <custom-transformer name="EtudiantToResultatExamen"
4: class="com.oxia.att.mule.intro.transofrmer.EtudiantToResultatExamen" />
5: <custom-transformer name="ResultatExamenToString"
6: class="com.oxia.att.mule.intro.transofrmer.ResultatExamenToString"/>
7: <custom-transformer name="HttpRequestToEtudiant"
8: class="com.oxia.att.mule.intro.transofrmer.HttpRequestToEtudiant" />
9: <custom-transformer name="ExceptionToString"
10: class="com.oxia.att.mule.intro.transofrmer.ExceptionToString" />
11: <custom-transformer name="HttpRequestToParameter"
12: class="org.mule.transport.servlet.transformers.HttpRequestToParameter" />
13: <custom-transformer name="ObjectToString"
14: class="org.mule.transformer.simple.ObjectToString" />
Donnons ici un exemple de transformateur qui reste, rappelons le, un code spécifique à Mule.
Exemple de code source d’un transformateur spécifique développe dans le cadre de ce tutorial
1: package com.oxia.att.mule.intro.transofrmer;
2: import org.mule.api.transformer.TransformerException;
3: import org.mule.transformer.AbstractTransformer;
4: import com.oxia.att.mule.intro.beans.ResultatExamen;
5: import com.oxia.att.mule.intro.beans.Etudiant;
6: public class EtudiantToResultatExamen extends AbstractTransformer {
7: public EtudiantToResultatExamen() {
8: super();
9: this.registerSourceType(Etudiant.class);
10: this.setReturnClass(ResultatExamen.class);
11: }
12: public Object doTransform(Object src, String encoding)
13: throws TransformerException {
14: ResultatExamen resultatExamen = new ResultatExamen();
15: Etudiant etudiant = (Etudiant) src;
16: resultatExamen.append("Le candidat : ");
17: resultatExamen.append(etudiant.getNom());
18: resultatExamen.append(" de L'universite : ");
19: resultatExamen.append(etudiant.getUniversite());
20: return resultatExamen;
21: }
22: }
Une classe de Transformation
· hérite de la classe AbstractTransformer
· et implémente la méthode doTransform(…).
Cette classe a accès au Payload du message et suppose qu’il est de type Etudiant
Il est préférable de rester indépendant du protocole de transport afin de réutiliser les transformations dans d’autres situations :
1: Etudiant etudiant = (Etudiant) src;
1: <model name="ResultatExamenSample">
2: La définition des services
3: </model>
Rappelons, que dans un service il ya 4 parties
<component /> |
Le composant |
<outbound>
</outbound> |
Le point de sortie |
<default-service-exception-strategy>
</default-service-exception-strategy> |
La gestion des exceptions |
</service> |
|
Définir les entrées du service
Dans le premier service nommé DonneesEtudiant, nous allons avoir deux points d’entrée :
· Un point d’entrée http
· Un point d’entrée vm
1: <inbound>
2: <inbound-endpoint address="http://localhost:8888"
3: transformer-refs="HttpRequestToEtudiant" synchronous="true">
4: </inbound-endpoint>
5: <vm:inbound-endpoint path="etudiant"
6: transformer-refs="StringToEtudiant" synchronous="true" />
7: </inbound>
Pour appeler le service avec HTTP, lancer cette URL dans un navigateur
http://localhost:8888?nom=Khalil
pour faire appel à ce service avec la programmation, utiliser la classe MuleClient:
MuleClient client = new MuleClient();
client.send("vm://etudiant", "Khalil", null);
UMOMessage response = client.send("vm://etudiant", "Ross", null);
System.out.println("response = " + response.getPayload());
Utilisons ici un appel direct à la classe de service (un Simple POJO)
1: <component class="com.oxia.att.mule.intro.service.VerifierCandidat" />
Nous illustrons dans cette partie l’usage des filtres :
Les Filtres permettent de préciser les conditions qui doivent être remplies pour un message afin qu’il soit acheminé à un service. Il existe plusieurs types de filtres offerts par Mule que vous pouvez utiliser. Il est possible de créer vos propres filtres.
Nous utilisons ici un routeur spécial : le <filtering-router> : qui présente l’avantage de filtrer selon le contenu et dispatché vers le point de sortie approprié.
· Si le résultat est de type Etudiant alors tout va bien
· Si c’est une exception (ici de type com.oxia.att.mule.intro.exception.CandidatException) alors on passe en mode erreur
1:<outbound>
2:<filtering-router>
3: <vm:outbound-endpoint path="getResultatExamen" synchronous="true" />
4: <payload-type-filter
5: expectedType="com.oxia.att.mule.intro.beans.Etudiant" />
6:</filtering-router>
7:<filtering-router>
8: <vm:outbound-endpoint path="userErrorHandler" synchronous="true" />
9: <payload-type-filter
10: expectedType="com.oxia.att.mule.intro.exception.CandidatException" />
11: </filtering-router>
12:</outbound>
Et
1: default-service-exception-strategy>
2: <vm:outbound-endpoint path="systemErrorHandler" />
3: </default-service-exception-strategy>
Pour finaliser le projet, il reste à indiquer les destinations getResultatExamen, userErrorHandler et systemErrorHandler
Pour cela une solution est définir des nouveaux services :
1: <service name="ResultatExamen">
2: <inbound>
3: <vm:inbound-endpoint path="getResultatExamen"
4: transformer-refs="EtudiantToResultatExamen"
5: responseTransformer-refs="ResultatExamenToString"
6: synchronous="true" />
7: </inbound>
8: <component
9: class="com.oxia.att.mule.intro.service.ObtenirResultatExamen" />
10: </service>
11: <service name="UserErrorHandler">
12: <inbound>
13: <vm:inbound-endpoint path="userErrorHandler"
14: responseTransformer-refs="ExceptionToString" synchronous="true"/>
15: </inbound>
16: </service>
Dans ce dernier service, nous utilisons le fameux routeur <pass-through-router>
1: <service name="SystemErrorHandler">
2: <inbound>
3: <vm:inbound-endpoint path="systemErrorHandler" synchronous="true" />
4: </inbound>
5: <outbound>
6: <pass-through-router>
7: <stdio:outbound-endpoint system="ERR" />
8: </pass-through-router>
9: </outbound>
10: </service>
Une fois lancé il suffit d’utiliser une simple page HTML
1: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2: <html xmlns="http://www.w3.org/1999/xhtml">
3: <head>
4: <title>Obtenir Résultat Examen</title>
5: </head>
6: <body>
7: <form method="GET" action="http://localhost:8888">
8: <input type="text" name="nom"/>
9: <input type="submit" value="Demander le Résultat de l'Examen" />
10: </form><br />
11: </body>
12: </html>
La réponse est alors la suivante
Le serveur indique que tout s’est bien passé
INFO 2009-07-12 00:08:53,890 [connector.http.0.receiver.2] org.mule.transport.vm.VMMessageDispatcher: Connected: endpoint.outbound.vm://getResultatExamen
|
Si on provoque une exception (il suffit d’envoyer un nom de 1 caractère)
Le résultat est toujours affiché ( la situation est maitrisée)
Le serveur indique qu’on est passé en mode exception :
<><><><><>
INFO 2009-07-12 00:12:24,000 [connector.http.0.receiver.2] org.mule.transport.vm.VMMessageDispatcher: Connected: endpoint.outbound.vm://userErrorHandler
|