Closed lthasle closed 2 years ago
/cc @pedroigor, @sberyozkin
Hi @mkouba @stuartwdouglas Can you comment please, FYI, the filter which has OidcClient
injected is:
@Priority(Priorities.AUTHENTICATION)
public class StreamAuthenticationFilterMidtNorge implements ClientRequestFilter {
@NamedOidcClient("MidtNorge")
Tokens tokens;
@Override
public void filter(ClientRequestContext clientRequestContext) throws IOException {
clientRequestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, "Bearer " + tokens.getAccessToken());
}
}
and it is used in this code:
@ApplicationScoped
public class QConsumer implements Runnable {
@Inject
ConnectionFactory connectionFactory;
@Inject
StreamService service;
private final ExecutorService scheduler = Executors.newSingleThreadExecutor();
@Override
public void run() {
try (JMSContext context = connectionFactory.createContext(Session.AUTO_ACKNOWLEDGE);
JMSConsumer consumer = context.createConsumer(context.createQueue(MyResource.MY_Q))) {
while (true) {
Message message = consumer.receive();
if (message == null) return;
// OidcClient is used during this call
service.updateState();
}
}
}
void onStart(@Observes StartupEvent ev) {
scheduler.submit(this);
}
void onStop(@Observes ShutdownEvent ev) {
scheduler.shutdown();
}
}
quarkus-smallrye-context-propagation
is in the pom.
I think the executor should be created differently, using the one provided by Quarkus ? thanks
I think the executor should be created differently, using the one provided by Quarkus ?
Yes, a manually created executor does not propagate the CDI request context. You'll need to add the io.quarkus:quarkus-smallrye-context-propagation
dependency and inject ManagedExecutor
instead. Or change the scope of the StreamService
bean to @ApplicationScoped
.
CC @FroMage @manovotn
@mkouba Thanks for your suggestions. But I already have quarkus-smallrye-context-propagation dependency & StreamService use @ApplicationScoped
& StreamService use @ApplicationScoped
I see. But from the stack trace I can see that this bean probably injects a rest client which expects the context to be active. So I'd say that the injected ManagedExecutor
is the only way to go.
+1, Martin is right. The executor needs to come from SR context propagation. It can be either injected or created via the builder pattern. Injection is the recommended and simpler approach.
I Injected the ManagedExecutor but then I got another fault, see code and stacktrace below, any more suggestions? @mkouba @sberyozkin
` @ApplicationScoped public class QConsumer implements Runnable {
@Inject
ConnectionFactory connectionFactory;
@Inject
StreamService service;
@Inject
ManagedExecutor scheduler;
@Override
public void run() {
try (JMSContext context = connectionFactory.createContext(Session.AUTO_ACKNOWLEDGE);
JMSConsumer consumer = context.createConsumer(context.createQueue(MyResource.MY_Q))) {
while (true) {
Message message = consumer.receive();
if (message == null) return;
service.updateState();
}
}
}
void onStart(@Observes StartupEvent ev) {
scheduler.submit(this);
}
} `
`
javax.ws.rs.ProcessingException: java.util.concurrent.CompletionException: java.lang.InterruptedException at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:780) at org.jboss.resteasy.microprofile.client.impl.MpClientInvocation.filterRequest(MpClientInvocation.java:75) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:491) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:152) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:115) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76) at com.sun.proxy.$Proxy106.updatestate(Unknown Source) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.jboss.resteasy.microprofile.client.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:146) at com.sun.proxy.$Proxy107.updatestate(Unknown Source) at org.my.StreamService.lambda$0(StreamService.java:26) at org.my.AbstractMeglerService.execute(AbstractMeglerService.java:17) at org.my.StreamService.updateState(StreamService.java:26) at org.my.StreamService_ClientProxy.updateState(Unknown Source) at org.my.QConsumer.run(QConsumer.java:33) at io.smallrye.context.impl.wrappers.SlowContextualRunnable.run(SlowContextualRunnable.java:19) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:548) at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478) 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:834) Caused by: java.util.concurrent.CompletionException: java.lang.InterruptedException at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:73) at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:61) at io.smallrye.mutiny.groups.UniAwait.indefinitely(UniAwait.java:42) at io.quarkus.oidc.client.runtime.TokensHelper.initTokens(TokensHelper.java:20) at io.quarkus.oidc.client.runtime.AbstractTokensProducer.initTokens(AbstractTokensProducer.java:38) at io.quarkus.oidc.client.runtime.AbstractTokensProducer.init(AbstractTokensProducer.java:33) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.create(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.create(Unknown Source) at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96) at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29) at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26) at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26) at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69) at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.get(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.get(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_Bean.create(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_Bean.create(Unknown Source) at io.quarkus.arc.impl.RequestContext.getIfActive(RequestContext.java:68) at io.quarkus.arc.impl.ClientProxies.getDelegate(ClientProxies.java:27) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_ClientProxy.arc$delegate(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_ClientProxy.getAccessToken(Unknown Source) at org.my.StreamAuthenticationFilterMidtNorge.filter(StreamAuthenticationFilterMidtNorge.java:21) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:767) ... 27 more Caused by: java.lang.InterruptedException at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1040) at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1345) at java.base/java.util.concurrent.CountDownLatch.await(CountDownLatch.java:232) at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:61) ... 50 more `
@lthasle Interesting. I think it might be related to the fact that the Tokens
producer you are injecting in the client filter is blocking. But I'm not sure why it makes a difference if you run the client from a thread different to the one which made the original request - as you confirmed at #22273 the client works OK if not run from the executor thread.
My guess ManagedExecutor
is tuned around the reactive calls so one just can't block in its threads.
You could've injected OidcClient
directly instead of Tokens
and use its Uni
-aware getAccessToken()
but then you'd still need to block to get the actual token as you running it in a filter.
Martin @mkouba, Matej @manovotn - is it indeed the case that ManagedExecutor
tasks must be non-blocking ?
@lthasle, One option is to use a OidcClientReactiveFilter - either this one or a custom one (I'll doc it as well how to create a custom reactive filter). But you'll need to switch from RestEasy Classic to RestEasy Reactive - it will be the best option if it can work for you - it will be faster as well.
@mkouba @manovotn Can you recommend any other options ? May be we can configure ManagedExecutor
to allow running the blocking tasks ?
@lthasle I'll also look at introducing a simple OidcClient
builder which will accept OidcClientConfig
and will return Uni<OidcClient>
if the discovery is required or OidcClient
if not so that the injection can be avoided.
I am not aware of ME not being able to serve blocking tasks. But I cannot really investigate now (on PTO and travelling). @FroMage knows a lot more about the reactive side of things.
@manovotn sure, enjoy it, happy holidays :-)
@sberyozkin Thanks for your effort and suggestions so far! We hope that we soon will be able to use: RestEasy Reactive, but for the time being we are not able to
Same problem with the latest quarkus version: 2.6.0.Final
I also had to change quarkus-test-artemis dependency:
@lthasle Np, with many people on PTO, myself signing off later today as well, it is unlikely we'll have a solution before the end of the year :-). But at least we know how to approach it: 1) investigate how ManagedExecutor
can be enhanced or configured to allow the blocking calls 2) Add OidcClientBulder
.
I think 1) has to be addressed in any case as a similar issue might arise not only for OidcClient
thanks
Same problem with the latest quarkus version: 2.6.1.Final
My guess ManagedExecutor is tuned around the reactive calls so one just can't block in its threads.
No it's not, this is directly backed by the Quarkus worker thread pool, so you can block.
The real question is why is the thread interrupted? And perhaps there are some bits which should handle the interruption?
The real question is why is the thread interrupted?
@FroMage @manovotn May be because the injection is happening on the IO thread while injected tokens producer is blocking.
It can be delayed though, the token acquisition.
@lthasle, can you please add quarkus.oidc-client.MidtNorge.early-tokens-acquisition=false
and see if it helps ?
@sberyozkin thanks for your proposal but adding: quarkus.oidc-client.MidtNorge.early-tokens-acquisition=false did NOT make any change unfortunately
@lthasle Sorry, I forgot that it is a global property, https://github.com/quarkusio/quarkus/blob/main/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/AbstractTokensProducer.java#L21, it is not a client tenant specific, can you please try quarkus.oidc-client.early-tokens-acquisition=false
@sberyozkin adding: quarkus.oidc-client.early-tokens-acquisition=false did NOT make any change unfortunately
Hmm... I'm out of the ideas right now. TokensProducer
which you have injected extends AbstractTokensProducer
and if this property is indeed injected then the early token acquisition must be skipped, but the stack trace suggests this property is not injected, io.quarkus.oidc.client.runtime.AbstractTokensProducer.initTokens(AbstractTokensProducer.java:38)
-> https://github.com/quarkusio/quarkus/blob/main/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/AbstractTokensProducer.java#L38
@sberyozkin Just to be clear, the result is the same when I use: quarkus.oidc-client.early-tokens-acquisition=false
But the stacktrace is different related to the class AbstractTokensProducer which you talk about: Here is the actual stacktrace, but I guess you already have seen this
javax.ws.rs.ProcessingException: java.util.concurrent.CompletionException: java.lang.InterruptedException at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:780) at org.jboss.resteasy.microprofile.client.impl.MpClientInvocation.filterRequest(MpClientInvocation.java:75) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:491) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:152) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:115) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76) at com.sun.proxy.$Proxy107.updatestate(Unknown Source) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.jboss.resteasy.microprofile.client.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:146) at com.sun.proxy.$Proxy108.updatestate(Unknown Source) at org.my.StreamService.lambda$0(StreamService.java:26) at org.my.AbstractMeglerService.execute(AbstractMeglerService.java:17) at org.my.StreamService.updateState(StreamService.java:26) at org.my.StreamService_ClientProxy.updateState(Unknown Source) at org.my.QConsumer.run(QConsumer.java:33) at io.smallrye.context.impl.wrappers.SlowContextualRunnable.run(SlowContextualRunnable.java:19) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:548) at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478) 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:834) Caused by: java.util.concurrent.CompletionException: java.lang.InterruptedException at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:73) at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:62) at io.smallrye.mutiny.groups.UniAwait.indefinitely(UniAwait.java:43) at io.quarkus.oidc.client.runtime.AbstractTokensProducer.awaitTokens(AbstractTokensProducer.java:47) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge.produceTokens(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_Bean.create(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_Bean.create(Unknown Source) at io.quarkus.arc.impl.RequestContext.getIfActive(RequestContext.java:68) at io.quarkus.arc.impl.ClientProxies.getDelegate(ClientProxies.java:27) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_ClientProxy.arc$delegate(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_ClientProxy.getAccessToken(Unknown Source) at org.my.StreamAuthenticationFilterMidtNorge.filter(StreamAuthenticationFilterMidtNorge.java:21) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:767) ... 27 more Caused by: java.lang.InterruptedException at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1040) at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1345) at java.base/java.util.concurrent.CountDownLatch.await(CountDownLatch.java:232) at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:61) ... 39 more
@lthasle Sorry about all of it, I'll try to have a look when I'm back;
So it all works if it is not a new thread - but if it is a new thread provided by ManagedExecutor
then the underlying blocking OidcClient
request is interrupted.
Hi @mkouba @manovotn @FroMage - if you have any other ideas why it can be the case then please comment - this is the only difference, the client request filter which has a blocking Tokens
producer, is run either from the same thread which entered the Quarkus endpoint (all is good) or from a new thread provided by ManagedExecutor
(does not work)
@sberyozkin
I get the same behavior if I try to use reactive, see stacktrace below.
But we are for the moment not able to use reactive for our project anyway.
java.util.concurrent.CompletionException: java.lang.InterruptedException at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:73) at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:62) at io.smallrye.mutiny.groups.UniAwait.indefinitely(UniAwait.java:43) at io.quarkus.oidc.client.runtime.TokensHelper.initTokens(TokensHelper.java:20) at io.quarkus.oidc.client.runtime.AbstractTokensProducer.initTokens(AbstractTokensProducer.java:38) at io.quarkus.oidc.client.runtime.AbstractTokensProducer.init(AbstractTokensProducer.java:33) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.create(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.create(Unknown Source) at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96) at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29) at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26) at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26) at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69) at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.get(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.get(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_Bean.create(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_Bean.create(Unknown Source) at io.quarkus.arc.impl.RequestContext.getIfActive(RequestContext.java:68) at io.quarkus.arc.impl.ClientProxies.getDelegate(ClientProxies.java:27) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_ClientProxy.arc$delegate(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_ClientProxy.getAccessToken(Unknown Source) at org.my.StreamAuthenticationFilterMidtNorge.filter(StreamAuthenticationFilterMidtNorge.java:21) at org.jboss.resteasy.reactive.client.handlers.ClientRequestFilterRestHandler.handle(ClientRequestFilterRestHandler.java:24) at org.jboss.resteasy.reactive.client.handlers.ClientRequestFilterRestHandler.handle(ClientRequestFilterRestHandler.java:9) at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:141) at org.jboss.resteasy.reactive.client.impl.AsyncInvokerImpl.performRequestInternal(AsyncInvokerImpl.java:262) at org.jboss.resteasy.reactive.client.impl.AsyncInvokerImpl.performRequestInternal(AsyncInvokerImpl.java:252) at org.jboss.resteasy.reactive.client.impl.AsyncInvokerImpl.method(AsyncInvokerImpl.java:212) at org.jboss.resteasy.reactive.client.impl.InvocationBuilderImpl.method(InvocationBuilderImpl.java:324) at org.my.StreamClientMidtNorge$$QuarkusRestClientInterface.updatestate(Unknown Source) at org.my.StreamService.lambda$0(StreamService.java:26) at org.my.AbstractMeglerService.execute(AbstractMeglerService.java:17) at org.my.StreamService.updateState(StreamService.java:26) at org.my.StreamService_ClientProxy.updateState(Unknown Source) at org.my.QConsumer.run(QConsumer.java:33) at io.smallrye.context.impl.wrappers.SlowContextualRunnable.run(SlowContextualRunnable.java:19) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:548) at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478) 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:834) Caused by: java.lang.InterruptedException at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1040) at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1345) at java.base/java.util.concurrent.CountDownLatch.await(CountDownLatch.java:232) at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:61) ... 45 more
@sberyozkin I get the same behavior if I try without a Q, but in another thread See stacktrace below
Required change: ` MyResource @Path("/ok") @GET public void ok() { //service.updateState(); CompletableFuture.runAsync(() -> service.updateState(), managedExecutor); // managedExecutor injected }
java.util.concurrent.CompletionException: java.lang.InterruptedException at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:73) at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:62) at io.smallrye.mutiny.groups.UniAwait.indefinitely(UniAwait.java:43) at io.quarkus.oidc.client.runtime.TokensHelper.initTokens(TokensHelper.java:20) at io.quarkus.oidc.client.runtime.AbstractTokensProducer.initTokens(AbstractTokensProducer.java:38) at io.quarkus.oidc.client.runtime.AbstractTokensProducer.init(AbstractTokensProducer.java:33) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.create(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.create(Unknown Source) at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96) at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29) at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26) at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26) at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69) at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.get(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.get(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_Bean.create(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_Bean.create(Unknown Source) at io.quarkus.arc.impl.RequestContext.getIfActive(RequestContext.java:68) at io.quarkus.arc.impl.ClientProxies.getDelegate(ClientProxies.java:27) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_ClientProxy.arc$delegate(Unknown Source) at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_ClientProxy.getAccessToken(Unknown Source) at org.my.StreamAuthenticationFilterMidtNorge.filter(StreamAuthenticationFilterMidtNorge.java:21) at org.jboss.resteasy.reactive.client.handlers.ClientRequestFilterRestHandler.handle(ClientRequestFilterRestHandler.java:24) at org.jboss.resteasy.reactive.client.handlers.ClientRequestFilterRestHandler.handle(ClientRequestFilterRestHandler.java:9) at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:141) at org.jboss.resteasy.reactive.client.impl.AsyncInvokerImpl.performRequestInternal(AsyncInvokerImpl.java:262) at org.jboss.resteasy.reactive.client.impl.AsyncInvokerImpl.performRequestInternal(AsyncInvokerImpl.java:252) at org.jboss.resteasy.reactive.client.impl.AsyncInvokerImpl.method(AsyncInvokerImpl.java:212) at org.jboss.resteasy.reactive.client.impl.InvocationBuilderImpl.method(InvocationBuilderImpl.java:324) at org.my.StreamClientMidtNorge$$QuarkusRestClientInterface.updatestate(Unknown Source) at org.my.StreamService.lambda$0(StreamService.java:26) at org.my.AbstractMeglerService.execute(AbstractMeglerService.java:17) at org.my.StreamService.updateState(StreamService.java:26) at org.my.StreamService_ClientProxy.updateState(Unknown Source) at org.my.MyResource.lambda$0(MyResource.java:30) at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736) at io.smallrye.context.impl.wrappers.SlowContextualRunnable.run(SlowContextualRunnable.java:19) at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:543) at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1452) 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:834) Caused by: java.lang.InterruptedException at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1040) at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1345) at java.base/java.util.concurrent.CountDownLatch.await(CountDownLatch.java:232) at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:61) ... 44 more `
I might be misreading this, but why would a request made from the scheduler be expected to be able to retrieve OIDC token from the current request (which doesn't exist)?
Hi @geoand the filter which is applied to the rest client retrieves this token from the remote OIDC server and it is failing; I'll need to add a test to reproduce
Ah okay. I misunderstood what it does then.
Thanks
Hi @lthasle I've finally found the time to add a test, please see #22987. It works fine. (I tested the default filter as well separately)
The only significant difference between your code and the test which I see is that you inject the client (and the factory) directly into Runnable
while in the test, Runnable uses the client injected into the endpoint (please try something similar as well).
If PR is approved then it will resolve this issue. may be it will make it to 2.7.0.CR1 but if not it should make it to 2.7.0.Final. Please try it then and if it still does not work then please re-open.
Something else might be contributing to the failure in your case. Note, @stuartwdouglas has just improved oidc-client
not to depend on vertx-http
but only on vertx-core
- it might be related as well. So yes, try 2.7.0
CR1/Final please
@sberyozkin Thanks for your effort, but I get the same fault when I use 2.7.0.CR1 Same applies if I replace the classic dependencies with the reactive ones as well. I am not sure how I can re-open the issue.
javax.ws.rs.ProcessingException: java.util.concurrent.CompletionException: java.lang.InterruptedException
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:780)
at org.jboss.resteasy.microprofile.client.impl.MpClientInvocation.filterRequest(MpClientInvocation.java:75)
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:491)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:152)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:115)
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76)
at com.sun.proxy.$Proxy117.updatestate(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.jboss.resteasy.microprofile.client.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:146)
at com.sun.proxy.$Proxy118.updatestate(Unknown Source)
at org.my.StreamService.lambda$0(StreamService.java:26)
at org.my.AbstractMeglerService.execute(AbstractMeglerService.java:17)
at org.my.StreamService.updateState(StreamService.java:26)
at org.my.StreamService_ClientProxy.updateState(Unknown Source)
at org.my.QConsumer.run(QConsumer.java:33)
at io.smallrye.context.impl.wrappers.SlowContextualRunnable.run(SlowContextualRunnable.java:19)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:548)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
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:834)
Caused by: java.util.concurrent.CompletionException: java.lang.InterruptedException
at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:79)
at io.smallrye.mutiny.groups.UniAwait.atMost(UniAwait.java:65)
at io.smallrye.mutiny.groups.UniAwait.indefinitely(UniAwait.java:46)
at io.quarkus.oidc.client.runtime.TokensHelper.initTokens(TokensHelper.java:20)
at io.quarkus.oidc.client.runtime.AbstractTokensProducer.initTokens(AbstractTokensProducer.java:38)
at io.quarkus.oidc.client.runtime.AbstractTokensProducer.init(AbstractTokensProducer.java:33)
at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.create(Unknown Source)
at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.create(Unknown Source)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:101)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.get(Unknown Source)
at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_Bean.get(Unknown Source)
at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_Bean.create(Unknown Source)
at io.quarkus.oidc.client.runtime.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_Bean.create(Unknown Source)
at io.quarkus.arc.impl.RequestContext.getIfActive(RequestContext.java:68)
at io.quarkus.arc.impl.ClientProxies.getDelegate(ClientProxies.java:27)
at io.quarkus.oidc.client.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_ClientProxy.arc$delegate(Unknown Source)
at io.quarkus.oidc.client.TokensProducer_MidtNorge_ProducerMethod_produceTokens_494654c3bfa2346b017c24e2e2c4fcfc99087d0e_ClientProxy.getAccessToken(Unknown Source)
at org.my.StreamAuthenticationFilterMidtNorge.filter(StreamAuthenticationFilterMidtNorge.java:23)
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:767)
... 27 more
Caused by: java.lang.InterruptedException
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1040)
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1345)
at java.base/java.util.concurrent.CountDownLatch.await(CountDownLatch.java:232)
at io.smallrye.mutiny.operators.uni.UniBlockingAwait.await(UniBlockingAwait.java:67)
... 50 more
@lthasle Hi, missed your comment, reopened. I don't know what else can be done - can you please create a specific reproducer, with a test similar to the one I added in my PR ? (The client calls the frontend endpoint, this endpoint, in turn, from a Runnable task calls the downstream endpoint). For example, in your reproducer you have
stream.api.midtnorge/mp-rest/url=https://mysite.com
stream.api.midtnorge/mp-rest/scope=javax.enterprise.context.ApplicationScoped
quarkus.oidc-client.MidtNorge.discovery-enabled=false
quarkus.oidc-client.MidtNorge.auth-server-url=${stream.api.midtnorge/mp-rest/url}
But it can't really work - the downstream target and OIDC server URLs are the same.
How about checkout out Quarkus and modifying the test I've added until you reproduce the problem - everything is already set up there except for the broker ?
@sberyozkin
Is there a guide which shows how I can setup my environment to run your test? I guess I need something in my settings.xml?
`
Quarkus - Documentation ............................ SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 44.735 s
[INFO] Finished at: 2022-01-24T19:19:37+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project quarkus-bootstrap-gradle-resolver: Could not resolve dependencies for project
io.quarkus:quarkus-bootstrap-gradle-resolver:jar:999-SNAPSHOT: Could not find artifact org.gradle:gradle-tooling-api:jar:7.3.3 in nexus.intern
(http://XXX.no/repository/public/) -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn
`
@lthasle Did you checkout the main branch and built it, see https://github.com/quarkusio/quarkus/blob/main/CONTRIBUTING.md ? CC @gsmet
Looks like you did, sorry
You just need to add an @ActivateRequestContext
to org.my.QConsumer#run
.
Note that if you run the test you will still see a different exception as Quarkus will shutdown before the startup task is complete (once the test is run quarkus shuts down, but the run method is async).
I think this can be closed.
@sberyozkin @stuartwdouglas THANKS! It works with @ActivateRequestContext
@stuartwdouglas Thanks Stuart, I've learned something new :-) @lthasle Glad it works for you now :-)
Describe the bug
It seams like Context is lost in the new thread when using Tokens from oidc-client
See also: https://github.com/quarkusio/quarkus/discussions/22273
Expected behavior
Usage of io.quarkus.oidc.client.Tokens should work, ie. have a value
Actual behavior
Usage(@Inject) of io.quarkus.oidc.client.Tokens is causing: ContextNotActiveException
The result from running: MyResourceTest.fail:
How to Reproduce?
It is based on: https://quarkus.io/guides/rest-client I added my stuff in the package: org.my
The problem can be verified by running the test: MyResourceTest.fail
The other test: MyResourceTest.ok is doing the same, BUT in same thread (that is not via a Q, as the other test), but it requires proper values in: application.properties to succeed.
Output of
uname -a
orver
uname -a Linux hty80028.sb1a.sparebank1.no 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 8 13:30:15 EST 2021 x86_64 x86_64 x86_64 GNU/Linux
Output of
java -version
openjdk version "11.0.10" 2021-01-19 OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.10+9) OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.10+9, mixed mode)
GraalVM version (if different from Java)
No response
Quarkus version or git rev
2.5.4.Final
Build tool (ie. output of
mvnw --version
orgradlew --version
)No response
Additional information
rest-client-quickstart.zip