Sunday 27 May 2007

Web Service client with Spring-WS and DuckTyping

This week I have tested Spring-WS, I'm interesting in Xpath support and I have done a simple client of BookService.
The BookService is a test of JSR 181 with XFire (perhaps I'll explain the implementation in other post).

One example of SOAP request/response:

SOAP Request:

<ns1:findBook xmlns:ns1="http://dahernan.net/BookService">
<ns1:isbn>12567</ns1:isbn>
</ns1:findBook>


SOAP Response:

<ns1:findBookResponse xmlns:ns1="http://dahernan.net/BookService">
<ns1:Book>
<author xmlns="http://model.dahernan.net">Matt Raible</author>
<isbn xmlns="http://model.dahernan.net">12567</isbn>
<price xmlns="http://model.dahernan.net">12.22</price>
<title xmlns="http://model.dahernan.net">Spring Live</title>
</ns1:Book>
</ns1:findBookResponse>


So, let's see the Spring-WS Client:

public class BookServiceClient {

private static final String MESSAGE =
"<ns1:findbook ns1="\"http://dahernan.net/BookService\"">" +
"<ns1:isbn>12567</ns1:isbn>" +
"</ns1:findbook>";

private WebServiceTemplate webServiceTemplate;

private XPathExpression xpathExp;

// ... getters and setters

public String getAuthor() {
StreamSource source = new StreamSource(new StringReader(MESSAGE));
DOMResult result = new DOMResult();
webServiceTemplate.sendAndReceive(source, result);
String author = xpathExp.evaluateAsString(result.getNode());

return author;
}


It's based in WebServiceTemplate (I like the Spring templates :), and XPathExpresion, the request is constant.
The response, first I build a DOM with response and next I evaluate the XPath Expresion.

And the Spring wiring.

<bean id="bookServiceClient" class="net.dahernan.example.BookServiceClient">
<property name="webServiceTemplate" ref="webServiceTemplate"/>
<property name="xpathExp" ref="xpathExp"/>
</bean>

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<property name="defaultUri" value="http://localhost:8080/xfire_test/services/BookService"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.http.HttpUrlConnectionMessageSender"/>
</property>
</bean>

<bean id="xpathExp" class="org.springframework.xml.xpath.XPathExpressionFactoryBean">
<property name="expression" value="/ns1:findBookResponse/ns1:Book/dh:author"/>
<property name="namespaces">
<props>
<prop key="ns1">http://dahernan.net/BookService</prop>
<prop key="dh">http://model.dahernan.net</prop>
</props>
</property>
</bean>


The last step, is do a small test.

public class BookServiceClientTest extends AbstractDependencyInjectionSpringContextTests{

protected static Logger logger = Logger.getLogger(BookServiceClientTest.class);

protected String[] getConfigLocations() {
return new String [] {"ws-beans.xml"};
}

public void testClient(){
BookServiceClient client = (BookServiceClient) this.applicationContext.getBean("bookServiceClient");
String author = client.getAuthor();
logger.info("Author: " + author);
}

}


All, without stubs, It looks like great.

2 comments:

Anonymous said...

Hi,
I am using sendAndRecieve() method the same way as u mentioned but i am getting the folliwing error!!!

nested exception is java.lang.ClassNotFoundException: org.springframework.ws.transport.http.HttpUrlConnectionMessageSender

can u help me out???
thanks

Anonymous said...

hi,
this is keerthi.. continuing the above comment.. i have added spring wiring in my
xxx-servlet.xml and calling the getAuthor() method in my controller class... is that ok?