Deciphering anonymous class references like MyPage$1$1$2

If you work with anonymous classes a lot (as Wicket applications do), you sometimes get confronted with compiler/tool messages referring to anonymous (inner) classes with names like MyPage$1$1$2 (for instance in FindBugs reports). Its pretty tedious to figure out which class is meant. Maybe there’s a better way, but what I do is go to the target directory and call “javap MyPage$1$1$2.class”. This produces a decompiled version of the class which makes it pretty clear which class it is.

Wicket 1.4 and browser tabs

We had an amazingly annoying problem in a Wicket application. A specific user was continuously having problems with ajax controls on pages (search fields, auto-complete fields etc). The problems were caused by PageExpiredExceptions. We couldn’t understand why only this one user had these problems. This went on for ages, until today I found out that Wicket 1.4 sets a default limit of 5 page maps per session. This specific user typically worked with multiple browser tabs on the application and once he went over 5, some of the page maps got evicted and the ajax stuff started failing.

The solution was to call “getSessionSettings().setMaxPageMaps(100)” to allow up to 100 page maps per session.

monit – trust is good, control better

monit is a very cool system for keeping your linux servers working – highly recommended. With a few lines of configuration, you can have it check any aspect of your system and services and when problems occur, have it alert or take remedial actions (like restarting services, cleaning up log or temporary files etc).

For example, we had the problem that we are running clustered web apps (using Terracotta) in VMware VMs. The cluster nodes were being suspended regularly for backups and this caused them to be evicted from the cluster. A simple solution was to use monit to monitor the apps (via the same health check port we were using for the availability check for the HAProxy load balancer) and to restart the services if the health check fails (as happens after the VM is unsuspended after the backup).

Here’s the line from the monitrc file we use to monitor the health check port (9000 in this case):

check host webapp with address localhost
if failed port 9000 protocol http with timeout 2 seconds then exec “/webapp/restart.sh”
The web app in this case is a java wicket app, running under jetty which also runs a health check on port 9000. A http query to this port causes the app to check its connection to its database and its cluster node status. If either fails, it returns a http error status. This health check is used by HAProxy (which takes failed nodes out of the load-balanced pool) and by monit (which restarts the services). This combination provides us with 100% uptime for these apps.

Java logging in development and production

Logging is tricky. Even some major open-source projects don’t do it correctly, so if you use their libraries, you end up with log files you didn’t ask for cluttering your machine.

Current best practices are to use a logging facade like commons-logging or slf4j to avoid these kind of problems by allowing libraries to conform to whatever logging strategy the application which uses the library is using. This means that if your app logs to myapp.log, then the library using slf4j will also log to myapp.log.

Here’s how we use slf4j in our projects:

Our libraries use slf4j-api – here’s the maven dependency you’ll need:

<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.4.2</version>
</dependency>

Our applications use slf4j-log4j12 – here’s the maven dependency you’ll need:

<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
	<version>1.4.2</version>
</dependency>

The code to log looks like this (its the same in libraries or applications):

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
public class MyClass {
	static Logger log = LoggerFactory.getLogger(MyClass.class);

	public Application() {
		log.info("some logging info");
	}
}

We want to have simple console logging during development. To do this we use a simple log4j.properties file containing only a console appender as shown below.

log4j.debug=false
log4j.rootLogger=INFO, Stdout
log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.Stdout.layout.conversionPattern=%-5p - %-26.26c{1} - %mn

We put this file in a Settings folder in our home directory.

During development we need to get log4j to load this file so we get console logging. We do this by defining a system property “log4j.configuration” in the Eclipse Preferences/Installed JREs/Edit/Default VM Arguments (that way it applies for all development projects):

-Dlog4j.configuration=file:///Users/roger/Settings/log4j.properties

During production, we do this same thing, but this time we pass a log4j configuration with a rolling file appender as shown below:

log4j.debug=false
log4j.rootLogger=INFO, R
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=myapp.log
log4j.appender.R.MaxFileSize=5000KB
log4j.appender.R.MaxBackupIndex=10
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d %p %t %c - %m%n

