Spring NoSuchBeanDefinitionException quando si passa a JPMS (Java Platform Module System)

Oct 02 2020

Sto cercando di migrare un grande progetto in JPMS (Java Platform Module System).

Contiene alcuni componenti Spring che mi stanno dando qualche problema. Ho creato un repository di prova per dimostrare il problema. Quando rimuovo il file module-info.java funziona perfettamente come mostrato dal test in TestControllerTest.java . Tuttavia, se aggiungo module-info.java, smette di funzionare con la seguente eccezione:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'RESTConfiguration': Unsatisfied dependency expressed through field 'fooAuthenticationProvider'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.spacemetric.spring.jpmstest.auth.FooAuthenticationProvider' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at [email protected]/org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)
at [email protected]/org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130)
at … 

L'analisi dello stack sembra indicare che ApplicationContextnon è in grado di trovare l' @Autowiredimplementazione. Ho aperto l'intero modulo per una riflessione profonda. La mia ipotesi altamente ignorante è che questo potrebbe essere correlato al percorso di classe rispetto a percorso modulepath, ma non so cosa fare al riguardo.

Il file module-info.java è il seguente:

open module com.spacemetric.spring.jpmstest {       
    requires spring.core;
    requires spring.context;
    requires spring.beans;
    requires spring.security.config;
    requires spring.security.web;
    requires spring.webmvc;
    requires spring.security.core;
    requires javax.servlet.api;
    requires spring.web;
}

Quanto segue è la riga di comando utilizzata da Eclipse per eseguire il test (come richiesto):

C: \ Programmi \ Java \ java-11-openjdk-11.0.7.10-1.windows.redhat.x86_64 \ bin \ javaw.exe -ea --add-opens com.spacemetric.spring.jpmstest / com.spacemetric. spring.jpmstest = ALL-UNNAMED --add-modules = ALL-MODULE-PATH -Dfile.encoding = UTF-8 -p "C: \ dev \ source \ spring-jpms-test \ target \ classes; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ spring-core \ 5.2.6.RELEASE \ spring-core-5.2.6.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ sicurezza \ spring-security-web \ 5.3.2.RELEASE \ spring-security-web-5.3.2.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ security \ spring-security- core \ 5.3.2.RELEASE \ spring-security-core-5.3.2.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ spring-bean \ 5.2.6.RELEASE \ spring- bean-5.2.6.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ spring-context \ 5.2.6.RELEASE \ spring-context-5.2.6.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ spring-web \ 5.2.6.RELEASE \ spring-web-5. 2.6.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ security \ spring-security-config \ 5.3.2.RELEASE \ spring-security-config-5.3.2.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ spring-webmvc \ 5.2.6.RELEASE \ spring-webmvc-5.2.6.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ javax \ servlet \ javax.servlet-api \ 3.1.0 \ javax.servlet-api-3.1.0.jar "-classpath" C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ spring-jcl \ 5.2 .6.RELEASE \ spring-jcl-5.2.6.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ spring-aop \ 5.2.6.RELEASE \ spring-aop-5.2.6 .RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ spring-expression \ 5.2.6.RELEASE \ spring-expression-5.2.6.RELEASE.jar; C: \ Users \ Oscar Haglund .m2 \ repository \ org \ junit \ jupiter \ junit-jupiter-engine \ 5.7.0 \ junit-jupiter-engine-5.7.0.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ apiguardian \ apiguardian -api \ 1.1.0 \ apiguardian-api-1.1.0.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ junit \ platform \ junit-platform-engine \ 1.7.0 \ junit-platform-engine-1.7.0.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ opentest4j \ opentest4j \ 1.2.0 \ opentest4j-1.2 .0.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ junit \ platform \ junit-platform-commons \ 1.7.0 \ junit-platform-commons-1.7.0.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ junit \ jupiter \ junit-jupiter-api \ 5.7.0 \ junit-jupiter-api-5.7.0.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ spring-test \ 5.2.6.RELEASE \ spring-test-5.2.6.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ restdocs \ spring-restdocs-mockmvc \ 2.0.5 .RELEASE \ spring-restdocs-mockmvc-2.0.5.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ springframework \ restdocs \ spring-restdocs-core \ 2.0.5.RELEASE \ spring-restdocs -core-2.0.5.RELEASE.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ com \ fastxml \ jackson \ core \ jackson-databind \ 2.9.5 \ jackson-databind-2.9.5.jar; C : \ Users \ Oscar Haglund.m2 \ repository \ com \ fastxml \ jackson \ core \ jackson-annotations \ 2.9.0 \ jackson-anno tations-2.9.0.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ com \ fastxml \ jackson \ core \ jackson-core \ 2.9.5 \ jackson-core-2.9.5.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ mockito \ mockito-junit-jupiter \ 3.5.10 \ mockito-junit-jupiter-3.5.10.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ mockito \ mockito-core \ 3.5.10 \ mockito-core-3.5.10.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ net \ bytebuddy \ byte-buddy \ 1.10.13 \ byte-buddy-1.10.13. jar; C: \ Users \ Oscar Haglund.m2 \ repository \ net \ bytebuddy \ byte-buddy-agent \ 1.10.13 \ byte-buddy-agent-1.10.13.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ objenesis \ objenesis \ 3.1 \ objenesis-3.1.jar; C: \ Users \ Oscar Haglund.m2 \ repository \ org \ junit \ platform \ junit-platform-launcher \ 1.7.0 \ junit-platform-launcher- 1.7.0.jar; C: \ dev \ eclipse \ configuration \ org.eclipse.osgi \ 259 \ 0.cp; C: \ dev \ eclipse \ configuration \ org.eclipse.osgi \ 257 \ 0.cp "- patch-module "com.spacemetric.spring.jpmstest = C: \ dev \ source \ spring-jpms-test \ target \ test-classes" --add-reads com.spacemetric.spring.jpmstest = ALL-UNNAMED org. eclipse.jdt.internal.junit.runner.RemoteTestRunner -version 3 -port 55245 -testLoaderClass org.eclipse.jdt.internal.junit5.runner.JUnit5TestLoader -loaderpluginname org.eclipse.jdt.junit5.rassemetric. .jpmstest.TestControllerTest

Risposte

1 Eugene Oct 02 2020 at 19:30

Prima di tutto metti module-info.javadentro src/main/java, non dentro src/test/java. Inoltre l'ho leggermente cambiato in:

module spring.jpms.test {
   requires spring.core;
   requires spring.context;
   requires spring.beans;
   requires spring.security.config;
   requires spring.security.web;
   requires spring.webmvc;
   requires spring.security.core;
   requires javax.servlet.api;
   requires spring.web;

   opens com.spacemetric.spring.jpmstest;

}

Ma comunque, questo risolve solo "parzialmente" perché:

Benvenuti in una realtà piuttosto cruda di modulese spring(o strumenti in generale). Dai un'occhiata qui, dove le persone hanno gli stessi problemi . L'unica soluzione praticabile che ho trovato è fare:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
    <configuration>
        <useModulePath>false</useModulePath>
    </configuration>
</plugin>

Funziona con mvn clean install(e junit5), non ho provato o giocato abbastanza intellijper farlo funzionare.