Proper configuration with the JCA connector in WIldfly


Andy
 
Edited

FYI The JCA was written by people who no longer develop DataNucleus, and is dependent on volunteers. Consequently you're pretty much on your own. Clearly JDO is just as usable outside of JCA, creating a PMF and PM's as required.


ebenzacar@...
 

I'm trying to integrate my instance of JBoss/Wildfly 10 with the Datanucleus JCA-JDO connector.  I saw an original post for JBoss AS7 (https://developer.jboss.org/docs/DOC-17094) as linked from the DataNucleus docs, but I find it somewhat incomplete.  I've been struggling with improving the configuration and will try to post a complete howto/installation once done. 

At the moment, I am having trouble understanding how to define my JNDI datasource in my persistence unit.   I have my DataSource properly defined in my Wildfly standalone.xml configuration:

<subsystem xmlns="urn:jboss:domain:datasources:4.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/POC_DN" pool-name="POC_DN" enabled="true">
<connection-url>jdbc:sqlserver://127.0.0.1:1433;databaseName=POC_DATANUCLEUS</connection-url>
<driver>sqlserver</driver>
<pool>
<min-pool-size>5</min-pool-size>
<max-pool-size>2000</max-pool-size>
</pool>
<security>
<user-name>datanucleus</user-name>
<password>datanucleus</password>
</security>
<validation>
<check-valid-connection-sql>select getdate()</check-valid-connection-sql>
</validation>
</datasource>

I have the following configured in my persistence unit:
    <persistence-unit name="pu">
<jta-data-source>java:jboss/datasources/POC_DN</jta-data-source>
<properties>
<property name="datanucleus.connection.resourceType" value="JTA"/>
<property name="datanucleus.storeManagerType" value="rdbms"/>
<property name="datanucleus.schema.autoCreateAll" value="false"/>
<property name="datanucleus.connectionPoolingType" value="dbcp2-builtin"/>
<property name="datanucleus.jtaLocator" value="jboss"/>
</properties>
</persistence-unit>

Finally, I have my rar configured as:
<resource-adapter id="datanucleus-jca-jdo">
<archive>
datanucleus-jdo-jca-5.2.7.rar
</archive>
<connection-definitions>
<connection-definition class-name="org.datanucleus.jdo.connector.ManagedConnectionFactoryImpl" jndi-name="java:/adap_1" enabled="true" connectable="true" use-java-context="false" pool-name="adap_1" use-ccm="true" sharable="true" enlistment="true">
<config-property name="PersistenceUnitName">pu<config-property>
<config-property name="PersistenceXmlFilename">file:///dev/Projects/poc/datanucleus/etc/configuration/persistence.xml</config-property>
<pool>
<prefill>false</prefill>
<use-strict-min>false</use-strict-min>
<flush-strategy>FailingConnectionOnly</flush-strategy>
</pool>
<security>
<application/>
</security>
<validation>
<use-fast-fail>false</use-fast-fail>
<validate-on-match>false</validate-on-match>
</validation>
</connection-definition>
</connection-definitions>
</resource-adapter>

Now, in my Spring Java code, I am trying to retrieve the PMF via JNDI and retrieve a PersistenceManager in the following method:
@Bean
@RequestScope
PersistenceManager getPersistenceManager( PersistenceManagerFactory pmf){
return pmf.getPersistenceManager();
}

@Bean
public JndiObjectFactoryBean datanucleusPersistenceManagerFactory(){
JndiObjectFactoryBean jndiObjectFactoryBean =new JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("java:/adap_1");
jndiObjectFactoryBean.setResourceRef(true);
jndiObjectFactoryBean.setProxyInterface(PersistenceManagerFactory.class);
return jndiObjectFactoryBean;
}

All these pieces work; I get a PM injected into my controller class:
@RestController
@RequestMapping(value ="/orgs")
public class OrgController {

@Autowired
PersistenceManager pm;

@GetMapping("/{id}")
public Organization get(@PathVariable Long id) {
Organization o = null;
o = (Organization)pm.getObjectById(Organization.class, id);
return o;
}

However, when it actually tries to execute the `getObjectById()` call, I get an exception thrown:
Caused by: org.datanucleus.exceptions.NucleusUserException: Unable to create transactional datasource for connections due to invalid/insufficient input. Consult the log for details and/or review the settings of "datastore.connectionXXX" properties
at org.datanucleus.store.rdbms.ConnectionFactoryImpl.initialiseDataSource(ConnectionFactoryImpl.java:129)
at org.datanucleus.store.rdbms.ConnectionFactoryImpl.<init>(ConnectionFactoryImpl.java:91)
... 125 more


Drilling more into things, I see that the PM is trying to initialize a Connection via the `org.datanucleus.store.rdbms.ConnectionFactoryImp.initialiseDataSource()` method, which delegates to the `generateDataSource` method.  However the JNDI connection string here should come from the datanucleus.ConnectionFactoryName and not the `jta-data-source`.  Am I missing a configuration somewhere?

If I override the value explicitly in my PU, and set my DS JNDI to the `datanucleus.ConnectionFactoryName`, it seems to work as expected.  I see that the the `JDOPersistenceManagerFactory` automatically copies the the jta-data-source to the DN property, but the `org.datanucleus.jdo.connector.PersistenceManagerFactoryImpl` does not seem to do this.  

Is this a configuration problem on my behalf, working as expected, or a bug/missing feature of the JCA adaptor? 

Finally, is there a  "correct" configuration of the RAR adaptor to retrieve the Persistence-Unit definition(s) from my webapp's Classpath instead of the RAR's classpath?  Right now, I can either put the persistence.xml in the RAR itself, or point to a fixed path.  But theoretically, I would want to include it within my application.  But the rar gets deployed before my application(s) and consequently attempts to load the persistence.xml prior to the application loading.  How do I configure this to delegate loading/initializing only once my app is deployed?

Thanks,

Eric