So the startup in production looks something like this:

java -Dlog4j.configuration=file:///home/administrator/log4j.properties -jar myapp.jar

Clustering scheduled jobs with Quartz and Terracotta

We’re using Quartz to handle scheduled jobs in our java applications. Since we cluster our apps for failover using Terracotta, we need to address the issue of how to failover scheduled jobs (we only want each job to execute exactly once, but for fault tolerance it should be scheduled on multiple servers).

Quartz handles this situation with clustered job stores and Terracotta provides a job store for Quartz. Its easy to use – just add the quartz-terracotta jar (you’ll also need a quartz version > 1.7 – I’m using 1.8.4 below).

<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<version>1.8.4</version>
</dependency>

<dependency>
	<groupId>org.terracotta.quartz</groupId>
	<artifactId>quartz-terracotta</artifactId>
	<version>1.2.0</version>
</dependency>

then set two systems properties. I’m doing it programmatically below because I use a commandline option to enable clustering in applications using embedded jetty. The “terracotta” commandline option is a terracotta url which tells the terracotta client where its servers are (something like “terracotta:9510,terracotta2:9510” for a fault-tolerant pair of terracotta servers).

if (cmd.hasOption("terracotta")) {
	System.setProperty("org.quartz.jobStore.class", "org.terracotta.quartz.TerracottaJobStore");
	System.setProperty("org.quartz.jobStore.tcConfigUrl", cmd.getOptionValue("terracotta"));
}

That’s it basically. The only additional thing you have to take care of is that while setting up the scheduled job, you need to be aware that another member of the cluster may have already set it up, so you should expect an ObjectAlreadyExistsException while setting up the quartz job.

Weird racing clock problem on VMWare Linux Guests

A while back we installed a new Dell server with a low-power Xeon 3GHz L3110 CPU to run some other essential network infrastructure. We chose the specific server configuration because it dissipates less than 30W while running 5 VMware VMs. It runs for hours on a UPS and doesn’t require cooling, so even if our server room air-conditioning were to die, this server should keep our network, firewalls, VPNs, DNS, DHCP and primary Terracotta server and a few other vital services up long enough for us to figure out what’s going on.

The server is running CentOS 5.5 and VMWare 1.0.10 – normally a very stable combination. However, we found that Linux guests running on this server were not keeping time properly. their clocks were running too fast – 50% too fast in fact. We finally figured out that the problem was caused by the fact that the CPU power-saving causes Linux to think that has a 2GHz processor instead of a 3GHz processor and this causes the 50% clock speedup in the Linux guests under VMWare. We disabled the demand-based power saving feature of the CPU in the BIOS and now it works correctly.

Adding AnnotatedConstraintBehavior to TextAreas

A while back I blogged about using an annotated constraint behavior to limit input in Wicket TextFields based on domain model annotations (http://blog.armstrongconsulting.com/?p=22). So if we annotate our domain models as follows:

@Length(max = 40)
private String firstName;

that gets automatically be translated into a maxlength=40 attribute on any text field bound to firstName (we use a form visitor on a custom form class to add the behavior to all text fields in the form).

That’s pretty cool, but unfortunately, it only works for text inputs because textarea doesn’t support the maxlength attribute. This really bothered me because its really important to limit the length of textareas since that’s where people try to paste in huge blocks of text and its annoying to only find out the limitation after submitting the form.

So today, I updated the behavior to also handle textareas. There’s a javascript workaround which simulates the maxlength behavior on textareas. I took the javascript from http://cf-bill.blogspot.com/2005/05/unobtrusive-javascript-textarea.html and in the renderHead of the behavior, I add the javascript.

Here’s the code – its in three files: AnnotatedConstraintBehavior.java (the behavior implementation), AnnotatedConstraintBehavior.js (the javascript needed to simulate maxlength on textareas) and ACForm.java (a form which does two extra things: (a) it validates its properties based on annotated constraints (like @NotNull and @Length)) and (b) it adds maxlength to text fields and textareas using the AnnotatedConstraintBehavior).

