Wednesday, September 30, 2009

Inter operating Apache Sandesah2 with WCF

Recently I have been working on interoperating WCF with the Apache Sandesha2. The good news is all the plain RM scenarios pass with some small fixings. Here is an sample client which can be used to invoke the wcf services available at http://131.107.72.15/endpoints/

First I generated the code for the given wsdl with wsdl2java tool with the following arguments

-uri http://10.100.1.238/ReliableMessaging_Service_WSAddressingAugust2004_Indigo/RequestReply.svc?wsdl
-u -ap -uw

-p org.wso2.carbon.interop.microsoft.rm.requestreply

-o target/generated-code

-Emp org.wso2.carbon.interop.microsoft.rm.requestreply

-ns2p http://tempuri.org/=org.wso2.carbon.interop.microsoft.rm.requestreply,http://schemas.microsoft.com/2003/10/Serialization/=org.wso2.carbon.interop.microsoft.rm.requestreply.types

Then we can simple invoke the service using the following client code.

// creating an configuration context which contains sandesah2 and addressing
ConfigurationContext configurationContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem("target" + File.separator +
"org.wso2.carbon.interop.microsoft.rm-SNAPSHOT.dir" +
File.separator + "repository");

EchoStringServiceCustomBinding_IEchoString9Stub stub = new EchoStringServiceCustomBinding_IEchoString9Stub(configurationContext,
"http://131.107.72.15/ReliableMessaging_Service_WSAddressingAugust2004_Indigo/RequestReply.svc/Reliable_Anonymous_Soap11_WSAddressingAugust2004_RM11");
// this is to send messages through tcp mon
stub._getServiceClient().getOptions().setProperty(Constants.Configuration.TRANSPORT_URL,
"http://localhost:8088/ReliableMessaging_Service_WSAddressingAugust2004_Indigo/RequestReply.svc/Reliable_Anonymous_Soap11_WSAddressingAugust2004_RM11");

// setting the correct addressing , soap and rm versions
stub._getServiceClient().getOptions().setProperty(AddressingConstants.WS_ADDRESSING_VERSION, AddressingConstants.Submission.WSA_NAMESPACE);
stub._getServiceClient().getOptions().setSoapVersionURI(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);
stub._getServiceClient().getOptions().setProperty(SandeshaClientConstants.RM_SPEC_VERSION, Sandesha2Constants.SPEC_VERSIONS.v1_1);

//wcf does not support make connections so disable it
Parameter sandeshaPolicyBeanParam = stub._getServiceClient().getAxisConfiguration().getParameter(Sandesha2Constants.SANDESHA_PROPERTY_BEAN);
if (sandeshaPolicyBeanParam != null) {
SandeshaPolicyBean sandeshaPolicyBean = (SandeshaPolicyBean) sandeshaPolicyBeanParam.getValue();
sandeshaPolicyBean.setEnableMakeConnection(false);
}

stub._getServiceClient().engageModule("addressing");
stub._getServiceClient().engageModule("sandesha2");

PingRequestBodyType pingRequestBodyType = new PingRequestBodyType();
pingRequestBodyType.setSequence("Sequence 1");
pingRequestBodyType.setText("testparam");
PingResponseBodyType pingResponseBodyType = null;
String responseString = "";
for (int i = 0; i < 3; i++) {
responseString += "testparam";
pingResponseBodyType = stub.echoString(pingRequestBodyType);
}

// after sending the messages we can close and terminate the sequence
SandeshaClient.closeSequence(stub._getServiceClient());
SandeshaClient.terminateSequence(stub._getServiceClient());

//wait until terminate sequence messge is send
SandeshaClient.waitUntilSequenceCompleted(stub._getServiceClient());

Sunday, September 27, 2009

Handling date and dateTime with Axis2

With Axis2 1.5 java.util.Date is mapped to xs:date type and java.util.Calendar is mapped to xs:dateTime. For an example if we deployed a POJO service as follows

public class TestService {

public Date getDate() {
return new Date();
}

public Calendar getCalendar() {
return Calendar.getInstance();
}
}

This generates an WSDL with schema like this.

<xs:element name="getDateResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="return" nillable="true" type="xs:date"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getCalendarResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="return" nillable="true" type="xs:dateTime"/>
</xs:sequence>
</xs:complexType>
</xs:element>
When invoking the service we get the following response xmls

<ns:getDateResponse xmlns:ns="http://service.lockhead.test"><ns:return>2009-09-28</ns:return></ns:getDateResponse>
<ns:getCalendarResponse xmlns:ns="http://service.lockhead.test"><ns:return>2009-09-28T10:55:01.770+05:30</ns:return></ns:getCalendarResponse>

Thursday, September 24, 2009

Sending an arbitrary soap message with Axis2

Axis2 code generation strictly follows the WS-I profile which prohibits sending soap messages with two child elements in the soap body. Even normal Service client API allows only one omElement to be send at the soap body.
One work around to send two elements is to use an operation client which allows a user to set whole SoapEnvelope hence sending any arbitrary one.

ServiceClient serviceClient = new ServiceClient();
OperationClient opClient = serviceClient.createClient(ServiceClient.ANON_OUT_IN_OP);
//creating message context
MessageContext outMsgCtx = new MessageContext();
Options opts = outMsgCtx.getOptions();
//setting properties into option
opts.setTo(new EndpointReference("http://localhost:8088/axis2/services/TestInOutService"));
opts.setAction("urn:TestInOutService");

SOAPFactory soapFactory = OMAbstractFactory.getSOAP11Factory();
SOAPEnvelope soapEnvelope = soapFactory.getDefaultEnvelope();

OMElement omElement1 = soapFactory.createOMElement(new QName("http://axis2.test","firstElement"));
OMElement omElement2 = soapFactory.createOMElement(new QName("http://axis2.test","secondElement"));

soapEnvelope.getBody().addChild(omElement1);
soapEnvelope.getBody().addChild(omElement2);

outMsgCtx.setEnvelope(soapEnvelope);
opClient.addMessageContext(outMsgCtx);
opClient.execute(true);

MessageContext inMsgtCtx = opClient.getMessageContext("In");

SOAPEnvelope response = inMsgtCtx.getEnvelope();
System.out.println(response);