I'm attempting to setup a JCA resource adapter for Gemfire 9.8 on IBM WebSphere Liberty base by following the link https://gemfire.docs.pivotal.io/98/geode/reference/archive_transactions/JTA_transactions.html#concept_cp1_zx1_wk
Here is my ra.xml:
<connector xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd"
version="1.5">
<display-name>GFE JCA Adaptor</display-name>
<vendor-name></vendor-name>
<spec-version>1.5</spec-version>
<eis-type>GFE JCA</eis-type>
<version>1.5</version>
<resourceadapter>
<config-property>
<config-property-name>ProductName</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>GemFire</config-property-value>
</config-property>
<config-property>
<config-property-name>UserName</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value/>
</config-property>
<config-property>
<config-property-name>Version</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>8.0</config-property-value>
</config-property>
<outbound-resourceadapter>
<connection-definition>
<managedconnectionfactory-class>org.apache.geode.internal.ra.spi.JCAManagedConnectionFactory</managedconnectionfactory-class>
<connectionfactory-interface>org.apache.geode.ra.GFConnectionFactory</connectionfactory-interface>
<connectionfactory-impl-class>org.apache.geode.internal.ra.GFConnectionFactoryImpl</connectionfactory-impl-class>
<connection-interface>org.apache.geode.ra.GFConnection</connection-interface>
<connection-impl-class>org.apache.geode.internal.ra.GFConnectionImpl</connection-impl-class>
<transaction-support>LocalTransaction</transaction-support>
<reauthentication-support>false</reauthentication-support>
</connection-definition>
</outbound-resourceadapter>
</resourceadapter>
And here is my resource adapter setting:
<library id="gemfireRaLib" apiTypeVisibility="spec, ibm-api, stable, third-party, api">
<fileset dir="path/to/geode-lib" includes="geode-dependencies.jar"/>
</library>
<resourceAdapter id="gemfireJCA" location="/path/to/geode-lib/geode-jca-9.8.3.rar">
<classloader apiTypeVisibility="spec, ibm-api, stable, third-party, api" commonLibraryRef="gemfireRaLib" delegation="parentFirst"/>
</resourceAdapter>
When I start my liberty server, spring boot initialization fails saying ClassNotFoundException org.apache.geode.ra.GFConnectionFactory is not found.
Then I put all geode dependencies as a shared library:
<library id="gemfireRaLib" apiTypeVisibility="spec, ibm-api, stable, third-party, api">
<fileset dir="/path/to/geode-lib" includes="geode-dependencies.jar"/>
<fileset dir="/path/to/geode-lib" includes="*.jar"/>
</library>
<resourceAdapter id="gemfireJCA" location="/path/to/geode-jca-9.8.3.rar">
<classloader apiTypeVisibility="spec, ibm-api, stable, third-party, api" commonLibraryRef="gemfireRaLib" delegation="parentFirst"/>
</resourceAdapter>
and
<webApplication contextRoot="apprRoot13" location="/path/to/mylocation.war" name="App13" id="App13">
<classloader apiTypeVisibility="spec, ibm-api, stable, third-party, api" commonProviderRef="gemfireRaLib" delegation="parentFirst" />
</webApplication>
Error:
spring-data-gemfire initialization fails:
AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [applicationContext-gemfire.xml]; nested exception is java.lang.NoClassDefFoundError: org.apache.geode.cache.PartitionResolver
In all above scenario I get gemfireJCA adapter installed successfully.
/path/to/shared/geode-lib/ contains the following jars:
geode-common-9.8.3.jar
geode-cq-9.8.3.jar
geode-jca-9.8.3.rar
geode-management-9.8.3.jar
geode-core-9.8.3.jar
geode-dependencies.jar
geode-lucene-9.8.3.jar
geode-wan-9.8.3.jar
When I pack them inside WAR the application bootsup but fails at
lookup = (GFConnectionFactory) template.lookup("gfe/jca");
saying:
java.lang.ClassCastException: org.apache.geode.internal.ra.GFConnectionFactoryImpl incompatible with org.apache.geode.ra.GFConnectionFactory
I get java.lang.ClassCastException: org.apache.geode.internal.ra.GFConnectionFactoryImpl incompatible with org.apache.geode.ra.GFConnectionFactory because GFConnectionFactoryImpl and GFConnectionFactory are loaded by different classloaders. Thats why I created a geode-lib shared library. Sharing it between JCA resource adapter and web application
Thanks a lot for your response. Here is the root cause of the issue.
To solve this I can follow any of the below solutions:
Deploy GemfireJCA and WAR in a Single EAR. Pack geode-jca.rar along with geode-*.jar and geode-dependencies.jar as a common library and WAR.
Please note: These geode-*.jar should not be in WEB-INF/lib of WAR.
Here is the EAR tree:
App13.ear:
|
|--gemfire-jca-9.8.3.rar
|--WebApp13.war(Without geode-*.jar)
|--lib
| |--geode-common-9.8.3.jar
| |--geode-cq-9.8.3.jar
| |--geode-management-9.8.3.jar
| |--geode-core-9.8.3.jar
| |--geode-dependencies.jar
| |--geode-lucene-9.8.3.jar
| |--geode-wan-9.8.3.jar
|--META-INF
| |--application.xml (with module connector for gemfireJCA using gemfire-jca-9.8.3.rar)
Handle connection via source code:
@Bean
public JCAManagedConnectionFactory jcaManagedConnectionFactory() {
JCAManagedConnectionFactory jcaManagedConnectionFactory =
new JCAManagedConnectionFactory();
jcaManagedConnectionFactory.setProductName("GemFire");
jcaManagedConnectionFactory.setUserName(""); // DO NOT SET ANY USERNAME
jcaManagedConnectionFactory.setVersion("8.0");
return jcaManagedConnectionFactory;
}
@Bean
public JCAManagedConnection jcaManagedConnection(JCAManagedConnectionFactory jcaManagedConnectionFactory)
throws ResourceException {
return (JCAManagedConnection) jcaManagedConnectionFactory
.createManagedConnection(null, null);
}
@Bean
public GFConnectionFactory getGFConnectionFactory(JCAManagedConnectionFactory jcaManagedConnectionFactory,
JCAManagedConnection jcaManagedConnection)
throws ResourceException {
GFConnectionFactory lookup =
(GFConnectionFactory) jcaManagedConnectionFactory
.createConnectionFactory(new ConnectionManager() {
private static final long serialVersionUID =
1L;
@Override
public Object allocateConnection(ManagedConnectionFactory mcf,
ConnectionRequestInfo cxRequestInfo)
throws ResourceException {
return jcaManagedConnection.getConnection(null,
cxRequestInfo);
}
});
return lookup;
}
Clean up connection during shutdown:
@Override
public void onApplicationEvent(ContextClosedEvent event) {
if (null != jcaManagedConnection) {
try {
jcaManagedConnection.cleanup();
} catch (ResourceException e) {
LOGGER.error("Error while shuttingdown the container {}",
e.getMessage());
LOGGER.error(e.getMessage(), e);
}
}
}