Deploy WSDL File as OSGI Bundle in Apache Karaf
Deploy WSDL File as OSGI Bundle in Apache Karaf
It is easy to generate Java classes from WSDL files and also to create a custom deployer for Karaf, so why do not join these two features? Well, that's just what Dominik Przybysz has done with his WSDL deployer.
Join the DZone community and get the full member experience.
Join For FreeWSO2 is the only open source vendor to be named a leader in The Forrester Wave™: API Management Solutions, Q4 2018 Report. Download the report now or try out our product for free.
Introduction
A WSDL file describes web services. Java classes are often generated from WSDL. For this purpose, we could use command line tools (e.g. wsdl2Java or wsimport) or the maven plugin.
On the other hand, we have Apache Karaf which is an OSGI container. Karaf has installed, by default, many deployers for creating OSGi bundles from files, e.g. Blueprint deployer, Spring deployer or War deployer.
It is easy to generate Java classes from WSDL files and also to create a custom deployer for Karaf, so why do not join these two features?
Installation of WSDL Deployer
Source code of my WSDL deployer is provided here. You can download and build it:
mvn clean install
We also need Karaf. I will use the newest version 4.0.5. It can be download from the Karaf website. When you download and unpack it, you can run it:
$ cd PUT_PATH_TO_KARAF_DIR_HERE
$ ./bin/karaf
__ __ ____
/ //_/____ __________ _/ __/
/ ,< / __ `/ ___/ __ `/ /_
/ /| |/ /_/ / / / /_/ / __/
/_/ |_|\__,_/_/ \__,_/_/
Apache Karaf (4.0.5)
Hit '<tab>' for a list of available commands
and '[cmd] --help' for help on a specific command.
Hit '<ctrl-d>' or type 'system:shutdown' or 'logout' to shutdown Karaf.
karaf@root()>
And install commons-io and wsdl-delpoyer bundles:
karaf@root()> install -s mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-io/1.4_3
Bundle ID: 52
karaf@root()> install -s mvn:com.github.alien11689.karaf/wsdl-deployer/1.0.0-SNAPSHOT
Bundle ID: 53
Install WSDL from Karaf Shell
I will test the deployer using a WSDL file named exampleService-2.0.0.wsdl
(provided WSDL is similar to this, but has another namespace in the types schema for testing purposes):
<?xml version="1.0"?>
<wsdl:definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://Example.org"
xmlns:sns="http://Example.org/schema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:wsa10="http://www.w3.org/2005/08/addressing"
xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex"
targetNamespace="http://Example.org"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xsd:schema targetNamespace="http://Example.org/schema" elementFormDefault="qualified" >
<xsd:element name="Add">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="a" type="xsd:int" />
<xsd:element minOccurs="0" name="b" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="AddResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="result" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="Subtract">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="a" type="xsd:int" />
<xsd:element minOccurs="0" name="b" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="SubtractResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="result" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="ICalculator_Add_InputMessage">
<wsdl:part name="parameters" element="sns:Add" />
</wsdl:message>
<wsdl:message name="ICalculator_Add_OutputMessage">
<wsdl:part name="parameters" element="sns:AddResponse" />
</wsdl:message>
<wsdl:message name="ICalculator_Subtract_InputMessage">
<wsdl:part name="parameters" element="sns:Subtract" />
</wsdl:message>
<wsdl:message name="ICalculator_Subtract_OutputMessage">
<wsdl:part name="parameters" element="sns:SubtractResponse" />
</wsdl:message>
<wsdl:portType name="ICalculator">
<wsdl:operation name="Add">
<wsdl:input wsaw:Action="http://Example.org/ICalculator/Add" message="tns:ICalculator_Add_InputMessage" />
<wsdl:output wsaw:Action="http://Example.org/ICalculator/AddResponse" message="tns:ICalculator_Add_OutputMessage" />
</wsdl:operation>
<wsdl:operation name="Subtract">
<wsdl:input wsaw:Action="http://Example.org/ICalculator/Subtract" message="tns:ICalculator_Subtract_InputMessage" />
<wsdl:output wsaw:Action="http://Example.org/ICalculator/SubtractResponse" message="tns:ICalculator_Subtract_OutputMessage" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="DefaultBinding_ICalculator" type="tns:ICalculator">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Add">
<soap:operation soapAction="http://Example.org/ICalculator/Add" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Subtract">
<soap:operation soapAction="http://Example.org/ICalculator/Subtract" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="CalculatorService">
<wsdl:port name="ICalculator" binding="tns:DefaultBinding_ICalculator">
<soap:address location="http://localhost/ICalculator" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
We can install it via command:
karaf@root()> install -s wsdl:file:PUT_PATH_TO_WSDL_HERE/exampleService-2.0.0.wsdl\$package=org.github.alien11689.example&s1=http://Example.org/schema&t1=org.github.alien11689.example.schema
Bundle ID: 54
Files must have the format ${bundleSymbolicName}-${version}.wsdl
.
Provided options are:
package
- allows to change package of generated interface- pair
s1
andt1
- maps schema in WSDL to package (the WSDL deployer is in its beta version nowadays and provides options to map only one schema).
Karaf has installed this file:
karaf@root()> headers 54
Bundle 54
---------
Manifest-Version = 2
Bundle-ManifestVersion = 2
Bundle-SymbolicName = exampleService-2.0.0.wsdl
Bundle-Version = 2.0.0
Export-Package =
org.github.alien11689.example.schema;version=2.0.0,
org.github.alien11689.example;version=2.0.0
Import-Package =
javax.jws,
javax.jws.soap,
javax.xml.bind.annotation,
javax.xml.namespace,
javax.xml.ws
Install WSDL by Putting It into Karaf Drop Folder
You can also install WSDL file by copying it to deploy
directory:
cp PUT_PATH_TO_WSDL_HERE/exampleService-2.0.0.wsdl PUT_PATH_TO_KARAF_DIR_HERE/deploy/deployedExampleService-2.0.0.wsdl
It is much more simple to do, but do not allow for customization (e. g. namespace to package mapping). It creates a bundle:
karaf@root()> list | grep deployedExampleService
55 | Active | 80 | 2.0.0 | deployedExampleService-2.0.0.wsdl
karaf@root()> headers 55
Bundle 55
---------
Manifest-Version = 2
Bundle-ManifestVersion = 2
Bundle-SymbolicName = deployedExampleService-2.0.0.wsdl
Bundle-Version = 2.0.0
Export-Package =
org.example;version=2.0.0,
org.example.schema;version=2.0.0
Import-Package =
javax.jws,
javax.jws.soap,
javax.xml.bind.annotation,
javax.xml.namespace,
javax.xml.ws
How Does It Work?
Deployer uses the wsimport
command to create it in a temporary directory and compile generated Java classes. Compiled classes are packed with MANIFEST.MF
into service.jar
and the JAR is really installed in the OSGi container. For example, my temporary directory is /tmp/4ff81631-3c08-487a-b731-1f95c568026f
:
$ tree /tmp/4ff81631-3c08-487a-b731-1f95c568026f
/tmp/4ff81631-3c08-487a-b731-1f95c568026f
├── Jaxb-binding.xml
├── Jaxws-binding.xml
├── service.wsdl
├── src
│ └── org
│ └── github
│ └── alien11689
│ └── example
│ ├── CalculatorService.java
│ ├── ICalculator.java
│ └── schema
│ ├── Add.java
│ ├── AddResponse.java
│ ├── ObjectFactory.java
│ ├── package-info.java
│ ├── Subtract.java
│ └── SubtractResponse.java
└── target
├── org
│ └── github
│ └── alien11689
│ └── example
│ ├── CalculatorService.class
│ ├── ICalculator.class
│ └── schema
│ ├── Add.class
│ ├── AddResponse.class
│ ├── ObjectFactory.class
│ ├── package-info.class
│ ├── Subtract.class
│ └── SubtractResponse.class
└── service.jar
And my service.jar
contains:
$ jar tf /tmp/4ff81631-3c08-487a-b731-1f95c568026f/target/service.jar
META-INF/
META-INF/MANIFEST.MF
org/
org/github/
org/github/alien11689/
org/github/alien11689/example/
org/github/alien11689/example/schema/
org/github/alien11689/example/schema/Add.class
org/github/alien11689/example/schema/ObjectFactory.class
org/github/alien11689/example/schema/Subtract.class
org/github/alien11689/example/schema/SubtractResponse.class
org/github/alien11689/example/schema/package-info.class
org/github/alien11689/example/schema/AddResponse.class
org/github/alien11689/example/ICalculator.class
org/github/alien11689/example/CalculatorService.class
Conclusion
WSDL generation and Karaf deployers can be easily joined and simplified with the creation of OSGi bundles without an explicit creation of a JAR. Provided the WSDL deployer is just in its beginning stages, but it can be very useful when we have many WSDLs and do not want to create separate artifacts for them.
Source code for the WSDL deployer is provided here.
IAM is now more than a security project. It’s an enabler for an integration agile enterprise. If you’re currently evaluating an identity solution or exploring IAM, join this webinar.
Published at DZone with permission of Dominik Przybysz . See the original article here.
Opinions expressed by DZone contributors are their own.
{{ parent.title || parent.header.title}}
{{ parent.tldr }}
{{ parent.linkDescription }}
{{ parent.urlSource.name }}