问题描述
当服务器端发生故障时,因为数据库和应用程序不同步,而不是发生错误,并且应用程序崩溃的spring / tomcat似乎吞没了异常,并假装没有发生任何事情。
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.
如果这不是spring / tomcat的默认值,那还有什么可能是造成的?
不幸的是,我们正在使用一大堆图书馆和框架。春天将是通常的嫌疑人,但可能是别的东西。
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.
更新
这是一个sql server数据库,我们使用 SqlServerDataSource
连接。 Hibernate在项目的某些部分使用,但用于在登录时查询数据库。在客户端,我们使用extjs,我们也使用ExtDirectSpring来注释客户端的方法。要翻译通过电线的数据,Jackson将被extdirect json处理程序包裹。
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.
有一些AOP的东西在做这些记录异常,但删除该代码产生相同的行为。
There's some AOP stuff going on thats to do with logging exceptions but deleting that code results in the same behaviour.
进一步更新
一个好主意,让你的破裂!看到我的回答我的建议的中间位置。
Ok its not a good idea to let your sever crash! See my answer below for my proposed middle ground.
推荐答案
好的,所以我做到这一点。我基本上使用了上面的想法,但认为有足够的额外发布我自己的答案。
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!
这是我的过滤器:
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()
{
}
}
$ b
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
在完成上述之后,我意识到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.
我担心我将要修补图书馆,但幸运的是有人已经抱怨了这一点,它在1.3.6中被修正。最初我尝试升级到最新版本,但它打破了一个代码的负载!一个伟大的图书馆无论如何,1.3.6添加了通过执行以下操作来关闭错误的功能:
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);
}
}
顾名思义,extdirectspring使用spring,使它的依赖关系显而易见的调用代码,但是如果你去挖掘(在github上)。您将在RouterController中看到它在catch中调用以下方法
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.
更新 - 为什么不应该这样做
原来你真的不应该在tomcat应用程序中调用 System.exit
。它不仅会降低您的应用程序,还会导致服务器退出。这导致了任何其他运行的应用程序!
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:
- 如果一系列测试中的第一个引发异常,则所有后续测试将失败
- 重新启动服务器耗时耗时,您必须是断开的人如果您在单独的计算机上运行手动测试部署,则可以查看异常
- ,否则如果某处导致问题,则必须重新启动服务器。
同样:
- 在生产中,每个人的应用程序都会关闭,大多数用户不能重新启动服务器。
我在做什么
错误已经写入tomcat日志+数据库。
The errors were already being written the the tomcat logs + the database.
- 在调试中现在还要使用stacktrace
- 重定向到错误页面我们将要重新定向到出错页面。我们还将设置一个电子邮件服务,通知我们例外情况。
- 对于UI /硒测试 - 它将与调试相同。
- 对于无头Js测试,服务器拒绝后续请求,直到下一次测试重置服务器的错误状态
- In debug we now also going to redirect to an error page with the stacktrace
- In production we are going to just redirect to a 'something went wrong' page. We're also going to set up an email service that notifies us of exceptions.
- For UI/selenium tests - it'll work the same as debug
- For headless Js tests the server rejects subsequent requests until the next test resets the error state of the server
只是为了做事情更复杂的是,令人惊讶的是,原始的webapp太薄了,不能掩盖错误,所以我保留旧的错误抑制,因为我们目前没有积极开发/修复它。
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.
这篇关于你如何阻止春季吞咽例外?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!