Tuesday, 31 March 2009

Less than Intuitive

I'm struggling with a cold and not feeling very sharp at the moment. Perhaps this accounts for me being over-sensitive about a couple of classes in Java that I've tripped over today? Or maybe writing JUnit tests most of the afternoon has numbed my mind?

The first is java.util.Calendar. It's not something I use every day and this little snippet is typical of mistakes I've made before.

    Calendar calendar = Calendar.getInstance();
    calendar.clear;
    calendar.set(2009, 03, 23);
    System.out.println(calendar.getTime());

I wanted March but my output was, of course, Thu Apr 23 00:00:00 BST 2009. Quite reasonably, if not intuitively, months are zero based in java.util.Calendar. But it's an easy one to slip on if you aren't paying attention or are feeling too lazy to type Calendar.MARCH as the second argument.

The second thing I fell foul of was the infamously tricky java.math.BigDecimal. Exemplified by this (although my actual problem was not so obvious):

    BigDecimal a = new BigDecimal("123");
    BigDecimal b = new BigDecimal("123.0");
    System.out.println(a.equals(b) ? "Same" : "Different");

The output in this case is Different. Again perfectly reasonable when you consider what BigDecimal sets out to achieve in terms of rounding control, but still less than intuitive for a spluttering and sneezing developer who's not used it for a while. Mental note: remember to specify the scale of numbers:

    BigDecimal a = new BigDecimal("123").setScale(2);
    BigDecimal b = new BigDecimal("123.0").setScale(2);
    ...

And all is well. Maybe after a good night's sleep I'll be the same.

Tuesday, 17 March 2009

Information from the AOP JoinPoint

I know. Logging is the most overdone and boring application of AOP, but even if you are planning on doing something more interesting with it, logging information about the method that triggered the advice is useful.

Here's just a couple of very simple reference examples on getting information about the joinpoint in the advice. They might save you five minutes hunting around in the JavaDocs. Let's start with Spring AOP/AspectJ:

public static final String getJoinPointDetails(JoinPoint joinPoint) {
    String className = joinPoint.getSignature().getDeclaringType().getName();
    String methodName = joinPoint.getSignature().getName();
    String paramList = CollectionUtil.listToString(joinPoint.getArgs());
    return className + " " + methodName + "(" + paramList + ")";
}

And the equivalent in an EJB3 interceptor:

public static final String getJoinPointDetails(InvocationContext invocationContext) {
    String className = invocationContext.getTarget().getClass().getName();
    String methodName = invocationContext.getMethod().getName();
    String paramList = CollectionUtil.listToString(invocationContext.getParameters());
    return className + " " + methodName + "(" + paramList + ")";
}

In both cases getName() is from java.lang.Class and returns the package name as a prefix to the class name. If you prefer a shorter version, you can use getSimpleName() to omit the package name.

The CollectionUtil.listToString() would go something like this:

public static final String listToString(List list) {
    StringBuilder sb = new StringBuilder();
    if (list != null) {
        for (int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            String s = o == null ? "<null>" : o.toString();
            sb.append(i == 0 ? s : ", " + s);
        }
    }
    return sb.toString();
}

public static final String listToString(Object[] array) {
    return listToString(Arrays.asList(array));
}

All very simple but handy things to tuck away in a library somewhere.

Friday, 13 March 2009

Simple Synchronizer Token with Spring MVC

The Problem

If you have used Struts 1.x, you'll probably be familiar with using the synchronizer token functionality provided through the saveToken() and isTokenValid() methods of the Action class. These prevent duplicate form submission, either as a result of double-clicking a submit button, or trying to submit a form from the browser history after using the back button.

Out of the box, Spring MVC doesn't have similar functionality, although it is being addressed with Spring Web Flow:

How to prevent user from double clicking the submit in a form using spring MVC AbstractTokenTransactionSynchronizer

So how could you use the synchronizer token pattern with Spring MVC if you aren't using Spring Web Flow?

