I have a POC for spring integration to be used along with JBoss and OSGi in Spring Dm server 2.0M6.
Code Sample
http://docs.google.com/fileview?id=0B-0gqvlsl_VvNzhiMzVmMzgtY2Y4Zi00YjJmLWJmNWQtMTIwMDZjNDViMmJl&hl=en
[Download this pdf - Rename file from pdf to rar and extract]
SwitchBoardBundle – Exposes connection factories as service
Exposes common thread pools as service
[Jboss ip values for connection factories are picked from property files]
Ara Bundle - Start a timertask which puts message into a login channel.
This channel is exposed as a service which is imported by PamClient Channel
Ara bundles defines its own thread pool and receives connectionFactory service from switchboard bundle.
PamClient Bundle - Listens to local events from ara bundle and remote events from Pamserver bundle
Imports login channel service from Ara bundle
Uses common thread pool defined in switchboard bundle
[Property file has values which can point each topic or queue to be hosted on a specific Jboss server]
PamServer Bundle – generates events on regular time intervals which will be put into Jms queue using jms adapters.
Also tested a use case where we could change connection factory without getting down the server
Saturday, December 12, 2009
Spring Integration+JMS(JBOSS)+OSGi
Friday, October 23, 2009
Dynamic registring of the Spring Bean to the Application Context
I have come across use cases where we need to dynamicaly create a bean and register it to the Application Context rather than creating it through xmls during initialization.
This api doc helps to do that
http://static.springsource.org/spring/docs/2.5.6/api/org/springframework/context/support/StaticApplicationContext.html#registerSingleton%28java.lang.String,%20java.lang.Class%29
Usecase Ref:
http://forum.springsource.org/showthread.php?t=76490
Useful Blog
http://www.carlobonamico.com/blog/2008/01/22/how-to-dynamicallyprogrammatically-define-spring-beans/
Spring Integration Router Configuration
Just came across a router config in which based on the header it will route the messages to respective channels-provided both header and channel
l have same names .(No static definition required in application xmls)
1. Configuration where mapping of header values to channels is required
<header-value-router input-channel="routingChannel" header-name="testHeader">
<mapping value="someHeaderValue" channel="channelA" />
<mapping value="someOtherHeaderValue" channel="channelB" />
</header-value-router>
2. Configuration where mapping of header values is not required if header values themselves represent the channel names
<header-value-router input-channel="routingChannel" header-name="testHeader"/>
Sunday, August 2, 2009
Example:Spring Integration + Spring DM OSGi + Spring JMS(JBoss MQ)
Source Code Download:http://www.4shared.com/dir/18401908/5d14c8a6/springintosgijms.html
I basically have three bundles
Jms Exchange - where jms input/output channels and apapters are declared
Jms-Sender - bundle publishing message into the queue
Jms-Receiver - bundle receiving message from the queue
Jms Exchange
------------------
Publishing channel will put the message into this channel
<!-- channel for jms In message -->
<integration:channel id="jmsInChannel" />
Wrapping the channel using gateway , so that bundle publishing into teh channel is unaware of spring integration apis.
<!-- gateway which puts message into channel -->
<integration:gateway id="jmsSendProxy"
default-request-channel="jmsInChannel" service-interface="com.jms.exchange.IJmsEvent" />
Publishing the gateway as OSGi service for sender to put messages into the cahnnel.
<osgi:service id="jmsSendService" interface="com.jms.exchange.IJmsEvent" ref="jmsSendProxy"></osgi:service>
Jms outbound adaptor which picks the message from channel and puts it into the defined jms queue.
<!-- adapter which puts message from channel to jms queue -->
<jms:outbound-channel-adapter id="jmsin"
destination="sendDestination" channel="jmsInChannel" />
JNDI template required for jms communication on JBoss MQ
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory
</prop>
<prop key="java.naming.provider.url">jnp://10.1.64.232</prop>
<prop key="java.naming.factory.url.pkgs">org.jnp.interfaces:org.jboss.naming
</prop>
</props>
</property>
</bean>
Connection Factory definition
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>java:ConnectionFactory</value>
</property>
</bean>
Queue details for sending message
<bean id="sendDestination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>queue/RequestQueue</value>
</property>
</bean>
JMS message driven channel adaptor which picks the message as soon as it on the JMS queue and puts it into
the given channel.
<!-- adapter which pulls message from queue into channel -->
<jms:message-driven-channel-adapter
id="jmsout" destination="sendDestination" channel="jmsOutChannel" />
Channel defined for putting the message from queue to channel.
<!-- channel for jms Out message -->
<integration:channel id="jmsOutChannel" />
Publishing the channel as OSGi service for receiver to pick the mssage from channel.
<osgi:service id="jmsListenChannel" ref="jmsOutChannel"
interface="org.springframework.integration.channel.SubscribableChannel" />
Jms Sender
--------------
Osgi referece in to teh gateway for publishing the message into the channel.
<osgi:reference id="jmsSendProxy" interface="com.jms.exchange.IJmsEvent" ></osgi:reference>
JMS Sender using the gateway to put messages into the channel.
<!-- POJO calling gateway -->
<bean id="sender" class="com.jms.sender.Sender">
<property name="jmsSendProxy" ref="jmsSendProxy"></property>
</bean>
public class Sender extends TimerTask{
private IJmsEvent jmsSendProxy;
public void setJmsSendProxy(IJmsEvent jmsSendProxy) {
System.out.println("SETTER CALLED");
this.jmsSendProxy = jmsSendProxy;
}
@Override
public void run() {
System.out.println("TIMER TASK");
jmsSendProxy.send("TEST MESSAGE");
}
}
Spring Time Task which puts the message into the channel periodically.
<bean id="senderTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="period" value="10000" />
<property name="timerTask" ref="sender" />
</bean>
<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="senderTask" />
</list>
</property>
</bean>
Jms receiver
-----------------
OSGi reference into the channel for listening the messages in the channel.
<osgi:reference id="jmsListenChannel"
interface="org.springframework.integration.channel.SubscribableChannel" />
Service Activator which has a calls a dummy method when a jms message is received.
<!-- service activator for listening to jms messages on channel -->
<integration:service-activator
input-channel="jmsListenChannel" ref="jmsreceiver" method="receive" />
<bean id="jmsreceiver" class="com.jms.receiver.Receiver">
public class Receiver {
public void receive(String arg)
{
System.out.println("Jms response recevived"+arg);
}
}
Example: Spring Integration + Spring DM OSGi + Spring Remoting
I basically have 4 bundles
1. Exchange bundle which has definitions of channels
This bundle is spring integration aware, and hence has channel definitions in it.
Channel definition.
<publish-subscribe-channel id="login"/>
This channl is wrapped around a gateway and exposed as a OSGi service.This is to ensure that the event generating bundle is unaware of spring integration apis
Wrapping channel around gateway
<gateway id="loginProxy" default-request-channel="login"
service-interface="com.pg.exchange.event.IEvent" />
Exposing gateway as OSGi service
<osgi:service id="loginChannel" ref="loginProxy"
interface="com.pg.exchange.event.IEvent" />
Also the channel is directly published as a OSGi service for listener listening to it.
<osgi:service id="loginAnnouncementsChannel" ref="login"
interface="org.springframework.integration.channel.SubscribableChannel" />
2. Login bundle - bundle which generate login event and publishes it using gateway.
Accepting the Gateway from the exchange bundle as a OSgi service
<osgi:reference id="eventPublisher"
interface="com.pg.exchange.event.IEvent"/>
This bundle generates periodic events using a spring timer task as shown below
<bean id="logineventGenerator" class="com.pg.ara.LoginEventGenerator">
<property name="eventPublisher" ref="eventPublisher"></property>
</bean>
<bean id="loginTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="period" value="10000" />
<property name="timerTask" ref="logineventGenerator" />
</bean>
<bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="loginTask" />
</list>
</property>
</bean>
Timer Task class generating events
public class LoginEventGenerator extends TimerTask {
IEvent eventPublisher;
public void setEventPublisher(IEvent eventPublisher) {
this.eventPublisher = eventPublisher;
}
@Override
public void run() {
System.out.println("login event published");
eventPublisher.login("Logged In");
}
}
3. Pam-proxy bundle is a bundle which listens to the event using OSGi refered pub-sub-channel
When the message is obtained it makes a spring remoting call uisng remoting adaptors
Consumed OSGi service
<osgi:reference id="loginAnnouncementsChannel"
interface="org.springframework.integration.channel.SubscribableChannel"/>
Activator which makes a remoting call when message is put on a channel
<si:service-activator input-channel="loginAnnouncementsChannel"
ref="exampleService"
method="testRemoting"
output-channel="responseChannel"/>
Channel which gets the spring remoting response
<si:channel id="responseChannel" />
Activator listening on the response
<si:service-activator input-channel="responseChannel"
ref="responseHandler"
method="handleResponse" />
ProxyFactory bean for making spring remoting call
<bean id="exampleService"
class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean" >
< property name="serviceUrl" value="http://localhost:8088/test/pamService" />
< property name="serviceInterface" value="com.pam.external.IExampleService" />
</bean>
Response handler for the spring remoting call
<bean id="responseHandler" class="com.pam.proxy.sample.ResponseHandler" />
All the above bean can be avoided and instead we can use http-invoker inbound and outbound adaptors as explained in spring integration reference guide.
But i did not want the spring remoting hosting side to be unaware of spring integration.
Also i did not want to put any java code in the pam-proxy bundle.
4. Pam web bundle publishing a spring remoting service
<bean id="exampleProxy" class="com.pam.ExampleService" />
<bean name="/pamService"
class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="exampleProxy" />
<property name="serviceInterface" value="com.pam.external.IExampleService" />
</bean>
Source Code Location :http://www.4shared.com/dir/18401573/8c9d7e8d/springintosgiremoting.html
Saturday, August 1, 2009
Spring Integration & OSGi
Spring Integration mainly deals with channels , which is a pipe where messages can be put , and there can be any number of subscibers listening to it.We can keep our business logic independent of the frameworks used.Here channels can be of different types direct channels,pub-sub-channel,polling channels etc .Also there are provisions to make the channel synchronous.
It also provides number of adapters like jms adapters,rmi adaptors,web service adpaters such that we always deal in terms of channels i .e we talk to channels and it publishes to the required framework.Since we keep our code independent of any framework it will be easy flip any of these using configuratiosn without affecting teh business logic.
Certain examples i came across which are very descriptive
1.Spring Integration Documentaion Examples(http://static.springsource.org/spring-integration/reference/htmlsingle/spring-integration-reference.html#samples)
2.Spring Integration Example(dist/org.springframework.integration.samples-1.0.2.SR1.jar)
3.Blog by Oleg(http://blog.springsource.com/2009/02/27/spring-integration-on-dm-server/)
Certain points to note.
1.Channels can be published as OSGi service and other bundles can import it and publish on the channel or listen to it.
Note :
When more than one pub sub channel is defined and needs to be published, filter attributes have to be used to distinguish one from teh other.
Ref : http://forum.springsource.org/showthread.php?t=75316
Two models for hiding spring integration apis from bundles
1. Have a seperate bundle(call it exchange bundle) with spring integration configurations.
2. Wrap the channel using gateway(
3a. Let all teh bundles interested in listening to teh event register with the exchange bundle using a interface.
Implement a service activator in the exchange bundle.The service activator will collect all the OSgi services interested in listening to the service and call teh method one after the other for all registered services.
3b. The service activator will have a register /unregister method ,and teh service activator will be exposed a OSgi service.The interested bundles will import this service and call the register method. On calling thr register method it will add to the list in teh activator, which will call the method when teh event is published on teh channel. (oleg's blog uses teh same model)
http://forum.springsource.org/showthread.php?t=75315
.jpg)