Adding Routing modules in Petals ESB

Petals ESB is based on a highly modular architecture built using software components based on the Fractal component model.

In a previous article about WSDM monitoring (https://chamerling.wordpress.com/2009/11/04/petals-esb-live-monitoring-with-wsdm-and-gwt/), I was speaking about adding routing modules to the ESB router to intercept messages and to notify the monitoring system that messages are transmitted and received between service consumers and providers.

In the current article, I am going to show you how you can add modules to the routing layer of the service bus. In short, the routing layer is the component which select the right endpoint(s) to send the current message to. The routing layer has been decomposed into routing modules which are all called when a message is sent or received.

There are two types of routing modules the SenderModule (org.ow2.petals.jbi.messaging.routing.module.SenderModule) and the ReceiverModule (org.ow2.petals.jbi.messaging.routing.module.ReceiverModule) which both have right names😉. All the sender modules will be called on message emission, the receiver ones will be called at message reception… Here are the Java APIs :

org.ow2.petals.jbi.messaging.routing.module.SenderModule


package org.ow2.petals.jbi.messaging.routing.module;

import java.util.Map;
import org.ow2.petals.jbi.component.context.ComponentContext;
import org.ow2.petals.jbi.messaging.endpoint.ServiceEndpoint;
import org.ow2.petals.jbi.messaging.exchange.MessageExchange;
import org.ow2.petals.jbi.messaging.routing.RoutingException;
import org.ow2.petals.transport.util.TransportSendContext;

public interface SenderModule {

void electEndpoints(final Map<ServiceEndpoint, TransportSendContext> electedEndpoints,

final ComponentContext sourceComponentContext, final MessageExchange exchange)

throws RoutingException;

}

org.ow2.petals.jbi.messaging.routing.module.ReceieverModule


package org.ow2.petals.jbi.messaging.routing.module;

import org.ow2.petals.jbi.component.context.ComponentContext;
import org.ow2.petals.jbi.messaging.exchange.MessageExchange;
import org.ow2.petals.jbi.messaging.routing.RoutingException;

public interface ReceiverModule {

boolean receiveExchange(final MessageExchange exchange,

final ComponentContext sourceComponentContext) throws RoutingException;

}

Implementing and adding modules to the Petals ESB router steps

1. Step one : Create your routing module by implementing the Sender and/or Receiver module interface(s) like, for example, just logging exchange information and date :


package com.googlecode.chamerling.blog.petals.router;

import java.util.Date;

import java.util.Map;

import org.objectweb.fractal.fraclet.annotation.annotations.FractalComponent;

import org.objectweb.fractal.fraclet.annotation.annotations.Interface;

import org.objectweb.fractal.fraclet.annotation.annotations.LifeCycle;

import org.objectweb.fractal.fraclet.annotation.annotations.Monolog;

import org.objectweb.fractal.fraclet.annotation.annotations.Provides;

import org.objectweb.fractal.fraclet.annotation.annotations.type.LifeCycleType;

import org.objectweb.util.monolog.api.Logger;

import org.ow2.petals.jbi.component.context.ComponentContext;

import org.ow2.petals.jbi.messaging.endpoint.ServiceEndpoint;

import org.ow2.petals.jbi.messaging.exchange.MessageExchange;

import org.ow2.petals.jbi.messaging.routing.RoutingException;

import org.ow2.petals.jbi.messaging.routing.module.ReceiverModule;

import org.ow2.petals.jbi.messaging.routing.module.SenderModule;

import org.ow2.petals.transport.util.TransportSendContext;

import org.ow2.petals.util.LoggingUtil;

@FractalComponent

@Provides(interfaces = {

@Interface(name = "logSender", signature = SenderModule.class),

@Interface(name = "logReceiver", signature = ReceiverModule.class) })

public class LogModule implements SenderModule, ReceiverModule {

@Monolog(name = "logger")

private Logger logger;

private LoggingUtil log;

/**

* {@inheritDoc}

*/

public void electEndpoints(

Map<ServiceEndpoint, TransportSendContext> electedEndpoints,

ComponentContext sourceComponentContext, MessageExchange exchange)

throws RoutingException {

this.log.info(LogModule.class.getCanonicalName()

+ " router module is sending a message exchange with ID = "

+ exchange.getExchangeId() + " at " + new Date());

for (ServiceEndpoint endpoint : electedEndpoints.keySet()) {

this.log.info("Selected endpoint : " + endpoint.getEndpointName());

}

// Do what you want...

}

/**

* {@inheritDoc}

*/

public boolean receiveExchange(MessageExchange exchange,

ComponentContext sourceComponentContext) throws RoutingException {

this.log.info(LogModule.class.getCanonicalName()

+ " router module is receiving a message exchange with ID = "

+ exchange.getExchangeId() + " at " + new Date());

// Do what you want...

return false;

}

@LifeCycle(on = LifeCycleType.START)

protected void start() {

this.log = new LoggingUtil(this.logger);

this.log.debug("Starting...");

}

@LifeCycle(on = LifeCycleType.STOP)

protected void stop() {

this.log.debug("Stopping...");

}

}

Note that the Fractal annotations are mandatory!

2. Add the modules to the Fractal descriptor files. The modules MUST be added to the JBI-Messaging.fractal configuration file (located in the src/main/resources of your favorite Petals ESB distribution) :

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE definition PUBLIC "-//ow2.objectweb//DTD Fractal ADL 2.0//EN" "classpath://org/objectweb/fractal/adl/xml/standard.dtd">

<definition extends="JBI-MessagingType" name="JBI-Messaging">

<component definition="org.ow2.petals.jbi.messaging.registry.DistributedEndpointRegistryImpl" name="EndpointRegistryImpl"/>

<component definition="org.ow2.petals.jbi.messaging.routing.RouterServiceImpl" name="RouterServiceImpl"/>

<component definition="org.ow2.petals.jbi.messaging.routing.module.TransportResolverModule" name="TransportResolverModule"/>

<component definition="org.ow2.petals.jbi.messaging.routing.module.EndpointResolverModule" name="EndpointResolverModule"/>

<component definition="org.ow2.petals.jbi.messaging.control.JMXExchangeCheckerClientImpl" name="ExchangeCheckerClientImpl"/>

<!-- My logging module -->
<component definition="com.googlecode.chamerling.blog.petals.router.LogModule" name="LogModuleImpl"/>

<!-- Expose -->

<binding client="this.router" server="MonitoringModuleImpl.service"/>

<binding client="this.transportlistener" server="RouterServiceImpl.transportlistener"/>

<binding client="this.endpoint" server="EndpointRegistryImpl.service"/>

<binding client="this.exchangechecker" server="ExchangeCheckerClientImpl.service"/>

<binding client="this.storage" server="MonitoringStorageServiceImpl.service"/>

<binding client="MonitoringModuleImpl.router" server="RouterServiceImpl.service"/>

<binding client="MonitoringModuleImpl.storageService" server="MonitoringStorageServiceImpl.service"/>

<binding client="EndpointRegistryImpl.configuration" server="this.configuration"/>

<binding client="EndpointRegistryImpl.topology" server="this.topology"/>

<!-- Add logging module to router -->

<binding client="RouterServiceImpl.sendermodule-3" server="LogModuleImpl.logSender"/>

<binding client="RouterServiceImpl.receivermodule-1" server="LogModuleImpl.logReceiver"/>

<!-- router -->

<binding client="RouterServiceImpl.transporter-local" server="this.transporter-local"/>

<binding client="RouterServiceImpl.transporter-tcp" server="this.transporter-tcp"/>

<!--the order of collection of bindings is alphabetically inversed -->

<binding client="RouterServiceImpl.sendermodule-2" server="EndpointResolverModule.service"/>

<binding client="RouterServiceImpl.sendermodule-1" server="TransportResolverModule.service"/>

<binding client="EndpointResolverModule.configuration" server="this.configuration"/>

<binding client="EndpointResolverModule.topology" server="this.topology"/>

<binding client="EndpointResolverModule.endpoint" server="EndpointRegistryImpl.service"/>

<binding client="EndpointResolverModule.checker" server="ExchangeCheckerClientImpl.service"/>

<binding client="TransportResolverModule.configuration" server="this.configuration"/>

<binding client="ExchangeCheckerClientImpl.jmx" server="this.jmx"/>
</definition>

Important things here are :

1. Instantiate the component with line

<component definition="com.googlecode.chamerling.blog.petals.router.LogModule" name="LogModuleImpl"/>

2. Adding the module to sender and receiver modules list :


<binding client="RouterServiceImpl.sendermodule-3" server="LogModuleImpl.logSender"/>

<binding client="RouterServiceImpl.receivermodule-1" server="LogModuleImpl.logReceiver"/>

Note that the lists are alphabetically inversed (The logger module « sendermodule-3 » will be called before the sendermodule-2 and the sendermodule-1 modules).

Here we are, the module will be called at each message emission/reception. Note that this is a basic usage of routing modules, you can do many things with these modules like real time monitoring, security check, authentication, endpoint filtering, content based routing, etc etc etc

Une réflexion sur “Adding Routing modules in Petals ESB

  1. Pingback: L’acheminement de messages dans Petals ESB : #2 Le routage « Christophe Hamerling TechBlog

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