views:

217

answers:

8

Is it possible to force java to make you catch RuntimeExceptions? Specifically I am working with the Spring framework and the whole Exception hierarchy is based upon RuntimeExceptions. A lot of the times I forget to try and catch the Exceptions. A specific example is when doing an LDAP query, or an SQL call.

+1  A: 

No. Subclasses of RuntimeException are never checked.

Matthew Flaschen
A: 

No, you cannot force the compiler to make you catch any RuntimeException.

Basically because the method you are calling does not declare it throws a RuntimeException, there is no way for the compiler to be aware of any exceptions that could be thrown, or to force you to catch them.

Geoff
Even if the method declares that it `throws RuntimeException`, the compiler still wouldn't force you to `catch` it simply because the language says it's unchecked.
polygenelubricants
Yes, that's true of current compilers, however it would be possible to add such an option to current compilers. This only covers a very small selection of methods that do actually throw RuntimeExceptions, since most of these methods are wrapped in other methods inside libraries where you have no control over the compilation and the exposed API does not declare any exceptions to be thrown.
Geoff
A: 

No that is not possible.

What you could do, but is bad design and definetly not recommended, is that you make the method throw an Exception

public void doStuff() throws Exception {}

Thus enforcing any caller to catch Exception. This includes RuntimeExceptions, but it is bad design since the scope is very broad and does not specify what exception that is being thrown.

Lars Andren
A: 

No. The only thing i can think of is to use a tool like FindBugs, PMD etc, to find these issues for you, although i don't believe either tool has a tool specific to that. You could write your own detector however. Of course this would only apply to explicit throwing of RuntimeExceptions, and not implicit ones, like NullPointerException.

MeBigFatGuy
A: 

Instead of forcing you to remember to catch all of the fun exceptions everywhere, I would encourage writing a wrapper for some of the spring calls.

So instead of being forced to remember

 try {
    SpringThing.doThatOneMethod();
 catch (SpringConnectionException sce) { /*handle it*/ }
 catch (SpringProxyException      spe) { /*handle it*/ }
 catch (SpringRuntimeException    sre) { /*handle it*/ }

, you could just always invoke your own SpringExceptionsWrapper.doThatOneMethod().

If you really wanted to, you could have the method signatures for your wrapper functions list out some checked exceptions that you might wrap stuff in. I wouldn't encourage it since it forces you to correctly handle it everywhere.

Mike
+4  A: 

No: RuntimeException and its subclasses are unchecked exceptions.

JLS 11.2.5 Why Runtime Exceptions are not Checked

The runtime exception classes (RuntimeException and its subclasses) are exempted from compile-time checking because, in the judgment of the designers of the Java programming language, having to declare such exceptions would not aid significantly in establishing the correctness of programs. Many of the operations and constructs of the Java programming language can result in runtime exceptions. The information available to a compiler, and the level of analysis the compiler performs, are usually not sufficient to establish that such run-time exceptions cannot occur, even though this may be obvious to the programmer. Requiring such exception classes to be declared would simply be an irritation to programmers.

JLS 11.5 The Exception Hierarchy

The class Exception is the superclass of all the exceptions that ordinary programs may wish to recover from. The class RuntimeException is a subclass of class Exception. The subclasses of RuntimeException are unchecked exception classes. The subclasses of Exception other than RuntimeException and its subclasses are all checked exception classes.

polygenelubricants
+1  A: 

In fact, Spring exceptions are made runtime for a good reason. Spring converts checked exceptions to a runtime, because if, for example, SQLException is thrown because database is down you are unlikely to be able to recover or do something meaningful.

Moreover, with checked exceptions your code becomes more tangled and clumsy, especially if you have to have another try/catch block in catch block.

wax
+6  A: 

Not with just Java.

But if you compile with the AspectJ compiler or modifies your classes with AspectJ load-time weaving, then it's possible.

A definition of an aspect from Wikipedia:

an aspect is a part of a program that cross-cuts its core concerns

Aspects is often used to add for example transaction and security logic.

To demonstrate how an aspect can solve your problem, I have created an example that catches all exceptions thrown back from call to the integration layer from inside a method in classes marked with the @Service annotation. In this case classes that contains .integration. in the package name.

This is just an example. You can modify it to catch RuntimeExceptions other places. For example in all methods that's inside a class that has Facade in its name and calls other methods. See the picture below for ideas:

alt text The orange arrows are my AspectJ pointcut illustrated with the AJDT plugin in Eclipse. This is the places where you can catch and deal with the runtime exceptions in an AfterThrowing advice.

Here is the advice:

@AfterThrowing(value="serviceMethodAfterExpcetionFromIntegrationLayerPointcut()",     
     throwing="e")
public void serviceMethodAfterExceptionFromIntegrationLayer(JoinPoint joinPoint,
  RuntimeException e) {
  StringBuilder arguments = generateArgumentsString(joinPoint.getArgs());

  logger.error("Error in service " + joinPoint.getSignature()
  + " with the arguments: " + arguments, e);
  }

My serviceMethodAfterExpcetionFromIntegrationLayerPointcut actuall consist of two other poincuts:

 @Pointcut("call(* *..integration.*.*(..))")
 public void integrationLayerPointcut() {}

 @Pointcut("within(@org.springframework.stereotype.Service *)")
 public void serviceBean() {}

 @Pointcut("serviceBean() && integrationLayerPointcut()")
 public void serviceMethodAfterExpcetionFromIntegrationLayerPointcut() {}

Short summarized, the pointcut finds all places in classes marked with the @Service annotation that call on a method in a class on the integration layer. (See orange arrows on the picture)

If you want to catch runtime exceptions in your test classes instead, you can change the pointcut to this:

@Pointcut("within(com.redpill.linpro.demo..*Test)")
public void inDemoProjectTestClass() {}

Then the advice above will catch all exceptions in the test classes that ends with Test in the ..demo package.

More information about @AspectJ style here.

AspectJ is well integrated with Spring. General information about AspectJ can be found here and Spring's AspectJ support here.

Espen