【问题标题】:Inject stateless bean into runnable for ScheduledExecutorService将无状态 bean 注入 ScheduledExecutorService 的可运行对象
【发布时间】:2017-02-22 09:53:34
【问题描述】:

我想在部署 Glassfish 之后运行一些进程。进程将每小时运行一次,它包含通过无状态 bean CarService 从 DB 表中获取数据,其中 findAll() 如下:

@PersistenceContext
private EntityManager em;

public List<Cars> findAll() {
    javax.persistence.criteria.CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
    cq.select(cq.from(Cars.class));
    return em.createQuery(cq).getResultList();
}

然后我使用 ScheduledExecutorService 并在部署后启动进程。

@ManagedBean(eager=true)
@ApplicationScoped
public class ApplicationStateChange {

private ScheduledExecutorService scheduler;

@PostConstruct
public void init() {
    System.out.println("ejb init method called");
    scheduler = Executors.newScheduledThreadPool(2);
    scheduler.scheduleAtFixedRate(new ScheduleTask();, 15, 30, TimeUnit.SECONDS);
}

@PreDestroy
    public void destroy() {
        /* Shutdown stuff here */
        System.out.println("ejb destroy method called");
        scheduler.shutdownNow();
    }

上面的 ScheduleTask() 包含包含业务逻辑的流程,例如:

public class ScheduleTask implements Runnable {

    @Inject
    CarService carService;
    private volatile ScheduledExecutorService scheduler = null;

    @Override
    public void run() {
        System.out.println("scheduletask is called");
        List<Car> carList = new ArrayList<>();
               carList = carService.findAll();
        if (carList != null) {
            for (Car car : carList) {
                System.out.println(car);
            }
        }
    }

我无法通过注入上述可运行类来获取 findALL() 方法。调度程序工作正常,但是当它到达 carList = carService.findAll(); 时它失败了,事实上它在 javax.persistence.criteria.CriteriaQuery cq = em.getCriteriaBuilder().createQuery(); 失败了

我怀疑持久性上下文在调用时没有正确加载。

我关注了以下问题Spawning threads in a JSF managed bean for scheduled tasks using a timer

scheduledExecutorService, timerService and Stateless EJB on scheduled jobs

【问题讨论】:

    标签: jsf jakarta-ee ejb executorservice


    【解决方案1】:

    正如您所链接的第一个问题的答案中明确显示的那样,只需将@Schedule 使用到带有@Startup 注释的@Singleton SessionBean 中,以确保它在服务器启动或应用程序部署时运行。

    正如您正确提到的,EntityManager 和 PersistenceContext 不能注入到非容器托管类中(而 Singleton SessionBean 是托管类)。

    链接答案:

    Spawning threads in a JSF managed bean for scheduled tasks using a timer

    【讨论】:

    • 好的,我可以使用容器管理的 '@Schedule' 而不是 ScheduledExecutorService 但现在我必须处理 glassfish 的 Timer 配置,这很痛苦,因为它正在回复 '信息:此服务器不拥有 EJB 计时器 信息: 这就是我尝试使用 ScheduledExecutorService 的原因,该服务将通过获得可运行的实现以固定速率运行进程.有什么方法可以将我的 EntityManager 挂接到 runnable 中吗?
    • 不,您不能将 EntityManager 注入到非容器管理的类中,您应该避免自己管理任务。关于如何在 Glassfish 中配置 Timer,这是一个很好的观点,但这也是一个全新的问题。打开一个新问题。
    • 感谢您的提示。我已经用调度程序测试了我的 entitymanager 并且工作正常。这个调度器和 ScheduledExecutorService 一样??意味着任务将由工作线程异步执行,而不是由将任务交给调度程序的线程执行。否则我必须通过对 EntityManager 中的 ArrayList 的每个元素使用 ScheduledExecutorService 来再次管理所有后续任务
    • 不幸的是,我对 ScheduledExecutorService 并不那么热衷,老实说,从您的评论中我无法理解问题所在。你真的应该在一个新问题中设置一个 mvce
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    • 2017-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多