Apache Axis2 Architecture Guide

This document will give an introduction to Axis2's modular architecture with explanations on every module.

Send your feedback to: axis-dev@ws.apache.org. Prefix subject with [Axis2]. To subscribe to mailing list see here.

Contents

The Big Picture

A new architecture for Axis was introduced during the August 2004 Summit in Colombo, Sri Lanka. This new architecture Axis2 is based on is more flexible, efficient and configurable in comparison to Axis1.x architecture. Some well established concepts from Axis 1.x, like handlers etc., have been preserved in this new architecture.

Any architecture is a result of what that architecture should yield. The success of an architecture should be evaluated based on the requirements expected to be met by that architecture. Let us start our journey into Axis2 by looking at the requirements.

Requirement of Axis2

In the SOAP terminology, a participant who is taking part in a Web service interaction is known as a SOAP Node. Delivery of a single SOAP Message is defined based on two participants, SOAP Sender and SOAP Receiver. Each SOAP Message is sent by SOAP Sender and received by SOAP Receiver. A single SOAP delivery is the most basic unit that builds the Web service interaction.

Each SOAP Node may be written in specific programming language, may it be Java, C++, .NET or Perl, the Web services allow them to interoperate. This is possible because on the wire each Web service interaction is done via SOAP, which is common to every SOAP Node.

Web service middleware handles the complexity in SOAP messaging and lets the users work with the programming language they are accustomed to. Axis2 allows java users to invoke Web services using java representations, and handles the SOAP messaging behind the curtain.

Axis2 handles SOAP processing along with numerous other tasks. This makes the life of the Web service developer a whole lot easier. Following are the identified requirements:

  1. Provide a framework to process the SOAP messages. The framework should be extensible and the users should be able to extend the SOAP processing per service or per operation basis. Furthermore, it should be able to model different Message Exchange Patterns (MEPs) using the processing framework.
  2. Ability to deploy a Web service (with or without WSDL)
  3. Provide a Client API that can be used to invoke Web services. This API should support both the Synchronous and Asynchronous programming models.
  4. Ability to configure Axis2 and it's components via deployment.
  5. Ability to send and receive SOAP messages with different transports.

Apart from the above functionalities, performance in terms of memory and speed is a major consideration for Axis2. Axis2 Core Architecture is built on three specifications- WSDL, SOAP and WS-Addressing. Other specifications like JAX-RPC, SAAJ & WS-Policy are layered on top of the Core Architecture.

Axis2 Architecture

Axis2 architecture lays out some principals to preserve the uniformity. They are as follows:

Axis2 architecture is modular. Therefore Axis2 Framework is built up of core modules which collectively make up the core architecture of Axis2, and non-core/other modules are layered on top of this core modules/architecture.

Core Modules:

Other Modules:

Information Model

Information Model has two main hierarchies-Contexts and Descriptions. This model is described in UML notations below.

( A ----<> B says, B has 1 or more objects of A. A------>B says, the given relationship holds between A and B.)

The two hierarchies are connected as shown in the above figure. The Description hierarchy represents the static data. This data may be loaded from a configuration file that exists throughout the lifetime of Axis2. For example, deployed Web services, operations, etc. On the other hand, the context hierarchy holds more dynamic information about the things that have more than one instances (e.g.Message Context).

These two hierarchies creates a model that provides the ability to search for key value pairs. When the values are searched at a given level, they are searched while moving up the hierarchy until a match is found. In the resulting model the lower levels override the values in the upper levels. For example, when a value is looked up in the Message Context and is not found, it would be looked up in the Operation Context etc, up the hierarchy. The Search is first done up the hierarchy, and if starting point is a Context then it is search in the Description hierarchy as well.

This allows the user to declare and override values, result being a very flexible configuration model. The flexibility could be the Achilles heel for the system as the search is expensive, specially for something that does not exist. Yet in the final analysis developers believe that the flexibility would serve better in this instant.

Context Description Configuration Description

Configuration Context

Holds the Axis2's run time status. A deep copy of this would essentially make a copy of Axis2.

Axis Configuration

Holds all global configurations. Transports, global modules, parameters and services etc.

Service Group Context

Holds information about a particular usage of the respective service group. The life of a Service Group Context starts when a user starts interacting with a service that belong to this service group. This can be used to share information between services (within the same service group) in a single interaction.

AxisServiceGroup

Holds deployment time information about a particular service group.

Service Context

This context is available throughout the usage of the respective service. This can be used to share information between several MEPs of the same service, within a single interaction. Life cycle depends on the scope of the service.

