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