Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vaadin throws runtime exception for Java 21 preview features #18271

Closed
diversit opened this issue Dec 11, 2023 · 2 comments
Closed

Vaadin throws runtime exception for Java 21 preview features #18271

diversit opened this issue Dec 11, 2023 · 2 comments

Comments

@diversit
Copy link

diversit commented Dec 11, 2023

Description of the bug

When a Java 21 preview feature is used in a Vaadin page or component,
the code compiler successfully but fails at runtime with an exception.

Exception thrown by Quarkus application using Vaadin:

2023-12-11 11:57:55,600 ERROR [com.vaa.flo.ser.DefaultErrorHandler] (executor-thread-1) : java.lang.RuntimeException: java.lang.Error: Unresolved compilation problems:
	'_' is a keyword from source level 9 onwards, cannot be used as identifier
	'_' is a keyword from source level 9 onwards, cannot be used as identifier

	at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.invokeMethod(PublishedServerEventHandlerRpcHandler.java:234)
	at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.invokeMethod(PublishedServerEventHandlerRpcHandler.java:204)
	at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.invokeMethod(PublishedServerEventHandlerRpcHandler.java:150)
	at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.handleNode(PublishedServerEventHandlerRpcHandler.java:133)
	at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:74)
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:459)
	at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$2(ServerRpcHandler.java:440)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:440)
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:323)
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:114)
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1522)
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:398)
	at com.vaadin.quarkus.QuarkusVaadinServlet.service(QuarkusVaadinServlet.java:84)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)
	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
	at io.quarkus.micrometer.runtime.binder.vertx.VertxMeterBinderUndertowServletFilter.doFilter(VertxMeterBinderUndertowServletFilter.java:28)
	at jakarta.servlet.http.HttpFilter.doFilter(HttpFilter.java:97)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:63)
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:67)
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:133)
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:65)
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
	at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:247)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:56)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:111)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:108)
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$9$1.call(UndertowDeploymentRecorder.java:626)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:152)
	at io.undertow.server.handlers.CanonicalPathHandler.handleRequest(CanonicalPathHandler.java:49)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$1.handleRequest(UndertowDeploymentRecorder.java:125)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:284)
	at io.undertow.server.DefaultExchangeHandler.handle(DefaultExchangeHandler.java:18)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$5$2.run(UndertowDeploymentRecorder.java:441)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)

The exception thrown by the 'minimal reproducible example' is different but the underlying issue is the same I think. Difference may be caused by 'minimal reproducible example' failing directly on the 'MainView' while our application fails on a subview component.

As mentioned in 'minimal reproducible example', the error also occurs in the 'Vaadin Rest example' project using SpringBoot so the used application server is not relevant.

When building the 'production' build, Maven fails with

[ERROR] Failed to execute goal com.vaadin:vaadin-maven-plugin:24.2.5:build-frontend (default) on project restexampleapp: Could not execute build-frontend goal: Error occured during goal execution: Cannot invoke "java.lang.Class.isInterface()" because the return value of "org.reflections.Reflections.forClass(String, java.lang.ClassLoader[])" is null

This can be fixed by adding a .mvn/jvm.config file containing

--enable-preview

Then when running mvn package -P production is successful and the build application runs without errors.

However, this fix does not work when running the application in 'dev' mode either using mvn springboot:run or mvn quarkus:dev.

Expected behavior

The application should run without errors when using Java 21 preview features.

Minimal reproducible example

The issue is reproducible with the Vaadin Quarkus base starter project : https://github.com/vaadin/base-starter-flow-quarkus/
by applying these changes:

  • In pom.xml:
    • set compiler target and source from 17 to 21.
    • add property <maven.compiler.enablePreview>true</maven.compiler.enablePreview>
  • in MainView.java
    • on line 29, change event variable 'e' to '_' (underscore)

Run ./mvnw quarkus:dev

Git Diff:

diff --git a/pom.xml b/pom.xml
index 2d416f4..28900d1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,12 +9,13 @@
     <version>1.0-SNAPSHOT</version>
 
     <properties>
-        <maven.compiler.target>17</maven.compiler.target>
-        <maven.compiler.source>17</maven.compiler.source>
+        <maven.compiler.target>21</maven.compiler.target>
+        <maven.compiler.source>21</maven.compiler.source>
 
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 
+        <maven.compiler.enablePreview>true</maven.compiler.enablePreview>
         <maven.compiler.parameters>true</maven.compiler.parameters>
         <failOnMissingWebXml>false</failOnMissingWebXml>
 
