How to use datanucleus.CurrentUserProvider?


1919wang@...
 

According to JDO Mapping Guide, to support auditing @CreateUser, we could define an implementation of the DataNucleus interface CurrentUserProvider, and specify it on PMF creation using the property datanucleus.CurrentUserProvider. 

I have a com.alpha.MyUserProvider implements CurrentUserProvider, and tried to set the property like below:

PersistenceUnitMetaData globalPumd = new PersistenceUnitMetaData(jdoName, transactionType, null);
Map<String, String> jdoProperties =
new HashMap<>();
...
jdoProperties.put("datanucleus.CurrentUserProvider", "com.alpha.MyUserProvider");

for (Map.Entry<String, String> entry: jdoProperties.entrySet()) {
globalPumd.addProperty(entry.getKey()
, entry.getValue()); // Here can only add String property value
}


PersistenceManagerFactory pmf
= new JDOPersistenceManagerFactory(globalPumd, null);
...


The property value can only be set as String; However, in org.datanucleus.PersistenceNucleusContextImpl gets the CurrentUserProvider by calling Configuration.getProperty, which is a String, then got a ClassCastException

(CurrentUserProvider)config.getProperty(PropertyNames.PROPERTY_MAPPING_CURRENT_USER_PROVIDER); 


Seems it requires put an MyUserProvider instance  as property value, but PersistenceUnitMetaData only accept String value.


Andy
 
Edited

You create an INSTANCE of your CurrentUserProvider, and specify that as the value of "datanucleus.CurrentUserProvider" to the persistence properties.
If you insist on creating a PMF in that way you use the second argument to input OVERRIDING PROPERTIES.


1919wang@...
 
Edited

Thanks Andy. 
I have several more questions:
  • The 1st option you mentioned is `JDOPersistenceManagerFactory.setPersistenceProperties()`, right? The underlying logic of those 2 options seems identical - saving the properties via `Configuration.setPersistenceProperties`, please correct me if I misunderstood.
  • One thing confusing is that PersistenceUnitMetaData only support String value properties, while overrideProps supports Object value; And when constructing PMF, those 2 properties are actually merged into one Map. So one question is - Is it better to make PersistenceUnitMetaData support Object value?
    public JDOPersistenceManagerFactory(PersistenceUnitMetaData pumd, Map overrideProps)
    {
    // Build up map of all properties to apply (from persistence-unit + overridden + defaulted)
    Map props = new HashMap();
    if (pumd != null && pumd.getProperties() != null)
    {
    props.putAll(pumd.getProperties());
    }
    if (overrideProps != null)
    {
    props.putAll(overrideProps);
    }


Andy
 

I didnt mention JDOPersistenceManagerFactory.setPersistenceProperties(), no.

PersistenceUnitMetaData is to replicate the file "persistence.xml" content. You cannot specify an Object in a text-based persistence.xml file. Hence PersistenceUnitMetaData doesnt support Object values.


1919wang@...
 

I got your point on PersistenceUnitMetaData.
May I ask what is the "persistence properties" if it doesn't mean JDOPersistenceManagerFactory.setPersistenceProperties()? I am new to datanucleus, your guide would be appreciated~

 

You create an INSTANCE of your CurrentUserProvider, and specify that as the value of "datanucleus.CurrentUserProvider" to the persistence properties.


Andy
 

The "persistence properties" are amply defined in the docs. "datanucleus.CurrentUserProvider" is one of them.
As said, you are using
PersistenceManagerFactory pmf = new JDOPersistenceManagerFactory(globalPumd, null);

and you need to provide any ADDITIONAL persistence properties (such as the one you wanted to specify) via the second argument in that constructor.