Invoking Web Services using Apache Axis2 Blog


    Apache Axis2 is the successor to the renowned Apache Axis SOAP project. Axis2 is a major improvement of the web services core engine and aims to be the platform to build applications based on service oriented architecture (SOA). It is blazing the trail by being a clean and extensible open source web services platform. The architecture of Axis2 is highly flexible and supports additional functionalities, features and enhancements such as:

    • AXIOM (AXIs2 Object Model), a new XML infoset representation with streaming support
    • An improved client with both synchronous and asynchronous support
    • Native support for MTOM (Message Transmission Optimization Mechanism)
    • Full support for WSDL 2.0 defined MEPs (Message Exchange Patterns)

    This document is mainly focused on Axis2 client-related technologies and their usage. At the end this article, you should understand the key terminologies and concepts, and most importantly how to use Axis2 client for your SOA applications.

    The Axis2 Client API

    There are two main usage patterns for Axis2. One is as a server to deploy web services and the other as a client to invoke services. When it comes to the client side, there are numerous requirements to cater to in today's web services. Asynchronous or non-blocking invocation patterns are assumed to be at the top of this requirements list. As stated above, one of the key feature in Axis2 is asynchronous web service invocation support. If you are not familiar with synchronous and asynchronous web service invocation, Figures 1 and 2 will help you to understand them. In the synchronous (blocking) case, a client sends the message and waits until it receives a response, while in an asynchronous (non-blocking) invocation, the client sends the message but does not wait for the response. For asynchronous uses, there will be some other mechanism (such as callback or pooling) to receive the response; Axis2 uses callback mechanisms in asynchronous web service invocations.

    Invoking a service in a synchronous manner
    Figure 1. Invoking a service in a synchronous manner

    Invoking a service in asynchronous manner
    Figure 2. Invoking a service in an asynchronous manner

    In addition to synchronous and asynchronous invocations, the client API has been divided into two main sub-APIs:

    • An easy-to-use API for average users:ServiceClient
    • An API for advanced tasks: OperationClient

    Working withServiceClient

    As mentioned above, the ServiceClient API provides an easy way of invoking services for average users. Axis2 assumes that an average user is a person who just cares about the payload (i.e., the SOAP body) of the message and nothing else. Advanced users are considered to be the those who deal not only with the payload but also with the full SOAP envelope.

    Using ServiceClient, you can invoke a service in a synchronous manner or in an asynchronous manner, which will be discussed later.

    To give better flexibility, ServiceClient provides a set of different constructors from which you can pick the correct constructor to cater to your requirements. For eachServiceClient you create, there has to be an Axis2 runtime to invoke the service. An Axis2 runtime is called aConfigurationContext and it consists of configurations, parameters, and other relevant data. Semantically,ConfigurationContext is similar toServletContext in an application server.

    Creating a ServiceClient using Its Default Constructor

    The easiest way to create a ServiceClient is to use its default constructor as shown below. In this case, it creates aConfigurationContext using the Axis2 default configuration file. Even if you create ServiceClientin this manner, you can use it to invoke any available web service.

    ServiceClient serviceClient = new ServiceClient ();

    One important point to note here is that if you try to create an instance of ServiceClient using the above constructor inside a running Axis2 server (or inside an application server where Axis2 is deployed), then rather than creating aConfigurationContext from the Axis2 default configuration, it uses the server's runtime as itsConfigurationContext. In that case, the client will have the luxury of accessing server's configuration data.

    Creating a ServiceClient using Your own ConfigurationContext

    There are many instances where you want to share the same Axis2 runtime across multiple clients or want to reuse the same runtime for every invocation. Also, maybe you do not like Axis2 default configuration and you want to create aConfigurationContext instance using your own configurations. In such situations it is best to use the following constructor.

    ServiceClient serviceClient = new ServiceClient (configContext, axisService);

    As you can see in the constructor, it takes two arguments,ConfigurationContext and AxisService. TheAxisService is a metadata representation of a web service in Axis2. On the client side, you do not need to worry too much about this. The idea of the AxisService argument is to provide a configured service proxy, which most of the time you are not going to use. So when you use this constructor, you can pass null for the AxisServiceargument.

    Creating a Dynamic Client

    The idea of a dynamic client is to create aServiceClient on the fly, or simply create a client for a given WSDL at runtime and use the createdServiceClient instance to invoke the corresponding service (the service corresponding to the WSDL). When you create the ServiceClient in this manner, it will create and configure a service proxy inside the client. The constructor for creating a dynamic client is as follows:

    ServiceClient dynamicClient = new ServiceClient( configContext, wsdlURL, wsdlServiceName, portName);
    • configContext: TheConfigurationContext you want to use, which can benull. If it is null, thenConfigurationContext will be created either using Axis2's default configuration or will use the server'sConfigurationContext.

    • wsldURL: This argument specifies the URL for the WSDL file and should not be null.

    • wsdlServiceName: A WSDL document might have multiple service elements, so if you want to pick a specific service element, then you can pass the QName of that service element or just pass null if you do not care about it. If the value is null, then the first entry in the service element list will be considered as the service element.

    • portName: A service element in a WSDL file could have multiple ports. So if you want to select a specific port, then you can pass the name of the port as value for this argument. Then again, if the value is null, the first one from the port list will be selected as the port.

    Sample WSDL to understand above service elements and ports is shown below:

    <wsdl:service name="MyService"> <wsdl:port name="ServicePort1" binding="axis2:ServiceBinding1"> <soap:address location=""/> </wsdl:port> <wsdl:port name="ServicePort2" binding="axis2: ServiceBinding2 "> <soap12:address location=""/> </wsdl:port> </wsdl:service>

    Working Samples withServiceClient

    There is nothing like code to explain. So the best way to understand ServiceClient API is to write a few real-world samples. Before writing client code, you need to start the Axis2 server and deploy the MyService.aar found in theResources section of this article.

    To understand the usage of ServiceClient, let's try to write some scenarios to invoke the service above.

    Scenario 1. Invoking the service in a blocking manner (sendReceive())

    The most common service invocation pattern is the request-response (called "in-out MEP" in WSDL 2.0 terminology). With Axis2 you can invoke in-out MEP in either a blocking manner or a non-blocking manner. The first sample invokes a service in blocking manner.

    Step 1. Create an instance ofServiceClient using any of the above constructors.

    Step 2. Create an OMElement for payload (request SOAP body, or the message). As stated in the introduction, XML representation in Axis2 is completely based on AXIOM, soOMElement is the XML element representation of AXIOM.

    You can use following code snippet to create the payload. You do not need to pay much attention to AXIOM here. To work in Axis2, one of the prerequisites is to have a good understanding about AXIOM, so check out the AXIOM tutorial to learn more about it.

    public OMElement createPayLoad() { OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace( "", "ns1"); OMElement method = fac.createOMElement("echo", omNs); OMElement value = fac.createOMElement("value", omNs); value.setText("Hello , my first service utilization"); method.addChild(value); return method; }

    Step 3. To invoke the service, you need to provide parameters such as endpoint address, SOAP Action, etc. For that, you need to create an instance of Option, which is a metadata representation for a particular invocation. The following code snippet shows you how to create an option object and fill it.

    ServiceClient client = new ServiceClient(); // create option object Options opts = new Options(); //setting target EPR opts.setTo(new EndpointReference("")); //Setting action ,and which can be found from the wsdl of the service opts.setAction("urn:echo"); //setting created option into service client sc.setOptions(opts);

    If you create a ServiceClient as a dynamic client, then you do not need to create an option object. It is automatically created.

    Step 4. sendReceive is theServiceClient API for invoking a service in blocking manner.

    OMElement res = sc.sendReceive(createPayLoad()); System.out.println(res);

    Once you run this sample code you will get the following output:

    <ns:echoResponse xmlns:ns=""> <ns:return>Hello , my first service utilization</ns:return> </ns:echoResponse>

    The above XML segment is called the response payload. You can find the complete source code for this scenario inside the, found in theResources section below.

    Scenario 2. Invoking a service in a non-blocking manner (sendReceiveNonBlocking())

    To invoke an in-out MEP in an asynchronous manner, you can use this API. As mentioned above, Axis2 uses a callback mechanism to provide asynchronous support; hence, you need to have an instance of org.apache.axis2.client.async.Callback to use this API.

    In this scenario, you could follow Steps 1 to 3 from Scenario 1 without any modification; the changes are in Step 4.

    Step 4. Invoking the service, first create an anonymous callback object.

    //creating an anonymous callback object Callback callback = new Callback() { public void onComplete(AsyncResult result) { System.out.println( result.getResponseEnvelope().getBody().getFirstElement()); } public void onError(Exception e) { e.printStackTrace(); } }; //invoking the service sc.sendReceiveNonBlocking(createPayLoad(), callback);

    Once you run the code sample, you should get the following output:

    -------Invoke the service--------- <ns:echoResponse xmlns:ns=""> <return>Hello , my first service utilization</return> </ns:echoResponse>

    The key differences in Scenarios 1 and 2 are as follows:

    • In Scenario 2, need to create callback object.
    • sendReceiveNonBlocking is a void operation.

    You can find the complete source code for this scenario inside the

    Scenario 3. Invoking a service using two transports

    With minor modifications you can use Scenario 1 or Scenario 2 to send the request using one transport and receive via some other transport (for example, sending via HTTP and receiving via TCP). The scenario can be represented graphically, as shown in Figure 3.

    Service invocation with two transports
    Figure 3. Service invocation with two transports

    To invoke a service in the above manner, you need to have WS-Addressing support; therefore, you need to engage the addressing module on both the client and sever sides.

    By changing Step 3 in the following manner, you can invoke the service via two transports. Let's send a request via HTTP and try to get the response via TCP.

    ServiceClient client = new ServiceClient(); Options opts = new Options(); opts.setTo(new EndpointReference( "")); //engaging addressing module 
    client.engageModule(new QName("addressing")); // I need to use separate listener for my response 
    opts.setUseSeparateListener(true); // Need to receive via TCP 
    opts.setTransportInProtocol(Constants.TRANSPORT_TCP); opts.setAction("urn:echo"); client.setOptions(opts);

    One thing to notice here is that you need to dropaddressing-1.1.mar (found in the Resources section) into your classpath). The classpath in this case is the location where you have your Axis2 .jar files, so drop the addressing .mar file into the same folder. You can find the complete source code for this scenario inside file.

    Scenario 4. Invoke an in-only MEP (fireAndForget())

    If you want to send data to a server without worrying about getting a response or exceptions, then you could use the "fire and forget" approach. Let's try to invoke the pingoperation in MyService.

    Step 1. Create a ServiceClient.

    Step 2. Create the payload OMElement. Here the payload section is a bit different compared to the above; specifically, the operation name is changed from echoto ping.

    public OMElement createPayLoad() { OMFactory fac = OMAbstractFactory.getOMFactory(); OMNamespace omNs = fac.createOMNamespace( "", "ns1"); OMElement method = fac.createOMElement("ping", omNs); OMElement value = fac.createOMElement("value", omNs); value.setText("10"); method.addChild(value); return method; }

    Step 3. When you run the following code, you will see the message "I got this value : Hello there" in the server's console, and you don't get any response or exception, even if something goes wrong in the server.

    ServiceClient client = new ServiceClient(); Options opts = new Options(); opts.setTo(new EndpointReference("")); 
    opts.setAction("urn:ping"); client.setOptions(opts); 

    Replace setTo with an invalid one and see whether you are getting any exception.

    Scenario 5: Invoking an in-only MEP (sendRobust())

    This API also offers one-way operation; the key difference from Scenario 4 is that if something goes wrong in the server, the client will be informed. You can use Scenario 4 code with a minor change to invoke the service in a robust manner. Steps 1 and 2 of Scenario 4 remain unchanged and Step 3 needs the following changes.

    ServiceClient client = new ServiceClient(); Options opts = new Options(); opts.setTo(new EndpointReference( "")); opts.setAction("urn:ping"); client.setOptions(opts); 

    Replace setTo with an invalid one and see whether you get an exception.

    You can find the complete source code for this scenario

    Working withOperationClient

    As you already know from ServiceClient, you have access to payload on both the sending and receiving sides, but that is not enough if you are trying to implement enterprise-level web applications where you will need to have more control. In those cases you might want to add custom headers to the outgoing SOAP message, access the incoming SOAP process directly, or access incoming and outgoing message contexts. However, withServiceClient you can do none of these. The solution is to use OperationClient for those scenarios. Let's invoke the echo operation usingOperationClient to better understand this API.

    Unlike ServiceClient, you do not have multiple ways of creating OperationClient; there is only one way. First create a ServiceClient, and then createOperationClient using that.

    Step 1. Create a ServiceClientinstance.

    ServiceClient client = new ServiceClient();

    Step 2. Create an OperationClient.

    OperationClient operationClient = client.createClient( ServiceClient.ANON_OUT_IN_OP);

    The constant ANON_OUT_IN_OP is the name of an anonymous operation, used when you createServiceClient using its default constructor.

    Step 3. Create a MessageContext (runtime representation of a particular message) and set properties on its option object:

    /creating message context MessageContext outMsgCtx = new MessageContext(); //assigning message context’s option object into instance variable Options opts = outMsgCtx.getOptions(); //setting properties into option opts.setTo(new EndpointReference( "")); opts.setAction("urn:echo");

    Step 3. Create a SOAPEnvelope and add that to the message context. This time, you need to create a full SOAP envelope, whereas in previous cases you had the luxury of just creating the SOAP body or the payload.


    The createSOAPEnvelope method will look like this:

    public SOAPEnvelope creatSOAPEnvelope() { SOAPFactory fac = OMAbstractFactory.getSOAP11Factory(); SOAPEnvelope envelope = fac.getDefaultEnvelope(); OMNamespace omNs = fac.createOMNamespace( "", "ns1"); // creating the payload OMElement method = fac.createOMElement("echo", omNs); OMElement value = fac.createOMElement("echo", omNs); value.setText("Hello"); method.addChild(value); envelope.getBody().addChild(method); return envelope; }

    Step 4. Add a message context tooperationClient:


    Step 5. To send the message, you need to call theexecute method in operationClient:


    The Boolean argument to this method indicates whether you want to invoke in a blocking manner (true) or non-blocking manner (false).

    Step 6. Access response message context and responseSOAPEnvelope:

    //pass message label as method argument MessageContext inMsgtCtx = operationClient.getMessageContext("In"); SOAPEnvelope response = inMsgtCtx.getEnvelope(); System.out.println(response);

    When you are invoking an in-out MEP as in this sample, the message label of the request is "Out" and value of the response is "In," which is why you have to pass "In" as a message label value to get the response message context. Once you have the message context, you can use that to access SOAPEnvelope, properties, transport headers, etc.

    When you run this code sample you should get the following as console output:

    <?xml version='1.0' encoding='utf-8'?> <soapenv:Envelope xmlns:soapenv=""> <soapenv:Header/> <soapenv:Body> <ns:echoResponse xmlns:ns=""> <ns:return>Hello</ns:return> </ns:echoResponse> </soapenv:Body> </soapenv:Envelope>

    Again you can find the complete source code for this scenario inside file.


    The Axis2 client API is very convenient and it has cool features like asynchronous web service utilization, multiple transport selection, and so on. Once you run the samples you will understand the basics of the Axis2 client API. To understand the rest of the API you need to write complex code. Good luck!