Skip to main content

Making Apache Wicket even more designer friendly

Posted by jjviana on February 9, 2010 at 6:00 AM PST

 

Hi, my name is Juliano Viana, I'm a software consultant and developer based in Brazil, and I've been honored with the opportunity to blog in Java.net! Hope I can contribute something to this great community resource.

For my first blog post at Java.net I've choosen to write about my web framework of choice, Apache Wicket.

A designer and developer friendly framework

Wicket is a great web framework - it allows the creation of complex web interfaces, complete with fancy ajax effects, in a simple and straigthforward way. The best Apache Wicket feature is in my oppinion the total separation between markup and business logic.A Web Designer working in an Apache Wicket project will probably never see a line of Java code, and the Developers can work on mock interfaces and be certain that when the time comes to make it look great the designers will be able to style it without any hassle.

Another feature I find extremely useful in Wicket is the page markup inheritance concept. In Wicket every page is a Java class that extends org.apache.wicket.Page.  Each page has also an associated HTML file containing the page markup.Wicket allows one to create base pages that contain your web site main markup and common funcionality (such as heder, footer, CSS files , analytics scripts, login area, search area, language selection box etc.). One can then create specialized pages that inherit this common layout from the base page and provides just the specialized content.

A Wicket Base Page usually looks like :

<html>
<head>
<title>
Your Title...
</title>
</head>
<body>
Common header goes here...
<wicket:child />
Common footer goes here...
</body>
</html>

The wicket:child tag is used to mark where you want specialized content to be placed. A Wicket page extending this base page will then contain only the following HTML:

<wicket:extend>

Page content goes here....

</wicket:extend>

At run time Wicket will combine both markups  in order to produce the final rendered page.

