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

RequestScoped Context no longer works since the 2.20+(Java 17/Quarkus 3.7+) Release #319

Closed
idursto opened this issue Jun 19, 2024 · 7 comments

Comments

@idursto
Copy link

idursto commented Jun 19, 2024

Prior to release 2.20 the RequestScoped context functioned as expected on an injected dependency on a Batchlet. The Request Context started at the start/trigger of the job and was torn down at the end of the job completing and subsequent jobs ran with the same dependency functioned the same. However ever since release 2.20 when a job is run with a Batchlet that contains a RequestScoped context injected dependency the following error occurs:

2024-06-19 16:26:02,644 WARN [org.jberet] (executor-thread-2) JBERET000001: Failed to run batchlet org.jberet.job.model.RefArtifact@429e1416: jakarta.enterprise.context.ContextNotActiveException: RequestScoped context was not active when trying to obtain a bean instance for a client proxy of CLASS bean [class={classHere}, id={idHere}] - you can activate the request context for a specific method using the @ActivateRequestContext interceptor binding

Sometimes the job will work the first time and then subsequent calls on the job get the above error. It's a fairly simple thing to recreate by injecting a RequestScoped dependency into any batch job and then running that job and using that dependency.

@radcortez
Copy link
Collaborator

We don't have a 2.20 release. Do you mean 2.2.x? Can you please clarify?

@idursto
Copy link
Author

idursto commented Jun 19, 2024

Yes, sorry I forgot a decimal. I am working on upgrading things to Java 17 and the RequestScoped issues broke my applications on anything > 2.2.x quarkus-jberet release when I tried to upgrade things. Changing the RequestScoped to ApplicationScoped fixes the issue to where the jobs run fine...but then obviously messes up quite a few things with my dependency injection on those dependencies as they are set to RequestScoped for a reason.

Any help is appreciated...

@radcortez
Copy link
Collaborator

I'll have a look.

@radcortez
Copy link
Collaborator

I had a look, and it seems that is working as expected. For instance, if you start your job manually, either with the rest client, or via a resource with JobOperator request scoped injection works fine.

If the job is started via a scheduler there is no request scope available, hence the error. I don't think we should manually start a request scope context in this situation.

Maybe there is something else I'm missing. Is there any chance you can provide me with a reproducer?

@idursto
Copy link
Author

idursto commented Jun 25, 2024

quarkusapi.zip

Attached is a simple implementation showing the problem. I have a HelloWorld job which has a ProcessHelloWorldBatchlet and within that Batchlet there is a RequestScoped service that just generates a random GUID that the job displays.

I invoke the job via the JobController and a restful endpoint to start it which leverages the job operator:

final var startedJobId = jobOperator.start(jobName, properties);

You can run the job once and it runs fine...any subsequent attempts to run the job results in a ContextNotActiveException:

__  ____  __  _____   ___  __ ____  ______ 
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2024-06-25 08:16:00,236 WARN  [io.qua.config] (Quarkus Main Thread) Unrecognized configuration key "quarkus.package.type" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo

2024-06-25 08:16:03,373 INFO  [io.quarkus] (Quarkus Main Thread) quarkusapi 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.11.2) started in 24.501s. Listening on: http://localhost:8080
2024-06-25 08:16:03,419 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2024-06-25 08:16:03,421 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, config-yaml, hibernate-orm, hibernate-orm-panache, jberet, jdbc-h2, narayana-jta, rest, rest-jsonb, smallrye-context-propagation, smallrye-openapi, swagger-ui, vertx]                                                                                                                                                             
HELLO WORLD PROCESSING ... RANDOM_ID: 9d5f0ee4-8c39-4c4e-9c6a-550ffbae6f8e MESSAGE: DEFAULT_HELLO                                                                                                                  
2024-06-25 08:16:55,262 WARN  [org.jberet] (executor-thread-2) JBERET000001: Failed to run batchlet org.jberet.job.model.RefArtifact@813dd6b4: jakarta.enterprise.context.ContextNotActiveException: RequestScoped context was not active when trying to obtain a bean instance for a client proxy of CLASS bean [class=org.acme.RequestScopedService, id=uiCJDJzfcgCceYTDIs-dLK__aPs]
        - you can activate the request context for a specific method using the @ActivateRequestContext interceptor binding
        at io.quarkus.arc.impl.ClientProxies.notActive(ClientProxies.java:70)
        at io.quarkus.arc.impl.ClientProxies.getSingleContextDelegate(ClientProxies.java:30)
        at org.acme.RequestScopedService_ClientProxy.arc$delegate(Unknown Source)
        at org.acme.RequestScopedService_ClientProxy.getRandomUUID(Unknown Source)
        at org.acme.ProcessHelloWorldBatchlet.process(ProcessHelloWorldBatchlet.java:23)
        at org.jberet.runtime.runner.BatchletRunner.run(BatchletRunner.java:74)
        at org.jberet.runtime.runner.StepExecutionRunner.runBatchletOrChunk(StepExecutionRunner.java:226)
        at org.jberet.runtime.runner.StepExecutionRunner.run(StepExecutionRunner.java:142)
        at org.jberet.runtime.runner.CompositeExecutionRunner.runStep(CompositeExecutionRunner.java:170)
        at org.jberet.runtime.runner.CompositeExecutionRunner.runFromHeadOrRestartPoint(CompositeExecutionRunner.java:94)
        at org.jberet.runtime.runner.JobExecutionRunner.run(JobExecutionRunner.java:58)
        at org.jberet.spi.JobExecutor$1.run(JobExecutor.java:100)
        at io.smallrye.context.impl.wrappers.SlowContextualRunnable.run(SlowContextualRunnable.java:19)
        at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:599)
        at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2516)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2495)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1521)
        at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
        at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:857)

@luca-bassoricci
Copy link
Contributor

I'va checked your code and after few tries I can say that it's just a question of timing; change batchlet code adding a sleep

System.out.println("HELLO WORLD PROCESSING ... RANDOM_ID: " + requestScopedService.getRandomUUID() + " MESSAGE: " + helloWorldMessage);
Thread.sleep(2000);
System.out.println("HELLO WORLD PROCESSING ... RANDOM_ID: " + requestScopedService.getRandomUUID() + " MESSAGE: " + helloWorldMessage);
return BatchStatus.COMPLETED.toString();

and code will fail at the first try,too.
IDK if executor used to execute jberet jobs has the responsability to propagate CDI scopes across thread because I don't really known how context propagation works (if involved).
Using a short-live scope as request one in a long running operation maybe is not a good pratice and can be better solution use JBeret's scopes.

@radcortez
Copy link
Collaborator

I looked into the spec, and there are no relevant mentions of CDI scopes and how they should work or be propagated. Due to JBatch's async nature, I think it is reasonable not to expect a request-scoped bean to be propagated.

Why did it work before? Well, a bug :)
quarkusio/quarkus#38605

I think we shouldn't propagate the request context automatically, especially because there may be cases where you don't have one. Even when you have one to propagate, any request data available may be expired or out of date.

My recommendation is to pass any request information as a job parameter. In other cases, like this reproducer where you have a request scoped bean with no actual request data, you could start the request scope manually by adding the @ActivateRequestContext annotation to the Batch component.

@radcortez radcortez closed this as not planned Won't fix, can't repro, duplicate, stale Jun 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants