persistence@glassfish.java.net

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

From: Tom Ware <tom.ware_at_oracle.com>
Date: Fri, 15 Sep 2006 08:52:56 -0400

Hi Marina,

  The TomCat issue really just relates to how we figure out if an XML
file is coming from a specific jar (or directory). The code we have
that deals with the URLs we get back from TomCat can just be put in the
method that makes that determination. I do not think it adds any more
complexity than that.

-Tom

Marina Vatkina wrote:

>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).
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>