You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A Quarkus application that uses an Emitter to send messages to a reactive messaging pipeline incidentally propagates context to the Incoming method. Of course, this only happens when the channel is "in-memory". When the channel uses a connector - for example, Kafka - then, as expected, propagation does not occur, because the context is lost when the message is sent to Kafka.
This creates a leaky abstraction with respect to context propagation in @Incoming methods. These methods unexpectedly inherit context from the Emitter's scope only when the channel uses an in-memory connector. I would expect an @Incoming method to never inherit context, so that its relationship to the current context is consistent regardless of the connector being used.
Expected behavior
The @Incoming method should execute with a cleared context regardless of whether it receives messages from an external system (e.g. Kafka) or an in-memory data structure.
Actual behavior
Context is propagated from the Quarkus REST resource to the Reactive Messaging consumer. This denies the Reactive Messaging consumer the ability to start its own request context to use while consume messages. For example, if the @Incoming method were also decorated with @ActivateRequestScope, then the method would use the request scope created by Quarkus REST, and that scope will be destroyed when Quarkus REST has finished serving the request.
How to Reproduce?
This small Quarkus application reproduces the issue. Its test passes, because it uses a ManagedExecutor to clear the context before calling the Emitter. This is a workaround to the described issue. Removing this workaround and instead executing the commented out code return emitter.send(body); (no ManagedExecutor used) demonstrates the problem.
@Path("/hello")
classGreetingResource {
@Channel("greeting")
Emitter<String> emitter;
@Inject@ManagedExecutorConfig(maxAsync = 2, maxQueued = 3, cleared = CDI)
ManagedExecutorexecutor;
@POST@Consumes(MediaType.TEXT_PLAIN)
publicCompletionStage<Void> hello(Stringbody) {
// context incidentally propagated, use ManagedExecutor to clear context at the emitter// return emitter.send(body);returnCompletableFuture.supplyAsync(() -> emitter.send(body), executor).join();
}
}
@ApplicationScopedclassGreetingProcessor {
@InjectRequestContextControllercontroller;
@InjectLoggerlogger;
@Incoming("greeting")
voidprocess(Stringname) {
if (!controller.activate()) {
thrownewIllegalStateException("Request context is already active");
}
logger.infof("Hello, %s", name);
}
}
Describe the bug
A Quarkus application that uses an
Emitter
to send messages to a reactive messaging pipeline incidentally propagates context to theIncoming
method. Of course, this only happens when the channel is "in-memory". When the channel uses a connector - for example, Kafka - then, as expected, propagation does not occur, because the context is lost when the message is sent to Kafka.This creates a leaky abstraction with respect to context propagation in
@Incoming
methods. These methods unexpectedly inherit context from theEmitter
's scope only when the channel uses an in-memory connector. I would expect an@Incoming
method to never inherit context, so that its relationship to the current context is consistent regardless of the connector being used.Expected behavior
The
@Incoming
method should execute with a cleared context regardless of whether it receives messages from an external system (e.g. Kafka) or an in-memory data structure.Actual behavior
Context is propagated from the Quarkus REST resource to the Reactive Messaging consumer. This denies the Reactive Messaging consumer the ability to start its own request context to use while consume messages. For example, if the
@Incoming
method were also decorated with@ActivateRequestScope
, then the method would use the request scope created by Quarkus REST, and that scope will be destroyed when Quarkus REST has finished serving the request.How to Reproduce?
This small Quarkus application reproduces the issue. Its test passes, because it uses a
ManagedExecutor
to clear the context before calling theEmitter
. This is a workaround to the described issue. Removing this workaround and instead executing the commented out codereturn emitter.send(body);
(noManagedExecutor
used) demonstrates the problem.quarkus-emitter-new-request-context.zip
Output of
uname -a
orver
Darwin MacBookPro 24.2.0 Darwin Kernel Version 24.2.0: Fri Dec 6 19:01:59 PST 2024; root:xnu-11215.61.5~2/RELEASE_ARM64_T6000 arm64
Output of
java -version
openjdk version "21.0.6" 2025-01-21 LTS OpenJDK Runtime Environment Temurin-21.0.6+7 (build 21.0.6+7-LTS) OpenJDK 64-Bit Server VM Temurin-21.0.6+7 (build 21.0.6+7-LTS, mixed mode, sharing)
Quarkus version or git rev
3.18.3
Build tool (ie. output of
mvnw --version
orgradlew --version
)Apache Maven 3.9.6 (bc0240f3c744dd6b6ec2920b3cd08dcc295161ae) Maven home: /Users/jgilday/.m2/wrapper/dists/apache-maven-3.9.6-bin/3311e1d4/apache-maven-3.9.6 Java version: 21.0.6, vendor: Eclipse Adoptium, runtime: /Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home Default locale: en_US, platform encoding: UTF-8 OS name: "mac os x", version: "15.2", arch: "aarch64", family: "mac"
Additional information
No response
The text was updated successfully, but these errors were encountered: