Category Archives: Struts

Hacking WebWork Result Types: Freemarker to HTML to JavaScript

I threw all of my past experience with Struts out the window when I started my new job because we use WebWork. WebWork is approximately one thousand times better though so I’m not complaining. One of the unique to WebWork features (as compared to Struts) is the notion of a result type which is the process responsible for combining the model with a some kind of template (usually JSP or FreeMarker) to create a view.

Anyway, for various reasons we’ve found it useful at work to output some pieces of content usually rendered as HTML instead as JavaScript via document.write(). Because it would be a nightmare to maintain two FreeMarker templates, one for HTML and one for JavaScript output, I figured out a way to transform a FreeMarker template that normally renders HTML to render JavaScript using a custom WebWork result type. Simply extend the FreemarkerResultdoExecute() method with code that will look extremely similar to the existing doExecute() method. I’ll highlight the differences by showing you two lines from the existing doExecute() method:

// Process the template
template.process(model, getWriter());

and then the updated version that transforms the HTML into JavaScript using the StringEscapeUtils class from the commons lang library:

// Process the template
StringWriter writer = new StringWriter();
template.process(model, writer);
getWriter().write("document.write('" + StringEscapeUtils.escapeJavaScript(writer.toString()) + "')");

The xwork config file changes a bit as well. Here’s both the HTML version and the JavaScript version:

<result name="html" type="freemarker">foo.ftl</result>
<result name="javascript" type="freemarkerhtml2javascript">
  <param name="location">foo.ftl</param>
  <param name="contentType">text/javascript</param>
</result>

The end result is that with a little logic added to your WebWork action, you can include the result of that action in your own site:

<ww:action name="viewSnippet" executeResult="true" />

and enable other people to use the same result via embedded JavaScript:

<script src="http://yoursite.com/yourSnippet.jspa?format=javascript"></script>

Using Betwixt, Struts and REST

My latest project at work launched a couple weeks ago, unfortunately there isn’t much to look at, but it’s not like I’m a Flash developer, so unless I start writing Windows apps, no one will ever be able to see my work anyway. Alas, a major portion of the project involved consolidating some business logic behind a SOAP API (I’ll go into that some other time). We were supposed to be moving our front end to ASP.NET but at the last minute, the ASP.NET migration didn’t happen so we ended up needing something that ASP could use as well, which meant REST. With the business logic wrapped up behind business delegates, all that was needed as a Servlet Filter to map requests for /myapp/xml to a Struts Action class, which invoked the business delegates and then returned XML to the client. Now on the SOAP end of things (Axis embedded in Tomcat), I didn’t have to deal with XML (Axis handles all the XML serialization and deserialization). But with REST you’re in conundrum: do you create toXML() methods on all of your JavaBeans? do you put the JavaBean or collection of beans in the Request scope and then generate the XML using JSP? Those options all seemed error prone and harder to test. I looked at JAXB (makes more sense when you have XML that you want to turn into a JavaBean) and Castor (same thing) but finally decided on using Betwixt, a Jakarta Commons library that provide a simple way of turning a JavaBean into XML. The end result looked something like this:

public class RESTAction extends DispatchAction {
  public ActionForward doSomething(...) {
    MyBean bean = BusinessLogic.getBean();
    response.setContentType("text/xml");
    OutputStream sos = response.getOutputStream();
    BeanWriter beanWriter = new BeanWriter(sos);
    BindingConfiguration config = beanWriter.getBindingConfiguration();
    config.setMapIDs(false);
    beanWriter.enablePrettyPrint();
    String declr = "<?xml version='1.0' encoding='UTF-8' ?>";
    beanWriter.writeXmlDeclaration(declr);
    beanWriter.write("mybean", bean);
    beanWriter.flush();
    beanWriter.close();
    return null;
  }
}

which when combined with this action mapping:

<action
  path="/xml"
  type="com.mycompany.web.actions.RESTAction"
  name="xmlForm"
  scope="request"
  parameter="method"
  validate="false">
  <forward name="error" path="/WEB-INF/views/xml/error.jsp" />
</action>

is invoked like so:

http://myserver/myapp/xml?method=doSomething

I’m not 100% sold on this as the “way”, but I do like how simple Betwixt is. If you’ve got a different idea, comment away.

Retrieving an RSS feed protected by Basic Authentication using ROME

Today I worked on a feature in a Struts web application where I needed to retrieve an RSS feed that is protected by Basic Authentication and then display the the results of the feed in a web page. I’ve heard alot about ROME in the past couple weeks, so I decided to try it out. It quickly passed the 10 minute test (downloaded rome-0.5.jar, downloaded jdom.jar, used the sample code from the tutorial on the wiki); I was able to retrieve, parse and display the results of my own feed in no time:

