BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Articles How to Extend the Axis2 Framework to Support JVM Based Scripting Languages

How to Extend the Axis2 Framework to Support JVM Based Scripting Languages

This article explains how to extend the Axis2 framework to support Java Virtual Machine (JVM) based scripting languages such as Jython, JRuby, etc. It provides a high level overview of the subject, covering some key concepts of Apache Axis2 and how it can be used to come up with an extension to a JVM based scripting language. After going through this article, a developer will be able to extend the Axis2 framework to support the JVM based scripting language of his or her choice. When the Axis2 framework is extended it is easy to:

  1. Deploy a script as a web service.
  2. Write a service client in the chosen scripting language.

Apache Axis2 is an open source Web services engine. It is a complete re-design and re-write of the widely used Apache Axis SOAP stack. Axis2 not only provides the capability to add Web Service interfaces to Web applications, but can also function as a standalone server application. Apache Axis2 supports SOAP as well as widely popular REST style of Web services. You can expose the same business logic implementation as a WS-* style interface as well as a REST/POX style interface simultaneously using Axis2.

The JVM was initially designed to support only the Java programming language. However, as time has gone on, more and more languages, including many scripting languages, have been ported to the platform. The JVM now supports a wide spectrum of scripting languages such as Jython, JRuby, ColdFusion, etc. For simplicity this article uses Jython as its scripting language, however the techniques described can equally be applied to other languages.

Jython is an implementation of the Python programming language in Java. It is a programming hybrid, exhibiting the strengths of both Java and Python. Since Jython is written 100% in Java, scripts written using Jython will run on top of any compliant JVM and can use existing Java libraries as if they were Python modules.

Web Service Implementation approaches

Web services are a collection of technologies that can be used to build a Service Orientated Architecture (SOA). Although there seems to be a general confusion about the relationship between SOA and Web services, it is important to know that Web services are an implementation methodology that adopts standard protocols to execute SOA. There are two widely used techniques in Web service development, code first and contact first:

With the code first approach, primary concern is given to the code; you start with the Java code, and the Web service contract (WSDL) is generated from it.  In contrast Contract First emphasises the service contract; you start with the WSDL contract, and use Java or a code generation tool to implement said contract. The contract first approach has some advantages. It promotes:

  • Loose coupling between applications
  • Interoperability between multiple services
  • The use of Abstraction to hide underlying implementation details
  • Collaboration and agreement between all parties

When considering the Code First approach, some of the advantages are that it:

  • Is simple and less time consuming
  • Can be used to expose legacy systems as Web services
  • Does not require an in depth knowledge on WSDL

That said when designing a service contract, you can always choose to use either the code-first or contract-first techniques. Ultimately the decision relies on whether you care more about ensuring interoperability or improving productivity.  This article will therefore show how to extend Apache Axis2 to support both techniques.

Extending Axis2 Framework to support Code First Approach

Axis2 contains a powerful XML based client API. This API can be used to develop Java service clients. Now our requirement is to write the service client in a scripting language, and we’ve chosen Jython for illustration purposes.

To allow Jython to work with the Axis2 Client library we need to develop a wrapper library around Axis2’s Client API. The wrapper library is developed to create a layer of abstraction on top of an existing body of functionality. At this point we are redefining the Axis2 Client API's interface to accept Jython scripts.

The above figure shows the architecture of the API. When your Jython client script is executed, a mapping Java service client is created and executed.  Then a Web service call is made and the result is passed back to your client script. More information on the Axis2 service client API can be found here.

When a SOAP message is being sent through the Client API, an Out Pipe activates. The Out Pipe will invoke the handlers and terminate with a Transport Sender that sends the SOAP message to the target endpoint. The SOAP message is received by a Transport Receiver, which reads the SOAP message and starts the In Pipe. The In Pipe consists of handlers and ends with the Jython Message Receiver, which consumes the SOAP message and hands it over to the application.

The following code snippet shows Jython client which is calling a web service.

from org.wso2.wsf.jython.client import WSClient
from org.wso2.wsf.jython.client import WSFault
from org.wso2.wsf.jython.client import WSMessage

req_payload_string = "<webSearch><appid>ApacheRestDemo</appid><query>Sri Lanka</query><form/></webSearch>"
LOG_FILE_NAME = "/home/heshan/IdeaProjects/MRclient/src/jython_yahoo.log"
END_POINT = "http://search.yahooapis.com/WebSearchService/V1/webSearch"

try
        client = WSClient({ "to" : END_POINT,
		            "http_method" : "GET",
			    "use_soap" : "false"},
			 LOG_FILE_NAME)
	req_message = WSMessage(req_payload_string, {})
	print " Sending OM : " , req_payload_string
	res_message = client.request(req_message)
	print " Response Message: " , res_message
	
