Premiers pas avec Apache Camel

camel-box-small.pngAprès m'être renseigné sur les ESB, j'en arrive à la conclusion que ce genre de solution est certes, fort utile, mais relativement lourd à mettre en œuvre dans une DSI.

Si vous ne voulez qu'intégrer différents systèmes hétérogènes en créant des "routes" , l'étude et l'installation d'un ESB ça fait un peu Marteau Piqueur pour réaliser un petit trou dans le sol...

C'est en me renseignant sur Fuse ESB que j'ai découvert leur brique Mediation Router qui s'appuie sur Apache Camel. La société fournit également un IDE pour simplifier le développement.

Je me suis penché sur la création d'un proxy de service web. Ce dernier aura pour but de centraliser l'appel des services web, de tracer tous les accès, comme le fait Oracle Web Services Manager.

Les EIP

En matière d'intégration applicative, il y a deux solutions - comme en développement - : soit on réinvente la roue, soit on réutilise des solutions et patterns existants et déjà éprouvés. Ma première découverte fut de savoir déjà qu'il existait des design patterns d'intégration applicative. Ils sont appelés les EIP

Il existe un livre sur ce sujet. L'ensemble des patterns sont décrits sur le site.

Les patterns sont bien décrits et le site fournit un vocabulaire pour formaliser les échanges inter applicatifs.

Petite remarque : cet article n'a pas pour but de se substituer à la documentation officielle ni à la lecture du livre Camel in Action.

Apache Camel

Les composants

Il y quelques composants qu'il faut maitriser ou tout du moins connaître . Les composants Camel reprennent la terminologie employée dans les EIP. On y retrouvera

Un contexte (CamelContext)

Pour simplifier le contexte camel représente un runtime d’exécution de règles métiers et workflows. Cette notion n'apparaît pas à ma connaissance dans le livre EIP.

Voici un exemple au format spring:

<camelContext xmlns="http://camel.apache.org/schema/spring"
		id="proxycontext">
		<camel:package>org.apache.camel.example.server</camel:package>
		<camel:jmxAgent id="agent" createConnector="true" />
		<routeBuilder ref="proxyroutebuilder" id="main" />
		<!-- <routeBuilder ref ="bambuilder" id="bam" /> -->
		<routeBuilder ref="ping" />
		<route id="audit">
			<from uri="seda:audit" />
			<to uri="bean:auditService?method=audit" />
		</route>

Une route

Un workflow avec un point d'entrée ( from) , un ou plusieurs points de sortie et entre les deux différentes actions possibles ( transformation, filtre,...)

Un exemple en Java :

from("cxf:bean:proxy?dataFormat=MESSAGE").streamCaching().tracing()
				.convertBodyTo(String.class)
				.wireTap("seda:audit").to("activemq:queue:gototoken")
				.onException(Exception.class).handled(true)
				.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(500)).end()
				.log("message transmis pour ");

Les endpoints

Le from et to de la route abordée précédemment

Ils sont généralement spécifiés par une URI (ex.: uri="activemq:gototoken ). Camel fournit une palanquée de connecteurs. La liste exhaustive est accessible sur le site officiel. On y retrouvera les protocoles POP, SMTP, UDP, FILE, HTTP, AWS,...

Les différentes possibilités

Pour utiliser ce framework, il faut aimer spring ou du moins ne rien à reprocher à ce framework. En effet, on peut s'en passer et utiliser la description via une syntaxe JAVA DSL, mais la spécification d'un proxy de service web peut, par eemple s'effectuer sans une seule ligne de code via une configuration spring.

le monitoring

Et bien la il faut un peut se creuser les méninges. j'ai essayé d'utiliser le composant BAM. Ca ressemble un peu à une usine à gaz et peu utilisable pour ce que je voulais faire cad un peoxy de services web. Après quelques discussions sur la mailing-list du projet et la lecture du livre Camel in Action, il m'est apparu que le plus simple serait de le faire à la main.

JMX

L'ensemble des stats disponibles sur les routes et traitements sont disponibles via JMX.

Pour l'activer il suffit d'ajouter les dépendances dans le fichier pom.xml

et activer dans le contexte

<camel:jmxAgent id="agent" createConnector="true" />

Notification d'évènements

Camel peut également notifier via log4j ,JMX, via une interface de publication (PublishEventNotifier) ou encore , via une surcharge de la classe EventNotifierSupport de créant un notificateur personnalisé des différents évènements qui peuvent être temps de parcours de la route, erreurs, etc.

Un exemple

Je suis en train d'écrire un POC. Il est disponible sur bitbucket. je suis parti volontairement d'une route assez simpliste . Je demande à Camel d'écouter les appels SOAP sur une URI donnée

<cxf:cxfEndpoint id="proxy"
		address="http://localhost:8080/ws-proxy/webservices/proxy"
		endpointName="s:WSProxyEndpointPort" serviceName="s:WSProxyEndpointService"
		wsdlURL="/wsdl/ws-proxy.wsdl" xmlns:s="http://wsproxy.touret.info" />

Et je transmets ensuite la requête au "vrai" service web

from("cxf:bean:proxy?dataFormat=MESSAGE").streamCaching().tracing()
				.convertBodyTo(String.class)
				.wireTap("seda:audit").to("http://monserviceweb")
				.onException(Exception.class).handled(true)
				.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(500)).end()
				.log("message transmis pour ");

Ce qui est assez marrant c'est qu'il n'est pas indispensable de connaître le wsdl à appeler en cible. En effet, le wsdl que j'ai placé en endpoint de réception est quasiment un bouchon et est complètement différent de la cible et mon application n'héberge aucun service web . Camel intercepte l'appel avant que le service web ne soit interprété et exécute la route dans le contexte courant.

Conclusion

Pas étonnant que ce framework serve de brique de médiation à différents ESB. Bien qu'assez récent, ce logiciel est très bien construit et bien documenté. Il peut suffire à réaliser la plupart des interconnexions disponibles via les ESB. Cependant l'une de ses grosses lacunes, mais bon on lui pardonnera car ce n'est pas trop le but, c'est le coté exploitation et cycle de vie des projets ou il faut (ré) écrire les différentes briques déjà disponibles dans les ESB.

Vus : 2091
Publié par Littlewing : 368