【问题标题】:How to figure out original exception responsible for transaction rollback in the JAX-RS exception mapper如何在 JAX-RS 异常映射器中找出负责事务回滚的原始异常
【发布时间】:2020-08-14 10:11:37
【问题描述】:

具体情况:在 Wildfly 15 上部署了一个 REST API 和一个 EJB 服务器 bean。REST 调用启动一个事务并触发一个自定义 CDI 事件。在我的服务器 bean 中,有一个带有事务阶段 BEFORE_COMPLETION 的事务观察者方法。在某些情况下,在此方法内部会故意抛出具有特定消息的自定义类型的运行时异常。我希望在这种情况下事务能够回滚(这也是正确发生的)。触发回滚的异常,我想在 JAX-RS 异常映射器中处理,最后从异常中发送特定的 HTTP 响应代码和消息。

现在,几乎一切都按我的意愿进行:事务回滚,异常映射器方法跳入并处理异常。

但我的大问题是:我在异常映射器中作为参数接收到的异常是 javax.transaction.RollbackException 类型,而不是我最初抛出的预期自定义类型。确切的消息是:“javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction.”另外,我的异常似乎没有嵌套在任何地方,例如作为收到异常的原因或在调用堆栈中,所以我无法弄清楚我的消息是什么,而且由于其他原因(如数据库错误等),我无法将此回滚与另一个潜在回滚区分开来。 /p>

问题:上面描述的我想要的想法是否可能?也许由于我缺乏 Java EE 经验,我完全误解了框架的行为方式,而这种情况根本无法以这种方式工作?知道这已经对我有帮助。否则,我应该怎么做才能让它工作,或者我怎样才能用其他方法达到预期的结果?

这是我当前的代码:

服务器 Bean

import javax.ejb.Stateless;
import javax.enterprise.event.Observes;
import javax.enterprise.event.TransactionPhase;
import javax.transaction.Transactional;

import my.custom.package.CustomRuntimeException

@Stateless
@Transactional
public class CustomBean
{
    public void onNewCustomEvent(
        @Observes( during = TransactionPhase.BEFORE_COMPLETION ) CustomEvent event )
    {
        // do something
        
        if ( isSomeError )
        {
            throw new CustomRuntimeException("Some important detail message.");
        }
    }
}

异常映射器

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class CustomRuntimeExceptionMapper implements ExceptionMapper< Throwable >
{
    @Override
    public Response toResponse( Throwable e ) // <--- Expect: CustomRuntimeException, receive: RollbackException
    {
        // evaluate the exception and send proper HTTP code
        return Response.status( Response.Status.NOT_FOUND ).build();
    }
}

异常类

public class CustomRuntimeException extends RuntimeException
{
    public CustomRuntimeException(String errorReason)
    {
        super (errorReason);
    }
}

2020-08-17。补充说明。 在服务器日志中,我注意到此错误消息,也许有助于更好地理解原因。我用谷歌搜索了这个,但找不到任何有用的东西。

WELD-000401: Failure while notifying an observer [UnbackedAnnotatedMethod] public CustomBean.onCustomEvent(@Observes CustomEvent) of event null.
 CustomRuntimeException

【问题讨论】:

    标签: java transactions jax-rs ejb jta


    【解决方案1】:

    其实你可以把这个注解放在你的自定义异常上

    @javax.ejb.ApplicationException(rollback=true)
    public class CustomRuntimeException extends RuntimeException{...}
    

    这样异常就会直接报告给客户端(解包)。

    默认情况下,EJB Container 将通过 EJBException 包装您的自定义异常,并且使用此注解不会包装异常。

    但在您的情况下,可能是另一个异常或回滚是原因,而不是 CustomAppException 尝试调试您的代码执行以找出实际发生的情况或提供完整的代码,以便我们尝试提供帮助。

    【讨论】:

    • 感谢您的回答,不幸的是,这并没有显着改变以前的行为。
    • 实际上我在 wildfly 15.0.0.Final 上为您测试了这个用例,它的工作原理与 java 文档所说的一样
    • 当你定义没有注释的自定义异常时,我得到 EJBException 包装我的自定义异常,如果我使用注释,我得到自定义异常在 jax-rs 异常映射器中解包
    • 可能会抛出另一个异常而不是您的 CustomException 这就是为什么您没有在回滚异常的 getCause() 中找到异常的原因
    • 能否请您将在事件处理程序中执行的完整代码?
    猜你喜欢
    • 2011-03-18
    • 2016-11-01
    • 2016-09-15
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多