I am trying to execute a sql statement in Listener's contextInitialized method, but when I run gretty local server, it throws RuntimeException error. I can't figure out, why. It doesn't run into any errors when i comment out ps.executeQuery();
.
@Override
public void contextInitialized(ServletContextEvent sce){
ServletContext sc = sce.getServletContext();
DataSource pool = new ConnectionPoolFactory().createConnectionPool();
String sql = "create table test (id int);";
try (Connection conn = pool.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.executeQuery();
} catch (SQLException e) {
throw new RuntimeException();
}
}
"Doctor, it hurts when I press here!"
Well, stop doing that then.
This:
} catch (SQLException e) { throw new RuntimeException(); }
is in a word insane. You're taking a useful error which includes 5 convenient aspects that will help you figure out what went wrong:
You've decided to pitch them all into the garbage, to replace it with a single RuntimeException that gives no useful information of any sort or kind whatsoever.
Do not do that.
Proper exception handling involves being a lot less scared of the throws
clause on methods. Got a method that does DB stuff, and the design of this method is clearly indicated to do so (if the method is named 'query' or otherwise contains any word that obviously indicates SQL, the answer is clearly: Yes, it does), then that method should be declared to throws SQLException
, for example.
Secondarily, in the rare cases where throwing it onwards does not work out, if you catch an exception, you do not want to just log it and continue, and you do not want to throw some other exception without setting up a cause first. This is the standard 'I do not know what to do and I do not want to spend any further time on thinking about it' exception handler:
} catch (ThingIDoNotWantToThinkAbout e) {
throw new RuntimeException("Unhandled", e);
}
That , e
is crucial, it sets up the actual exception as cause, so that you actually see it in your stack traces and logs. It is very common to see a standard exception handling of e.printStackTrace()
. Do not do this - 90% of java examples are bad. This causes all sorts of problems, because the 'logs' go to standarderr (which is a lot less flexible than letting them go to the exception handler of the context within which you are operating. For example, if writing a web handler, e.printStackTrace()
just dumps stack. Throwing an exception upwards will dump stack and allow the framework to add information about the request that triggered the problem, and serve up a suitable HTTO status 500 error page. Also, by just running printStackTrace, the code will continue execution, which is obviously not what you want: Something went wrong - continuing blindly onward will either guarantee that your software silently does the wrong thing, or causes further exceptions, thus resulting in a single error causing hundreds of stack traces flooding your syserr.
Once you've fixed this problem here and everywhere else in your code, the actual problem will most likely be clear as day. Something about the SQL server being down or a syntax error in your SQL.