我想回滚事务不是在EJB内部而是在JSF托管bean内部。在EJB内部,我们可以使用SessionContext.setRollBackOnly()
,但我可以在托管bean中使用什么?
@Stateless
@Local(AccountLocal.class)
public class AccountBean implements AccountLocal {
public void test1() throws CustomException(){
...
}
public void test2() throws CustomException(){
...
throw new CustomException();
}
public void test3() throws CustomException(){
...
}
public void all() throws CustomException(){
test1();
test2();
test3();
}
}
在我的托管bean中:
@SessionScoped
public class LoginBean implements Serializable{
public void test(){
try{
accountBean.test1();
accountBean.test2();
accountBean.test3();
}catch(CustomException e){
// WHAT HERE TO ROLLBACK TRANSACTION ?
}
}
}
编辑:如果其中一个test1
,test2
或test3
回滚,其他人也会回滚,我该如何确保?
我测试了此代码,即使accountBean.test1();
回滚,也会验证accountBean.test2();
。
解决方案是否只能将这3个方法嵌套在一个EJB方法中?
@SessionScoped
public class LoginBean implements Serializable{
public void test(){
try{
accountBean.all();
}catch(CustomException e){
...
}
}
}
答案 0 :(得分:5)
如果抛出未经检查的异常,则EJB容器会自动回滚事务(请注意JPA的PersistenceException
就是这样)。您的CustomException
似乎是经过检查的例外情况。如果将其更改为扩展RuntimeException
,如下所示
public class CustomException extends RuntimeException {
// ...
}
或创建一个新选项不是一个选项,那么您需要在rollback
属性设置为true
的类中设置@ApplicationException
注释。
E.g。
@ApplicationException(rollback=true)
public class CustomException extends Exception {
// ...
}
请注意,具体问题与JSF无关。服务层和管理事务完全不在JSF的责任范围内。这是EJB的责任。从这个角度来看,JSF应该仅仅充当“观点”。
答案 1 :(得分:1)
我在这里扮演魔鬼的拥护者,因为BalusC的建议是你不应该让你的支持豆子充当服务是绝对正确的。
但是,纯粹作为技术上的例外,它可以在辅助bean中启动JTA事务,然后以编程方式控制启动,提交或回滚。
您可以通过@Resource注入UserTransaction来完成此操作。在调用EJB方法之前,请在此实例上调用start,并在最后一次调用之后调用commit或rollback。
同样,这是纯理论答案。在实践中,不要这样做,让支持bean调用1个EJB方法,如果需要,可以调用其他EJB bean。