Introduction aux EIPs (suite) : mise en pratique avec Apache Camel

Suite de l’article précédent, la mise en pratique des EIPs se fera avec une mise en bouche de deux frameworks d’intégrations : Apache Camel et Spring Integration

Pour rappel, l’exemple de flux simple a été modélisé ainsi :

Deux implémentations vont être réalisées afin de présenter les deux frameworks, voici la première avec Apache Camel.

Apache Camel

Directement basé sur les EIPs, Camel permet de créer des routes et des règles de médiations. Nous verrons que ce framework comme Spring Integration, ne suit pas forcément à la lettre les design et modélisations des EIPs, certaines simplifications et extensions sont mises en place. Une des particularités de Camel est qu’il propose plusieurs moyen de définir des routes, comme par exemple par l’intermédiaire d’une API Java de type DSL ou par fichier de configuration Spring XML.

L’implémentations des EIPs se fait par l’utilisation de composants (qui peuvent être des endpoints comme des simple transformer) et de data format afin de faciliter la conversion de données.

Chaque composant possède sa propre URI,  qui déterminer à la fois le transport utilisé et des paramètres propres au composant. Par exemple, un endpoint http en entrée relié à un endpoint http de sortie donne en Java DSL :

from("jetty:http://localhost:9000/test").to("http://www.google.com");

Cette route indique que le composant Camel jetty est utilisé en entrée, écoute sur le port 9000 et transmet les requêtes en entrée vers google grâce au composant http de camel.
La liste des composants est disponibles ici. Ainsi le composant file permet de lire ou écrire un fichier, le composant cxf de faire appel à un web service cxf etc…
Un exemple de route en xml :

<route>
	<from uri="jetty:http://localhost:9000/test" />
	<to uri="http://www.google.com" />
</route>

Implémentation de la route

Implémenter notre route d’exemple se résume donc à choisir les composants camel à utiliser ou à en créer de nouveaux. L’implémentation choisie a finalement été :

  • Utilisation d’un web service rest CXF comme endpoint d’entrée
  • Utilisation d’un template velocity pour construire la requête XML nécessaire
  • Utilisation du composant http pour le endpoint vers google
  • Une transformation standard du xml vers json grâce à un data-format
L’exemple ayant été implémenté sous maven, chaque composant est une dépendance maven à rajouter pour pouvoir l’utiliser, soient CXF, velocity, http et xmljson.
La route a été définie ainsi :
from("cxfrs:bean:spellCheckEndpoint")
		.to("velocity:request.xml")
		.setHeader(Exchange.HTTP_URI,
			simple("http://www.google.com/tbproxy/spell?lang=en"))
		.setHeader(Exchange.HTTP_METHOD, constant("POST"))
		.to("http://googleSpellCheck").marshal().xmljson();
L’équivalent en xml :
<route>
    <from uri="cxfrs:bean:spellCheckEndpoint"/>
    <to uri="velocity:request.xml"/>
    <setHeader headerName="CamelHttpUri">
        <simple>http://www.google.com/tbproxy/spell?lang=en</simple>
    </setHeader>
    <setHeader headerName="CamelHttpMethod">
        <constant>POST</constant>
    </setHeader>
    <to uri="http://googleSpellCheck"/>
    <marshal>
        <xmljson/>
    </marshal>
</route>

La route va être détaillée point par point.

CXF

Le endpoint d’entrée utilise le composant CXFRS. L’URI précise le bean spring à utiliser, son implémentation (JAX-RS) est simple :

@Path("/")
public class SpellCheck {
	@GET
	@Path("/{word}")
	@Produces("text/json")
	public String getSpellCheck(@PathParam("word") String word) {
		return word;
	}
}

Il retourne simplement le path param ‘word’ qui constituera donc le corps du message de la route.
Il est ensuite déclaré en tant que bean spring grâce à une notation spécifique afin de créer simplement le connecteur jetty associé :

<cxf:rsServer id="spellCheckEndpoint" address="http://0.0.0.0:9001/spell/"
		serviceClass="com.sedona.simple.SpellCheck" />

Template Velocity

Le composant velocity est ensuite utilisé pour dynamiser le requête xml qui sera envoyée à google :

<?xml version="1.0" encoding="utf-8" ?>
<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">
    <text>${body[0]}</text>
</spellrequest>

Le path param précédemment récupéré par le service JAX-RS est donc inséré dans la balise text et le xml constitue désormais le payload du message.

Http

L’envoi de la requête http vers google se fait par le composant http. Comme précisé dans le précédent article les messages routés sont composés de headers et d’un payload. Afin de spécifier la destination réel du message et la méthode utilisée pour le requête (un Post), des headers sont précisés avant de faire appel au composant.

Réponse json

Enfin, la réponse est convertie grâce aux système data format de Camel, grâce à xmljson.
Par défaut, une route Camel est de type request/reply, le retour vers le endpoint d’entrée est implicite.

Dernières configurations

Si la notation java DSL est utilisée, le code java doit être dans la méthode configure() d’un classe héritant de RouteBuilder. Le fichier spring doit ensuite contenir une référence vers cette dernière :

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation=" http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://camel.apache.org/schema/spring
	http://camel.apache.org/schema/spring/camel-spring.xsd">

	<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
		<package>com.sedona.simple</package>
	</camelContext>
</beans>

Pour la notation XML, il faut rajouter la définition dans la balise camelContext.
Pour tester, une classe Main standard camel est utilisée, se basant sur spring, elle charge automatiquement les fichiers spring positionnés dans le classpath dans META-INF/spring.

Une fois démarré, un simple test : http://localhost:9001/spell/herllo nous retourne un json avec des propositions de correction :

{"@error":"0","@clipped":"0","@charschecked":"6","@suggestedlang":"en","c":{"@o":"0","@l":"6","@s":"0","#text":"hello\tHelli\thell\tHeall\thallo"}}

Conclusion

Ce petit exemple a permis de présenter un aperçu de Camel, une page présente comment les différents EIPs sont intégrés mais c’est surtout la richesse de ses composants et connecteurs qui font la force de Camel, il a était simple de réaliser cette route avec un minimum de développement.

Prochain article : même exercice avec Spring Integration !

You may also like...

Laisser un commentaire