Some Wicke[dt] Scala
Apache Wicket is a cool web framework to develop with. I’m in that business for some time now and I still haven’t found any nicer – really! JSF is no match at all, and since I’m doing most of my programming in Scala I’d taken a brief look at Lift. But that’s not mine, either. Everything in Wicket is ad-hoc reusable, that’s what I like best about it. And I think of Wicket and Scala as the perfect combination to develop with: Scala’s traits allow adding and overriding things so easy to Wicket components that it’s just a joy!
I want to add some foundations to above statements, so be prepared for some tough Wicket internal stuff – easily written in Scala! And for the readers still developing Wicket applications in Java: You might find the resulting library equally useful and should be able to use it from Java as well.
Enter the Quest
You may have found yourself in need to preprocess the markup for your Wicket components. Typically, you like using FreeMarker or Velocity for that. There are Wicket projects which provide you with some kind of support to do so. But those only go half the way. You can load template files and process them, but you can’t add Wicket components in them! Actually you could using <wicket:component> – but that’s a) not officially supported and b) doesn’t work when adding components with Ajax behaviors, since those components are coming in in a late stage in Wicket’s rendering scheme. Suppose you want to add some self-updating RSS feed panels based on some markup coming from a database you’re lost here.
The solution: Dynamo
I had such a task and found myself writing a generalized template engine with support for dynamic Wicket components. Here’s a short code example how it’s working:
class FreemarkerApplication extends WebApplication with Dynamo {
def getTemplateEngine: TemplateEngine = new FreemarkerEngine( appPath, new Properties, Locale.GERMAN )
def getHomePage = classOf[FreemarkerDynamoPage]
}
class FreemarkerPage extends WebPage with TemplateContainer {
val getTemplateName = "DynamoPage.ftl"
val getParameterMap = new java.util.Map[String,AnyRef]
}
class FreemarkerDynamoPage extends FreemarkerPage with DynamicComponentContainer
That’s it! All logic is hidden behind the scenes, you just have to know it works. Your dynamic code might add components in the following way:
<h3>Dynamic Wicket Components:</h3>
<#list StringList as s>
<dynComponent
class="de.footprint.wicket.application.dynamo.TextPanel"
label="${s}" />
</#list>
But how?
There were three tasks to accomplish. First was to define a general interface to call the processed template file. That wasn’t too difficult:
trait TemplateEngine {
@throws( classOf[ResourceStreamNotFoundException] )
def processTemplate( templateName: String, parameter: java.util.Map[String,AnyRef], locale: Locale ): String
def resetCache: Unit
}
Second was to hook into the markup loader to call on the engine whenever a container of type TemplateContainer was required. The Dynamo trait registers a customzed MarkupCache with the Application which just does that.
The third task was to add the dynamic component stuff. Now it got a bit nasty. The resource stream had to be filtered for components added by the template engine – and that had to happen before Wicket got it’s hand on the resources, i.e. WicketTagIdentifier got on the resource. So, the markup had to be loaded manually beforehand and the additional components had to be given unique (and stable) wicket:id’s. Having all that, the components only had to be created and added with their correct wicket:id. Easy, huh?
The nice thing with Scala is, you can just hide all these tasks in traits and add them to the components. onBeforeRender will just be overriden and mixed in, so the functionality is magically just there.
Famous last words
The code is here: Dynamo
To run the examples you have to use mvn resin:run.
It includes general support for FreeMarker and Velocity, but this approach can easily be integrated with any other markup source provider.
I hope you find this useful and get some ideas how Scala/Wicket can boost your code – not only in function but also in readability.
— Jan.