Axis C++ Architecture Guide

Under construction ....
0.1 Version
Feedback: axis-dev@ws.apache.org

Contents

Introduction
Architecture Overview
Subsystems
    AxisEngine
    HandlerPool
    Soap Deserializer
    Soap Serializer
    WSDD Module 
    Server Configuration
    Logger
Web Service Deployment 
Wrapper Classes and WSDL Generation
Client Stub Generation
Open Issues

Introduction

This guide describes the architecture of Axis C++ implementation.

Architectural Overview

Axis C++ is all about deploying C++ web services and processing SOAP messages. As you see later Axis C++ consists of several subsystems working together. Axis C++ architecture closely follows Axis Java in Handler and message paths.

Handlers and the Message Path in Axis

Axis C++ implementation follows how handlers and message paths work in Axis Java implementation.

When the central Axis processing logic runs, a series of Handlers are each invoked in order. The order of invocation is determined by two factors - deployment configuration and whether the engine is a client or a server. The object which is passed to each Handler invocation is a MessageData. A MessageData is a structure which contains several important parts: 1) Deserializer, 2) Serializer, and 3) a bag of properties. More on this in a bit.

Message Path on the Server

The server side message path is shown in the following diagram. The small cylinders represent Handlers and the larger, enclosing cylinders represent Chains (ordered collections of Handlers which will be described shortly).

A message arrives (in some protocol-specific manner) at a Transport Listener. In this case, let's assume the Listener is an apache module. It's the Listener's job to package the protocol-specific data into a soapstream object (specified in Packet.h), and pass it to AxisEngine to be processed. The soapstream is also loaded with various properties by the Listener -  in this example the property "trtype" would be set to the transport type and the value of the SOAPAction HTTP header is inserted in to a header list.

The AxisEngine's first job is to check what the transport is. Then the MessageData object is created and populated (with Serializer, Deserializer etc). Also the Serializer and Deserializer is initialized. Then the configured handlers and the target web service handler are loaded. All transport, global and service specific handlers are loaded in to Chains. A Chain is also a Handler consisting of a sequence of Handlers which are invoked in turn -- more on Chains later.

Then the loaded handler chains are invoked in the order shown passing the MessageData object into the invoke().

Subsystems

Axis comprises several subsystems working together with the aim of separating responsibilities cleanly and making Axis modular. Subsystems which are properly layered enable parts of a system to be used without having to use the whole of it.

AxisEngine

AxisEngine contains the core logic of the message flow. AxisEngine's "Process" method contains the message flow logic. Following sequence diagrams show the message flow logic.

Following Diagram shows how the transport listener passes the SOAP message to the AxisEngine. AxisEngine is a singleton object for a process.

Now following diagram depicts the Engine Initialization.

Following diagram depicts the AxisEngine's message flow logic

HandlerPool

AxisEngine instantiates a HandlerPool object in its constructor. HandlerPool does the following 3 tasks,

  1. Loads and keeps Transport and Global handlers.
  2. Loads service specific handlers when needed and unloads when needed.
  3. Loads target web service handler when needed and unloads when needed.

To provide above functionality the HandlerPool makes use of other two classes HandlerChain and HandlerLoader. HandlerLoader loads holds and unloads the dynamic link library (or shared object) that contain either a handler or a web service. HandlerChain is used to keep a list of handlers to be invoked in order. HandlerChain itself is a handler.

In order for the HandlerLoader to dynamically load a class, every DLL (or Shared object) must have following export functions

int GetClassInstance(DCLInterface **inst);

int DestroyInstance(DCLInterface *inst);

AxisEngine has no idea of any web service methods in the deployed web service class that is dynamically loaded from a DLL. Therefore in order to communicate with loaded class we have to have a known interface. This interface is known as BasicHandler and is known to AxisEngine. This interface is implemented by every webservice and a handler.

Soap Deserializer

Currently the Soap Deserializer is implemented using SAX2 parser. Soap Deserializer exposes and API such that the API is independent of the implementation. This API is decided with a view of using XML pull parsing for the implementation. Once the Deserializer is given a message with its SetStream(..) method its GetXXX methods can be called in sequence to get the parsed SOAP data.


Soap Serializer

Soap Serializer's task is to generate SOAP stream to be sent. There are a set of functions (API that is the opposite functionality with Soap Deserializer). Once the Serializer is given all the information that is required to generate a SOAP using the API, the getStream(..) function can be used to get the SOAP message.


WSDD Module

WSDD module is a set of classes that parses the deployment descriptor file(server.wsdd) and makes the information available to the AxisEngine.  A WSDDDeployment object is instantiated in AxisEngine's constructor.


Server Configuration


Logger

Web Service Deployment 

The solution is to write a wrapper class for each web service class. This wrapper class is written with full awareness of the actual web service class and the corresponding WSDD. Then this wrapper class is compiled to a DLL (Shared Library in Linux) and is deployed as the web service. Following diagram shows this process.

 

Wrapper Classes and WSDL Generation

WrapperClassGenerator writes the wrapper class using only the web services include file and the deployment descriptor for that web service. The corresponding WSDL too is generated.

Web Service to Wrapper Class Mapping

Following example shows how the Web service maps to the Wrapper class.

The actual web service object is instantiated in the constructor of the wrapper class and is destroyed in the destructor. The Invoke method can be written just by looking at the WSDD. Or else by looking at the exposed methods of the web service class. The Invoke method chooses what method to be called as follows.

Then each allowed method in the actual web service class is wrapped by a Wrapper method in the Wrapper class. Only a method signature is needed to write the corresponding wrapper method. This implies that following are needed, 

  1. Method Name

  2. No of parameters

  3. Sequence and types of the parameters

  4. Return type

Client Stub Generation

 

 

Open Issues

1.