Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 326728

Summary: Computed root URL for META-INF/persistence.xml inside a war-file is wrong
Product: z_Archived Reporter: Nick M <nick>
Component: EclipselinkAssignee: Nobody - feel free to take it <nobody>
Status: NEW --- QA Contact:
Severity: normal    
Priority: P2 CC: allee8285, eclipselink.orm-inbox, michael.f.obrien, nigredo.tori, patric, tom.ware
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: All   
See Also: https://github.com/eclipse-ee4j/eclipselink/pull/220
Whiteboard:
Bug Depends on: 307105, 335575    
Bug Blocks: 304363    

Description Nick M CLA 2010-09-30 20:22:19 EDT
Build Identifier: 2.1.1.v20100817-r8050

In class:
org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor
... function:
computePURootURL(URL pxmlURL, String descriptorLocation)

In my situation it is passed the following URL:
jar:file:/xxx/myapp.war!/WEB-INF/classes/META-INF/persistence.xml

The result root URL should be:
jar:file:/xxx/myapp.war!/WEB-INF/classes

But instead the function returns:
file:/xxx/myapp.war

The code seems to assume that the persistence unit root is the same as JAR file root. Unless I am missing something, in WAR files that's not the case.

Dug up this random article about that distinction: http://javahowto.blogspot.com/2007/06/where-to-put-persistencexml-in-web-app.html

Otherwise, my NetBeans is packaging the WAR file incorrectly.

Either way, this results in a "java.net.MalformedURLException": the code down the line is trying to look for "META-INF/persistence.xml" directly under the WAR file root being returned by this method instead of under WAR file's "WEB-INF/classes" sub-directory.

NOTE: bug 304363 reports a MalformedURLException, but it deals with a situation when there is NO persistence.xml file, period. In my case, the file is actually being found, but the root URL is mis-calculated and botched afterwards.

SUGGESTED FIX:

Deal with any "jar:" URL just like "file:" URLs are already dealt with (go up N levels in directory hierarchy depending on "descriptorLocation" path depth). Sorry, no patch.

MY WORKAROUND FOR NOW:

Modify NetBeans build process to duplicate the persistence.xml into a "META-INF" directory straight under WAR root.

For anyone reading, alternative workaround may be to compile the entities and persistence unit into a separate JAR and either deploy an EAR or add the entity JAR into the WAR file "WEB-INF/lib" directory.

NOTE: these workarounds are not too bad, but the JPA spec is still being broken, so this is probably a non-trivial priority.

Thanks!


Reproducible: Always

Steps to Reproduce:
My web-app explicitly calls "Persistence.createEntityManagerFactory(unitName)" in its init method. The web-app's WAR file (containing "WEB-INF/classes/META-INF/persistence.xml" as necessary) is deployed into a vanilla Jetty instance with all the appropriate EclipseLink JARs in its classpath.

NOTE: deploying the same app as an unzipped directory *works* (since the logic for "file:" URLs is different). This is probably why the bug does not show up in 99% of app servers out there - they all "explode" the WAR file during deployment instead of using the pure JAR URL approach.
Comment 1 Tom Ware CLA 2010-10-07 13:18:39 EDT
What app server are you running on?
Comment 2 Nick M CLA 2010-10-11 11:15:11 EDT
This was in:
jetty-hightide-7.1.6.v20100715

I just used the standard vanilla distribution of it.

