When something fails on the server side because the database and the application are out of sync instead of getting an error and the application crashing spring/tomcat seems to swallow the exception and pretend nothing has happened.
Call me crazy but if the program fails catastrophically I want it to actually fail catastrophically! Is there anyway to switch this behaviour off? It's really slowing development down when the server pretends that everything is fine when it's just thrown up into the logs.
If this isn't the spring/tomcat default then what else might be causing it? We are using a boatload of libraries and frameworks unfortunately. Spring would be the usual suspect but it could be something else.
Update
It's a sql server database which we are connecting to using SqlServerDataSource
. Hibernate is in use in some parts of the project but is used to query the database at login time. On the client side we are using extjs and we are also using ExtDirectSpring to annotate methods for the client side to talk to. To translate the data going across the wire there's Jackson, which then gets wrapped by the extdirect json handler.
There's some AOP stuff going on thats to do with logging exceptions but deleting that code results in the same behaviour.
Further update
Ok its not a good idea to let your sever crash! See my answer below for my proposed middle ground.
If you really want to do that (but IMHO you should not ...) you can use a filter that will block the application once it let an uncaught exception go. It could be something like :
public class CrashFilter implements Filter {
private boolean crashed = false;
private String msg = "Major problem : application stopped";
@Override
public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws IOException, ServletException {
if (crashed) {
HttpServletResponse resp = (HttpServletResponse) sr1;
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg);
return;
}
try {
fc.doFilter(sr, sr1);
}
catch (Exception ex) {
crashed = true;
throw new ServletException(ex);
}
}
// init and destroy omitted from brevity
}
Ok so I did this in the end. I've basically used the ideas above but thought there was enough extra to post my own answer.
It turns out you really shouldn't do this as other people suggested and I've added a bit at the bottom to say why!
Here's my filter:
public class FailOnErrorFilter implements Filter
{
@Override
public void init(FilterConfig config) throws ServletException
{
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException
{
try {
filterChain.doFilter(request, response);
}
catch (Exception exception) {
System.exit(1);
}
}
@Override
public void destroy()
{
}
}
To get this working you have to modify the web.xml:
<filter>
<filter-name>failingFilter</filter-name>
<filter-class>fullyQualified.FailOnErrorFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>failingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The top one defines the filter + the second one says use it everywhere.
ExtDirectSpring
After doing the above I realised that ExtDirectSpring was a further culprit. It's default behaviour is to swallow all exceptions in server side methods.
I was worried I was going to have to patch the library but thankfully someone else had already complained about this and it got fixed in 1.3.6. Initially I tried upgrading to the latest version but it broke a load of code! What a great library. Anyway 1.3.6 added in the ability to switch off the suppression of errors by doing the following:
//this is to switch off blanket switching of exceptions in extdirect spring
@Component
public class NoExceptionHandling implements RouterExceptionHandler
{
@Override
public Object handleException(MethodInfo methodInfo, BaseResponse baseResponse, Exception e, HttpServletRequest httpServletRequest)
{
throw new RuntimeException(e);
}
}
As the name suggests extdirectspring uses spring and so doesn't make its dependencies obvious to calling code, however if you go digging (its on github). You'll see in RouterController it calls the following method in the catch
private Object handleException(MethodInfo methodInfo, BaseResponse response, Exception e, HttpServletRequest request) {
return configurationService.getRouterExceptionHandler().handleException(methodInfo, response, e, request);
}
Where router controller does this:
@Autowired(required = false)
private RouterExceptionHandler routerExceptionHandler;
public RouterExceptionHandler getRouterExceptionHandler() {
return routerExceptionHandler;
}
It sets up a default one if you dont provide one.
Update - why you shouldn't do this
It turns out you really shouldn't call System.exit
in a tomcat application. Not only does it bring down your application it also causes the server to exit. This brings down any other applications running aswell!
It's also not appropriate for a number of other reasons:
Likewise:
What I'm doing instead
The errors were already being written the the tomcat logs + the database.
Just to make things more complicated unsurprisingly the original webapp is too flaky to not mask errors so I've kept the old error suppression in place for that as we're not actively developing/fixing it at the moment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With