// AnnotatedConstraintBehavior.java
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.validation.constraints.NotNull;

import org.apache.commons.validator.EmailValidator;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.application.IComponentOnBeforeRenderListener;
import org.apache.wicket.behavior.AbstractBehavior;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.model.AbstractPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.IPropertyReflectionAwareModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.util.lang.PropertyResolver;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.validator.StringValidator;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;

/**
 * Configure a Wicket <code>Component</code> based on Hibernate annotations (@NotNull and @Length(min=x,max=y)).
 * <p>
 * Inspects the <code>Model</code> of a <code>FormComponent</code> and configures the <code>Component</code> according to the declared Hibernate Annotations used on the model object. <br />
 * <strong>NOTE:</strong> This means the <code>Component</code>'s <code>Model</code> <em>must</em> be known when {@link #configure(Component) configuring} a <code>Component</code>.
 * </p>
 *
 * <p>
 * This object can be used as a <code>Behavior</code> to configure a single <code>Component</code>. <br />
 * <strong>NOTE:</strong> this object is <em>stateless</em>, and the same instance can be reused to configure multiple <code>Component</code>s.
 * </p>
 *
 * <pre>
 * public class MyWebPage extends WebPage {
 * 	public MyWebPage() {
 *     TextField name = new TextField("id", new PropertyModel(user, "name");
 *     name.addBehavior(new AnnotatedConstraintBehavior());
 *     add(name);
 *   }
 * }
 * </pre>
 *
 * <p>
 * This object can also be used as a component listener that will automatically configure <em>all</em> <code>FormComponent</code>s based on Hibernate annotations. This ensures that an entire application respects annotations without adding custom
 * <code>Validator</code>s or <code>Behavior</code>s to each <code>FormComponent</code>.
 * </p>
 *
 * <pre>
 * public class MyApplication extends WebApplication {
 * 	public void init() {
 * 		addPreComponentOnBeforeRenderListener(new AnnotatedConstraintBehavior());
 * 	}
 * }
 * </pre>
 *
 * @see http://jroller.com/page/wireframe/?anchor= hibernateannotationcomponentconfigurator
 * @see http ://jroller.com/page/wireframe/?anchor=hibernate_annotations_and_wicket
 */
