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



在Jakarta EE 8环境中:是否可以在application.xml中的EAR级别[1]定义一个("可移植JNDI"(数据源,并在库/JAR模块内的persistence.xml中将该数据源用作JTA数据源?

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

通过以下尝试/方法(对于一个完整的例子,我创建了一个简单的git-reo[2](,这样的EAR的部署失败了(至少对于Payara和WildFly(。


尝试/方法

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

ear/
├── shared-lib-jar
|   ├── ...
|   └── META-INF
|       ├── ...
|       └── persistence.xml
├── api-war/
|   └── ...
├── ui-war/
|   └── ...
├── application.xml
├── ...

在EAR的application.xml中,数据源定义如下:

<application>
<!-- ... -->
<data-source>
<name>java:app/appDS</name>
<!-- ... -->
</data-source>
</application>

persistence.xml中,application.xml中定义的JNDI名称用作JTA数据源:

<persistence>
<persistence-unit name="..." transaction-type="JTA">
<jta-data-source>java:app/appDS</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<!-- ... -->
</persistence-unit>
</persistence>

不同(2(应用程序服务器的意外/故障行为/情况

设置:CCD_ 6作为CCD_;基于文件的";数据库

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]]]

WildFly(1.4.11.最终版(

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

{"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:https://jakarta.ee/specifications/platform/8/platform-spec-8.html#a1688

2:https://gitlab.com/hjoeren/application-level-ds-example

是的,你差不多完成了,至少在Payara或Glasshish的情况下是这样。您不需要在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>

然后,只需使用管理控制台或asadmin命令在Payara(或GF(应用程序服务器上配置适当的连接池和JDBC资源。文件glassfish-resources.xml 示例

$cat glassfish-resources.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">    
<resources>
<jdbc-connection-pool connection-creation-retry-interval-in-seconds="30" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" wrap-jdbc-objects="false" res-type="javax.sql.DataSource" `name="mysql_myrootPool"` is-connection-validation-required="true" connection-creation-retry-attempts="10" validate-atmost-once-period-in-seconds="60">
<property name="User" value="root"/>
<property name="Password" value="secret"/>
<property name="URL" value="jdbc:mysql://localhost:3306/mydb?zeroDateTimeBehavior=convertToNull"/>
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="zeroDateTimeBehavior" value="convertToNull"/>
<property name="characterEncoding" value="utf-8"/>
<property name="useSSL" value="false"/>
</jdbc-connection-pool>
<jdbc-resource enabled="true" `jndi-name="jdbc/mydatasource"` object-type="user" `pool-name="mysql_myrootPool"`/>
</resources>
$asadmin add-resources glassfish-resources.xml

请注意池、持久性单元和资源的正确名称。

现在,您可以在任何允许的地方(EJB、Servlet、Interceptors等(将连接注入EAR中包含的任何EJB或WEB模块中,如

@PersistenceContext(unitName = "my.PU")
private EntityManager em;

终于发现了错误:我把application.xml放错了文件夹。与其将application.xml放在根文件夹中,不如将其放在META-INF文件夹中更深一层,这样项目结构看起来像这样:

ear/
├── shared-lib-jar
|   ├── ...
|   └── META-INF
|       ├── ...
|       └── persistence.xml
├── api-war/
|   └── ...
├── ui-war/
|   └── ...
├── META-INF/
|   ├── ...
|   └──application.xml
├── ...

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

最新更新