Статьи

Взгляд внутрь FUSE ESB 4: платформа интеграции на основе OSGi

В последнее время , версия 4 FUSE ESB была выпущенаЭто версия корпоративной поддержки Apache ServiceMix 4, переименованная Progress Software (ранее IONA), но с полностью открытым исходным кодом и лицензией Apache. Эта новая основная версия FUSE ESB основана на OSGi и представляет ряд новых моделей развертывания, в дополнение к JBI 1.0, что значительно упрощает вашу жизнь в качестве разработчика интеграции.

В этой статье я познакомлю вас с новой версией FUSE ESB, объяснив новые функциональные возможности проектов ServiceMix Kernel и NMR с помощью нескольких практических примеров. Чтобы попробовать примеры, описанные в этой статье, вы можете скачать копию FUSE ESB с http://fusesource.com

Разве FUSE ESB не поддерживает JBI?

Да, в версии 3 FUSE ESB (на основе Apache ServiceMix 3.x) архитектура основана на JBI 1.0. Это означает, что функциональные возможности интеграции, предоставляемые FUSE ESB, могут быть реализованы с помощью сервисных механизмов (SE) и компонентов привязки (BC), которые подключаются через нормализованный маршрутизатор сообщений. А с помощью сервисных сборок (SA) и сервисных блоков (SU) вы можете развертывать функции интеграции с помощью задач Ant или подключаемых модулей Maven в контейнере ServiceMix. Более подробную информацию о версии Apache ServiceMix 3 вы можете прочитать в другой статье, написанной мной для DZone, Разработка на основе шаблонов с ServiceMix .

Но все ли изменилось в версии 4 FUSE ESB? Ну да и нет. Версия 4 основана на пакетах OSGi, а модель загрузки классов в JBI 1.0 была заменена OSGi. Теперь вы можете развернуть свои артефакты интеграции в виде пакетов OSGi в контейнере ServiceMix; однако JBI 1.0 по-прежнему поддерживается версией 4, и такие компоненты JBI, как JMS BC, File BC, Validation SE и Bean SE, все еще там. Таким образом, вы все еще можете развернуть свои старые добрые сборки служб в контейнере ServiceMix 4 без необходимости менять реализацию с ServiceMix 3.

Архитектура FUSE ESB 4

Но давайте не будем слишком сильно сравнивать версии 3 и 4 и взглянем на новую архитектуру FUSE ESB 4. Fuse ESB 4 состоит из двух основных проектов: ядра и ЯМР, как показано на рисунке 1.

Рисунок 1 Архитектура FUSE ESB 4, основанная на OSGi.

Компонент ядра является основой FUSE ESB 4. Ядро предоставляет платформу на основе OSGi, использующую Apache Felix (хотя могут использоваться и другие контейнеры OSGi) с несколькими компонентами сверху. Сначала есть консоль , которая является центральным инструментом для взаимодействия с ядром. Когда вы запускаете FUSE ESB, консоль запускается автоматически, поэтому вы можете управлять средой ESB. Запустить FUSE ESB очень просто, просто откройте командную строку и перейдите в установочный каталог FUSE ESB, например, c: \ fuse-esb-4.0.0.4 Затем введите следующую команду, чтобы запустить ESB.

Windows: bin \ servicemix.bat

Linux / Unix: bin / servicemix.sh

Когда запускается FUSE ESB, отображается консоль, подобная изображенной на рисунке 2.

Рисунок 2 Снимок экрана консоли Fuse ESB, которая запускается с Fuse ESB.

Консоль очень интуитивно понятна и проста в использовании. Есть удобная опция «справки», которую вы можете использовать, чтобы ознакомиться с командами. Команда, которую вы будете использовать довольно часто при использовании FUSE ESB, это команда ‘osgi list’. Это показывает обзор всех установленных пакетов OSGi на контейнере. Для управления пакетами можно использовать несколько команд, таких как «установка osgi», «удаление osgi», «запуск osgi» и «остановка osgi». Обзор всех команд, связанных с OSGi, можно получить с помощью команды «osgi help».