@SuppressWarnings("serial")
public class AnnotatedConstraintBehavior extends AbstractBehavior implements IComponentOnBeforeRenderListener {
	static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AnnotatedConstraintBehavior.class);

	@SuppressWarnings("unchecked")
	private static Map configs = new HashMap() {
		{
			put(NotNull.class, new AnnotationConfig() {
				public void onAnnotatedComponent(Annotation annotation, FormComponent component) {
					component.setRequired(true);
				}
			});
			put(Length.class, new AnnotationConfig() {
				public void onAnnotatedComponent(Annotation annotation, FormComponent component) {
					int max = ((Length) annotation).max();
					log.debug("adding maxlength=" + max + " attribute to " + component.getMarkupId());
					component.add(new AttributeModifier("maxlength", true, new Model(Integer.toString(max))));
					component.add(StringValidator.maximumLength(max));
				}
			});

			put(Email.class, new AnnotationConfig() {
				public void onAnnotatedComponent(Annotation annotation, FormComponent component) {
					component.add(new StringValidator() {
						@Override
						protected void onValidate(IValidatable<string> validatable) {
							if (!EmailValidator.getInstance().isValid(validatable.getValue())) {
								error(validatable);
							}

						}
					});
				}
			});

		}
	};

	@Override
	public void renderHead(IHeaderResponse iHeaderResponse) {
		super.renderHead(iHeaderResponse);
		iHeaderResponse.renderJavascriptReference(new ResourceReference(AnnotatedConstraintBehavior.class, "AnnotatedConstraintBehavior.js"));
	}

	@Override
	public final void bind(Component component) {
		super.bind(component);
		configure(component);
	}

	@Override
	public final void onBeforeRender(Component component) {
		if (!component.hasBeenRendered()) {
			configure(component);
		}
	}

	void configure(Component component) {
		if (!isApplicableFor(component)) {
			return;
		}
		FormComponent<?> formComponent = (FormComponent<?>) component;
		for (Annotation annotation : getAnnotations(component.getDefaultModel())) {
			Class<? extends Annotation> annotationType = annotation.annotationType();
			AnnotationConfig config = (AnnotationConfig) configs.get(annotationType);
			if (null != config) {
				config.onAnnotatedComponent(annotation, formComponent);
			}
		}
	}

	private Collection<annotation> getAnnotations(IModel<?> model) {

		try {
			// Only if a setter method is available we'll search for the
			// related field and find its Annotations.
			Method setter = ((IPropertyReflectionAwareModel) model).getPropertySetter();

			String name = setter.getName();

			if (name.startsWith("set") &amp;&amp; name.length() > 3) {
				name = name.substring(3, 4).toLowerCase() + name.substring(4);
			} else {
				return Collections.emptyList();
			}

			Object target = ((AbstractPropertyModel<?>) model).getTarget();
			Field field = PropertyResolver.getPropertyField(name, target);
			if (field == null) {
				return Collections.emptyList();
			}

			return Arrays.asList(field.getAnnotations());
		} catch (Exception ignore) {
			return Collections.emptyList();
		}
	}

	private boolean isApplicableFor(Component component) {
		if (!(component instanceof FormComponent<?>)) {
			return false;
		}
		IModel<?> model = component.getDefaultModel();
		if (model == null || !IPropertyReflectionAwareModel.class.isAssignableFrom(model.getClass())) {
			return false;
		}

		return true;
	}

	/**
	 * simple interface to abstract performing work for a specific annotation.
	 */
	private static interface AnnotationConfig extends Serializable {
		void onAnnotatedComponent(Annotation annotation, FormComponent<?> component);
	}
}
// AnnotatedConstraintBehavior.js
// javascript to simulate maxlength behavior on textareas
// source: http://cf-bill.blogspot.com/2005/05/unobtrusive-javascript-textarea.html

<script type="text/javascript">

 function textAreasInit(){
  var objs = document.getElementsByTagName("textarea");
  var oi = 0; //oi is object index
  var thisObj;

  for (oi=0;oi<objs.length;oi++) {
   thisObj = objs&#91;oi&#93;;
   // note that maxlength is case sensitve
   if (thisObj.getAttribute('maxlength')){
    thisObj.onkeyup = forceMaxLength;
   }
   thisObj.onchange = saveEntryValue;
  }
 }

 function forceMaxLength(){
  var maxLength = parseInt(this.getAttribute('maxlength'));
  if(this.value.length > maxlength){
   this.value = this.value.substring(0,maxlength);
  }
 }

function addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+,  NS6 and Mozilla
// By Scott Andrew
{
  if (elm.addEventListener){
 elm.addEventListener(evType, fn, useCapture);
 return true;
  } else if (elm.attachEvent){
 var r = elm.attachEvent("on"+evType, fn);
 return r;
  } else {
 alert("Handler could not be removed");
  }
}

addEvent(window, "load", textAreasInit);
</script>
// ACForm.java
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import org.apache.wicket.Component;
import org.apache.wicket.Component.IVisitor;
import org.apache.wicket.behavior.AbstractBehavior;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
import org.wicketstuff.jsr303.PropertyValidation;

public class ACForm<t> extends Form<t> {
	private static final long serialVersionUID = 1L;

	static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Placeholder.class);

	public ACForm(String id, IModel<t> model) {
		super(id, model);
		add(new PropertyValidation());
	}

	public ACForm(String id) {
		super(id);
	}

	@Override
	protected void onBeforeRender() {
		super.onBeforeRender();
		visitChildren(TextField.class, new AddBehaviorVisitor(new AnnotatedConstraintBehavior()));

		// note: textarea doesn't actually support the maxlength attribute, but we add it anyway and enforce it with javascript (the AnnotatedConstraintBehavior adds it)
		visitChildren(TextArea.class, new AddBehaviorVisitor(new AnnotatedConstraintBehavior()));
	}
}

