vaadin / flow

Vaadin Flow is a Java framework binding Vaadin web components to Java. This is part of Vaadin 10+.
Apache License 2.0
588 stars 164 forks source link

Production build fails if Spring Boot Application implements AppShellConfigurator and is annotated with a Spring Data JPA Repository #19616

Open leluna opened 1 week ago

leluna commented 1 week ago

Description of the bug

If the application class is used as AppShellConfigurator as in the starter project, the production build fails with NoClassDefFoundError: org/springframework/context/ApplicationEventPublisherAware if the application class is also annotated with @EnableJpaRepositories.

This happens only with profile production, but fails in the prepare-frontend goal that is executed before build-frontend.

The exception itself comes probably from the fact that the AppShellConfigurator class (or any class that is annotated with @Theme) is annotated with @EnableJpaRepository, which imports JpaRepositoryFactoryBean that ultimately implements ApplicationEventPublisherAware. However, why the class cannot be found is not not clear to me. Its dependency spring-context is included in the compile scope.

ApplicationEventPublisherAware has many implementations in Spring Security too.

More detailed stacktrace:

Caused by: java.lang.TypeNotPresentException: Type [unknown] not present at java.lang.reflect.Method.getDefaultValue (Method.java:724) at sun.reflect.annotation.AnnotationType.<init> (AnnotationType.java:133) at sun.reflect.annotation.AnnotationType.getInstance (AnnotationType.java:85) at sun.reflect.annotation.AnnotationParser.parseAnnotation2 (AnnotationParser.java:262) at sun.reflect.annotation.AnnotationParser.parseAnnotations2 (AnnotationParser.java:121) at sun.reflect.annotation.AnnotationParser.parseAnnotations (AnnotationParser.java:73) at java.lang.Class.createAnnotationData (Class.java:4068) at java.lang.Class.annotationData (Class.java:4057) at java.lang.Class.getAnnotationsByType (Class.java:3965) at com.vaadin.flow.internal.AnnotationReader.getAnnotationsFor (AnnotationReader.java:221) at com.vaadin.flow.server.frontend.scanner.FullDependenciesScanner.lambda$verifyTheme$5 (FullDependenciesScanner.java:383) at java.util.stream.ReferencePipeline$7$1.accept (ReferencePipeline.java:273) at java.util.Iterator.forEachRemaining (Iterator.java:133) at java.util.Spliterators$IteratorSpliterator.forEachRemaining (Spliterators.java:1845) at java.util.stream.AbstractPipeline.copyInto (AbstractPipeline.java:509) at java.util.stream.AbstractPipeline.wrapAndCopyInto (AbstractPipeline.java:499) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential (ReduceOps.java:921) at java.util.stream.AbstractPipeline.evaluate (AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect (ReferencePipeline.java:682) at com.vaadin.flow.server.frontend.scanner.FullDependenciesScanner.verifyTheme (FullDependenciesScanner.java:389) at com.vaadin.flow.server.frontend.scanner.FullDependenciesScanner.discoverTheme (FullDependenciesScanner.java:339) at com.vaadin.flow.server.frontend.scanner.FullDependenciesScanner.<init> (FullDependenciesScanner.java:131) at com.vaadin.flow.server.frontend.scanner.FullDependenciesScanner.<init> (FullDependenciesScanner.java:94) at com.vaadin.flow.server.frontend.scanner.FrontendDependenciesScanner$FrontendDependenciesScannerFactory.createScanner (FrontendDependenciesScanner.java:93) at com.vaadin.flow.server.frontend.NodeTasks.<init> (NodeTasks.java:125) at com.vaadin.flow.plugin.base.BuildFrontendUtil.prepareFrontend (BuildFrontendUtil.java:172) at com.vaadin.flow.plugin.maven.PrepareFrontendMojo.execute (PrepareFrontendMojo.java:64) at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126) at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328) at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174) at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75) at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162) at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:73) at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:53) at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:118) at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:261) at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:173) at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:101) at org.apache.maven.cli.MavenCli.execute (MavenCli.java:906) at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:283) at org.apache.maven.cli.MavenCli.main (MavenCli.java:206) at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:77) at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke (Method.java:568) at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:283) at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:226) at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:407) at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:348) Caused by: java.lang.NoClassDefFoundError: org/springframework/context/ApplicationEventPublisherAware at java.lang.ClassLoader.defineClass1 (Native Method) at java.lang.ClassLoader.defineClass (ClassLoader.java:1012) at java.security.SecureClassLoader.defineClass (SecureClassLoader.java:150) at java.net.URLClassLoader.defineClass (URLClassLoader.java:524

Expected behavior

No exception during production build.

Minimal reproducible example

Using the starter:

Execute mvn clean package -Pproduction and see the build fail.

Versions

mcollovati commented 1 week ago

My guess is that this happens because, even though the dependencies' scanner is using the project classpath, the maven plugin goal is executed within the plugin classpath.

mcollovati commented 1 week ago

Related draft PR #19010

mcollovati commented 1 week ago

Workaround should be moving the @EnableJpaRepositories on a separated @Configuration class

leluna commented 1 week ago

Another workaround would be to implement a separate class for AppShellConfigurator

enver-haase commented 4 days ago

I had the exact same problem in December 2021 with vaadin-maven-plugin:9.0.0 . The workaround from that time still applies when you comment it back in:

<plugin>
                                <groupId>com.vaadin</groupId>
                                <artifactId>vaadin-maven-plugin</artifactId>
                                <version>${vaadin.version}</version>
                                <!-- This is a problem with Vaadin 22.0.0; more exactly
                                vaadin-maven-plugin:9.0.0
                    and flow-maven-plugin:9.0.0 . The build-frontend step breaks without the
                    stanza below. -->
                                <!--dependencies>
                                        <dependency>
                                                <groupId>org.springframework</groupId>
                                                <artifactId>spring-context</artifactId>
                                                <version>5.3.13</version>
                                        </dependency>
                                </dependencies-->
                                <executions>
                                        <execution>
                                                <goals>
                                                        <goal>prepare-frontend</goal>
                                                </goals>
                                        </execution>
                                </executions>
                        </plugin>