Synchronizer Token

The basic idea of the synchronizer token pattern is that you keep a value in session scope that marks a point in the flow of the web application. As each form is rendered, it includes the value of the token from that point in time. On submission, the value that was embedded in the form is included in the request. The application can then compare the "historical" request token against the current session token. If the two are the same, processing continues and the session token is given a new value, effectively making the form out of date. If the two are different, it means that the form's token is lagging behind the current session token, i.e. the form has already been submitted.

So, in implementing the synchronizer token pattern, there are three components to deal with. Firstly, providing and managing the session token itself; secondly, having forms embed and submit the historical value of the token; thirdly, providing a mechanism for the application to check the request and session tokens and act accordingly.

1. Managing the Session Token

The way I choose to do this with Spring MVC is to borrow some ideas from the way that Struts 2 addresses the problem. I start off with a session listener to set up the token in session scope:

TokenListener.java
package mypackage;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class TokenListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent sessionEvent) {
        HttpSession session = sessionEvent.getSession();
        session.setAttribute(
            TokenFormController.getTokenKey()
        ,   TokenFormController.nextToken()
        );
    }

}

This listener has to be declared in web.xml of course:

web.xml
...
<listener>
    <listener-class>mypackage.TokenListener</listener-class>
</listener>
...

We'll see the code for the TokenFormController in a moment. For the time being, note that the session listener is fired whenever the container creates a session and it initialises the synchronizer token with a generated value.

2. Embedding the Historical Token in the Form

When we want to protect a form from duplicate submission, we need to capture the value of the token, embed it in the form as it is rendered and have the historical value submitted along with the other form data. The obvious way to do this is with a hidden field in the form.

Rather than worry about exactly how to do this in each form, I use a simple tag:

/WEB-INF/tags/token.tag
<%@tag description="Synchronizer Token" import="mypackage.TokenFormController" %>

<input
    type="hidden"
    name="<%=TokenFormController.getTokenKey()%>"
    value="<%=session.getAttribute(TokenFormController.getTokenKey())%>"
/>

This is easily included in the form JSP:

myInputForm.jsp
<%@ taglib prefix="tags" tagdir="/WEB-INF/tags/" %>
...
<form:form action="myAction.action">
    ...
    <tags:token/>
    ...
</form:form>

This example is written as if the Spring MVC dispatcher servlet is mapped to *.action. Obviously it doesn't matter and this is not a convention commonly used for Spring MVC but it keeps things clear for this example.

3. The TokenFormController

I find the simplest and most transparent way of getting the token functionality into form controllers is to use a custom controller derived from the SimpleFormController hierarchy. This subclass provides token checking and routing to an "invalid token" view. In my example the controller also handles the generation of the next token value and defines the name of the token attribute. We've seen this in action in steps 1 & 2. You may prefer to factor this out into a separate class.

As I tend to use CancellableFormController for most of my input forms, I've created my TokenFormController as a subclass of that. Here is the complete code:

TokenFormController.java
package mypackage;

import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.validation.BindException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.CancellableFormController;

public class TokenFormController extends CancellableFormController {

    private static final String TOKEN_KEY = "_synchronizerToken";
    private String invalidTokenView;

    @Override
    protected ModelAndView onSubmit(
        HttpServletRequest request
    ,   HttpServletResponse response
    ,   Object command
    ,   BindException errors
    ) throws Exception {
        if (isTokenValid(request)) {
            return super.onSubmit(request, response, command, errors);
        }
        return new ModelAndView(invalidTokenView);
    }

    private synchronized boolean isTokenValid(HttpServletRequest request) {
        HttpSession session = request.getSession();
        String sessionToken = (String)session.getAttribute(getTokenKey());
        String requestToken = request.getParameter(getTokenKey());
        if (requestToken == null) {
            // The hidden field wasn't provided
            throw new TokenException("Missing synchronizer token in request");
        }
        if (sessionToken == null) {
            // The session has lost the token.
            throw new TokenException("Missing synchronizer token in session");
        }
        if (sessionToken.equals(requestToken)) {
            // Accept the submission and increment the token so this form can't
            // be submitted again ...
            session.setAttribute(getTokenKey(), nextToken());
            return true;
        }
        return false;
    }

