quarkiverse/quarkus-groovy

@CompileStatic breaks devmode restart

Closed this issue · 8 comments

Editing a groovy class with @CompileStatic annotation in dev mode leads to "Error restarting Quarkus" with stacktrace listed below. Restart succeeds when the @CompileStatic annotation is removed.

The stacktrace originates from the included reactive-routes example so the problem is easy to reproduce by editing the return value of MyDeclarativeRoutes#hello-route in dev mode.

io.vertx.core.impl.NoStackTraceException
Caused by: java.lang.RuntimeException: startup failed:
/<redacted>/quarkus-groovy/examples/reactive-routes/src/main/groovy/org/acme/MyDeclarativeRoutes.groovy: Not an ASTTransformation: org.codehaus.groovy.transform.sc.StaticCompileTransformation declared by groovy.transform.CompileStatic

/<redacted>/quarkus-groovy/examples/reactive-routes/src/main/groovy/org/acme/MyDeclarativeRoutes.groovy: AST transformation implementation classes must be annotated with org.codehaus.groovy.transform.GroovyASTTransformation. org.codehaus.groovy.transform.sc.StaticCompileTransformation lacks this annotation.

General error during conversion: Cannot invoke "org.codehaus.groovy.transform.GroovyASTTransformation.phase()" because "transformationClass" is null

java.lang.NullPointerException: Cannot invoke "org.codehaus.groovy.transform.GroovyASTTransformation.phase()" because "transformationClass" is null
	at org.codehaus.groovy.transform.ASTTransformationCollectorCodeVisitor.verifyAndAddTransform(ASTTransformationCollectorCodeVisitor.java:291)
	at org.codehaus.groovy.transform.ASTTransformationCollectorCodeVisitor.lambda$addTransformsToClassNode$3(ASTTransformationCollectorCodeVisitor.java:256)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:1024)
	at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at org.codehaus.groovy.transform.ASTTransformationCollectorCodeVisitor.addTransformsToClassNode(ASTTransformationCollectorCodeVisitor.java:256)
	at org.codehaus.groovy.transform.ASTTransformationCollectorCodeVisitor.visitAnnotations(ASTTransformationCollectorCodeVisitor.java:112)
	at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:49)
	at org.codehaus.groovy.transform.ASTTransformationCollectorCodeVisitor.visitClass(ASTTransformationCollectorCodeVisitor.java:77)
	at org.codehaus.groovy.transform.ASTTransformationVisitor.lambda$addPhaseOperations$1(ASTTransformationVisitor.java:222)
	at org.codehaus.groovy.control.CompilationUnit$IPrimaryClassNodeOperation.doPhaseOperation(CompilationUnit.java:938)
	at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:692)
	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:666)
	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:647)
	at io.quarkiverse.groovy.deployment.GroovyCompilationProvider.compile(GroovyCompilationProvider.java:78)
	at io.quarkus.deployment.dev.QuarkusCompiler.compile(QuarkusCompiler.java:228)
	at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.checkForChangedClasses(RuntimeUpdatesProcessor.java:725)
	at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:461)
	at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:441)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$5.call(VertxHttpHotReplacementSetup.java:150)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$5.call(VertxHttpHotReplacementSetup.java:137)
	at io.vertx.core.impl.ContextBase.lambda$executeBlocking$0(ContextBase.java:167)
	at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:277)
	at io.vertx.core.impl.ContextBase.lambda$internalExecuteBlocking$2(ContextBase.java:199)
	at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
	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)

3 errors

	at io.quarkiverse.groovy.deployment.GroovyCompilationProvider.compile(GroovyCompilationProvider.java:85)
	at io.quarkus.deployment.dev.QuarkusCompiler.compile(QuarkusCompiler.java:228)
	at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.checkForChangedClasses(RuntimeUpdatesProcessor.java:725)
	at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:461)
	at io.quarkus.deployment.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:441)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$5.call(VertxHttpHotReplacementSetup.java:150)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$5.call(VertxHttpHotReplacementSetup.java:137)
	at io.vertx.core.impl.ContextBase.lambda$executeBlocking$0(ContextBase.java:167)
	at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:277)
	at io.vertx.core.impl.ContextBase.lambda$internalExecuteBlocking$2(ContextBase.java:199)
	at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
	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)
	```

I did a project at address https://github.com/fernando88to/appgroovy and had the same error.

Thx for the feedback, which version of the extension do you use?

Thx for the feedback, which version of the extension do you use?

In the example above I used the version 3.5.0

@robokaso what about you? which version do you use?

I'm asking that because I'm about to release a 3.5.2 with this fix and Quarkus 3.5.2, I'm just wondering if I need to backport it.

I've just released v 3.5.2 with the bug fix and Quarkus 3.5.2

I just pulled the current quarkus-groovy master, retried dev mode restart on the examples/reactive-routes project and sadly I keep getting the same @CompileStatic error listed in the original issue description.

Additionally I'm now seeing an error in the log on every http request (even when I don't modify the code and regardless of whether @CompileStatic is used or not).

HTTP Request to /hello-route failed, error id: c8d09ad0-7059-4e21-8d23-5178cb6bd512-1: java.lang.IllegalStateException: Response has already been written
	at io.vertx.core.http.impl.Http1xServerResponse.end(Http1xServerResponse.java:422)
	at io.vertx.core.http.impl.Http1xServerResponse.end(Http1xServerResponse.java:410)
	at io.vertx.core.http.impl.Http1xServerResponse.end(Http1xServerResponse.java:389)
	at org.acme.MyDeclarativeRoutes_RouteHandler_helloRoute_9c156c6cf4f609b21c62cf57f44cc06ba5d4eaa3.invoke(Unknown Source)
	at io.quarkus.vertx.web.runtime.RouteHandler.handle(RouteHandler.java:97)
	at io.quarkus.vertx.web.runtime.RouteHandler.handle(RouteHandler.java:22)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1286)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:140)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:144)
	at io.quarkus.vertx.http.runtime.VertxHttpRecorder$16.handle(VertxHttpRecorder.java:1381)
	at io.quarkus.vertx.http.runtime.VertxHttpRecorder$16.handle(VertxHttpRecorder.java:1350)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1286)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:144)
	at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:59)
	at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:37)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1286)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:144)
	at io.quarkus.vertx.web.runtime.VertxWebRecorder$2.handle(VertxWebRecorder.java:155)
	at io.quarkus.vertx.web.runtime.VertxWebRecorder$2.handle(VertxWebRecorder.java:139)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1286)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:144)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$4.handle(VertxHttpHotReplacementSetup.java:192)
	at io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup$4.handle(VertxHttpHotReplacementSetup.java:181)
	at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
	at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:54)
	at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)

I confirm that the bug is fixed as you can see in the next screenshot unless I missed something in the steps to reproduce.

quarkus-groovy-70

Regarding the stack trace you are mentioning, it is a known stack trace that I never took the time to address since it is harmless. If it is a problem for you please create another ticket