在Runnable中访问注册的EntityManager

时间:2016-08-19 09:41:02

标签: java jpa servlets servletcontextlistener

我有一个使用JPA的JSF应用程序。 JTA-DataSource是野生蝇管理的。

现在我必须定期运行一些数据库操作。正如这里提到的(SO: How to run a background task in a servlet based web application?)我创建了两个类:

@WebListener
public class Scheduler implements ServletContextListener {

    private ScheduledExecutorService scheduler;

    @SuppressWarnings("deprecation")
    @Override
    public void contextInitialized(ServletContextEvent event) {
        Calendar c = new GregorianCalendar();
        Date d = c.getTime();
        int stm = 60 - d.getSeconds();
        int mth = 60 - d.getMinutes();

        scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleAtFixedRate(new TestRunner(), stm, 60, TimeUnit.SECONDS);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        scheduler.shutdownNow();
    }
}

public class TestRunner implements Runnable {
    private EntityManager em;

    public TestRunner() {
    }

    @Override
    public void run() {
        this.Test();
    }

    public void Test() {
        System.out.println("Test executed...");
        if (this.em != null) {
            System.out.println(em.find(Ship.class, 2).getName());
            System.out.println(em.find(Commodity.class, 1).getName());
        } else {
            System.out.println("EntityManager is null");
        }
    }
}

访问注册的持久性单元最好。 我试图通过@PersistenceContext(unitName = "PU")获取EM,尝试在web.xml中注册Persistence以通过JNDI获取它,但没有运气。

我的错误在哪里?

1 个答案:

答案 0 :(得分:0)

为我找到了一个解决方案:定义第二个持久性内容。

首先,我的持久性单位:

@PersistenceContext(unitName = "PU", type = PersistenceContextType.EXTENDED)
private EntityManager em;

在JSF中,我通过

使用CDI-Beans中的EntityManager
public TestRunner() {
    this.em = Persistence.createEntityManagerFactory("RLPU").createEntityManager();
}

在CronJob / Scheduler / Runnable中,我通过

创建EntityManager
random.jumpahead(n)

所以我可以在容器托管类和非托管类中使用持久化上下文。