在 WebSphere Liberty 中注入 JPA 实体管理器时出错
Error Injecting the JPA Entity Manager in WebSphere Liberty
我继承了一个遗留应用程序,该应用程序最初是使用 WebSphere 6.1 构建的,然后顺利迁移到 WebSphere 8.0 运行 JPA 2.0 和 openJPA。出于战略原因,我们正在迁移到 WebSphere Liberty。我们首先在 WebSphere Classic 8.5.5.8 和 JPA 上进行了测试,实体管理器没有任何问题。但是,在 Liberty 8.5.5.8 上,出现以下异常:
javax.ejb.EJBException: The java:comp/env/com.xxx.xxxx.service.CHServiceBean/em reference of type javax.persistence.EntityManager for the CHServiceBean component in the CHServiceEJB.jar module of the CHServiceEAR application cannot be resolved.
at com.ibm.wsspi.injectionengine.InjectionBinding.getInjectionObject(InjectionBinding.java:1493)
.....
[err] Caused by:
[err] javax.ejb.EJBException: The java:comp/env/com.xxxx.xxxx.service.CHServiceBean/em reference of type javax.persistence.EntityManager for the CHServiceBean component in the CHServiceEJB.jar module of the CHServiceEAR application cannot be resolved.
[err] at com.ibm.wsspi.injectionengine.InjectionBinding.getInjectionObject(InjectionBinding.java:1493)
[err] at [internal classes]
我有另一个 EJB 注入问题,该问题已通过配置绑定文件得到解决,但我无法解决此问题。我有两个应用程序,每个应用程序都有自己的 EAR 文件,但都 运行 在同一个 Liberty JVM 中。应用程序 A 运行 是前端 end/UI 逻辑,而应用程序 B 是后端 EJB/JPA 接口。在项目方面,JPA 应用程序设置为 2.0(我想要 2.1,但基于另一个线程,JPA 2.0 和 EJB 3.1 目前已达到我所能达到的最高水平...请在此处查看我的其他线程主题 -->).
这是我的 server.xml 文件:
<server description="new server">
<!-- Enable features -->
<featureManager>
<feature>javaee-7.0</feature>
<feature>localConnector-1.0</feature>
<feature>distributedMap-1.0</feature>
<feature>adminCenter-1.0</feature>
<feature>ssl-1.0</feature>
<feature>usr:webCacheMonitor-1.0</feature>
<feature>webCache-1.0</feature>
<feature>ldapRegistry-3.0</feature>
</featureManager>
<!-- Admin Center Config Start -->
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
<httpEndpoint host="*" httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>
<keyStore id="defaultKeyStore" password="xxxxxx"/>
<basicRegistry id="basic">
<user name="admin" password="xxxxx"/>
<user name="nonadmin" password="xxxxxx"/>
</basicRegistry>
<administrator-role>
<user>admin</user>
</administrator-role>
<remoteFileAccess>
<writeDir>${server.config.dir}</writeDir>
</remoteFileAccess>
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true"/>
<applicationMonitor updateTrigger="mbean"/>
<enterpriseApplication id="CHNewCHRDMEAR" location="CHNewCHRDMEAR.ear" name="CHNewCHRDMEAR">
<application-bnd>
<security-role name="AllAuthenticated">
<special-subject type="ALL_AUTHENTICATED_USERS"/>
</security-role>
</application-bnd>
</enterpriseApplication>
<enterpriseApplication id="CHServiceEAR" location="CHServiceEAR.ear" name="CHServiceEAR"/>
<!-- JAAS Authentication Alias (Global) Config -->
<authData id="dbUser" password="{xor}MzhmJT06ajI=" user="dbUser"/>
<!-- JDBC Driver and Datasource Config -->
<library id="DB2JCC4Lib">
<fileset dir="C:\DB2\Jars" includes="db2jcc4.jar db2jcc_license_cisuz.jar"/>
</library>
<dataSource containerAuthDataRef="dbUser" id="CHTEST2" jndiName="jdbc/nextgen" type="javax.sql.XADataSource">
<jdbcDriver libraryRef="DB2JCC4Lib"/>
<properties.db2.jcc databaseName="CHTEST2" password="{xor}MzhmJT06ajI=" portNumber="60112" serverName="server.com" sslConnection="false" user="dbUser"/>
<containerAuthData password="{xor}MzhmJT06ajI=" user="dbUser"/>
</dataSource>
<dataSource id="CHTEST2_RO" jndiName="jdbc/nextgen_RO" type="javax.sql.XADataSource">
<jdbcDriver libraryRef="DB2JCC4Lib"/>
<properties.db2.jcc databaseName="CHTEST2" password="{xor}MzhmJT06ajI=" portNumber="60112" serverName="server.com" sslConnection="false" user="dbUser"/>
<containerAuthData password="{xor}MzhmJT06ajI=" user="dbUser"/>
</dataSource>
<!-- More in file, but no included...-->
</server>
这是我的 persistence.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<persistence 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"
version="2.0">
<persistence-unit name="CHService" transaction-type="JTA">
<jta-data-source>jdbc/nextgen</jta-data-source>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="openjpa.jdbc.TransactionIsolation" value="read-uncommitted" /></properties></persistence-unit>
<persistence-unit name="CHServiceRO" transaction-type="JTA">
<jta-data-source>jdbc/nextgen_RO</jta-data-source>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="openjpa.jdbc.TransactionIsolation" value="read-uncommitted" />
</properties>
</persistence-unit>
</persistence>
我*相信我们完全依靠注入来获取 JPA jndi 查找的上下文,但那是因为我在我们的代码中没有看到任何对任何 JPA 特定 JNDI 名称的初始上下文的调用。下面是我来自 EJB 项目的两个带注释的会话 bean:
一个。 CHService Bean:
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
@Local({ CHServiceLocal.class })
@Remote({ CHServiceRemote.class })
@Interceptors({ CHServiceLog.class })
@Resources({
@Resource(name = "jdbc/nextgen", mappedName = "jdbc/nextgen", authenticationType = AuthenticationType.APPLICATION, shareable = true, type = javax.sql.DataSource.class),
@Resource(name = "services/cache/CHBluepages", mappedName = "services/cache/CHBluepages", authenticationType = AuthenticationType.APPLICATION, shareable = true, type = com.ibm.websphere.cache.DistributedMap.class),
@Resource(name = "services/cache/CHGeneric", mappedName = "services/cache/CHGeneric", authenticationType = AuthenticationType.APPLICATION, shareable = true, type = com.ibm.websphere.cache.DistributedMap.class) })
public class CHServiceBean extends AbstractCHServiceImpl implements
CHService {
@PersistenceContext(unitName = "CHService")
private EntityManager em;
b。 CHServiceRO bean:
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
@Local({CHServiceLocalRO.class})
@Remote({CHServiceRemoteRO.class})
@Interceptors({CHServiceROLog.class})
@Resources({
@Resource(name="jdbc/nextgen_RO", mappedName="jdbc/nextgen_RO", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=javax.sql.DataSource.class),
@Resource(name="jdbc/nextgen", mappedName="jdbc/nextgen", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=javax.sql.DataSource.class),
@Resource(name="services/cache/CHBluepages", mappedName="services/cache/CHBluepages", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=com.ibm.websphere.cache.DistributedMap.class),
@Resource(name="services/cache/CHGeneric", mappedName="services/cache/CHGeneric", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=com.ibm.websphere.cache.DistributedMap.class)
})
public class CHServiceBeanRO implements CHServiceRO {
@PersistenceContext (unitName="CHServiceRO") private EntityManager em;
private CHServiceBase ch;
@PostConstruct
private void init() { ch = new CHServiceBase(em); }
这是调用 JPA 应用程序的前端应用程序 Web.xml 的片段:
<resource-ref id="ResourceRef_1436377001246">
<res-ref-name>jdbc/nextgen</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Application</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<resource-ref id="ResourceRef_1436377001247">
<res-ref-name>jdbc/nextgen_RO</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Application</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
基于 Gas 关于此主题的 post:java.lang.ClassCastException,Getting Entitymanager Via JNDI Lookup
我还尝试使用以下条目更新 web.xml:
<persistence-unit-ref>
<persistence-unit-ref-name>chJPA</persistence-unit-ref-name>
<persistence-unit-name>CHService</persistence-unit-name>
</persistence-unit-ref>
<persistence-unit-ref>
<persistence-unit-ref-name>chJPA_RO</persistence-unit-ref-name>
<persistence-unit-name>CHServiceRO</persistence-unit-name>
</persistence-unit-ref>
Bean 代码为:
@PersistenceContext(name = "chJPA", unitName = "CHService")
和
@PersistenceContext (name="chJPA_RO", unitName="CHServiceRO")
得到相同的错误只是使用不同的 jndi 名称,即 java:comp/env/chJPA 类型 javax.persistence.EntityManager 的引用对于 CHServiceBean com.......等等.
最后,根据这个 post:
看来我可能无法拥有完整的 JavaEE 7 功能和 运行 JPA 2.0?请指教!
正如您所指的 post - 您不能将 <feature>javaee-7.0</feature>
与 JPA 2.0 一起使用,因为它启用 2.1,这就是您有冲突的原因。
所以你有两个选择:
- 使用 Java EE7 和 JPA 2.1
- 或者仅启用所需的 Java EE 6 功能,然后使用 JPA 2.0
由于您是从目前不支持 Java EE7 的 WAS 8.0 迁移的,因此更容易的选择可能是使用第二个选项。
因此,请尝试删除 javee-7.0
功能,并添加 ejbLite-3.1
和 jpa-2.0
以及您需要的更多内容。
您说得对,您不能拥有 javaee-7.0 和 JPA 2.0 功能,因为它启用了 JPA 2.1 功能。所以Gas给出的答案是正确的。
我只是想指出,既然您说过您最终确实想转到 JPA 2.1,一旦解决了 eclipse 问题,您应该使用 WebSphere Application Server Migration Toolkit 来确定迁移时所需的应用程序更改从 JPA 2.0 到 JPA 2.1。 Liberty JPA 2.0 实现构建于 OpenJPA 之上,而 JPA 2.1 实现构建于 EclipseLink 之上。迁移工具包可在 wasdev 上免费下载:https://developer.ibm.com/wasdev/downloads/#asset/tools-WebSphere_Application_Server_Migration_Toolkit
我继承了一个遗留应用程序,该应用程序最初是使用 WebSphere 6.1 构建的,然后顺利迁移到 WebSphere 8.0 运行 JPA 2.0 和 openJPA。出于战略原因,我们正在迁移到 WebSphere Liberty。我们首先在 WebSphere Classic 8.5.5.8 和 JPA 上进行了测试,实体管理器没有任何问题。但是,在 Liberty 8.5.5.8 上,出现以下异常:
javax.ejb.EJBException: The java:comp/env/com.xxx.xxxx.service.CHServiceBean/em reference of type javax.persistence.EntityManager for the CHServiceBean component in the CHServiceEJB.jar module of the CHServiceEAR application cannot be resolved. at com.ibm.wsspi.injectionengine.InjectionBinding.getInjectionObject(InjectionBinding.java:1493) ..... [err] Caused by: [err] javax.ejb.EJBException: The java:comp/env/com.xxxx.xxxx.service.CHServiceBean/em reference of type javax.persistence.EntityManager for the CHServiceBean component in the CHServiceEJB.jar module of the CHServiceEAR application cannot be resolved. [err] at com.ibm.wsspi.injectionengine.InjectionBinding.getInjectionObject(InjectionBinding.java:1493) [err] at [internal classes]
我有另一个 EJB 注入问题,该问题已通过配置绑定文件得到解决,但我无法解决此问题。我有两个应用程序,每个应用程序都有自己的 EAR 文件,但都 运行 在同一个 Liberty JVM 中。应用程序 A 运行 是前端 end/UI 逻辑,而应用程序 B 是后端 EJB/JPA 接口。在项目方面,JPA 应用程序设置为 2.0(我想要 2.1,但基于另一个线程,JPA 2.0 和 EJB 3.1 目前已达到我所能达到的最高水平...请在此处查看我的其他线程主题 -->
这是我的 server.xml 文件:
<server description="new server">
<!-- Enable features -->
<featureManager>
<feature>javaee-7.0</feature>
<feature>localConnector-1.0</feature>
<feature>distributedMap-1.0</feature>
<feature>adminCenter-1.0</feature>
<feature>ssl-1.0</feature>
<feature>usr:webCacheMonitor-1.0</feature>
<feature>webCache-1.0</feature>
<feature>ldapRegistry-3.0</feature>
</featureManager>
<!-- Admin Center Config Start -->
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
<httpEndpoint host="*" httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>
<keyStore id="defaultKeyStore" password="xxxxxx"/>
<basicRegistry id="basic">
<user name="admin" password="xxxxx"/>
<user name="nonadmin" password="xxxxxx"/>
</basicRegistry>
<administrator-role>
<user>admin</user>
</administrator-role>
<remoteFileAccess>
<writeDir>${server.config.dir}</writeDir>
</remoteFileAccess>
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true"/>
<applicationMonitor updateTrigger="mbean"/>
<enterpriseApplication id="CHNewCHRDMEAR" location="CHNewCHRDMEAR.ear" name="CHNewCHRDMEAR">
<application-bnd>
<security-role name="AllAuthenticated">
<special-subject type="ALL_AUTHENTICATED_USERS"/>
</security-role>
</application-bnd>
</enterpriseApplication>
<enterpriseApplication id="CHServiceEAR" location="CHServiceEAR.ear" name="CHServiceEAR"/>
<!-- JAAS Authentication Alias (Global) Config -->
<authData id="dbUser" password="{xor}MzhmJT06ajI=" user="dbUser"/>
<!-- JDBC Driver and Datasource Config -->
<library id="DB2JCC4Lib">
<fileset dir="C:\DB2\Jars" includes="db2jcc4.jar db2jcc_license_cisuz.jar"/>
</library>
<dataSource containerAuthDataRef="dbUser" id="CHTEST2" jndiName="jdbc/nextgen" type="javax.sql.XADataSource">
<jdbcDriver libraryRef="DB2JCC4Lib"/>
<properties.db2.jcc databaseName="CHTEST2" password="{xor}MzhmJT06ajI=" portNumber="60112" serverName="server.com" sslConnection="false" user="dbUser"/>
<containerAuthData password="{xor}MzhmJT06ajI=" user="dbUser"/>
</dataSource>
<dataSource id="CHTEST2_RO" jndiName="jdbc/nextgen_RO" type="javax.sql.XADataSource">
<jdbcDriver libraryRef="DB2JCC4Lib"/>
<properties.db2.jcc databaseName="CHTEST2" password="{xor}MzhmJT06ajI=" portNumber="60112" serverName="server.com" sslConnection="false" user="dbUser"/>
<containerAuthData password="{xor}MzhmJT06ajI=" user="dbUser"/>
</dataSource>
<!-- More in file, but no included...-->
</server>
这是我的 persistence.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<persistence 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"
version="2.0">
<persistence-unit name="CHService" transaction-type="JTA">
<jta-data-source>jdbc/nextgen</jta-data-source>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="openjpa.jdbc.TransactionIsolation" value="read-uncommitted" /></properties></persistence-unit>
<persistence-unit name="CHServiceRO" transaction-type="JTA">
<jta-data-source>jdbc/nextgen_RO</jta-data-source>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="openjpa.jdbc.TransactionIsolation" value="read-uncommitted" />
</properties>
</persistence-unit>
</persistence>
我*相信我们完全依靠注入来获取 JPA jndi 查找的上下文,但那是因为我在我们的代码中没有看到任何对任何 JPA 特定 JNDI 名称的初始上下文的调用。下面是我来自 EJB 项目的两个带注释的会话 bean:
一个。 CHService Bean:
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
@Local({ CHServiceLocal.class })
@Remote({ CHServiceRemote.class })
@Interceptors({ CHServiceLog.class })
@Resources({
@Resource(name = "jdbc/nextgen", mappedName = "jdbc/nextgen", authenticationType = AuthenticationType.APPLICATION, shareable = true, type = javax.sql.DataSource.class),
@Resource(name = "services/cache/CHBluepages", mappedName = "services/cache/CHBluepages", authenticationType = AuthenticationType.APPLICATION, shareable = true, type = com.ibm.websphere.cache.DistributedMap.class),
@Resource(name = "services/cache/CHGeneric", mappedName = "services/cache/CHGeneric", authenticationType = AuthenticationType.APPLICATION, shareable = true, type = com.ibm.websphere.cache.DistributedMap.class) })
public class CHServiceBean extends AbstractCHServiceImpl implements
CHService {
@PersistenceContext(unitName = "CHService")
private EntityManager em;
b。 CHServiceRO bean:
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
@Local({CHServiceLocalRO.class})
@Remote({CHServiceRemoteRO.class})
@Interceptors({CHServiceROLog.class})
@Resources({
@Resource(name="jdbc/nextgen_RO", mappedName="jdbc/nextgen_RO", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=javax.sql.DataSource.class),
@Resource(name="jdbc/nextgen", mappedName="jdbc/nextgen", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=javax.sql.DataSource.class),
@Resource(name="services/cache/CHBluepages", mappedName="services/cache/CHBluepages", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=com.ibm.websphere.cache.DistributedMap.class),
@Resource(name="services/cache/CHGeneric", mappedName="services/cache/CHGeneric", authenticationType=AuthenticationType.APPLICATION, shareable=true, type=com.ibm.websphere.cache.DistributedMap.class)
})
public class CHServiceBeanRO implements CHServiceRO {
@PersistenceContext (unitName="CHServiceRO") private EntityManager em;
private CHServiceBase ch;
@PostConstruct
private void init() { ch = new CHServiceBase(em); }
这是调用 JPA 应用程序的前端应用程序 Web.xml 的片段:
<resource-ref id="ResourceRef_1436377001246">
<res-ref-name>jdbc/nextgen</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Application</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<resource-ref id="ResourceRef_1436377001247">
<res-ref-name>jdbc/nextgen_RO</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Application</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
基于 Gas 关于此主题的 post:java.lang.ClassCastException,Getting Entitymanager Via JNDI Lookup
我还尝试使用以下条目更新 web.xml:
<persistence-unit-ref>
<persistence-unit-ref-name>chJPA</persistence-unit-ref-name>
<persistence-unit-name>CHService</persistence-unit-name>
</persistence-unit-ref>
<persistence-unit-ref>
<persistence-unit-ref-name>chJPA_RO</persistence-unit-ref-name>
<persistence-unit-name>CHServiceRO</persistence-unit-name>
</persistence-unit-ref>
Bean 代码为:
@PersistenceContext(name = "chJPA", unitName = "CHService")
和
@PersistenceContext (name="chJPA_RO", unitName="CHServiceRO")
得到相同的错误只是使用不同的 jndi 名称,即 java:comp/env/chJPA 类型 javax.persistence.EntityManager 的引用对于 CHServiceBean com.......等等.
最后,根据这个 post:
正如您所指的 post - 您不能将 <feature>javaee-7.0</feature>
与 JPA 2.0 一起使用,因为它启用 2.1,这就是您有冲突的原因。
所以你有两个选择:
- 使用 Java EE7 和 JPA 2.1
- 或者仅启用所需的 Java EE 6 功能,然后使用 JPA 2.0
由于您是从目前不支持 Java EE7 的 WAS 8.0 迁移的,因此更容易的选择可能是使用第二个选项。
因此,请尝试删除 javee-7.0
功能,并添加 ejbLite-3.1
和 jpa-2.0
以及您需要的更多内容。
您说得对,您不能拥有 javaee-7.0 和 JPA 2.0 功能,因为它启用了 JPA 2.1 功能。所以Gas给出的答案是正确的。
我只是想指出,既然您说过您最终确实想转到 JPA 2.1,一旦解决了 eclipse 问题,您应该使用 WebSphere Application Server Migration Toolkit 来确定迁移时所需的应用程序更改从 JPA 2.0 到 JPA 2.1。 Liberty JPA 2.0 实现构建于 OpenJPA 之上,而 JPA 2.1 实现构建于 EclipseLink 之上。迁移工具包可在 wasdev 上免费下载:https://developer.ibm.com/wasdev/downloads/#asset/tools-WebSphere_Application_Server_Migration_Toolkit