Вместо того чтобы обсуждать все компоненты, показанные на рисунке 1, один за другим, давайте сначала рассмотрим небольшой пример, чтобы ознакомиться с основными компонентами FUSE ESB.

Короткая поездка на верблюде

One of the main changes between version 3 and 4 of FUSE ESB is the integration with Apache Camel (http://activemq.apache.org/camel) to implement routing functionality. In version 3 there was already support for Camel with the Camel service engine, but in version 4 Camel is integrated in the core of the ServiceMix container. So let’s explore the use of Camel routing inside the FUSE ESB a bit.

With Camel, we have two options to implement the integration logic, a Java class using the Java domain specific language (DSL) or a Spring XML configuration file using the Camel XSD. For this first example we’ll use the Spring XML configuration option, because we can deploy this directly to the FUSE ESB without any packaging. Let’s look at a very simple example, where a file is moved from one directory, camel-test-in, to another directory, camel-test-out, in listing 1.

Listing 1 Spring configuration file, camel-file-test.xml, using Camel to move a file to another directory.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel-osgi="http://activemq.apache.org/camel/schema/osgi"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://activemq.apache.org/camel/schema/spring
http://activemq.apache.org/camel/schema/spring/camel-spring.xsd
http://activemq.apache.org/camel/schema/osgi
http://activemq.apache.org/camel/schema/osgi/camel-osgi.xsd">
<camel-osgi:camelContext xmlns="http://activemq.apache.org/camel/schema/spring">
<route>
<from uri="file:camel-test-in"/>
<to uri="file:camel-test-out"/>
</route>
</camel-osgi:camelContext>
</beans>

As you can see in listing 1, we can define a Camel route configuration directly in a Spring XML configuration file. In this Camel configuration the Camel OSGi module is used. In the route element definition a source directory is configured with the from element and a target directory with the to element.

Before we can deploy this Camel example, we first have to install the Camel component on the FUSE ESB container. This is a good time to talk about the provisioning component implemented in the FUSE ESB kernel, also shown in figure 1. To provide a flexible way of installing new OSGi bundles to the FUSE ESB container, the kernel provides several sources, including Maven artifacts, URLs and local file paths. To interact with the provisioning component the features command can be used in the console of the FUSE ESB container. To get an overview of features that can be installed on the FUSE ESB container you can use the ‘features list’ command. A feature consists of one or more OSGi bundles and provides specific functionality that can be used to develop integration functionality. By default, the result of the ‘features list’ command is an substantial number of components, including Camel, ActiveMQ, the JBI components that we could already use in FUSE ESB 3, and the NMR project.

To get our simple Camel example running, we need to install the Camel functionality. The installation of a specific feature is very simple to do with the console. Just run the command ‘feature install camel’, where camel can of course be replaced by other features you may wish to install. The feature name should be exactly the same as the name you see as a result of the ‘feature list’ command. When the Camel feature is installed, the Camel file example can easily be deployed on the FUSE ESB by copying the Camel configuration file, camel-file-test.xml, to the deploy directory in the FUSE ESB installation directory.

If the FUSE ESB has been started you can now see that the Camel file example has been installed by executing the ‘osgi list’ command. The last OSGi bundle that is showed in the list is now the camel-file-test.xml bundle with a status of active. This means that the FUSE ESB has already started the Camel file example OSGi bundle and is polling the camel-test-in directory for files. If you copy a file to the camel-test-in directory it is consumed by the FUSE ESB container and a new file with the same content is created in the camel-test-out directory. So, we can use the components provided by Camel out-of-the-box in the FUSE ESB container, and we don’t have to create a JAR file or another deployment package, we can use a Spring XML configuration and your mediation flow is deployed and running.

Well, this is almost true. By default the following Camel components are installed with the Camel feature:

Camel component

Short description

Bean component

Bind Spring beans to a message exchange.

DataSet

Use a data set to send large number of messages to stress test a message flow.

Direct

Synchronous call to another endpoint.

File

Consume and produce files from a specified directory.

List

A List can be used to test and debug message exchanges.

Log

Log the message exchange with Jakarta Commons Logging.

Mock

Use the mock component to test a message flow.

SEDA

Asynchronous call to another endpoint in the same Camel Context.

Timer

Send a message on a specific time interval.

Validator

Validates the message payload with XML Schema and JAXP validation.

VM

Asynchronous call to another endpoint in the same JVM.

XSLT

Transforms the message using a XSLT stylesheet.

In the simple file example we used the Camel file component. As you can see on the Camel website, there are a lot of other Camel components available (http://activemq.apache.org/camel/components.html). So if we would like to use the Camel JMS component in the FUSE ESB we should do an additional installation. But the Camel JMS component is not available by default in the features list. To make other Camel components available in the features list we should add a features URL where the provisioning component can retrieve the additional components. Execute the following command to do this using a URL that matches the version of FUSE ESB that you are using:

features addUrl http://repo.fusesource.com/maven2/org/apache/servicemix/camel/org.apache.servicemix.camel.features/4.0.0.4-fuse/org.apache.servicemix.camel.features-4.0.0.4-fuse-features.xml

When we execute the ‘features list’ command now, a large number of additional Camel components is available to install, including the Camel JMS component. So to enable the Camel JMS component functionality just execute the ‘features install camel-jms’ command. So now let’s look at a bit more complex example using the Camel Java DSL implemented with an OSGi bundle.

Deploying an OSGi bundle

In the first example we showed how to use the Camel Spring XML configuration. But when we want to implement a Camel Java DSL route or use Java beans in the integration logic, we need another deployment mechanism. In FUSE ESB 4 the most obvious choice would be an OSGi bundle utilizing the Spring dynamic modules (Spring DM) framework. Figure 3 shows an example we’ll implement with an OSGi bundle.

Figure 3 Camel example that consumes a JMS message and validates it against an XML Schema definition. There is a standard target queue and an error queue in case of validation errors.

We’ll implement a ValidationRouter class with the Camel Java DSL that consumes a hello message from the camel.jms.in JMS queue. The message exchange will be logged and then it will be validated against the hello.xsd XML Schema definition file. When there are no validation errors, the hello message will be sent to the camel.jms.out queue and in the case of validation errors, the message will be forwarded to the camel.jms.error queue.

Note that ActiveMQ is included in FUSE ESB 4 by default and the ActiveMQ broker is started automatically when you start the FUSE ESB container. The ActiveMQ configuration that’s used by FUSE can be found in the deploy directory in the activemq-broker.xml file. So in this example we’ll make use of this default ActiveMQ broker. In listing 2, the implementation of the ValidationRouter is shown.

Listing 2 Implementation of the ValidationRouter class.

package com.fusesource.camel;


import org.apache.camel.ValidationException;
import org.apache.camel.builder.RouteBuilder;
public class ValidationRouter extends RouteBuilder {
public void configure() throws Exception {
from("jms:camel.jms.in")
.to("log:showAll?level=info")
.tryBlock()
.to("validator:hello.xsd")
.to("jms:camel.jms.out")
.handle(ValidationException.class)
.to("jms:camel.jms.error");
}
}

Listing 2 shows the really powerful configuration language of the Camel Java DSL. With only a few lines of code you can define quite a bit of logic. With the from method the source JMS queue is configured, where a listener will consume newly arrived messages. Then, with the Camel log component, the message exchange is logged to the container log file. In this case the showAll configuration is used, which means the whole message exchange is logged. There are other logging configurations available which log for example the message headers or the message payload. You can also configure a log level, such as the info level which is used in this example.

Then a tryBlock method is used to be able to catch possible validation errors that may occur in the validator component. With the handle method exceptions can be caught and handled with a piece of integration logic. When a ValidationException occurs the message is forwarded to the camel.jms.error queue. To make the ValidationRouter class available within the Camel context and to start the JMS polling, we need to define a Camel XML configuration file similar to the first example shown in listing 1. But, in this second example we implemented the routing logic in a Java class, so let’s look at how to configure a Java DSL example in listing 3.

Listing 3 Camel XML configuration file, beans.xml.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel-osgi="http://activemq.apache.org/camel/schema/osgi"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://activemq.apache.org/camel/schema/spring
http://activemq.apache.org/camel/schema/spring/camel-spring.xsd
http://activemq.apache.org/camel/schema/osgi
http://activemq.apache.org/camel/schema/osgi/camel-osgi.xsd">
<camel-osgi:camelContext xmlns="http://activemq.apache.org/camel/schema/spring">
<package>com.fusesource.camel</package>
</camel-osgi:camelContext>
<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory">
<osgi:reference id="connectionFactory" interface="javax.jms.ConnectionFactory" />
</property>
</bean>
</beans>

Instead of the route element definition we saw in the camelContext definition in the first example, we now define a package element, which contains the ValidationRouter class. When we deploy this second example to the FUSE ESB container, the com.fusesource.camel package will be scanned for Camel classes like the RouteBuilder class we defined with the ValidationRouter. Because we use the Camel JMS component, we have to define a Spring bean with a connection factory. We can define an ActiveMQConnectionFactory with a brokerURL property with a value of tcp://localhost:61616. But the connection factory is already defined in the activemq-broker.xml file that can be found in the deploy directory.

<osgi:service ref="pooledConnectionFactory">
<osgi:interfaces>
<value>javax.jms.ConnectionFactory</value>
</osgi:interfaces>
<osgi:service-properties>
<entry key="name" value="default"/>
</osgi:service-properties>
</osgi:service>

 So we can also define an OSGi reference to this connection factory with the osgi:reference element. To be complete, listing 4 shows the XML Schema definition that will be used to validate the incoming message.

 Listing 4 The XML Schema definition file, hello.xsd.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://fusesource.com/examples"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
targetNamespace="http://fusesource.com/examples">
<xsd:element name="hello-request">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="name" type="xsd:string" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

This concludes the implementation of the Camel JMS example. The source code can of course be downloaded at the link shown at the end of this article, but let’s have a quick look at the project structure in figure 4.

Figure 4 Project structure of the Camel JMS example.

The camel-jms-example project is Maven based and therefore a pom.xml file is defined at the root of the project directory. The ValidationRouter is defined where you would expect a Java file in a Maven project, the src/main/java directory. The Camel XML configuration file beans.xml is defined in the src/main/resources directory under META-INF/spring. The XML Schema definition hello.xsd is defined at the root of the src/main/resources directory.

Now let’s get this example running on the FUSE ESB container. First we’ve to build the camel-jms-example project with the mvn clean install Maven command. A camel-jms-example-1.0.jar OSGi bundle file will be created in the target directory of the project. This jar file can be deployed to the FUSE ESB container by copying it to the deploy directory, just like we did in the first example. Remember that we’ve already installed the camel-jms feature, because we’ll need this feature to be installed before this example is deployed. When you now run the ‘osgi list’ command in the FUSE ESB console, you can see that the example OSGi bundle is deployed and active under the name ‘Fuse example : : Camel JMS’. In the source code of the camel-jms-example project you can find the hello-test.xml and hello-test2.xml test files. With the HermesJMS tool (http://www.hermesjms.com) you can use these files to add a message to the camel.jms.in queue to trigger the example. When you have produced a message to the queue you can see the log file of the FUSE ESB container by executing the ‘log d’ or ‘log display’ command in the console. You can see that the incoming message content is logged here.

In the first two examples we focused on the Camel functionality available in FUSE ESB. But FUSE ESB also provides an easy to use definition for web services with Apache CXF. But to communicate between Camel routes and these web services we need an interaction layer. So we need a bus inside the ESB, which is named the NMR in FUSE ESB 4.

Introducing the NMR

The NMR project enables the interaction between different components in the OSGi container. This is quite similar to the normalized message router which is defined in the JBI specification, but it’s more flexible and not only dedicated to JBI. The main purpose of the NMR is to mediate between service consumers and service providers. In the example shown in figure 5, you can see that the NMR can be used to communicate between a Camel route definition and a JAX-WS endpoint. This example is provided with FUSE ESB 4 with the name cxf-camel-nmr.

Figure 5 An overview of the cxf-camel-nmr example provided with FUSE ESB 4. This example shows the use of a NMR to mediate between a Camel route and a JAX-WS endpoint.

For a change we don’t trigger the integration logic with a file or a JMS message in the cxf-camel-nmr example, but with a timer. The timer is defined as part of the Camel route definition. Then a Spring bean, MyTransform, is invoked with its transform method, which basically returns the message that can be sent as a request to the web service. Then the web service is invoked via the NMR and the result is passed on, again to the MyTransform Spring bean, which logs the web service response with the display method. Now let’s take a look at the XML configuration in listing 5.

Listing 5 The XML configuration for the Camel route and JAX-WS endpoint definition.

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:camel-osgi="http://activemq.apache.org/camel/schema/osgi"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://activemq.apache.org/camel/schema/spring
http://activemq.apache.org/camel/schema/spring/camel-spring.xsd
http://activemq.apache.org/camel/schema/osgi
http://activemq.apache.org/camel/schema/osgi/camel-osgi.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/transport/nmr/cxf-transport-nmr.xml" />
<import resource="classpath:org/apache/servicemix/camel/nmr/camel-nmr.xml" />
<camel-osgi:camelContext xmlns="http://activemq.apache.org/camel/schema/spring">
<!-- Route periodically sent events into the NMR -->
<route>
<from
uri="timer://myTimer?fixedRate=true&period=5000&exchangePattern=InOut" />
<bean ref="myTransform" method="transform"/>
<to uri="nmr:{http://cxfcamel.examples.servicemix.apache.org/}HelloWorldImplPort"/>
<bean ref="myTransform" method="display" />
</route>
</camel-osgi:camelContext>
<bean id="myTransform" class="org.apache.servicemix.examples.cxfcamel.MyTransform">
<property name="value">
<value><![CDATA[
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns1:sayHi xmlns:ns1="http://cxf.examples.servicemix.apache.org/">
<arg0>Guillaume</arg0>
</ns1:sayHi>
</soap:Body>
</soap:Envelope>]
]></value></property>
</bean>
<jaxws:endpoint id="helloWorld"
implementor="org.apache.servicemix.examples.cxfcamel.HelloWorldImpl"
address="nmr:HelloWorld" />
</beans>

We’ll start with the timer definition in the Camel route. The timer triggers the Camel route at a fixed rate of 5 seconds and produces an InOut exchange pattern. We need this InOut exchange pattern to communicate with the web service, because we need to send a request (In) and receive a response (Out). In the next step the transform method of the MyTransform Spring bean is invoked. In listing 6 we’ll look at the implementation of the MyTransform class in detail, but this method returns the SOAP envelope as configured with the value property of the myTransform Spring bean definition. So this produces a message with an element of sayHi and a value of Guillaume.

Then the hello world web service is invoked which is configured with the jaxws:endpoint. We’ll look at the implementation of the HelloWorldImpl in listing 7, but this method returns the obvious “hello” message. Then the MyTransform bean is called again, but now with the display method, which logs the web service response. Notice that we need to import several XML files at the top of the XML configuration file, to initialize Apache CXF and the NMR.The implementation of the MyTransform class is shown in listing 6, but this will not be too complex.

Listing 6 The MyTransform implementation which produces the web service request and logs the response.

package org.apache.servicemix.examples.cxfcamel;
import java.util.logging.Logger;
import javax.xml.transform.Source;
import org.apache.camel.converter.jaxp.StringSource;
import org.apache.camel.converter.jaxp.XmlConverter;
public class MyTransform {
private static final transient Logger LOG = Logger.getLogger(MyTransform.class);
private String value;
public Object transform(Object body) {
LOG.info(">>>> " + value);
return new StringSource(value);
}
public void display(Source body) throws Exception {
String str = new XmlConverter().toString(body);
LOG.info("<<<< " + str);
}
// omitted the getter and setter for the value property
}

The HelloWorldImpl class is very simple and is annotated with the @WebService annotation which sets the web service interface class, which just defines the sayHi method in this example.

To run this example you can use the provisioning component in FUSE ESB. Just execute the features install examples-cxf-camel-nmr command and the example will automatically be made active, so the timer will produce a new InOut exchange every 5 seconds.

In the first three examples we mainly focused on the Camel, CXF and NMR functionality available in FUSE ESB. But we can also use the JBI components that were already available in the version 3. Let’s implement an example where we create an OSGi bundle that’s using JBI components and the Camel functionality we already used.

Using JBI components in an OSGi bundle

In the second example we used the JMS functionality provided by Camel. But as you may know, ServiceMix also offers JMS functionality via the JMS binding component. You are free to choose your favorite JMS implementation when using FUSE ESB 4, but the JBI components often provide additional functionality on top of the functionality provided by the corresponding Camel components. In FUSE ESB 3 we had to construct a service assembly and implement service units to use the JBI binding components and service engines. In FUSE ESB 4, we can also use an OSGi bundle with a single XML configuration file, just like we did in the earlier examples, to make use of the JBI components provided by ServiceMix. This eases our effort to develop an integration solution using these JBI components. Be aware that not every JBI component available in FUSE ESB 3 has been made OSGi-ready yet, for example the Apache Ode BPEL service engine can only be used with a service assembly deployment model and the same goes for the JSR181 service engine.

In the next example we’ll configure the File binding component using Camel routing functionality to show the new OSGi bundle deployment model capability for the use of JBI components. A schematic overview of the example is shown in figure 6.

Figure 6 A simple example using the File binding component to show the OSGi bundle deployment model for JBI component configurations.

The main difference with the other examples is that we mainly used Camel functionality there. In this example there is a file poller component which consumes files from the insuranceIn directory and forwards the file contents as a JBI message to the Camel route definition. Then the Camel route definition sends the message on to the file sender, which writes a new file to the insuranceOut directory. To keep things simple we only used the file binding component, but you can imagine that you use all the JBI components which are available in FUSE ESB 4.

Let’s look at the implementation of this simple example. First, the XML configuration of the file poller and sender and the Camel route definition is shown in listing 8.

Listing 8 The XML configuration that defines a file poller, file sender and a Camel route.

<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:file="http://servicemix.apache.org/file/1.0"
xmlns:camel="http://activemq.apache.org/camel/schema/spring"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:esb="http://fusesource.com/examples/jbicamel"
xmlns:camel-osgi="http://activemq.apache.org/camel/schema/osgi"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://www.springframework.org/schema/osgi-compendium
http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd
http://servicemix.apache.org/file/1.0
http://servicemix.apache.org/file/1.0/servicemix-file.xsd
http://activemq.apache.org/camel/schema/spring
http://activemq.apache.org/camel/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://activemq.apache.org/camel/schema/osgi
http://activemq.apache.org/camel/schema/osgi/camel-osgi.xsd">
<camel-osgi:camelContext xmlns="http://activemq.apache.org/camel/schema/spring">
<package>com.fusesource.camel</package>
</camel-osgi:camelContext>
<file:poller service="esb:insuranceFileService"
endpoint="pollerEndpoint"
targetService="esb:insuranceCamelRouter"
file="insuranceIn"
delay="5000"
period="2000"/>
<file:sender service="esb:insuranceFileService"
endpoint="senderEndpoint"
directory="insuranceOut"/>
<osgi:reference id="jbi" interface="org.apache.camel.Component"/>
<bean class="org.apache.servicemix.common.osgi.EndpointExporter" />
</beans>

The Camel route definition is already shown in a previous example. What’s new here is the file poller and file sender definition. For JBI components you always have to configure a service and endpoint name because this uniquely identifies the JBI component in the container. For the file poller a targetService attribute is configured which defines the target component where the consumed file content is sent to. So this makes sure that the file content is sent to the Camel router.

In addition to the file poller and sender, we need to define an EndpointExporter bean that registers the poller and sender service and endpoint name in the OSGi registry. We also need to define an OSGi reference with an identifier of jbi, which enables the Camel route definition to talk with the JBI components. In the RouteBuilder class shown in listing 9, this jbi identifier is used.

Listing 9 The InsuranceRouter implementation which talks with the file poller and sender.

package com.fusesource.camel;

import org.apache.camel.builder.RouteBuilder;
public class InsuranceRouter extends RouteBuilder {
public void configure() throws Exception {
from("jbi:service:http://fusesource.com/examples/jbicamel/insuranceCamelRouter")
.to("log:showAll?level=info")
.to("jbi:service:http://fusesource.com/examples/jbicamel/insuranceFileService");
}
}

In the from method we can define a JBI service address, which enables JBI components, such as the file poller in this example, to send messages to this InsuranceRouter. Notice that you need to define the fully qualified service name, including the namespace and the service name. In this example, we log the incoming message and sent it to the insuranceFileService JBI service. This is, of course, the file sender we defined in listing 8.

To get this example running, we first need to install several components on the container using the features install command. Execute the following commands to install the necessary components:

features install jbi

features install servicemix-shared

features install servicemix-file

features install servicemix-camel

Now we can build the OSGi bundle. The jbi-camel-test project structure is similar to figure 4, so we can build the OSGi bundle using Maven with the mvn clean install command. In the target directory of the project the jbi-camel-test-1.0.jar is then created, so this file can be copied to the deploy directory of the FUSE ESB 4. Now you can trigger the example by copying the insurance-request.xml message to the insuranceIn directory created in the root of the FUSE ESB installation. This file is moved to the insuranceOut directory and the message content is logged to the FUSE ESB container. You can look at this log file with the log display command in the console.

Conclusion

In this article we’ve shown the new architecture of FUSE ESB 4 and the new capabilities this brings for developers. The new FUSE ESB console provides a nice management tool to interact with the container. And the provisioning component provides a really flexible way to install and remove components from the container, so you can create the ESB you need in your environment. The integration with Maven is really helpful to developers.

We looked at two main deployment models with the Spring XML configuration file and OSGi bundle in several examples. In the examples we showed that the role of Camel is pretty dominant in FUSE ESB 4 and this makes implementing routing logic very easy. You can choose if you want to define this logic with XML configuration or the Java DSL.

And of course we can still use JBI within FUSE ESB 4, so we can reuse the JBI components that are already available in FUSE ESB 3. You can choose to use OSGi bundles with a single configuration file or a service assembly consisting of several service units.

I hope you enjoyed this introduction into FUSE ESB 4 and working with the given examples. I really think the new OSGi bundle deployment model and the ease to configure Camel routes and CXF services is a step forward. FUSE ESB 4 is ready to be used and should ease your life as an integration developer. Keep integrating!

Additional resources

1. Fuse ESB – http://fusesource.com/products/enterprise-servicemix4/

2. ServiceMix 4 – http://servicemix.apache.org/SMX4/index.html

3. Fuse website – http://www.fusesource.com

3. Enterprise Integration Patterns – http://www.enterpriseintegrationpatterns.com

4. Apache Camel – http://activemq.apache.org/camel

5. Download article source code – http://www.esbinaction.com/files/osgi_article.zip

Tijs Rademakers

Tijs is a software architect working for Atos Origin and specializing in enterprise integration. Tijs is the co-author of the Manning book “Open Source ESBs in Action” (http://www.manning.com/rademakers). He speaks frequently at Java conferences about open source enterprise integration projects like ServiceMix, Mule, Apache Synapse and Apache Tuscany.