Thursday, September 3rd 2009

jurlmap - RESTful URLs for your Java app

If you are in the business of writing Web 2.0-ish applications then clean urls are an essential part of the package.

Bad => /member.jsp?username=tastychicken&view=blog&sort=hot
Good => /member/tastychicken/blog/hot

Here are some reasons why this matters:

  • Your app looks more professional and by paying attention to details such as your urls you will give people the impression that your app is rock solid, well designed and in general that you know what you are doing. This assumes that the rest of your site looks as good as your urls.

  • It is easier for people to remember your urls and navigate to them manually. According to some research that I once stumbled upon on google but now totally forgot where and what it was about, people spend as much as 24% of their time on a search results page looking at the returned urls, and are more likely to click on clean and informative urls than messed up ones.

  • It likely matters for SEO.

So if you are writing a site in java how do you go about implementing such urls for your app? There are several ways:

  • You can do it the old fashion manual way, like it was done for centuries.
    You can create a filter in which you manually parse urls and forward to servlets or jsp pages for the action. This becomes repetitive and unmaintainable very quickly.

  • You can use apache's mod_rewrite.
    And yet there are times when you would like to stay completely in java rather than having a part of your application (the url structure) stored in a completely separate and unrelated place. Plus maybe you don't want or can't run apache on your live setup for some reason.

  • You can use an existing library such as UrlRewriteFilter which implements in Java the functionality of apache mod_rewrite. This is a very good and powerful tool, and yet, I still prefer something that is more directly tuned to the single goal or creating clean urls, which would avoid multiple lines of xml configuration per url mapping (for some sage advice regarding xml usage go here), and would give me even more help with handling parameters.

To address this problem i wrote a small library called jurlmap. Some features of jurlmap are:

  • Simple pattern language for brevity and convenience
  • Direct binding of parameters to bean properties or method parameters
  • Configuration in plain java and annotations. No need for external configuration artifacts

Here are some url pattern examples:

protected void configure() {
    // In this pattern $ means a string, which when matched 
    // is bound to parameter `Username` and control forwarded to profile.jsp
    // Parameter will be accessible via request.getParameter()
    forward("/profile.jsp", "/profile/$Username");

    // Here % means integer pattern and * means until end of the pattern.
    // Binds integers to parameter ArticleId and forwards to article.jsp
    forward("/article.jsp", "/article/%ArticleId/*");

    // When matched will send a redirect back to browser and parameters
    // are appended to query string so in this case the target will
    // be `/servlets/profileservlet?Username=...`
    redirect("/servlets/profileservlet", "/member/$Username");

    // On match creates an instance of LoginPage and calls it's service method
    // LoginPage class implements com.pagegoblin.jurlmap.Page.
    // If it is annotated with a @Deploy(url) annotation
    // the we don't need to pass a url to the deploy method.
    // In this case parameters are bound to bean properties or fields 
    // of the newly created LoginPage instance.

Detailed info and more advanced use cases can be found in the manual.