Category: Wicket Tutorials

Wicket 101: Making Use of the MDC Logging Context

Logging frameworks like log4j and logback usually offer a class called MDC (Mapped Diagnostic Context) to store contextual information of a user’s session to be used in log statements. As an example, here’s how to attach a session id to log statements using Wicket and log4j. Impatient? Skip right to the github example project

The Logging Configuration

Log4j is usually configured with a properties or xml file. If you want to output the session id with each log statement, you have to define the session with a variable like %X{sessionId} (see table “Conversion characters” in the javadoc of the PatternLayout class):

log4j.appender.Stdout.layout.conversionPattern=%-5p - %-26.26c{1} - %X{sessionId} - %m\n

This configuration reads the parameter “sessionId” out of the MDC context (if available) and prints it out with each log statement.

Filling the MDC context with Wicket

The session ID has to be stored in the MDC context, of course, before it can be printed out by the above logging configuration. Wicket offers the IRequestCycleListener interface for this purpose. You can extend AbstractRequestCycleListener if you don’t want to implement all methods of the interface:


public class AddSessionIdToMdcListener extends AbstractRequestCycleListener {
  @Override
  public void onBeginRequest(RequestCycle cycle) {
    super.onBeginRequest(cycle);
    WebSession session = WebSession.get();
    // the check on isTemporary() is necessary, since temporary sessions
    // have a NULL sessionId
    if (!session.isTemporary()) {
      MDC.put("sessionId", session.getId());
    }
  }
}

All we do is simply calling MDC.put() at the beginning of each Wicket request. By the way: you can put anything in the context, it doesn’t have to be a session id. The listener can be added to your Wicket application with the following line within the init() method of the Application class:

@Override
public void init() {
  super.init();
  getRequestCycleListeners().add(new AddSessionIdToMdcListener());
}

On Wicket’s Session ID

Note that Wicket only creates a session id for stateful pages, i.e. if you have at least one stateful component on a page or if you explicitly call setStatelessHint(false). This should be the case for most Wicket pages, though.

Resources

Wicket 101: Changing the location of your HTML markup

This post applies to Wicket 6.

Most components in Wicket consist of a Java class and a corresponding HTML markup file. By default, Wicket looks for the HTML markup for a component directly next to it in the Java classpath. For most cases, this is a reasonable configuration. However, for the few cases in which you want Wicket to look for the HTML markup files in another location, here is how.

Add the following line to the init()-method of your Application class:

getResourceSettings().getResourceFinders()
  .add(new WebApplicationPath(getServletContext(), "/"));

The result is that you can put your HTML files directly in the web archive path(in a Maven project this would be src/main/webapp) instead of into the classpath. If you use a Path instead of a WebApplicationPath, you could also put your files somewhere on the filesystem of the server. Also, you can implement your own IResourceFinder.

Advanced Wicket: Dynamic ListView within a Form

With ListView, Wicket provides a nice and easy way to create dynamic lists with no problem to add, remove or shift items during runtime. When using a ListView to list input fields in a form however, things can get strange…here’s a solution.

The Requirement

You want to create a form that contains multiple input fields. The user shall be able to add input fields or remove previously added  input fields.

Problem #1

By default the ListItems within a ListView are removed, newly created and added back to the ListView each time the ListView is rendered. If you add a new ListItem with a new input fields to the ListView, the user input in these fields will be lost when the page is re-rendered.

Solution #1

A solution to this problem is quickly found: just call listView.setReuseItems(true). This tells the ListView not to create new ListItems each time it is rendered. However, this leads to Problem #2.

Problem #2

Each ListView is backed by a model that contains a list of items that are to be displayed. If a new item is added to this list and setReuseItems is set to true, the ListView will wrap only this new item in a new ListItem and add the ListItem to the ListView the before it is rendered the next time (see ListView.onPopulate()). Since ListView works on the index of the backing model list, each time you insert a new item in the middle of this list, ListView will think you added it at the last position of the list. The result ist that each time you add a new item to the model list (no matter where you put it), the last item of the list is added to the ListView. When the ListView is rendered this can lead to duplicated rendering of the last item.

