Tuesday, March 10, 2015

Catch Exception or catch Throwable when you need to log anything


When you ask yourself a question what to catch in main method Exception and Throwable - use Throwable to catch all unexpected problems for sure.

if you choose to catch Exception you will lose Errors ,and Errors are not only system problems.

interesting Error that could happen in business logic + misconfiguration
http://docs.oracle.com/javase/7/docs/api/java/lang/ExceptionInInitializerError.html

initialization of non static field

Configuration.getBean(FileToCsvExtractor.class);

declaration of Configuration

public enum Configuration {
INSTANCE;

private AbstractApplicationContext context;

private Configuration() {
this.context = new AnnotationConfigApplicationContext("com.mycompany");
}

public static <T> T getBean(Class<T> clazz) {
return INSTANCE.context.getBean(clazz);
}

public void destroy() {
context.close();
}

}


If you somewhow did a mistake in from and Configuration will fail to initialize then getBean is failed with ExceptionInInitializerError, but it have a cause Exception that could be like:

Exception in thread "main" java.lang.ExceptionInInitializerError
at com.mycompany.ExecutableImpl.execute(LdLogRenaissanceDeployJob.java:23)
at com.revere.xfeed.customclients.renaissance.MyTestClass.main(MyTestClass.java:8)
Caused by: org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.FileNotFoundException: myproperties.properties (No such file or directory)
at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:87)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:694)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:669)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:461)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)


so you have to catch Thowable in main method to log all problems before exiting a application.

interface Executable {
void execute(Object args) throws Throwable;
}

class ExecutableImpl implements Executable {

public void doAll() throws IOException, FTPException {
                        Configuration.getBean(FileToCsvExtractor.class);
throw new IOException();
}

@Override
public void execute(Object args) throws Throwable {
try {
doAll();
} catch (Throwable th) {
throw th;
}
}

}

or do "throws Exception" in interface , no other changes are required,  but that will kind if lie to developers as you know that code could throw ExceptionInInitializerError :) even it mean to be RuntimeException.

More interesting cases where catching Errors is ok:
http://blog.igorminar.com/2008/05/catching-stackoverflowerror-and-bug-in.html
http://programmers.stackexchange.com/questions/209099/is-it-ever-okay-to-catch-stackoverflowerror-in-java

Smb in code could use Errors http://docs.oracle.com/javase/7/docs/api/java/lang/AssertionError.html :) as a validation of some sort, .....


One more case of Error that is ok finish gently application  - is
java.lang.NoClassDefFoundError: com.mycompany.ISqlRowMapper
....
Caused by: java.lang.ClassNotFoundException: com.mycompany.ISqlRowMapper
it is completely to ok to catch it log it!! Yes it was terrible misconfiguration in maven level, but UTs were passed and problem appear only in fully deployed application  and in the middle of execution (not at start).

No comments:

Post a Comment