AxisService

Hold the Operations and the service level configurations

Operation Context

Holds the information about the current MEP instance, maintain the messages in the current MEP etc.

AxisOperation

Holds the operation level configurations

Message Context

Holds all the information about the Message currently being executed.

AxisMessage

Hold message level static information like schema of the particular message.

XML Processing Model

As we mentioned above, XML processing model of Axis2 has becomes a separate sub-project, called Apache Axiom, in Apache Web services project. Please refer to the OM Tutorial for more information.

SOAP Processing Model

The architecture identified two basic actions a SOAP processor should perform, sending and receiving SOAP messages. The architecture provides two Pipes ('Flows'), to perform these two basic actions. Axis Engine or the driver of Axis2 defines two methods send() and receive() to implement these two Pipes. The two pipes are named In Pipe and Out Pipe, and the complex Message Exchange Patterns (MEPs) are constructed by combining these two pipes.

Extensibility of the SOAP processing model is provided through handlers. When a SOAP message is being processed the handlers that are registered would be executed. The handlers can be registered in global, service, or operation scopes and the final handler chain is calculated combining the handlers from all the scopes.

The handlers act as interceptors and they process parts of the SOAP message and provide add-on services. Usually handlers work on the SOAP headers, yet they may access or change the SOAP Body as well.

When a SOAP message is being sent through the Client API, an Out Pipe would begin, the Out Pipe invokes the handlers and end with a Transport Sender that sends the SOAP message to the target endpoint. The SOAP message is received by a Transport Receiver at the target endpoint, which reads the SOAP message and starts the In Pipe. The In Pipe consists of handlers and ends with the Message Receiver, which consumes the SOAP message.

Above explained processing happens for each and every SOAP message exchanged. After processing one message Axis2 may decide to create other SOAP messages, in which case more complex message patterns emerge. However Axis2 always view the SOAP message in terms of processing a single message. The combination of the messages are layered on top of that basic framework.

The two pipes does not differentiate between the Server and the Client. The SOAP Processing Model handles the complexity and provides two abstract pipes to the user. The different areas or the stages of the pipes are given names, and according to the Axis2 slang those are named 'phases'. A Handler always runs inside a phase, and the phase provides a mechanism to specify the ordering of handlers. Both Pipes have built in phases, and both define the areas for 'User Phases' which can be defined by the user.

Axis2 Default Processing Model

Axis2 has some inbuilt handlers that run in inbuilt phases and they create the default configuration for the Axis2. We will be looking more in to how to extend the default processing Model in the next section.

There are three special handlers defined in Axis2.
  1. Dispatchers - Finds the service and the operation the SOAP message is directed to. Dispatchers always run on the In-Pipe and inside the Dispatch phase. The in-built dispatchers dispatch to a particular operation depending on various conditions like WS-Addressing information, URI information, SOAP action information, etc. (See here for more information on Dispatching)

Processing an Incoming SOAP Message

Incoming SOAP Message is always received by a Transport Receiver waiting for the SOAP Messages. Once the SOAP Message arrives, the transport Headers are parsed and a

Message Context is created from the incoming SOAP Message. This message context encpsulates all the information, including the SOAP message itself, transport headers, etc., inside it. Then the In Pipe is executed with the Message Context.

Let us see what happens at each phase of the execution. This process may happen either in the server or in the Client.

  1. Transport Phase - The handlers are in the phase meant to process transport specific information such as validating incoming message by looking at various transport headers, add data into message context etc.
  2. Pre-Dispatch Phase- The main functionality of the handlers in this phase is to populate message context in order to do the dispatching. As an example, processing of addressing headers of the SOAP message, if any, happen in this phase. Addressing handlers extract information and put them in to the message context.
  3. Dispatch Phase - The Dispatchers run in this phase and tries to find the correct service and operation this particular message is destined to.
    The post condition of the dispatch phase (any phase can contain a post condition) checks whether a service and an operation was found by the dispatchers. If not the execution will halt and throws out a "service not found error".
  4. User Defined Phases - Users are allowed to engage their custom handlers here.
  5. Message Validation Phase - Once the user level execution has taken place this phase validates whether SOAP Message Processing has taken place correctly.
  6. Message Processing Phase - The Business logic of the SOAP message is executed here. A Message Receiver is registered with each Operation. This Message receiver (associated to the particular operation) will be executed as the last Handler of this phase.

There may be other handlers in any of these phases. Users may use custom handlers to override the mechanics in each of these phases.