Solution # 2

Always (!) add items at the end of the model list that backs a ListView. This way, ListView will add the correct ListItem before being rendered again. If the new item is to be displayed in the middle of the list, override the ListView’s renderIterator() method. Here you can create an iterator that sorts the items according to their model values. Here is an example from my Wicked Forms library:
@Override
protected Iterator<Component> renderIterator() {
 return iterator(new Comparator<Component>() {
  @Override
  @SuppressWarnings("unchecked")
  public int compare(Component o1, Component o2) {
   ListItem<Abstractformelementmodel> item1 = (ListItem<Abstractformelementmodel>) o1;
   AbstractFormElementModel model1 = item1.getModelObject();
   ListItem<Abstractformelementmodel> item2 = (ListItem<Abstractformelementmodel>) o2;
   AbstractFormElementModel model2 = item2.getModelObject();
   return model1.getIndex().compareTo(model2.getIndex());
  }
 });
};

Wicked Forms – Dynamic Forms Library

Before building your own dynamic form have a look at Wicked Forms. With Wicked Forms you can “describe” your form in plain java and let Wicket render it without having to hassle with details as described above.

Rolling your own AJAX Behavior with Wicket

Apache Wicket provides a lot of predefined AJAX components like the AjaxButton and the AjaxEventBehavior which fulfill almost any of your AJAX-needs. However, in some special cases you may need to create your own AJAX behavior to pass some custom parameters from client to server via AJAX.

The Problem

The AJAX Behaviors Wicket provides all have a specialized function. The AjaxButton provides an onSubmit-Method to react on a form submission via AJAX. The more general AjaxBehavior provides an onEvent-Method in which you can update parts of your page via AJAX.
But what to do if you have some client-side javascript logic that makes some calculations and you want to send the result of that calculation to your server via AJAX? The following sections provide a surprisingly simple solution for this problem. Scroll to the bottom to see the full 30 lines of the finished behavior class if you want to skip the tutorial part :).

The Behavior

First, we have to create our own AjaxBehavior by subclassing AbstractDefaultAjaxBehavior. The respond-method has to be implemented. This method is called on the server-side when an AJAX call is made from the client. In this method, we want to somehow access some values that are passed from the client-side.
public class MyAjaxBehavior extends AbstractDefaultAjaxBehavior {</p>
  @Override
    protected void respond(AjaxRequestTarget target) {
      // here, we want to access some parameters that were sent
      // by the client via AJAX
    }
   }

Calling the Behavior from Client-Side Javascript

The behavior does nothing so far. It has to be called from the client-side for the respond-method to be called on the server-side. To achieve this, we simply implement the renderHead() to execute some javascript when the page is loaded (you can also add this javascript to any other event of course, like clicking a button).
public class MyAjaxBehavior extends AbstractDefaultAjaxBehavior {</pre>
  @Override
    protected void respond(AjaxRequestTarget target) {
    // here, we want to access some parameters that were sent
    // by the client via AJAX
  }

  @Override
    public void renderHead(Component component, IHeaderResponse response) {
      super.renderHead(component, response);
      response.render(OnDomReadyHeaderItem.forScript(getCallbackScript()));
  }

}
Remember to call super.renderHead(). Otherwise Wicket’s javascript files will not be included. The AbstractDefaultAjaxBehavior class already provides a method that generates the javascript that is needed to issue an AJAX request: getCallbackScript(). This method will generate a javascript fragment something like the following, where “u” and “c” are two Wicket-specific parameters that are needed to find our AjaxBehavior on the server side an call its respond()-method.
Wicket.Ajax.ajax({"u":"./?1-1.IBehaviorListener.2-component","c":"component"});

Passing Parameters from Client to Server

Let’s say we have two custom parameters, param1 and param2, that we want to pass from the client-side javascript to our server-side code. How to do that?

Wicket provides the concept of “extra parameters” that can be added to the javascript AJAX call by adding the “ep” parameter to the function call:

