Spring in Practice

Willie Wheeler's Spring blog

Make Web Services Transparent With Spring 2.5 and Apache CXF 2.0

| Comments

In our previous installment, we showed how to create Java-first web services in Spring 2.5 using Apache CXF 2.0. This time we’re going to show how to consume web services, once again using Spring 2.5 and Apache CXF 2.0.

Something great about the Spring/CXF duo is that your web service clients don’t know that they’re web service clients. The approach is simple: as in any Spring app, you define Java interfaces for your services and inject the service implementations into the client classes that use them (such as MVC controllers). CXF allows you to generate dynamic proxies according to the same Java service contract—the proxies are just another service implementation—and hence your client classes have no idea that they’re calling web services.

This article shows you what you need to do to get it to work. If you haven’t already done so, please see the previous article, Web services with Spring 2.5 and Apache CXF 2.0, to get your web services set up. That article describes a user comment service that I build upon in the current article.

Project setup

First we need to set up the web service client project. Here are the various dependencies involved.

Spring 2.5

These all come from the Spring 2.5 distribution. You can use whatever Spring 2.5 libraries you need for your own app. Here I just happen to be using Spring MVC and JSTL, though neither of those is required for Spring/CXF integration.

  • jstl.jar (in lib/j2ee)
  • spring.jar
  • spring-mvc.jar (in dist/modules; the sample app uses Spring MVC)
  • standard.jar (in lib/jakarta-taglibs; this is the JSTL reference implementation)

CXF and dependencies

You can get these from the CXF 2.0.4 distribution. Whether all of these are really necessary I don’t know—for example I’m not sure why we need the JavaMail library—but I’m just going by what the CXF user manual says.

  • commons-logging-1.1.jar
  • cxf-2.0.4-incubator.jar (this is the main CXF JAR)
  • geronimo-activation_1.1_spec-1.0-M1.jar (or Sun’s Activation jar)
  • geronimo-annotation_1.0_spec-1.1.jar (JSR 250)
  • geronimo-javamail_1.4_spec-1.0-M1.jar (or Sun’s JavaMail jar)
  • geronimo-servlet_2.5_spec-1.1-M1.jar (or Sun’s Servlet jar)
  • geronimo-stax-api_1.0_spec-1.0.jar
  • geronimo-ws-metadata_2.0_spec-1.1.1.jar (JSR 181)
  • jaxb-api-2.0.jar
  • jaxb-impl-2.0.5.jar
  • jaxws-api-2.0.jar
  • neethi-2.0.2.jar
  • saaj-api-1.3.jar
  • saaj-impl-1.3.jar
  • wsdl4j-1.6.1.jar
  • wstx-asl-3.2.1.jar
  • XmlSchema-1.3.2.jar
  • xml-resolver-1.2.jar

Aegis dependencies

In addition to the above, you will need to add jdom-1.0.jar since Aegis databinding uses it.

Client library dependencies

In the previous article we created three classes in the contactus package: ContactUsService, ContactUsServiceImpl, and Message. You will need to JAR ContactUsService (which is a service interface) and Message (which is a domain model class) and add the JAR as a dependency for the client application. You do not need to include ContactUsServiceImpl since that’s the backend for the web service; it’s not part of the interface. On the client side we will see that CXF will create a web service proxy according to the ContactUsService interface, and it will use Message for marshalling and unmarshalling.

With the dependencies in place, we’ll now create a simple client that can view user messages using the web service we created the last time. We’re not going to treat the “post user message” operation in this article though it works in exactly the same way (which is why we’re not going to treat it).

Creating the client application

This sample app is based on Spring MVC. For that we’ll need to create a couple of MVC controllers, a couple of JSPs, a web.xml file, and a Spring application context file.

Spring MVC controller for viewing messages

First we’ll create a Spring MVC controller called myapp.ViewMessagesController.

package myapp;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import contactus.ContactUsService;

