WSO2Con 2013 CFP Banner

Exposing CORBA Services as Web Services - Introduction to the Axis2 CORBA Module

Discuss this article on Stack Overflow
By Eranga Jayasundera
  • 11 Nov, 2007
  • Level:  Intermediate
  • Reads: 14427

Eranga Jayasundara in his article introduces the CORBA module of Apache Axis2 along with an integration example. He goes on to say, "CORBA module of Axis2 bridges CORBA and Web Services, allowing Web service clients to invoke CORBA services. This bridging is totally transparent to the Web service clients so that they can invoke a CORBA backed Web service in the same way as invoking a generic Web service." Find out how exactly this is done.

Introduction

Axis2 CORBA moduleApache Axis2, the successor to the renowned Apache Axis, is a well known open source Web service engine developed by the Apache Software Foundation. As the next generation of the Apache Web Service stack, Axis2 offers a modular, flexible, configurable, reliable and light weight architecture for deploying Web services. Further facilitating the Service Oriented Architecture, Apache Axis2 now supports the integration of CORBA and Web services through the new CORBA module of Axis2. This article introduces the CORBA module of Apache Axis2 along with an integration example.

How it Works

The CORBA module of Axis2 bridges CORBA and Web Services, allowing Web service clients to invoke CORBA services. With the CORBA module of Axis2, you can easily map a CORBA service as a Web service. The following figure illustrates the basic functionalities of the Axis2 CORBA module.

 

The Structure of the CORBA module

The Web service client sends SOAP messages to the Axis2 server as usual. When a SOAP message is received by Axis2, the message is passed through a set of interceptors called handlers (Refer Axis2 architecture guide for more information) and finally the message is sent to the corresponding message receiver. In this scenario, the message is received by a "CORBA Message Receiver". Axis2 CORBA module comes with a set of CORBA message receivers which convert those SOAP messages to IIOP, so that, the CORBA message receiver invokes the corresponding methods of the remote CORBA server by sending appropriate IIOP messages. The return values are sent back to the CORBA message receiver. The CORBA message receiver converts the IIOP messages to SOAP messages and sends them to the Web service client.


To facilitate the above scenario, first of all you have to expose a Web service which is mapped to the CORBA service. This can be done by simply deploying two text files, namely the IDL file and a Web service configuration file, to the Axis2 server.  The IDL file describes the CORBA service interface in OMG Interface Description Language (OMG IDL). Axis2 automatically generates the WSDL for the operations described in the IDL file. The configuration file is a simple XML file which contains metadata about the service such as the file name and the path to the IDL file, how to locate the CORBA service, which CORBA implementation to use, name of the CORBA interface, etc.

During the initialization of the Web service, the IDL parser and the CORBA deployer processes the IDL file and the Configuration file respectively. The deployer component uses the pluggable deployer architecture provided by Axis2, so that one can easily activate or deactivate the module by modifying the Axis2 configuration file.

Axis2 is capable of generating WSDL for the "CORBA Web Service" at run time. The clients can then use this WSDL to generate  the client side stubs for invoking the Web service.

The CORBA Invoker component provides a reflection-like API for CORBA message receivers to invoke a remote CORBA service. The CORBA Invoker uses the CORBA Dynamic Invocation Interface (DII) for invoking remote CORBA services. By default, Axis2 uses the DII provided by Apache Yoko. However, you can easily plug another CORBA implementation instead of Apache Yoko by providing "orbClass" and "orbSingletonClass" parameters in the Web service configuration file.