Wicket.Ajax.ajax({
  "u":"./?1-1.IBehaviorListener.2-component",
  "c":"component",
  "ep":[
    {"name":"param1","value":"value1"},
    {"name":"param2","value":"value2"}]});

The Strings “value1″ and “value2″ will then be submitted via the AJAX call. Our Behavior will have to be altered to generate the extra parameters in it’s javascript output. We do this by overriding the method updateAjaxAttributes():

public class MyAjaxBehavior extends AbstractDefaultAjaxBehavior {</pre>
  @Override
  protected void respond(AjaxRequestTarget target) {
    // here, we want to access some parameters that were sent
    // by the client via AJAX
  }

  @Override
  public void renderHead(Component component, IHeaderResponse response) {
    super.renderHead(component, response);
    response.render(OnDomReadyHeaderItem.forScript(getCallbackScript()));
  }

  @Override
  protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
    super.updateAjaxAttributes(attributes);
    attributes.getExtraParameters().put("param1", "value1");
    attributes.getExtraParameters().put("param2", "value2");
  }

}

However, our Ajax call will now always pass the values “value1″ and “value2″ for our two parameters. What we want is to pass values dynamically calculated in javascript.

Passing Dynamic Parameter Values

To pass dynamically calculated javascript values to the server, these values have to be calculated first, and then added into our “extra parameters” array.

To dynamically calculate the parameter values, our renderHead-method is altered. Remember: if you want to trigger the AJAX event somewhere else and not onDomReady, you can do so. For the calculation of the javascript values you can call any Javascript module you might use.

  
@Override
  public void renderHead(Component component, IHeaderResponse response) {
    super.renderHead(component, response);
    String script = "var param1Value = My.JavaScript.Module.calculate1();";
    script += "var param2Value = My.JavaScript.Module.calculate2();"; 
    script += getCallbackScript();
    response.render(OnDomReadyHeaderItem.forScript(script));
  }

Next, we have to pass the javascript variables param1Value and param2Value as “extra parameters” in our Wicket.Ajax.ajax function call instead of the fixed values “value1″ and “value2″. This can be done by overriding getCallbackScript() and slightly altering our implementation of updateAjaxAttributes() from above:

@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
  super.updateAjaxAttributes(attributes);
  attributes.getExtraParameters().put("param1", "PLACEHOLDER1");
  attributes.getExtraParameters().put("param2", "PLACEHOLDER2");
}

public CharSequence getCallbackScript() {
  String script = super.getCallbackScript().toString();
  script = script.replace("\"PLACEHOLDER1\"", "param1Value");
  script = script.replace("\"PLACEHOLDER2\"", "param2Value");
  return script;
}

The method updateAjaxAttributes() now inserts placeholders into the extra parameters map. The method getCallbackScript() is overridden to replace all occurrences of these placeholders within quotes with the names of the javascript variables that contain outr calculated values.

The workaround with the placeholders is neccessary because otherwise we will have extra quotes around our javascript variable names (i.e. the value of param1 will always be the string “param1Value” instead of the actual value of the javascript variable with that name).

Accessing the passed Parameters on the Server

At last, we can access the values of the javascript variables on the server within the respond() method of our behavior:
@Override
public CharSequence getCallbackScript() {
  RequestCycle cycle = RequestCycle.get();
  WebRequest webRequest = (WebRequest) cycle.getRequest();
  StringValue param1 = webRequest.getQueryParameters().getParameterValue("param1");
  StringValue param2 = webRequest.getQueryParameters().getParameterValue("param2");
  // do whatever you need with param1 and param2
}

The Complete Behavior

Finally, the whole behavior at a glance:
public class MyAjaxBehavior extends AbstractDefaultAjaxBehavior {

  @Override
  protected void respond(AjaxRequestTarget target) {
    RequestCycle cycle = RequestCycle.get();
    WebRequest webRequest = (WebRequest) cycle.getRequest();
    StringValue param1 = webRequest.getQueryParameters().getParameterValue("param1");
    StringValue param2 = webRequest.getQueryParameters().getParameterValue("param2");
    // do whatever you need with param1 and param2
  }

