是否可以在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();
}
}
答案 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);
}
我注意到注释仅在放置在各个方法上时才有效,通过将它放在类本身上不会有所作为。