Showing posts with label wicket. Show all posts
Showing posts with label wicket. Show all posts

Thursday, May 19, 2011

Apache Wicket Cookbook — book review

Some time ago I reviewed the drafts of the new book from Wicket rockstar programmer Igor Vaynberg: Apache Wicket Cookbook. If you are serious about using Wicket, this book is for you. It is fast, to the point, has very clear code samples and teaches you all the relevant (both clean and dirty) stuff you need and which Wicket in Action could not cover.

Conclusion: this is the book to read after 'Wicket in Action'.

Thursday, April 1, 2010

Another Wicket course coming up

I'll be doing the public Wicket introduction course from jweekend again on May 27 and 28. For more information see the link above or drop me a note.

Wicket root mounts

Just in case you missed it: I recently wrote an article that shows how to mount pages on the root in Wicket. As a lot of time went into creation the example application I posted the article on my employers blog.

Wednesday, September 16, 2009

Wicket do's and dont's

Just published an article on my employer's blog: Wicket do's and dont's.

Monday, May 25, 2009

More Wicket filter options

Wicket has this very clever idea to serve requests from a servlet Filter instead of a Servlet. The brilliance of it is that you can serve pages on the root of your context, but still allow the servlet container to process requests that Wicket has nothing to do with.

By default this works correct automatically. Incoming requests that are not recognized by Wicket are just passed through.

However, there is an optimization that is not very well documented. When you already know that certain paths are never going to be handled by Wicket (for example because you configured a servlet for them), you can tell the Wicket filter to ignore those paths in the same file as where you define the servlets: in the web.xml.

Example web.xml configuration:

<filter> <filter-name>wicket.filter</filter-name> <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class> <init-param> <param-name>ignorePaths</param-name> <param-value>images/,rest/</param-value> </init-param> </filter>
This will let the Wicket filter immediately pass through to the servlet container for all URLs that start with http://host/app-context/images/ and http://host/app-context/rest/.

Note: make sure the paths are comma separated without additional whitespace.

Monday, April 6, 2009

Wicket course preparations

Soon I will start teaching Wicket courses in The Netherlands. To prepare I spend some days in London with jWeekend teacher Cemal Bayramoglu (also know for organizing the London Wicket meetups). Most of our time we were at jWeekend's nice classroom, right in the middle of London, with close access to a very nice Thai restaurant, several coffee corners, etc.

The first day we went through the entire course that Al Maw and Cemal created. We had great fun discussing all the ins-and-outs. The second day we focused more on how the course should be taught.

I am really glad my company JTeam also thought it was a good idea to team up with jWeekend. The course is excellent and as the number of eyes on the material has only increased, will be even more excellent in the future.

Please contact as at info@jteam.nl if you are interested in getting a Wicket course.

Tuesday, March 17, 2009

Amsterdam Wicket meetup March 24 2009

The Wicket meetup has finally been given a date and time! March 24 2009, 19:00 - 22:00 in the Mövenpick hotel Amsterdam.

Presentations

Registration (do not register on the page above)

Wednesday, January 7, 2009

‘Effective Wicket’ presentation now on Vimeo

My Effective Wicket talk on NL-JUG’s J-Fall conference of 2008-11-12 is now online! Watch the presentation (Dutch spoken) on Vimeo: part 1 and part 2 (provided by bachelor-ict.nl).

Feel free to download the slides of Effective Wicket (mirror) (PDF 4.1 Mb). If you want to see the notes skip to page 55.

Thursday, November 13, 2008

Effective Wicket presentation

Yesterday was J-Fall, the fall conference of the NL-JUG. One of the presentations was my Effective Wicket talk. Feel free to download the slides of Effective Wicket (mirror) (PDF 4.1 Mb). If you want to see the notes skip to page 55.

If you want the original material (code/images etc.) for your own presentation, please drop me a note. Its all creative commons, copyright by JTeam.

Update 2009-01-07: Watch the presentation (Dutch spoken) on Vimeo: part 1 and part 2 (provided by bachelor-ict.nl).

Wednesday, October 15, 2008

Wicket extreme consistent URLs

