Archive

Archive for July, 2006

TransientObjectException And Versioned Objects

July 30th, 2006

My unit tests started throwing Hibernate’s dread-inducing TransientObjectException shortly after I introduced @Version attributes into some of my domain objects. Assuming I was creating a parent-child relationship, the old code looked something like:

Long parentId = ... // passed in from some web form or link
Child child = new Child();
child.setParent(new Parent(parentId));  // convenience constructor
childService.save(child);  // throws TransientObjectException

The problem here is since the version object isn’t populated, Hibernate rightfully treats the object as unsaved and throws the TransientObjectException. One option is to load the Parent from the database, but that can be expensive, although not horrible if you’re using a second-level cache.

The other option is to update the convenience constructor to also set the version to some arbitrary value:

public Parent(Long parentId) {
    setId(parentId);
    setVersion(0);  // my @Versions are always integers.  yours may vary
}

Setting the version attribute will avoid the TransientObjectException. As long as your child object doesn’t have cascades that cause the parent object to be saved, this should work for you.

nick Entry

Struts Message Resources

July 29th, 2006

The MessageResources class allows a developer to easily support multiple languages, in addition to supporting multiple date and numeric formats. Another useful trait is that properly using resource bundles will allow the developer to store label strings in a centralized location, without having to duplicate the same string throughout your JSP code. For example, instead of having the string “First Name” in each form with a field for the user’s first name, you can simply refer to this property in the resources bundle with the following struts tag:

<bean:write key="label.first.name"/>

This will allow you to make changes easily, without having to open multiple JSPs or resorting to complicated regular expressions to change the label strings.

Usage

Getting started with message resource bundles requires you to:

  1. Create a message resources bundle for each locale you wish to support.
  2. Configure the web application to load the message resources bundle.
  3. Use the appropriate JSP tags to load the resources, or…
  4. …load the resource values from an Action class.

Creating the Resource Bundle

The default implementation of the MessageResources class takes a file with simple "key=value" lines as input. Below is our example message resources bundle file.

label.username=Username
label.password=Password
label.first.name=First Name
label.last.name=Last Name
label.email=Email Address
label.phone.number=Phone Number
label.welcome=Welcome back {0} {1}!

error.min.length=The input must be at least {0} characters in length.
error.max.length=The input cannot be longer than {0} characters in length.

The values with integers surrounded by brackets are a carry-over from the java.text.MessageFormat class. They allow the developer to pass in parameters that are inserted into the string. You can have up to four parameter fields per value string.

Configuration

There are two ways to tell Struts the location of your resource bundle: either by specifying it in your web.xml or in the struts-config.xml file. First, the web.xml configuration:

<servlet>
<servlet-name>action</servlet-name>
<servlet-class>
    org.apache.struts.action.ActionServlet
</servlet-class>
<init-param>
<param-name>

    application
</param-name>
<param-value>
    com.systemmobile.example.ApplicationResources
</param-value>
</init-param>
</servlet>

This configuration states that the name of the resources bundle is ApplicationResources.properties and it is located in the com.systemmobile.example package. The ".properties" extension is implied; you do not have to include it in the configuration. If you also have various resource bundles based on locale, such as ApplicationResources_fr.properties to support French, you only need to specify the base file name, as listed above.

The second, and likely preferred, method of making your resource bundle available to your Struts application is to specify it in the struts-config.xml file:

<message-resources parameter="com.systemmobile.example.ApplicationResources"/>

The parameter attribute is required. The same notes apply for this configuration method as for the web.xml method regarding the location of the file in the package structure and multiple locales.

Using the struts-config.xml file to configure your message resources is preferred as it gives you quite a bit of additional flexibility:

  • You can list multiple message-resources tags to load messages from multiple files. If you do this, use the key attribute to give a unique name to each bundle. e.g.:
    <message-resources key="myResources" parameter="com.systemmobile.example.ApplicationResources"/>
    
    <message-resources key="moreResources" parameter="com.systemmobile.example.MoreApplicationResources"/>

    You would then have to give the key name when using the bean:message tag:

    <bean:message bundle="moreResources" key="some.message.key"/>
  • Setting the null attribute to "false" will display missing resource values as ???key??? instead of displaying null. This string is easily found during automated testing of your JSPs, making in-container unit testing more complete. (Details about how messages are retrieved from resource bundles can be found in the Internationalization section.)
    <message-resources parameter="com.systemmobile.example.ApplicationResources" null="false"/>
  • Additionally, the message-resources tag allows you to use your own implementation of the MessageResourcesFactory class, which is outside the scope of this article.

Where To Put The File

The most common cause of problems with the message resources on the struts-user mailing list is where to put the actual file in the WAR. The short answer is that the file/files must exist somewhere in your classpath. This can mean putting it into a JAR file, or putting it in the /WEB-INF/classes directory, or in a subdirectory under classes. The table below gives the location of the message bundle file, the assocated value of the "parameter" attribute for the message-resources tag, and a short description if necessary.

Resources Location parameter Value Description
/WEB-INF/classes/ApplicationResources.properties ApplicationResources The file is in the classes directory, which is in the web app’s classpath.
/WEB-INF/classes/resources/ApplicationResources.properties resources.ApplicationResources The file is in the "resources" directory, and therefore package, so the directory name is given. [1]
In the app.jar file, in the com.systemmobile.example package/directory. com.systemmobile.example.ApplicationResources The full path to the file in the JAR file.

Tags

The most common Struts tag to use is the bean:message tag. This tag allows you to load a specific message resource from the bundle using the "key" attribute. It also allows you to populate any or all of the four arguments in the value:

<bean:message key="label.password"/>
<bean:message key="error.min.length" arg0="6"/>

<bean:message key="label.welcome" arg0="Ralph" arg1="Nader"/>

The html:message tag allows you to display errors (default) or messages to the user, while html:errors will only display error messages. Messages and errors must be present in the request, obviously, or there will be nothing to display. Here is an example of displaying the messages:

<logic:messagesPresent message="true">
  <html:messages id="msg" message="true">

    <div class="success">
      <bean:write name="msg"/>
    </div><br/>
  </html:messages>
</logic:messagesPresent>

Other tags have limited support for message resources, such as html:link. The html:link tag allows you to specify the title text with the "titleKey" attribute. Many of the html tags support the "altKey" attribute to load the alternate text label value from the resources bundle.

Actions

You can also access message resources from within Action classes. The Action class has the following methods to obtain a reference to a MessageResource instance:


// returns a resource bundle for the locale specified in the request
protected MessageResources getResources(HttpServletRequest request);

// returns a resource bundle for the locale specified in the request,
// for the given key as given in the <message-resources/> element
protected MessageResources getResources(javax.servlet.http.HttpServletRequest request, java.lang.String key);

The MessageResources class will allow you to retrieve locale-dependent messages from the underlying resource bundle. The API for MessageResources can be found in Resources. Some of the more commonly used methods include:

// these methods load a resources key for the given locale
public String getMessage(java.util.Locale locale, java.lang.String key);
public String getMessage(java.util.Locale locale, java.lang.String key,
       java.lang.Object arg0);
public String getMessage(java.util.Locale locale, java.lang.String key,
       java.lang.Object[] args);
public String getMessage(java.util.Locale locale, java.lang.String key,
       java.lang.Object arg0, java.lang.Object arg1)
public String getMessage(java.util.Locale locale, java.lang.String key,
       java.lang.Object arg0, java.lang.Object arg1, java.lang.Object arg2);
public String getMessage(java.util.Locale locale, java.lang.String key, java.lang.Object arg0,
       java.lang.Object arg1, java.lang.Object arg2, java.lang.Object arg3);

// these methods load a resources key for the locale retrieved
// from the HttpServletRequest
public String getMessage(java.lang.String key);
public String getMessage(java.lang.String key, java.lang.Object arg0);
public String getMessage(java.lang.String key, java.lang.Object[] args);
public String getMessage(java.lang.String key, java.lang.Object arg0,
       java.lang.Object arg1);
public String getMessage(java.lang.String key, java.lang.Object arg0,
       java.lang.Object arg1, java.lang.Object arg2);
public String getMessage(java.lang.String key, java.lang.Object arg0,
       java.lang.Object arg1, java.lang.Object arg2, java.lang.Object arg3);

Returned Strings can be set as attributes in the request or session and passed back to the view layer. You’ll notice that some of the various overloaded getMessage(...) methods take Objects as arg0...arg3. This is the equivalent to the bean:message arg0...arg3 attributes.

In addition to the MessageResources class, a few other classes make use of resources bundles. ActionMessage is used to pass message resource keys from the action to the JSP. Messages can apply to specific bean properties or can be generic. The ActionError, subclass of ActionMessage, class uses the resource bundle keys to store error messages when form validation fails.

Internationalization

Loading a specific message resources bundle for a give locale is handled by the MessageResources class, or by it’s immediate subclass, PropertyMessageResources. Since you’re likely to use the PropertyMessageResources class, we’ll examine how it loads message resources for a key using the getMessage(Locale, String) method.

  1. The message is located using specific Locales. If the message cannot be found, more generic Locales are used. For instance if the message can’t be found in ApplicationResources_pt_br.properties (Brazilian Portuguese), the ApplicationResources_pt.properties file (and therefore Locale) will be searched. If the ApplicationResources_pt.properties file does not exist or the key is not found, the mesage will be retrieved from the ApplicationResources.properties file. Increasingly generic resource bundles are tried until the default Locale is used.
  2. If the message key is found, it is added to a Locale-specific cache and returned as a java.lang.String.
  3. If the message key is not found, null is returned if the returnNull attribute is true, which is the default. If returnNull is false, a string such as ???key??? is return, where key is the passed message resources key.

JSTL

The JSTL (JavaServer Pages Standard Tag Library) fmt tag has recently come into vogue as the preferred way to utilize the message resources functionality with JSPs. It also works quite well with Struts. Setting it up is pretty simple, as the rules about classpath and file location still apply. After downloading the JSTL jar and TLDs and copying them into the appropriate places in your application, put the following configuration block into your web.xml:

<context-param>
  <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
  <param-value>ApplicationResources</param-value>
</context-param>

The above configuration is if the file ApplicationResources.properties is located in the /WEB-INF/classes directory. See above for the guidelines about configuration.

Then put this taglib directive into your JSP:


<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>

Finally, the following tag will load a resource:

<fmt:message key="label.first.name"/>

Here are some additional examples of using the fmt tags to load resource values. (Note: these were taken from the Jakarta JSTL examples.)

// loading a resource from a specific bundle and populating a parameter
<fmt:message key="currentTime" bundle="${deBundle}">
 <fmt:param value="${currentDateString}"/>
</fmt:message>

// using the forEach iterator to populate paramters
<fmt:message key="serverInfo" bundle="${deBundle}">
 <c:forEach var="arg" items="${serverInfoArgs}">
  <fmt:param value="${arg}"/>

 </c:forEach>
</fmt:message>

Conclusion

The message resources functionality in Struts allows you to easily create fully internationalized web applications, as well as providing a convenient abstraction between messages and the JSPs. The resource values can be loaded from within actions or using the Struts tags, although the JSTL tags are rapidly gaining favor. I hope that this article clarified a few things for you regarding this handy and, sometimes confusing, feature of Struts.

About the Author

Nick Heudecker is a software developer with more than six years of experience designing and building enterprise applications. His firm, System Mobile, Inc., specializes in application integration, custom software development and wireless applications. He is a Sun Certified Java Programmer and is located in Chicago.

nick Articles

Nutritional Supplements for Programmers

July 26th, 2006

Lately I’ve been getting a number of questions from colleagues on how to treat things like carpal tunnel syndrome, more commonly known as Repetitive Strain Injury, or RSI. These questions sometimes lead into other questions on how to treat another programmer ailment - eye strain. This entry covers a few nutritional supplements I’ve used in order to keep coding long after I should’ve stopped.

DISCLAIMER
Problems like RSI and eye strain/discomfort are your body’s way of telling you something is wrong and you should reduce or even stop your activity. However, deadlines often loom and you need to put in extra hours. The items I mention below may help you, but keep in mind the only real fix is to manage your work schedule more realistically. Before taking any of the vitamins or minerals mentioned below, please consult your doctor or medical professional.