diff --git a/src/main/java/com/example/starter/base/MainView.java b/src/main/java/com/example/starter/base/MainView.java
index 079f8aa..774f79c 100644
--- a/src/main/java/com/example/starter/base/MainView.java
+++ b/src/main/java/com/example/starter/base/MainView.java
@@ -25,7 +25,7 @@ public class MainView extends VerticalLayout {
         textField.addThemeName("bordered");
 
         // Button click listeners can be defined as lambda expressions
-        Button button = new Button("Say hello", e -> {
+        Button button = new Button("Say hello", _ -> {
             add(new Paragraph(greetService.greet(textField.getValue())));
         });

Application fails with:

2023-12-11 12:16:03,997 ERROR [io.qua.run.boo.StartupActionImpl] (Quarkus Main Thread) Error running Quarkus: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:118)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:104)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.ExceptionInInitializerError
	at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
	at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1160)
	at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.ensureClassInitialized(MethodHandleAccessorFactory.java:300)
	at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.newConstructorAccessor(MethodHandleAccessorFactory.java:103)
	at java.base/jdk.internal.reflect.ReflectionFactory.newConstructorAccessor(ReflectionFactory.java:200)
	at java.base/java.lang.reflect.Constructor.acquireConstructorAccessor(Constructor.java:549)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:70)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
	at io.quarkus.runner.GeneratedMain.main(Unknown Source)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	... 3 more
Caused by: java.lang.RuntimeException: Failed to start quarkus
	at io.quarkus.runner.ApplicationImpl.<clinit>(Unknown Source)
	... 16 more
Caused by: java.lang.UnsupportedClassVersionError: Preview features are not enabled for com/example/starter/base/MainView (class file version 65.65535). Try running with '--enable-preview'
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1027)
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:506)
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:466)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:534)
	at java.base/java.lang.Class.forName(Class.java:513)
	at com.example.starter.base.MainView_Bean.<init>(Unknown Source)
	at io.quarkus.arc.setup.Default_ComponentsProvider.addBeans1(Unknown Source)
	at io.quarkus.arc.setup.Default_ComponentsProvider.getComponents(Unknown Source)
	at io.quarkus.arc.impl.ArcContainerImpl.<init>(ArcContainerImpl.java:125)
	at io.quarkus.arc.Arc.initialize(Arc.java:39)
	at io.quarkus.arc.runtime.ArcRecorder.initContainer(ArcRecorder.java:47)
	at io.quarkus.deployment.steps.ArcProcessor$generateResources844392269.deploy_0(Unknown Source)
	at io.quarkus.deployment.steps.ArcProcessor$generateResources844392269.deploy(Unknown Source)
	... 17 more

Note: The same changes can be applied to the Vaadin-Rest-example project (https://github.com/vaadin/vaadin-rest-example) using SpringBoot and it fails with a similar exception.
Therefore concluding that the application server (SpringBoot or Quarkus) is not relevant for this issue.

Versions

  • Vaadin / Flow version:24.2.5 (latest)
  • Java version: 21 --enable-preview
  • OS version: MacOS Ventura 13.4
  • Browser version (if applicable): NA
  • Application Server (if applicable): Quarkus 3.3.x
  • IDE (if applicable): NA
@mcollovati
Copy link
Collaborator

Based on Quarkus docs, you need to configure the quarkus-maven-plugin and the MAVEN_OPTS environment variable to correctly run experimental features with mvn quarkus:dev https://quarkus.io/guides/maven-tooling#configuring-development-mode

Similarly, if you use the spring boot maven plugin to run the application, you have to configure it to enable the experimental features <jvmArguments>--enable-preview</jvmArguments>

@diversit
Copy link
Author

diversit commented Dec 11, 2023

Thanks!
I had the feeling it had to be some configuration somewhere, just couldn't figure out where.

I tried it out and can confirm that with those settings both Vaadin example projects and our project run fine with Java 21 preview features.

Note that for Quarkus to create a production build it requires MAVEN_OPTS='--enable-preview' or a .mvn/jvm.config file containing --enable-preview. I prefer the latter since that is simple to check in with the project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

No branches or pull requests

2 participants