Processing of the Outgoing Message

Out Pipe is simpler because the service and operation to dispatch is known by the time the pipe is executed. The Out Pipe may be initiated by the

Message Receiver or the Client API implementation. Phases of the Out Pipe are described below:
  1. Message Initialize Phase - First phase of the Out Pipe. Serves as the placeholder for the custom handlers
  2. User Phases - This executes handlers in user defined phases
  3. Transports Phase - Execute any transport handlers taken from the associated transport configuration. The last handler would be a transport sender which would send the SOAP message to the target endpoint.

Extending SOAP Processing Model

Above we discussed the default processing model of Axis2. Now let us discuss the extension mechanism for the SOAP processing model. After all, the whole effort of making this SOAP engine/processing model was focused much on making it extendable.

Idea behind introducing step wise processing of the SOAP message in terms of handlers & phases is to allow easier modification of the processing order. The notion of phases makes it easier to place handlers in between other handlers. This enables modification on the default processing behavior. SOAP Processing Model can be extended with handler or modules.

Extending the SOAP Processing Model with Handlers

The handlers in a module can specify the phase they need to be placed in. Furthermore they can specify their location inside a phase by providing phase rules. Phase rules will place a handler

  1. as the first handler in a phase.
  2. or as the last handler in a phase.
  3. or before a given handler
  4. or after a given handler

Extending the SOAP Processing Model with Modules

Axis2 defines an entity called a 'module' that can introduce handlers and Web service operations. A Module in terms of Axis2 usually acts as a convenient packaging that includes:

Modules have the concept of being 'available' and 'engaged'. 'Availability' means the module is present in the system, but has not been activated, i.e., the handlers included inside the module have not been used in the processing mechanism. When a module is 'engaged' it becomes active and the handlers get placed in the proper phases. The handlers will act in the same way as explained in the previous section. Usually a module will be used to implement a WS-* functionality such as WS-Addressing.

Apart from the extension mechanism based on the handlers, the WS-* specifications may suggest a requirement for adding new operations. For example, once a user add Reliable Messaging capability to a service, the "Create Sequence" operation needs to be available to the service endpoint. This can be implemented by letting the modules define the operations. Once the module is engaged to a service, the necessary operations will be added to that service.

A service, operations or the system may engage a module. Once the module is engaged the handlers and the operations defined in the module are added to the entity that engaged them.

Modules can not be added (no hot deployment) while the Axis2 engine is running, but they will be available once the system is restarted.

Deployment

The Deployment Model provides a concrete mechanism to configure Axis2. This model has three entities that provide the configuration.

The axis2.xml file

This file holds the global configuration for the client and server, and provide following information:

  1. The global parameters
  2. Registered transport-in and transport-outs
  3. User defined phase names
  4. Modules that are engaged globally (to all services)
  5. Globally defined Message Receivers

Service Archive

Service archive must have a META-INF/services.xml file and may contain the dependent classes. The services.xml file has following information.

  1. Service level parameters
  2. Modules that are engaged service level
  3. Service Specific Message Receivers
  4. Operations inside the service

Module Archive

Module archive must have a META-INF/module.xml file and dependent classes. The module.xml file has Module parameters and the Operations defined in the module.

When the system is starting up, Axis2 asks the deployment model to create an Axis Configuration. Deployment Model first finds the axis2.xml file and builds the global configuration. Then it checks for the module archives and then for the service archives. After that, the corresponding services and modules are added to the Axis Configuration. System will build contexts on top of the Axis Configuration. After this, Axis2 is ready to send or receive the SOAP messages. Hot deployment is only allowed for services.

Client API

There are three parameters that decide the nature of the Web service interaction.

  1. Message Exchange Pattern (MEP)
  2. The Behavior of the transport, whether it's One-Way or Two-Way
  3. Synchronous/ Asynchronous behavior of the Client API

Variations of the three parameters can result in indefinite number of scenarios, even though Axis2 is built on a core that support any messaging interaction, the developers were compelled to provie in-built support for only two most widely used Message Exchange Patterns (MEPs).

Two supported MEPs are One-Way and the In-Out (Request-Response) scenarios in the Client API. The implementation is based on a class called ServiceClient and there are extensions for each MEP that Axis2 Client API supports.

One Way Messaging Support

The One-Way support is provided by the fireAndForget method of ServiceClient. For one way invocations one can use HTTP , SMTP and TCP transports. In the case of the HTTP transport the return channel is not used and the HTTP 202 OK is returned in the return Channel.

