shop
is your application's context name and wicket
the path where you mapped the Wicket filter, then by default, the url for the IndexPage will be akin tohttp://somehost/shop/wicket/index?wicket:interface=:0:headerPanel:index2::ILinkListener::
. I said ugly didn't I?Wicket has a mechanism for prettifying URLs. In ShopApplication, you can instruct wicket to "mount" a page on a specific path. Here is the code.
public class ShopApplication extends WebApplication {Wow, that was easy!
@Override
public ClassgetHomePage() {
return IndexPage.class;
}
@Override
protected void init() {
mountBookmarkablePage("index", IndexPage.class);
}
}
Now, assume you have a navigation panel, included on all the pages of your application, where you list links to the various pages of your application. Here is the markup:
<table cellpadding="0" cellspacing="0">We are referencing the mounted path "index" directly. How convenient is that? Although, convenient such references do not work correctly. The navigator will translate it into
<tr align="center">
<td><a class="menuitem" href="index">Index</a></td>
... other pages
</tr>
</table>
http://somehost/shop/index
instead of the correct http://somehost/shop/wicket/index
. For bookmarkable links such as "index", Wicket offers the
<wicket:link>
tag instructing Wicket to to automatically create bookmarkablelink components for the links inside the tags. So let's try that.
<tr align="center">The above is easy enough and will work, as long as all your pages are in the same java package.
<wicket:link>
<td><a class="menuitem" href="index">Index</a></td>
... other pages
</wicket:link>
</tr>
Indeed, the
<wicket:link>
tag doctors url references with respect to the java page of the current page belongs to, but if the page is located in a different package, then the urls will be rendered incorrectly. Bummer.So, we seem to be stuck. Googling for "wicket url mountBookmarkablePage" you will find an article by R.J. Lorimer on controlling Wicket URLs which did not go far in reducing my level of confusion. After further investigation, I found an example which caters for the use case we've been discussing so far, that is the nice-url example.
The nice-url example, after mounting the
Home
page as "/the/homepage/path", simply adds a BookmarkablePageLink to the Home class on another page, namely Page1. Here is the relavant code.<a wicket:id="homeLink" href="#">[go back]</a>which magically works, in the sense that when the link for the url is rendered, it will somehow contain the mounted path "/the/homepage/path". How does
public class Page1 extends WicketExamplePage {
public Page1(PageParameters parameters) {
add(new BookmarkablePageLink("homeLink", Home.class));
}
}
BookmarkablePageLink
know that Home is mounted on "/the/homepage/path"?It does not know. Instead, it invokes the
urlFor(IPageMap pageMap, Class pageClass, PageParameters parameters)
method defined in its parent class, Component
. This method will in turn ask the request cycle the page is associated with to find the correct url. The request cycle will eventually go through all mount points, asking them whether they apply to Home.class. The first mount point which applies will then be asked to encode the Home page, returning the mounted path. The exact details might vary, but from a 100 feet point of view, wicket does reverse lookup to see which mount point maps to a given page which goes to explain the aforementioned magic.