Jpa 使用EAR级别定义的数据源作为共享JAR的persistence.xml中的JTA数据源

Jpa 使用EAR级别定义的数据源作为共享JAR的persistence.xml中的JTA数据源,jpa,jakarta-ee,wildfly,ear,payara,Jpa,Jakarta Ee,Wildfly,Ear,Payara,在雅加达EE 8环境中:是否可以在application.xml中定义EAR级别[]的(“portable JNDI”)数据源,并将该数据源用作库/JAR模块中persistence.xml中的JTA数据源 目的:创建一个通用JAR模块,该模块定义JPA实体以及相应的“存储库”,以便多个WAR模块(例如RESTful API和UI模块)可以使用该JAR模块,并将该模块打包为可部署到多个应用服务器的EAR 通过以下尝试/方法(对于一个完整的示例,我创建了一个简单的git repo[]),这样一个E

在雅加达EE 8环境中:是否可以在
application.xml
中定义EAR级别[]的(“portable JNDI”)数据源,并将该数据源用作库/JAR模块中
persistence.xml
中的JTA数据源

目的:创建一个通用JAR模块,该模块定义JPA实体以及相应的“存储库”,以便多个WAR模块(例如RESTful API和UI模块)可以使用该JAR模块,并将该模块打包为可部署到多个应用服务器的EAR

通过以下尝试/方法(对于一个完整的示例,我创建了一个简单的git repo[]),这样一个EAR的部署失败了(至少对于Payara和WildFly是如此)


尝试/方法

假设有一个由两个WAR模块组成的应用程序,两个WAR模块都使用一个共享JAR模块,因此有一个类似以下内容的应用程序结构:

ear/
├── shared-lib-jar
|   ├── ...
|   └── META-INF
|       ├── ...
|       └── persistence.xml
├── api-war/
|   └── ...
├── ui-war/
|   └── ...
├── application.xml
├── ...
<application>
  <!-- ... -->
  <data-source>
    <name>java:app/appDS</name>
    <!-- ... -->
  </data-source>
</application>
ear/
├── shared-lib-jar
|   ├── ...
|   └── META-INF
|       ├── ...
|       └── persistence.xml
├── api-war/
|   └── ...
├── ui-war/
|   └── ...
├── META-INF/
|   ├── ...
|   └──application.xml
├── ...
在EAR的
application.xml
中,数据源的定义如下:

ear/
├── shared-lib-jar
|   ├── ...
|   └── META-INF
|       ├── ...
|       └── persistence.xml
├── api-war/
|   └── ...
├── ui-war/
|   └── ...
├── application.xml
├── ...
<application>
  <!-- ... -->
  <data-source>
    <name>java:app/appDS</name>
    <!-- ... -->
  </data-source>
</application>
ear/
├── shared-lib-jar
|   ├── ...
|   └── META-INF
|       ├── ...
|       └── persistence.xml
├── api-war/
|   └── ...
├── ui-war/
|   └── ...
├── META-INF/
|   ├── ...
|   └──application.xml
├── ...

不同(2)个应用服务器的意外/错误行为/情况

设置:
org.h2.jdbcx.JdbcDataSource
作为
类名和“基于文件”的数据库

Payara(5.2020.2)

不会创建数据库文件,服务器日志显示:

[2020-07-07T22:56:32.731+0200] [Payara 5.2020] [SEVERE] [AS-DEPLOYMENT-00026] [javax.enterprise.system.tools.deployment.dol] [tid: _ThreadID=168 _ThreadName=admin-thread-pool::admin-listener(11)] [timeMillis: 1594155392731] [levelValue: 1000] [[
  JNDI lookup failed for the resource: Name: foo-core, Lookup: java:app/appDS, Type: javax.sql.DataSource.]]

[2020-07-07T22:56:32.731+0200] [Payara 5.2020] [SEVERE] [] [javax.enterprise.system.core] [tid: _ThreadID=168 _ThreadName=admin-thread-pool::admin-listener(11)] [timeMillis: 1594155392731] [levelValue: 1000] [[
  JNDI lookup failed for the resource: Name: [foo-core], Lookup: [java:app/appDS], Type: [javax.sql.DataSource]]]
{"WFLYCTL0062: Composite operation failed and was rolled back. Steps that failed:" => {"Operation step-2" => {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"foo-ear-0.0.1-SNAPSHOT.ear\".WeldStartService" => "Failed to start service
    Caused by: java.lang.IllegalArgumentException: WFLYWELD0037: Error injecting persistence unit into CDI managed bean. Can't find a persistence unit named 'foo-core' in deployment foo-ear-0.0.1-SNAPSHOT.ear for injection point protected javax.persistence.EntityManager com.acme.BookRepository.entityManager"}}}}
WildFly(1.4.11.决赛)

数据库文件已创建,但服务器日志显示:

[2020-07-07T22:56:32.731+0200] [Payara 5.2020] [SEVERE] [AS-DEPLOYMENT-00026] [javax.enterprise.system.tools.deployment.dol] [tid: _ThreadID=168 _ThreadName=admin-thread-pool::admin-listener(11)] [timeMillis: 1594155392731] [levelValue: 1000] [[
  JNDI lookup failed for the resource: Name: foo-core, Lookup: java:app/appDS, Type: javax.sql.DataSource.]]

[2020-07-07T22:56:32.731+0200] [Payara 5.2020] [SEVERE] [] [javax.enterprise.system.core] [tid: _ThreadID=168 _ThreadName=admin-thread-pool::admin-listener(11)] [timeMillis: 1594155392731] [levelValue: 1000] [[
  JNDI lookup failed for the resource: Name: [foo-core], Lookup: [java:app/appDS], Type: [javax.sql.DataSource]]]
{"WFLYCTL0062: Composite operation failed and was rolled back. Steps that failed:" => {"Operation step-2" => {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"foo-ear-0.0.1-SNAPSHOT.ear\".WeldStartService" => "Failed to start service
    Caused by: java.lang.IllegalArgumentException: WFLYWELD0037: Error injecting persistence unit into CDI managed bean. Can't find a persistence unit named 'foo-core' in deployment foo-ear-0.0.1-SNAPSHOT.ear for injection point protected javax.persistence.EntityManager com.acme.BookRepository.entityManager"}}}}

1:


2:

是的,你差不多完成了,至少在帕亚拉或格拉希什的情况下是这样。您不需要在application.xml中公开数据源

首先在persistence.xml声明您的数据源,就像您所做的那样:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="my.PU" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    **<jta-data-source>jdbc/mydatasource</jta-data-source>**
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="eclipselink.logging.level" value="INFO"/>
      <property name="eclipselink.logging.parameters" value="true"/>
      <property name="eclipselink.persistence-context.flush-mode" value="COMMIT"/>
    </properties>
  </persistence-unit>
</persistence>

终于发现了错误:我把
application.xml
放错了文件夹。与其将
application.xml
放在根文件夹中,不如将其放在
META-INF
文件夹的更深一层,以便项目结构如下所示:

ear/
├── shared-lib-jar
|   ├── ...
|   └── META-INF
|       ├── ...
|       └── persistence.xml
├── api-war/
|   └── ...
├── ui-war/
|   └── ...
├── application.xml
├── ...
<application>
  <!-- ... -->
  <data-source>
    <name>java:app/appDS</name>
    <!-- ... -->
  </data-source>
</application>
ear/
├── shared-lib-jar
|   ├── ...
|   └── META-INF
|       ├── ...
|       └── persistence.xml
├── api-war/
|   └── ...
├── ui-war/
|   └── ...
├── META-INF/
|   ├── ...
|   └──application.xml
├── ...

为了查看完整示例,我修复了此问题中的错误配置。

感谢@s-kadakov的回答。我知道,使用Payara/Glassfish,我可以通过
Glassfish resources.xml
声明JDBC资源。但正如问题中提到的,我正在寻找一些独立于应用服务器的方法(“可部署到多个应用服务器”)因此,我们希望使用
application.xml
,因为这是定义数据源的标准方法。不要担心使用的应用程序服务器。我想也可以在WildFly server()中声明数据源,因此这纯粹是部署问题。是的,您是对的:也可以在WildFly中声明数据源。但是,如果有一种方法可以以供应商中立的格式声明数据源,并且每个应用服务器(请参阅)环境都必须理解,那么为什么要以几种特定于供应商的方式声明数据源是部署工程师的责任。使用硬编码的数据源,您可以强制客户在每次环境更改(例如,IP更改)时重新打包您的应用程序,而这正是程序员所需要的。另一方面,当您在虚拟环境中部署并可以使用环境变量对其进行调优时,这并不是问题。