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).