The purpose of this document 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, process addressing headers through
Axis client side and server side handlers.
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.
When Axis's AdminClient is run on this deploy.wsdd file (refer to axis
documentation for more details), the AddressedVersion service gets deployed.
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
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.
Note about serialization of reference properties : 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 web
service 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.
Note : This implementation needs a version of Xerces in the classpath
(not specified elsewhere). If you use the default JDK 1.4 XML parsers (by not
adding a specific parser implementation to your classpath), the following
code in org.apache.axis.message.addressing.util.TextExtractor (in the getText(Node) method throws
a classcast exception.
Document doc = node.getOwnerDocument();
DocumentTraversal traversable = (DocumentTraversal) doc;
This is because the Crimson implementation of Document does not implement the
DocumentTraversal interface.