CMT无状态bean中的异常处理

时间:2013-08-14 21:17:29

标签: java exception transactions ejb

是否可以在CMT(容器管理事务)无状态bean中捕获异常?

下面的代码在我尝试时不会捕获任何异常。如果我使用BMT(Bean管理事务),我可以捕获异常。但我想继续留在CMT。

@Path("books")
public class BookResource 
{

    @EJB
    private BooksFacade book_facade;

    private Books local_book;


    @POST
    @Consumes({"application/xml", "application/json"})
    public Response create(Books entity) 
    {
       try 
        {
            book_facade.create(entity);
        } catch (RuntimeException ex) 
        {
            System.out.println("Caught database exception");
        }
       return Response.status(Response.Status.CREATED).build();
    }



 public class TXCatcher
{

    //@Resource
    //UserTransaction tx;
    private final static Logger LOG = Logger.getLogger(TXCatcher.class.getName());

    @AroundInvoke
    public Object beginAndCommit(InvocationContext ic) throws Exception 
    {
        //ic.proceed();
        System.out.println("Invoking method: " + ic.getMethod());
        try 
        {
            //tx.begin();
            Object retVal = ic.proceed();
            //tx.commit();
            return retVal;
        }catch (RollbackException e) 
        {
            LOG.log(Level.SEVERE, "-----------------Caught roolback(in interceptor): {0}", e.getCause());
            System.out.println("Invoking method: " + ic.getMethod());
            throw new CustomEx("Database error");
        }catch (RuntimeException e) 
        {
            LOG.log(Level.SEVERE, "-----------------Caught runtime (in interceptor): {0}", e.getCause());
            System.out.println("Invoking method: " + ic.getMethod());
            //tx.rollback();

            throw new CustomEx("Database error",e.getCause());
            //throw new CustomEx("Database error");
        }



        //return ic.proceed();


    }

}

2 个答案:

答案 0 :(得分:0)

这取决于你想要捕捉到什么样的问题。您可以尝试使用显式的EntiyManager.flush,但是根据您的数据源隔离级别,在事务提交之前无法捕获一些错误,并且没有用于捕获CMT的事务提交错误的机制。如果是这种情况,你唯一的选择是使用BMT(即使你说你不想)。唯一可能使得更可口的建议是编写一个行为与CMT类似的EJB拦截器(即将UserTransaction注入拦截器,并在@AroundInvoke中开始/提交/回滚)。

答案 1 :(得分:0)

通过在我的BooksFacade类创建函数中放置以下函数,CMT在第一个事务中创建了第二个事务。当从第二个事务抛出异常时,我的BookResource类create方法可以捕获它。不需要BMT。

@Overide
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void create(Books entity) 
{
    super.create(entity);
}  

我注意到注释仅在放置在各个方法上时才有效,通过将它放在类本身上不会有所作为。