zoran jeremic
zoran jeremic

Reputation: 2138

jar-file from persistence.xml is not found in eclipse

I have two maven projects in my eclipse workspace. First project has hibernate entities which should be used in the second project. I added it as dependency in the second project as:

<dependency>
        <groupId>org.prosolo</groupId>
        <artifactId>bigdata.common</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

I disabled workspace resolution so, bigdata.common-0.0.1-SNAPSHOT.jar is listed under Maven Dependencies. Furthermore, I configured persistence.xml to import this jar file:

<persistence-unit name="entityManager"
    transaction-type="RESOURCE_LOCAL">      
    <jar-file>lib/bigdata.common-0.0.1-SNAPSHOT.jar</jar-file>

However, when I run project from eclipse, EntityManager can't be initialized due to the following error:

Caused by: java.lang.IllegalArgumentException: File [lib/bigdata.common-0.0.1-SNAPSHOT.jar] referenced by given URL [file:lib/bigdata.common-0.0.1-SNAPSHOT.jar] does not exist

There is no problem if I run project from terminal or if I use absolute path to .jar file, but with relative path problem persists in Eclipse. I'm using maven-jetty-plugin to run application in both cases.

I've found this bug report https://hibernate.atlassian.net/browse/HHH-4161, but it seems that there is no solution for it.

I'm wondering if there is any solution for this problem, or if it's not possible to use jar-file, what other approach should I use to be able to use hibernate entities from other project with package scanning.

Thanks, Zoran

Upvotes: 1

Views: 2271

Answers (1)

Julien Kronegg
Julien Kronegg

Reputation: 5253

[EDIT] This issue has been solved in Hibernate 5.0.7, see HHH-4161.

This issue also occurs on Hibernate 5.0.2 and is planned to be solved in Hibernate 5.0.5, according to recent update on HHH-4161.

In this issue, I proposed a workaround based on a custom Scanner class which manages the relative URLs and absolutize them. I copied the AbstractScannerImpl source code into test.MyCustomScanner, added the constructors of StandardScanner, and added the following code in the environment.getNonRootUrls() loop:

if (!url.getPath().startsWith("/")) {
    // relative URL => make it processed relatively to the root URL of the META-INF/persistence.xml
    // This means that rootUrl has a META-INF directory (but the rootUrl has no META-INF in path).
    // See JPA 2.1 specification page 366-368: http://download.oracle.com/otn-pub/jcp/persistence-2_1-fr-eval-spec/JavaPersistence.pdf
    // Note: while the solution looks smart, the getNonRootUrls may include more
    // than the <jar-file>. Thus, it may have side effects.
    try {
        URL absoluteUrl = new URL(environment.getRootUrl(),url.getPath());
        url=absoluteUrl;
    } catch (MalformedURLException e) {
        throw new RuntimeException("cannot make the relative URL as absolute:"+url);
    }
}

The spirit is the same as Lauri Harpf's pull request (https://github.com/hibernate/hibernate-orm/pull/889/files), but with the priority given to the relative URL and using a relative URL test instead of an exception catching mechanism.

The risk with this approach is that all non root URLs are managed the same way, not only the ones of <jar-file> tags. Thus, side effects may appear. The custom scanner is then added to the persistence.xml:

<property name="hibernate.ejb.resource_scanner" value="test.MyCustomScanner" />

When run, the execution log shows no exception and only raises a concern that MyEntity table does not exist, which shows that the entities.jar has been processed correctly:

oct. 30, 2015 8:11:50 PM org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
    name: test-hibernate2
    ...]
oct. 30, 2015 8:11:51 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.0.2.Final}
oct. 30, 2015 8:11:51 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
oct. 30, 2015 8:11:51 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
oct. 30, 2015 8:11:51 PM org.hibernate.boot.internal.MetadataBuilderImpl$MetadataBuildingOptionsImpl <init>
INFO: HHH90000001: Found usage of deprecated setting for specifying Scanner [hibernate.ejb.resource_scanner]; use [hibernate.archive.scanner] instead
oct. 30, 2015 8:11:51 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.0.Final}
oct. 30, 2015 8:11:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH000402: Using Hibernate built-in connection pool (not for production use!)
oct. 30, 2015 8:11:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000401: using driver [org.hsqldb.jdbcDriver] at URL [jdbc:hsqldb:mem:testdb]
oct. 30, 2015 8:11:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000046: Connection properties: {user=sa}
oct. 30, 2015 8:11:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000006: Autocommit mode: false
oct. 30, 2015 8:11:51 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
oct. 30, 2015 8:11:51 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.HSQLDialect
oct. 30, 2015 8:11:52 PM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000228: Running hbm2ddl schema update
oct. 30, 2015 8:11:52 PM org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl processGetTableResults
INFO: HHH000262: Table not found: MyEntity
oct. 30, 2015 8:11:52 PM org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl processGetTableResults
INFO: HHH000262: Table not found: MyEntity

Another workaround I used in one of my previous customer was to build the list of <class> tags at build time based on the dependencies of the JARs in the application classpath. It looks a bit complex at first sight, but it gives a very good control on the application: developers can look in the persistence.xml to immediately know which entity classes will be loaded at runtime. Note that this approach was used in 2007, long before I thought about the custom Scanner workaround.

Upvotes: 1

Related Questions