web-dev-qa-db-ja.com

module-info.Javaが存在する場合、findResource( "")がnullを返します。なぜですか?

Spring Bootアプリケーションに_module-info.Java_が存在する場合、_spring-orm_が起動時に例外をスローする理由をデバッグしています。これは例外です。

_org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is Java.lang.NoClassDefFoundError: javax/transaction/UserTransaction
    at [email protected]/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1699) ~[spring-beans-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:573) ~[spring-beans-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.Java:495) ~[spring-beans-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.Java:317) ~[spring-beans-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.Java:222) ~[spring-beans-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:315) ~[spring-beans-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:199) ~[spring-beans-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.Java:1089) ~[spring-context-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.Java:859) ~[spring-context-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:550) ~[spring-context-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.Java:140) ~[spring-boot-2.0.4.RELEASE.jar:na]
    at [email protected]/org.springframework.boot.SpringApplication.refresh(SpringApplication.Java:762) [spring-boot-2.0.4.RELEASE.jar:na]
    at [email protected]/org.springframework.boot.SpringApplication.refreshContext(SpringApplication.Java:398) [spring-boot-2.0.4.RELEASE.jar:na]
    at [email protected]/org.springframework.boot.SpringApplication.run(SpringApplication.Java:330) [spring-boot-2.0.4.RELEASE.jar:na]
    at [email protected]/org.springframework.boot.SpringApplication.run(SpringApplication.Java:1258) [spring-boot-2.0.4.RELEASE.jar:na]
    at [email protected]/org.springframework.boot.SpringApplication.run(SpringApplication.Java:1246) [spring-boot-2.0.4.RELEASE.jar:na]
    at tech.flexpoint.dashmanserver/tech.flexpoint.dashmanserver.DashmanServerApplication.main(DashmanServerApplication.Java:13) [classes/:na]
    at Java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at Java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:62) ~[na:na]
    at Java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43) ~[na:na]
    at Java.base/Java.lang.reflect.Method.invoke(Method.Java:564) ~[na:na]
    at [email protected]/org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.Java:49) [spring-boot-devtools-2.0.4.RELEASE.jar:na]
Caused by: Java.lang.NoClassDefFoundError: javax/transaction/UserTransaction
    at Java.base/Java.lang.Class.getDeclaredMethods0(Native Method) ~[na:na]
    at Java.base/Java.lang.Class.privateGetDeclaredMethods(Class.Java:3119) ~[na:na]
    at Java.base/Java.lang.Class.privateGetPublicMethods(Class.Java:3144) ~[na:na]
    at Java.base/Java.lang.Class.getMethods(Class.Java:1863) ~[na:na]
    at [email protected]/org.hibernate.service.internal.AbstractServiceRegistryImpl.applyInjections(AbstractServiceRegistryImpl.Java:288) ~[hibernate-core-5.2.17.Final.jar:na]
    at [email protected]/org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.Java:279) ~[hibernate-core-5.2.17.Final.jar:na]
    at [email protected]/org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.Java:239) ~[hibernate-core-5.2.17.Final.jar:na]
    at [email protected]/org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.Java:210) ~[hibernate-core-5.2.17.Final.jar:na]
    at [email protected]/org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.getService(SessionFactoryServiceRegistryImpl.Java:80) ~[hibernate-core-5.2.17.Final.jar:na]
    at [email protected]/org.hibernate.internal.SessionFactoryImpl.canAccessTransactionManager(SessionFactoryImpl.Java:942) ~[hibernate-core-5.2.17.Final.jar:na]
    at [email protected]/org.hibernate.internal.SessionFactoryImpl.buildCurrentSessionContext(SessionFactoryImpl.Java:953) ~[hibernate-core-5.2.17.Final.jar:na]
    at [email protected]/org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.Java:319) ~[hibernate-core-5.2.17.Final.jar:na]
    at [email protected]/org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.Java:462) ~[hibernate-core-5.2.17.Final.jar:na]
    at [email protected]/org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.Java:892) ~[hibernate-core-5.2.17.Final.jar:na]
    at [email protected]/org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.Java:57) ~[spring-orm-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.Java:365) ~[spring-orm-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.Java:390) ~[spring-orm-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.Java:377) ~[spring-orm-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.Java:341) ~[spring-orm-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.Java:1758) ~[spring-beans-5.0.8.RELEASE.jar:na]
    at [email protected]/org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1695) ~[spring-beans-5.0.8.RELEASE.jar:na]
    ... 21 common frames omitted
