【发布时间】:2014-05-29 23:05:02
【问题描述】:
我想提交一个带有文件和其他简单字段的表单。因为发送文件并将其保存在文件系统中是 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 所做的更改。
编辑
我已经用@TransactionAttribute(TransactionAttributeType.MANDATORY) 注释了我的LectureFacade.create 方法,它给了我一个javax.ejb.EJBTransactionRequiredException 所以看起来CDI 事务没有传播到EJB 事务。
【问题讨论】:
-
如何将交易标记为失败?带注释?一些代码可以帮助我们帮助您。
-
没有,我只是看到抛出了java.io.FileNotFoundException,文件没有保存,但是数据库中的数据已经保存了。
-
您可以通过解耦创建讲座和上传与讲座相关的文件来简化事情并避免处理此问题。因此工作流程将是 1)创建讲座并将 id 返回给客户端 2)客户端上传文件并将 id 作为参数传递。如果您在侧面 handleFileUpload 中有其他与模型相关的逻辑,这可能会被过度简化,但由于您没有粘贴我不知道的代码。
-
另外,您的 emailSubsystem 商务逻辑是 TX 的一部分吗?
标签: jakarta-ee jta