Reputation: 2138
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
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