RESTful Web Services using Progress FUSE ESB 4.0 Preview and Spring Dynamic Modules
I
recently started doing a substantial amount of research on ServiceMix 4
and OSGi (particularly Spring Dynamic Modules) and it's interesting to
see the capabilities you can gain when you combine the two.
have been playing around with the samples applications and looking at
the code behind both ServiceMix 4 and Spring DM, and I felt like I
should share some of my findings.
In this installment we'll look at a sample application that combines RESTful style of Web Services and Spring Dynamic Modules (Spring DM).
One way of providing RESTful services from within ServiceMix is by using the CXF Components that come with the product. As explained here, CXF provides different ways of exposing RESTful services. For the sample application I'll use the JAX-RS (JSR-311) API to expose the sample Weather application that comes with Spring Dynamic Modules from within FUSE ESB 4.0 Preview (ServiceMix 4).
The Ingredients
- Progress FUSE ESB 4.0 Preview
- Spring Dynamic Modules 1.2.0 M1
- Java 1.5+
- Maven 2.0.9
- CXF-SpringDM-Weather Sample application SVN Repository
- Subversion Client (SVN command line, Tortoisevn)
PROGRESS FUSE ESB 4.0 Preview Configuration
- Download Progress FUSE ESB 4.0 Preview from the link above and install it. The installation of product is really straight forward and choosing the default configuration should be just fine.
- Go to the examples directory of the FUSE ESB product and build the cxf-osgi project. This step prepares your local maven repository with the artifacts required to build the sample application. If you run the following, you should be just fine: mvn install
Spring Dynamic Modules Installation
- Download Spring Dynamic Modules from the link above and install it. For the sample I'll assume the installation directory is C:\dev\spring-osgi-1.2.0-m1
- Go to the samples directory (C:\dev\spring-osgi-1.2.0-m1\src\samples) of the Spring DM distribution and execute: mvn -Dmaven.test.skip=true clean install -P felix This step will help with the deployment of the weather service from within the ServiceMix console.
- Using a Subversion client, checkout the sample application from here: VN Repository had to provide a URL link instead of the URL itself to avoid the word wrapping caused by such long URL. You can open your browser to the URL above, copy and paste the address to your svn client. I'll assume the code will be checked out to the directory C:\dev\cxf-springdm-weather
- Install the required bundles for the sample application. From the directory C:\dev\cxf-springdm-weather\lib execute the following command:
mvn install:install-file -DgroupId=javax.ws.rs -DartifactId=jsr311-osgi-api -Dversion=0.8 -Dpackaging=jar -Dfile=jsr311-osgi-api-0.8.jar
- Change to the C:\dev\cxf-springdm-weather directory and build the application with: vn clean install if everything goes well, maven will create a target directory with a jar file with the name cxf-springdm-weather-4.0.0.0-fuse.jar
Deployment
The CXF implementation of JAX-RS depends on two OSGI bundle jars (jettison-1.0.1.jar and jsr311-osgi-api-0.8.jar). I had to convert these jars to OSGi bundles and I'm providing them within lib directory of the sample application so that you don't have to convert them yourself.
Here is how you would deploy the sample application from within ServiceMix console. These steps use the "osgi" command to install and start the required bundles:
- Launch the ServiceMix Kernel by running in/servicemix n the root dir of FUSE ESB distribution.
- osgi install file:/C:/dev/cxf-springdm-weather/lib/jettison-1.0.1.jar
- osgi install -s file:/C:/dev/cxf-springdm-weather/lib/jsr311-osgi-api-0.8.jar
- Use the command "osgi list" to find the bundle id for the bundle with the name "Apache CXF Bundle Jar (2.1.1.fuse)" and execute the command "osgi refresh ". In my system the bundle id is 56, so the command I used was: osgi refresh 56.
- osgi install -s mvn:org.springframework.osgi.samples/weather-dao/1.2.0-m1
- osgi install -s mvn:org.springframework.osgi.samples/weather-service/1.2.0-m1
- osgi install -s file:/C:/dev/cxf-springdm-weather/target/cxf-springdm-weather-4.0.0.0-fuse.jar
At this point you should see an output similar to this one within the ServiceMix console:
servicemix> Instantiating org.apache.servicemix.examples.restful.springdm.WeatherServiceFrontEnd
class org.apache.servicemix.examples.restful.springdm.WeatherServiceFrontEnd setting weatherService: org.springframework.osgi.samples.weather.service.WeatherServiceImpl@5c0dbc55
Sep 12, 2008 10:41:40 AM org.apache.cxf.endpoint.ServerImpl initDestination
INFO: Setting the server's publish address to be /weather
Testing The Application
Now, just open your browser and go to the following url:
http://localhost:8080/cxf/weather/service/historical-high/11-11-2002
The date must be in the format mm-dd-yyyy.
If you provide an invalid date an exception will be displayed in the
ServiceMix console and today's date will be used for processing. our browser should display this:

Sample Application Code Walk-Through
The following diagram depicts the request/response flow of the Sample application. Notice
how the CXF component is serving as a proxy between the HTTP/WS
component and the WeatherServiceFrontEnd Bean. Similarly, Spring DM
serves as a proxy to the registered OSGi services, in this case,
Weather-Service service and the Weather-dao service.
Spring DM's Weather Application
First let me start explaining little bit about the Spring DM's weather sample application.
The Spring DM weather application
comes with some other OSGi bundles, but we only needed the
weather-service and weather-dao bundles for the sample applciation.f you look at the context file eather/src/main/resources/META-INF/spring/weather-service-context.xml, you'll find the <osgi:service ref="weatherService"> .... </osgi:service> tag. This tag registers
the weatherService bean (defined in the same context file) inside the
OSGi registry. Later, we'll look at how we get a reference to this
service and inject it to our RESTful web service bean.
The
cxf-springdm-weather bundle (the front end of the sample application)
depends on the service exposed by the weather-service bundle and the
weather-service bundle depends on the service exposed by the
weather-dao bundle. This is a typical design of applications that take
advantage of the modularity provided by OSGi. Of course, Spring DM makes it really easy to accomplish such design by applying IoC principals.
The WeatherServiceFrontEnd Bean
On the CXF/JAX-RS side, we start looking at the org.apache.servicemix.examples.restful.springdm.WeatherServiceFrontEnd class. This class is nothing more than a POJO with JAX-RS annotations and with a dependency on an object implementing the org.springframework.osgi.samples.weather.service.WeatherService interface. An instance of this interface will be injected using Spring DM.
In a nutshell, the JAX-RS is a combination of annotations that help mapping the URI and HTTP request parameters to a POJO. The @Path("/service/") maps the URL immediately after the /cxf, which is the root of this application as we specified it in the xbeans.xml context file. We'll be talking about the configuration in the context file in just a minute. The @ProduceMime("application/xml") says that this application will be returning xml data.
If you look at the method getHistoricalHighForDate(...), you'll notice that here we used some other JAX-RS annotations. The @Path("/historical-high/{date}") maps this to a URI underneath /cxf/weather/service. The @PathParam("date") maps the {date} specified by the above @Path to an argument of the getHistoricalHighForDate method. I purposely didn't use any XML API to make the code of the sample application easier to read and follow. As you can see the code is really straight forward and all it does is delegate the call to implementation of the WeatherService and wrap in a XML string the results. More details on JAX-RS and how is used with CXF can be found here.
Note: JAX-RS needs to know what JAX-RS implementation would be used. This is done by creating a file called "javax.ws.rs.ext.RuntimeDelegate" in the META-INF/services directory. The contents of the file specify the name of the class performing this implementation.
The Sample Application Context File
The context file, located in META-INF/spring/xbean.xml, is used to configure the RESTful service, CXF and inject the weather service. At the start of the context file, you'll find the usual namepace definitions, including those for JAX-RS and Spring DM. Then, there are a set of context imports:
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-http.xml" />
<import resource="classpath:META-INF/cxf/osgi/cxf-extension-osgi.xml" />
These imports configure CXF's HTTP transport, hooks JAX-RS with CXF, and configure CXF within ServiceMix and the OSGi container.
Then, there is the definition of the WeatherServiceFrontEnd bean.
<bean id="weatherServiceFrontEnd" class="org.apache.servicemix.examples.restful.springdm.WeatherServiceFrontEnd" >
<property name="weatherService">
<springdm-osgi:reference interface="org.springframework.osgi.samples.weather.service.WeatherService" timeout="5000" />
</property>
</bean>
This is where the magic of Spring DM and Spring IoC is used to inject the weather-service to the weather RESTful service bean.
The <springdm-osgi:reference ...> tag finds a service in the OSGi registry with the interface org.springframework.osgi.samples.weather.service.WeatherService
and injects it to the weatherService property of the org.apache.servicemix.examples.restful.springdm.WeatherServiceFrontEnd bean.
Lastly,
the configuration of the RESTful web service by mapping it to the
"/cxf/weather" URI using the address attribute of the JAX-RS component
tag:
<jaxrs:server id="weatherService" address="/weather" >
<jaxrs:serviceBeans>
<ref bean="weatherServiceFrontEnd" />
</jaxrs:serviceBeans>
</jaxrs:server>
As
you can see in the snippet of code above, the reference of the
WeatherServiceFrontEnd bean is injected into the JAX-RS component.
OSGi Bundles
The
last thing to explain is how to help the OSGi container find the
required classes for the various bundles of an application. This is
usually done by specifying package imports/exports in the
META-INF/MANIFEST.MF file. If you look closely at the provided pom.xml
file, you'll notice that I'm using a ServiceMix 4 specific artifact as
the parent for this project. This is due to the fact that I've used one
of the sample's pom.xml file as starting point for this project. I'm
guessing that down the road FUSE ESB 4.0 will come with maven
archetypes, as its predecessor did, to facilitate the start of new
projects. Back with the maven project, the maven-bundle-plugin plug-in
is used to take care of generating the MANIFEST.MF file for us. This is
done at the moment when the application is being built by the maven
build process. All we have to do is specify the packages to
import/export in the plug-in's configuration section. In there you'll
find the packages of JAX-RS, CXF, the weather-service, among others. or a more in-depth look OSGi bundles, visit Costin Leau's Blog.
Final Words
The
combination of an ESB like ServiceMix on top of an OSGi Container, all
that with the flexibility and easy of use of Spring Dynamic Modules
makes this an interesting product to use for your Enterprise Application Integration needs.
I look forward to the GA release of the FUSE ESB 4.0 product.
Recommended Reading
- Progress FUSE ESB 4 Preview Documentation
- Spring Dynamic Modules Reference
- Rod Biresch's Blog
- Steve Smith's Blog
- James Strachan's Blog
- Guillaume Nodet's Blog
- Costin Leau's Blog
| Attachment | Size |
|---|---|
| xml-output.png | 16.14 KB |
Software Architect at Chariot Solutions working with Java, Spring Framework, Open Source, and SOA/Integration technologies. Roberto is a DZone MVB and is not an employee of DZone and has posted 2 posts at DZone.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)
















Comments
Garry Brother replied on Wed, 2009/04/29 - 6:02pm
rikky james replied on Sat, 2009/09/19 - 7:08am
Gary Cartagena replied on Thu, 2010/02/11 - 8:41pm