Some of the main features of the Axis2 CORBA module are:

  • Automatic WSDL generation driven by the IDL file.
  • Supports (almost) all the CORBA data types including Structs, Value types (objects-by-value), Enums, Unions, Typedefs, Arrays (including multi-dimensional arrays and Sequences.
  • Supports in, out and inout parameters
  • Converts CORBA exceptions to SOAP faults.
  • Generates matching web service operations for the methods of the CORBA service.
  • Interoperable with any CORBA implementation.
  • Supports Java RMI/IIOP.

Sequence Diagram

Integration Scenario

To show how the Axis2 CORBA module can be used, let's imagine a simple integration scenario.

In this example, we are going to integrate a simple CORBA service with the Axis2 Web service engine. So we have to create

  1. A CORBA service
  2. CORBA to Web service bridge using the CORBA module of Apache Axis2
  3. A Web service client

 

Prerequisites

Make sure the following software packages are properly installed.

Include JAVA_HOME/bin and AXIS2_HOME/bin to the PATH environment variable.

 

Creating the CORBA Server

First we are going to create a simple CORBA server using the bottom-up approach. Let's start the example by creating an IDL (Interface Description Language) file which describes the interface of our CORBA service.

Create a new directory called CORBA2WS. Inside CORBA2WS directory, and save the following IDL code as mycorbaserver.idl.

module corba2ws 
{ 
    enum TrigonometricFn 
    { 
        sin, 
        cos, 
        tan 
    }; 

    valuetype TrigonometricVal 
    { 
        private TrigonometricFn func; 
        private double angle; 
        TrigonometricFn getFunc(); 
        double getAngle(); 
    }; 

    typedef sequence<long>  LongVals; 

interface MyCorbaService
{
double evalTrigonoFn(in TrigonometricVal t);
long maxvalue(in LongVals l);
string concat(in string first, in string second, out long length);
};
};


The above file describes the interface of the CORBA server in OMG Interface Description Language (IDL). This IDL contains three user defined data type and a CORBA interface. The user defined data types defined in the IDL file are:

  • TrigonometricFn - An Enumeration type of sin, cos and tan values.
  • TrigonometricVal - A value type (Object by Value). This value type contains func and angle member variables. func is an instance of TrigonometricFn enumeration type whereas angle is a floating point number. So, an instance of the TrigonometricVal value type contains a trigonometric operation and an angle (in radians). Other than the variables, the value type has two methods, namely getFunc() and getAngle().
  • LongVals - A sequence (dynamic array) of long values.


The name of the CORBA service interface, "MyCorbaService" has three methods.

  1. evalTrigonoFn - This method takes a TrigonometricVal as a parameter and returns a floating point number which represents the value of the trigonometric function stored in the TrigonometricVal parameter.
  2. maxvalue - This method takes a sequence of long values as a parameter and returns the largest value of the sequence.
  3. concat - This method takes two strings (first and second) as parameters and returns a concatenated string. Other than the return value (string), this method returns an output parameter length, which gives the number of characters in the concatenated string.


Now we have to generate the Java bindings from the IDL file. Open a console window and cd to the directory which contains the mycorbaserver.idl file. Enter the following command to generate the bindings.

idlj -fall mycorbaserver.idl

Typically, the above command will generate the files illustrated in the following figure.

Files generated

Now, we have to create three Java classes - TrigonometricValImpl.java, MyCorbaServiceImpl.java and Server.java - inside the newly created corba2ws directory.

The TrigonometricValImpl.java class is used to implements the value type TrigonometricVal.

package corba2ws; 

public class TrigonometricValImpl extends TrigonometricVal { 
    public TrigonometricFn getFunc() { 
        return func; 
    }

    public double getAngle() { 
        return angle; 
    } 
}

 

Now, we have to implement MyCorbaService to the business logic of the CORBA service. A possible implementation of the MyCorbaService is (MyCorbaServiceImpl.java): 

package corba2ws; 

import org.omg.CORBA.IntHolder; 
import java.util.Arrays; 

public class MyCorbaServiceImpl extends MyCorbaServicePOA { 
    public double evalTrigonoFn(TrigonometricVal t) { 
        TrigonometricFn fn = t.getFunc(); 
              if (TrigonometricFn.sin.equals(fn)) 
            return Math.sin(t.getAngle()); 
        else if (TrigonometricFn.cos.equals(fn)) 
            return Math.cos(t.getAngle()); 
        else if (TrigonometricFn.tan.equals(fn)) 
            return Math.tan(t.getAngle()); 
        else 
        throw new RuntimeException("Bad paramenter"); 
    } 

    public int maxvalue(int[] l) { 
        Arrays.sort(l); 
        return l[l.length - 1]; 
    } 

    public String concat(String first, String second, IntHolder length) { 
        String result = first + second; 
        length.value = result.length(); 
        return result; 
    } 
}

 

The Server.java provides the main method to run our simple CORBA server. 

package corba2ws; 

import org.omg.CosNaming.NamingContextExt; 
import org.omg.CosNaming.NamingContextExtHelper; 

public class Server { 
    public static void main(String[] args) { 
        org.omg.CORBA_2_3.ORB orb = 
                (org.omg.CORBA_2_3.ORB) org.omg.CORBA.ORB.init(args, null); 
        try { 
            orb.register_value_factory("TrigonometricVal", new TrigonometricValDefaultFactory());
            org.omg.PortableServer.POA poa = 
                    org.omg.PortableServer.POAHelper.narrow( 
                            orb.resolve_initial_references("RootPOA")); 
            poa.the_POAManager().activate(); 
            org.omg.CORBA.Object o = 
                    poa.servant_to_reference(new MyCorbaServiceImpl()); 

            NamingContextExt nc = 
                    NamingContextExtHelper.narrow( 
                            orb.resolve_initial_references("NameService")); 
            nc.bind(nc.to_name("mycorbasrv"), o); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
        orb.run(); 
    } 
}

 

Using a console window, cd into the directory which contains the mycorbaserver.idl file and enter the following command to compile all the Java classes.


javac *.java

Running the CORBA Server

Open a console window and execute the following command to start the CORBA naming service.


tnameserv -ORBInitialPort 2900

Now, open another console window and change the current directory to the directory which contains the mycorbaserver.idl file. Run the following command to start the CORBA server.


java corba2ws.Server -ORBInitialPort 2900

Creating the CORBA - Web Service Bridge

Now we are ready to create a CORBA - Web service bridge using the Axis2 CORBA module. First we have to prepare Axis2 to work with the CORBA module.

  1. Make sure axis2-corba-{version}.jar is available in AXIS2_HOME/lib directory.

  2. Download latest Apache Yoko binary distribution from http://cwiki.apache.org/YOKO/download.html. Extract the downloaded archive to a temporary directory and copy yoko-core-{version}.jar and yoko-spec-corba{version}.jar to AXIS2_HOME/lib directory. (You can use the Axis2 CORBA module with other CORBA implementation as well. Refer to the Axis2 CORBA module user guide for more information.)

  3. Add the following line to the <axisconfig> section of the axis2.xml file which is located in AXIS2_HOME/conf directory.

    <deployer extension=".xml" directory="corba" class="org.apache.axis2.corba.deployer.CorbaDeployer"/>

  4. Create a new directory named corba inside AXIS2_HOME/repository directory. (If you are using the Axis2 WAR distribution, create the corba directory inside the WEB-INF directory of Axis2.)

 

Now, your Axis2 server is ready to deploy CORBA web services. Copy mycorbaserver.idl file to the newly created corba directory and create a new file named mycorbaserver.xml inside the same directory.

<service name="mycorbaserver" scope="application">
    <description>CORBA Web Service</description>
    <parameter name="idlFile">mycorbaserver.idl</parameter>
    <parameter name="namingServiceUrl">corbaloc::localhost:2900/NameService</parameter>
    <parameter name="objectName">mycorbasrv</parameter>
    <parameter name="interfaceName">corba2ws::MyCorbaService</parameter>
</service>

Start the Axis2 server and navigate to http://localhost:8080/axis2/services/mycorbaserver?wsdl using your favorite Web browser. You should see the WSDL of the new Web service.lWSDL 

WSDL

The EPR of the new mycorbaserver Web service would be http://localhost:8080/axis2/services/mycorbaserver.

Creating the Web service Client


Now we can create a Web service client to invoke the methods of the CORBA server.

Create a new directory named WSClient (outside CORBA2WS directory). Open a console window and cd into the WSClient directory. Execute the following command to generate the stub classes for the Web service client.


wsdl2java.sh -p test -uri http://localhost:8080/axis2/services/mycorbaserver?wsdl       (on Linux)
OR
wsdl2java.bat -p test -uri http://localhost:8080/axis2/services/mycorbaserver?wsdl       (on Windows)

This command will create a new directory "test" and generate two classes inside the "test" directory. Now, we have to create another class inside the same "test" directory.

package test; 

import java.rmi.RemoteException; 

public class Client { 
    public static void main(String[] args) throws RemoteException { 
        MycorbaserverStub stub = new MycorbaserverStub(
                 "http://localhost:8080/axis2/services/mycorbaserver"); 
        MycorbaserverStub.TrigonometricVal tv = 
                 new MycorbaserverStub.TrigonometricVal(); 
        tv.setAngle(1); 
        tv.setFunc(MycorbaserverStub.TrigonometricFn.sin); 
        MycorbaserverStub.EvalTrigonoFn t = new MycorbaserverStub.EvalTrigonoFn(); 
        t.setT(tv); 
        MycorbaserverStub.EvalTrigonoFnResponse response = stub.evalTrigonoFn(t); 
        System.out.println("Sin(1.0) = " + response.get_return()); 

        MycorbaserverStub.LongVals l = new MycorbaserverStub.LongVals(); 
        l.setItem(new int[]{1, 2, 45, 215, 34}); 
        MycorbaserverStub.Maxvalue maxvalue = new MycorbaserverStub.Maxvalue(); 
        maxvalue.setL(l); 
        MycorbaserverStub.MaxvalueResponse response2 = stub.maxvalue(maxvalue); 
        System.out.println("Max value of the array is: " + response2.get_return()); 

        MycorbaserverStub.Concat concat = new MycorbaserverStub.Concat(); 
        concat.setFirst("Axis2"); 
        concat.setSecond("CORBA"); 
        MycorbaserverStub.ConcatResponse concatResponse = stub.concat(concat); 
        System.out.println("Concatenated string: " + concatResponse.get_return()); 
        System.out.println("Lenth of the string: " + concatResponse.getLength()); 
    } 
}

 

Add all the JAR files in the AXIS2_HOME/lib to the CLASSPATH and execute java test.Client to run the client. This will invoke our CORBA server through Axis2 Web service engine and print the results as follows.

Sin(1.0) = 0.8414709848078965
Max value of the array is: 215
Concatenated string: Axis2CORBA
Lenth of the string: 10

Conclusions

The CORBA module of Axis2 bridges CORBA and Web Services, allowing Web service clients to invoke CORBA services. This bridging is totally transparent to the Web service clients so that they can invoke a CORBA backed Web services in the same way as invoking a generic Web service. In fact with CORBA module of Apache Axis2, it's possible to allow the CORBA integration in an ESB environment.

References

Author

Eranga Jayasundera

WSO2Con 2014 USA