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

Date: Sun, 11th Nov, 2007
Level: Intermediate
Reads: 10545 Comments: 9 | Login or register to post comments
Eranga Jayasundera
Consultant
IT
erangaj's picture

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

elad.avneri.kodak.com's picture

Can't Download Yoko

From the article: 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.) When trying to download Yoko from the URL I get "The requested URL /dist/incubator/yoko/1.0-incubator-M2/yoko-distribution-1.0-incubating-M2-runtime-bin.zip was not found on this server." and I can't also find the "Axis2 CORBA module user guide" referenced above. Can someone help?
sunil kumar's picture

Error running the example

Hi Eranga, Thanks a lot of for your detailed example for exposing Corba services as Web services. But, I was unable to run the example the successfully. I am getting the following error while starting the Axis2 1.5 server: [ERROR] Error while deploying null org.apache.axis2.deployment.DeploymentException: an identifier is required after the 'long' keyword Could you help me resolve the issue? I tried to google around to fix the error, but I did not get any help! I am using Axis2 1.5 with yoko-distribution-1.0-incubating jars. Thanks in advance, Sunil.
elad.avneri.kodak.com's picture

I am getting the same error

Here are the full details of the exception [ERROR] Error while deploying null org.apache.axis2.deployment.DeploymentException: an identifier is required after the 'long' keyword at org.apache.axis2.corba.deployer.CorbaDeployer.populateService(CorbaDeployer.java:329) at org.apache.axis2.corba.deployer.CorbaDeployer.processService(CorbaDeployer.java:128) at org.apache.axis2.corba.deployer.CorbaDeployer.deploy(CorbaDeployer.java:97) at org.apache.axis2.deployment.repository.util.DeploymentFileData.deploy(DeploymentFileData.java:136) at org.apache.axis2.deployment.DeploymentEngine.doDeploy(DeploymentEngine.java:659) at org.apache.axis2.deployment.repository.util.WSInfoList.update(WSInfoList.java:144) at org.apache.axis2.deployment.RepositoryListener.update(RepositoryListener.java:337) at org.apache.axis2.deployment.RepositoryListener.checkServices(RepositoryListener.java:241) at org.apache.axis2.deployment.DeploymentEngine.loadServices(DeploymentEngine.java:131) at org.apache.axis2.deployment.FileSystemConfigurator.loadServices(FileSystemConfigurator.java:147) at org.apache.axis2.context.ConfigurationContextFactory.createConfigurationContext(ConfigurationContextFactory.java:95) at org.apache.axis2.context.ConfigurationContextFactory.createConfigurationContextFromFileSystem(ConfigurationContextFactory.java:206) at org.apache.axis2.transport.SimpleAxis2Server.(SimpleAxis2Server.java:47) at org.apache.axis2.transport.SimpleAxis2Server.main(SimpleAxis2Server.java:98) Caused by: org.apache.axis2.corba.exceptions.IDLProcessorException: an identifier is required after the 'long' keyword at org.apache.axis2.corba.idl.IDLProcessor.process(IDLProcessor.java:52) at org.apache.axis2.corba.receivers.CorbaUtil.getIDL(CorbaUtil.java:185) at org.apache.axis2.corba.deployer.CorbaDeployer.processOperations(CorbaDeployer.java:439) at org.apache.axis2.corba.deployer.CorbaDeployer.populateService(CorbaDeployer.java:300) ... 13 more Caused by: org.apache.axis2.corba.exceptions.InvalidIDLException: an identifier is required after the 'long' keyword at org.apache.axis2.corba.idl.parser.IDLVisitor.findDataType(IDLVisitor.java:397) at org.apache.axis2.corba.idl.parser.IDLVisitor.visitAnonymousSequence(IDLVisitor.java:554) at org.apache.axis2.corba.idl.parser.IDLVisitor.findDataType(IDLVisitor.java:354) at org.apache.axis2.corba.idl.parser.IDLVisitor.visitAndAddTypedefs(IDLVisitor.java:509) at org.apache.axis2.corba.idl.parser.IDLVisitor.visit(IDLVisitor.java:111) at org.apache.axis2.corba.idl.parser.IDLVisitor.visit(IDLVisitor.java:80) at org.apache.axis2.corba.idl.IDLProcessor.process(IDLProcessor.java:49) ... 16 more
david.cole.sug.com's picture

