This section explains how to create a simple FUSE Mediation Router application and how to deploy it
as an OSGi bundle into the FUSE ESB OSGi container. The examples in this section are taken from
the camel-osgi
demonstration, which defines a simple route in a Spring XML
configuration file.
The camel-osgi
demonstration is located in the following directory:
InstallDir
/examples/camel-osgi
The demonstration shows how to define a route in XML, where the route is built up from the following parts:
At the start of the route is a timer
endpoint, which generates a
heartbeat event every two seconds.
Next comes a callout to a transformer bean (implemented in Java), which transforms the hearbeat into a message containing the current date and time.
At the end of the route is a log
endpoint, which sends the transformed
message to Jakarta commons logger.
The route is deployed into the FUSE ESB container as an OSGi bundle.
Relative to the CLASSPATH, the application's Spring XML file must be located in the following directory:
META-INF/spring
When you start an application bundle in the FUSE ESB OSGi container, Spring looks for any
files matching *.xml
located in META-INF/spring
and processes all
of the matched files. In effect, the Spring XML files located in this directory bootstrap
the bundled application.
Example 1.1 shows the routes for the
camel-osgi
demonstration, taken from the Spring XML configuration file,
META-INF/spring/beans.xml
.
Example 1.1. Spring XML File Defining a Route
<?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:osgi="http://activemq.apache.org/camel/schema/osgi"
xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.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://www.springframework.org/schema/osgi-compendium http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd"> <osgi:camelContext xmlns="http://activemq.apache.org/camel/schema/spring">
<route>
<from uri="timer://myTimer?fixedRate=true&period=2000"/> <bean ref="myTransform" method="transform"/> <to uri="log:ExampleRouter"/> </route> </osgi:camelContext> <bean id="myTransform" class="org.apache.servicemix.examples.camel.MyTransform">
<property name="prefix" value="${prefix}"/>
</bean> <osgix:property-placeholder persistent-id="org.apache.servicemix.examples">
<osgix:default-properties> <prop key="prefix">MyTransform</prop> </osgix:default-properties> </osgix:property-placeholder> </beans>
The default namespace, | ||||
The XML schema namespace, | ||||
The Camel/OSGi namespace, | ||||
The OSGi compendium namespace,
For more details, see Spring Compendium Services. | ||||
The contents of the | ||||
Each route is defined using a For more details about how to define XML routes, see Defining Routes in XML. | ||||
The For more details about how to instantiate Java classes using Spring, see The IoC Container chapter in the Spring documentation. | ||||
The prefix value is specified using a property placeholder,
| ||||
The presence of the |
Example 1.2 shows the definition of a transformation
bean class, org.apache.servicemix.examples.camel.MyTransform
, which is
responsible for transforming the body of the In message in a route. The
MyTransform.transform()
method from this class gets called by the preceding
XML route (see Example 1.1).
Example 1.2. Transformation Bean Example
package org.apache.servicemix.examples.camel; import java.util.Date; import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory; public class MyTransform { private static final transient Log LOG = LogFactory.getLog(MyTransform.class); private boolean verbose = true; private String prefix = "MyTransform"; public Object transform(Object body) {
String answer = prefix + " set body: " + new Date(); if (verbose) { System.out.println(">>>> " + answer); } LOG.info(">>>> " + answer); return answer;
} public String getPrefix() { return prefix; } public void setPrefix(String prefix) {
this.prefix = prefix; } ... }
The | |
The
There are other ways of defining bean transformation methods—for more details, see Bean Integration. | |
In this example, the body of the incoming message is ignored and the transformed
message, | |
The |
In order to package the demonstration as an OSGi bundle (which is simply a JAR file), it is necessary to add a number of entries to the JAR's manifest file. Relative to the JAR root, the manifest file is stored in the following location:
META-INF/MANIFEST.MF
Where the pathname of this location is case-insensitive. For example,
meta-inf/Manifiest.mf
would work just as well. Example 1.3 shows the manifest for the
camel-osgi
bundle, which includes some OSGi-specific manifest entries, known as
bundle headers.
Example 1.3. Manifest for the camel-osgi Demonstration
Manifest-Version: 1.0 Built-By: YOURUSERNAME Created-By: Apache Maven Bundle Plugin Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt Import-Package: org.apache.camel.osgi,org.apache.commons.logging Bnd-LastModified: 1222079507224 Bundle-Version: 4.0.0.fuse Bundle-Name: Apache ServiceMix Example :: Camel OSGi Bundle-Description: This pom provides project information that is comm on to all ServiceMix branches. Build-Jdk: 1.5.0_08 Private-Package: org.apache.servicemix.examples.camel Bundle-DocURL: http://www.apache.org/ Bundle-ManifestVersion: 2 Bundle-Vendor: The Apache Software Foundation Bundle-SymbolicName: camel-osgi Tool: Bnd-0.0.255
Some of these manifest entries (for example, Bnd-LastModified
,
Build-Jdk
, Private-Package
, and Tool
) are generated
by the Maven bundle plug-in for information purposes only and they are thus not particularly
important. Some of the OSGi bundle headers are also included for information only. The
important entries are the bundle headers that affect the interaction between the bundle and
the OSGi container and these are, as follows:
A human-readable name for the current bundle. For example, when you enter the
command, osgi list
, from the FUSE ESB console, the installed bundles are
listed with their bundle name.
A unique name for the current bundle. The bundle symbolic name is the primary way of identifying a bundle. For example, you would use the bundle symbolic name to refer to a bundle from within a piece of code or in a configuration file. The usual convention for a bundle symbolic name is to use a reverse URL format (the sample value shown here is unconventional in this respect).
The value of this header is a comma-separated list of Java package names for all
of the packages needed by, but not included in this bundle. For example, the
org.apache.commons.logging
package is listed here because it is used by
the transformation bean code.
![]() | Note |
---|---|
The syntax of the package list can be a bit more complicated than a comma-separated list (for example, you can optionally select particular package versions and so on). For full details of the syntax, consult the OSGi specification. |
(Not used in the example) The value of this header is a
comma-separated list of Java package names for packages contained in the current
bundle that you want to make available to other bundles. The
Export-Package:
and Import-Package:
headers are
complementary: the Java packages exported by one bundle using
Export-Package:
become available to other bundles that import them using
Import-Package:
.
Creating the contents of these headers can be an annoying chore, if you have to do it by
hand. For example, a moderately complex piece of Java code might need to import dozens of
different packages using the Import-Package:
header. For larger applications,
it would be convenient to have some way of automatically generating bundle headers.
If you are using the Apache Maven2 build
system to build your application, you have the option of using the Maven bundle
plug-in to generate all of the bundle headers automatically. As already noted,
this feature can be extremely convenient for large, complex applications. Example 1.4 shows how to modify the top-level Maven build
file, pom.xml
, in order to enable the bundle plug-in.
Example 1.4. Configuration of Maven Bundle Plug-In in pom.xml File
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> ... <groupId>org.apache.servicemix.examples</groupId> <artifactId>camel-osgi</artifactId> <packaging>bundle</packaging><version>4.0.0.2-fuse</version> <name>Apache ServiceMix Example :: Camel OSGi</name> ... <dependencies> <dependency>
<groupId>org.apache.felix</groupId> <artifactId>org.osgi.core</artifactId> <version>1.0.0</version> </dependency> ... </dependencies> ... <build> <plugins> <plugin>
<groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <configuration> <instructions> <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName> <Import-Package>*,org.apache.camel.osgi</Import-Package> <Private-Package>org.apache.servicemix.examples.camel</Private-Package> </instructions> </configuration> </plugin> </plugins> ... </build> ... </project>
Change the packaging from | ||||
Add a dependency on the Apache Felix library, as shown.
| ||||
The |
There is no need to install the Maven bundle plug-in explicitly. Because the plug-in is archived in the default Maven2 repository (that is, http://repo1.maven.org/maven2/), Maven will automatically locate and download the plug-in the first time you build your application (provided that the build machine is connected to the Internet). The preceding configuration defines the following instructions for generating bundle headers:
<Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName> <Import-Package>*,org.apache.camel.osgi</Import-Package> <Private-Package>org.apache.servicemix.examples.camel</Private-Package>
The preceding elements can be explained as follows:
Generates the Bundle-SymbolicName:
manifest entry. In this example,
it is set to the project's artifact ID, which resolves to camel-osgi
. If
you want to be sure to avoid a name clash, you could define the symbolic name as
follows:
<Bundle-SymbolicName>$(pom.groupId).${pom.artifactId}</Bundle-SymbolicName>
Which would resolve to org.apache.servicemix.examples.camel-osgi
in
the current example.
Generates the Import-Package:
manifest entry. The wildcard character
, *
, generates a list containing every referenced Java package not
included in the current Maven project. The org.apache.camel.osgi
package
is listed explicitly, because it is not referenced in the source code, but it is
needed at run time.
Generates the Private-Package:
manifest entry. This entry does
not correspond to a bundle header and is ignored by the OSGi
container. The private package list contains the names of all the Java packages that
are defined in the current bundle, but are not visible to other bundles. It is
provided for information purposes only.
Because the bundle plug-in generates sensible defaults for most of the bundle headers, the preceding plug-in configuration is normally adequate to get you started with most projects. For more details about configuring the Maven bundle plug-in, see Maven bundle plug-in.