[ https://issues.apache.org/jira/browse/JDO-545?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12545558 ]
Matthew T. Adams commented on JDO-545: -------------------------------------- Patch on prior comment includes indicated updates in comments submitted with patch. > Allow users to supply property-overriding Map instances when configuring from > resources (properties, jdoconfig.xml, or persistence.xml) > --------------------------------------------------------------------------------------------------------------------------------------- > > Key: JDO-545 > URL: https://issues.apache.org/jira/browse/JDO-545 > Project: JDO > Issue Type: Improvement > Components: api2, api2-legacy > Affects Versions: JDO 2 maintenance release 1 > Reporter: Matthew T. Adams > Assignee: Matthew T. Adams > Fix For: JDO 2 maintenance release 1 > > Attachments: jdo-545.patch > > > See my changes inline below, enclosed by "<<<" and ">>>", and my comments. > -matthew > On Oct 1, 2007, at 2:07 PM, Craig L Russell wrote: > Javadogs, > I've completed the specification update for these methods. Please take a look > and comment: > Note that this section doesn't exactly match what Matthew has already > implemented, but really close... > <proposed> > PersistenceManagerFactory methods > The methods in this section provide for bootstrapping the > PersistenceManagerFactory by configuration according to the properties > documented in Section 11.1. Users have a choice of configuration techniques: > The application provides a Map of properties used to construct a > PersistenceManagerFactory > The application provides a Map of override properties and <<<the name of a > resource in standard Java Properties format, the name of a named > PersistenceManagerFactory, or a JPA persistence unit name>>> that are used to > construct a PersistenceManagerFactory > The application provides the name of a resource in standard Java Properties > format whose contents define the properties for the PersistenceManagerFactory > The application provides an InputStream in standard Java Properties format > whose contents define the properties for the PersistenceManagerFactory > The application provides a File whose contents are in standard Java > Properties format which define the properties for the > PersistenceManagerFactory > The application provides a JNDI name and context in which the name is defined > The application provides a resource named META-INF/jdoconfig.xml and > optionally META-INF/services/javax.jdo.PersistenceManagerFactory which > contain configuration information > The application provides a resource named META-INF/persistence.xml and > optionally META-INF/services/javax.persistence.EntityManagerFactory which > contain configuration information > For the cases of InputStream, File, and resource name, a Properties instance > is constructed by JDOHelper and passed to one of the > getPersistenceManagerFactory(Map) methods. When using these techniques, each > configuration of PersistenceManagerFactory is contained <<<either in a Java > Properties resource, in a META-INF/jdoconfig.xml and optionally a > META-INF/services/javax.jdo.PersistenceManagerFactory, or in a > META-INF/persistence.xml and optionally a > META-INF/services/javax.persistence.EntityManagerFactory. The >>> > propsLoader parameter is used only to load the resource to construct the Map. > Once the Map with configuration information is obtained, the loader is used > for loading all other resour<<<c>>>es, > Comment: I'm confused about what the "propsLoader" and the "loader" are. > I'll assume the "propsLoader" is the ClassLoader used to load resources > required to build the Properties instance (aka "Map"), and the "loader" is > the ClassLoader used to load classes and whatever other resources whose > loading can't be controlled. > including the persistence.xml, jdoconfig.xml, services locators, and > PersistenceManagerFactory class. > Comment: This is not true; some of these resources are loaded by > propsLoader, some are not. If all native JDO means of creating a Properties > instance (aka "Map") fail, we delegate to javax.persistence.Persistence, and > we can't tell Persistence.createEntityManagerFactory(..) which ClassLoader to > use for resource loading and which to use for class loading; in fact, we > can't tell it anything about which ClassLoader(s) to use. > In order to build the Properties instance (aka "Map"), the following > resources are loaded by the propsLoader: the Java Properties resource with > the given name, and if that's not found, all META-INF/jdoconfig.xml files on > the classpath. If, after constructing a Properties instance there is no > javax.jdo.PersistenceManagerFactoryClass property, then the propsLoader is > used again to load a META-INF/services/javax.jdo.PersistenceManagerFactory; > the exact one is determined by ClassLoader's getResourceAsStream(String) > method. If no META-INF/jdoconfig.xml files are found or no > PersistenceManagerFactory is found with the requested name, then JDOHelper > delegates to javax.persistence.Persistence.createEntityManagerFactory(String) > to look up the META-INF/persistence.xml file with the persistence unit name > given, then casts the returned EntityManagerFactory to a > PersistenceManagerFactory. > A8.6-22 [public static > PersistenceManagerFactory getPersistenceManagerFactory > (Map props, String name, ClassLoader loader);] > A8.6-23 [public static > PersistenceManagerFactory getPersistenceManagerFactory > (Map props, String name);] > These methods create a new copy of the Map parameter, add the property > "javax.jdo.option.Name" with the value of the name parameter and delegate to > the corresponding JDOHelper method taking a Map parameter. > Comment: This is new and not yet coded. I understand the motivation to add > these methods (which is Persistence.createEntityManagerFactory(String,Map)), > so I'm cool with adding these, but we'll have to tighten up the description > of the overriding Properties, especially in the case that no Java Properties > resource is found and the named PMF is not found. Do we pass the given Map > down to Persistence.createEntityManagerFactory(String,Map)? I am inclined to > say yes (see end comments plus the patch). > A8.6-13 [public static > PersistenceManagerFactory getPersistenceManagerFactory > (File propsFile);] > A8.6-14 [public static > PersistenceManagerFactory getPersistenceManagerFactory > (File propsFile, ClassLoader loader);] > A8.6-17 [public static > PersistenceManagerFactory getPersistenceManagerFactory > (InputStream stream);] > A8.6-18 [public static > PersistenceManagerFactory getPersistenceManagerFactory > (InputStream stream, ClassLoader loader);] > These methods use the parameter(s) passed as arguments to construct a > Properties instance, and then delegate to the JDOHelper method > getPersistenceManagerFactory that takes a Map parameter. > A8.6-15 [public static > PersistenceManagerFactory getPersistenceManagerFactory > (String propsResourceName);] > A8.6-16 [public static > PersistenceManagerFactory getPersistenceManagerFactory > (String propsResourceName, ClassLoader loader);] > A8.6-21[public static > PersistenceManagerFactory getPersistenceManagerFactory > (String propsResourceName, ClassLoader propsLoader, > ClassLoader pmfLoader);] > These methods use the propsLoader getResourceAsStream method with the > propsResourceName as an argument to obtain an InputStream, construct a new > Properties instance, then delegate to the corresponding JDOHelper method > getPersistenceManagerFactory that takes a Map parameter. > Comment: Correct. > If the named resource does not exist, JDOHelper constructs a new Map, adds a > property named "javax.jdo.option.Name" with the value of the > propsResourceName parameter, and then delegates to the corresponding > JDOHelper method taking a Map parameter. > Comment: Minor detail (see below). JDOHelper conveniently converts a null > name to an empty string. > The empty string (not a null string) identifies the default > PersistenceManagerFactory name. > Comment: JDOHelper's > gerPersistenceManagerFactory(String[,ClassLoader[,ClassLoader]]) methods > treat the empty string and a null string equally. Officially, the empty > string is the name of the anonymous or unnamed PMF; null strings are just > converted to empty strings for convenience. We should probably add a > constant ANONYMOUS_PERSISTENCE_MANAGER_FACTOR_NAME (or > UNNAMED_PERSISTENCE_MANAGER_FACTORY_NAME) String with the value "" to > javax.jdo.Constants just so that it's explicit in the code. What do you > think? > A8.6-2 [public static > PersistenceManagerFactory getPersistenceManagerFactory > (Map props);] > A8.6-3 [This method delegates to the corresponding method with a class loader > parameter, using the calling thread's current contextClassLoader as the class > loader.] > A8.6-1 [public static > PersistenceManagerFactory getPersistenceManagerFactory > (Map props, ClassLoader loader);] > This method returns a PersistenceManagerFactory based on entries contained in > the Map parameter. Three map entries are significant to the processing of > this method: > javax.jdo.option.PersistenceUnitName: If not null, this identifies the name > of the persistence unit to be accessed. The > Persistence.createEntityManagerFactory method is called with the props and > PersistenceUnitName as parameters. The result is cast to > PersistenceManagerFactory and returned to the user. > javax.jdo.option.Name: If not null, this identifies the name of the > PersistenceManagerFactory listed in jdoconfig. The class loader loads > META-INF/jdoconfig.xml and finds the PersistenceManagerFactory by name. If > the value of the entry javax.jdo.option.Name is the empty string, this > identifies the unnamed PersistenceManagerFactory listed in jdoconfig. > JDOHelper constructs a Map instance with the contents of the jdoconfig entry > and overrides its contents with the props parameter. Processing continues > with PersistenceManagerFactoryClass. > javax.jdo.PersistenceManagerFactoryClass: > If not null, this identifies the name of the PersistenceManagerFactory class. > JDOHelper uses the loader to resolve the PersistenceManagerFactory class name. > A8.6-6 [If the class named by the PersistenceManagerFactoryClass property > cannot be found, or is not accessible to the user, then JDOFatalUserException > is thrown.] JDOHelper invokes the static method getPersistenceManagerFactory > in the named class, passing the props as the parameter. A8.6-7 [If there is > no public static implementation of the getPersistenceManagerFactory(Map) > method, ]A8.6-5 [or if there are any exceptions while trying to call the > static method,] A8.6-8 [or if the implementation of the static > getPersistenceManagerFactory(Map) method throws an exception, then > JDOFatalInternalException is thrown]. The nested exception indicates the root > cause of the exception. > Comment: Correct so far. > If null, JDOHelper loads the PersistenceManagerFactory class using the > services lookup pattern. That is, resources named > META-INF/services/<<<javax.jdo.>>>PersistenceManagerFactory are loaded by the > loader and each class in turn is used to call its static > getPersistenceManagerFactory method, passing the props as the parameter. If > one of the resources succeeds in returning a non-null > PersistenceManagerFactory, it is returned to the user and any exceptions > (thrown by other resources) are ignored. If no resource succeeds, > JDOFatalUserException exception is thrown to the user, with a nested > exception for each failure. > Comment: The implementation only attempts to find one resource named > META-INF/services/javax.jdo/PersistenceManagerFactory (via ClassLoader's > getResourceAsStream(String) method), not all of them. Are you suggesting > that we change this? > The standard key values for the properties are found in Section 11.1. > Comment: To implement support for user-supplied, property-overriding Maps, I > suggest that we make the existing methods > getPersistenceManagerFactory(String name) > getPersistenceManagerFactory(String name, ClassLoader resourceLoader) > getPersistenceManagerFactory(String name, ClassLoader resourceLoader, > ClassLoader pmfLoader) > and the new methods > getPersistenceManagerFactory(Map overrides, String name) > getPersistenceManagerFactory(Map overrides, String name, ClassLoader > resourceLoader) > convenience methods that delegate to the meaty method > getPersistenceManagerFactory(Map overrides, String name, ClassLoader > resourceLoader, ClassLoader pmfLoader) > If I understand all of this correctly, then the last operation of this method > before delegating to > getPersistenceManagerFactory(Map props, ClassLoader resourceLoader, > ClassLoader pmfLoader) > is to replace any values in props with values from overrides. If this method > ends up delegating instead to > Persistence.createEntityManagerFactory(String,Map), then it will pass the > overriding properties as the Map in that method. > I implemented this while going through this post. Please review the attached > patch to make sure that I got it right. > Note that it is only in JDOHelper's getPersistenceManagerFactory(Map props, > ClassLoader resourceLoader, ClassLoader pmfLoader method that > META-INF/services lookup is used, and then only when there is no > javax.jdo.PersistenceManagerFactoryClass property in props! > JDO implementations are permitted to define key values of their own. A8.6-9 > [Any key values not recognized by the implementation must be ignored.] > A8.6-10 [Key values that are recognized but not supported by an > implementation must result in a JDOFatalUserException thrown by the method.] > A8.6-11 [The returned PersistenceManagerFactory is not configurable (the > setXXX methods will throw an exception).] A8.6-12 [JDO implementations might > manage a map of instantiated PersistenceManagerFactory instances based on > specified property key values, and return a previously instantiated > PersistenceManagerFactory instance. In this case, the properties of the > returned instance must exactly match the requested properties.] > A8.6-19 [public static > PersistenceManagerFactory getPersistenceManagerFactory > (String jndiLocation, Context context);] > A8.6-20 [EMAIL PROTECTED] public static > PersistenceManagerFactory getPersistenceManagerFactory > (String jndiLocation, Context context, ClassLoader loader);] > These methods look up the PersistenceManagerFactory using the naming context > and name supplied. The implementation's factory method is not called. The > behavior of this method depends on the implementation of the context and its > interaction with the saved PersistenceManagerFactory object. As with the > other factory methods, the returned PersistenceManagerFactory is not > configurable. > </proposed> -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online.