Web Service Versioning with Endpoints using XFire

I wanted to document an example of using web service versioning using endpoints. I posted on the XFire mailing list asking what other people do but got little in return. I read the XFire Versioning Wiki entry and that mentioned using namespaces and/or custom headers. Although the namespaces/custom header approach works fine, it has the significant drawback of your web service clients to actually modify the outgoing SOAP message, which is always nice to avoid.

Using endpoints also allows us to have nicer WSDL URLs based on version number, e.g.:


In this example, I want to host multiple versions of the service while maintaining a logical URL like shown above. There’s a simple little trick involved in doing this using XFire and it needs us to override the getService(HttpServletRequest) method of the XFireServletController class. In order to plug a different controller, we must override the createController() method in XFire’s main servlet. I’m using Spring so I would need to override XFireSpringServlet but if your’e not using Spring you would override XFireServlet instead.

public class CustomXFireServlet extends
                         XFireSpringServlet {
  public XFireServletController createController()
                      throws ServletException {
    return new CustomXFireServletController(getXFire(),

So I’ve specified a new controller, CustomXFireServletController which is the primary entry point for all service requests. I’ll override the getService(HttpServletRequest) method which will parse the service name out of the URL as per your convention.

public class CustomXFireServletController extends
        XFireServletController {

  public CustomXFireServletController(XFire xFire) {

  public CustomXFireServletController(XFire xFire,
                     ServletContext servletContext) {
    super(xFire, servletContext);

   * Override getService to look for a URL of the form:
   * http://.../services/1_0_0/SportsService
   * which would map to a service registered as
   * SportsService1_0_0
   * @param request HttpServletRequest
   * @return Service name corresponding to URL
  protected String getService(HttpServletRequest
                                          request) {
    String pathInfo = request.getPathInfo();
    if (pathInfo != null && pathInfo.startsWith("/") &&
        StringUtils.countMatches(pathInfo, "/") == 2) {
      int lastSlash = pathInfo.lastIndexOf("/");
      String version = pathInfo.substring(1, lastSlash);
      String name = pathInfo.substring(lastSlash+1);
      return name + version;
    } else {
      return super.getService(request);

So I’m counting on a service with the name of SportsService1_0_0 to be registered with XFire. This service would be accessible at http://arsenalist.com/services/1_0_0/SportsService

The last step is to modify your web.xml so that it uses the CustomXFireServlet:


This is one of the cleanest solutions for having versioning capabilities for your web services. Your web service clients don’t need to specify any specific namespaces or create custom headers just to invoke a specific version of a service. There are no external dependencies (not even on Spring) The endpoint method works on top of the SOAP envelope and you have the power to customize it to any convention that you might want to use.¬† For example, you could actually specify the version number using the querystring if you like:


All these are delectable options that you can choose from.

Update: Andrew Ochsner’s excellent comment on this post also shows how you can do versioning using Spring’s DispatcherServlet and SimpleUrlHandlerMapping.


4 thoughts on “Web Service Versioning with Endpoints using XFire

  1. Andrew Ochsner

    We do something similar but different. We use org.springframework.web.servlet.DispatcherServlet as the XFireServlet. Then in our xfire-servlet.xml file (our Spring/XFire configuration file), we set up the following:


    <?xml version=”1.0″ encoding=”UTF-8″?>
    <!DOCTYPE web-app PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN” “http://java.sun.com/dtd/web-app_2_3.dtd”>

    <!– For xfire context initialisation in a spring environment –>
    <!– Register the spring context listener –>






    <?xml version=”1.0″ encoding=”UTF-8″?>

    <beans xmlns=”http://www.springframework.org/schema/beans”

    <bean id=”ourFirstServiceBean” class=”com.example.OurFirstServiceImpl” />
    <bean id=”ourSecondServiceBean” class=”com.example.OurSecondServiceImpl” />

    <bean name=”jaxbServiceFactory”
    <constructor-arg ref=”xfire.transportManager” />

    <bean class=”org.springframework.web.servlet.handler.SimpleUrlHandlerMapping”>
    <property name=”urlMap”>
    <entry key=”/2006/07/*”>
    <ref bean=”ourFirstService”/>
    <entry key=”/2007/01/*”>
    <ref bean=”ourSecondService”/>

    <bean id=”ourFirstService” class=”org.codehaus.xfire.spring.remoting.XFireExporter”>
    <property name=”serviceBean” ref=”ourFirstServiceBean” />
    <property name=”serviceFactory” ref=”jaxbServiceFactory” />
    <bean id=”ourSecondService” class=”org.codehaus.xfire.spring.remoting.XFireExporter”>
    <property name=”serviceBean” ref=”ourSecondServiceBean” />
    <property name=”serviceFactory” ref=”jaxbServiceFactory” />

    This way it’s configuration not some parsing logic in some code that can’t be changed. Works for us, but I suppose there’s some more complicated examples that might need parsing.

    Andy O

  2. Java Guy


    Are you saying that if you have 200 services you will have 200 entries in the ? Is that map somehow generated or maintained manually. I like the idea otherwise.

  3. arsenalist

    You can extend SimpleUrlHandlerMapping and override setUrlMap() to specify your own mapping. Then you can populate your map with whatever you want using Java code.

    The only thing I don’t like about the Spring way of doing this is that you have to modify your mappings every time a new service or service version is added.

    Also, you obviously need a dependency on Spring which is not needed in the method shown in the post.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s