Axis2 : Rerouter vos appels de services sans modifier vote code client

Imaginons que vous ayez à votre disposition un client de Web service et que pour une raison (qui doit être bonne je l’accorde), vous avez besoin de rerouter vos appels de service vers un nouveau point d’accès. Le problème est que vous n’avez pas le droit de modifier le code client (ou que vous ne l’avez pas), que vous ne voulez pas regénérer ce code client à partir du WSDL du nouveau service a appeler (qui est exactement le même hormis l’adresse du endpoint)… Heureusement, votre client utilise la pile Web service Apache Axis2, et les développeurs d’Axis2 ont gentiment pensé à introduire des modules dans leur architecture. Une bonne intorduction aux modules est disponible dans le guide d’architecture d’Axis2.

Nous allons donc développer un module qui change dynamiquement l’URL de l’endpoint à appeler (on utilisera bien sûr Maven2 pour nous aider à créer et packager le projet…).

1. Créer le projet

Utilisons Maven2 pour créer un projet :

mvn archetype:generate

et je réponds bêtement a Maven quand il me pose des questions sur le groupId, l’artifactId, etc… Une fois créé, je génère le projet Eclipse associé et je l’importe (Eclipse fait aussi parti de mes grand amis) :

mvn eclipse:eclipse

Ill faut modifier le POM pour dire a Maven que l’on est en train de créer un projet qui n’est pas une librarie Java mais un module Axis2. Ceci est possible en spécifiant le type de projet dans le POM et en déclarant que l’on veut utiliser le plugin MAR fournit par Axis2 :


<project ...>

...

<groupId>foo.bar</groupId>
<artifactId>reroute</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>mar</packaging>

...

<dependencies>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-kernel</artifactId>
<version>1.5.1</version>
</dependency>
</dependencies>

...

<build>
<plugins>
<plugin>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-mar-maven-plugin</artifactId>
<version>1.5.1</version>
<extensions>true</extensions>
<configuration>
<moduleXmlFile>src/main/META-INF/module.xml</moduleXmlFile>
<includeDependencies>false</includeDependencies>
</configuration>
</plugin>
</plugins>
</build>
...
</project>

2. Business code

Créons maintenant notre handler (le module est en fait un handler Axis2 packagé dans une archive avec un descripteur de module). Pour faire simple, je vais étendre la classe AbstractHandler pour créer mon Handler de reroutage et remplacer le ‘target EPR’ par le nouveau (bien sûr on peut faire quelque chose de beaucoup plus évolué, on va dire qu’ici tout part vers un seul service) :

package net.chamerling.blog.axis2module.reroute;

import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.handlers.AbstractHandler;
import org.apache.axis2.util.LoggingControl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author chamerling
 *
 */
public class ReRouteHandler extends AbstractHandler {
	private static final Log log = LogFactory.getLog(AbstractHandler.class);

	private static final String FINAL_EPR_PREFIX = "http://localhost:8082/petals/proxy/";

	/**
	 * {@inheritDoc}
	 */
	public InvocationResponse invoke(MessageContext messageContext)
			throws AxisFault {
		EndpointReference toEPR = messageContext.getOptions().getTo();
		String finalEPR = FINAL_EPR_PREFIX + toEPR.getAddress();

		if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled()) {
			log.debug("Reroute Handler for message : "
					+ messageContext.getMessageID());
			log.debug("Initial ToEPR is " + toEPR.getAddress()
					+ " and is changed to " + finalEPR);
		}

		toEPR.setAddress(finalEPR);
		return InvocationResponse.CONTINUE;
	}
}
<pre>

Avec Axis2 c’est ‘facile’, tout est dans le message context! Je viens de remplacer le service à appeler par le mien en modifiant le champ ‘address’ du ‘EndpointReference’.

3. Packager le module

Pour créer un module avec le Handler que l’on vient de définir, il faut passer par l’écriture du fichier de description du module, le ‘module.xml’. Ici c’est simple :

<module name="reroute">
	<OutFlow>
		<handler name="ReRouteHandler" class="net.chamerling.blog.axis2module.reroute.ReRouteHandler">
			<order phase="reroutePhase" />
		</handler>
	</OutFlow>
</module>
<pre>

Mon module s’appellera donc ‘reroute’ et sera appelé que lors de la phase d’émission de message ‘OutFlow’. Plus d’informations sur ce qui est possible avec ce fichier sur le site d’Axis2.

4. Configurer Axis2

Il y a plusieurs façcons de dire à Axis2 d’utiliser le module que l’on vient de développer. En se basant sur la contrainte de départ, je n’ai pas le droit de modifier mes services donc je ne peux pas modifier le descripteur de service ‘service.xml’. Heureusement, j’ai accès au serveur et je peux modifier le fichier de configuration d’Axis2 ‘axis2.xml’ :

...
<!-- Engage the reroute module -->
<module ref="reroute" />
...
<phaseOrder type="OutFlow">
	<!--      user can add his own phases to this area  -->
	<phase name="soapmonitorPhase" />
	<phase name="OperationOutPhase" />
	<!--system predefined phase-->
	<!--these phase will run irrespective of the service-->
	<phase name="PolicyDetermination" />
	<phase name="reroutePhase" />
	<phase name="MessageOut" />
	<phase name="Security" />
</phaseOrder>
<pre>

Je viens d’engager mon module pour tous les services et je l’ai aussi ajouté dans la collection de phases qui est appelé lors de l’émission d’un message. A chaque fois qu’un message est envoyé vers un service, on passe donc dans le module que l’on vient de développer. Je viens donc de modifier les services invoqués sans modifier le code client! Je reviendrais bientôt sur l’utilisation de ce genre de choses dans un vrai cas d’usage avec du REST, du SOAP, des PROXYs, de l’ESB distribué sur le Web (bien sûr avec Petals ESB), etc…

Resources

Le code de ce ‘tutoriel’ est bien sûr disponible sur mon Google Code sous http://code.google.com/p/chamerling/source/browse/#svn/trunk/blog/reroute-axis2.

4 réflexions sur “Axis2 : Rerouter vos appels de services sans modifier vote code client

  1. Pingback: Les classloaders des modules dans Axis2: Les ressources « Christophe Hamerling TechBlog

  2. Pingback: 2010 in review « c.hamerling

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s