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

Advertisements

5 Things to Consider when Load Testing

Load tests are used to assure that an application is able to cope with real life. Usually, real life looks different from any load test scenario, but such a test can nonetheless help to gain some insights. No matter which tool is used to execute the load tests, here are some things to think about while planning and executing load tests.

Run load tests early

Don’t wait until a couple weeks before the release of your software before running the load tests. Run them as soon as the software has reached a relatively stable state where developing and maintaining (!) a load test is not overly expensive. Run them occasionally. It will help to get a feel for the software. Run them in earnest a couple weeks before the release on the real server infrastructure your software is going to be deployed on. Issues with your software should have been flushed out by your earlier tests, so all issues you will find will have to do with the infrastructure.

Reconsider the parameters for your load test

Load tests are usually run in parallel. Multiple threads running on multiple servers, each of them sending requests to stress your software. Most load test tools like JMeter allow to parameterize your load tests. Think about the parameters you will have. Each thread will probably need a username and password. Don’t just let all threads use the same user. What effect will it have if the same user is logged in multiple times at once? What effect do the other parameters have?

Test your load test

Like everything else, a load test has to be tested in itself. Does it work correctly? Is the load test client thread-safe? It should be, since it will probably be executed in multiple threads simultaneously. Start testing it against you local development server before moving on to other server environments. Let it run against the target environment as early as possible, since the target environment may not be available for load testing all the time. Let it run with multiple threads before day zero to flush out any concurrency issues.

Automate load test rollout

Tools like JMeter allow running load tests from multiple clients. Installing and configuring JMeter on each of those clients can be very time consuming. You run a test, you notice something is wrong, you correct it, you roll out JMeter on all clients again. Do yourself a favor and automate the rollout process the first time you have to do it. Otherwise you will curse yourself after the third time doing it by hand. Consider using a public cloud infrastructure with automatic deployment.

Don’t plan too much

Don’t plan a strict series of test runs with all parameters like number of concurrent threads and a time schedule planned out. Most certainly, you won’t be able to follow that plan anyway. Start your load test with a few concurrent threads and slowly add to them. Write down results like average response time and other insights like server or database load for each series. After having run a couple series you will be able to draw some conclusions which help with choosing what kind of series to start next.

Wicked Charts 1.5.0 released

Wicked Charts has been released in version 1.5.0.

Wicked Charts is a Java Wrapper for the popular Highcharts JavaScript charting library. It provides ready-made Chart components for JSF2.1, Apache Wicket 1.4.x, 1.5.x and 6.x.

New Features in Version 1.5.0 include the support for Wicket 1.4.x and Highcharts 3.

See http://www.wicked-charts.org for details.

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.

Managing Multiple Eclipse-Workspaces with Shortcuts

Most of us are working on more than one project at once, each living in its own eclipse workspace. Eclipse supports this with the workspace feature and even provides a function to switch between workspaces. A not so commonly known function of eclipse is that it also supports command line arguments which make life a little easier if you have multiple workspaces. This way, you can create multiple shortcuts on your desktop, each starting the same eclipse installation with a different workspace. How to do this in an orderly fashion is described in the following.

Create ECLIPSE_HOME system property

First, create the system property ECLIPSE_HOME, pointing to the folder in which you have your eclipse version of choice installed. If you need more that one eclipse installation, simply create multiple system properties with different names. You can also skip this step completely but it makes the shortcuts we create later more robust.

Create JAVA_HOME system property

The JAVA_HOME system property should already be set on most systems. However, you should check that it points to a JDK and not to a JRE.

Create a shortcut for each workspace

Now, create a shortcut for each of your workspaces that you want to quick access for. In windows, create a .bat file in each workspace folder with the following content (in unix systems this can be created analogous):

"%ECLIPSE_HOME%\eclipse.exe" -vm "%JAVA_HOME%\bin" -data .

This shortcut will start the eclipse installed in ECLIPSE_HOME with the Java runtime lying in JAVA_HOME. Eclipse will start with the current folder (“.”) as workspace.

Conclusion

Having a quick access shortcut to each workspace like above saves some time switching between workspaces. You can play around with the eclipse command line parameters and add some more or change them. More command line parameters of eclipse can be found here.

Batch Formatting of Java Source Files with Eclipse

Sometimes it is helpful to format a whole batch of Java source files in the same style your eclipse source formatter is configured. This is for example very helpful if you have to merge two development branches and you want to format the source files of both branches before comparing them to remove unimportant differences between both branches.
The eclipse source formatter has a hidden feature that allows it to be run on a directory of java files with a simple shell command:
eclipse -application org.eclipse.jdt.core.JavaCodeFormatter -verbose
  -config <PATH_TO_CONFIG_FILE> <PATH_TO_JAVA_SOURCES>

Parameters:

  • <PATH_TO_CONFIG_FILE>: Path to the properties file containing the configuration of the code formatter. This file is created in .settings/org.eclipse.jdt.core.prefs when you configure the formatter in eclipse for a specific project
  • <PATH_TO_JAVA_SOURCES>: Path to the folder containing the java source files to format.

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.