事务超时时如何采取措施

时间:2019-07-15 06:58:05

标签: java java-ee jboss transactions ejb

我正在维护看起来像这样的代码

@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之类的东西。

2 个答案:

答案 0 :(得分:1)

一些注意事项:

  • 没有简单的方法来使用监听器AFAIK处理事务超时
  • 注释在后台使用动态代理,它们不会因此应用于内部调用,而您必须从外部(在注入到调用方中的bean上)调用downloadFile
  • 当调用fileDownloadedFinishedNotification时,当前事务将被中止,因此对已事务处理的资源(数据库等)的所有操作都将回滚(您可能必须在专用事务中调用该方法) (例如,用@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)注释您的方法。
  • 假设download方法通过网络检索内容,除非您最后通过专用的JCA adapter访问此内容,否则事务超时不会引发任何异常,Transaction reaper仅标记当前事务中止并释放相关资源,但是does not interrupt the thread仅随后对MANAGED资源(数据源,JMS等)的访问将引发异常
  • 关于最后一点,在与非托管资源进行交互时,了解当前事务是否仍处于活动状态的唯一方法是使用EJBContext.getRollbackOnly()或通过对任何托管资源进行虚拟访问来定期检查其状态。

答案 1 :(得分:1)

有多种方法可以实现您想要的,但是正确的实现需要更多有关您对应用程序更改的访问级别的信息。 在很多地方都解释了事务传播,但是让您在EJB容器中运行应用程序,我将从这里开始:

https://docs.oracle.com/javaee/6/tutorial/doc/bncih.html

我会读完所有章节,但最适合您的情况的是此处的容器托管交易:

https://docs.oracle.com/javaee/6/tutorial/doc/bncij.html

现在假设您拥有完全访问权限,并且可以按照我将要实现的方式更改数据库结构,即:

  • 您正在上级事务T1中运行服务
  • 在调用下载方法之前,请调用另一个服务来记录开始的下载和完成的最大预期时间。在REQUIRED_NEW交易中执行此操作。这项耗时的数据库交互将在自治事务T2中运行
  • 一旦上述T2事务提交,您的下载开始记录即被提交并可供查询
  • 再次回到父级T1开始下载
  • 如果下载成功完成,请使用与T2相同的记录来记录成功。
  • 如果超时,则将永远不会记录以上内容,并且数据库仍将显示下载已开始,并显示了最大预期完成时间
  • 定义一个定期启动的监视过程,并检查下载状态。如果已超过预期的完成时间,则该监视过程警报或记录故障或触发其他重试或您的业务规则是什么

希望有帮助。抱歉,我没有为示例打码,但我想您将有足够的起点。

欢呼