  @Override
  public CharSequence getCallbackScript() {
    String script = super.getCallbackScript().toString();
    script = script.replace("\"PLACEHOLDER1\"", "param1Value");
    script = script.replace("\"PLACEHOLDER2\"", "param2Value");
    return script;
  }

  @Override
  protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
    super.updateAjaxAttributes(attributes);
    attributes.getExtraParameters().put("param1", "PLACEHOLDER1");
    attributes.getExtraParameters().put("param2", "PLACEHOLDER2");
  }

  @Override
  public void renderHead(Component component, IHeaderResponse response) {
    super.renderHead(component, response);
    String script = "var param1Value = My.JavaScript.Module.calculate1();";
    script += "var param2Value = My.JavaScript.Module.calculate2();";
    script += getCallbackScript();
    response.render(OnDomReadyHeaderItem.forScript(script));
  }

}

Deploying a Wicket App on Google’s AppEngine

Google’s App Engine (GAE) cloud infrastructure provides a fast and easy way to deploy a Java web application to the public web. And it’s free up to a certain traffic threshold. So, I tried it with a Wicket application and had to overcome some small obstacles. Following is a description of the steps necessary to deploy a Java application (precisely, a Wicket application) to Google App Engine.

Create a GAE account

Go to https://developers.google.com/appengine and create an App Engine account. If you already have a Google Mail account, it’s just a click.

>Install GAE SDK

Download the GAE SDK for Java here. Unzip it anywhere on your hard drive.

Prepare your Java application for GAE

Next to the standard web.xml deployment descriptor you need to provide a descriptor called appengine-web.xml in the WEB-INF folder of your WAR. Following is the content of an appengine-web.xml with which I successfully deployed a demo app on App Engine:
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application>wicket-charts</application>
  <!-- Version must only contain letters, hyphens ("-") and numbers! Otherwise, 
    a HTTP 500 will occur on update -->
  <version>1-2-0</version>
  <threadsafe>false</threadsafe>
  <sessions-enabled>true</sessions-enabled>
  <system-properties></system-properties>
</appengine-web-app>

Take care that the content of the version tag contains only letters, numbers or hyphens (no periods!). Otherwise you get an inexpressive HTTP 500 error when deploying the application.

Additionally to providing a depoyment descriptor you have to adhere to some restrictions GAE imposes on java applications. The main restrictions are:

  • Your application may not store anything in the local filesystem (which actually already is a constraint of the servlet API, but most application servers do not enforce this rule)
  • Your application may not use all classes of the JRE. For example, AWT/Swing classes are a no-go for GAE applications. The classes you may use are listed in a white list.

The second restriction is by far the more constraining. You simply cannot run an application on GAE that uses one of the prohibited classes! This makes the deployment of applications built without GAE in mind a gamble.

Prepare your Wicket application for GAE

The steps above are valid for all Java applications. For making a Wicket application ready for GAE, simply put the Google App Engine Initializer in the classpath of your application and you’re done. The initializer will automatically configure your Wicket application on startup so that it adheres to the GAE restrictions. Among other things, the initializer configures your application not to use Wicket’s DiskDataStore which stores the PageMap in the file system.

If you want to have full control over how your Wicket application is configured, you have to make the necessary configurations in your application’s init method yourself (but you have to find out yourself what configurations are necessary for the application to run on GAE).

Deploy your application on the GAE development server

To test if your application runs on GAE, run the following command:

<path_to_appengine_sdk>/bin/dev_appserver.cmd <path_to_your_war>

where points to a directory (expanded war archive) and not a war file.

On http://localhost:8080 you should now see your application.

Deploy your application into the GAE cloud

To finally deploy your application to the cloud, run the following command:

<path_to_appengine_sdk>/bin/appcfg.cmd update <path_to_your_war>

where  again points to a directory. You will be prompted to enter your GAE login credentials before the application will be uploaded.

You should then be able to access your application on http://.appspot.com.

Wicket & HTML5 Showcase App

Since HTML5 and Wicket are both favorite topics of mine and I’m currently writing an article about Wicket and JavaScript, I’ve built a showcase application to try out some HTML5 features with Wicket.

To start, I’ve built a litte JavaScript module that takes a form and stores the user input into the HTML5 IndexedDB. Then I played around with Wicket Behaviors to add the JavaScript to the application. I will be adding more features to the showcase as I play around with HTML5. My conclusion up to this point is that it’s a lot of fun to work with Wicket and HTML5 together!

The App has a nice Design made by a Designer at adesso, André Firchow. Thanks for letting me use it! It’s that much more fun to work with an eye-pleasing Look & Feel :). Here’s a screen:

The Showcase App is hosted at google code.: http://code.google.com/p/wickethtml5/. Feel free to try it out!

Hijacking the Wicket AJAX Debug console

One very cool feature of Wicket is the AJAX debug window. The debug window is the place where Wicket logs client-side messages from its JavaScript code. Looking at these messages can help a lot in analyzing AJAX communication. The debug window looks like in the picture below.

If you are developing Javascript components for Wicket, wouldn’t it be nice to use this debug window for your own JavaScript components? It’s not hard to do at all. The steps are explained below.

Enabling the Debug Window

The Debug window is enabled by default. To enable it explicitly, follow these steps:

  • start your Wicket application in development mode (or start it in deployment mode and call getDebugSettings().setAjaxDebugModeEnabled(true) in the init method of your application)
  • load a page with at least one of Wicket’s AJAX components
  • you will now see a link “WICKET AJAX DEBUG” on the page which opens the debug window.

Rolling your own JavaScript Behavior

So, you are developing some kind of javascript to be used from a Wicket component. The way to do this is by defining a Behavior that includes the needed javascript files and calls the right javascript command at the right time. It looks something like this:

public class MyJavascriptBehavior extends Behavior{</pre>
  @Override
  public void renderHead(Component component, IHeaderResponse response) {
    response.renderJavaScriptReference("myJavascript.js");
    response.renderOnDomReadyJavaScript("myJavascriptCall()");
  }
}

The javascript file myJavascript.js contains some functionality you want to include. The javascript method myJavascriptCall() is called when the DOM is fully loaded. In the javascript file you want to output some debug info.

// myJavascriptFile.js
function myJavascriptCall(){
  // ...snip... arbitrary javascript logic
  alert('debug info');
}

Hijacking the Wicket Debug Window

Now, outputting debug info via alert() is not very sophisticated. Instead, we want to log the information to the wicket debug window. First, we have to include Wicket’s own javascript files in our behavior class. To achieve that, we write the method includeDebugJavascript():

public class MyJavascriptBehavior extends Behavior{</pre>
  @Override
  public void renderHead(Component component, IHeaderResponse response) {
    response.renderJavaScriptReference("myJavascript.js");
    response.renderOnDomReadyJavaScript("myJavascriptCall()");
    includeDebugJavascript(response, component.getApplication());
  }

  private void includeDebugJavascript(IHeaderResponse response, Application application) {
    if (application.getDebugSettings().isAjaxDebugModeEnabled()) {
      response.renderJavaScriptReference(WicketEventReference.INSTANCE);
      response.renderJavaScriptReference(WicketAjaxReference.INSTANCE);
      response.renderJavaScriptReference(
        new JavaScriptResourceReference(AbstractDefaultAjaxBehavior.class, "wicket-ajax-debug.js"));
      response.renderJavaScript("wicketAjaxDebugEnable=true;", "wicket-ajax-debug-enable");
    }
  }
}

That’s it. It’s the same mechanism the Wicket framework itself uses (in 1.5.3, that is; as of this writing, this mechanism was somewhat refactored in the trunk). Now, to log something to the wicket debug window from your javascript, modify your javascript as follows:

// myJavascriptFile.js</pre>
function myJavascriptCall(){
  // ...snip... arbitrary javascript logic
  logInfo("Hello Wicket Debug Window");
}

