Spring启动 - Eclipelink扫描orm.xml

时间:2014-08-15 02:18:45

标签: spring jpa eclipselink spring-boot

我正在将现有应用程序转换为spring引导,当我使用创建的jar运行应用程序时,我在扫描时发现异常并在我的实体jar中找到一个orm.xml(作为依赖项包含在内)。

org.eclipse.persistence.exceptions.PersistenceUnitLoadingException:
Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: org.springframework.boot.loader.LaunchedURLClassLoader@38cdedfd
Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [UAccessPersistenceUnit] failed.
Internal Exception: java.lang.RuntimeException: java.io.IOException: Unable to open root Jar file 'jar:file:everything-jar.jar'
        at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(PersistenceUnitLoadingException.java:127)
                at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactoryImpl(PersistenceProvider.java:107)
                        at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:177)
                                at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)


Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [UAccessPersistenceUnit] failed.
Internal Exception: java.lang.RuntimeException: java.io.IOException: Unable to open root Jar file 'jar:file:everything-jar.jar'
        at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.createPredeployFailedPersistenceException(EntityManagerSetupImpl.java:1954)
                at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:1945)
                        at org.eclipse.persistence.internal.jpa.deployment.JPAInitializer.callPredeploy(JPAInitializer.java:98)
                                at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactoryImpl(PersistenceProvider.java:96)
                                        ... 46 common frames omitted
                                        Caused by: org.eclipse.persistence.exceptions.EntityManagerSetupException:
                                        Exception Description: Predeployment of PersistenceUnit [UAccessPersistenceUnit] failed.
                                        Internal Exception: java.lang.RuntimeException: java.io.IOException: Unable to open root Jar file 'jar:file:everything-jar.jar'
                                                at org.eclipse.persistence.exceptions.EntityManagerSetupException.predeployFailed(EntityManagerSetupException.java:230)
                                                        ... 50 common frames omitted

这不是使用spring数据,我现在正在从外部属性文件构建数据源。扫描似乎会导致问题。

这是使用eclipselink 2.5.1的春季启动1.1.5-RELEASE

everything-jar.jar是一个春季启动包装罐。使用我的编译类,弹簧启动加载程序和包装在jar中的实体。我已经标记了要解压缩的依赖性并且它有效,但它并不理想。

这个问题不断出现,现在如果我尝试从另一个jar加载persistence.xml,它会抛出同样的异常。

1 个答案:

答案 0 :(得分:0)

经过大量调查后,问题似乎有两个部分。

  1. spring boot loader支持看起来像这样的url: 罐子:文件:!/ /

  2. Eclipselink为嵌入式orm.xml文件生成URL,如下所示 罐子:罐子:文件:!/ /

  3. 我在弹簧启动时得到了一个修复,以便更好地打开eclipselink URL,但是为了立即修复,我们需要创建一个自定义ArchiveFactoryImpl并覆盖createArchive方法,以便在协议为时返回自定义JarInputStreamURLArchive广口瓶中。

    在这个自定义类中,将get条目覆盖为URL,以检查具有以jar开头的jar协议的url,并从原始文件创建一个新URL(这会从原始URL中删除协议部分us jar:url而不是jar:url:url

    public URL getEntryAsURL(String entryPath) throws IOException {
                URL entryUrl = super.getEntryAsURL(entryPath);
    
                if(entryUrl == null) {
                    return null;
                }
    
                if("jar".equals(entryUrl.getProtocol()) && entryUrl.getFile().startsWith("jar:")) {
                    //cut off the jar portions
                    String file = entryUrl.getFile();
                    return new URL(file);
                } else {
                    return entryUrl;
                }
            }