Addressing RSI with vitamins is fairly simple: B-Complex. Lots and lots of it. When I start experiencing wrist pain, I take about 5000-6000 times the minimum daily requirement (MDR), then back down to 2000-3000 times the MDR as the pain subsides, usually the next day. Your body also needs vitamin C to process the B, so I also take some C with each dose of B.

Aside from the RSI, B-Complex is also an excellent antioxidant. Among other benefits, antioxidants can help prevent macular degeneration, the breakdown of the part of the eye that allows you to see fine details. Personally, I believe that loading up with antioxidants can help with general eye strain, but I can’t find anything to back that up.

For eye strain, I also take two multi-vitamin, multi-mineral pills, typically with the other pills. My preferred brand also has some B and C, but I’ve found that it’s not enough to stave off RSI. Vitamins A and C, as well as Zinc and Selenium have been shown to help with eye health, so make sure your multi has these in sufficient doses.

While the multis help with eye strain, you should take frequent breaks from staring at the monitor. This doesn’t mean you need to stop working - you just need focus your eyes on something else, preferrably far away. And no, a television a few feet away doesn’t count. Ideally something at least 15 feet away for a few minutes.

If you’re nearsighted and wear glasses, consider getting a separate pair of glasses with a weaker prescription for use when coding. After all, you only need to see to the monitor. I’ve had a second prescription for a few years and it’s helped greatly.

Buying Vitamins
Most people are overwhelmed when buying vitamins because of various brands and kinds. I prefer Carlson Labs, but if you don’t want to shell out the money for them, select a manufacturer that uses all natural ingredients. If you’re prone to getting an upset stomach, consider capsules instead of tablets. Capsules are often easier for the body to digest.

Aside from the benefits to coding, I’ve found that taking vitamins and the multis improves my general mood and ability to concentrate. (Playing a round of golf also helps me concentrate, but I can’t always get to the links when client demands are pressing.)

nick Entry

The Failure of Mobile ESPN

July 21st, 2006

Mobile ESPN launched in February of 2006 with a blistering ad campaign. Six months on, the service has only drawn ten thousand subscribers after spending more than $30 million on advertising. Why has Mobile ESPN been a failure?

Linking content and (a bad) device
If you want to subscribe to Mobile ESPN, you’ll need to signup with ESPN’s MVNO, which is actually run through Sprint. Currently, it’s not possible to access their content using another network. Requiring a dedicated network might not be so bad if the product were better. The only phone available for Mobile ESPN service is the Sanyo MVP. Mobile ESPN recently doubled its phone lineup with the addition of the Samsung ACE. However, two phones can hardly be called a broad selection.

Bad timing
The Super Bowl in 2006 was held in early February, before Mobile ESPN launched. Why a mobile sporting news service was launched after the nation’s most popular sport season ended is puzzling. Perhaps ESPN counted on NCAA March Madness to carry the service, but that doesn’t seem to have helped much. World Cup coverage also failed to draw more subscribers.

The upcoming NFL season may pull in more subcribers, but only if potential customers can access Mobile ESPN content using their preferred devices and mobile provider. Only time will tell if Mobile ESPN will become viable. In the meantime, it’s an excellent example of how not to run a MVNO.

nick Entry

AJAX-Enabled Select Lists with Wicket

July 17th, 2006

By now I’m guessing most people know about Wicket’s AJAX ability and how developers aren’t required to write any JavaScript for the vast majority of applications. AJAX is completely integrating to the component framework, which, I believe, is how AJAX should be.

A common use case for AJAX are dependent select lists. For example, a user selects from a list of States in the first list and the list of Cities is updated based on the selected State. Wicket makes this easy. There are a few steps we need to complete:

  1. Define the models used by the two DropDownChoice objects.
  2. Create the DropDownChoice objects.
  3. Wire the AJAX behavior.

If you’re not familiar with Wicket, it uses models as backing objects for Pages, Forms, and even FormComponents, like TextFields and DropDownChoices.

Let’s take a look at the complete form object, then we’ll examine the various portions below.

public class MyForm extends Form {

  private String selectedState;
  private String selectedCity;

  public MyForm(String id) {
    super(id);

    IModel stateChoiceModel = new AbstractReadOnlyModel() {
      public Object getObject(Component component) {
        return listOfStates;
      }
    };
    IModel cityChoiceModel = new AbstractReadOnlyModel() {
      public Object getObject(Component component) {
        if (selectedState == null) {
          return Collections.EMPTY_LIST;
        }
        return cityService.getCities(selectedState);
      }
    };

    DropDownChoice state = new DropDownChoice("state", new PropertyModel(this, "selectedState"), stateChoiceModel);
    state.setOutputMarkupId(true);
    add(state);
    DropDownChoice city = new DropDownChoice("city", new PropertyModel(this, "selectedCity"), cityChoiceModel);
    city.setOutputMarkupId(true);
    add(city);

    state.add(new AjaxFormComponentUpdatingBehavior("onchange") {
      protected void onUpdate(AjaxRequestTarget target) {
        target.addComponent(city);
      }
    }
  }

  public void setSelectedState(String selectedState) {
    this.selectedState = selectedState;
  }

  public String getSelectedState() {
    return this.selectedState;
  }

  public void setSelectedCity(String selectedCity) {
    this.selectedCity = selectedCity;
  }

  public String getSelectedCity() {
    return this.selectedCity;
  }
}

With the form defined, we’ll need some markup:

<form wicket:id="form">
  <select wicket:id="state"></select>
  <select wicket:id="city"></select>
</form>

Now I’ll point out the where the form handles the three steps I mentioned above.

1. Define the models used by the two DropDownChoice objects.
This step is completed in the following code:

    IModel stateChoiceModel = new AbstractReadOnlyModel() {
      public Object getObject(Component component) {
        return listOfStates;
      }
    };
    IModel cityChoiceModel = new AbstractReadOnlyModel() {
      public Object getObject(Component component) {
        if (selectedState == null) {
          return Collections.EMPTY_LIST;
        }
        return cityService.getCities(selectedState);
      }
    };

The ’stateChoiceModel’ provides the list of states to the DropDownChoice. Since we need to populate that when the page is first rendered, the list is simply returned. The list can be Strings, or a collection of POJOs. (Although if you’re using POJOs, you’ll need to look at IChoiceRenderer as well.)

Things start to get more interesting for the ‘cityChoiceModel’. Since we can’t populate the list of cities without the state, we fall back to an empty list. If the state populated, as it will be after the user selects a state, the list of cities will be populated accordingly.

2. Create the DropDownChoice objects.
Let’s take a look at the code that creates the DropDownChoices, since this is where you might be getting confused:

    DropDownChoice state = new DropDownChoice("state", new PropertyModel(this, "selectedState"), stateChoiceModel);
    state.setOutputMarkupId(true);
    add(state);

    DropDownChoice city = new DropDownChoice("city", new PropertyModel(this, "selectedCity"), cityChoiceModel);
    city.setOutputMarkupId(true);
    add(city);

You’ll notice that the code for both the ’state’ and ‘city’ drop-downs are the same except for a few Strings. Let’s look at one of the constructors:

new DropDownChoice("state", // #1
    new PropertyModel(this, "selectedState"), // #2
    stateChoiceModel); // #3
  1. Creates a new object with the given id. This id must match the markup.
  2. Creates a new PropertyModel. This is the model that’s updated when the form is submitted or when the form component is updated via AJAX. Since we’ve called new PropertyModel(this, “selectedState”), the form object’s ’selectedState’ property will be updated. This could’ve just as easily been a POJO or a HashMap.
  3. Pass in the model with the states. This is used by the DropDownChoice to create the options in the select list.

The same steps are take for the ‘city’ DropDownChoice. You’ll also notice that I called:

city.setOutputMarkupId(true);

This inserts an id attribute in the generated markup used to update the DOM. The generated id would look something like:

<select id="form_city">

Wicket handles inserting this id for you, so you don’t need to know what it is ahead of time. However, you must call ’setOutputMarkupId(true)’ for all components that you want to be updated via AJAX.

3. Wire the AJAX behavior.
Finally, we need to tell the ’state’ DropDownChoice to update the ‘city’ DropDownChoice when the select list changes. This is shockingly easy:

    state.add(new AjaxFormComponentUpdatingBehavior("onchange") {
      protected void onUpdate(AjaxRequestTarget target) {
        target.addComponent(city);
      }
    }

The AjaxFormComponentUpdatingBehavior is called with the ‘onchange’ event is fired. By adding the ‘city’ component to as a component of the AjaxRequestTarget, the model used by the ‘city’ DropDownChoice is updated, this time with a non-null selectedState.

That’s all there is to dependent select-lists with Wicket.

nick Entry

Creating PDFs with UJAC

July 16th, 2006

A recent project required me to create a number of PDF documents from information stored in a database - nothing new there. However, instead of using something like iText directly, I took a look at UJAC - Useful Java Application Components. The UJAC print module supports an XML abstraction over iText, allowing other personnel to create and modify the XML, and therefore the resulting PDF.

The XML is simple, as you can see from the following sample:

<document size="LETTER" margin-left="25" margin-right="25" margin-top="10" margin-bottom="25">
    <color-def name="border-color" color-space="RGB" value="204,204,204"/>
    <font-def name="header" family="Helvetica" size="14" style="bold"/>
    <font-def name="subheader" family="Helvetica" size="14" style="bold"/>
    <font-def name="label" family="Helvetica" size="12" style="bold"/>
    <font-def name="normal" family="Helvetica" size="12" style="normal"/>
    <font-def name="small" family="Helvetica" style="normal" size="9"/>
    <style-def name="header" border-style="bottom" border-width="1" border-color="border-color" font="header" />
    <style-def name="label" font="label"/>
    <style-def name="bottom-row" border-style="bottom" border-width="1" border-color="border-color" padding-left="15"/>
    <footer font="small">
        <footer-part padding-top="10" halign="center">Page ${pageNumber} of ${pageCount}</footer-part>
    </footer>
    <table widths="25,75" padding="10" padding-top="5" padding-bottom="5">
        <table-row font="header">
            <cell valign="top">
                <image source="logo.jpg" height="80"/>
            </cell>
            <cell font="header" valign="middle">
                Sample Header
                <paragraph font="normal">
                    500 E Main St. PO Box 312
                </paragraph>
                <paragraph font="normal">
                    Bedford MA 31239
                </paragraph>
            </cell>
        </table-row>
    </table>
    <paragraph font="subheader">
        Inspection Report - Completed: <date-format format="MMM, dd yyyy" value="${form.complete}"/>
    </paragraph>
</document>

UJAC ships with a date-format and number-format tag, but I ran into a problem formatting boolean values. Needing to support “N/A”, “Yes” and “No” output, I created my own BooleanTag. The closeItem() method is shown below:

    public void closeItem() throws DocumentHandlerException {
        if (!isValid()) {
            return;
        }

        Object value = null;
        try {
            value = documentHandler.evalObject(valueAttr);
        }
        catch (ExpressionException ex) {
            throw new TagAttributeException(locator(), "Attribute evaluation failed: " + ex.getMessage(), ex);
        }

        if (value == null) {
            phraseHolder.addChunk(this, "N/A", getFont().getFont());
        }
        else {
            if (!(value instanceof Boolean)) {
                throw new DocumentHandlerException(locator(), "Unable to format non-boolean values at boolean-format item.");
            }

            Boolean b = (Boolean) value;
            if (b) {
                phraseHolder.addChunk(this, "Yes", getFont().getFont());
            }
            else {
                phraseHolder.addChunk(this, "No", getFont().getFont());
            }
        }
    }

Most of this code was taken from the NumberTag in UJAC and repurposed. After the code was completed, I just had to update the UJAC DTD and register the tag with the DocumentTagFactory.

UJAC is great for creating simple or complex PDFs. I highly recommend it.

nick Entry

HTML Formatted Email

July 11th, 2006

A number of the projects we’ve been working on require HTML formatted emails. Getting email just right in your application is tricky enough without adding in the relative complexities of HTML. Creating HTML emails was particularly complicated for Eventful, which allows the user to define the look and feel of the HTML, including header and footer images.

David Greiner’s post on HTML formatted emails helped to shed a fair amount of light on a difficult topic.

nick Entry