Spring grails应用程序由于在init中捕获异常而关闭

Spring grails应用程序由于在init中捕获异常而关闭,spring,exception,grails,groovy,application-shutdown,Spring,Exception,Grails,Groovy,Application Shutdown,我有一个Grails2.4.5应用程序,它在启动时从bootstrap.groovy运行init闭包。它可能抛出异常,也可能不抛出异常,但无论哪种情况,应用程序都必须继续运行。实际发生的情况是,在init()期间,应用程序无法与服务器通信,底层库抛出一个SocketTimeoutException,然后被我的代码捕获。捕获到的异常意外地导致应用程序调用destroy()并关闭应用程序,这是我不希望看到的。我希望既然捕获了异常,就不会报告任何错误,应用程序应该保持运行 下面是使用RestTempl

我有一个Grails2.4.5应用程序,它在启动时从bootstrap.groovy运行init闭包。它可能抛出异常,也可能不抛出异常,但无论哪种情况,应用程序都必须继续运行。实际发生的情况是,在init()期间,应用程序无法与服务器通信,底层库抛出一个SocketTimeoutException,然后被我的代码捕获。捕获到的异常意外地导致应用程序调用destroy()并关闭应用程序,这是我不希望看到的。我希望既然捕获了异常,就不会报告任何错误,应用程序应该保持运行

下面是使用RestTemplate库导致应用程序被销毁的代码。没有这段代码,它仍然在运行。捕获并打印异常,然后关闭应用程序

init = { servletContext ->
    try {
        // Send a post request
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", auth);
        headers.add(HttpHeaders.CONTENT_TYPE, "application/json");
        HttpEntity entity = new HttpEntity(headers);
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectTimeout(10000);
        httpRequestFactory.setReadTimeout(10000);
        RestTemplate rt = new RestTemplate(httpRequestFactory);
        ResponseEntity<String> rtString = rt.exchange(ME_URL + '/apps/register', HttpMethod.POST, entity, String.class);
    } catch (Exception e) {
        // don't rethrow
        println e.getMessage(); // gets here, app is shutdown
    }
}
现在我开始认为可能是init()泄漏了异常,所以我试图手动抛出一个异常来测试这个理论。我尝试了一个基本异常以及前两个库抛出的SocketTimeoutException。这很有趣,因为我已经证明这个异常不会以某种方式“泄漏”出grails init闭包。下面的代码不会导致应用程序关闭,它仍在运行,这正是我想要的

init = {
    try {
        throw new java.net.SocketTimeoutException("fake exception");
    } catch (Exception e) {
        // don't rethrow
        println e.getMessage(); // gets here, but app continues
    }
}
通常,错误日志中打印的唯一内容是java.net.SocketTimeoutException的stacktrace,以及我自己的检测代码,以显示确实调用了destroy()

2017-01-09 12:01:51825[localhost-startStop-1]错误堆栈跟踪- 完整堆栈跟踪:XXX.YYY.ZZZ.AAA.GatewayException: java.net.SocketTimeoutException:读取在时超时 三十、 YYY.ZZZ.registerApp(GatewayService.groovy:83)位于 三十、 YYY.ZZZ.initApp(GatewayService.groovy:50)位于 三十、 YYY.ZZZ.init(GatewayService.groovy:39)位于 三十、 YYY.ZZZ.slientInit(GatewayService.groovy:30)位于 三十、 YYY.ZZZ.BBB(初始化器.groovy:88)位于 BootStrap$\u closure1.doCall(BootStrap.groovy:17)位于 grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:327) 在 grails.util.Environment.executeForEnvironment(Environment.java:320) 在 grails.util.Environment.executeForCurrentEnvironment(Environment.java:296) 在java.util.concurrent.FutureTask.run(FutureTask.java:266)处 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 在java.lang.Thread.run(Thread.java:745)处,由以下原因引起: com.mashape.unirest.http.exceptions.unirest异常: java.net.SocketTimeoutException:读取在时超时 http.HttpClientHelper.request(HttpClientHelper.java:143) 在 com.mashape.unirest.request.BaseRequest.asObject(BaseRequest.java:80) 在XXX.YYY.ZZZ.registerApp(GatewayService.groovy:71)。。。还有12个

我要找的是:

  • 为什么会这样
  • 我能做些什么来解决这个问题
  • 如果我无法修复现有代码,那么解决方法是什么?我尝试过的解决方法:在扩展InitializingBean之后使用PostContext注释和AfterPropertieSet方法。这两个解决方案不起作用,因为我使用的init代码最终将使用GORM,所以GORM必须在代码运行时运行。在这两个钩子期间,GORM还没有准备好(或者错误消息是这样说的)
  • 我正在使用Grails2.4.5

    还有一件事:除了上面看到的代码之外,我已经删除了init中的所有代码,所以我相当确定这些REST调用获取异常是应用程序关闭的直接原因


    非常感谢您的帮助。谢谢

    嗨,我有几个问题:1)我的URL,这是一个独立的服务器吗?2) 当您将超时值增加到更大的值时,例如30秒,您的服务器启动是否会暂停30秒,然后无法初始化?3) 您确定抛出的异常实际上不是一个错误(不是异常的子类,但仍然是可丢弃的)吗?可能用catch(Throwable e)替换catch(Execption e)?1)我的URL当前设置为,我们遇到了这个问题。今天,我发现代码突然起作用了——也就是说,我们捕获了异常,应用程序继续运行。我跟踪到一个开发人员将端口更改为我的计算机上没有运行的端口,因此仍然失败,但出现了HttpHostConnectException。当使用端口8081时,它会失败,因为有一个服务正在侦听该端口,但失败是SocketTimeoutException,它以某种方式(直接或间接)导致应用程序终止,尽管有catch语句。2)超时增加到2分钟,是的,服务器启动会暂停该时间。这是一个阻塞呼叫。然后它捕获异常(当使用端口8081时-请参见#1),但应用程序被销毁。因此,似乎超时不是一个因素3)是的,当然这是一个例外。HttpHostConnectException和SocketTimeoutException。我还试着用脚踢的方式抓住一次性的东西,行为也是一样的@loteqBounty仍然可用-需要找到根本原因,以及如何更改代码(无需进行一些疯狂的奇怪破解)以解决我的问题
    init = {
        try {
            throw new java.net.SocketTimeoutException("fake exception");
        } catch (Exception e) {
            // don't rethrow
            println e.getMessage(); // gets here, but app continues
        }
    }