except WSFault, e:
	e.printStackTrace();

Extending the Apache Axis2 to support the Contract First Approach

Axis2 code generator

For code generation, Axis2 includes a code generation module which is called the Axis2 Code Generator. The code generator allows multiple data-binding frameworks to be incorporated and is easily extendable. Therefore the code generation tool can be extended to support a scripting language. Before diving into details on how to extend the tool let's have a look at the Axis2 Code Generator.

When you consider a SOAP processing engine, one of the key value additions will be code generation based on WSDL. It:

  1. Offers User convenience - A code generation tool helps users to use the framework in an easy and efficient way.
  2. Makes use of the framework to it's full potential.

Now let's have a look at the architecture of Axis2 Code generator.

The tool's architecture is pretty straightforward. The core processes the WSDL and builds an object model. Then the built object model is parsed against the templates to build the source code.

Extending the Axis2 code generator to support scripting languages

The code generation engine calls the extensions one by one finally calling a component known as the Emitter. The Emitter is the actual component that does the significant bit of work in the code generation process. Emitters are usually language dependent and hence one language has one emitter associated with it. Therefore there should be an emitter to support Jython code generation. This simple yet powerful architecture is shown in the above illustration.

The Emitter processes the WSDL and builds an object model. The object model is simply an XML file which contains the object model for the WSDL with respect to the Axis2 information model (ie. axis service, axis operation, axis message, etc). The template is an XSLT file which contains information on how the code should be generated. Finally the built object model is parsed against the template to build the Jython source code.

In order to support the Contract First approach you need to generate a skeleton and a message receiver for your service. The generic message receiver that we have already written will not work because it works only on a limited schema structure. We can use the existing infrastructure in Axis2 to do this. Axis2 creates an intermediate XML structure representing a WSDL and we have to run 2 XSLTs on that to create the skeleton class and the message receiver. With the help of these XSLTs and the code generation tool we can support Contract First Web services in Jython. At the end, the message receiver and the skeleton can be used to write a service client in Jython.

Server side

This section will discuss how to expose your business logic as a Web service.

The solution to the requirement of exposing a Jython Web service in Axis2 lies within the pluggable deployer concept of Axis2. In order to expose services written in Jython, we will be writing a custom deployer together with a Jython message receiver.

The message receiver consumes SOAP messages and hands them over to applications. The message receiver is the last handler in the in-pipe. For more information on Message Receivers and Axis2 Architecture, please refer to the documentation.

The deployer needs to map Jython data types to XML schema data types. This process is known as data binding. Thereafter, with the help of data binding and method annotations, an XML Schema is generated for the Jython service. Next, both the generated XML schema, and the meta-data pertaining to an AxisService, are given to the Axis2 engine. Axis2 engine will create the WSDL out of it and your Jython service will be exposed as a Web service. If you are interested in learning more on deployers, I suggest you take a look at the article on Axis2 deployment - Custom deployers.

The figure above shows the architecture of this solution. The incoming SOAP message is received by the Transport Listener and it is passed through the handler chain. Then it is given to the Jython Message Receiver, which traverses through the Axis Object Model (AXIOM) structure and retrieves the relevant information. This retrieved information is passed in to the Jython service. Then the Jython service gets executed and the resulting object is passed back in to the Jython Message Receiver. In the Jython Message Receiver an AXIOM structure is created out of the returned Jython object. Then the response is sent through the handler chain to the Transport Sender. The Transport Sender sends the response to the client. The process explained above takes place for each and every SOAP message that is exchanged.

How a Jython service is deployed

At the deployment time the annotations of the Jython script are read. Then the mapping of the dynamic Jython types to static Java types is done. This process is called data binding. After corresponding matching types are mapped, an XML schema is created out of the service. The following steps describe how the XML schema is generated out of the Jython service:

  1. Annotations of the Jython service are read.
  2. An AxisService is created for the Jython service.
  3. An AxisOperation is created for every Jython method.
  4. An AxisMessage is added to the operation. It contains the types of the method parameters.
  5. Each and every AxisOperation is added to the AxisService.
  6. Finally the XML Schema for the Jython message is generated.

The generated AxisService is given to Axis2 engine. Finally the Axis2 engine generates the WSDL out of it.

Conclusion

Apache Axis2 can be extended in a such a way that it will support JVM based scripting languages. After the extensions are made, a user can expose services and write service clients using the JVM scripting language extension.

About the author

Heshan Suriyaarachchi is a Software Engineer at WSO2 Inc and a member of the WSO2 Enterprise Service Bus (ESB) team. Heshan has experience in Web services, SOA, middleware and Distributed Systems. He enjoys playing Basketball and contributing towards open source projects in his spare time.

Blog: http://heshans.blogspot.com/

Rate this Article

Adoption
Style

BT