Saturday, July 7, 2007

XFire WebService With Spring

Tried setting up XFire with Spring and thought I'd share that experience. One more place to come for this information will not hurt ah!

Once again I used Maven to build my test application. At the bottom of this article you will find a download link for the entire application.

I have used Axis in the past and wanted to try out some other frameworks. At the same time I absoutely needed the framework to support JSR 181 (web service annotations), required the framework to integrate with Spring and relatively simple configuration. Oh also I did not want to write any WSDL. This example is an RPC based web service (unlike my previous article on document based web service with Spring-WS). I will after this article also start using Axis2, since I have been an Axis fan for many years.

JSR 181 is important to me. I think annotations are the right way to go for most simple tasks that do not require a lot of input. The web service annotations are good. I have seen examples of annotations where it would be easier and more clearer to put it into the old XML style configuration. Some folks are anti-annotations and I think that attitude is not the best. Use it where it makes sense and reduces configuration in external files.

Lets view the echo service java POJO code.

package com.aver;

public interface EchoService {
    public String printback(java.lang.String name);
}
package com.aver;

import java.text.SimpleDateFormat;
import java.util.Calendar;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

@WebService(name = "EchoService", targetNamespace = "http://www.averconsulting.com/services/EchoService")
public class EchoServiceImpl implements EchoService {

    @WebMethod(operationName = "echo", action = "urn:echo")
    @WebResult(name = "EchoResult")
    public String printback(@WebParam(name = "text")
    String text) {
        if (text == null || text.trim().length() == 0) {
            return "echo: -please provide a name-";
        }
        SimpleDateFormat dtfmt = new SimpleDateFormat("MM-dd-yyyy hh:mm:ss a");
        return "echo: '" + text + "' received on " + dtfmt.format(Calendar.getInstance().getTime());
    }
}

As you can see above I have made liberal use of JSR 181 web service annotations.

  • @WebService declares the class as exposing a web service method(s).
  • @WebMethod declares the particular method as being exposed as a web service method.
  • @WebParam gives nice-to-read parameter names which will show up in the auto-generated WSDL. Always provide these for the sake of your consumers sanity.
  • Also you can see that the java method is named 'printback' but exposed as name 'echo' by the @WebMethod annotation.
Here is the web.xml.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:org/codehaus/xfire/spring/xfire.xml
            /WEB-INF/xfire-servlet.xml
        </param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>XFireServlet</servlet-name>
        <servlet-class>
            org.codehaus.xfire.spring.XFireSpringServlet
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>XFireServlet</servlet-name>
        <url-pattern>/servlet/XFireServlet/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>XFireServlet</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>
</web-app>

The web.xml configures the 'XFireSpringServlet' and sets up the Spring listener. Straightforward.
Finally here is the xfire-servlet.xml (this is our spring configuration file).

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
">www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <bean id="webAnnotations"
        class="org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations" />

    <bean id="jsr181HandlerMapping"
        class="org.codehaus.xfire.spring.remoting.Jsr181HandlerMapping">
        <property name="typeMappingRegistry">
            <ref bean="xfire.typeMappingRegistry" />
        </property>
        <property name="xfire" ref="xfire" />
        <property name="webAnnotations" ref="webAnnotations" />
    </bean>

    <bean id="echo" class="com.aver.EchoServiceImpl" />
</beans>
  • Sets up the xfire bean to recognize jsr 181 annotations.
  • Last bean is our echo service implementation bean (with annotations).
Thats it. Build and deploy this and you should see the WSDL at http://localhost:9090/echoservice/services/EchoServiceImpl?wsdl.
By Mathew