quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.76k stars 2.68k forks source link

Shutdown task failed: java.lang.IllegalArgumentException - quarkus-hibernate-orm and quarkus-smallrye-fault-tolerance enabled #2710

Closed rsvoboda closed 5 years ago

rsvoboda commented 5 years ago

I see java.lang.IllegalArgumentException thrown at the end of test phase when quarkus-hibernate-orm and quarkus-smallrye-fault-tolerance are enabled.

Stacktrace includes keywords like HystrixThreadEventStream and io.quarkus.smallrye.faulttolerance. This error message is present only if quarkus-hibernate-orm extension is used too. There is no exception when only quarkus-smallrye-fault-tolerance is enabled.

2019-06-04 15:53:16,096 ERROR [io.qua.run.StartupContext] (main) 
  Running a shutdown task failed: java.lang.IllegalArgumentException
mvn io.quarkus:quarkus-maven-plugin:999-SNAPSHOT:create \
    -DprojectGroupId=io.quarkus.qe \
    -DprojectArtifactId=scenario-101-getting-started \
    -DprojectVersion=1.0.0-SNAPSHOT \
    -DclassName="io.quarkus.qe.hello.GreetingResource" \
    -Dextensions=io.quarkus:quarkus-hibernate-orm,io.quarkus:quarkus-smallrye-fault-tolerance
mvn clean package
...
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.884 s - in io.quarkus.qe.hello.GreetingResourceTest
2019-06-04 15:53:16,096 ERROR [io.qua.run.StartupContext] (main) Running a shutdown task failed: java.lang.IllegalArgumentException
    at io.quarkus.arc.ArcContainerImpl.unwrap(ArcContainerImpl.java:558)
    at io.quarkus.arc.ArcContainerImpl.instance(ArcContainerImpl.java:563)
    at io.quarkus.arc.InstanceImpl.resolve(InstanceImpl.java:163)
    at io.quarkus.arc.InstanceImpl.<init>(InstanceImpl.java:75)
    at io.quarkus.arc.InstanceImpl.<init>(InstanceImpl.java:61)
    at io.quarkus.arc.InstanceImpl.select(InstanceImpl.java:111)
    at io.quarkus.arc.ArcCDIProvider$ArcCDI.select(ArcCDIProvider.java:60)
    at io.smallrye.context.jta.context.propagation.JtaContextProvider.tm(JtaContextProvider.java:86)
    at io.smallrye.context.jta.context.propagation.JtaContextProvider.currentTransaction(JtaContextProvider.java:78)
    at io.smallrye.context.jta.context.propagation.JtaContextProvider.currentContext(JtaContextProvider.java:25)
    at io.smallrye.context.impl.CapturedContextState.<init>(CapturedContextState.java:21)
    at io.smallrye.context.SmallRyeContextManager.captureContext(SmallRyeContextManager.java:60)
    at io.smallrye.context.SmallRyeThreadContext.currentContextExecutor(SmallRyeThreadContext.java:208)
    at io.smallrye.context.propagators.rxjava1.ContextPropagatorOnObservableCreateAction.call(ContextPropagatorOnObservableCreateAction.java:24)
    at io.smallrye.context.propagators.rxjava1.ContextPropagatorOnObservableCreateAction.call(ContextPropagatorOnObservableCreateAction.java:12)
    at rx.plugins.RxJavaHooks.onCreate(RxJavaHooks.java:337)
    at rx.Observable.unsafeCreate(Observable.java:162)
    at rx.Observable.lift(Observable.java:299)
    at rx.Observable.onBackpressureBuffer(Observable.java:7883)
    at com.netflix.hystrix.metric.HystrixThreadEventStream.<init>(HystrixThreadEventStream.java:111)
    at com.netflix.hystrix.metric.HystrixThreadEventStream$1.initialValue(HystrixThreadEventStream.java:66)
    at com.netflix.hystrix.metric.HystrixThreadEventStream$1.initialValue(HystrixThreadEventStream.java:63)
    at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:180)
    at java.lang.ThreadLocal.get(ThreadLocal.java:170)
    at com.netflix.hystrix.metric.HystrixThreadEventStream.getInstance(HystrixThreadEventStream.java:128)
    at io.quarkus.smallrye.faulttolerance.runtime.SmallryeFaultToleranceTemplate$1.run(SmallryeFaultToleranceTemplate.java:25)
    at io.quarkus.runtime.StartupContext.close(StartupContext.java:59)
    at io.quarkus.runner.ApplicationImpl1.doStop(Unknown Source)
    at io.quarkus.runtime.Application.stop(Application.java:167)
    at io.quarkus.runner.RuntimeRunner$1.close(RuntimeRunner.java:138)
    at io.quarkus.runner.RuntimeRunner.close(RuntimeRunner.java:84)
    at io.quarkus.test.junit.QuarkusTestExtension$5.close(QuarkusTestExtension.java:241)
    at io.quarkus.test.junit.QuarkusTestExtension$ExtensionState.close(QuarkusTestExtension.java:354)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.execution.ExtensionValuesStore.closeAllStoredCloseableValues(ExtensionValuesStore.java:61)
    at org.junit.jupiter.engine.descriptor.AbstractExtensionContext.close(AbstractExtensionContext.java:73)
    at org.junit.jupiter.engine.execution.JupiterEngineExecutionContext.close(JupiterEngineExecutionContext.java:53)
    at org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor.cleanUp(JupiterEngineDescriptor.java:67)
    at org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor.cleanUp(JupiterEngineDescriptor.java:30)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$cleanUp$9(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.cleanUp(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:83)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:142)
    at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:117)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:383)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:344)
    at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:125)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:417)
