Create RESTful URLs with Wicket

Create RESTful URLs with Wicket

June 20, 2008 23:32 7 comments

This is a tutorial on using Wicket with REST-style URLs. Normally, Wicket generates URLs that are a bit ugly.
For example:

http://www.example.com/wui/?wicket:bookmarkablePage=%3Anl.stuq.demo.SomePage.

Ugly!

RESTful URLs change that: they are more meaningful for the user, hide some of your implementation details, and are just beautiful. Plus, you’re joining one of the latest hypes. Life couldn’t be better…

Looking around on the intertubes, there is not much useful information about using RESTful URLs in Wicket. Because I need this for a project I’m currently working on, I decided to turn this into a small tutorial.

What is REST?

Representational State Transfer (REST) is a software architectural style for distributed hypermedia systems like the world wide web. The best way to explain this, is an example. A REST application might define the following resources:

  • http://example.com/users/
  • http://example.com/users/{user} (one for each user)
  • http://example.com/findUserForm
  • http://example.com/locations/
  • http://example.com/locations/{location} (one for each location)
  • http://example.com/findLocationForm

This is a very, very short explanation of only a small part of what REST does. More information, as always, can be found on Wikipedia.

When you use custom URLs, you effectively hide some of your internal structure behind more meaningful URLs. This means you can refactor more easily without breaking external links or bookmarks to a specific part of your site. This is also important for search engine optimization.

Note: I’m not going to describe here when you should or should not use REST
with Wicket. That’s an architectural discussion, which depends greatly
on your project. I have discovered some limitations in the Wicket development model that prevent the full implementation of REST. Please read further for more information.

First steps

I suggest you download the code first and read along during the rest of this post.

We are going to create a customer overview page and a products overview page, reachable on “http://example.com/customers/” and “http://example.com/products/”.

The HomePage has two links, to the customer list and the product list. The product and customer lists have links to each individual product (http://example.com/products/${ID}) and customer (http://example.com/customers/${ID}).

For the Wicket UI, I created a HomePage, which links to the CustomerOverviewPage and ProductOverviewPage, which link to the Customer and Product detail pages. To serve up the data, we have some simple services, a ProductService and a CustomerService.

The code

Wicket has a nice built in method of declaring (mounting) custom URL schemes. Simply give a class which implements the IRequestTargetUrlCodingStrategy interface to a WebApplication.

public final void mount(IRequestTargetUrlCodingStrategy encoder)

Relatively new in Wicket is the MixedParamUrlCodingStrategy, which we will use in a minute.

This is an example of how to use the MixedParamUrlCodingStrategy in your WebApplication class:

        public WicketApplication()
        {
        MixedParamUrlCodingStrategy productURLS = new MixedParamUrlCodingStrategy(
                "products",
                ProductDetailPage.class,
                new String[]{"id"}
        );
        mount(productURLS);

This means:

  • "products"

    This is the part of the URL after the Wicket’s application URL. In this case: “http://www.example.com/products

  • ProductDetailPage.class

    This defines for which class this URL is meant. In our project, the ProductDetailPage shows a product’s details.

  •  new String[]{"id"}

    This is a list of all the parameters that you want to pass to this page. This shows up in the URL like this: “http://www.example.com/products/23” for a product with ID 23. You can easily pass more parameters to this page by adding items to this String array.

  • mount(productURLS);

    This passes this MixedParamUrlCodingStrategy to the WebApplication.

The Product detail page

The ProductDetailPage receives these URL parameters in the following way:

public ProductDetailPage(PageParameters parameters) {
int id = parameters.getInt("id");

After that, you can get the Product with this ID (the rest of the code can be downloaded below):

setModel(new CompoundPropertyModel(productService.getProduct(id)));
 
add(new Label("id"));
add(new Label("name"));
 
add(new BookmarkablePageLink("backLink", getApplication().getHomePage()));

Limitations of Wicket

It is currently not possibly (without doing a workaround outside Wicket) to do HTTP PUT, DELETE and POSTs to arbitrary URLs. If you do know how to achieve this, you are very welcome to post it in the comments.

Further steps

In the above tutorial we configured the URL’s in the WebApplication init() method. This has the drawback that information about a single page is in muliple places. It is good from an architecture perspective to configure the URL’s from the Page itself. Look at the wicket-stuff annotation project for more information on how to do that. You can find an excellent tutorial there. The wicketstuff-annotation library is used to mount your pages declaratively via Java annotations.

Further reading

Download

Download the complete example project and start experimenting! (run with mvn jetty:run and connect to http://localhost:8080/demo)

Let me know how and where you use it in the comments!

7 Comments

  • [...] MixedParamUrlCodingStrategy should also work (see blog) (exactly the [...]

  • Jared Blitzstein » Blog Archive » A look at Apache Wicket

    [...] Create RESTful URLs with Wicket [...]

  • I’m figuring out how to do proper url’s, and while searching for a solution, I arrived at your blog. I ran the demo, but I was dissapointed with the fact that the overview page for ‘customers’ and ‘products’ in your demo still have ugly urls (I was expecting to be able to view the overview pages at /products/ and /customers/ respectively). Mounting a bookmarkable page request to those pages however results in an error related to an already existing mount to ‘products’ and ‘customers’. But luckily there is a workaround(?), adding a trailing slash:


    BookmarkablePageRequestTargetUrlCodingStrategy productsURL = new BookmarkablePageRequestTargetUrlCodingStrategy("products/", ProductOverviewPage.class, null);
    mount(productsURL);
    BookmarkablePageRequestTargetUrlCodingStrategy customersURL = new BookmarkablePageRequestTargetUrlCodingStrategy("customers/", CustomerOverviewPage.class, null);
    mount(customersURL);

    Not sure though, whether this is a hack or not… but it worked for me. And while it is still limited, for simple applications in wicket its good enough… still searching for a more extensive URL writing mechanism though…

  • Hi. It was useful. Thank you.

  • Автоматическая режим смазки CONTILUBE, вообщем то, понижает срабатывание втулок да рабочего инструмента.

  • AP²

    This article is interesting, but that’s not related to REST. It’s just pretty URLs. In a REST application, the client must not know how to construct any URL; the architecture must follow the HATEOS constraint.

  • That is really attention-grabbing, You’re an overly skilled blogger.
    I’ve joined your feed and sit up for in quest of more of your excellent post.
    Also, I have shared your web site in my social networks

Leave a reply


Trackbacks

  1. it-fabrik blog » Human-readable (SEO friendly) URL in Wicket
  2. Jared Blitzstein » Blog Archive » A look at Apache Wicket