persistence@glassfish.java.net

Re: [Fwd: [Issue 1074] Regression: TopLink does not serach classpath for mapping files specified in persistence.xml]

From: Marina Vatkina <Marina.Vatkina_at_Sun.COM>
Date: Wed, 13 Sep 2006 14:51:51 -0700

Hi Sahoo,

I'll still leave it to Tom to explain the Tomcat part, but
here is more strange stuff around this problem:

In some cases (looks like in java2db of redeploy to drop
old tables, but this part will be changed, and during some
load (see the stack below), when we create EMF, the PU url
(persistenceUnitInfo.getPersistenceUnitRootUrl()) returns
file:/faith4/gf/publish/glassfish/domains/domain1/applications/j2ee-apps/foo/foo/entities.jar
This file includes all entries from pu.jar and from foo/entities.jar
(as determined via iterating over entries from a JarInputStream(...)
created from that url).

Can you please check how can this be? (The line number in
PersistenceUnitProcessor won't match as I added some
debugging code to my version).

thanks,
-marina

The stack:
        at java.lang.Thread.dumpStack(Thread.java:1158)
        at
oracle.toplink.essentials.ejb.cmp3.persistence.PersistenceUnitProcessor.createInputStreamForFileInPersistenceUnit(PersistenceUnitProcessor.java:224)
        at
oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.processORMetadata(EntityManagerSetupImpl.java:965)
        at
oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:497)
        at
oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.createContainerEntityManagerFactory(EntityManagerFactoryProvider.java:152)
        at
com.sun.enterprise.server.PersistenceUnitLoaderImpl.load(PersistenceUnitLoaderImpl.java:195)
        at
com.sun.enterprise.server.PersistenceUnitLoaderImpl.load(PersistenceUnitLoaderImpl.java:77)
        at
com.sun.enterprise.server.AbstractLoader.loadPersistenceUnits(AbstractLoader.java:849)
        at
com.sun.enterprise.server.ApplicationLoader.load(ApplicationLoader.java:179)
        at
com.sun.enterprise.server.TomcatApplicationLoader.load(TomcatApplicationLoader.java:113)
        at
com.sun.enterprise.server.ApplicationManager.applicationDeployed(ApplicationManager.java:322)
        at
com.sun.enterprise.server.ApplicationManager.applicationDeployed(ApplicationManager.java:196)
        at
com.sun.enterprise.server.ApplicationManager.applicationDeployed(ApplicationManager.java:633)
        at
com.sun.enterprise.admin.event.AdminEventMulticaster.invokeApplicationDeployEventListener(AdminEventMulticaster.java:908)
        at
com.sun.enterprise.admin.event.AdminEventMulticaster.handleApplicationDeployEvent(AdminEventMulticaster.java:892)
        at
com.sun.enterprise.admin.event.AdminEventMulticaster.processEvent(AdminEventMulticaster.java:445)
        at
com.sun.enterprise.admin.event.AdminEventMulticaster.multicastEvent(AdminEventMulticaster.java:160)
        at
com.sun.enterprise.admin.server.core.DeploymentNotificationHelper.multicastEvent(DeploymentNotificationHelper.java:295)
        at
com.sun.enterprise.deployment.phasing.DeploymentServiceUtils.multicastEvent(DeploymentServiceUtils.java:203)
        at
com.sun.enterprise.deployment.phasing.ServerDeploymentTarget.sendStartEvent(ServerDeploymentTarget.java:285)
        at
com.sun.enterprise.deployment.phasing.ApplicationStartPhase.runPhase(ApplicationStartPhase.java:119)
        at
com.sun.enterprise.deployment.phasing.DeploymentPhase.executePhase(DeploymentPhase.java:95)
        at
com.sun.enterprise.deployment.phasing.PEDeploymentService.executePhases(PEDeploymentService.java:871)
        at
com.sun.enterprise.deployment.phasing.PEDeploymentService.start(PEDeploymentService.java:541)
        at
com.sun.enterprise.deployment.phasing.PEDeploymentService.start(PEDeploymentService.java:585)
        at
com.sun.enterprise.admin.mbeans.ApplicationsConfigMBean.start(ApplicationsConfigMBean.java:719)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)



