I have a standalone appliaction packaged as a runnable jar. The jar is created from Eclipse with the "Package required libraries into generated JAR" option, dependencies of the project are manged with Maven. Running the jar I get the following exception
{noformat} avax.persistence.PersistenceException: Unable to locate persistence units at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilderOrNull(HibernatePersistenceProvider.java:95) ~[jar:rsrc:hibernate-core-5.2.12.Final.jar!/:?] at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilderOrNull(HibernatePersistenceProvider.java:71) ~[jar:rsrc:hibernate-core-5.2.12.Final.jar!/:?] at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:52) ~[jar:rsrc:hibernate-core-5.2.12.Final.jar!/:?] at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55) ~[jar:rsrc:hibernate-jpa-2.1-api-1.0.0.Final.jar!/:?] at it.commit.barbagli.automaamiacque.AmiacqueFlow.<init>(AmiacqueFlow.java:129) ~[rsrc:./:?] at it.commit.barbagli.automaamiacque.Application.main(Application.java:46) [rsrc:./:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_151] at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_151] at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_151] at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_151] at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58) [automaamiacque-win.jar:?] Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -1 at java.lang.String.substring(Unknown Source) ~[?:1.8.0_151] at org.hibernate.boot.archive.internal.ArchiveHelper.getJarURLFromURLEntry(ArchiveHelper.java:45) ~[jar:rsrc:hibernate-core-5.2.12.Final.jar!/:?] at org.hibernate.jpa.boot.internal.PersistenceXmlParser.parsePersistenceXml(PersistenceXmlParser.java:254) ~[jar:rsrc:hibernate-core-5.2.12.Final.jar!/:?] at org.hibernate.jpa.boot.internal.PersistenceXmlParser.doResolve(PersistenceXmlParser.java:233) ~[jar:rsrc:hibernate-core-5.2.12.Final.jar!/:?] at org.hibernate.jpa.boot.internal.PersistenceXmlParser.locatePersistenceUnits(PersistenceXmlParser.java:72) ~[jar:rsrc:hibernate-core-5.2.12.Final.jar!/:?] at org.hibernate.jpa.HibernatePersistenceProvider.getEntityManagerFactoryBuilderOrNull(HibernatePersistenceProvider.java:91) ~[jar:rsrc:hibernate-core-5.2.12.Final.jar!/:?] ... 10 more {noformat}
The final jar includes some classes from Eclipse to leverage a JarInJarLoader, which basically handles loading of jars included directly inside the resulting jar. This loader registers an rsrc: protocol which is considered by the Hibernate bootstrap process, so when it gets to the {noformat}ArchiveHelper.getJarURLFromURLEntry{noformat} at line 45 it tries to substring the "file" variable from beginning up to "file.lenght() - entry.length()" which is a negative number (exactly -1 as reported in the exception) because entry is the string "/META-INF/persistence.xml", while file is taken from the url "rsrc:/META-INF/persistence.xml" excluding getting the protocol file part of the url , thus resulting in "META-INF/persistence.xml" , ( without the initial "/" with respect to "entry" variable value) .
Is it possible to use hibernate from a runnable jar packaged this way? A warkaround workaround is to change package strategy to "Extract required libraries into generated JAR", but this mix libraries with actual user code, and I would prefer to keep them separated. |
|