In-Out (Request Response) Messaging Support

The In-Out support is provided by the sendReceive() method in ServiceClient. This provides a much simpler interface for the user. The Client API has four ways to configure a given Message Exchange

  1. Blocking or Non-Blocking nature - this can be decided by using sendReceive() or sendReceiveNonBlocking() methods
  2. Sender transport - transport used to send the SOAP Message
  3. Listener transport - transport the Response is received
  4. Use Separate Channel - determines whether the response is send over a separate transport connection or not. This can be false only when sender and listener transport is same and is a Two-Way transport.

Depending on the values of the above four parameters, Axis2 behaves differently.

Transports

Axis2 has two basic constructs for transports, namely; Transport Senders and Transport Receivers . These are accessed via the AxisConfiguration.

The incoming transport is the transport via which the AxisEngine receives the message. The outgoing transport is decided based on the addressing information (wsa:ReplyTo and wsa:FaultTo). If addressing information is not available and if server is trying to respond, then the out going transport will be the outputstream of the incoming transport (if it is two-way transport).

At the client side the user is free to specify the transport to be used.

Transport Senders and Transport Receivers contain following information.

  1. Transport Sender for Out Configuration
  2. Transport Listener for In Configuration
  3. Parameters of the transport

Each and every transport out configuration defines a transport sender. Transport sender sends the SOAP message, depending on its configuration.

Transport receiver waits for the SOAP Messages and for each SOAP Message that arrives, it uses the In Pipe to process the SOAP Message.

Axis2 presently support the following transports:

  1. HTTP - In HTTP transport the transport listener is a servlet or org.apache.axis2.transport.http.SimpleHTTPServer provided by Axis2. The transport sender uses commons-httpclient to connect and send the SOAP Message.
  2. TCP - This is the most simplest transport, but needs the WS - Addressing support to be functional.
  3. SMTP - This works off a single email account. Transport receiver is a thread that checks for emails in fixed time intervals.
  4. JMS

Code Generation

Although the basic objective of the code generation tools has not changed, the code generation module of Axis2 has taken a different approach to generate code. Primarily the change is in the use of templates, namely XSL templates which gives the code generator the flexibility to generate code in multiple languages.

The basic approach is to set the code generator to generate an XML and parse it with a template to generate the code file. The following figure describes how this shows up in the architecture of the tool.

The fact here is that it is the same information that is extracted from the WSDL no matter what code is generated. First, an AxisService is populated from a WSDL. Then the code generator extracts information from the AxisService and creates an XML which is language independent. This emitted XML is then parsed with the relevant XSL to generate code for the relevant language. No matter what the output language, the process is the same except for the template that is being used.

Data Binding

Integration with Code Generation Engine

Databinding for Axis2 is implemented in an interesting manner. Databinding has not been included in the core deliberately and hence the code geneation allows different data binding frameworks to be plugged in. This is done through an extension mechanism where the codegen engine calls extensions first and then executes the core emitter. The extensions populate a map of QNames vs. class names that is passed to the code generator on which the emitter operates on.

The following diagram shows the structure:

The following databinding extensions are available:

  1. ADB - ADB (Axis Data Binding ) is a simple framework that allows simple schemas to be compiled. It is lightweight and simple, works off StAX and fairly performant. However, it does not support the complete set of schema constructs and is likely to complain for certain schemas!
  2. XMLBeans - XMLbeans claims that it supports the complete schema specification and it is the choice, if full schema support is needed!
  3. JAX-Me - JaxMe support has been added in a similar manner to XMLbeans and serves as another option for the user
  4. JibX - This is the most recent addition to the family of databinding extensions and it is also another option the users have for data binding.

Serialization and De-Serialization of Data bound classes

AXIOM is based on a StAX API (Streaming API for XML). Xml-beans supports StAX API. Data binding in Axis2 is achieved through interfacing the AXIOM with the Xml-beans using the StAX API which is supported by both parties. At the time of the code generation there will be utility methods generated inside the stub (or the message receiver) that can de-serialize from AXIOM to data bound object and serialize from data bound object to AXIOM. For example, if the WSDL has an operation called "echoString", once the code is generated the following methods will be generated inside the relevant classes.

public static
org.apache.axiom.om.OMElement toOM(org.soapinterop.xsd.EchoStringParamDocument
param)// This method will handle the serialization.

public static org.apache.xmlbeans.XmlObject
fromOM(org.apache.axis2.om.OMElement param, java.lang.Class type) //This
method will handle the de-serialization.