Many knows the tradeoff of using exceptions while designing an application:

On one hand, using try-catch block nicely segregates between regular code and exception handling code

On the other hand, using exceptions has a definite performance cost for the JVM

Every time I’ve been facing this quandary, I’ve ruled in favor of the former, because "premature optimization is evil". However, this week has proved me that exception handling in designing an API is a very serious decision.

I’ve been working to improve the performances of our application and I’ve noticed many silent catches coming from the Spring framework (with the help of the excellent dynaTrace tool). The guilty lines comes from the RequestContext.initContext() method:

if ( this . webApplicationContext . containsBean ( REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME )) { this . requestDataValueProcessor = this . webApplicationContext . getBean ( REQUEST_DATA_VALUE_PROCESSOR_BEAN_NAME , RequestDataValueProcessor . class ); }

Looking at the JavaDocs, it is clear that this method (and the lines above) are called each time the Spring framework handles a request. For web applications under heavy load, this means quite a lot! I provided a pass-through implementation of the RequestDataValueProcessor and patched one node of the cluster. After running more tests, we noticed response times were on average 5% faster on the patched node compared to the un-patched node. This is not my point however.

Should an exception be thrown when the bean is not present in the context? I think not…​ as the above snippet confirms. Other situations e.g. injecting dependencies, might call for an exception to be thrown, but in this case, it has to be the responsibility of the caller code to throw it or not, depending on the exact situation.

There are plenty of viable alternatives to exceptions throwing:

Returning null This means the intent of the code is not explicit without looking at the JavaDocs, and so the worst option on our list Returning an Optional<T> This makes the intent explicit compared to returning null . Of course, this requires Java 8 Return a Guava’s Optional<T> For those of us who are not fortunate enough to have Java 8 Returning one’s own Optional<T> If you don’t use Guava and prefer to embed your own copy of the class instead of relying on an external library Returning a Try Cook up something like Scala’s Try , which wraps either (hence its old name - Either ) the returned bean or an exception. In this case, however, the exception is not thrown but used like any other object - hence there will be no performance problem.

Conclusion: when designing an API, one should really keep using exceptions for exceptional situations only.