Caused by: Java.lang.ClassNotFoundException: javax.transaction.UserTransaction
    at Java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.Java:582) ~[na:na]
    at Java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.Java:190) ~[na:na]
    at Java.base/Java.lang.ClassLoader.loadClass(ClassLoader.Java:499) ~[na:na]
    ... 42 common frames omitted
_

_module-info.Java_が存在する場合はnullを返し、存在しない場合は_"file:/C:/Users/pupeno/Documents/Dashman/code/dashmanserver/target/classes/"_を返すURLClassLoader.findResource("")に問題を追跡しました。

同じ例外をスローする最小限の例を作成しました。実行するには、次のことが必要です。

  1. ここからModitectの最近のコピーをクローンしてインストールします: https://github.com/moditect/moditect このバグ修正がまだ出ていないため https://github.com/moditect/moditect/issues/51
  2. デモリポジトリのクローンを作成します: https://github.com/dashmantech/demo
  3. 資格情報demo/confi/application.propertiesを使用してローカルPostgreSQLデータベースをセットアップします
  4. 最初に_mvn clean package_を実行して、ModiTecがすべてのモジュールを作成するようにします
  5. IntelliJの最近のコピーでプロジェクトを開きます
  6. 「デモの実行」プロファイルの再生をクリックします(_.idea_ディレクトリは、適切な実行プロファイル、引数などに含まれています)。

_"file:/C:/Users/pupeno/Documents/Dashman/code/dashmanserver/target/classes/"_が機能するには、findResource("")が_spring-orm_を返す必要があります。

findResource("")は次のようになります。

_public URL findResource(final String name) {
    /*
     * The same restriction to finding classes applies to resources
     */
    URL url = AccessController.doPrivileged(
        new PrivilegedAction<>() {
            public URL run() {
                return ucp.findResource(name, true);
            }
        }, acc);

    return url != null ? URLClassPath.checkURL(url) : null;
}
_

そのため、モジュールシステムを使用せずにアクセスできることがありますが、_module-infe.Java_が存在する場合、Javaのモジュールシステムによって防止されます。私の問題は、それを機能させる方法がわからないということです。それを機能させるには、何をエクスポートまたは開く必要がありますか?

Spring Bootがそのメソッドの呼び出しを引き起こす方法は、RestartClassLoaderのサブクラスであるURLClassLoader、具体的にはsuper.findResource(name)を呼び出す124行目です。

_@Override
public URL findResource(String name) {
    final ClassLoaderFile file = this.updatedFiles.getFile(name);
    if (file == null) {
        return super.findResource(name);
    }
    if (file.getKind() == Kind.DELETED) {
        return null;
    }
    return AccessController
            .doPrivileged((PrivilegedAction<URL>) () -> createFileUrl(name, file));
}
_

使用されている特定のRestartClassLoaderインスタンスはClassPathResourceのメンバーであり、次のように定義されています。

_this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
_

コンストラクターでは、 85行目

最後に、getDefaultClassLoader()は次のようになります。

_/**
 * Return the default ClassLoader to use: typically the thread context
 * ClassLoader, if available; the ClassLoader that loaded the ClassUtils
 * class will be used as fallback.
 * <p>Call this method if you intend to use the thread context ClassLoader
 * in a scenario where you clearly prefer a non-null ClassLoader reference:
 * for example, for class path resource loading (but not necessarily for
 * {@code Class.forName}, which accepts a {@code null} ClassLoader
 * reference as well).
 * @return the default ClassLoader (only {@code null} if even the system
 * ClassLoader isn't accessible)
 * @see Thread#getContextClassLoader()
 * @see ClassLoader#getSystemClassLoader()
 */
@Nullable
public static ClassLoader getDefaultClassLoader() {
    ClassLoader cl = null;
    try {
        cl = Thread.currentThread().getContextClassLoader();
    }
    catch (Throwable ex) {
        // Cannot access thread context ClassLoader - falling back...
    }
    if (cl == null) {
        // No thread context class loader -> use class loader of this class.
        cl = ClassUtils.class.getClassLoader();
        if (cl == null) {
            // getClassLoader() returning null indicates the bootstrap ClassLoader
            try {
                cl = ClassLoader.getSystemClassLoader();
            }
            catch (Throwable ex) {
                // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
            }
        }
    }
    return cl;
}
_

私の_module-info.Java_の内容:

_module tech.flexpoint.dashman {
    exports tech.flexpoint.dashman to com.fasterxml.jackson.databind;
    exports tech.flexpoint.dashman.controllers.configurator to javafx.fxml;

    opens tech.flexpoint.dashman to javafx.graphics, jna;
    opens tech.flexpoint.dashman.controllers.common to javafx.fxml;
    opens tech.flexpoint.dashman.controllers.configurator to javafx.fxml;
    opens tech.flexpoint.dashman.models to org.hibernate.validator, tech.flexpoint.dashmancommon, javafx.base;

    opens common;
    opens configurator;
    opens displayer;
    opens winscreensaver;

    requires appdirs;
    requires org.bouncycastle.provider;
    requires com.fasterxml.jackson.core;
    requires com.fasterxml.jackson.databind;
    requires com.fasterxml.jackson.datatype.jdk8;
    requires io.sentry;
    requires jackson.annotations;
    requires Java.desktop;
    requires Java.sql;
    requires Java.validation;
    requires javafx.controls;
    requires javafx.fxml;
    requires javafx.graphics;
    requires javafx.media;
    requires javafx.web;
    requires jna;
    requires jna.platform;
    requires org.Apache.commons.lang3;
    requires org.kordamp.ikonli.javafx;
    requires org.kordamp.ikonli.fontawesome5;
    requires spring.core;
    requires spring.retry;
    requires spring.web;
    requires tech.flexpoint.dashmancommon;
}
_

IntelliJでは、これらのプラグインを有効にしています:

  • ロンボクプラグイン
  • .ginore
  • パワーシェル
  • VisualVMランチャー
  • ANSI蛍光ペン
  • バッチスクリプトのサポート
  • バイトコードビューア
  • CMDサポート
  • 著作権
  • カバレッジ
  • CSSサポート
  • データベースツールとSQL
  • Git統合
  • GitHub
  • グラドル
  • グルーヴィー
  • Herokuの統合
  • HTMLツール
  • HTTPクライアント
  • javaのl18n
  • IDE設定の同期
  • Java Bytecode Decompiler
  • Java EE:EJB、JPA、サーブレット
  • Java Streamデバッガー
  • JavaFX
  • JUnit
  • 行ソーター
  • マークダウンのサポート
  • Maven統合
  • Maven統合拡張機能
  • 持続性フレームワークのサポート
  • プロパティのサポート
  • スマリのサポート
  • Spring AOP/@ AspectJ
  • 春バッチ
  • 春のブーツ
  • 春のデータ
  • 春の統合パターン
  • Spring OSGi
  • 春のセキュリティ
  • 春のサポート
  • Spring Webサービス
  • Spring WebSocket
  • ターミナル
  • YAML
50
pupeno

依存関係を宣言したと仮定します。

<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>javax.transaction-api</artifactId>
    <version>1.3</version>
</dependency>

module-info.Javaに次を含めます。

requires Java.transaction;

バージョン1.3は自動モジュール名を宣言しますが、バージョン1.2は宣言しません。
後者のrequires javax.transaction.api;。 ソース

3

元の問題で述べたように、コードはmodule-info.Javaがなくても機能しますが、module-info.Javaは機能しません。問題を説明し、最小限のプロジェクトを作成するなど、問題にドリルダウンするために、あなたがこのすべてのハードワークを行ったことがわかります。

あなたの問題を見ると、モジュールの1つがURLClassLoader.findResource("")nullを返していることが明らかです。リストの下のモジュールの1つがこのクラスメソッドをオーバーライドしている場合や、実装があいまいな場合があります。

最小限の例では空のmodule-info.Javaから始めて、エラーが表示されるまで一度に1つのモジュールを追加し続けてみませんか?これは犯人を見つける助けになると思います。

1
Rinsad Ahmed

この(または同様の)問題は、既に GitHub のspring-bootで申請されていました(ただし、Java 9)で。

私は疑いで moditect を持っていますが、moditect on GitHubに提出された問題もあります そしてあなたの issue も見つけました; ASMを6.2.1に更新すると、少なくとも1つの重大な変更が修正されます。

<dependency>
    <groupId>org.ow2.asm</groupId>
    <artifactId>asm</artifactId>
    <version>6.2.1</version>
</dependency>
0
Martin Zeitler