Web service in OSGi bundle

In this short tutorial we will create OSGi bundle that will expose web service using CXF library. Like it or not, but the project will be created with usage of Maven utility. Also, this example will be using Spring Dynamic Modules.

Project

Let us start with creating an empty project. We will do it using archetype:generate:

mvn -B archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.0 \
-DgroupId=com.lukaszbaran.simpleosgi.ws \
-DartifactId=osgi-simple-ws -Dversion=1.0

After execution of this command, Maven should generate project structure. Delete the classes AppMain and AppTest. To make the project simpler to edit, generate Eclipse project files:

mvn eclipse:eclipse

Code & configuration

The next step is to create the interface and its implementation (don’t forget about packages as well):

 // ICalculator.java
 package com.lukaszbaran.simpleosgi.ws;
 import javax.jws.WebService;
 @WebService
 public interface ICalculator {
    int add(int a, int b);
    int sub(int a, int b);
 }

Service implementation (CalculatorImpl.java) is created in com.lukaszbaran.simpleosgi.ws.impl package:

// CalculatorImpl.java
package com.lukaszbaran.simpleosgi.ws.impl;
public class CalculatorImpl implements ICalculator {
	@Override
	public int add(int a, int b) {
		return a + b;
	}
	@Override
	public int sub(int a, int b) {
		return a - b;
	}
}

Since the project is going to use Spring Dynamic Modules, it is necessary to create beans.xml file in src / main / resources / META-INF / spring / beans.xml path. The file should look like this:

<?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:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.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/cxf-extension-http.xml"/>
	<import resource="classpath:META-INF/cxf/osgi/cxf-extension-osgi.xml"/>
 <jaxws:endpoint
  id="calculator"
  implementor="com.lukaszbaran.simpleosgi.ws.impl.CalculatorImpl"
  address="/calculator"/>
</beans>

This file defines the address of our end-point and and points the class which implements service interface.

POM

The next step is to create pom.xml file that will be used to build our project (of course, if you were doing this tutorial from the beginning, the only thing you need to do is to copy build section from the following XML into your POM).

<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">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.lukaszbaran.simpleosgi.ws</groupId>
	<artifactId>osgi-simple-ws</artifactId>
	<packaging>bundle</packaging>
	<version>1.0</version>
	<name>osgi-simple-ws</name>
	<url>http://maven.apache.org</url>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.felix</groupId>
				<artifactId>maven-bundle-plugin</artifactId>
				<extensions>true</extensions>
				<version>1.4.0</version>
				<configuration>
					<instructions>
						<manifestLocation>META-INF</manifestLocation>
						<_include>-osgi.bnd</_include>
					</instructions>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

As you can see, in the code above we configured maven-bundle-plugin, so that it would use configuration from osgi.bnd file.  It should be created in the same directory as pom.xml file:

Import-Package: javax.jws, javax.wsdl, META-INF.cxf, META-INF.cxf.osgi, org.apache.cxf.bus, org.apache.cxf.bus.spring, org.apache.cxf.bus.resource, org.apache.cxf.configuration.spring, org.apache.cxf.resource, org.apache.servicemix.cxf.transport.http_osgi, org.springframework.beans.factory.config 

Private-Package: com.lukaszbaran.simpleosgi.ws.*

Require-Bundle: org.apache.cxf.cxf-bundle

Compilation & installation

The project should be compiled by executing:

mvn clean package

If everything has been done correctly, the bundle should be now in the target directory. To make our bundle running in OSGi environment (in our case it would be Fuse ESB) we should take care of installing cxf-osgi feature (feature is simply a pack of bundles). In Fuse ESB we do it using the following command:

features install cxf-osgi

Note: if you do not do this you may get some strange exceptions like this one:

org.osgi.framework.BundleException:
 Unresolved constraint in bundle 154:package;
 (package=META-INF.cxf.osgi)

Now we can install our bundle in the container (e.g. by copying to the container’s deploy directory). Service may be accessed by opening URL: http://localhost:8080/cxf/calculator?wsdl (assuming the default configuration).

3 thoughts on “Web service in OSGi bundle

  1. Would be nice if the example was without the Maven “overhead”. The title should include “with Maven”

  2. Hi ,

    Can you please let me know the way I can add the cxf-osgi feature in case I have to deploy the OSGI Bundle in JBoss 7?

    Thanks

Comments are closed.