Arsenalist

The Toronto Raptors Blog with an Arsenal touch

Archive for the ‘struts’ Category

Unit Testing Struts 2 Actions wired with Spring using JUnit

Posted by Arsenalist on June 18, 2007

This post has moved here.

Posted in java, junit, spring, struts, tech, testing | 86 Comments »

Struts 2 Validation using Annotations

Posted by Arsenalist on May 10, 2007

This post has moved here.

Posted in java, struts, tech | 12 Comments »

Struts 2 Form Control Templates

Posted by Arsenalist on April 11, 2007

This, like many other areas of Struts 2 has remained virtually unchanged after it’s port from Webwork. The idea is that you can template the look of your controls in a fine-grained or application-wide level. Suppose you have a fetish for good practice and want to precede every occurrence of an input tag with a label tag like so:

<label for="firstName">First Name</label>
   <input type="text" name="firstName"
          id="firstName"/>

Although you can write a label tag for every input tag manually to achieve this effect, you can also specify a template to render your <s:textfield> tags to reduce the actual code you write in your JSP or Freemarker page.

Create a template called text.ftl in the folder template/mySimpleTheme and make sure template is in your classpath. Include the following in text.ftl:

<label
<#if parameters.id?exists>
for="${parameters.id?html}" <#t/>
</#if>
>${parameters.label?html}</label>

<#include "/${parameters.templateDir}/simple/text.ftl" />

The include file is pointing to a bare-bones template packaged with Struts which renders a simple <input type=”text”/> with all its attributes. All we’re doing in the additional code is doing a check for the existence of an id being passed in via the textfield tag and printing it in a label tag along with the value of label that is being passed in. Now that we’ve got a template to work with, all that’s left to do is use it. Here’s a way you can apply it to a single textfield:

<s:textfield id="firstName" name="firstName"
                theme="mySimpleTheme"
                label="First Name"/>

The above would render:

<label for="firstName">First Name</label>
   <input type="text" name="firstName"
          id="firstName"/>

The theme=”mySimpleTheme” declaration is telling Struts to look for a template in the mySimpleTheme directory under template (the default template directory). If you want this template to render all textfield elements instead of you specifying theme=”mySimpleTheme” every time, you can modify the struts.ui.theme and struts.ui.templateDir properties in struts.properties which have the default values of xhtml and template, respectively. To take a peek at the built-in templates that Struts provides, you’ll need to dig open struts2-core-2.0.6.jar and look at the template folder. This is probably a good exercise for anybody trying to develop a custom UI using Struts 2.

As mentioned the default theme is xhtml which renders <td>’s, <tr>’s and every thing else that is undesirable in markup. If you want to disable the rendering of anything but the attributes of the tag, you can use the provided “simple” theme as such:

<s:textfield id="firstName" name="firstName"
                theme="simple"
                label="First Name"/>

Alternately you could just set the struts.ui.theme to simple in struts.properties. You can also set the template attribute of each control to point to a different templates directory.

The overall mechanism for controlling appearance is completely different than Struts 1.x and somewhat more complex than it might need to be for many cases. It’s probably abstracted by erring on the side of caution and allowing you the freedom to tweak your templates any which way. Some might argue that there is an extremely tight binding between the display of controls and their functionality (both being controlled by Struts tags) and they would be true.

This is a fairly low-level method of controlling the look of a control and CSS is your best bet when trying to render them properly. Struts does use CSS classes when rendering their built-in themes of xhtml and xhtml_css although the naming might not be to your liking. For example, if you use their xhtml_css theme and use <s:textfield>, you’ll end up having to write CSS classes called wwgrp and wwlbl to control the display of labels and input elements.

One quick note, the xhtml_css theme also generates a very worthless <br/> tag between a label and the control which can throw of your entire look, do get rid of this you’ll have to do a .wwgrp br { display: none; } in your CSS stylesheeet.

This post has moved here.

Posted in java, struts, tech | 9 Comments »

Struts 2 and Zero Configuration for Actions and Results

Posted by Arsenalist on April 4, 2007

Struts 2 (WebWork on drugs?) comes equipped with some pretty nice features, one of them being Zero Configuration where you don’t have to write any XML configuration or muck around with property files to get your application up and running. You simply specify a path to your action packages and Struts will read the classes, create actions based on the class name and register it with XWork. Once you combine this with the annotation support for action classes which enables you to define results and namespaces, the struts.xml (or should I say xwork.xml) goes out the window.

To start with, you must specify the path your action packages reside in, this can be a comma separated list:

<filter>
  <filter-name>action2</filter-name>
  <filter-class>
  org.apache.struts2.dispatcher.FilterDispatcher
  </filter-class>
  <init-param>
  <param-name>actionPackages</param-name>
  <param-value>
  com.arsenalist.action,com.arsenalist.otheractions
  </param-value>
  </init-param>
</filter>

Here’s an example of how the classes in com.arsenalist.action that extend ActionSupport (or implement Action) get mapped to a URL:

  • LoginAction: Gets mapped to login. Since this class ends with the word Action, Sturts strips Action out of the name and converts it to lowercase. If you don’t want the action to be converted to lowercase, you must set the forceLowerCase to false for the ClasspathConfigurationProvider.
  • SubmitOrder: This gets innocently mapped to submitorder.
  • SubmitActionClass: Since the action is in the middle of the class name and not at the end, this gets mapped to submitactionclass.

So the URL to call the execute() method of the LoginAction class becomes:

http://<hostname&gt;:<port>/login.action

Remember you can call different methods in the action class provided you set the struts.enable.DynamicMethodInvocation property to true in struts.properties. The usual syntax for invoking dynamic methods applies here too, so to call the attemptLogin() method in the LoginAction class the URL will be:

http://<hostname>:<port>/login!attemptLogin.action

Now lets talk about specifying results in the action class via annotations instead of XML.

@Result(name=Action.SUCCESS,
  value="/WEB-INF/pages/login.ftl",
  type=FreemarkerResult.class)
public class LoginAction extends ActionSupport {

  public String execute() {
    return SUCCESS;
  }
  public String attemptLogin() {
    return SUCCESS;
  }
}

You can specify multiple Results using the @Results annotation. You may also specify namespaces for your actions classes using the @Namespace annotation, for example if we had declared @Namespace(“/security”) at the class level in addition to the @Result annotation, the URL to execute LoginAction.execute() would be:

http://<hostname>:<port>/security/login.action

Now if this is too much work for you and you would rather use default results instead of specifying them through annotations, fear not, there is something for you. It’s called the struts2-codebehind-plugin and instead of you specifying paths to results, it will implicitly assume the path to your result in the format of:

pathPrefix/actionName-resultCode.ext

where pathPrefix is specified in struts.xml. So an example path to a result would be /WEB-INF/pages/login-success.ftl. To use this, simply add this JAR to your classpath. Or alternately add the following to your Maven pom.xml:

<dependency>
  <groupId>org.apache.struts</groupId>
  <artifactId>struts2-codebehind-plugin</artifactId>
  <version>2.0.6</version>
</dependency>

You’ll also need to specify the pathPrefix in struts.xml or alternately declare a property in struts.properties.

<constant name="struts.codebehind.pathPrefix"
          value="/WEB-INF/pages/"/>

I don’t really like this method as its too too restrictive in its nature and sometimes the same result can be returned for different actions which would introduce a redundancy in the convention.

Important Note

The one thing struts.xml buys you is having multiple actions map to the same action class. For example, if you wanted to have /doThis.action and /doThat.action map to different methods in the same class, you wouldn’t be able to do it using annotations since they force you to have one action URL per class. In most of the development I’ve done, having one class per action URL added way too many action classes to the application. If I want to process CRUD operations for a user, it would make sense to have only one UserAction class with different action paths (/user/update, /user/delete etc.) which correspond to different methods in UserAction. Of course, you can always use the /actionName!methodName.action syntax to get around this restriction of annotations but once you start integrating something like Sitemesh into your app and want your paths nicely mapped to views, you might end up wishing you had used struts.xml.

This post has moved here.

Posted in java, struts, tech | Comments Off on Struts 2 and Zero Configuration for Actions and Results

Struts and Webwork: A Tale of Two Tools

Posted by Arsenalist on January 11, 2007

It wasn’t too many years ago that the people at Apache realized that you could probably come up with an organized way to use JSP’s and Servlets without making a huge mess. They called it Struts and it was a good, maybe even a great product when it came out. As the years went on and incremental releases of Struts started coming out, the product never really got better. Things were fixed here and there, maybe a feature was added but nothing worthy of a major release ever happened to it. Developers, even the slower ones, realized that an MVC framework offers a way to sanely manage the various scenarios in a web application, and even streamline some of the behavior common to their applications. Struts opened the door to a new wave of web development and served as the flagship product leading the way for J2EE.

However, Struts never got past the 1.x range of things because it never got significantly better. It always stayed the same and it’s committers decided that there’s no need to fix something when it’s not drastically broken. Then it was left to other people to come up with add-ons and plugins to Struts to make up for the lacking framework. Products like Struts Spring Plugin and Struts AjaxTags which had no business existing, were created. What should have been part of the framework, was now an add-on. It was left to Michael McGrady to figure out how to properly use buttons in a Struts application. All in all, Struts slowed down to a crawl until nothing but bug fixes highlighted the releases.

In the corner sat Patrick Lightbody and Jason Carreira who saw what Struts was lacking and started on Webwork, a framework that was based on common sense. OpenSymphony’s Webwork was a simple alternative to Struts that lacked the community support, but had all the features to make web development a whole lot easier. What the initial releases of Webwork lacked were more than made up for the groundbreaking Webwork2, which blew Struts out of the water in every way. Webwork2 had Spring integration, pluggable view rendering, an intuitive validation framework, dynamic action invocation, action classes that were simple and powerful and a tag library that supported them perfectly. Later releases of Webwork2 had Ajax capabilities and even made use of Java 5.0 generics and annotations. In short, if you had to start a new project, you’d be a fool not to go with Webwork.

I was a Webwork user and despised using Struts because it felt clumsy, redundant and boring. Then one day I was reading Patrick Lightbody’s blog and he mentioned that Struts and Webwork were merging for the betterment of the Java development community. I was shocked to see the pretty girl actually agree to a date with an 80 year old dying patient. There was no reason for it. In my shock I asked people why on earth Webwork would even want to be associated with a product like Struts that was good five years ago and was now reduced to being used by developers who refused to use anything except what they’re comfortable with. They told me that Webwork lacked the marketing power of Struts and nobody was going to use it because they were already using Struts. That to me wasn’t a reasonable explanation since I believed that people would soon see just how much better Webwork was than Struts and would naturally switch over. But my theory will never get a chance to be proved correct since the two have now merged.

So what convinced the Webwork folks to join forces with Struts? I don’t know. I’m not privy to that information but I’m sure it was a convincing argument. Now that the two have actually become one, I hope Struts2, now in beta, adapts a progressive and exciting approach to changing web trends and technologies much like Webwork did. I would hate to see Struts2 fall behind like its predecessor, especially when it’s got the great start it needs, thanks to Webwork.

Even though the body is Struts, I hope the soul is still Webwork.

Posted in java, struts, tech, web, webwork | 5 Comments »