WSO2Con 2013 CFP Banner

Enabling Web Services by Embedding Axis2/C

Discuss this article on Stack Overflow
By Malinda Kaushalye
  • 9 Oct, 2006
  • Level: 
  • Reads: 8071

Apache Axis2/ C is the C implementation of the popular Axis2 architecture, the next generation of Web services and Service Oriented Architectures (SOA). Kaushalye Kapuruge in this article does a fantastic job in explaining how to embed Axis2/C in your platform to enable Web services. He uses a Axis2/C's PHP and AJAX extensions to demonstrate adding Web services capability to any C based platform.

Malinda Kaushalye
Tech-lead
WSO2 Inc.

Introduction

For many years there was a requirement in IT systems to communicate over the Internet regardless of the platform, language, location or the technology they were developed from. Development of XML as a common format for exchanging data, and the broad acceptance of services oriented architecture made the Web services ubiquitous. Many businesses are trying to make their services available via Web services and thus trying to support Web services standards. As a result many vendors/individuals are willing to participate in discussions and implementations of Web services standards. All these make Web services the next generations technology that demolishes many technical barriers in connecting applications.

The Apache Axis engine comes to the picture with the above background. Apache Axis2 is the second generation of Axis engine with lots of advantages over its predecessor. Axis2/C is the C language implementation of the popular Axis2 architecture.

In the following article we will discuss how to embed Axis2/C in your platform to enable Web services. In other words, how to add Web services capabilities to another platform using the Axis2/C implementation. We will try to highlight areas that you need to concentrate in the process of embedding, of course, with some samples using ongoing implementations.

Axis2/C Design

Axis2/C is written with the motivation that it should be possible to bind it to any C based platform. This is a huge advantage compared to it's big brothers, Axis2/Java and Axis/C++. For example, it is possible to bind Axis2/C with scripting languages such as Perl, PHP, Ruby etc. Also now there is a Firefox XPI extension that extends AJAX capabilities to consume Web services through Web clients. In the future there will be a similar extension for Internet Explorer with ActiveX support.

Embedding Axis2 with other platforms

Apart from the selection of C language, there are few other important design decisions that cleared the path for Axis2/C to be pluggable to other platforms.

One decision is to use an environment structure. This environment encapsulates memory management, error handling, logging and threading mechanisms. This allows others to use their own implementations for above mechanisms in integrating Axis2/C. To elaborate this a bit more, think about memory allocation in Axis2/C's PHP extension which is implemented using the interface with emalloc and efree. If you have already gone through the Axis2/C source you might have seen that the environment object is passed around every function to make sure the above objective is achieved.

Another design characteristic is the pseudo object oriented design. Note that the first implementation of Axis2 was in Java language. So it was required to have a similar design and API for the C implementation as well. All data is hidden in the source and only the operations are exposed in function headers. To simplify calling these operations there are macros defined for each and every operation in the function header. Therefore, it is very important that you understand and follow the same design in embedding Axis2/C. Introducing Apache Axis2/C is a good article to read more on this.

Axis2 takes XML and emits XML. If your extension needs any other formats you have to make sure that you convert everything to XML before feeding to the Axis2 engine and vise versa. Also Axis2 uses special object model called AXIOM. We will discuss about AXIOM with details in the next section.

AXIOM

AXIOM stands for AXis Object Model. It is the object model that is being used by the Axis2 engine. To embed Axis2/C in your platform you need to support AXIOM. So it's very important to understand how AXIOM works.

AXIOM Has Three Important Characteristics:

  1. AXIOM is light weight. The depth of the object hierarchy is reduced to consume less memory.
  2. Objects are not created until the necessity arises. This is a very important feature in AXIOM compared to other XML object models. It is very handy when it comes to very large XML files or SOAP messages. For example, think about a SOAP message with a large body and few SOAP header elements. Most of the time we need to process SOAP headers only. So it is very inefficient to map the whole XML tree to an object hierarchy.
  3. AXIOM is based on StAX, which is a pull based parser.

AXIOM is specifically written for Axis2. So it is unlikely that it is available in other platforms. AJAX supports XML DOM. PHP supports both Simple XML and DOM. Thus for the extensions written for Axis2 there are converters to convert AXIOM to desired object models and vice versa. Before embedding Axis2 you have to think about which formats your platform is supporting and what way you have to convert your object models to AXIOM before fetching it to the Axis2. Following is code extracted from the PHP extension. It converts an OM node to it's DOM counterpart.