Setting up a page to be behind a particular URL (aka mounting) in Wicket is fairly easy. Daan recently wrote REST like URLs for Wicket in which this is nicely explained. However, consistently keeping nice URLs, for example after a form submit, is a whole lot harder. So hard in fact, that even Wicket champion Igor believes it is currently not possible (it is an old post). His reasoning is of course completely correct, but he forgot one thing. Let me explain.

The problem
Many web applications have a login page. On it there is a form where you fill in your username and password. Suppose the page is mounted to:

http://example.com/login
with code like this in the application's init method:
mountBookmarkablePage("login", LoginPage.class);
When the user enters a wrong password, form validation (I assume you have a password validator) will fail and Wicket will redirect the user to a URL that points to the second version of the login page (the one with the error message). These URLs typically look like:
http://example.com/?wicket:interface=:0:::
For many applications this is just fine, in some its just too ugly.

A non solution
One of the proposed solutions is that you redirect to another page in the onError method of the form. E.g.

add(new Form(...) { @Override protected void onError() { setResponsePage(LoginPage.class); } }

The redirection will happen, and the URL is indeed that of the login page, but you will have no error messages. Instead of going to the second version of the login page, you have created a new instance of the login page!

Another attempt
We could pass the error code in the URL:

add(new Form(...) { @Override protected void onError() { PageParameters pp = new PageParameters(); pp.setString("error", "wronglogin"); setResponsePage(new LoginPage(pp)); } }

Unfortunately, with the default URL encoding stratey the URL will now be:
http://example.com/login/error/wronglogin
Not at all attractive.

Getting close
A fairly recent addition to Wicket is the HybridUrlCodingStrategy (and subclasses). Let's mount the login page with one of these:

mount(new HybridUrlCodingStrategy("login", LoginPage.class));

If a user now enters wrong credentials, Wicket will redirect you to
http://example.com/login.2
The .2 means the second version of the login page for the current session. If the user would delete the .2 from the URL, the HybridUrlCodingStrategy will find the latest available version of the page and serve that. A whole lot nicer but still not perfect.

The solution
If only if we could force Wicket to not display the version number. Well... we can! We'll have to do some coding first:

// First attempt, DO NOT USE public class NonVersionedHybridUrlCodingStrategy extends HybridUrlCodingStrategy { // ... trivial ctor @Override protected String addPageInfo( String url, PageInfo pageInfo) { // Do not add the version number as // super.addPageInfo would do. return url; } }

And now mount with:
mount(new NonVersionedHybridUrlCodingStrategy( "login", LoginPage.class));
Indeed, the version number is gone! However, there is still a tweak to be done. In some circumstance Wicket will redirect you to the latest version of the page, but now that redirect will be to the same URL. This is no problem for Firefox and IE, but Safari, Opera and many tools do not allow this. Here is the final version that does not have the problem:
/** * UrlCodingStrategy that will give the same * URL for every version of a page. * @author Erik van Oosten */ public class NonVersionedHybridUrlCodingStrategy extends HybridUrlCodingStrategy { public NonVersionedHybridUrlCodingStrategy( String mountPath, Class pageClass) { super(mountPath, pageClass, false); } @Override protected String addPageInfo( String url, PageInfo pageInfo) { // Do not add the version number as // super.addPageInfo would do. return url; } }

I named the URL strategy 'non versioned' as it no longer makes sense to have multiple versions of a page, just the last one will do. You should therefore also add the following fragment to each page constructor:
setVersioned(false);

Proof
Try it out! Go to tipSpot.com and try to login.

Sunday, May 4, 2008

Everything about Wicket internationalization

I have been using Wicket for about one and a half year (and followed it about a year longer), and only recently I realized the tremendous flexibility of Wicket. The core developers keep introducing major features by replacing large and small parts of the core, without changing much of the existing programming interface. It doesn't stop there though. Any good developer can do the same with relatively little effort. On occasion I replaced important parts of the core myself, just because I wanted it a little bit different.

Upcoming release 1.4 is all about introducing the long awaited generic models. But the release notes of Wicket 1.4-m1 contain another little gem. Created by non-core developer John Ray: child components within a wicket:message element. But before I explain what that means, lets first look at your internationalization options in Wicket.

This article requires you to have a very basic grasp of Wicket (what the application class is, how wicket:id is used, and simple components like Panel and Label). A bit of knowledge on Java properties helps as well.

Simple texts: wicket:message element, and wicket:message attribute
A simple web page easily contains dozens of texts that need i18n. It would be cumbersome to have to put a wicket:id on all of these, and then add a Label to each. Instead you can use the wicket:message element in the HTML file directly. For example in MyPanel.html:

<wicket:message key="helloworld">Hello</wicket:message>
The key (helloworld) is used to lookup the message in the property files. The default text (Hello) is used when the message could not be found.
The property files are (MyPanel.properties):
helloworld: Hello world

And for Dutch(MyPanel_nl.properties):
helloworld: Hallo wereld

The ouput with an English locale:
Hello world
You can do the same for HTML attributes. For example:
<input type="submit" value="Default text" wicket:message="value:helloworld"/>
Would result in:
<input type="submit" value="Hello world"/>
If there are multiple attributes to translate, add them prepended with a comma:
<input type="submit" value="Default text" wicket:message="value:helloworld,title:hellotitle"/>

Wicket's locale selection
As usual in Java i18n systems, messages are looked up by locale. The locale is automatically extracted from the HTTP request, but can also be explicitly set with getSession().setLocale(Locale.US).
If you need to override the locale for a specific component, override getLocale() on that component and it will be used by that component and its children.

If a client does not provide a preferred Locale, Java's default Locale is used. See Locale.getDefault() and Locale.setDefault(Locale)) for more information.

Finding the message
Another extremely powerful concept is how the message is looked up in the property files. Normally a properties file with the same name as the current component is used. E.g. if you are working within the component SummaryPanel, the message is looked up in the file SummaryPanel_nl_NL.properties (for Dutch, Netherlands locale). If that fails (either because the file does not exist, or because it does not contain the message), file SummaryPanel_nl.properties, and then SummaryPanel.properties are investigated. This is all just like Java's resource bundles work. But of course Wicket goes further. If the message is still not found, the property files of the parent class are investigated, and again, and again, all the way up to java.lang.Object. For each class all locale variants are searched for.

Components are reusable, but in order to make it really reusable you should be able to override the messages depending on where the component is used. This is facilitated by first looking up the message (following the algorithm above) for every parent in the component hierarchy (aka page hierarchy). Every component can override the messages of its child components, so the search starts at the page's properties and then trickles down to the component that uses it (yes, its top-down). In order to make overrides specific to a certain child component, you can prefix the message key with the component id of the child. See ComponentStringResourceLoader for more details.

If no message was found in the page hierarchy, another search starts which will look at your application class and its super classes. So Wicket first looks at MyApplication.properties (provided MyApplication is the name of your application) and then up the class hierarchy, passing org.apache.wicket.Application, up to java.lang.Object. This is how Wicket provides its many default i18n texts.

This might sound complicated, but in practice you simply have one properties file per page and some more for components that are reused over multiple pages. For smaller applications you can even put everything in one properties file. These rules work so well that you just do what you think is correct and it almost always just is.

One note on the location of the properties files: like HTML files, they must be in the same package (and same classloader) as the component they are associated with. In practice they live next to each other in the same directory.
If you want Wicket to get its resources from somewhere else (e.g. from a database), you can implement the interface org.apache.wicket.resource.loader.IStringResourceLoader and configure this in the init() method of your application class.

References: ExtensionResourceNameIterator, ComponentStringResourceLoader, and for real control freaks the new PackageStringResourceLoader.

Reloading and caching
When Wicket is started in development mode, changed properties files are detected and reloaded. To properly make use of this feature from an IDE, you should run Wicket directly from the compiled sources, for example with the Start file, included in every QuickStart. In Eclipse you just save the properties file, in IntelliJ you must do a make (Ctrl-F9) before changes are picked up. In production mode, resolved properties are heavily cached for performance. (Same applies to html files.)

Putting dynamic values in the messages
As soon as you need to add values to the messages, you also need to add some Java code. The java code provides the vales, but the rest of the text still comes from the properties file. One of the nice things here is how Wicket leverages java bean properties.

Here is a complete example. Not many frameworks make this so easy!

MyPanel.properties: summ: You, and ${otherCount} others, reviewed '${title}' \ and rated it ${rate}. MyPanel.html: <span wicket:id="summary">Text that will be replaced.</span> MyPanel.java: // Summary has getters for otherCount, title, etc. Summary summary = ...; add(new Label("summary", new StringResourceModel( "summ", this, new Model(summary))));
Resulting in something like:
<span>You, and 5 others, reviewed 'Wicket in Action' and rated it excellent.</span>
Property based message key It goes further: do you know a framework that can do this?
MyPanel.properties: summ.short: Thanks! summ.long: You, and ${otherCount} others, reviewed '${title}' \ and rated it ${rate}. Thanks! MyPanel.html: <span wicket:id="summary">Text that will be replaced.</span> MyPanel.java: // summary.getMsgPrefs().getStyle() returns "short" or "long" add(new Label("summary", new StringResourceModel( "summ.${msgPrefs.style}", this, new Model(summary))));
And more! The Java property syntax is also still available (e.g. like {0,Date}, {2,number,###.##} etc.)? You can find all forms in the javadocs of StringResourceModel.

The trouble with property files
Now this is all nice, but there is one problem you will frequently encountered while using string resources. In this problem you have a sentence that contains one or more dynamically constructed parts (for example some links). The order of these dynamic parts is potentially different for each locale. In the previous example, we may want to link to an information page on the title, and on the word 'others' open a modal window with a list of people.

If you try this with Wicket 1.3 (or any other Java framework I know of that uses resource bundles) you'll find that there is actually no pure way to do this. I know of 3 workarounds, but neither is very attractive. Lets review them. The first way is to split the texts before, after and between the dynamic components. This works good enough, but varying the order of the components is not possible unless you so something clever on the Java side, or have multiple HTML files. The latter is also workaround number 2: for each locale use a separate HTML file with the translation directly included (note: Wicket uses the same rules to lookup HTML files as it does for property files, e.g. MyPanel_nl.html just works like you expect it to). However, having more then one HTML file per component often leads to maintenance horror as changes must be synchronized over many files. The third workaround is to add placeholders to the message text that later are replaced by some HTML. That HTML is either hand written (in which case you may wonder why you started with Wicket at all), or you need to do some serious Wicket hacking to get components to render to a StringBuffer.

Now lets do this with Wicket 1.4-m1:

MyPanel.properties: summ: You, and ${othersLink}, reviewed ${titleLink} \ and rated it ${rate}. others: ${otherCount} others MyPanel.html: <wicket:message key="summ">Text that will be replaced. <span wicket:id="rate">rate</span> <a href="#" wicket:id="titleLink"> <span wicket:id="titleLabel">label</span></a> <a href="#" wicket:id="othersLink"> <span wicket:id="othersLabel">label<</span></a> </wicket:message> MyPanel.java: // Note, we directly add the embedded components // rate, othersLink and titleLink add(new Label("rate", new PropertyModel(summary, "rate"))); Link othLink = new Link("othersLink") { .... } add(othLink); othLink.add(new Label("othersLabel", new StringResourceModel( "others", this, new Model(summary)))); ExternalLink titleLink = new ExternalLink( "titleLink", summary.getTitleUrl()); add(titleLink); titleLink.add(new Label("titleLabel", new PropertyModel(summary, "title")));
The html file contains a wicket:message element with some embedded components. All text within the element is removed and replaced by the text from the properties file. Labels like ${othersLink} are replaced by the rendered component of the same wicket:id. That component must be embedded in the wicket:message element. Note that the order of the components is irrellevant. Also note that you will not see any reference to the wicket:message element in the java code.

If you want runnable code you can download the complete example code (a Maven 2 project based on Wicket's QuickStart). See below for instructions.

Getting string resources from code
Despite all of the above, there always remain some cases in which you need direct access to the messages. Luckily Wicket provides access through the Localizer. You can get the localizer from any component with getLocalizer().

Again, see the complete example code for an example.

Encoding troubles
Fairly unknown to beginning programmers is that you are only allowed to use ISO-8859-1 encoding in java properties files. If you live in Europe this is a fairly annoying as many languages have characters that are not known to ISO-8859-1 (for example the euro symbol €). The simple workaround is escaping: cree\u00EBr instead of creeër. (I always use this site to look up the ISO codepoint.)

But imagine you are making a site in Thai! Luckily Wicket can also read XML property files. Here is a fragment of the Thai properties that comes with Wicket:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="Required">ข้อมูลใน ${label} เป็นที่ต้องการ.</entry> </properties>
Nice!

Sample code
To test the code in this article I created a small test application. Unzip it, and run mvn jetty:run to start it. When it is started access it on http://localhost:8080/i18ntest.

Changing resource settings
Finally, if you need more power, you can change all of Wicket's settings in the init() method of your application. Call getResourceSettings() to get a IResourceSettings instance. Let look at some of the options.

ThrowExceptionOnMissingResource: this will make Wicket throw an exception when a resource is missing. At first this may seem a convenient way to test that you listed all messages in a properties file. However, many standard Wicket components use defaults as fall back, so this option is mostly useless. Alternatively, watch for warnings in the log.

UseDefaultOnMissingResource: this will make Wicket use the default value (e.g. the text within the wicket:message element) when the resource is not found in a properties file. Setting this to true (the default) may hide errors for a long time, but setting this false will make your site not work if you made an error. Choose carefully.

There are many more options that allow you to change what, when and how properties are loaded. I have never found a use for these, but they are there if you need them.

Conclusion
As you have seen in this article, Wicket provides simple ways to do everything around internationalization, and some more less simple ways to completely customize this for the rare case you need it. Furthermore, the new Wicket 1.4 release will make it a lot better with support for componenta embedded in a wicket:message element. You can download the example to see everything in action.

Update 20080526: Incorperated the comment from Stefan Fußenegger on what happens if the user gives no preferred locale.

Update 20080527: Scott Swank put this article on the Wicket Wiki. Feel free to edit it there!

Update 20091203: Corrected text after Satish_j pointed out that I made a glaring mistake in the order messages are looked up in the page hierarchy.

Wednesday, February 20, 2008

Repeated lesson: always distrust 3th party code generators

Warning: rant follows!

I am usually try to avoid generation tools. But I fell for it again. I thought that using Wicket Web Beans would speed up development of the administration screens in my current project. Indeed, the first screens were shown very quickly. But a few weeks later, it did not turn out to be so smooth as expected.

Here are some of my pain points:

  • You must explicitly exclude properties you do not want to see. So when you add the method boolean isPersisted() in the base class of all your entities, you must visit the meta data for each entity and add "-persisted".
  • Writing new types of input fields for specific properties works, but is a little clumsy.
  • I have no clue how to add validation. Especially when you consider the excellent vlidation support in Wicket has for this, it is kind weird that it is not clear how to do this with Wicket Web Beans.
  • When you have a recursive data structure, Wicket Web Beans crashes during the render phase with a StackOverflowException!
  • Somehow I failed to get custom input fields for collection properties.
Some positive points:
  • Support is good though the wwb user e-mail list. Unfortunately, I failed to provide the correct input (which is source code) as we changed the code constantly in an attempt to work around to shortcomings mentioned above. Secondly I did not want to sent our domain objects to a public list.
  • For simple domain models you are probably quickly set up and done.

Okay, we could have worked on Wicket Web Beans itself. After all it is open source. The code quality seems quite alright though I expect you need some time to get into it. Due to project dynamics and considering the excellent Wicket form support, I decided to pull out.

Unfortunately its now 2 days before the end of the sprint. So in 2 days we will shame ourselves in the demo before the customer with almost nothing working. Hopefully we can do better next week with regular Wicket forms.

Note: 'me too' comments are likely to be removed. I am also very interested in success stories!

Update, a couple of hours later: I reworded the article a bit as I found the first version too harsh.

Sunday, December 16, 2007

WebBeans, the JSF cover up

At JavaPolis I saw very good presentation on WebBeans by Bob Lee. Bob did a very good job in explaining the concepts while thankfully still giving lots of code examples. WebBeans provides a way to use ordinary Java beans in the JSF environment. You do this with annotations.

Praise for WebBeans, and its main predecessor Seam; they really make developing JSF applications simpler. In particular, the conversation scope is a brilliant invention. But how simple does it get? Well lets see. For every aspect that can be managed there is an annotation. In one of the presentation examples I counted about 5 lines of ordinary Java code plus at least 12 annotations! Now there are ways to group annotations, but you do this by introducing more annotations! So instead of having to deal with JSF stuff, you now how to cook annotation soup.

I have always hated JSP programming, and now that I see that even talented people like Bob Lee and Gavin King are wrestling to fix JSF, I finally know why. The problem is that the whole idea of having contexts to store page data is flawed. It breaks all kinds of encapsulation rules and breaks the beloved type safety.

So what are the alternatives? Actually there are a few very nice web frameworks that do not use contexts. The one I am most familiar with is Wicket. Another often named contender is Tapestry, but of course there are many more. Wicket, like Swing, uses a component tree to build pages. Each component is completely responsible for its own markup (html) and data (the model). No encapsulation rules are broken. Another addition is GWT, not exactly a web framework, but nevertheless useful for making componentized web applications.

Thursday, May 24, 2007

Wicket for BSCs, part II

So you are in a Big Slow Company (BSC) and want to switch to Wicket. I wrote about this before, but today's e-mail from Mark Stock on the Wicket user list backs up the arguments with some hard figures. Here is an abstract with some key phrases:
In my experience, it's taken me about two weeks to get up to speed on Wicket. ..... Now, the prototype that I have so far would have probably taken me at least two weeks in Struts 1 and I already know Struts 1 very well. The difference in productivity between the two frameworks is pretty dramatic.
So? What are you waiting for!

Tuesday, May 1, 2007

Wicket article translated to French

My article Backward compatible AJAX development with Wicket has just been tranlated to French by ZedroS! Nice work Joseph!

Thursday, March 8, 2007

Turmoil in Wicket land

The impossible task faced by the Wicket team is finally coming to an end. For months and months work was done on 2 branches (1.3 and 2.0), with a third in maintenance mode (1.2). Three branches is realy too much for a group of volunteers. For the uninitiated: the 1.3 and 2.0 branches differ in one major big way: 2.0 has one extra argument to each and every component. Another large difference is that 2.0 supports generic models. For the rest, most new features and fixes were added to both 1.3 and 2.0.

So what are the options? It seems that the 'constructor change' will be dropped. This means that the 2.0 branch will be abandoned. All other 2.0 only features will be ported to 1.3. Users that use the 2.0 beta code from svn will have to migrate to 1.3.

Is this good news? I think so! If this turns out to be true, the excellent work of the Wicketeers will be much more focused again. Furthermore, all the good new features will be available for Wicket users of all branches!

Update 2007-03-19 And yes, it did turn out to be true:

I think it is time to close the vote and count our blessings. [...]

7 +1 binding votes, [...] 4 abstainees, and no non-binding votes.

This wraps it: we will drop the constructor change and migrate all features of trunk to branch 1.x in 2 releases: everything non-Java 5 goes into 1.3 and java 5 specifics into 1.4

Martijn

Tuesday, March 6, 2007

Wicket to the recue!

My previous site (for the municipality of Amsterdam) is barely finished, and I have already convinced my next client (where I work as a consultant) that Wicket is more suited for them then Spring MVC. Life is sweet! Spring MVC has a lot of Spring quality, but the programming model is just not what I want to work with. Wicket to the rescue!

Sunday, January 7, 2007

Backward compatible AJAX development with Wicket

(Also published in Dutch and French, French translation by ZedroS).

Despite the general acceptance of AJAX, there is still some reticence in some sectors. The rich interaction provided by AJAX can not be used by people that, because of their handicap have to use a browser that does not support Javascript or CSS. For a sector like the government it is not acceptable to exclude these people and I believe this is an attitude that should be practiced more often.

Many developers today can or will only create web applications that work solely in Internet Explorer. Building an AJAX application that also works without Javascript is simply too much for many companies. To do this anyway, a number of techniques are known. A more general approach is given by Unobtrusive Javascript, but this article presents a different, more flexible approach that uses Wicket.

Wicket is one of the few fully component based web frameworks. In such a web framework one combines components to larger components until you have a web page. The advantage of components is that it is a lot more comfortable to develop and modify components separately. With a page oriented web framework one must usually develop the whole page simultaneously. Struts for example prescribes that you first collect all information for the whole page before a JSP page will render the (whole) page.

Composing Wicket components (a Wicket introduction)

Once creates a component in Wicket by writing an HTML fragment (the template) and by writing Java code that couples more components to the template. Creation and coupling of components happens during the construction phase. During the render phase the components can add or change the fragment or even completely replace it.

Lets look at an example. Here is an HTML template and the associated Java code:

<h1 wicket:id="title">_Template title</h1>
add(new Label("title", "The real title"));
The Label component is coupled to an h1 element. Label will put the real title in the HTML template during the render phase. The result is:
<h1>The real title</h1>

Composing components is just as simple. Suppose we want to use a title with subtitle on many places. We will create a component for that, a Panel to be precise:

<wicket:panel>
  <h1 wicket:id="title">_Template title</h1>
  <h2 wicket:id="subtitle">_Template subtitle</h2>
</wicket:panel>
class TitlePanel extends Panel {
  public TitlePanel(String id, String title, String subtitle) {
    super(id);
    add(new Label("title", title));
    add(new Label("subtitle", subtitle));
  } }
The panel can now be used (for example in the template of another panel) with:
<span wicket:id="titlepanel"></span>
add(new TitlePanel(
  "titlepanel", "The real title", "with a subtitle"));

Linking between pages is done with the Link component:

<a href="#" wicket:id="detaillink">Book details</a>
add(new Link("detaillink") {
  void onClick() {
    setResponsePage(new DetailPage(bookId));
  } });
The Link component will put a Wicket generated href attribute on the a element during the render phase. When the link is clicked the Wicket servlet will call the onClick method. In this example the response page is changed to a page that is constructed on the spot (pages are of course also components). After this the response page is rendered and sent to the browser. If the onClick method was left empty, the response page would not have changed and the current page is rendered again.

Dynamic pages in Wicket

Links are not only for jumping to other pages. In Wicket it is just as easy to change a part of the page by replacing a component by another one. Lets extend the example a bit:

final BookDetailPanel bookDetailPanel = ...;
add(bookDetailPanel);
add(new Link("detaillink") {
  void onClick() {
    bookDetailPanel.replaceWith(
      new BookDetailPanel(bookId));
  } });
Clicking the link leads to a change in the current page. After this the current page is rendered again, and another book is displayed. Note that exceptionally little code is needed. In many other web frameworks all information of the complete page must be collected again.

The observant reader will have noticed that replacing a piece of a page is a trick that is nowadays mostly done with AJAX. In the example however, we have not used a single line of Javascript. Since the whole page is send to the browser again and again, lets change the example a bit more:

final Component bookDetailPanel = ...;
bookDetailPanel.setOutputMarkupId(true);
add(bookDetailPanel);
add(new AjaxFallbackLink("detaillink") {
  void onClick(AjaxRequestTarget target) {
    Component newBookDetailPanel =
      new BookDetailPanel(bookId);
    newBookDetailPanel.setOutputMarkupId(true);
    bookDetailPanel.replaceWith(newBookDetailPanel);
    if (target != null) {
      target.addComponent(newBookDetailPanel);
    }
  }
});
During the render phase the component AjaxFallbackLink generates both a href and an onclick attribute on the coupled a element. Furthermore it makes sure that a number of Wicket Javascript files are added to the HTML header. Depending on whether Javascript is supported, the browser will request either a normal URL, or it will do an AJAX call. In both cases the Wicket servlet will call the onClick method. In the first case the argument of onClick is null and everything will work exactly as in the previous example. When an AJAX call is done, Wicket will only render the components that were added to the AjaxRequestTarget and the result of that is sent to the browser. On the browser side, the Wicket Javascript searches for the element that needs to be replaced by using the id attribute. To make sure it is set, method setOutputMarkupId(true) is called.

With just a few lines of code we have created an AJAX application that even works in browsers without Javascript.

Conclusion

This article shows only a small piece of Wicket's AJAX capabilities. For example it is fairly easy to let the user know an AJAX call is in progress, to quickly execute some Javascript before an AJAX call (for example to disable a submit button), or to validate a form input when it changed.

Wicket is not only a fantastic framework to easily build modern and maintainable web applications, it is even possible to do it in such a way that older and special browsers can deal with them.

Friday, December 15, 2006

Why would you go for Wicket too?

To answer that question Ryan Crumley investigated a couple of web frameworks for long term web development. He choose Wicket for a number of teams, even though there was lots of knowledge for older things like JSP. You can read his report to the wicket user list on nabble.

Thursday, November 30, 2006

Wicket most active Java Web framework forum


As you can see on this Nabble page, Wicket has the most active forum of all registered Java Web Frameworks.

Ruby on Rails and Django are the hot things in Ruby and Phyton land. So may we conclude Wicket is the hot thing in Java land?