(for a complete description of how markup inheritance works in Wicket, see http://wicket.apache.org/examplemarkupinheritance.html).

 

What designers wanted

Recently I have started a new web project and (not surprisingly) decided to use Wicket as the main web framework. This project is not just a web application, but an entire web site. A website doesn't contain only application pages - it will have lots if informational pages like help, about, contact, news etc.

Once the designers decide the basic look and feel of the web site, this look and feel  can then be moved to the Base Page  and be automatically applied to all application pages.

This is great, but what if a designer wants to just create an informational page that still inherits the default web site content and behavior?

Here is the problem: since in Wicket each page is equal parts HTML and Java code, the designer needs to ask a developer to create a corresponding Java class for each page she wants to create, even if this page has pretty much the same behavior as the base page.

Wouldn't it be great if one could just place a HTML file into the web app content directory and have it automatically inherit all the features of a Wicket page?

The idea is to have a special page class (I've called it DynamicPage for the lack of a more appropriate name) that gets associated with any "orphan" HTML file in the web application  (meaning a file not already associated with  a Wicket page ).

DynamicPage should extend the application's BasePage and hence inherit all the common funcionality and layout.

This is a big departure from the way Wicket usually works, but would make our life much easier.

Customizing Wicket behavior

Thanks to the vision of the Apache Wicket creators one can customize almost everything in Wicket without having to resort to patching the code. After reading Wicket's code for a while I realized that I needed to implement a custom IRequestCycleProcessor. As the name implies an IRequestCycleProcessor is responsible for processing a web request, and among other things it routes the request to an appropriate RequestTarget (which in Wicket can be a Page or a component inside a Page, among other possibilities).

I've created a new IRequestCycleProcessor by extending WebRequestCycleProcessor (the default implementation) and overriding the method:

 public IRequestTarget resolve(RequestCycle cycle, RequestParameters parameters) {
.....
}

My implementation first calls the superclass implementation to try to resolve the request in the traditional way. If the super implementation cannot find a Wicket target for the request, and the request is for an existing HTML file, it then returns an instance of BookmarkablePageRequestTarget  which has DynamicPage as the Java class counterpart.

The next step is to make DynamicPage render the correct HTML markup file based on the request URL. This is accompished by making DynamicPage implement two interfaces: IMarkupResourceStreamProvider and IMarkupCacheKeyProvider. These interfaces tell Wicket that this page class is responsible for locating and loading its own markup.

A couple of aditional classes are required in order to make sure that Wicket is able to create page URLs for these dynamic pages correctly: DynamicWebRequestCodingStrategy and DynamicwebRequestTargetURLCodingStrategy. These classes are sligthly modifiied versions of the standard Wicket implementations and they help make the implementation complete: components inside these dynamic pages behave exactly as in "normal"pages, for traditional requests and also for Ajax requests.

Location, location, location...

Now that the designers can just create Wicket pages on the fly just by creating HTML files, they would also like to be able to place these HTML files in a separate folder from the Java source files. Wicket by default expects HTML files to be on the same directory as Java source files, and that is something that sometimes causes problems as designers don't feel very comfortable messing around with Java source code.

It is easy to change that by implementing  a ResourceStreamLocator  that tells Wicket where it should get the HTML markup files from. I have impemented a WebAppResourceStreamLocator which just loads the HTML files from the standard web context ( by calling ServetContext.getResource ). This implementation also allows one to strip common directories from the file name. This is useful if you use a deep Java package structure for your Wicket pages and still  want your web app directory to look "natural". For example, Wicket will by default look for the HTML file for com.mycompany.web.MyPage under "com/company/web/MyPage.html". With WebAppResourceStreamLocator one can configure it to look for just "MyPage.html".

Pushing the component model further

Now that we have come all this way, wouldn't it be nice if we could improve things further by allowing designers to include Wicket panels inside these dynamic pages without the need for developer intervention?

Why does that make sense? Well, suppose your developers create a cool product search panel which, being a component, can be placed in any page. The designers would probably benefit from the freedom to move this component around and even place it inside arbitrary pages with little effort.

I've solved this problem by registering a new Wicket tag "wicket:dynamic" which can instantiate and add components to dynamic pages on the fly. This tag looks a lot like the standard "wicket:component" tag, but unlike wicket:component it adds the components at page construction time (not on page rendering time). I have chosen to implement it because wicket:component is not a fully supported Wicket tag acording to the documentation ( some Wicket developers believe it goes againt the core Wicket philosophy), and because some components don't work well if added at page rendering time.

Putting it all together

In order to make it easy to use these customizations in any Wicket application I have created a class library called LogicWicket (library and source can be downloaded here).

In order to use LogicWicket to make your applications more designer friendly, all you have to do is:

  1. Include the LogicWicket jar file in  your web application
  2. Implement a Dynamic Page class. This class should  extend your application's Base page and implement a few methods that delegate to LogicWicket's DynamicPageSupport class (see the example DynamicPage provided).
  3. In your Wicket Application class  init method, register the custom resource stream locator:  getResourceSettings().setResourceStreamLocator(new WebAppResourceStreamLocator(getServletContext(),"com/mypackage/web"));
  4. In tour Wicket Application class, override the method newRequestCycleProcessor like this:
          
 @Override
    protected IRequestCycleProcessor newRequestCycleProcessor() {
        return new DynamicWebRequestCycleProcessor(getServletContext(), DynamicPage.class);
    }

Replace DynamicPage.class with the page class you have implemented in step 2.

 I have created an example app distributed with LogicWicket that can be used as a starting point for your own applications.

Happy coding!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Comments

I know it's been a while but.. Do you still happen to have ...

I know it's been a while but.. Do you still happen to have this source code? The download link is broken.

Is Wicket really the best?

Hi Juliano! With so many web frameworks around (I believe a new one comes to being each two weeks) it is a very rare case to see someone confident in comparing just several of them. I will appreciate if you apply your expertise to compare Wicket technology to HybridJava technology. Here is a reference to an article with another such a comparison: http://www.theserverside.com/discussions/thread.tss?thread_id=54866#320116

Hi, I have not used

Hi,

I have not used HybridJava so I can't really compare it with Wicket. But just a superficial look at it reveals what for me is a big let down: In Wicket a designer (someone who has no Java knowledge) can completely style an application without ever seeing (or having the possibility of changing) a line of Java code. From what I understand HybridJava combines markup and logic on the same file just like JSP, and I wouldn't want to go back there.

 

then how is dynamics coded in Wicket?

Apparently I am on my side not too experienced with Wicket. Not seeing a line of Java code is an understandable desire for a designer. But if not in Java - how in Wicket does that designer depict the fact, for instance, that a row will be repeated a number of times, unknown in advance? Would that be possible in pure HTML we would probably not need many other things (Wicket included).