String feed = "http://cephas.net/blog/index.rdf";
URL feedUrl = new URL(feed);
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(new XmlReader(feedUrl));
System.out.println(feed);

Easy. But that wasn’t my problem. I needed to be able to set the Basic Authentication header which is usually done like this:

String feed = "http://yoursite.com/index.rdf";
URL feedUrl = new URL(feed)
HttpURLConnection httpcon = (HttpURLConnection)feedUrl.openConnection();
String encoding = new sun.misc.BASE64Encoder().
  encode("username:password".getBytes());
httpcon.setRequestProperty ("Authorization", "Basic " + encoding);
httpcon.connect();
.. // do stuff
httpcon.disconnect();

Turns out that the designers of the ROME library were pretty smart. In addition to including the XmlReader(URL url) constructor, they also included a XmlReader(URLConnection connection) constructor, which allows you to combine the two blocks of code I wrote above to make this:

String feed = "http://yoursite.com/index.rdf";
URL feedUrl = new URL(feed)
HttpURLConnection httpcon = (HttpURLConnection)feedUrl.openConnection();
String encoding = new sun.misc.BASE64Encoder().
  encode("username:password".getBytes());
httpcon.setRequestProperty ("Authorization", "Basic " + encoding);
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(new XmlReader(httpcon));

Add this code to your Struts action, put the resulting SyndFeed in the request scope (request.setAttribute("feed", feed);) and then in the JSP:

<c:forEach var="entry" items="${feed.entries}">
  <strong>${entry.title}</strong><br />
  ${entry.description.value}<br />
  <fmt:formatDate value="${entry.publishedDate}" type="both" pattern="MMMM dd, yyyy" />
  by ${entry.author} | <a href="${entry.link}">link</a>
</c:forEach>

So there you have it. I hope that makes it easier for someone else!

Struts Tips #3

Developing a Java web application (especially in Struts) is different in many ways from developing in ColdFusion, ASP or even ASP.NET. One of the major differences is the structure of the application; generally ColdFusion, ASP and ASP.NET applications are structured around the file system; you end up at http://www.myhost.com/corporate/default.asp or http://www.myhost.com/products/default.cfm. One of the core ideas of Struts is the idea of mapping an action (/cart/checkout/billing) to an Action class (com.myhost.cart.checkout.Billing), the file system doesn’t really come into play. Another variation is the way in which applications are normally deployed (or at least the way I’ve seen them deployed): ASP, ColdFusion and ASP.NET applications are generally deployed at the root of a website while Java web applications introduce the idea of a ‘context’, where the context can be the root (context = “”) or the context can be something else (context = “/store”).

These two differences lead to a major problem if you’re creating web applications with Struts: instead of being able to reference an image using an absolute path like this:
<img src="/images/logo.jpg" />
you need to reference your images using a relative path like this:
<img src="images/logo.jpg" />
But wait! You can’t do that either because the URL of your page could /cart/checkout/billing.do or /products/cars/accessories.do, both of which could be deployed to different servlet context (“/store” for instance). If you used a relative path and then visited a page like /cart/checkout/billing.do, the webserver would request the image from /cart/checkout/images/logo.jpg, which is most likely not where you have it located.

Luckily, the Struts team put together the tag (for images) and the associated tag (for image buttons). The tags are pretty easy to pick and use. Putting an image on a page is going to take the form of:
<html:img src="/images/logo.jpg" />
or
<html:img page="/images/logo.jpg" />
The first one won’t help much in the context of this discussion; it has the exact same problems as using a regular old <img src="..." /> tag, except that the URL will be rewritten for users that don’t accept cookies. The second option is much more useful. If you use the page attribute instead of the src attribute, the “…image will automatically prepend the context path of this web application (in the same manner as the page attribute on the link tag works), in addition to any necessary URL rewriting. (src)”

Using the <html:image /> tag is really no different, so I won’t get into it (it generates an <input type="image" ... /> tag), other than to mention that it doesn’t accept height or width attributes and it doesn’t (like all JSP tag attributes) pass them through to the generated tag, which could cause problems if you migrate all your <input type="image" .../> tags over to <html:image />.

In short, if you’re developing a Struts application, make sure to familiarize yourself with all the tags, doing so can save you alot of time when your boss decides that the application should be deployed in a different servlet context.

More:

Struts & Java Tips: Issue #2

A couple weeks ago I wrote a short essay on some of the things that I ran into while working with Java and Jakarta Struts. Because I didn’t know what else to call it, I jokingly referred to it as Issue #1. Well, a month and a half later I think I have enough to write issue #2. I should probably call it something more general like ‘Java Web Development Tips’ or something, but why change now?

First, I thought I’d touch on some of the interesting things that I’ve run into while working in the presentation layer which in my case is JSP. This week I needed to create a search form that enabled end users to sort and filter results based on a number of parameters. Without showing 1000 lines of code, one of the challenges when doing a form like this is maintaining the form state when doing filtering and sorting (because not all the fields are sortable and not all can be filtered) and the most common solution is to use hidden form fields. Struts includes a <html:hidden> tag that will automatically maintain state for you form, but it requires that you know all the names of all the fields up front when you’re writing your form. If you decide to add a sortable or filterable property later, you’d need to hardcode another hidden form field. Instead, I chose to use the JSTL forEach tag and the special ‘param’ scope to programatically create my hidden form fields:

<c:forEach var="p" items="${param}">
  <input type="hidden" name="${p.key}" value="${p.value}">
</c:forEach>

The non-intuitive part of this code in my mind is the param ‘scope’, which (if you mess around with it a bit) is a HashMap derived from the getParameterMap() method of the ServletRequest interface. The forEach tag iterates over each parameter, which results in a Map.Entry; the Map.Entry provides JavaBean style accessors for key and value, which I can then use to create the hidden form fields.

The Action class that backs the search form uses an ActionForm to collect the data and then copies the data from the ActionForm bean to a bean made specifically for use with the search DAO. That code looks something like this:

public ActionForward execute(ActionMapping m, ActionForm f, HttpServletRequest req, HttpServletResponse res)
throws Exception {
...
// get the data posted from the form
SearchOrdersForm input = (SearchOrdersForm)f;
// bean coupled w/ the search DAO
ManagerSearchParams sp = new ManagerSearchParams();
// copy the properties from the form to the searchparams bean
// using the BeanUtils class
BeanUtils.copyProperties(sp, input);
// perform the search (in this case we're looking for orders
Collection orders = OrderDAO.findOrders(sp);
// push the collection to the jsp
request.setAttribute("orders", orders);

I’m not sure if there is a pattern in this or not, but the coupling of the ManagerSearchParams bean with the OrderDAO in the above example turned out (at least so far) to be very useful. Another part of the application required that I retrieve orders from persistent storage (in this case Hibernate & SQL Server) by date (ie: I needed to find all orders between date1 and date2). Instead of writing a new method on the DAO (ie: OrderDAO.searchbyDate()), the ManagerSearchParams bean already had start & end date properties. I simply created a new instance of the ManagerSearchParams bean, populated the startdate and enddate properties, and then fired the findOrders() method on the OrderDAO class.

JSTL vs. Struts taglib

The last couple weeks have been spent working on a couple different Struts applications, all of which will be deployed on Tomcat 5 with Hibernate. I’m finding that working with Struts is an enjoyable experience, the framework encourages true separation of HTML presentation and business logic and model.

As someone working on all aspects of the application, one of the things I butt my head against pretty freqently are the limitations of the struts HTML & Logic tags. For example, an application that shows a listing of widgets commonly shows each row representing a widget in alternating colors… grey, white, grey, white, etc. The Struts tags, specifically the logic:iterate tag provides no mechanism for determining what the current row number is. There are a number of solutions out there, almost all of them suggest using scriplets to create a simple counter in the loop:

<%
String LIGHT_COLOR = "LightColor";
String currentColor = DARK_COLOR;
int i = 0;
%>
<logic:iterate id="product" name="products">
<%
if ( i % 2 == 0) {
currentColor = "BLACK";
} else {
currentColor = "WHITE";
}
i++;
%>
<tr ALIGN="center" class="<%=currentColor %>">
<td>
  <bean:write name="product" property="label" />
</td>
</tr>
</logic:iterate>

Of course, the entire reason tags are used is so that you don’t have to use scriptlets, so it seems like a pretty ugly hack to me. Fortunately I’m using Tomcat 5, so I stumbled upon the JSTL forEach tag, which provides effectively the same functionality as the Struts iterate tag, with the benefit of an index and row status so that the above code becomes:

<c:forEach var="product" items="${products}" varStatus="status">
  <c:choose>
   <c:when test="${status.index % 2 == 0}">
   <tr ALIGN="center" class="dark">
   </c:when>
   <c:when test="${status.index % 2 != 0}">
   <tr ALIGN="center" class="light">
   </c:when>
  </c:choose>
</c:forEach>

which is a bit more simple, with the main benefit that you don’t have use any Java code.

Further, it seems that there is alot of overlap between JSTL and the Struts tag library, which isn’t a bad thing. I’m guessing that not everyone has the opportunity to use JSTL since it requires a web container that supports JSP 2.0, but for those who are deploying to JSP 2.0 web containers, how much do you use JSTL versus the Struts tags? Are you phasing out Struts tags for JSTL? Keeping with Struts tags to maintain a sort of purity to your application?