Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jpa 添加实体和持久化单元后,EJB计时器服务不再可用_Jpa_Jakarta Ee_Timer_Payara - Fatal编程技术网

Jpa 添加实体和持久化单元后,EJB计时器服务不再可用

Jpa 添加实体和持久化单元后,EJB计时器服务不再可用,jpa,jakarta-ee,timer,payara,Jpa,Jakarta Ee,Timer,Payara,我正在玩弄EJB计时器,但在同一个项目中尝试同时运行计时器和持久性实体时遇到了麻烦。在我的初始设置中,我只有计时器,这些计时器按预期启动: @Stateless public class TimerHandler { @Resource protected TimerService mTimerService; @PostConstruct public void init() { // could do cool stuff but choo

我正在玩弄EJB计时器,但在同一个项目中尝试同时运行计时器和持久性实体时遇到了麻烦。在我的初始设置中,我只有计时器,这些计时器按预期启动:

@Stateless
public class TimerHandler {

    @Resource
    protected TimerService mTimerService;

    @PostConstruct
    public void init() {
        // could do cool stuff but choose not to
    }

    public Timer start(long aDuration) {
        TimerConfig conf = new TimerConfig();
        conf.setPersistent(false); // don't want the timer to be saved
        return mTimerService.createSingleActionTimer(aDuration, conf);
    }

    @Timeout
    public void timeOutAction(Timer aTimer) {
        // does fancy stuff
        System.out.println("So fancy :)");
    }

}
我在让计时器运行时遇到了一些麻烦,但我采取了粗暴的方式重新安装了Payara(Glassfish)。在这之后,使用计时器就可以了。我可以启动并取消它,如下所示:

@Stateful
public class MyClass {

    @EJB
    private TimerHandler mTimerHandler;

    private Timer mTimer;

    public void startTimer(int aDuration) {
        mTimer = mTimerHandler.start(aDuration);
    }

    public void stopTimer() {
        try {
            mTimer.cancel();
        } catch (NoSuchObjectLocalException | NullPointerException ex) {
            System.out.println("There is no timer running.");
        }
    }
}
然而,在我尝试将实体添加到项目中之后,问题出现了。我的实体如下所示:

@Entity
public class TestEntity implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String testValue;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTestValue() {
        return testValue;
    }

    public void setTestValue(String value) {
        testValue = value;
    }

    // removed standard code for @Override of equals(), 
    // hashCode() & toString()
}
我通过我的控制器bean操纵它:

@Stateless
public class TestDBController {
    @PersistenceContext(unitName = "TimerTestWithDBPU")
    private EntityManager em;

    public long saveValue(String value) {
        TestEntity entity = new TestEntity();
        entity.setTestValue(value);
        em.persist(entity);
        em.flush();
        return entity.getId();
    }

    public String getValue(long aId) {
        TestEntity entity = em.find(TestEntity.class, aId);
        return entity.getTestValue();
    }
}
我的持久性单元(Persistence.xml)的设置方式如下:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence 
            http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="TimerTestWithDBPU" transaction-type="JTA">
    <jta-data-source>jdbc/timer_test_pool</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="javax.persistence.schema-generation.database.action" 
                  value="create"/>
    </properties>
  </persistence-unit>
</persistence>

为什么会这样?您不能同时使用ejb计时器和持久实体运行应用程序吗?

事实证明,您可以!谁会想到

这句来自《圣经》的话为我指明了正确的方向

使用EJB计时器服务相当于与单个JDBC资源管理器交互。如果EJB组件或应用程序直接通过JDBC或间接(例如,通过实体bean的持久化机制)访问数据库,并且还与EJB计时器服务交互,则其数据源必须配置XA JDBC驱动程序

我将尝试描述我所做的工作(我是JavaEE领域的新手,因此一些概念和特性名称可能不正确)

在我的例子中,您需要在应用程序服务器(Payara)中配置一个资源,以便它使用XA JDBC驱动程序而不是普通的JDBC驱动程序。(我不完全理解为什么会这样,如果有人愿意详细说明,我很乐意听到)

为此:

  • 创建一个数据库,给它一个名称,并指定用户名密码
  • 进入Payaras管理页面->资源->JDBC->JDBC连接池->新建
  • 具体说明:
    • 一个名字,在我的例子中是“TestPool”
    • 选择资源类型为:“javax.sql.XADataSource”
    • 选择您的供应商:我使用JavaDB
  • 单击next并将Datasource Classname设为默认值
  • 至少指定(我相信)以下属性:
    • 服务器名(如localhost)
    • 端口号(如1527)
    • 密码(如测试)
    • 用户(如测试)
    • URL(例如jdbc:derby://localhost:1527/Test)
    • 数据库名称(如测试)
  • 单击“完成”
  • ConnectionPool需要连接到JDBC资源,并获取服务器能够使用的JNDI名称。在Payara的管理页面中:

  • 转到->资源->JDBC->JDBC资源-新建
  • 给它一个名称(例如jdbc/TestPool)并选择您先前创建的池
  • 如果愿意,请添加说明(说明很酷)
  • 点击ok 现在在持久化单元(Persistence.xml)中添加新的连接池作为项目的数据源

    最后,我删除了ejb驱动程序(_TimerPool)的默认连接池,并创建了一个新的连接池,使用与上面相同的过程(1-10),但名称类似于“TimerEJB”。要使其正常工作,您需要“安装”数据库,这意味着创建适合应用服务器的标准数据库。Payara和Glassfish为此提供了SQL:

    %install-path-of-payara%\glassfish\lib\install\databases\
    
    选择文件ejbtimer\u[VENDOR\u NAME].sql,并在您创建的数据库上运行该文件。在此之后,您应该将其作为ejb计时器的默认连接工具。在Payaras管理页面:

  • 转到->配置->服务器配置->EJB容器->EJB计时器服务
  • 输入为TimerEJB连接池(步骤8.)创建的JNDI名称(资源名称)作为“计时器数据源”
  • 拯救
  • 现在重新启动一切,或者至少重新启动Payara和数据库服务器,您应该可以开始了

    最后一部分是受一个相关问题的启发


    希望这对某人有所帮助:)

    由于您使用的是非持久计时器,这可能是Payara/Glassfish中的一个bug。非持久化计时器不应该需要数据源。如果可以的话,尝试使用fresh Payara Web Profile分发版,看看计时器是否可以开箱即用(Web Profile根本不支持持久计时器,因此不需要计时器的数据源)。
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.1" xmlns="htt...>
      <persistence-unit name="TimerTestPU" transaction-type="JTA">
        <jta-data-source>jdbc/TestPool</jta-data-source> <!-- Magic Line -->
        .
        .
        .
      </persistence-unit>
    </persistence>
    
    java.lang.NoClassDefFoundError: Could not initialize class
            org.apache.derby.jdbc.EmbeddedDriver Could not initialize class 
            org.apache.derby.jdbc.EmbeddedDriver
    
    %install-path-of-payara%\glassfish\lib\install\databases\