Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Deploy WSDL File as OSGI Bundle in Apache Karaf

DZone's Guide to

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.

Free Resource

Share, secure, distribute, control, and monetize your APIs with the platform built with performance, time-to-value, and growth in mind. Free 90-day trial of 3Scale by Red Hat

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 and t1 - 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.

Explore the core elements of owning an API strategy and best practices for effective API programs. Download the API Owner's Manual, brought to you by 3Scale by Red Hat

Topics:
osgi ,wsdl ,deploy ,bundle ,java ,karaf ,apache

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.urlSource.name }}