Blog

Readable url’s in Wicket – An introduction to wicketstuff-annotation

09 Oct, 2008
Xebia Background Header Wave

Have you ever tried to pronounce a url generated by Wicket? It’s quite a tedious job and often end users want to have understandable url’s (even when that url has no meaning).
It’s is quite easy to get normal url’s in Wicket. In this article I’ll show you several solutions, the first two with plain Wicket and the final solution is with wicketstuff-annotations.

Recently I read an article called “Wicket Creating RESTful URLs”. It’s a useful article but it still didn’t feel right. It should be easier and in the right place.
In Stripes for example you can just put @UrlBinding("/helloWorld.action") on your ActionBean and it works. That’s what I want!
After some searching I found wicketstuff-annotation. Wicketstuff provides a large set of additions to Wicket to make it even better. wicketstuff-annotation is a small part of it.

Start from scratch

To demonstrate wsa (Wicketstuff annotation) I will let Maven 2 generate a simple Wicket application from scratch. To generate this application visit https://wicket.apache.org/quickstart.html

Execute this statement on the command line and you’ll have a working Wicket application within seconds.
Add a link to HomePage.html so you can see what url’s Wicket generates and how to improve them:

<wicket:link>
<a href="HomePage2.html?page=133&paragraph=25">
Link to wicket document HomePage2.html
</a>
</wicket:link>

Make a copy of HomePage.java and HomePage.html and call the files HomePage2.java and HomePage2.html. Change the href to HomePage2.html in the file HomePage2.html to HomePage.html. When you redeploy the application you will see the unreadable url I was talking about earlier:

https://xebia.com/blog:8080
/wicketstuff-test/?wicket:bookmarkablePage=:com.xebia.HomePage2&paragraph=25&page=133

I added the parameters page and paragraph to show that even these parameters can be made more readable.
Another bad thing is that we expose our package structure. End users don’t care in what package the page is and you shouldn’t give potential hackers any information.

The plain Wicket solution

The simplest solution is mounting a package to a path. We can map all of the package com.xebia to xebia.com/blog:8080/wicketstuff-test/web for example. Unfortunately we cannot map to the root (/) of the application. To mount a package add the following line to the constructor of WicketApplication:

mount("web",PackageName.forClass(HomePage.class));

The ugly url now looks much better:

xebia.com/blog:8080/wicketstuff-test/web/HomePage2/paragraph/25/page/133/

Even the parameters page and paragraph are improved.
Suppose you don’t want to expose the name of your WebPage (HomePage2) and also hide the parameter names. This can be achieved by mounting a MixedParamurlCodingStrategy to the application:

public WicketApplication() {
    String[] parameterNames = new String[] { "page", "paragraph"};
    MixedParamUrlCodingStrategy mixedParamUrlCodingStrategy =
new MixedParamUrlCodingStrategy(
            "h2", HomePage2.class, parameterNames);
    mount(mixedParamUrlCodingStrategy);
}

The problem with this solution is that you have to pass all parameters and put all class files in the Application file. The url structure and page parameters are related to the page, not the application, so they should be on the WebPage. But the result is a very nice url without  having to add an extra dependency to wsa:

https://xebia.com/blog:8080/wicketstuff-test/h2/133/25/

The Wicketstuff Annotation solution

To add wsa suppport to your application you have to add a dependency to your pom.xml:

<dependency>
     <groupId>org.wicketstuff</groupId>
     <artifactId>wicketstuff-annotation</artifactId>
     <version>1.1</version>
 </dependency>

The next step is clearing the old solution from the constructor of WicketApplication.
Add the folllowing line:
new AnnotatedMountScanner().scanPackage("com.xebia").mount(this);
This line will search the package com.xebia for annotations to mount url’s. In a production environment it is probably smarter to limit this to the package where all the WebPage classes are (ie. com.xebia.web).
Now we can finally add annotations to HomePage2 :

@MountPath(path = "h2")
@MountMixedParam(parameterNames = { "page", "paragraph" })
public class HomePage2 extends WebPage {
...
}

This works exactly the same as before, only in the right place.
There are several variations on the second annotation :

@MountPath (and no second annotation)
https://xebia.com/blog:8080/wicketstuff-test/h2/paragraph/25/page/133/
@MountPath and @MountMixedParam
https://xebia.com/blog:8080/wicketstuff-test/h2/133/25/
@MountPath and @MountQueryString
https://xebia.com/blog:8080/wicketstuff-test/h2?paragraph=25&page=133

There are several other encoding strategies you can use. On the wsa javadoc there isn’t much information. When you want to know more you should consult the Wicket javadocs and look for the package org.wicket.request.target.coding. The names used here are similar to the ones for wsa.

Conclusion

Wicketstuff annotation is a very nice addition to Wicket. It helps you to encode your url’s in the right place. The only small drawback is the dependency on Spring core, such a small library as wsa should work without Spring (not that Spring is a bad thing, I just don’t like many dependencies). So don’t be alarmed when you see a Spring jar pop up between your libraries.
Also be aware that the mount(path, packageName) solution is the safest when you don’t want to expose the package structure. When you forget to add annotations you end up with the ugly url’s and still exposing the package structure. I tried to add multiple mount points, but this wasn’t possible.

Sources

https://wicketstuff.org/confluence/display/STUFFWIKI/wicketstuff-annotation
https://css.dzone.com/news/wicket-creating-restful-urls
https://cwiki.apache.org/WICKET/url-coding-strategies.html

Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts