Introduction

The purpose of this page is to illustrate one way of using the WS-FX Addressing code to setup and process WS-Addressing headers.

The Apache WS-FX/Addressing project processes WS-Addressing headers through Axis client and server side handlers.

Deploying a Service

The example below shows a sample deploy.wsdd file that sets up the addressing handlers for the Version webservice. To differentiate from the existing Version service, we call this service AddressedVersion.

Note : This webservice is exactly the regular Version service that comes with Axis, but just has handlers to process WS-Addressing headers.

<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

  <handler
    name="addr" 
    type="java:org.apache.axis.message.addressing.handler.AddressingHandler" />

  <service name="AddressedVersion" provider="java:RPC">
    <requestFlow>
      <handler type="addr"/>
    </requestFlow>
    <responseFlow>
      <handler type="addr"/>
    </responseFlow>

    <parameter name="allowedMethods" value="getVersion"/>
    <parameter name="className" value="org.apache.axis.Version"/>
  </service>
</deployment>

When Axis's AdminClient is run on this deploy.wsdd file (refer to Axis documentation for more details), the AddressedVersion service gets deployed.

Invoking a Service

The example below shows a sample Axis client (using DII) and a corresponding client-config.wsdd file. The Axis client engine loads the client-config.wsdd file from the current (local) directory and uses this to set up WS-Addressing headers.

/*
 * Example VersionClient
 */
import javax.xml.namespace.QName;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.message.addressing.Action;
import org.apache.axis.message.addressing.AddressingHeaders;
import org.apache.axis.message.addressing.Constants;
import org.apache.axis.message.addressing.EndpointReference;
import org.apache.axis.types.URI;

/**
 * Class : VersionClient
 */
public class VersionClient {

  static String url = "http://localhost:8080/axis/services/AddressedVersion";

  public static void main(String[] args) throws Exception {
    Service service = new Service();
    Call call = (Call) service.createCall();
    AddressingHeaders headers = setUpAddressing();
    call.setProperty(Constants.ENV_ADDRESSING_REQUEST_HEADERS, headers);
    call.setTargetEndpointAddress(new java.net.URL(url));
    call.setOperationName(new QName(
        "http://localhost:8080/axis/services/Version", "getVersion"));
    String ret = (String) call.invoke(new Object[] {});
    System.out.println("Sent 'Hello!', got '" + ret + "'");
  }

  private static AddressingHeaders setUpAddressing() throws Exception {
    AddressingHeaders headers = new AddressingHeaders();
    Action a = new Action(new URI("urn:action"));
    headers.setAction(a);
    EndpointReference epr = new EndpointReference("http://www.apache.org");
    headers.setFaultTo(epr);
    return headers;
  }
}

The code is very much like any regular Axis client; however, in this case, we set a property in the Call object whose value is equal to the AddressingHeaders instance we want to setup. The two lines shown below achieve that:

  AddressingHeaders headers = setUpAddressing();
  call.setProperty(Constants.ENV_ADDRESSING_REQUEST_HEADERS, headers);

In the setUpAddressing method, it is possible to set up other fields of the headers as well. If not set, the Apache implementation uses defaults. It is important to set up the Action field alone, since the implementation does not set a default for that.

The client-config.wsdd file is shown below

<deployment name="test"
            xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
  <handler
    name="addr" 
    type="java:org.apache.axis.message.addressing.handler.AddressingHandler" />

  <globalConfiguration>
    <requestFlow>
      <handler type="addr"/>
    </requestFlow>
    <responseFlow>
      <handler type="addr"/>
    </responseFlow>
  </globalConfiguration>

  <transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"/>
  <transport name="local" pivot="java:org.apache.axis.transport.local.LocalSender"/>
  <transport name="java" pivot="java:org.apache.axis.transport.java.JavaSender"/>
</deployment>

Note : While running AdminClient to deploy the AddressedVersion service, ensure that it is not run from the directory having the client-config.wsdd file. I did it and had to debug my problems.

Addressing Handler Configuration

The WS-Addressing specification describes a SOAP binding for Endpoint references, whereby reference properties are encoded as direct SOAPHeaderElements . The problem with this approach is that there is no way for a deserializer engine to know whether a particular header element is a reference property or not. If the engine takes the approach of treating all non WS-Addressing headers as reference properties, we run the risk of consuming headers belonging to other protocols. Not deserializing it means the webservice implementation has to read header elements on its own - not very convienient.

This implementation allows deployers to configure which approach they need. By setting a handler property called 'referencePropertyNames', the handler can be instructed on the approach it needs to follow. If this property is not set, the default behavior is for the handler to ignore all non-wsaddressing headers. This property could be set to a '*' which means all non-wsaddressing headers will be treated as reference properties. It could also be set to a comma-separated list of QNames in the form {namespace}localname.

The deploy.wsdd snippet below, configures the handler to process all headers (by setting the property value to '*'. The stuff in comments shows how the handler can be configured to process specific reference properties. Also note that this property makes sense only with deserialization. Serialization of reference properties does not have any ambiguity.

<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

  <handler
    name="addr" 
    type="java:org.apache.axis.message.addressing.handler.AddressingHandler">

    <!-- configure handler to process all headers -->
    <parameter name="referencePropertyNames" value="*"/>

    <!--
      configure handler to process specific reference prop elements
      each item in the value represents a QName
    <parameter
       name="referencePropertyNames"
       value="{http://blah}duh, {http://don}dude, {http://fabrikam.com}CustomerKey"/>
    -->
  </handler>

  <service name="AddressedVersion" provider="java:RPC">
    <requestFlow>
      <handler type="addr"/>
    </requestFlow>
    <responseFlow>
      <handler type="addr"/>
    </responseFlow>

    <parameter name="allowedMethods" value="getVersion"/>
    <parameter name="className" value="org.apache.axis.Version"/>
  </service>
</deployment>