class AddBehaviorVisitor implements IVisitor<component>, Serializable {
	private static final long serialVersionUID = 1L;
	private final AbstractBehavior behavior;
	Set<component> visited = new HashSet<component>();

	public AddBehaviorVisitor(AbstractBehavior behavior) {
		this.behavior = behavior;
	}

	@Override
	public Object component(Component component) {
		if (!visited.contains(component)) {
			visited.add(component);
			component.add(behavior);
		}
		return IVisitor.CONTINUE_TRAVERSAL;
	}
}

Using Wicket’s CheckBoxMultipleChoice

When I started with Wicket, I remember fighting with CheckBoxMultipleChoice for hours trying to get it to work. I just used it again today and was surprised at how easy it is to use once you’re familiar with how Wicket works. So for anyone struggling with it, here’s how to do it.

Say we want to display a list of Projects associated with a User and we want to do it with the CheckBoxMultipleChoice. The projects which the user currently has access to should be checked initially. Checking or unchecking boxes will add or remove access to projects.

You can accomplish this with the following code:

add(new CheckBoxMultipleChoice("projects", new Model<project>(userProjects), allProjects));

Assuming you have a span with wicket:id=”projects” in your HTML, this will display a checkbox for each project found in the “allProjects” list. Those which are also in the “userProjects” list will be checked. After submitting the form, the “userProjects” list will hold those which were checked when the form was submitted.

Note: I have omitted a renderer – that’s because my Project class has a toString() method which returns its name. That’s allows Wicket to render it correctly without an explicit renderer.

Second thing to note is that “userProjects” must be an ArrayList of Projects, not a List (as your service method would normally return it). The reason for this is that the Model demands a Serializable class so the easiest thing is to define userProjects as follows:

ArrayList userProjects = new ArrayList(service.getUserProjects());

The choices parameter (allProjects) can be a List, so you can use it straight from your service method.

Hope that helps anyone trying to use CheckBoxMultipleChoice for the first time.

How to display an enum in a dropdown in Wicket

Its often useful to use an enum as the model for a dropdown (or radio group) in Wicket, but not immediately obvious how to handle the display of the values. Lets say I have an enum with three colors:

enum Color { RED, GREEN, BLUE };

I can hook this up to a dropdown with the following code:

<select wicket:id="color"/>

enum Color { RED, GREEN, BLUE };
private Color color = Color.GREEN;
add(new DropDownChoice<color>("color", new Model<color>(color), Arrays.asList(Color.values())));

However, that would display “RED”, “GREEN”, “BLUE”. I probably don’t want the dropdown to use the default toString() form of my enum declarations, but rather I want it to load translatable texts from property files.

To do this, I can use Wicket’s EnumChoiceRenderer as follows:

<select wicket:id="color"/>
enum Color { RED, GREEN, BLUE };
private Color color = Color.GREEN;
add(new DropDownChoice<color>("color", Arrays.asList(Color.values()), new EnumChoiceRenderer<color>(this)));
Color.RED=Red
Color.GREEN=Green
Color.BLUE=Blue

Now I get what I wanted – a dropdown displaying “Red”, “Green” and “Blue”.

Mockito

We just started using Mockito for unit testing of our Wicket applications. Its a great tool, allowing us to easily mock out our service layers on a test-by-test basis.

In the example below, we’re testing a page called ItemPage. It takes an id of an item to load – internally the page uses itemService.find(id) to load the item from the database. Using Mockito, we mock out the itemService.find call to return a test item.

public class TestItemPage extends WicketTestcase {
	private static final long serialVersionUID = 1L;

	@Test
	public void TestItemPage() {
		when(itemService.find(Mockito.anyInt())).thenAnswer(new Answer() {

			@Override
			public Item answer(InvocationOnMock invocation) throws Throwable {
				final int id = (Item) invocation.getArguments()[0];
				Item item = new Item(id);
				item.setTitle("test");
				item.setDeadline(new Date());
				return item;
			}
		});

		tester.startPage(new ItemPage(12345));
		tester.assertRenderedPage(ItemPage.class);
	}
}