Solution to an identifier is required after the 'long' keyword

I was also getting the same exception: Caused by: [16:51:27.129] Caused by: org.apache.axis2.corba.exceptions.InvalidIDLException: an identifier is required after the 'long' keyword [16:51:27.129] at org.apache.axis2.corba.idl.parser.IDLVisitor.findDataType(IDLVisitor.java:397) [16:51:27.129] at org.apache.axis2.corba.idl.parser.IDLVisitor.visitAnonymousSequence(IDLVisitor.java:554) [16:51:27.129] at org.apache.axis2.corba.idl.parser.IDLVisitor.findDataType(IDLVisitor.java:354) [16:51:27.129] at org.apache.axis2.corba.idl.parser.IDLVisitor.visitAndAddTypedefs(IDLVisitor.java:509) [16:51:27.129] at org.apache.axis2.corba.idl.parser.IDLVisitor.visit(IDLVisitor.java:111) [16:51:27.129] at org.apache.axis2.corba.idl.parser.IDLVisitor.visit(IDLVisitor.java:80) [16:51:27.129] at org.apache.axis2.corba.idl.IDLProcessor.process(IDLProcessor.java:49) I found out after looking over the code for the IDLVisitor class in the corba module that this is a problem in the IDL file when defining the sequence type: typedef sequence <long> longVals; They are expecting you to provide a 'bounded' sequence only, meaning it is setup with a maximum number of values in the sequence. To correct the issue, simply add a size to the sequence: typedef sequence <long,20> longVals; That should take care of the issue for the purpose of the sample. However, I do think it should be able to handle unbounded sequences and I will submit a JIRA regarding the issue. I have create a JIRA issue for the corba module on the Axis2 website: https://issues.apache.org/jira/browse/AXIS2-4955
amit.tare.hotmail.com's picture

gsoap corba module

hello, nice document... but i am working with C++ to develop a CORBA server. so i am using Gsoap there. can u please tell me that how can i use gsoap with CORBA. is there any module which support corba with the help of gsoap to develop webservices in CORBA. can i use mod_gsoap for that. pls rply. Amit tare. amit.tare@hotmail.com incredible India(अतुल्य भारत)
v3d's picture

exposing multipe interfaces

How can I expose 2 or more CORBA interfaces as Web Services? How the mycorbaserver.xml file's parameters will change if 2 or more CORBA interfaces are exposed? ~v3d
lprenek's picture

Hi, I went through this step

Hi, I went through this step by step tutorial and Hello world really works! Great! But I tried to wrap my idl file from real project. But I came acrross to many erros, for example: expression #include (error line 2:1: unexpected token: include ), it seems that primitive type "long long" isn't supported I'm using axis2 version 1.4.1, Tomcat 6.0 Are these thinks errors or I just my mistakes? Thanks Libor
erangaj's picture

Error in executing client using Axis2

Minny wrote: hi, I am trying to expose corba service calls as web services using Apache axis2 by referring this article from the site http://wso2.org/library/2807. Server side is ready. The methods exposed are getting displayed in the url. And WSDL was also generated. Client side stubs are ready and got compiled successfully. But while trying to run the client i am getting the following errors We are stuck in the last stage of accessing the web services using client. log4j:WARN No appenders could be found for logger (org.apache.axis2.description.AxisService). log4j:WARN Please initialize the log4j system properly. Exception in thread "main" org.apache.axis2.AxisFault: unknown         at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:486)         at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:343)         at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:389)         at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:211)         at org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)         at test.MycorbaserverStub.concat(MycorbaserverStub.java:388)         at test.Client.main(Client.java:22) Classpath have been set correctly as specified in the article. Please help me to get through. Thanks, Minny
erangaj's picture

Re: Error in executing client using Axis2

Hi Minny, The details provided by you are not sufficient to find the issue. Can you please provide some more details including sample source code. Please make sure to use the latest nightly build (or checkout from svn and build) of Axis2 as CORBA module is not yet available in released versions. Thanks, Eranga