Sanjeeb Kumar Sahoo wrote On 09/13/06 12:34,:
> Marina,
>
> Marina Vatkina wrote:
>
>>Sahoo,
>>
>>I'll do more experiments with Class-path in manifest to see why were
>>the files found originally, when that entry was missing. I need to test
>>a PU packaged into a jar in SE as well to see which path we take in
>>finding the files.
>>
>>But step#2 is not that simple. If you have your PU defined in Java SE
>>and mappingFile.xml is located in the PU root, plus (incidentally) there
>>is another mappingFile.xml located somewhere on the classpath, we
>>most probably should ignore that other one.
>
> What I wrote is valid for Java EE as this is what the javadocs of
> PersistenceUnitInfo.getMappingFiles() say:
> /**
> * @return The list of mapping file names that the persistence
> * provider must load to determine the mappings for the entity
> * classes. The mapping files must be in the standard XML
> * mapping format, be uniquely named and be resource-loadable
> * from the application classpath.
> * Each mapping file name corresponds to a <mapping-file>
> * element in the persistence.xml file.
> */
>
> I have not seen such rules for Java SE, but I will be surprised if the
> rules were meant to be any different for Java SE. Assuming this, if an
> application has more than one mapping file with same name in ClassPath,
> then provider should not prefer one over the other. Either use first one
> returned by ClassLoader or throw exception.
>
>>Also, if we ever support jar-file in SE, that complicated logic might
>>need to be added back to step#2.
>
> Which complicated logic?
>
> Thanks,
> Sahoo
>
>>And the last one - Tom mentioned (I'll leave it for Tom to give details
>>and examples) that Tomcat returns some strange URLs that need to be
>>addressed separately, and this is done in URL comparisons after
>>getResources()
>>call.
>>
>>Let's see what else I can find on what seemed like an easy bug fix ;).
>>
>>thanks,
>>-marina
>>
>>Sanjeeb Kumar Sahoo wrote:
>>
>>>Marina,
>>>
>>>There is also a bug in the code and the subject line of this mail
>>>thread spells it out nicely. The code does not distinguish between
>>>the default mapping file(META-INF/persistence.xml) and the files
>>>specified using <mapping-file> element in persistence.xml. It is
>>>making a merged list and then applying uniform strategy to look them
>>>up. That's wrong. It should do this:
>>>// step #1: try to read default mapping file (META-INF/orm.xml) from
>>>PURoot and from each referenced jar-file.
>>>// during this time, it can use all the complex logic that is
>>>required to handle various difference kinds of URLs that can be
>>>encountered.
>>>// step #2: read explicitly specified mapping-files
>>>for (String mfName : puInfo.getmappingFiles()) {
>>>// don't do any special processing if user specified META-INF/orm.xml
>>>here as well. That's a bug in user code.
>>>InputStream mfStream =
>>>persistenceUnitInfo.getTempClassLoader().getResourceAsStream(mfName);
>>>// read the content...
>>>}
>>>
>>>In step #2, we can definitely throw a ValidationException if we come
>>>across multiple mapping files with same name as Winsoek suggested
>>>earlier.
>>>
>>>I have a feeling, this change has to be made in more than one place.
>>>
>>>Thanks,
>>>Sahoo
>>>
>>>Marina Vatkina wrote:
>>>
>>>
>>>>Hi Tom,
>>>>
>>>>It was my fault - manifest file in PU didn't have Class-Path entry
>>>>to add
>>>>that jar to the classpath (thanks Sahoo!).
>>>>
>>>>thanks,
>>>>-marina
>>>>
>>>>Tom Ware wrote:
>>>>
>>>>
>>>>>Hi Marina,
>>>>>
>>>>>Are the entities you are having trouble loading on the classpath?
>>>>>It is my understanding that the jars should be on the classpath
>>>>>(either put there by the application server, or, in the SE case,
>>>>>explicitly put there)
>>>>>
>>>>>-Tom
>>>>>
>>>>>Marina Vatkina wrote:
>>>>>
>>>>>
>>>>>>Hi Wonseok,
>>>>>>
>>>>>>Very good point about more than one resource.
>>>>>>
>>>>>>PersistenceUnitProcessor.createInputStreamForFileInPersistenceUnit
>>>>>>the 1st thing it does - looks for the mapping files located in a jar.
>>>>>>
>>>>>>Attached test proves that it does look in a jar as it complains about
>>>>>>not found classes. Which brings up another questions: am I doing
>>>>>>something wrong there, or is it another bug: 2 out of 3 entities
>>>>>>listed in the mapping file(s) and located in that ref-ed jar can't be
>>>>>>loaded (so they are ignored - the 3rd bug?).
>>>>>>
>>>>>>thanks,
>>>>>>-marina
>>>>>>
>>>>>>Wonseok Kim wrote On 09/10/06 23:05,:
>>>>>>
>>>>>>
>>>>>>
>>>>>>>Hi, Marina
>>>>>>>
>>>>>>>I agree that orm.xml or mapping files in the PU root should be
>>>>>>>used if
>>>>>>>there are multiple same name files in the classpath.
>>>>>>>But if there is no one in PU root and we pick one of the same name
>>>>>>>mapping files in the classpath, it can be unpredictable.
>>>>>>>How about throwing an exception in that case? Of course if there
>>>>>>>is one
>>>>>>>mapping file in the classpath, it should work.
>>>>>>>If you agree with this, the 4th step should call getResources() and
>>>>>>>check the number of returned resources.
>>>>>>>
>>>>>>>I'm now curious that current impl can process several
>>>>>>>META-INF/orm.xml
>>>>>>>files which exist in referenced jar files from persistence.xml. You
>>>>>>>mentioned it is accomplished by current impl, but I couldn't find
>>>>>>>it in
>>>>>>>the code... please instruct me.
>>>>>>>
>>>>>>>Thanks
>>>>>>>- Wonseok
>>>>>>>
>>>>>>>On 9/9/06, *Marina Vatkina* <Marina.Vatkina_at_sun.com
>>>>>>><mailto:Marina.Vatkina_at_sun.com>> wrote:
>>>>>>>
>>>>>>>Team,
>>>>>>>
>>>>>>>Do you have any idea of a simpler/better/nicer solution for locating
>>>>>>>mapping
>>>>>>>files in a PU?
>>>>>>>
>>>>>>>thanks,
>>>>>>>-marina
>>>>>>>
>>>>>>>-------- Original Message --------
>>>>>>>From: mvatkina_at_dev.java.net <mailto:mvatkina_at_dev.java.net>
>>>>>>>Subject: [Issue 1074] Regression: TopLink does not serach classpath
>>>>>>>for mapping
>>>>>>>files specified in persistence.xml
>>>>>>>
>>>>>>>https://glassfish.dev.java.net/issues/show_bug.cgi?id=1074
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>User mvatkina changed the following:
>>>>>>>
>>>>>>>What |Old value |New value
>>>>>>>================================================================================
>>>>>>>
>>>>>>>
>>>>>>>Status|NEW |STARTED
>>>>>>>--------------------------------------------------------------------------------
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>------- Additional comments from mvatkina_at_dev.java.net
>>>>>>><mailto:mvatkina_at_dev.java.net> Fri Sep 8 20:41:35 +0000
>>>>>>>2006 -------
>>>>>>>Here is what I learned about the current implementation:
>>>>>>>
>>>>>>>1. Because there can be more than 1 persistence.xml on the
>>>>>>>classpath,
>>>>>>>META-INF/orm.xml or any other mapping file referenced from a
>>>>>>>persistence.xml,
>>>>>>>must be 1st looked up in the PU root or in any jar file referenced
>>>>>>>from that
>>>>>>>persistence.xml. Otherwise we can get some other PU's mapping files
>>>>>>>that are
>>>>>>>accidentally on the classpath (is it a spec oversight that there is
>>>>>>>no PU name
>>>>>>>in the mapping file?).
>>>>>>>This is accomplished by steps 1 and 2 in
>>>>>>>PersistenceUnitProcessor.createInputStreamForFileInPersistenceUnit().
>>>>>>>
>>>>>>>
>>>>>>>2. In Tomcat the PU root is returned by a complicated URL that is
>>>>>>>handled by
>>>>>>>step 3 in the above method.
>>>>>>>
>>>>>>>The solution would be to add getResourceAsStream call as the 4th
>>>>>>>step, but it's
>>>>>>>not clear if we should attempt to do so for the default mapping file
>>>>>>>(META-INF/orm.xml).
>>>>>>>
>>>>>>>