Monday, August 10, 2009

Spring and Pipes&Filters

Finally an IoC container that almost everyone agrees on: Spring.
After many inhouse, half-baked attempts and 'framework wars' a default solution. TIBCO folks might remember the days of TAF (1996), GAF, XXTAF or PushBeans. Also
openadaptor.org should be noted here.

Now Spring certainly is nice and generic, but for building EAI adapters or 'message processing pipelines' it is not ideal. In case of these pipelines, the message path is very structured: from a source bean through several transformation beans until it finally reaches one (or many) sinks. XML already imposes an 'order of things' so an ideal configuration language of a little adapter might look something like this:
<pipelines> <pipe name="Jdbc2JMSPipe"> <jdbc dbref="db1" querysql="select * from table1"> <concatenate method1="getFirstName" method2="getLastName" result="setName"> <jmsObject2MapMessage> <jmsPublish topic="PERSON"> </pipe> </pipelines> This example configures a processing pipeline to get rows from a JDBC connection, invoke the concatenation filter, convert an object to a JMS MapMessage and finally publish the result to a JMS topic named 'T.PERSON'.

The configuration above is easy to understand and manipulate. One can imagine extensions with for-loops, if-clauses etc.  For example:<pipelines>
<pipe name="Jdbc2JMSPipe"> <jdbc dbref="db1" querysql="select * from table1"> <concatenate method1="getFirstName" method2="getLastName" result="setName"> <jmsObject2MapMessage> <if method="getName" startswith="a-z"> <jmsPublish topic="PERSON.LOWERCASE"> <else> <jmsPublish topic="PERSON.UPPERCASE"> </else> </if> </pipe> </pipelines> Configuring the first example pipeline with Spring could look like this: <beans> <bean id="1" class="com.abc.jdbc" dbRef="db1" querySql="select * from table1"> <property name="next"> <ref bean="2"> </property> </bean> <bean id="2" class="com.abc.concatenate" method1="getFirstName" method2="getLastName" result="setName"> <property name="next"> <ref bean="3"> </property> </bean> <bean id="3" class="com.abc.jmsObject2MapMessage> <property name="next"> <ref bean="4"> </property> </bean> <bean id="4" class="com.abc.jmsPublish" topic="T.PERSON"/> </beans> The order of beans is defined explicitly although XML already provides an order.
A nasty user of this system could even reorder the beans in a different order :-(
So maybe some XSLT to transform from a 'pipes&filters' language to a Spring configuration ?
Or extend Spring with this kind of processing step ?
Or how about a XML-aware bean reference: <beans> <bean id="1" class="com.abc.jdbc" dbRef="db1" querySql="select * from table1"> <property name="next"> <ref bean="following-sibling"> </property> </bean> <bean id="2" class="com.abc.concatenate" method1="getFirstName" method2="getLastName" result="setName"> <property name="next"> <ref bean="following-sibling"> </property> </bean> <bean id="3" class="com.abc.jmsObject2MapMessage> <property name="next"> <ref bean="following-sibling"> </property> </bean> <bean id="4" class="com.abc.jmsPublish" topic="T.PERSON"/> </beans>
Currently, I think XSLT would be the best solution since it keeps the clarity of the pipes&filters language.

2 comments:

  1. Take a look at Mule, its good a creating pipelines between transports and works well with Spring.

    ReplyDelete
  2. Yes, Mule looks good. Also Spring 3.x has support for a more flexible XML dialect.

    ReplyDelete