gsmet commented 5 years ago

It looks related to context propagation and maybe ArC.

@mkouba @FroMage ?

FroMage commented 5 years ago

Isn't there another issue about this that we fixed?

rsvoboda commented 5 years ago

I use latest master

mkouba commented 5 years ago

It's definitely related to context propagation. From what I see in the stack the JtaContextProvider attempts to use ArC after the container was shut down. A similar issue was in ArcContextProvider - see https://github.com/quarkusio/quarkus/issues/2696.

There is no exception when only quarkus-smallrye-fault-tolerance is enabled.

Yes, that confirms my assumption that it's a bug in JtaContextProvider.

FroMage commented 5 years ago

So JtaContextProvider should be updated with a similar fix? What's weird here is that this seems to be hapening due to running cleanup, so perhaps it's a cleanup ordering issue?

FroMage commented 5 years ago

Seems to me that HystrixThreadEventStream.getInstance().shutdown() is also technically invalid, because it will create a new threadlocal (this is what happens here) just to shut it down. There seems to be no way to check if that creation is required, though.

FroMage commented 5 years ago

@mmusgrov do you agree we should add specific behaviour when CDI is present but there's no transaction manager? I can probably fix this.

FroMage commented 5 years ago

attempts to use ArC after the container was shut down

We call:

   private boolean isCdiUnavailable() {
        try {
            return CDI.current() == null;
        } catch (IllegalStateException e) {
            // no CDI provider found, CDI isn't available
            return true;
        }
    }

This is not the right way to do it?

mkouba commented 5 years ago

This should be a portable way. If you don't need to be portable, just use Arc.container() != null.

I'll fix our CDIProvider to throw ISE if it's not available.

FroMage commented 5 years ago

Ah, ArcContextProvider now calls

        ArcContainer arc = Arc.container();
        if (arc == null || !arc.isRunning()) {

But CDI does not appear to have that, is this true @mkouba ?

FroMage commented 5 years ago

This needs to be portable, it's not in quarkus.

FroMage commented 5 years ago

OK, if your fix to CDIProvider is enough to fix this, then it's much easier than the alternatives :)

mkouba commented 5 years ago

I'll send a PR shortly...

FroMage commented 5 years ago

Trying out the PR with the problematic example project.

FroMage commented 5 years ago

And I confirm it fixes the issue.