static xmlDocPtr serialize_om_to_doc
(axis2_env_t *env, axiom_node_t *ret_node)
{
axiom_xml_writer_t *writer = NULL;
axiom_output_t *om_output = NULL;
xmlDocPtr doc = NULL;

writer = axiom_xml_writer_create_for_memory(env, NULL, AXIS2_TRUE, 0, AXIS2_XML_PARSER_TYPE_DOC);
om_output = axiom_output_create (env, writer);
AXIOM_NODE_SERIALIZE (ret_node, env, om_output);
doc = (xmlDocPtr)AXIOM_XML_WRITER_GET_XML(writer, env);
return doc;
}

Another interesting feature of AXIOM is that there is a SOAP specific API. As we mentioned before AXIOM is for Axis2 engine. Axis2 is a SOAP processing engine. So there are lots of well defined structures to represent SOAP constructs in AXIOM. Keep this also in mind when you write converters.

Understanding Service Client

To consume services that are deployed, Axis2/C has a service client interface. Service client interface provides following functionalities.

  • Send/ Receive messages to/from the service
  • Set/Get option parameters of the client
  • Engage/Disengage modules
  • Add/Remove SOAP headers

Sending and receiving messages are carried out in different Message Exchange Patterns (MEPs). It also supports synchronous and asynchronous modes of operations. For example, the service client API provides functionalities like fire_and_forget, send_receive, send_receive_non_blocking etc.

In the message processing chain it is required to pass some parameters to intermediate handlers. This is achieved by setting options parameters in the client side. So the Service Client interface has methods to specify options that are to be used.

One powerful feature of Service Client is the ability of engaging modules dynamically. The client decides which modules it needs to be initialized in the process of sending messages. For example, a client might need to provide security for the messages exchanged. In that case it has to engage the Rampart modules dynamically. Especially when a client (e.g. a PHP client) doesn't have the luxury of using descriptor files.

To consume a service you need to wrap this Service Client interface. The PHP extension has already done this. So let's see how to consume a service by using the Service Client wrapper available in the PHP extension of Axis2/C.

$serviceClient = new Axis2ServiceClient("http://localhost:9090/axis2/services/echo"); 
$resPayload = $serviceClient->sendReceiveSimpleXML($simplexml);

The first statement of the above example creates a new ServiceClient object with the service name as the parameter. Then it sends the message by calling sendReceiveSimpleXML(). $simplexml is a SimpleXMLElement. The complete code is available in echo_client_simple_xml_in_out.php file under samples directory. Here the PHP extension developer has provided a nice wrapper for users to create a service client and consume the service. In creating the service client this is what happens behind the scene.

AXIS2_GET_THIS(obj);
intern = (axis2_object*)zend_object_store_get_object(obj TSRMLS_CC);
client = axis2_svc_client_create(AXIS2_GLOBAL(env), AXIS2_GLOBAL(client_home));
client_options = axis2_options_create(AXIS2_GLOBAL(env));
AXIS2_SVC_CLIENT_SET_OPTIONS(client, AXIS2_GLOBAL(env), client_options);
intern->ptr = client;
intern->obj_type = PHP_AXIS2_SVC_CLIENT;

A similar wrapper is available in AJAX extension of Axis2/C. This is an effort to let Web developers invoke Web services from the client side. The extension comes as a Firefox XPI. This is how a Web service is invoked.

var req = new SOAPHttpRequest();  
req.soapVer = 1.1;
req.onreadystatechange = listenStatus;
req.open("POST", "http://api.google.com/search/beta2", false);
req.send ( reqContent);
var resultContent = req. responseXML;

Here we first create a SOAPHttpRequest object. Then we set the SOAP version and assign the a function (not seen in the above) to set the onreadystatechange flag of the request object. Now all we have do is to open a connection and send the request.

One difference in AJAX wrapper to the PHP is that its written in C++ (as other firefox extensions). But it still uses the Axis2/C core written in C.

options = axis2_options_create(env);
svc_client = axis2_svc_client_create(env, client_home);
AXIS2_SVC_CLIENT_ENGAGE_MODULE(svc_client, env, AXIS2_MODULE_ADDRESSING);
AXIS2_SVC_CLIENT_SET_OPTIONS(svc_client, env, options);
if ( NS_SUCCEEDED (rv ) ) {
ret_node = AXIS2_SVC_CLIENT_SEND_RECEIVE(svc_client, env, cont_node);
}
writer = axiom_xml_writer_create_for_memory(env, NULL, AXIS2_TRUE, 0, AXIS2_XML_PARSER_TYPE_BUFFER);
om_output = axiom_output_create (env, writer);
AXIOM_NODE_SERIALIZE (ret_node, env, om_output);
mResponseText = PL_strdup ((char* )AXIOM_XML_WRITER_GET_XML(writer, env) );
mStatus = SOAPHTTPREQUEST_HTTP_STATUS_SUCCESS;

