Exception 在Groovy中为异常或错误添加更多上下文

Exception 在Groovy中为异常或错误添加更多上下文,exception,groovy,Exception,Groovy,当我只想为发生的任何异常(包括解析错误甚至内存不足)添加更多上下文时,我编写如下代码 try { new JsonSlurper().parseText(response) } catch (any) { throw new IllegalStateException("Cannot parse response:\n$response", any) } 这很好,但我可能最终会将OutOfMemoryError包装在IllegalStat

当我只想为发生的任何异常(包括解析错误甚至内存不足)添加更多上下文时,我编写如下代码

    try {
        new JsonSlurper().parseText(response)
    } catch (any) {
        throw new IllegalStateException("Cannot parse response:\n$response", any)
    }
这很好,但我可能最终会将
OutOfMemoryError
包装在
IllegalStateException
中,这听起来不太正确,因为可能会有专门的异常处理机制,只用于
错误
可丢弃文件


有没有办法只向异常添加更多上下文,而仍然保留其原始类型或类别?也就是说,当我得到
OOME
时,我想重新显示
错误
,当我得到一些解析异常时,我想重新显示一些未检查的异常等。当然,我不想为每个类别手动执行,因为
OOME
不太可能,我也不想为特殊情况生成特殊代码(尽管我仍然希望在技术上是正确的)。

您可以在groovy中通过使用其功能来实现这一点。特别是,对于您的案例,它提供了您所需要的一切。使用它们,您可以动态地将
contextData
对象添加/附加到
异常
中,您希望它随身携带:

    private static void throwsEnhancedException() throws IOException {
        try {
            throwsBasicException()
        } catch (IOException e) {
            e.metaClass.contextData = "My context data"
            throw e;
        }
    }
然后,要在代码的其他部分检索此
contextData
,只需检查
异常
对象,如下所示:

    private static void doSomethingWithContextData(Closure contextDataHandler) throws IOException {
        try {
            throwsEnhancedException();
        } catch (IOException e) {
            // RETRIEVE `contextData` FROM `e` OR NULL IF THE PROPERTY DO NOT EXIST
            def contextData = e.hasProperty('contextData')?.getProperty(e)

            // DO SOMETHING WITH `contextData`
            contextDataHandler(contextData)
        }
    }
在这里,我使用参数
contextDataHandler
作为groovy,以灵活的方式处理
contextData

以下是此功能的完整工作演示:

import java.time.LocalDateTime

class ExceptionEnhancer {
    static void main(String[] args) {
        def logger = { println "${LocalDateTime.now()} - Context Data = [$it]" }
        doSomethingWithContextData logger
    }

    private static void doSomethingWithContextData(Closure contextDataHandler) throws IOException {
        try {
            throwsEnhancedException();
        } catch (IOException e) {
            // RETRIEVE `contextData` FROM `e` OR NULL IF THE PROPERTY DO NOT EXIST
            def contextData = e.hasProperty('contextData')?.getProperty(e)

            // DO SOMETHING WITH `contextData`
            contextDataHandler(contextData)
        }
    }

    private static void throwsEnhancedException() throws IOException {
        try {
            throwsBasicException()
        } catch (IOException e) {
            e.metaClass.contextData = "My context data"
            throw e;
        }
    }

    public static void throwsBasicException() throws IOException {
        throw new IOException();
    }
}


希望这能有所帮助。

通过使用groovy的功能,您完全可以在groovy中做到这一点。特别是,对于您的案例,它提供了您所需要的一切。使用它们,您可以动态地将
contextData
对象添加/附加到
异常中,您希望它随身携带:

    private static void throwsEnhancedException() throws IOException {
        try {
            throwsBasicException()
        } catch (IOException e) {
            e.metaClass.contextData = "My context data"
            throw e;
        }
    }
然后,要在代码的其他部分检索此
contextData
,只需检查
异常
对象,如下所示:

    private static void doSomethingWithContextData(Closure contextDataHandler) throws IOException {
        try {
            throwsEnhancedException();
        } catch (IOException e) {
            // RETRIEVE `contextData` FROM `e` OR NULL IF THE PROPERTY DO NOT EXIST
            def contextData = e.hasProperty('contextData')?.getProperty(e)

            // DO SOMETHING WITH `contextData`
            contextDataHandler(contextData)
        }
    }
在这里,我使用参数
contextDataHandler
作为groovy,以灵活的方式处理
contextData

以下是此功能的完整工作演示:

import java.time.LocalDateTime

class ExceptionEnhancer {
    static void main(String[] args) {
        def logger = { println "${LocalDateTime.now()} - Context Data = [$it]" }
        doSomethingWithContextData logger
    }

    private static void doSomethingWithContextData(Closure contextDataHandler) throws IOException {
        try {
            throwsEnhancedException();
        } catch (IOException e) {
            // RETRIEVE `contextData` FROM `e` OR NULL IF THE PROPERTY DO NOT EXIST
            def contextData = e.hasProperty('contextData')?.getProperty(e)

            // DO SOMETHING WITH `contextData`
            contextDataHandler(contextData)
        }
    }

    private static void throwsEnhancedException() throws IOException {
        try {
            throwsBasicException()
        } catch (IOException e) {
            e.metaClass.contextData = "My context data"
            throw e;
        }
    }

    public static void throwsBasicException() throws IOException {
        throw new IOException();
    }
}


希望有帮助。

我强烈建议不要做你想做的事情。有各种各样的原因。考虑下面的场景。如果<代码>响应< /代码>持有2 GB的不正确的数据?你想记录吗?如果你的应用程序使用了一些远程记录器,你想用你的网络传输2 GB的数据吗?不处理您的客户请求?如果JSON响应包含一些敏感数据怎么办?我不知道上下文,但您请求的内容听起来很可疑。解析异常通常提供一些有用的上下文,可以用来调查问题。在我的上下文中没有敏感数据。如果有东西返回2GB不正确的数据t数据,我想努力将其记录下来,以便进行调查。对我来说,这总比没有用于调查的数据好。一般来说,我同意,在泛型库中应该避免使用此类代码,但在我的代码中,这是我所期望的。我明白你的意思,我同意拥有用于调查的数据是必要的。然而,这并不只是您可以捕获任何异常,将响应转储到文件(或DB),记录错误发生并转储用于调查的数据(您可以从JSON响应生成sha1sum,并确保只转储一次响应),最后-重新显示您之前捕获的异常。当然,转储响应可能会失败,因此您需要提前考虑。这种实现是明确的,可以很好地封装。是的,您提出的建议听起来像是解决方案,但需要额外的编码和测试。在我的情况下,绝大多数响应都是真正的s购物中心(我控制他们)我希望在调查过程中直接传递它们,以减少在调查过程中的一跳。我强烈建议不要做你想做的事情。有各种各样的原因。考虑下面的场景。如果<代码>响应< /代码>持有2 GB的不正确数据?要记录吗?如果你的应用程序使用了一些远程的数据,你会怎么办?logger-您想使用您的网络传输2 GB的数据而不是处理您的客户请求吗?如果JSON响应包含一些敏感数据怎么办?我不知道上下文,但您请求的内容听起来很可疑。解析异常通常提供一些有用的上下文,可以用来调查问题。在我的文本没有敏感数据。如果有东西返回2GB不正确的数据,我想努力将其记录下来,以便进行调查。对我来说,这总比没有数据进行调查好。一般来说,我同意,在泛型库中应该避免此类代码,但在我的代码中,这是我所期望的。我明白你的意思,我同意having用于调查的数据是必不可少的。但是,使用异常并不合理。请换一种方式考虑。您可以捕获任何异常,将响应转储到文件(或DB),记录错误发生的情况,并转储用于调查的数据(您可以从JSON响应生成sha1sum,并确保只转储一次响应),最后-重新显示您之前捕获的异常。当然,转储响应可能会失败,因此您需要提前考虑。这种实现是明确的,可以很好地封装。是的,您提出的建议听起来像是解决方案,但需要额外的编码和测试。在我的情况下,绝大多数响应都是真正的small(我控制它们),所以我想直接通过它们,例外是在调查过程中少跳一次。