Tuesday, 22 June 2010

ServiceMix (FUSE ESB) and OSGi Camel

Share
Today's post is a continuation of my ServiceMix 4 series. As usual the journey was full of adventures...

Today I will show you how I deployed Camel OSGi unit and how I integrated it with CXF BC and SE units.


Prerequisites

Please make yourself familiar with my two previous posts about SM 4:
If you're new to Apache Camel you may also want to read this post:
Bogus servicemix-osgi-camel-archetype archetype

The example created by servicemix-osgi-camel-archetype is bogus. It defines Camel 2.x dependency, but camel-context.xml contains old ActiveMQ Camel namespaces.

First I had to open META-INF/spring/camel-context.xml and change camel namespaces to the new ones:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://camel.apache.org/schema/osgi"
   xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
      http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring-2.3.0.xsd
      http://camel.apache.org/schema/osgi http://camel.apache.org/schema/osgi/camel-osgi-2.3.0.xsd">
</beans>

Also, I removed osgi-compendium namespace as in the latest version osgi:property-placeholder had been replaced with standard Spring construct (see: https://jira.springsource.org/browse/OSGI-174).

As a last change in camel configuration file I added EndpointExporter definition:

<bean class="org.apache.servicemix.common.osgi.EndpointExporter" />

Then, I opened pom.xml and added the corresponding org.apache.servicemix.common.osgi package to Maven2 Felix plugin's <Import-Packge /> configuration element.

I built it, installed into local Maven2 repository, deployed to FUSE ESB 4.2, and started it. After a while I saw the following output in Karaf's console:

karaf@root> >>>> This is test set body:  Tue Jun 08 07:19:24 CEST 2010
>>>> This is test set body:  Tue Jun 08 07:19:26 CEST 2010
>>>> This is test set body:  Tue Jun 08 07:19:28 CEST 2010
>>>> This is test set body:  Tue Jun 08 07:19:30 CEST 2010
>>>> This is test set body:  Tue Jun 08 07:19:32 CEST 2010
>>>> This is test set body:  Tue Jun 08 07:19:34 CEST 2010
>>>> This is test set body:  Tue Jun 08 07:19:36 CEST 2010
>>>> This is test set body:  Tue Jun 08 07:19:38 CEST 2010
>>>> This is test set body:  Tue Jun 08 07:19:40 CEST 2010

Extended Order Processing Example

My previous example was quite simple:

order-processing-service-bc -> order-processing-service-se

I wanted to put Camel JBI route between BC and SE units:

order-processing-service-bc -> camel-order-processing-service -> order-processing-service-se

Modifying Apache CXF BC component

Quick look at http://camel.apache.org/jbi.html.

I modified BC to send messages to new endpoint (I added targetEndpoint attribute and set it to CamelRoute, thanks to Freeman Fang :) ):

<cxfbc:consumer wsdl="classpath:wsdl/person.wsdl" targetInterface="person:Person" targetService="person:PersonService" targetEndpoint="CamelRoute" useJBIWrapper="false" useSOAPEnvelope="false" />

Built it and deployed to FUSE ESB 4.2.

Modifying Camel route

I opened my camel-context.xml removed old route and wrote a new one (note that <from /> matches CXF BC targetService/targetEndpoint attributes):

<osgi:camelContext xmlns="http://camel.apache.org/schema/spring">
 <route id="order-processing-route">
  <from uri="jbi:endpoint:http://servicemix.apache.org/samples/wsdl-first/PersonService/CamelRoute"/>
  <convertBodyTo type="org.w3c.dom.Document"/>
  <bean ref="myTransform" method="transform" />
  <to uri="log:TransformedInput" />
  <to uri="jbi:endpoint:http://servicemix.apache.org/samples/wsdl-first/PersonService/PersonImplPort"/>
  <to uri="log:Output" />
 </route>
</osgi:camelContext>

Also, I changed the MyTransform.transform() method of my bean to:

public Object transform(Object body) {
    Document doc = (Document) body;
    NodeList list = doc.getDocumentElement().getChildNodes();
    Node node = list.item(1);
    node.setTextContent("148");
    return doc;
}

(I was overriding the person id with a constant value of 148.)

I built it, installed into Maven2 repository, deployed to FUSE ESB 4.2 and started it.

nmr:list

It showed me the following endpoints:

{http://servicemix.apache.org/samples/wsdl-first}PersonService:PersonImplPort (SE)
{http://servicemix.apache.org/samples/wsdl-first}PersonService:soap (BC)
{http://servicemix.apache.org/samples/wsdl-first}PersonService:CamelRoute (Camel)

I launched soapUI and created a new Project for http://localhost:8080/cxf/PersonService?wsdl. Everything worked as expected, I saw Camel's logs in Karaf's console, plus the person id was changed to 148.

Source code download

A complete download containing CXF BC, CXF SE, and Camel units is available here: FUSE-ESB-OSGi-JBI-CXF-BC-SE-Camel.zip.

Summary

Simple, isn't it? In my next post I will write about SM4 and WS-BPEL support. Guess what engine works out of the box with SM4? Yes, Apache ODE :)

Stay tuned,
Łukasz

0 comments: