我正在维护看起来像这样的代码
@Asynchronous
@TransactionTimeout(value = 1, unit = TimeUnit.HOUR)
public void downloadFile(Long fileId) {
//This method takes more than 1hour
service.download(fileId)
//this method should be called even when download finished with error
service.fileDownloadedFinishedNotification(fileId);
}
这只是一个示例代码,我们正在向 fileDownloadedFinished
传递我们想要显示的消息等,并且在其中我们希望将进程标记为已完成,但有错误/成功。
因此,正如您在下载时看到的那样,我们会遇到超时,之后 fileDownloadedFinishedNotification
将不会被调用,因为事务因超时而失败。
我正在考虑将通知提取到其他方法并像这样调用它:
@Asynchronous
@TransactionTimeout(value = 1, unit = TimeUnit.HOUR)
public Future<String> downloadFile(Long fileId) {
//This method takes more than 1hour
service.download(fileId)
return new AsyncResult<String>("Test");
}
public void example(){
long id = 15;
String msg = "default stuff";
try {
msg = downloadFile(id).get();
}
catch (Exception e) {
e.printStackTrace();
}
service.fileDownloadedFinishedNotification(fileId, string);
}
但我不确定这是否是个好主意,或者也许还有其他一些功能,我可以在超时时调用。类似于 onTimeout
。
最佳答案
一些注意事项:
- 据我所知,没有简单的方法可以使用监听器处理事务超时
- 注释在幕后使用动态代理,因此它们不会应用于内部调用,您必须调用
downloadFile
从外部(在调用者中注入(inject)的 bean 上)。 - 当前事务将在
fileDownloadedFinishedNotification
时中止将被调用,因此对事务处理资源(数据库等)的所有操作都将回滚(您可能必须在专用事务中调用该方法(例如,使用@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
注释您的方法。 - 假设
download
方法通过网络检索内容,除非您最后通过专用JCA adapter
访问此内容,事务超时不会抛出异常,Transaction reaper
只将当前事务标记为中止并释放相关资源,但 does not interrupt the thread ,只有对托管资源(数据源、JMS 等)的后续访问才会抛出异常。 - 关于最后一点,在与非托管资源交互时,了解当前事务是否仍处于 Activity 状态的唯一方法是使用
EJBContext.getRollbackOnly()
定期检查其状态。或者通过对任何托管资源进行虚拟访问。
关于java - 当交易超时时如何执行一些操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57034630/