public final class ViewMessagesController {
    private ContactUsService contactUsService;
    public void setContactUsService(ContactUsService contactUsService) {
        this.contactUsService = contactUsService;
    public ModelMap viewMessages() {
        return new ModelMap("messages", contactUsService.getMessages());

Since this is an article about Spring/CXF integration and not about Spring MVC, I won’t go into the details of Spring MVC or annotation-based configuration. If however you are interested in learning more, please see my article Annotation-Based MVC in Spring 2.5.

At any rate, the code is easy enough to understand. We have a dependency injection method setContactUsService. Any implementation of ContactUsService could go in there, including the one we wrote in the previous article, contactus.ContactUsServiceImpl. In this case, though, we’re going to use a CXF-generated dynamic proxy as shown below.

The viewMessages method simply grabs a list of messages from the ContactUsService and puts it in a model that the JSP will be able to see.

JSP for viewing messages

You will need to put this file at /WEB-INF/jsp/viewmessages.jsp in order for the request mapping to work as specified in ViewMessagesController above and myapp-servlet.xml below. For those who are unfamiliar with Spring’s annotation-based MVC configuration, the @RequestMapping(“/viewmessages.do”) annotation maps the given path to the viewMessages method, and the view resolver in myapp-servlet.xml tells Spring to look inside /WEB-INF/jsp/ for the corresponding JSP.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
        <title>View Messages</title>
        <h1>View Messages</h1>
            <c:forEach var="message" items="${messages}">
                <li>${message.lastNameFirstName} (${message.email}): ${message.text}</li>

This just displays a list of user messages. I’m using JSTL and JSTL EL. The ${messages} reference in the forEach tag refers to the list of messages that I placed in the ModelMap in ViewMessagesController.viewMessages above. Spring takes care of making the contents of the ModelMap available to the JSP.


<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="ws" version="2.5">

This just sets up the Spring MVC DispatcherServlet and tells the servlet container that the *.do extension mapping goes to the DispatcherServlet.

Now let’s dig into the guts of it—the Spring application context.

Creating the Spring application context

This is where all the good stuff is: in the Spring application context.

Spring application context: myapp-servlet.xml

Put this file at /WEB-INF/myapp-servlet.xml so that it’s where DispatcherServlet expects to find it. The myapp- part needs to match the value specified for <servlet-name> above. (There’s a way to change this but I’m not worried about that for this sample app.)

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <!-- Configure CXF to use Aegis data binding instead of JAXB -->
    <bean id="aegisBean"
    <bean id="jaxwsAndAegisServiceFactory"
        <property name="dataBinding" ref="aegisBean"/>
        <property name="serviceConfigurations">
            <bean class="org.apache.cxf.jaxws.support.JaxWsServiceConfiguration"/>
            <bean class="org.apache.cxf.aegis.databinding.AegisServiceConfiguration"/>
            <bean class="org.apache.cxf.service.factory.DefaultServiceConfiguration"/> 

    <!-- Factory to create the dynamic proxy -->
    <bean id="contactUsFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
        <property name="serviceClass" value="contactus.ContactUsService"/>
        <property name="address"
        <property name="serviceFactory" ref="jaxwsAndAegisServiceFactory"/>
    <!-- Web service dynamic proxy -->
    <bean id="contactUsService"
    <!-- Controllers -->
    <bean class="myapp.ViewMessagesController">
        <property name="contactUsService" ref="contactUsService"/>
    <!-- View resolvers -->
    <bean id="viewResolver"
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>

There’s lots to talk about here. Let’s do it bean-by-bean:

aegisBean: CXF supports different databinding mechanisms (i.e., mechanisms for mapping back and forth between Java and XML). The default is JAXB but I was never able to get that to work for complex data types like contactus.Message. So instead I used Aegis (which is bundled with CXF) and it works great.

jaxwsAndAegisServiceFactory: This factory creates service models either based on a service’s WSDL or else based on the structure of the service class. These service models are in turn used by the service proxy factory, which creates your client-side web-service-aware dynamic proxies. Anyway, you don’t have to worry too much about jaxwsAndAegisServiceFactory; the only reason we’re including it is that we need to be able to tell it to use Aegis databinding.

contactUsFactory: This is a factory that generates the dynamic proxies we’ve been talking about. These proxies implement the contactus.ContactUsService interface, and this is what gives us the transparency referenced in the title of this article: the client application has no idea that it’s working with web services at all (other than in the configuration). If you wanted to, you could collapse the client app and the contactus.ContactUsServiceImpl backend and remove the web service altogether. That’s part of the beauty of Spring (and of Java interfaces and dynamic proxies).

We specify not only the service class but also the web service endpoint address and the service factory. Again the only reason we have to deal with the service factory at all is that we’re using the non-default Aegis databinding. If you’re able to get it working with JAXB then more power to you. (And I’d be interested in hearing about it!)

IMPORTANT: You will need to set the host, port and context path in the address property to match your web service deployment address. The one in the config file is the one I’m using but you’re probably using at least a different context path.

The other beans are just Spring MVC beans. Nothing we need to worry about here.

We’re now ready to try it out!

Try it out

Your application’s view messages functionality should now work. Start up both your web service and your application. Then point your browser to


(well, substitute in your host, port and context path!) and you should see the pair of hardcoded messages that we created in the last article:


If you got the screen above, then it’s working! Your application is pulling the messages from a web service, and transparently so. If you decide you don’t want to use web services, no problem: just pull the web service out and wire the service bean right into your MVC controller or other client class.

I hope you found this useful. As always let me know if you have comments, questions or corrections.


Update (2008-09-03): Sam Brodkin was kind enough to create a Maven project for this article. Thanks Sam!

Post migrated from my Wheeler Software site.