February 16, 2010

Consuming web service using Spring

With the adoption of SOA in companies, we have many web applications accessing web services which are local and external. My application currently interacts with web services built by other team with in the organization and also with third party. Java frameworks offer different ways to consume web services and we will have a look what spring framework has to offer.

Consuming web services with Spring is very simple. With Spring you will be able to configure a web service client using XML bean configuration. Spring takes care of creating the client stub when the applications starts. You can then access the web service from the Spring bean container.

Spring provides remoting support for web services via JAX-WS with the help of two factory beans, namely LocalJaxWsServiceFactoryBean and JaxWsPortProxyFactoryBean. I will use the latter as it returns a proxy that implements our business service interface. For this tutorial, I will take a public web service available at WebserviceX.NET. For demo, I have taken the whois lookup service. Here is our bean configuration:


<bean id="whoisService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
<property name="wsdlDocumentUrl"  value="http://www.webservicex.net/whois.asmx?wsdl" />
<property name="namespaceUri"     value="http://www.webservicex.net" />
<property name="serviceName"      value="whois" />
<property name="portName"         value="whoisSoap" />
<property name="serviceInterface" value="com.spweb.services.WhoIsService" />
</bean>
Now, lets have a closer look at the bean configuration. I have defined five properties; wsdlDocumentUrl holds the WSDL URL for the web service we are going to consume. namespaceUri
defines the namespace, you can get this details from the WSDL file. Next comes the serviceName and portName of the web service. And the final property is the service interface. We will have to create the service interface so that we can interact with web service.

When the spring application starts, the bean gets created and we will be able to access the web service through this bean. To access, I injected the bean to one of my controller (I am using MVC) and call the necessary methods through my service interface. Now, lets have a look at our service interface. Its a simple java interface with some annotations and will have all the methods that we call. Here is our service interface:
@WebService(name = "whoisSoap",
targetNamespace = "http://www.webservicex.net")
public interface WhoIsService {

@WebMethod(operationName = "GetWhoIS",
action = "http://www.webservicex.net/GetWhoIS")
@WebResult(name = "GetWhoISResult", 
targetNamespace = "http://www.webservicex.net")
@RequestWrapper(localName = "GetWhoIS", 
targetNamespace = "http://www.webservicex.net",
className = "net.webservicex.GetWhoIS")
@ResponseWrapper(localName = "GetWhoISResponse", 
targetNamespace = "http://www.webservicex.net", 
className = "net.webservicex.GetWhoISResponse")
public String getWhoIs(@WebParam(name = "HostName", 
targetNamespace = "http://www.webservicex.net")String domain);
}
In order to work with web services, you need to study the WSDL file carefully. All the details come from this file. The first annotation is @WebService, which is used to define the interface as a service endpoint interface. In this case, I have specified the two properties namely, name and targetNamespace. The name property holds the name of wsdl:portType and targetNamespace holds the namespace of the the WSDL.

Next we declare methods which will be called. To tie these methods to the web service calls we use the @WebMethod annotation. The annotation specifies the operation name and action URL. Along with this, we also specify @WebResult,@RequestWrapper,@ResponseWrapper. These annotations provide information regarding request and response data types. The @WebParam is used to map the method parameters with the parameters of the web service.

Finally to consume the web service, I simple call the method as shown below:
if(whoService!=null) {
resultString = whoService.getWhoIs("hostname.com");
}
I do not create a instance of the service bean, instead it gets injected when the application starts. Here are few other points to note, I didn't use the Spring web service. The only jar dependency I had was saaj-impl apart from the spring framework's jars.

11 comments :

Anonymous said...

Good One.

barry said...

hello have you got the complete project?
i want to consume a web service by using spring

Abdel Olakara said...

@barry, What is the issue you are facing?

Anonymous said...

HI, i am getting the following error:
Wrapper class net.webservicex.GetWhoIS is not found

What can i do?

Deepak said...

Hi,

I am not able to write proper RequestWrapper and ResponseWrappper class. Can you pls elaborate your example by providing complete details.

Thanks
Deepak

ChAiTaLi said...

I tried this example. Its gives me following exception.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'whoisService' defined in ServletContext resource [/WEB-INF/ap
plicationContext.xml]: Invocation of init method failed; nested exception is org.jboss.ws.metadata.wsdl.WSDLException: Cannot connect to: http://www.
webservicex.net/whois.asmx?wsdl
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1338)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)


Am I missing something ?????

I have spring-web 2.5.6 and saaj-impl-1.3.2.jar in my classpath

fingersmagoo said...

How would you go about using this when you have the wsdl file local, but the services are remote. Applications like Salesforce allow you to only generate the wsdl and immediately download....it is not available via url. SO the wsdl file is in the claspath.

Abdel Olakara said...

@fingermagoo, did you try referring the local wsdl file?

need help said...

can you post your entire code from scratch pls??so many are facing this issue...

need help said...

Abdel Olakara,

can you pls send the code from scratch?So many are facing the same issue.

need help said...

please post ur source code here..
it will be helpful to many ppl.