Whether you are trying to make your app more RESTful or just keeping up with programming fashion, clean urls are essential in modern web applications and for good reasons.

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

Why does this matter at all?

  • 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. Assuming of course that the rest of your site looks as good as your neat urls...

  • It is easier for people to remember your urls and navigate to them manually. According to some research (can't remember the exact reference, just google it if you don't believe me), 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 may matter for SEO (opinions differ on this one).

  • Plenty of other reasons explained in a multitude of related published articles so if you want more google away.

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 (as it is a well established fact that xml is only good for sexual deviants), and would give me even more help with handling parameters.

To address this problem i wrote a small library called jurlmap. It was originally part of a framework I created to implement this website, (that is the website you are looking at right now). However I don't yet feel prepared to inflict another web framework on the world at this point, so I am releasing this as an independent library.

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.
    deploy(LoginPage.class);
}

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

Enjoy.