This Method Has Been Called Before

Sometimes you have a method that should only be called once, and any further calls to this method are considered to be an error. And you thought you had made sure that this method is only called once. But every now and then you find something in your log file that points to the fact that this method has in fact been called twice. This is an outrage!

So, how do you track down those spurious calls that happen out of nowhere and that can not possibly happen at all? Turns out, it’s not that hard: I thought up this method after reading a bit of log file from a fellow Freenet user. For a single method call it contained two different stack traces, one from the current call, and one from the last call. So after a couple of seconds I came to the conclusion that it has to happen a little bit like this:

public class SomeClass {
	/* Example UUID: dc033fa4-0102-4051-af9a-df9441312192 */
	private Exception firstCallException;
	public void someMethod() {
		if (firstCallException != null) {
			throw new Exception("Method already called!",
				firstCallException);
		}
		/* do stuff here */
		firstCallException = new Exception();
	}
}

What happens here is quite simple, really. first­Call­Exception is initialized with null, so on the first execution of some­Method nothing spectacular happens but at the end of the method first­Call­Exception is set: a new Exception is created which also initializes a stack trace for the current thread. On the second call we realize that first­Call­Exception has already been set so this method must have been called before! We throw a new Exception which uses the exception of the first method call as root cause; this enables us to get information about both exceptions from the resulting exceptions. Also, this would allow us to chain an arbitrary number of exceptions, e.g. when you have to track all calls to a method.

(This method will fail in some way when accessed by multiple threads — I leave it as an exercise for the reader to make it thread-safe.)

Share and Enjoy

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS