openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Pinaki Poddar (Created) (JIRA)" <j...@apache.org>
Subject [jira] [Created] (OPENJPA-2057) Rethinking ClassLoading architecture
Date Tue, 11 Oct 2011 16:11:12 GMT
Rethinking ClassLoading architecture 
-------------------------------------

                 Key: OPENJPA-2057
                 URL: https://issues.apache.org/jira/browse/OPENJPA-2057
             Project: OpenJPA
          Issue Type: Improvement
          Components: kernel
            Reporter: Pinaki Poddar


This issue proposes an overhaul of the classloading architecture.

Background:
------------------
OpenJPA runtime needs to load classes and resources at various time points in its life cycle
and employs various classloading strategies at different parts of its code base. 
These are few broad categories of classes/resources OpenJPA needs to load
1. Resources: user-specified resources such as persistence.xml or orm.xml
2. Persistent Domain classes
3. Native Plug-ins: Implementation of interfaces e.g. UpdateManager that are supplied by OpenJPA
and packaged in its own distribution
4. User Plug-ins: Implementation of interfaces e.g. MappingStrategy or ValueHandlers that
the user has supplied via configuration and packaged in deployed units
5. Temporary classloader for java agent or weaving code loading domain classes to enhance
them prior to their use

To load these different artifacts by their name, OpenJPA at different places employ available
classloaders such as 
   i) the current thread's context class loader 
   ii) the clasloader that loaded OpenJPA native classes/interfaces 
  iii) the classloader that loaded a deployed application which can vary based on the container
(Spring, OSGi, JEE) environment
  iv) system classloader   

The problem is the decision about which classloader is appropriate in a given context is quite
scattered. This weakness appears in numerous places where a method is supplied with a ClassLoader
and if the supplied loader is null, the method chooses a classloader (often the context classloader)
or a class has its own classforname() method that tries a series of classloaders etc. 

This is a perennial problem and manifested in several reported bugs whose resolutions often
introduced further localized logic to account for the point defects, thereby  accentuating
the same trends that I believe is the root cause of the problem itself. 

Proposed solution/design:
-------------------------------------
Unify classloading decision in a singular abstraction. 
Allow that abstraction to cope with classloading regimes of different containers (Spring,
OSGi, JEE etc). 

The natural candidate for unifying classloading is existing Configuration object. This object
is a per persistence unit singleton and available throughout the runtime. 
However, certain class/resource loading must take place even before a Configuration instance
is instantiated. For example, to locate and load the persistence.xml itself. 
Also note that the persistence.xml or orm.xml may contain fully-qualified names of persistent
domain classes or  plug-in names (both native and custom/user variety) and they can occur
either by their  fully-qualified class name or registered alias. The specialized parsers often
has to load the class given their parsed string names or aliases. 

The bootstrap sequence of OpenJPA runtime is to construct a specific ConfigurationProvider
and a series of specialized parsers to parse meta-data of various sorts (annotations, mapping
xml, persistence.xml). These ConfigurationProviders are responsibilities of ProductDerivation
-- the core mechanics that contributes their individual aspects to build up a Configuration.


Given this existing well-designed bootstrap strategy, here is a proposal
  1. Let each ProductDerivation make their decision on how they will load whatever they need
to load using whatever classloader they may need. For example, a OSGi ProductDerivation will
use a bundle classloader to load its relevant resources. This phase occurs *before* a persistence
unit (i.e. EntityManagerFactory) is constructed.
  2. Once the ProductDerivations have finished their loading using their own ConfigurationProvider,
they transfer the accumulated information to a Configuration instance which essentially becomes
the holder of entire runtime information for an EntityManagerFactory. During this transfer
phase, let the ProductDerivations set the classloader as well into the Configuration instance.
  3. Once the Configuration instance has the classloader, this classloader is used throughout
the codebase.

But what kind of classloader is used by the Configuration that will suit complex needs of
class/resource loading? 
OpenJPA already has a powerful abstraction called MultiClassLoader which can employ an ordered
series of (possibly unrelated) classloaders. So that MultiClassLoader is the correct classloader
for Configuration instance. The ProductDerivation or ConfigurationProvider can add/remove
their contributions. 

I understand that a change of this nature could be destabilizing in short-term. Also the change
is difficult to validate across various container environments. I hope the community users
will help by suggesting and testing such an overhaul to streamline OpenJPA classloading for
long-term sustainability and maintenance. 
   
  



--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Mime
View raw message