Pages

Sunday, August 29, 2010

Xfire work around when not all WSDL operations are in the client Interface

One of the major challenges for a project is the when we start integration testing with the client. No matter how much precaution we take there will be some surprises. One of our clients changed there wsdl at the last moment.The change is very simple, they combined their multiple webservices together in to a single wsdl. So in effect we have to care only few of the wdsl operations. uha... Xfire is expecting all the wsdl operations in the client interface. How can we solve this... Finally we solved it by deploying a local copy of  their wsdl removing the unnecessary  operations from it. So Xfire client will think that its looking at the real wsdl and the interface has all the operations defined. In order to do this we created a .war directory and put the local wsdl in it and deploy it. From the Xfire client point to this wsdl.

Orginal Client WSDL( other details omitted)

<wsdl:operation name="Sample1">
         <soap:operation soapAction="http:xx/sample1" style="document"/>
         <wsdl:input>
            <soap:body use="literal"/>
         </wsdl:input>
         <wsdl:output>           
<soap:body use="literal"/>
        </wsdl:output>
         <wsdl:fault name="CommunicationExceptionFault">
            <soap:fault name="CommunicationExceptionFault" use="literal"/>
         </wsdl:fault>
         <wsdl:fault name="InvalidOperationExceptionFault">
            <soap:fault name="InvalidOperationExceptionFault" use="literal"/>
         </wsdl:fault>
      </wsdl:operation>
   </wsdl:binding>
<wsdl:operation name="sample2">
         <soap:operation soapAction="http:xx/sample2" style="document"/>
         <wsdl:input>
            <soap:body use="literal"/>
         </wsdl:input>
         <wsdl:output>
            <soap:body use="literal"/>
         </wsdl:output>
         <wsdl:fault name="CommunicationExceptionFault">
            <soap:fault name="CommunicationExceptionFault" use="literal"/>
         </wsdl:fault>
         <wsdl:fault name="InvalidOperationExceptionFault">
            <soap:fault name="InvalidOperationExceptionFault" use="literal"/>
         </wsdl:fault>      </wsdl:operation>
   </wsdl:binding>
LocalCopy  (We are only interested in operation sample1)
localClient.wsdl
<wsdl:operation name="Sample1"><br />
         <soap:operation soapAction="http:xx/sample1" style="document"/><br />
         <wsdl:input><br />
            <soap:body use="literal"/><
         </wsdl:input><br />
         <wsdl:output><br />
            <soap:body use="literal"/>&lt
         </wsdl:output><
         <wsdl:fault name="CommunicationExceptionFault"
            <soap:fault name="CommunicationExceptionFault" use="literal"/>
         </wsdl:fault>
         <wsdl:fault name="InvalidOperationExceptionFault">
            <soap:fault name="InvalidOperationExceptionFault" use="literal"/>
         </wsdl:fault>
      </wsdl:operation>
   </wsdl:binding>

And the web service client will be defined as :
<bean id="sampleClient" parent="abstractsampleClient">
        <property name="serviceInterface"
                  value="com.testsample.SampleController" />
        <property name="wsdlDocumentUrl"
                  value="http://localhost/mock-client-wsdl/localClient.wsdl" />
    </bean>

 Note: localClient.wsdl file will be created in a directory  mock-client-wsdl.war and deployed in the server  so that it will act as external .wsdl file

Consider this:
 1) Keeping a local copy of the client wsdl is not always a good idea.
 2)Because of this complexity the application maintainability will be tough with out proper documentation

However this is the simplest work around to make it work....

Sunday, August 22, 2010

Sharing Properties in Spring and Ant

Sharing properties among different modules of application is a big topic of discussion. Its very important for changing the properties per environment while production deployment and also effectively  testing the application pointing to or injecting  a mock implemention . One of many advantages of spring frame work is this testing flexibility.We can even test the production using the mock objects. In order to get these full benefit we need to use PropertyPlaceholderConfigurer class from spring frame work.

1. Define sample.properties
jdbc.driver=org.hsqldb.jdbcDriver
2. Set up PropertyPlaceholderConfigurer
  <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:bin/sample.properties" />
</bean>

3.Use them as follows
 <bean
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"><value>${jdbc.driver}</value></property>
...
...
</bean>

This class resolves placeholders in bean property values of context definitions. It pulls values from a properties file into bean definitions.The default placeholder syntax follows the Ant / Log4J / JSP EL style:  ${...}. If you want to check against multiple properties files, specify multiple resources via the "locations" setting. You can also define multiple PropertyPlaceholderConfigurers, each with its own placeholder syntax. Default property values can be defined via "properties", to make overriding definitions in properties files optional. A configurer will also check against system properties (e.g. "user.dir") if it cannot resolve a placeholder with any of the specified properties. This can be customized via "systemPropertiesMode". Property values can be converted after reading them in, through overriding the PropertyResourceConfigurer.convertPropertyValue(java.lang.String) method. For example, encrypted values can be detected and decrypted accordingly before processing them.

Another benefit is the same file can be used in ant build file also :

<property file="sample.properties"/>
...
<target name="browse">
<java classname="org.hsqldb.util.DatabaseManager" fork="yes" failonerror="true">
<classpath refid="classpath"/>
<arg value="-url"/>
<arg value="${jdbc.url}"/>
</java>
</target>
<property name="driverClassName"><value>${jdbc.driver}</value></property><br />
...<br />
<br />
...<br />
</bean><br />
<br />
<br />
 

Tuesday, August 17, 2010

Soap Message Logging in Xfire

