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.
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().
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
AxisEngine instantiates a HandlerPool object in its constructor. HandlerPool does the following 3 tasks,
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.
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'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 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.
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.
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.
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,
Method Name
No of parameters
Sequence and types of the parameters
Return type
1.