Thanks!
Nick
Comment 3 Tom Ware CLA 2010-10-14 13:23:50 EDT
Setting target and priority.  See the following page for details of the meanings of these fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines
Comment 4 Michael OBrien CLA 2010-11-26 16:09:38 EST
>This similar to bug # 307105 but different enough to not dup it.
This one is specific to a PU outside the ejb-jar but in the war, the other bug is both an EE and SE case
Comment 5 Michael OBrien CLA 2010-11-30 09:52:35 EST
>looking at this Jetty issue as an auxillary to bug # 307105 (no target yet)
- we currently do not have a platform for the web-only (no ejb container) Jetty platform (the closest is NoServerPlatform (SE)
Comment 6 Patric Rufflar CLA 2012-01-25 11:08:15 EST
Same or similar problem here with a RESOURCE_LOCAL persistence unit.
EclipseLink 2.1.3 fails _randomly_ (50% chance) on jetty 7.x. (it dependents on iteration order of a HashSet)

The interesting thing is that EclipseLink determines two possible Archive objects within JPAInitialzer.findPersistenceUnitInfoInArchives(String puName, Map m, PersistenceInitializationHelper persistenceHelper):

One is a DirectoryArchive which contains the URL 
file:/tmp/jetty-0.0.0.0-21080-mywar.war-_mywar-any-/webinf/WEB-INF/classes/

The other is JarFileArchive which contains the URL
file:/home/user/path/to/mywar.war

The JarFileArchive fails, the DirectoryArchive works.
If the DirectoryArchive is returned first by the HashSet iterator, EclipseLink will work, if not, it will crash:


Internal Exception: java.net.MalformedURLException
        at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionLoadingFromUrl(PersistenceUnitLoadingException.java:99)
        at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processPersistenceArchive(PersistenceUnitProcessor.java:453)
        at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.getPersistenceUnits(PersistenceUnitProcessor.java:361)
        at org.eclipse.persistence.internal.jpa.deployment.JPAInitializer.findPersistenceUnitInfoInArchive(JPAInitializer.java:156)
        at org.eclipse.persistence.internal.jpa.deployment.JPAInitializer.findPersistenceUnitInfoInArchives(JPAInitializer.java:143)
        at org.eclipse.persistence.internal.jpa.deployment.JPAInitializer.findPersistenceUnitInfo(JPAInitializer.java:125)
        at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:98)
        ... 44 more
Caused by: Exception [EclipseLink-30004] (Eclipse Persistence Services - 2.1.3.v20110304-r9073): org.eclipse.persistence.exceptions.PersistenceUnitLoadingException
Exception Description: An exception was thrown while processing persistence.xml from URL: file:/home/user/path/to/mywar.war
Internal Exception: java.net.MalformedURLException
        at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionProcessingPersistenceXML(PersistenceUnitLoadingException.java:117)
        at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processPersistenceXML(PersistenceUnitProcessor.java:494)
        at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processPersistenceArchive(PersistenceUnitProcessor.java:451)
        ... 49 more
Caused by: java.net.MalformedURLException
        at java.net.URL.<init>(URL.java:601)
        at java.net.URL.<init>(URL.java:464)
        at java.net.URL.<init>(URL.java:413)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:650)
        at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:186)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:772)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
        at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processPersistenceXML(PersistenceUnitProcessor.java:492)
        ... 50 more
Comment 7 Albert Lee CLA 2014-03-18 11:10:10 EDT
I ran into the same problem using WebSphere Liberty app server.

I attempted the following patch and it seems to resolve the problem, but there may be other better solution to the problem:

public class ArchiveFactoryImpl implements ArchiveFactory {
 ....
 public Archive createArchive(URL rootUrl, String descriptorLocation, Map properties) throws URISyntaxException, IOException {
  ....
   } else if ("jar".equals(protocol)) { // NOI18N
    ....
    if (e == null) {
     ....
     // ****  PATCH BEGIN  ****
     if (descriptorLocation != null &&
         rootUrl.getPath().endsWith(".war!/") &&
         !descriptorLocation.startsWith("WEB-INF/classes")) {
	   descriptorLocation = "WEB-INF/classes/" + descriptorLocation;
     }
     // ****  PATCH END  ****
     result = new JarFileArchive(rootUrl, conn.getJarFile(), descriptorLocation);
     ....
Comment 8 Dmitry Polienko CLA 2018-08-17 06:54:41 EDT
Hit this bug (or something close to it) today. I had a weird setup like this:

1. A JAR (or a directory in development environment).
2. Some bootstrapping code in it (launching embedded Jetty with the web application).
3. Web application resources in /webapp inside it.
4. Web application classes in /webapp/WEB-INF/classes.
5. /webapp/WEB-INF/classes/META-INF/persistence.xml.

As a result, weaving worked as expected in development environment (persistence root resolved to /foo/bar/webapp/WEB-INF/classes), but failed when running from a JAR (persistence root at /foo/bar.jar).
Comment 9 Eclipse Genie CLA 2018-08-20 07:18:50 EDT
GitHub Pull Request 220 created by [nigredo-tori]
https://github.com/eclipse-ee4j/eclipselink/pull/220
Comment 10 Eclipse Webmaster CLA 2022-06-09 10:32:51 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink