WildFly部署deneme2-ear.ear时缺失指定JDBC数据源服务排查求助
1. 当前配置
1.1 DataSourceConfig.java
import jakarta.annotation.sql.DataSourceDefinition; import jakarta.ejb.Singleton; @Singleton @DataSourceDefinition( name = "java:global/jdbc/deneme2DS", className = "org.h2.jdbcx.JdbcDataSource", url = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", user = "sa", password = "sa" ) public class DataSourceConfig { // 仅用于定义数据源,类可以为空 // 类加载时自动注册数据源 }
1.2 persistence.xml
<persistence xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" version="3.0"> <!-- 使用可移植的JNDI名称 --> <jta-data-source>java:global/jdbc/deneme2DS</jta-data-source> <properties> <property name="jakarta.persistence.schema-generation.database.action" value="drop-and-create" /> <property name="jakarta.persistence.sql-load-script-source" value="import.sql" /> <!-- Hibernate配置属性 <property name="hibernate.show_sql" value="false" /> --> </properties> </persistence>
2. 部署错误日志
20:26:07,298 ERROR [org.jboss.as.controller.management-operation]
(Controller Boot Thread) WFLYCTL0013: Operation ("deploy") failed -
address: ([("deployment" => "deneme2-ear.ear")]) - failure
description: {
"WFLYCTL0412: Required services that are not installed:" => ["jboss.naming.context.java.global.jdbc.deneme2DS"],
"WFLYCTL0180: Services with missing/unavailable dependencies" => [
"jboss.persistenceunit."deneme2-ear.ear/deneme2-ejb.jar#primary".FIRST_PHASE
is missing [jboss.naming.context.java.global.jdbc.deneme2DS]",
"jboss.persistenceunit."deneme2-ear.ear/deneme2-ejb.jar#primary" is
missing [jboss.naming.context.java.global.jdbc.deneme2DS]"
] }
注:该配置在Payara服务器上可正常运行。
3. 排查思路与解决方案
原因分析
WildFly与Payara对Jakarta EE规范的实现细节存在差异,主要可能涉及以下几点:
@DataSourceDefinition的JNDI命名空间处理逻辑不同- 类加载顺序导致Singleton EJB初始化晚于持久化单元加载
- WildFly默认未包含H2数据库驱动
具体解决方法
方法一:调整JNDI命名空间并触发Singleton初始化
WildFly中java:global命名空间的资源注册需要确保EJB模块被优先加载,可改用应用级命名空间java:app,同时添加初始化方法确保类被加载:
- 修改
DataSourceConfig.java的JNDI名称:
@DataSourceDefinition( name = "java:app/jdbc/deneme2DS", // 替换为java:app命名空间 className = "org.h2.jdbcx.JdbcDataSource", url = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", user = "sa", password = "sa" )
- 在
DataSourceConfig类中添加@PostConstruct方法触发初始化:
@PostConstruct public void init() { // 空方法,确保类被容器加载 }
- 同步修改
persistence.xml中的数据源引用:
<jta-data-source>java:app/jdbc/deneme2DS</jta-data-source>
方法二:添加H2驱动依赖
WildFly默认不包含H2驱动,需手动添加:
- 方式1:通过Maven依赖
在EJB模块的pom.xml中添加依赖:
<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.2.224</version> <!-- 使用对应版本 --> <scope>provided</scope> </dependency>
- 方式2:部署为WildFly模块
- 创建模块目录:
$WILDFLY_HOME/modules/com/h2database/h2/main - 放入H2驱动jar包,同时创建
module.xml:
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.5" name="com.h2database.h2"> <resources> <resource-root path="h2-2.2.224.jar"/> <!-- 对应jar包名称 --> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> </dependencies> </module>
- 在
standalone.xml中注册驱动:
<subsystem xmlns="urn:jboss:domain:datasources:7.0"> <drivers> <driver name="h2" module="com.h2database.h2"> <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class> </driver> </drivers> </subsystem>
方法三:改用WildFly原生数据源配置
直接在WildFly配置文件中定义数据源,避免代码层面的类加载问题:
在standalone.xml的datasources子系统中添加:
<datasource jndi-name="java:global/jdbc/deneme2DS" pool-name="deneme2DS" enabled="true" use-java-context="true"> <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url> <driver>h2</driver> <security> <user-name>sa</user-name> <password>sa</password> </security> </datasource>
部署时移除代码中的@DataSourceDefinition配置,确保persistence.xml引用正确的JNDI名称。
内容的提问来源于stack exchange,提问作者Ebuzer Taha KANAT

