Hi Mitesh,
The reason updateServerPlatform method uses loader parameter is that the server platform class may be defined in the persistence unit, and therefore the "main" classloader used to load TopLink classes may not define this class.
However the classes defined in the persistence unit should be able to "see" TopLink classes defined by the "main" classloader (the most simple implementation would be the passed class loader is a child of the "main" classloader).
Therefore I don't see how the problem may arise when updateServerPlatform is called by deploy method with the "real" classloader.
However there may be a problem when the method is called earlier, by predeploy method using temporary classloader (which is also supposed to see TopLink classes): the server platform instantiated using temporary classloader will be set - and never overridden with the same one loaded using the "real" classloader. Again, that only applicable in case of user-defined server platform. The same applies also to updateLoggers.
The only reason to have updateServerPlatform and updateLoggers in predeploy is to make sure that the correct logger is used in predeploy method.
updateServerPlatform and updateLoggers methods called for the second time in deploy method (through updateServerSession method): at this point if server platform class name is the same as the original one then the new server platform is not created (the same for loggers).
What probably should happen: in case serverPlatform's class name is the same as the specified, verify that it's classloader is the "main" one (the same one used to load TopLink classes). Otherwise it's a user-defined platform loaded on the temporary classloader - then it should be overridden with the new one (the same class name, but using the passed ("real") classloader).
Please let me know does that make sense to you.
Thanks,
Andrei
----- Original Message -----
From: Mitesh Meswani
To: persistence_at_glassfish.dev.java.net
Cc: Timothy.Quinn_at_Sun.COM
Sent: Thursday, May 24, 2007 9:16 PM
Subject: A Question about code in EntityMangerSetupImpl
Hi Tom, Gordon,
I have a question about following code from EntityMangerSetupImpl
protected boolean updateServerPlatform(Map m, ClassLoader loader) {
String serverPlatformClassName = PropertiesHandler.getPropertyValueLogDebug(TopLinkProperties.TARGET_SERVER, m, session);
....
....
ServerPlatform serverPlatform = null;
// New platform - create the new instance and set it.
--->A Class cls = findClassForProperty(serverPlatformClassName, TopLinkProperties.TARGET_SERVER, loader);
try {
Class clz = oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.class;
--->B Constructor constructor = cls.getConstructor(new Class[]{oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.class});
serverPlatform = (ServerPlatform)constructor.newInstance(new Object[]{session});
Here depending on from which environment and from which method updateServerPlatform is called, the parameter loader is either the classloader that loads the application (PereistenceUnit) or the tempClassLoader which is expected to be a clone.
At point (A) above, we use the parameter 'loader' as the classloader to load the class specified by property TopLinkProperties.TARGET_SERVER. At point (B) we try to get constructor for cls with parameter 'oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.class'. If 'cls' is loaded by a different classloader than the classloader that loads 'DatabaseSessionImpl.class', the constructor will never be found. Infect, this is what is happening inside appclient for glassfish and we are not able to inject persistence artifacts into appclient.
The question is at point (A) above, why do we use the parameter 'loader' as the classloader to load the class specified by property TopLinkProperties.TARGET_SERVER?
Thanks,
Mitesh