Introduction

A couple of days ago I quickly had to create a WW result type that would transform a Rome (https://rome.dev.java.net/) SyndFeed to several news feeds. WW makes this very, very easy.

Used versions

WebWork 2.2 beta 4
Rome 0.7 beta

The code

com.acme.result.RomeResult.java
/**
 * 
 */
package com.acme.result;

import java.io.Writer;

import org.apache.log4j.Logger;

import com.opensymphony.webwork.ServletActionContext;
import com.opensymphony.xwork.ActionInvocation;
import com.opensymphony.xwork.Result;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedOutput;

/**
 * A simple Result to output a Rome SyndFeed object into a newsfeed.
 * @author Philip Luppens
 * 
 */
public class RomeResult implements Result {

	private String feedName;

	private String feedType;

	private final static Logger logger = Logger.getLogger(RomeResult.class);

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.opensymphony.xwork.Result#execute(com.opensymphony.xwork.ActionInvocation)
	 */
	public void execute(ActionInvocation ai) throws Exception {
		if (feedName == null) {
			// ack, we need this to find the feed on the stack
			logger
					.error("Required parameter 'feedName' not found. "
							+ "Make sure you have the param tag set and "
							+ "the static-parameters interceptor enabled in your interceptor stack.");
			// no point in continuing ..
			return;
		}

		// don't forget to set the content to the correct mimetype
		ServletActionContext.getResponse().setContentType("text/xml");
		// get the feed from the stack that can be found by the feedName
		SyndFeed feed = (SyndFeed) ai.getStack().findValue(feedName);

		if (logger.isDebugEnabled()) {
			logger.debug("Found object on stack with name '" + feedName + "': "
					+ feed);
		}
		if (feed != null) {

			if (feedType != null) {
				// Accepted types are: rss_0.90 - rss_2.0 and atom_0.3
				// There is a bug though in the rss 2.0 generator when it checks
				// for the type attribute in the description element. It's has a
				// big 'FIXME' next to it (v. 0.7beta).
				feed.setFeedType(feedType);
			}
			SyndFeedOutput output = new SyndFeedOutput();
			//we'll need the writer since Rome doesn't support writing to an outputStream yet
			Writer out = null;
			try {
				out = ServletActionContext.getResponse().getWriter();
				output.output(feed, out);
			} catch (Exception e) {
				// Woops, couldn't write the feed ?
				logger.error("Could not write the feed", e);
			} finally {
				//close the output writer (will flush automatically)
				if (out != null) {
					out.close();
				}
			}

		} else {
			// woops .. no object found on the stack with that name ?
			logger.error("Did not find object on stack with name '" + feedName
					+ "'");
		}
	}

	public void setFeedName(String feedName) {
		this.feedName = feedName;
	}

	public void setFeedType(String feedType) {
		this.feedType = feedType;
	}

}

Code Explanation

Easy enough. We try to find the SyndFeed object on the WW stack. If we can find it, we will set the feed type (rss v0.9 +, atom 0.3) if it has been specified in the result parameters (see below). Then we use a SyndFeedOutput to write our newsfeed to our PrintWriter from our response.

XWork configuration

Before you can use this result, you will need to register it in your xwork.xml:

<package name="default" extends="webwork-default">
	<result-types>
		<result-type name="feed" class="com.acme.result.RomeResult"/>
	</result-types>
	<interceptors>
..

You can now use this result type. So, create an Action that will create and populate the Rome SyndFeed, and make sure you provide a getter for your populated SyndFeed. The actual creation of your feed is beyond this recipe, but you can find plenty of examples in the Rome Wiki (http://wiki.java.net/bin/view/Javawsxml/Rome05Tutorials).

<action name="feed" class="com.acme.action.CreateFeedAction">
	<result name="success" type="feed">
		<param name="feedName">feed</param>
		<param name="feedType">rss_1.0</param>
	</result>
</action>

Concluding thoughts

This is a simple feed result using Rome as a news feed generator. You might want to make sure you don't generate your feed on every request, but there are lots of ways to deal with such problems. You can also provide additional setters in the Result to set your feed title, url, etc, but this should suffice for a quickstart.