Saturday, November 12, 2011

Restful urls and spring mvc

Spring 3.0 boasts of Rest support. One aspect of this is using resource-based urls. For example, using /hotels/hilton/suiteNo1 instead of /hotels?hotel=hilton&room=suiteNo1.

So how do we achieve this? The typical fashion of using spring mvc is to map all the incoming requests that match some pattern (e.g. *.form) to spring's DispatcherServlet like this -


    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>*.form</url-pattern>
    </servlet-mapping>


This mandates that our application urls are like /hotels/hilton.form. This is not what we want here. We'd rather drop the .form if we can.

So lets map everything to the dispatcherServlet instead of just .form requests, shall we?



    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>


This enables us to drop the .form extensions. But there's a problem lurking here. A request for a static public resource like an image also goes via the dispatcherServlet. And since there won't be a controller defined for that, it'll throw a 404. We don't really want to map css and image requests to the spring servlet.
The problem can be summarised as follows : We want to map all requests except css/image/js requests to the dispatcherServlet.


How do we achieve this? Tuckey's urlrewrite comes to the rescue. In principle, its simply a Filter that lets us rewrite urls based on certain patterns. The order of processing is important. The filter will kick in _before_ the container chooses which servlet gets to handle the request. So what we need to do in the tuckey urlrewrite filter is to 'mark' all the urls which we want spring to handle with a certain prefix (say /myapp) and leave the css/image/js urls untouched. Furthermore, we configure the spring servlet to handle only those urls with that myapp prefix in them. Here's how the tuckey configuration looks:


    <rule>
        <name>Jsp Rule</name> 
        <from>**/app/**/jsp/**</from> 
        <to last="true">$1/$2/jsp/$3</to>
    </rule>
    <rule>
        <name>Css Rule</name>
        <from>**/css/**</from>
        <to last="true">$1/css/$2</to>
    </rule>
    <rule>
        <name>Js Rule</name>
        <from>**/js/**</from>
        <to last="true">$1/js/$2</to>
    </rule>
    <rule>
        <name>Spring Rule</name>
        <from>**</from>
        <to>/app/$1</to>
    </rule>

There is some duplication here - maybe all the resources can be moved under a common directory. But I'll leave that to all you responsible developers.
The 'last=true' bit is important - and something that was missing from many other blogs. Without it, tuckey just falls through to the next rule after one rule matches. So after matching /css/style.css it'll fall through to the spring rule and change it to /app/css/style.css. Won't do. The last=true means tuckey will not process subsequent rules if there is a match on that particular rule.

And there we have it. Beautiful urls.

Wednesday, November 9, 2011

Television

I am not a big TV fanboy. I generally prefer the outdoors instead. However, these days, for better or for worse, I've been watching a bit of TV. My focus is mainly on the wildlife, travel and sports ones. My favourite channel without a doubt is National Geographic HD. The astronomy-related shows are superb. They're also based on fairly cutting-edge and recent research. So its mostly stuff that you'd probably not know via other means unless you are working in a related field. Did you know there's a jet of water shooting from one of Saturn's moons? The wildlife shows are a good reminder of what is out there and we're missing. From seeing the annual migration of the wildebeest to understanding why the shark is nature's greatest killing machine ever built - maybe you can get by without knowing. But again, you're missing out. Other favourites are TLC (Travel and Living). Their shows provide a great insight into so many different cultures. I find it very interesting. As far as sports on TV are concerned, I don't have much time left to watch any more than the occasional Soccer and Cricket. There are definitely better ways to spend your time, but its not all bad.