EJB调度程序服务无状态与单例

时间:2015-12-14 18:56:55

标签: java-ee scheduler ejb-3.1

我的应用程序有一个调度程序,需要每10秒运行一次,从数据库中提取新记录。我已经按照运行正常的this guide实现了ejb调度程序服务。没有客户端来命中()方法,它应该仅作为调度程序运行。

仅限单身人士,

@Singleton
@Startup
public class DataFetcherService {
    @Schedule(second="*/10", minute="*", hour="*", persistent=true)
    public void hit() {
           //do some stuff
           fetchData();
    }
    public void fetchData() {
          //Fetch new records from the database through DAO objects
    }
}

如果我用@stateless替换@singleton会有什么不同吗?请建议

更新:无状态方法,

@Singleton
@Startup
public class DataFetcherService {
    @EJB
    DataFetcherBean dataFetcherBean;
    @Schedule(second="*/10", minute="*", hour="*", persistent=true)
    public void hit() {
           dataFetcherBean.fetchData();
    }  
}
@Stateless
public class DataFetcherBean { 
    public void fetchData() {
          //Fetch new records from the database through DAO objects
    }
}

2 个答案:

答案 0 :(得分:3)

我对你的问题并不完全清楚,但如果我理解你的话,你可以采取这两种方式。如果您愿意,可以在EntityManager中注入@Singleton,然后将您的JPA相关商业逻辑放入@Singleton中可由hit()调用的方法以及任何其他方法这些其他客户会打电话。在这种情况下,客户端访问和调度访问都将以同步方式发生。性能不佳但我猜这是你的架构。

另一个选择是通过将此数据获取业务逻辑放在其自己的@Stateless EJB中并将该EJB注入到您的@Singleton中来更松散地耦合。然后,您的@Singleton可以从hit()和任何其他方法调用此EJB上的方法。因为@Singleton的默认容器管理并发性是@Lock(LockType.WRITE),所以您将有效地序列化注入的EJB的所有访问权限(只要它都通过单例)。这种设计使得事物更松散地耦合,但增加了所涉及的类的数量,并添加了一个无状态的EJB,这将使用更多的资源进行池化。这些是一些权衡。

如果您选择第一个选项并且您需要非同步执行所述biz逻辑,则需要使用@Stateless EJB重构内容。

还有一件事需要考虑。如果你决定采用@Singleton唯一的方法,你必须要小心,如果你需要让它的一个方法调用另一个方法。在这种情况下,您将无法使用CMC(容器管理的并发),而是您将使用ConcurrenyManagementType.Bean并自己处理同步。

根据OP的新评论更新:

@Hello - 如果您将@Singleton替换为@Stateless,您也会将@Startup作为@Singleton唯一可用的@Schedule。这对你来说可能有问题,也可能没有关系,尽管它对fetchData();方法没有任何影响,因为在应用程序部署时会看到并“设置”。

您需要使用bean的代理调用SessionContext,或者从注入的@Singleton资源或通过自注入获取。你现在这样做的方法就是调用容器,包括在调用调度方法时启动容器的TX。有时这个问题有时它不会导致细微的错误,这就是为什么通常最好通过代理访问'本地'方法。

最后,如果对@Lock(LockType.WRITE)使用上述方法,则需要切换到bean托管并发,因为容器不会处理这种类型的方法访问props方法进入时尚并会给你一个错误(至少这是我在Glasfish的JavaEE6中看到的行为)。

答案 1 :(得分:2)

在您的预定服务中使用@Singleton和@Stateless之间存在一些差异:

  • 如果使用@Stateless,那么执行带注释的方法的bean实例将完全自治,并且不能被应用程序的其余部分引用。容器将在部署时创建计时器,并根据计划调用回调。如果您尝试注入此bean的实例,那么您将获得它的另一个副本(没有正在运行的计划)。

  • 如果使用@Singleton bean,则可以注入它并更改其状态,可能会影响计时器回调的行为。