    public static String nextToken() {
        long seed = System.currentTimeMillis(); 
        Random r = new Random();
        r.setSeed(seed);
        return Long.toString(seed) + Long.toString(Math.abs(r.nextLong()));
    }

    public String getInvalidTokenView() {
        return invalidTokenView;
    }

    public void setInvalidTokenView(String invalidTokenView) {
        this.invalidTokenView = invalidTokenView;
    }

    public static String getTokenKey() {
        return TOKEN_KEY;
    }

}

It's all fairly straightforward if you are familar with the way the SimpleFormController hierarchy fits together. The onSubmit() method ties into the standard controller flow - you just override the usual doSubmitAction(), formBackingObject(), and associated methods in your subclass to provide the controller functionality for your input form. You can pretty much forget about token processing. You'll need the TokenException unchecked exception class but this is just a trivial subclass of RuntimeException.

The isTokenValid() method deals with the token checking. The nextToken() and getTokenKey() methods provide the next value and the name of the token respectively. Refer back to the session listener and tag to see how they make use of these.

The string attribute invalidTokenView, which is returned as the view name of the returned ModelAndView if the request and session tokens don't match, is injected using the dispatcher servlet xml file. Just the same as the way the cancelView property works with the standard CancellableFormController.

A typical configuration in the dispatcher servlet xml file would look something like this:

dispatcher-servlet.xml
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="myAction.action">myActionController</prop>
                ...
            </props>
        </property>
    </bean>
    ...
    <bean id="myActionController" class="mypackage.MyActionController">
        <property name="useCacheControlHeader" value="false"/>
        ...
        <!-- Required for CancellableFormController -->
        <property name="cancelParamKey" value="cancel"/>
        <property name="cancelView" value="redirect:myCancel.action"/>
        <!-- Standard FormController properties -->
        <property name="formView" value="myInputForm.jsp"/>
        <property name="successView" value="redirect:mySuccess.action"/>
        <!-- Required for the TokenFormController -->
        <property name="invalidTokenView" value="invalidToken.jsp"/>
    </bean>

For clarity, I've omitted other properties I usually have in here, e.g. a service facade bean that provides access to the Model, and validator references. MyActionController is the subclass of TokenFormController that manages the input form.

That's about it. The only subtlety here, if you want the same back-button behaviour as you might expect from Struts 1.x, is the useCacheControlHeader. Setting this to false (the default is true from AbstractFormController), prevents the browser from getting a fresh copy of the input form as it works back through history.

You'll probably want to do some tweaking if you want to use this in your applications, but hopefully that's enough to give you some ideas about how to implement the synchronizer token pattern with Spring MVC. I've found it quite a productive method.

Tuesday, 10 March 2009

Colour Schemes

I spend most of my time concentrating on the back-end of a web application and front-end design isn't one of my strong points. So anything that helps me to knock together a passable stylesheet and design for an application is welcome.

Enter the Colour Scheme Designer. Choose your basic colour from a colour wheel and let it build colour schemes based on mono, complementary or other models. To help you choose, it displays mock-up web pages in light and dark designs based on your chosen colours. It can even simulate various forms of colour-blindness. When you are happy, you can export the results as text, e.g. to paste as a handy reference in a comment in a CSS file, or as a GIMP palette.

Even if you don't follow the colour guidelines rigidly it's a good way of getting a start with a colour scheme.

Saturday, 7 March 2009

Composite Views with JSP

Tiles

Tiles has long been my first consideration for assembling pages from components. I got started with Tiles while working on Struts 1.x projects and went Tiles crazy before settling down to a fairly standard header, menu, content, footer approach. Apart from separating component layout from content, the nice part about Tiles and Struts integration was being able to forward to a Tiles definition without having to have a real page that assembled the components.

