我想提交一个包含文件和其他简单字段的表单。因为发送文件并将其保存在文件系统中对于Web层来说是典型的,所以我在CDI托管bean中执行此操作。从这个CDI托管bean我也调用EJB将其他数据存储在数据库中。保存文件可能会失败,因此我使用@Transactional(JEE7)注释了我的CDI bean的方法。我期望的是在保存文件失败时回滚EJB的事务,但事实并非如此。这是正常的行为吗?在这种情况下如何回滚EJB的事务?
@Named
@javax.faces.view.ViewScoped
public class LectureCtrl
{
@Inject LecturesFacade lecturesFacade;
@Getter @Setter UploadedFile paper;
@Getter @Setter Lecture lecture;
@Transactional(rollbackOn={FileNotFoundException.class})
public void create(Lecture _lecture) throws MessagingException, IOException
{
try{
Long _lectureId = lecturesFacade.create( _lecture );
//args: file, path, constant filename "abstract"
WebUtils.handleFileUpload( this.paper, "conferences/"+lecture.getConference().getId()+"/lectures/"+_lectureId, "abstract" );
}catch(Exception e){
System.out.println(e);
throw e;
}
}
public String onSubmitNewLecture(){
//JSF-specific code
this.create(this.lecture);
//JSF-specific code
}
}
@Stateless
public class LecturesFacade {
@PersistenceContext EntityManager em;
@Inject EmailSubsystem emailSubsystem;
public Long create( Lecture lecture ) throws MessagingException
{
em.persist(lecture);
em.flush();
em.refresh(lecture);
Long id = lecture.getId();
emailSubsystem.sendEmailOnNewLecture(lecture);
return id;
}
}
例外:
INFO: java.io.FileNotFoundException: C:\konferencje\files\conferences\3\lectures\20\abstract (Access is denied)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:212)
at java.io.FileOutputStream.<init>(FileOutputStream.java:165)
at BackingBeans.WebUtils.handleFileUpload(WebUtils.java:154)
at BackingBeans.LectureCtrl.create(LectureCtrl.java:56)
...
当WebUtils.handleFileUpload
失败时,我还希望回滚lecturesFacade.create
所做的更改。
修改
我已使用LectureFacade.create
注释了我的@TransactionAttribute(TransactionAttributeType.MANDATORY)
方法,并向我抛出javax.ejb.EJBTransactionRequiredException
,因此看起来CDI事务不会传播到EJB事务。 / p>
答案 0 :(得分:0)
问题是您需要定义回滚事务的已检查异常。 @Transactional注释有一个名为rollbackOn的字段来设置此
所以尝试注释@Transactional(rollbackOn={FileNotFoundException.class})
- 我没有尝试过代码,所以可能会有拼写错误。您需要指定此原因的原因是FileNotFoundException是一个已检查的异常。
请阅读我链接的文档,因为这是使用容器管理事务时最常见的错误之一。
这很奇怪。您可以尝试将IOException添加到rollbackOn
吗?如果这不能解决,我会检查:
LectureCtrl
创建了一个事务代理答案 1 :(得分:0)
我刚刚意识到我正在从同一类的非事务方法(onSubmitNewLecture)调用@Transactional方法(create),因此将省略@Transactional拦截器。