Spring in Practice

Willie Wheeler's Spring blog

Publish an RSS Feed With Spring 3.0

| Comments

At the time of this writing, Spring 3.0 isn’t out yet, but that doesn’t mean we can’t start goofing around with the nightly snapshots. I’ve been doing just that, and in this article I’ll show you how to publish an RSS feed using the new AbstractRssFeedView class from Spring 3.0.

Those familiar with Spring Modules might recognize our view class. It began life as AbstractRssView in the Spring Modules project. But as of Spring 3.0, it’s now a first-class member of the framework (though it’s been renamed to AbstractRssFeedView), along with the AbstractAtomFeedView class for Atom feeds, and the AbstractFeedView, which serves as a base class for both. The new classes, like the old one, are based on Sun’s ROME API.

You’ll need to know Spring Web MVC to get the most out of this article. In particular, you’ll need to understand the relationship between controllers and views, which in a nutshell is this: when a controller is done processing a request, it returns a logical view name that a view resolver subsequently maps to a view.

Without further ado, let’s look at some code.

The controller

Let’s start with the controller, since processing starts there, and since that’s probably more familiar to more readers than implementing views. Here’s a pretty basic controller for a news feed.

package rssdemo.web;

import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import rssdemo.model.NewsItem;
import rssdemo.service.NewsService;

public final class NewsController {
    private NewsService newsService;
    private String rssNewsFeedView;
    public void setNewsService(NewsService newsService) {
        this.newsService = newsService;
    public void setRssNewsFeedView(String rssNewsFeedView) {
        this.rssNewsFeedView = rssNewsFeedView;
    public String rss(HttpServletResponse res, Model model) {
        List<NewsItem> newsItems = newsService.getAllNewsItems();
        model.addAttribute(newsItems);                                     // 1
        return rssNewsFeedView;                                            // 2

As you can see, this controller really is as simple as I said it would be. Our rss() method grabs a list of NewsItems from the NewsService 1 and places it on the Model under a conventionally-generated key, which in this case would be newsItemList. Then we simply return an injected logical view name 2, which we’re going to map to an actual view shortly. (We inject the view name to maintain the separation between the controller and the view.)

Now let’s check out the star of the show, which would be our view.

The view, via Spring 3.0’s new AbstractRssFeedView

Now we come to the meat of the subject. Here we’re going to implement a Spring Web MVC view by extending Spring 3.0’s new AbstractRssFeedView class and by using ROME to model our news feed. Once we have the view in place, we’ll be ready to configure the mapping from the logical view name we set in the controller to the view.

The next listing what’s involved in implementing a view for an RSS feed. If you’re doing an Atom feed, the approach is entirely analogous, but you would just need to extend AbstractAtomFeedView instead of AbstractRssFeedView.

package rssdemo.web;

import java.util.*;
import javax.servlet.http.*;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.web.servlet.view.feed.AbstractRssFeedView;
import com.sun.syndication.feed.rss.Channel;
import com.sun.syndication.feed.rss.Description;
import com.sun.syndication.feed.rss.Item;
import rssdemo.model.NewsItem;

public final class RssNewsFeedView extends AbstractRssFeedView {           // 1
    private String feedTitle;                                              // 2
    private String feedDesc;
    private String feedLink;
    public void setFeedTitle(String feedTitle) {
        this.feedTitle = feedTitle;
    public void setFeedDescription(String feedDesc) {
        this.feedDesc = feedDesc;
    public void setFeedLink(String feedLink) {
        this.feedLink = feedLink;

    protected void buildFeedMetadata(
            Map model, Channel feed, HttpServletRequest request) {         // 3
    protected List<Item> buildFeedItems(
            Map model,
            HttpServletRequest request,
            HttpServletResponse response)
        throws Exception {                                                 // 4
        List<NewsItem> newsItems =
            (List<NewsItem>) model.get("newsItemList");                    // 5
        List<Item> feedItems = new ArrayList<Item>();
        for (NewsItem newsItem : newsItems) {                              // 6
            Item feedItem = new Item();
            Description desc = new Description();
        return feedItems;

So what’s going on here? Well, we begin by extending the AbstractRssFeedView class 1. Then we include some injected fields for feed metadata 2. We use these in the optional buildFeedMetadata() method 3. I say “optional” because the AbstractRssFeedView provides a dummy implementation (actually, its superclass AbstractFeedView provides it).

The method we’re required to implement is buildFeedItems() 4. Here’s where we map our list of domain objects (here, a list of NewsItem objects that are just something we cooked up ourselves) to the ROME API, which provides a structure for modeling feeds. We begin by grabbing the NewsItem list off the model (recall from listing 1 that we placed the list on the model in the controller) 5. Then we iterate over the NewsItem list, mapping each one to a ROME Item 6.

That should be pretty straightforward-looking. And we’re almost done. There’s just one part that remains, and that’s establishing the mapping between the logical view name we return from the controller and the RssNewsFeedView that we just created. We do that in the application context.

Configure the view resolver for your RSS feed

The last thing we need to take care of is configuring up the right view resolver in our application context. We can’t use the standard InternalResourceViewResolver here because we’re not mapping to a URL; instead we want to map to a view (namely, the RssNewsFeedView that we just created) and we want that view to handle generating the output directly.

The simplest approach here is to use something called the BeanNameViewResolver. The idea with this type of resolver is quite simple. Whenever a controller returns a logical view name, the BeanNameViewResolver will attempt to find a bean on the application context with the same name (or ID). If there’s a match, then it interprets that bean as the mapped view. Otherwise, the other resolvers are given their shot at matching the view name.

To add a BeanNameViewResolver, all we need to add is this:

<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>

We also need to inject the view name into our controller, as we saw in listing 1. Here’s how we can do that:

<bean class="rssdemo.web.NewsController"

We just chose the name rssNewsFeedView more or less arbitrarily; we could have chosen anything. It’s good to choose something accurate and descriptive just to keep things clear and the minimize the chance of a mapping conflict, since the name you choose is going to be a bean name. Speaking of which, we’ll need to put our view on the app context too:

<bean id="rssNewsFeedView"
    p:feedTitle="Ye Olde Cigar Shoppe"
    p:feedDescription="Latest and greatest news about cigars"

And there you have it! When the DispatcherServlet gets a request for the RSS feed, it will run the controller method and then grab the resulting view name, which we’ve configured to be rssNewsFeedView. Then the BeanNameViewResolver will find the corresponding view bean on the app context—in this case our RssNewsFeedView—and the view bean will finish up the request as required. All in all a nice, clean way of handling feed publication.

Post migrated from my Wheeler Software site.