[jboss-jira] [JBoss JIRA] (AS7-5062) PersistenceUnitRootURL for JPA providers may not be spec compliant
Craig Ringer (JIRA)
jira-events at lists.jboss.org
Fri Jul 6 04:24:12 EDT 2012
[ https://issues.jboss.org/browse/AS7-5062?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12704750#comment-12704750 ]
Craig Ringer edited comment on AS7-5062 at 7/6/12 4:23 AM:
-----------------------------------------------------------
It took me a bit of time to find out the answer to how EclipseLink is choking on the persistence unit root. It turns out that it does in fact check the protocol explicitly in org.eclipse.persistence.internal.jpa.deployment.ArchiveFactoryImpl using URL.getProtocol() and looking for "jar" or "file".
If neither are found it tries to open the URL as an input stream using ArchiveFactoryImpl.isJarInputStream() , which calls url.openStream(), getting a valid org.jboss.vfs.VirtualJarInputStream, which it wraps in a java.util.jar.JarInputStream and calls JarInputStream.getNextEntry() on. This call returns null, so EclipseLink decides it can't iterate through the contents of the archive.
Failing all else, it falls back to return a org.eclipse.persistence.internal.jpa.deployment.URLArchive if its various container-specific hacks and heuristics can't work out a more specific archive adapter to use. The comment on URLArchive says:
{quote}
* This is an implementation of {@link Archive} when container returns a url
* that is not one of the familiar URL types like file or jar URLs. So, we can
* not recursively walk thru' its hierarchy. As a result {@link #getEntries()}
* returns an empty collection.
{quote}
Here's the ArchiveFactory code that makes the decision about the archive adapter to use:
{code}
package org.eclipse.persistence.internal.jpa.deployment;
public class ArchiveFactoryImpl implements ArchiveFactory {
// ...
public Archive createArchive(URL rootUrl, String descriptorLocation, Map properties) throws URISyntaxException, IOException {
// ...
String protocol = rootUrl.getProtocol();
if ("file".equals(protocol)) {
// ...
} else if ("jar".equals(protocol)) {
// ...
} else if (isJarInputStream(rootUrl)){
result = new JarInputStreamURLArchive(rootUrl, descriptorLocation);
} else {
result = new URLArchive(rootUrl, descriptorLocation);
}
}
}
{code}
Here's the complete code for ArchiveFactoryImpl.isJarInputStream:
{code}
/**
* This method is called for a URL which has neither jar nor file protocol.
* This attempts to find out if we can treat it as a URL from which a JAR
* format InputStream can be obtained.
* @param url
*/
protected boolean isJarInputStream(URL url) throws IOException {
InputStream in = null;
try {
in = url.openStream();
if (in == null) { // for directories, we may get InputStream as null
return false;
}
JarInputStream jis = null;
try {
jis = new JarInputStream(in);
if (jis.getNextEntry() == null){// if there is no next entry, this jar stream can't be used
return false;
}
return true; // we are successful in creating a Jar format IS
} finally {
if (jis != null){
jis.close();
}
}
} catch (IOException ioe) {
if (in != null) {
in.close();
}
return false;
}
}
{code}
was (Author: ringerc):
It took me a bit of time to find out the answer to how, exactly, EclipseLink is choking on the persistence unit root. It does, indeed, check the protocol explicitly in org.eclipse.persistence.internal.jpa.deployment.ArchiveFactoryImpl . It falls back to return a org.eclipse.persistence.internal.jpa.deployment.URLArchive if its various container-specific hacks and heuristics can't work out a more specific archive adapter to use. The comment on URLArchive says:
{quote}
* This is an implementation of {@link Archive} when container returns a url
* that is not one of the familiar URL types like file or jar URLs. So, we can
* not recursively walk thru' its hierarchy. As a result {@link #getEntries()}
* returns an empty collection.
{quote}
Here's the ArchiveFactory code that makes the decision about the archive adapter to use:
{code}
package org.eclipse.persistence.internal.jpa.deployment;
public class ArchiveFactoryImpl implements ArchiveFactory {
// ...
public Archive createArchive(URL rootUrl, String descriptorLocation, Map properties) throws URISyntaxException, IOException {
// ...
String protocol = rootUrl.getProtocol();
if ("file".equals(protocol)) {
// ...
} else if ("jar".equals(protocol)) {
// ...
} else if (isJarInputStream(rootUrl)){
result = new JarInputStreamURLArchive(rootUrl, descriptorLocation);
} else {
result = new URLArchive(rootUrl, descriptorLocation);
}
}
}
{code}
> PersistenceUnitRootURL for JPA providers may not be spec compliant
> ------------------------------------------------------------------
>
> Key: AS7-5062
> URL: https://issues.jboss.org/browse/AS7-5062
> Project: Application Server 7
> Issue Type: Bug
> Components: JPA / Hibernate
> Affects Versions: 7.1.1.Final
> Environment: $ java -version
> java version "1.7.0_03-icedtea"
> OpenJDK Runtime Environment (fedora-2.2.1.fc17.8-x86_64)
> OpenJDK 64-Bit Server VM (build 23.0-b21, mixed mode)
> $ uname -a
> Linux ayaki.localdomain 3.4.2-4.fc17.x86_64 #1 SMP Thu Jun 14 22:22:05 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
> Reporter: Craig Ringer
> Assignee: Scott Marlow
> Labels: compatibility, eclipselink, jpa, spec
>
> Discussion on the EclipseLink bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=383200 ("On JBoss AS 7, EclipseLink doesn't find entity classes unless they're explicitly listed in persistence.xml") suggests that JBoss AS 7 may not be providing a spec-compliant PersistenceUnitRootURL or contents.
> EclipseLink can't scan the contents of a deployment for @Entity annotated classes, so it doesn't find any entities unless they're explicitly named in persistence.xml .
> http://docs.oracle.com/javaee/6/api/javax/persistence/spi/PersistenceUnitInfo.html#getPersistenceUnitRootUrl() states:
> {quote}
> java.net.URL getPersistenceUnitRootUrl()
> Returns the URL for the jar file or directory that is the root of the persistence unit. (If the persistence unit is rooted in the WEB-INF/classes directory, this will be the URL of that directory.) The URL will either be a file: URL referring to a jar file or referring to a directory that contains an exploded jar file, or some other URL from which an InputStream in jar format can be obtained.
> *Returns*: a URL referring to a jar file or directory
> {quote}
> ... and that's what EclipseLink expects. However, for EclipseLink class scanning to function correctly an adapter class must be provided, such as the classes provided here:
> https://community.jboss.org/wiki/HowToUseEclipseLinkWithAS7
> to integrate EclipseLink with JBoss's VFS.
> It may be worth investigating why this is necessary and whether the current behavior is standards compliant.
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.jboss.org/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira
More information about the jboss-jira
mailing list