Java / Web DevelopmentNo Comments
17
Jun 08

Using Velocity date tool with Spring MVC

I was having trouble getting Velocity‘s date tool to work with Spring MVC. I followed the instructions, most copied verbatim from what was most likely one ancient source. Those instructions said that to enable Velocity’s date formatting tool, DateTool, I needed to configure the VelocityViewResolver like this (WRONG):

<bean id="viewResolver">
  class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"></bean>
<br /><property name="numberToolAttribute"><value>numbertool</value></property>
<br /><property name="dateToolAttribute"><value>datetool</value></property>
&nbsp;

And then use it as:

$date.format("yyyy-MM-dd", $currentDate)

This would have been cool had I seen it in just one source but more than one source had it. The problem is small but crucial:

The value you give the dateToolAttribute property will be the name of the object Velocity will try to access when you are using the tool. So in the above configuration, the value for dateToolAttribute is “dateTool”, and hence the usage should be:

$dateTool.format(“yyyy-MM-dd”, $currentDate)

It may sound petty but it took me time to discover… lame.


31
May 08

Spring MVC binding problem

Spring MVC has a very peculiar approach to handling dates from form submissions. Gone are what I feel is the ‘standard’ approach to forms, via select drop-downs, and in comes the open input text field. That may be valid especially if you are using a JavaScript-based date selector element. Fine.

The issue is that those JavaScript date selector elements select just that, dates, and if you need both date and time, you will normally resort to two fields, one for date and one for time. I followed this approach and hoped to rely on Spring’s CustomDateEditor to handle the two fields separately, each with its own formatting. Issue is, that once you bind the CustomDateEditor to a target class (in the initBinder method of your controller), in this case java.util.Date, that will be the only binding ANY field that needs to be a Date object will use. You cannot have two custom property editors for the same target class.

One approach, as discussed in this message board discussion, recommends extending the CustomDateEditor and using a subclass of java.util.Date, such as java.sql.Time, to allow for the separate binding. I am still OK with this somewhat cludgy approach. What happens to me is something far more bizarre. The errors I get when Spring attempts to perform the binding complain about the nature of the date string the custom binder is receiving:

Failed to convert property value of type [java.lang.String[]] to required type [java.sql.Date] for property 'date'; nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: "[Ljava.lang.String;@1e07d3e,06/11/2008"

The interesting part here is the date: what Spring is getting is the something looking like an array of Strings, including the memory representation of a String object, sort of like a C-language pointer address. (WTF?)

I first examined the request object: when this was the initial submission of the form, the actual property for the field was invisible! In other words, calling request.getParameter(“date”) returned an empty String!

Looking further into this, I looked into I created a subclass of CustomDateEditor which overrides its setValue() method, so I can see what Spring MVC is passing into the property editor. Using Eclipse’s debugger, I discovered that what is passed in is indeed an array of Strings. The array contained two values – an empty string and the string containing the date that needed to parsed. Resubmitting the form put what I described as String pointer address value as the first member of the array, followed by the date string to be parsed.

I am truly puzzled by what is going on here. I am too tired to continue as it is late. Calling in the cavalry.


23
May 08

Setting up Spring MVC welcome page without rewrites or redirection

So you have a Spring MVC web application and want to make sure that when the user enters a URL such as
http://www.myawesomedomain.com he/she will see the home page of your application. How do you get Spring MVC’s RequestDispatcher servlet, which acts as the traffic cop and then some for your web application, to act as the default URL handler in the eyes of the web application? There are two good ways to do it, and two bad ones. Let’s start with the bad ones, of course:

  • Redirect through meta tag: you add a meta-refresh element to the head element which causes the browser showing the page to go the ‘real’ home page url, such as /index.do
  • You use JavaScript to force the page to redirect – this will also work but forces you to rely on client-side processes to get stuff done. For example: window.location="index.do" inside an index.html file.

Both are sub-prime because search engines are not too keen to follow such redirects, often time avoiding JavaScript altogether.

So what are the good ways:

  • Using Apache’s mod-rewrite to mask the URL of your application, but that assumes you have a web server in front of your application
  • Using the servlet API – which is what you read below

So how do you do it?

  1. In the application’s web.xml file map the RequestDispatcher servlet to handle requests for index.htm, aside from handling the extension of your liking, say, *.do. You do this through the servlet-mapping element. This should look like this:

    <servlet -mapping>
        </servlet><servlet -name>requestDispatcher</servlet>
        <url -pattern>*.do</url>
     </servlet -mapping>
      <servlet -mapping>
        </servlet><servlet -name>requestDispatcher</servlet>
        <url -pattern>/index.htm</url>
     </servlet -mapping>  
    
  2. Also in web.xml, set up a welcome file that may be requested by a browser when a user does not enter a specific page request, e.g. www.domain.com. Most browsers at a minimum will automatically request, on behalf of the user, index.html and index.htm.

So choose one, say index.htm and set the <welcome-file> element to look something like this:

<welcome-file-list>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>

This will make your application by default make requests for ‘/’ go to index.htm.

  • The last and final step is to map the url index.htm to the controller for the application’s home page. You do this in a Spring MVC beans xml file when specifying the URL mapper.
    For example:

    <bean id="unAuthenticatedUrlMapping"
            class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
          <props>
            <prop key="/index.do">homePageController</prop>
            <prop key="/index.htm">homePageController</prop>
          </props>
        </property>
      </bean>
    

    This way the RequestDispatcher will know which control is actually going to load the information that will be displayed by the view for the home page.

  • And that’s it. No redirection. No nonsense.