Tiles is Apache Tiles 2.0 these days, divorced from the Struts 1.x distribution. There are some minor syntactical differences between Struts 1.x Tiles and Tiles 2.0. <tiles:put> becomes <tiles:putAttribute>, for example, but this is just a minor irritation.

I've used Tiles 2.0 very successfully with both Spring MVC and Struts 2 applications. Integration is very straightforward in both cases and you quickly forget that you are using Tiles.

In both cases you define the TilesListener (or the TilesServlet or the TilesFilter) in your web application deployment descriptor:

web.xml
<listener>
    <description>Tiles Listener</description>
    <listener-class>org.apache.tiles.web.startup.TilesListener</listener-class>
</listener>

With Spring MVC, you define a view resolver for Tiles and you can then use a Tiles definition in the view name that you return from your ModelAndView.

dispatcher-servlet.xml
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>

With Struts 2, you define a new result type, optionally making it the default result type with the default="true" attribute. You can then use the Tiles definition in an action result.

struts.xml
<result-types>
    <result-type name="tiles" default="true" class="org.apache.struts2.views.tiles.TilesResult"/>
    ...
</result-types>

I've also tried Tiles 2.0 with JSF 1.1 but it didn't really play very nicely. It wasn't possible to specify a Tiles definition in a navigation rule and there was constant fiddling with <f:verbatim> tags in the tiles themselves to prevent content getting out of order.

I note that MyFaces has a non-standard extension in the form of JspTilesViewHandlerImpl, which allows forwarding to Tiles definitions:

wiki.apache.org/myfaces/Tiles_and_JSF

Sitemesh

Sitemesh looks pretty good for page decoration stuff like headers, footers, sidebars, etc. I like the way you can inject meta-data from the page header into the decorated page. I've not got round to delving much deeper than that.

This is a nice introductory tutorial for Sitemesh:

today.java.net/pub/a/today/2004/03/11/sitemesh.html

I was aware of issues with Sitemesh and JSF so my current JSF/JPA project wasn't the time to try and explore it in more detail:

forums.opensymphony.com/thread.jspa?threadID=36939&messageID=72427 mail-archive.com/users@myfaces.apache.org/msg34480.html

Prelude and Coda

For my current project, all I needed was a basic header with a CSS stylesheet reference and a standard footer. So I used the standard, but perhaps underused, mechanism provided for in the JSP 2.0 specification:

web.xml
<jsp-config>
   <jsp-property-group>
       <display-name>All Pages</display-name>
       <url-pattern>*.jsp</url-pattern>
       <include-prelude>/WEB-INF/jspf/head.jspf</include-prelude>
       <include-coda>/WEB-INF/jspf/foot.jspf</include-coda>
   </jsp-property-group>
</jsp-config>

I like this method for a simple layout or a prototype. Minimal setup. No additional libraries, servlets, filters or tag libraries to consider. But very quickly you can make your pages look consistent and respectable.

The prelude and coda have to follow the same rules as other included fragments, in particular that JSP and tag library start and end tags must always appear in the same document. This means, for example, that I couldn't open my <f:view> tag in the header and close it in the footer. It's OK to deal with HTML tags like <html> and <body> this way of course - there wouldn't be much point otherwise.

Bear in mind also that the include of the prelude and coda content is done when the JSP is first compiled, so a clean and build may be required after you add these directives to web.xml.

Friday, 6 March 2009

Entering the Blogosphere

So, here we go. My first tentative step into the world of blogging.

I've spent the last couple of weeks reviewing some JSF/JPA stuff in preparation for a training course that I will be running toward the end of March. At times it's been a frustrating exercise because of the lack of decent documentation. Fortunately bloggers who have been down the same road and who have had the generosity to write about it have played a major role in filling in the gaps. Thanks to you all.

I guess this is my way of putting something back into the pot.

Followers