function logInfo(message){
  if (islogEnabled())
  WicketAjaxDebug.logInfo(msg);
}

function isLogEnabled(){
  if (typeof(WicketAjaxDebug)=="undefined") {
    return false;
  } else {
    return true;
  }
}

The detour with isLogEnabled() is neccessary, since the javascript variable WicketAjaxDebug is null if you don’t have the AJAX debug settings (see above) set to true. Calling the method logInfo() on a null reference causes an error, even in javascript. The methods logDebug() and logError() are also supported. For a clean and reusable component, you should wrap your javascript code in its own namespace, which was not done here.

Wicket & HTML5: Required and Placeholder attributes

HTML5 introduced some new markup elements. This post shows how two of those can easily be integrated in a web application based on Apache Wicket.

The required flag

The new required flag looks like this:

<input type="text" required/>

If the browser comes across this flag, it will mark the input field somehow if it is empty (you can decide how it will be marked by using CSS).

Wicket already comes with a RequiredTextField, which uses a server-side validator to check if the user has typed in some text. Sadly, it does not include the new flag. This is easily amended: we simply subclass RequiredTextField:

public class Html5RequiredTextField&lt;T&gt; extends RequiredTextField&lt;T&gt; {</pre>
  // ... constructors

  @Override
  protected void onComponentTag(final ComponentTag tag) {
    tag.put("required", true);
    super.onComponentTag(tag);
  }
}

By overriding onComponent(), we tell the new RequiredTextField to output ‘required=”true”‘. Et voilá, our first HTML5 Wicket component. That was easy. On to the next feature.

The placeholder text

HTML5 supports placeholder text in any input elements:

<input type="text" placeholder="Placeholder text..."/>

A browser displays the placeholder text if the user has not entered anything yet. Teaching Wicket to use the placeholder is the same story as before…simply subclass an existing Wicket component and override the onComponentTag() method:

public class Html5PlaceholderTextField<T> extends TextField<T> {
  private final String placeholder;

  public Html5PlaceholderTextField(String id, String placeholder) {
    super(id);
    this.placeholder = placeholder;
  }

  // other constructors (each with placeholder parameter)

  @Override
  protected void onComponentTag(final ComponentTag tag) {
    tag.put("placeholder", this.placeholder);
    super.onComponentTag(tag);
 }
}

This is not a very flexible solution however, since you would have to subclass each type of input component (NumberTextField, EmailTextField, …) to teach them the placeholder attribute. A more flexible approach is the use of a Behavior:

public class PlaceholderBehavior extends Behavior {
  private final String placeholder;

  public PlaceholderBehavior(String placeholder) {
    this.placeholder = placeholder;
  }

  @Override
  public void onComponentTag(Component component, ComponentTag tag) {
    tag.put("placeholder", this.placeholder);
  }
}

This behavior can be added to every input object like this:

EmailTextField mailField = new EmailTextField("myField");
mailField.add(new PlaceholderBehavior("Type your mail address here...");

Let’s hope the wicket devs include these features in one of the next minor releases, since it it would be no effort at all.

Marrying HTML5 and Apache Wicket: The new form elements

Since I like playing around with Apache Wicket and I recently got the opportunity to dive into the new features of HTML5, I was wondering how much effort it would take to integrate those features into a Wicket application. For an easy start, I chose to have a look at the new form elements HTML5 offers (a very good demo of HTML5 form elements can be found here: http://slides.html5rocks.com/#new-form-types).

A full text search for “html5″ through Wicket’s code base (version 1.5.3) reveals that some of the new input elements have already been thought of:

  • FileUploadField
  • EmailTextField
  • NumberTextField
  • RangeTextField
  • UrlTextField

Nothing left to do here… . However, the following features seem to have been looked over:

  • the required flag
  • the placeholder text
  • date input
  • color input
  • telephone input
  • search input 
I’ll have a look at how we can incorporate those features into a Wicket application in the next blog posts. It shouldn’t be a lot of work with Wicket’s flexible component model.