Anyone  who has even a little application support experience would know the importance of appropriate logging in the code.If something is not working, it would be a hell at 2 AM to figure out  what happened to request in side the application.That is one of the reasons why people from production support make faces when they hear about dev team is using a new framework. Most of the frameworks, in order to make the performance good, use very little logging. Some frameworks give the option to the developer.If the developer wants to have extensive logging he has to configure. Xifre was one among them. In my current application ,it was important to see the entire Soap request came in and the Soap response went out to the system.

Since Xfire is stax based it never caches the whole message in memory , but luckily  there were options to  configure to log the whole  in/out messages.

First  we need to add a DOMInHandler  to the  request flow.  It reads the incoming stream to a DOM document and sets the stream to  a W3CDOMStreamReader.Then use LoggingHandler to log the message.

Same approach can be used for the out going messages using , DOMOutHandler and LoggingHandler.

//Tell XFire to cache a DOM document for the various in/out flows
service.addInHandler(new org.codehaus.xfire
                        .util.dom.DOMInHandler());
service.addOutHandler(new org.codehaus.xfire
                         .util.dom.DOMOutHandler());

// Add a logging handler to each flow 
service.addInHandler(new org.codehaus.xfire
                            .util.LoggingHandler());
service.addOutHandler(new org.codehaus.xfire
                           .util.LoggingHandler());

In the  XML config  looks like :
&lt;bean id="sampleWS"<br />
          class="org.codehaus.xfire.spring.remoting.XFireExporter"<br />
          abstract="true"><br />
        &lt;property name="style" value="document" /><br />
        &lt;property name="serviceFactory" ref="bindingServiceFactory" /><br />
        &lt;property name="namespace" value="http://sample.com" /><br />
        &lt;property name="xfire" ref="xfire" /><br />
        &lt;property name="inHandlers"><br />
            &lt;list><br />
                &lt;ref bean="inHandler" /><br />
                &lt;ref bean="loggingHandler" /><br />
            &lt;/list><br />
        &lt;/property><br />
        &lt;property name="outHandlers"><br />
            &lt;list><br />
                &lt;ref bean="outHandler" /><br />
                &lt;ref bean="loggingHandler" /><br />
            &lt;/list><br />
        &lt;/property><br />
       <br />
    &lt;/bean><br />
<br />
<br />
 &lt;bean id="inHandler"<br />
          class="org.codehaus.xfire.util.dom.DOMInHandler"<br />
          scope="prototype" /><br />
<br />
    &lt;bean id="outHandler"<br />
          class="org.codehaus.xfire.util.dom.DOMOutHandler"<br />
          scope="prototype" /><br />
<br />
    &lt;bean id="loggingHandler"<br />
          class="org.codehaus.xfire.util.LoggingHandler"<br />
          scope="prototype" />

Saturday, August 14, 2010

Xfire and WS in Document Literal Wrapped Style

Developers life has changed a lot . Most of the time you dont need to know whats going behind the scene. We are just following the trails somebody has gone before.When something is not working then we will do a Google search, straight forward: other guys had the same error message, blindly follow the steps given in the answer.I agree some times it will take little bit time to rephrase the search and read through the blogs etc. But what if you dont quite find what you are looking for .. Go back to the basics. Try to understand whats going on in the code esp. the third party open source code. This is what I did for couple of days this week. The problem was related to a web service.I was using Xfire and Jibx combination for the webservice client creation. When it try to send a request to an external webservice , it was creating an extra outer element for the request. like

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<ns1:GetDetails xmlns:ns1="http://services.sample.com/Details">
<yup:GetDetails xmlns:yup="http://services.sample.com/yupment" xmlns:ent="http://services.sample.com/Common/Entities" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<yup:DetailsRequest>

Here  <ns1:GetDetails  is an extra element in the request, due to which it was failing the validation in the server side. I tried to find the root cause of why Xfire/Jibx is adding this extra element. Debugged the Xfire source and find the place where it is adding it and found out if "wrapped" is true it will add ns1 element to the request. I tried to find out where are we defining  this wrapped flag. Mean while I noticed that the client wsdl is created by using microsoft tools. It gave me a wild guess of whether they are using any of so called "non standard" stuff.
 
Kept on reading so many article about WS styles and finally caught the attention of  following snippet. Yeah .. thats right .. there is a 'non standard' microsoft stuff out there,document/literal wrapped pattern.

These are the basic characteristics of the document/literal wrapped pattern:
  • The input message has a single part.
  • The part is an element.
  • The element has the same name as the operation.
  • The element's complex type has no attributes.
I started looking at the wsdl and found that it matches the above characteristics. I  made the element name and the operation different.. wow!!!! it started working.

So mastery solved..... By seeing the same element and operation name Xfire was creating  the out going request as a wrapped one.

<wsdl:message name="AService_GetDetailsInfo_InputMessage">
      <wsdl:part name="parameters" element="tns:GetDetailsInfo"/>
   </wsdl:message>
  
   </wsdl:message>

   <wsdl:portType name="AService">

     <!-- Changed from GetAccountInfo to GetDetailsInfoOp to avoid wrapped style;Hence do double request by Xfire!-->
      <wsdl:operation name="GetDetailsInfoOp">
         <wsdl:input wsaw:Action=
         <wsdl:output wsaw:Action=
         <wsdl:fault wsaw:Action=
         <wsdl:fault wsaw:Action=
      </wsdl:operation>
   </wsdl:portType>
  
     <!-- Changed from GetAccountInfo to GetDetailsInfoOp to avoid wrapped style; Hence do double request by Xfire!-->
     <wsdl:operation name="GetDetailsInfoOp">
         <soap:operation soapAction=
         <wsdl:input>
            <soap:body use="literal"/>
         </wsdl:input>
         <wsdl:output>
 
To read more about the pros and cones of  Wrapped style as well as other styles go to:
    http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/

    Moral : Go back to the basics when ever you can ... Knowledge is power !!!!!
    Related Posts Plugin for WordPress, Blogger...