Note that for the ease of understanding, certain code parts are omitted in the listing. We really encourage you to see the actual implementation to get a complete understanding of the code.

Understanding Service

Similar to the Service Client interface, Axis2/C provides a Service interface as well. When you try to embed Axis2/C in your platform to provide services, you must wrap this interface. The idea here is not to write services, but to provide a framework for deploying services. The only existing example for this is the PHP extension.

<?php
function echoString($text)
{
return $text;
}

$echo_service = new Axis2Service();
$echo_service->addFunction("echoString");
$echo_service->process();
?>

Above shows a simple echo service written in PHP. Once a request has come to the PHP engine, it will create a new Axis2 service and adds the function that is to be executed. Then to begin the Axis2 specific processing it will call the process().
The code that wraps the Service creation is given below:

php_worker = AXIS2_GLOBAL(php_worker);
conf_ctx = AXIS2_PHP_WORKER_GET_CONF_CTX(php_worker, AXIS2_GLOBAL(env));
conf = AXIS2_CONF_CTX_GET_CONF(conf_ctx, AXIS2_GLOBAL(env));
svc = AXIS2_CONF_GET_SVC(conf, AXIS2_GLOBAL(env), svc_info->svc_name);
if(NULL != svc){
svc_info->svc = svc;
} else {
svc_qname = axis2_qname_create(AXIS2_GLOBAL(env), svc_info->svc_name, NULL, NULL);
svc_info->svc =axis2_svc_create_with_qname(AXIS2_GLOBAL(env), svc_qname);
}
svc_info->msg_recv = axis2_php_xml_msg_recv_create(AXIS2_GLOBAL(env));

Engaging modules

Modules are a way to extend the Axis2 engine's capabilities. A module consists of set of handlers and a descriptor that specifies set of rules for handlers. The biggest advantage of having modules is to support the WS-* specifications. Many WS-* specifications are about changing the SOAP header information. Some examples are WS-Addressing, WS-Security, WS-ReliableMessaging.

Axis2/C integration in your platform must consider how to engage/disengage modules (Engaging means that the handlers specified in the module are in the message flow. In other words, it is active inside the engine) and how to pass parameters that are required for modules. For example, providing security for messages can be optional. So the extension should allow the flexibility of enabling or disabling the feature. If enabled, the security module expects certain parameters to be passed. Like which tokens need to be specified in security headers.

There is no need of writing specific wrappers for engaging a module in the server side. Modules can be engaged using the descriptor files (axis2.xml, services.xml). But for the client side it is necessary to give a wrapper. Let's see how AJAX extension has done this.

req.options ({ wsa_action:"http://ws.apache.org/axis2/c/samples/echoString" } );
req.engage ( "addressing", "vx" );

Following is the wrapper code.

AXIS2_SVC_CLIENT_ENGAGE_MODULE(svc_client, env, AXIS2_MODULE_ADDRESSING);
char* wsa_action = nsnull;
GetOptionByKey (SOAPHTTPREQUEST_OPT_WSA_ACTION, &wsa_action );
AXIS2_OPTIONS_SET_ACTION(options, env, wsa_action);

Conclusion

Ability to embed with other platforms is a powerful feature in Axis2/C design. Key points to consider are providing wrappers for client and service interfaces and the way of handling XML object model. Also it is necessary to support the concept of module based deployment that nourishes the Axis2 capabilities with WS-* specifications. Right now there are two extensions, one for PHP and the other for AJAX . Keep your eyes open, there are many more to come.

References

[1] OM Tutorial - http://ws.apache.org/axis2/c/docs/om_tutorial.html

[2] Introducing Apache Axis2/C - http://wso2.org/library/252

[3] Axis2/C's AJAX XPI, Mozilla Firefox Extension -http://wso2.org/projects/wsf/ajax/xpi

[4] Axis2/C's PHP Extension - http://pecl.php.net/package/axis2

[5] View Axis2/C Source - http://svn.apache.org/viewvc/webservices/axis2/trunk/c/

[6] Apache Axis2/C Officil Site - http://ws.apache.org/axis2/c/index.html

Author

Malinda Kaushalye Kapuruge, Software Engineer, WSO2 Inc. kaushalye at wso2 dot com