WicketBuilder
Groovy Wicket Builder
The Wicket Builder utility implements a Groovy Builder for constructing Wicket Component trees.
While using the builder makes building Component trees easier and more clear to the reader, the original driver was the fact that Groovy does not allow anonymous inner classes. Wicket relies on overriding methods to provide custom functionality for many Component types. Groovy can be used to code Wicket page classes, but each class that is overridden needs a named class definition. Possible, but clunky.
The WicketBuilder simulates these overrides with named Closures. Closures are, essentially, portable code blocks. Under the hood, the builder creates dynamic class overrides and runs the closures when the named method is called.
Some example code. First Java:
Form form = new Form("contactForm"){ protected void onSubmit() { try { ((Contact)getModel().getModelObject()).save(); } catch(SomeCrazyException e) { throw new RuntimeException("I don't know what to do with this. Just fail.", e); } } }; form.add(new RequiredTextField("firstname"); form.add(new RequiredTextField("lastname").add(StringValidator.maximumLength(32)); add(form);
And Groovy, with the WicketBuilder:
WicketBuilder builder = new WicketBuilder(this) builder.form("contactForm", model:new CompoundPropertyModel(contact), onSubmit:{ model.modelObject.save() }) { requiredTextField("firstname") requiredTextField("lastname") {add(StringValidator.maximumLength(32))} }
The builder structure follows a tree pattern, so the code winds up being laid out more like how it will look in the actual html page.
The name of each pretended method (in bold above) is resolved to a Wicket Component object, and added in a parent/child structure.
Named closures in the attributes list (see 'onSubmit' above, italicized and underlined) tip off the builder to produce a dynamic subclass, overriding that method and using the closure provided as the body of the method.
Custom components can be used as well. If in the same package, just make sure the Wicket default constructor is available (SomeClass(String key)). Then, simply use the class name with the first character in lower case.
builder.form("someForm") { someClass("some other thing") ... }
If the custom Components are in other packages, a configuration object needs to be provided (more to come...)
The WicketBuilder code is currently in the 1.3 branch only.
https://wicket-stuff.svn.sourceforge.net/svnroot/wicket-stuff/branches/wicket-1.3/wicket-contrib-groovy
Wordy explanation of the idea:
http://bigheadco.blogspot.com/2007/03/wicket-and-groovy.html;