| Summary: | Cannot find resource from bundle once started | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [RT] Gemini.JPA | Reporter: | Alex Blewitt <alex.blewitt> | ||||
| Component: | Core | Assignee: | Shaun Smith <shaun.smith> | ||||
| Status: | RESOLVED FIXED | QA Contact: | |||||
| Severity: | normal | ||||||
| Priority: | P3 | ||||||
| Version: | 1.0.0 | ||||||
| Target Milestone: | --- | ||||||
| Hardware: | All | ||||||
| OS: | All | ||||||
| Whiteboard: | |||||||
| Attachments: |
|
||||||
|
Description
Alex Blewitt
OK, some additional info. I'm using DS (Apache Felix SCR), Eclipse Virgo and Gemini JPA 1.0.0M2 and EclipseLink 2.1.1 bundles + dependents I have a component which consumes an EntityManagerFactory and registers a service interface. This service implementation contains a call which (later) invokes the emf.createEntityManagerFactory(). As a result, by the time that's invoked, the bundle is already running (though the model classes haven't necessarily been loaded). The problem is when the createEntityManagerFactory is called, Gemini JPA seems to be failing to acquire resources from a running bundle thanks to the tests below. (Should it be the negation of these?) It checks the 'initial PUs' or something but fails to find it, which is why it falls back to this lookup. I'm not sure if the PUs, which must have been loaded/parsed in order to create the EMF service entry, should be being cached somewhere and this path not taken. FWIW the bundle spends very little time in the INSTALLED state since it is installed and brought on-line by Virgo and/or DS. OK, can still reproduce this with EclipseLink 2.2.0-M5 (18Nov) and JPA 1.0.0.M3
Call stack is much the same as before.
At the point we get the bundle, we have the PUnitInfo already:
props.put(GeminiOSGiInitializer.OSGI_BUNDLE, pUnitInfo.getBundle());
EntityManagerFactory emf = eclipseLinkProvider.createEntityManagerFactory(emName, props);
but by the time we go up a couple of calls, we lose it:
org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory
try {
SEPersistenceUnitInfo puInfo;
puInfo = initializer.findPersistenceUnitInfo(name, nonNullProperties, initializationHelper);
// either persistence unit not found or provider not supported
if(puInfo == null) {
return null;
}
so this returns null as we can't find the puinfo.
So, good news. By commenting out those if bundle state checks, I can now get onto my next error. Fortunately, this one is 'forgot to put temporal type on date element' so I think I'm looking good :) OK, I now have JPA working in my runtime. It seems that EclipseLink wants to create an SEPersistenceUnitInfo, and to do so, looks for the META-INF/persistence.xml after startup. (It already has the Gemini Persistence Unit with the right classes, data etc.) However, since it can't introspect the bundle because the classloader willingly pretends it's empty, it gives up without even giving further parts a chance. So fortunately, this looks like a bug in Gemini JPA rather than EclipseLink, but I don't know what the right solution is. It's either to override the 'findPersistenceUnit' to consult the map (which it already has) instead of deferring upwards, or to remove the check on the started status of the bundle via the proxy class loader. To reproduce, I think all you need to do is: * Install and start the Gemini/JPA bundles * Install (but don't start) a JPA with a META-INF/persistence.xml * Get hold of the EntityMangerFactory * Start the JPA bundle * Call emf.createEntityManager() I think that's the sequence I'm doing. The call to 'createEntityManager' is in a bundle with the JPA for me, so in effect, it's already started. (The same happens with the samples; I don't know how it's not getting triggered there.) A slight caveat is that i'm testing this in Virgo rather than a standard Equinox runtime - there may be some issue here. Looks like a bug in the ProxyClassLoader code where delegation is made to the superclass instead of to the bundle. Assigning to Shaun. It does delegate to the bundle, but *only* if irbid in the INSTALLED state. There's even an "if" condition that looks specifically for this case. We just need to remove the "if". Created attachment 184526 [details]
Patch the corrects behavior when bundle is not INSTALLED or UNINSTALLED
When a bundle was not INSTALLED or UNINSTALLED the BundleProxyClassLoader should have been forwarding methods onto the bundle. It was not. The patch corrects this. Alex, please test this in your environment and let me know if this resolves your issue. Patch committed in SVN TX 89. Thanks. Looks like a more complex change than the one I made which was simply to remove the if. Will try out a binary to see if that works. Note that if the persistence.xml is contributed as a fragment then this behaviour might still be problematic - I'll try that as well. I believe that this fixes the issue, but I'll mark it as verified when I test it against the next milestone since I'm not sure if my compilation-and-repackage was correct. |