Popular Posts

Sunday, October 12, 2008

How to add a custom SOAP header to the request using AXIOM

Suppose you want to add the following SOAP header block to your web service request message.
<myNS:header xmlns:myNS="http://ws.org">
This is a custom soap header
</myNS:header >

There are different approaches to add user defined headers to the request soap messages. Lets see how it could be done using AXIOM in simpler way.
In this example we are going to invoke Axi2 default version service with adding a custom soap header in to the request.

Pre-requisites
Download and install Apache Axis2
Install Apache Tcpmon

Step 1

Start Axis2 server by running AXIS2_HOME/bin/axis2server.bat{sh}
Go to http://localhost:8080. You will see that the default version service is deployed there.

Step 2

Now, we need to generate client stubs. Go to AXIS2_HOME/bin and run wsdl2java.bat{sh} with the following parameters.
WSDL2Java -uri http://localhost:8080/axis2/services/Version?wsdl -o out -uw

The client stubs will be generated in a directory called "out".

Now, write a client importing the generated stub classes as follows(You can easily create a project in Eclipse using the generated Build.xml)

import java.rmi.RemoteException;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.AxisFault;
import sample.axisversion.ExceptionException0;
import sample.axisversion.VersionStub;


public class CustomSoapHeaderClient {

public static void main(String[] args) throws AxisFault{

String url = "http://localhost:8090/axis2/services/Version";
VersionStub stub = new VersionStub(url);

OMFactory omFactory =OMAbstractFactory.getOMFactory();
OMNamespace omNamespace = omFactory.createOMNamespace("http://ws.org", "myNS");
OMElement header = omFactory.createOMElement("header", omNamespace);
header.setText("This is a custom soap header");
stub._getServiceClient().addHeader(header);

try {
System.out.println(stub.getVersion());
} catch (RemoteException e) {
e.printStackTrace();
} catch (ExceptionException0 e) {
e.printStackTrace();
}
}


}

Note the highlighted code which creates the custom soap header.

Step 3

We can visualize the soap request using Tcpmon. Therefore open tcpmon and configure listen port in 8090 and target port 8080.
Compile and run the above client. You will see the following message in request pane of Tcpmon.

<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header>
<myNS:header xmlns:myNS="http://ws.org">This is a custom soap header</myNS:header>


6 comments:

Mari Raja said...

Hi Charitha,

I used ur code. But I am getting the following error,

org.apache.axis2.AxisFault: Missing wsse:Security header in request
at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:512)
at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:370)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:416)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:228)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)

How can I fix it. Please help me.

Thanks,
Mari Raja.

Charitha said...

Hi Mari,
It seems you have engaged "apache rampart" module at your web service. If you did so, you must have the necessary security policies at the client side.

Regards
Charitha

Mari Raja said...

Hi Charitha,

Thanks for reply.

Yes Charitha.I am using apache rampart module at my webservice.

In server side, I added my security policy on services.xml.


But in the client side, where can I add my security policy ?

This is my client code :

OMFactory omFactory = OMAbstractFactory.getOMFactory();
OMElement omSecurityElement = omFactory.createOMElement
(new QName( "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security", "wsse"), null);

OMElement omusertoken = omFactory.createOMElement
(new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "UsernameToken", "wsu"), null);

OMElement omuserName = omFactory.createOMElement
(new QName("", "Username", "wsse"), null);
omuserName.setText("administrator");

OMElement omPassword = omFactory.createOMElement
(new QName("", "Password", "wsse"), null);
omPassword.addAttribute("Type","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText",null );
omPassword.setText("passw0rd");

omusertoken.addChild(omuserName);
omusertoken.addChild(omPassword);
omSecurityElement.addChild(omusertoken);
cewsClientStub._getServiceClient().addHeader(omSecurityElement);


But still I am getting the same exception. Please help me.


Thanks,
Mari Raja.

Charitha said...

Hi,
If you are using a security policy at the service level, do not construct the security headers manually at the client side. Point to the relevant client policy as explained in http://charithaka.blogspot.com/2008/03/secure-web-services-signing-soap.html

Ex:-

serviceClient.engageModule("rampart");

Options options = serviceClient.getOptions();
options.setProperty(RampartMessageData.KEY_RAMPART_POLICY, loadPolicy("C:\\wsas\\client-epo\\policy.xml"));
serviceClient.setOptions(options);

private static Policy loadPolicy(String xmlPath){
StAXOMBuilder builder = new StAXOMBuilder(xmlPath);
return PolicyEngine.getPolicy(builder.getDocumentElement());
}

Mari Raja said...

Thanks charitha. It is working fine. Thanks for ur help.

A.MariRaja

vishnu said...

Hi Charitha

I have somewhat different issue I am using Rampart for WS-Security and sign body using a signature given by third party and request message has security headers corresponding to it. But response doesn't have security headers which should be fine but Rampart complains about security headers not being found in response. If you encountered or know something about this could you please post the response. All your help is highly appreciated.

for your info stacktrace

[java] log4j:WARN No appenders could be found for logger (org.apache.axis2.deployment.FileSystemConfigurator).
[java] log4j:WARN Please initialize the log4j system properly.
[java] Exception in thread "main" org.apache.axis2.AxisFault: Missing wsse:Security header in request
[java] at org.apache.rampart.handler.RampartReceiver.setFaultCodeAndThrowAxisFault(RampartReceiver.java:166)
[java] at org.apache.rampart.handler.RampartReceiver.invoke(RampartReceiver.java:99)
[java] at org.apache.axis2.engine.Phase.invoke(Phase.java:318)
[java] at org.apache.axis2.engine.AxisEngine.invoke(AxisEngine.java:251)
[java] at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:160)
[java] at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:364)
[java] at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:417)
[java] at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229)
[java] at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
[java] at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:539)
[java] at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:520)
[java] at org.apache.rampart.samples.policy.sample03.Client.main(Unknown Source)
[java] Caused by: org.apache.rampart.RampartException: Missing wsse:Security header in request
[java] at org.apache.rampart.RampartEngine.process(RampartEngine.java:117)
[java] at org.apache.rampart.handler.RampartReceiver.invoke(RampartReceiver.java:92)
[java] ... 10 more

-Vishnu