I've been looking at the public specs for this and there's a pretty big hole at this late stage in the spec. The spec mandates field level interception for the persistence manager. This requires a rewriting class loader using a technology such as AOP or cglib.
Trouble is, this requires that the PM be able to intercept classes being loaded by the container or managed environment. There is no contract to do this besides hacking it in to the system class loader which as a solution is just crawling with issues. Different apps in the same container may use different PMs but use same class names etc.
It seems to be me that persistent object spec needs an extra attribute on the PM provider which the container should provide when the provider is initialized. It should look something like:
public ClassLoader transformClasses(ClassLoader cl)
The container provides the class loader it would use to load the app classes and remember different apps within the same container may use different class loaders so this means we'd be newing up a different PM for each application potentially. In return, the pm returns either the same class loader if it doesn't use rewritting, this is possible if it used a remember and compare approach or used a deploy tool to preinstrument the app. Or it returns a new class loader that takes the classes from the container class loader and modifies the classes as they load.
This interface should be part of the jars for the PM only and have nothing to do with the J2EE or EJB specification. I'd like to see older application servers such as WAS 5.x or older competitive applications server or non J2EE managed environments such as spring etc use these interfaces to allow these PMs to be plugged in to them also. This is supposed to be a portable persistence manager not one that only works with a J2EE 1.5 platform after all.
In a way this interface with the single method shouldn't be coupled to the PM or EJB 3.0 at all. Managed environments that allowed AOP style plugins would be required to provide something like this anyway to allow such a plugin to work in a predictable fashion. Otherwise, how are managed environment vendors supposed to support such plugins as they have no architected way to plugin them in and scope them correctly.
It would be nice to see frameworks like JBoss AOP or Spring AOP use a mechanism like this to seperate the concerns or allow a third party AOP plugin that an application may be dependant on to be plugged in, why do they insist you use THEIR AOP plugin. I may like another if I'm a customer, give me the choice.
>> The spec mandates field level interception for the persistence manager. <<
This is not true. JBoss EJB3 implementation does not need to do field interception.
The spec was very carefully written so that field interception was not mandatory.
However, there is currently a proposal in the EG - that I believe has pretty much already been adopted - to add a hook for class transformation if (only if) the persistence provider wants it.
Posted by: Gavin King | September 08, 2005 at 07:54 PM
Yep
I meant field level change detection. I mentioned this approach later in the entry with the 'norewriting' comment which is likely what you guys are doing in your implementation. Copy the object and compare the attributes with the originals at commit time to spot changes using the required getter/setter pairs for each attribute.
Which is faster depends I guess on how many attributes are present.
Posted by: Billy | September 08, 2005 at 08:03 PM
The point is that the snapshot comparison approach (which has advantages and disadvantages) can be implemented by reflection, or by class generation, neither of which requires control of the classloader.
Posted by: Gavin King | September 08, 2005 at 08:38 PM
You can always enhance the classes at build time, hence not use any classloader hacking system.
Posted by: Emmanuel Bernard | September 09, 2005 at 07:50 AM
Yes,
I mentioned that in the blog.
Posted by: Billy | September 09, 2005 at 09:18 AM
I don't think Containers would be too keen on using a classloader provided by the Provider (and I suspect WebSphere would be last in line for that one). What Gavin was referring to, that we have just adopted, is a method on the Container-Persistence Provider interface that gives the Provider a classloader that it can use to do stuff with and the ability to add a Transformer to the Container classloader. Talk to your rep on the EG (Randy) to get more info on it and see if it meets your needs. I think it should.
As far as offering this at a higher level you should contact Jim Knutson (IBM rep on J2EE), or your spec reps at other levels to propose this. Could be useful.
Posted by: Mike Keith | September 09, 2005 at 10:53 AM
I was suggesting the container providing the classloader to the application resources to the provider and the provider then returning a classloader using that class loader as a base. The security stuff here is bogus, the provider is messing with the classes either way...
Posted by: Billy | September 09, 2005 at 01:56 PM