I have an existing endpoint calling some function, and it works fine when doing a rest call to the endpoint. Then I want to create a scheduler that will call that function regularly. The scheduler itself works as expected, but now there is an unexpected exception in the function during a scheduled function. The rest of the endpoint still works. Since the problem seems to be a RequestScoped bean, I tried ActivateRequestContent, but nothing changes.
Below is minimally reproduicable example that better explain the problem.
EDIT: I don't want to modify the service or some external cron. I would prefer the solution to be within Scheduler.
I have a resource:
@Path("/hello")
public class GreetingResource {
@Inject
GreetingService greetingService;
@GET
public String hello() {
return greetingService.getGreetings();
}
}
A service:
@ApplicationScoped
public class GreetingService {
@Inject
RequestBean requestBean;
public String getGreetings() {
//do logic, call other services, save to DB, etc
if (requestBean.getAcceptLanguage().equals("en")) {
return "Hello from RESTEasy Reactive";
} else {
return "Hola desde RESTEasy Reactive";
}
}
}
And a RequestScoped bean.
@RequestScoped
public class RequestBean {
private String acceptLanguage;
RequestBean(HttpHeaders httpHeaders) {
acceptLanguage = httpHeaders.getHeaderString(HttpHeaders.ACCEPT_LANGUAGE);
if (acceptLanguage == null || acceptLanguage.isBlank()) {
this.acceptLanguage = "en";
}
}
public String getAcceptLanguage() {
return acceptLanguage;
}
}
The endpoints work in test and postman.
But now I need to do the exact same work regularly.
So I added the scheduler.
@ApplicationScoped
public class Scheduler {
@Inject
GreetingService greetingService;
@Scheduled(every = "10s")
@ActivateRequestContext
public void scheduledTask() {
try {
Log.info("Scheduler is starting");
greetingService.getGreetings();
Log.info("Scheduler is finished");
} catch (Exception e) {
Log.error("Error while running scheduler", e);
}
}
}
I expected no exception, but I got an exception inside the scheduledTask.
java.lang.IllegalStateException: No RESTEasy Reactive request in progress
at org.jboss.resteasy.reactive.server.injection.ContextProducers.getContext(ContextProducers.java:149)
at org.jboss.resteasy.reactive.server.injection.ContextProducers.headers(ContextProducers.java:52)
at org.jboss.resteasy.reactive.server.injection.ContextProducers_ProducerMethod_headers_VA74pGGn-tu4h7_tlI2NceCHbzU_Bean.doCreate(Unknown Source)
at org.jboss.resteasy.reactive.server.injection.ContextProducers_ProducerMethod_headers_VA74pGGn-tu4h7_tlI2NceCHbzU_Bean.create(Unknown Source)
at org.jboss.resteasy.reactive.server.injection.ContextProducers_ProducerMethod_headers_VA74pGGn-tu4h7_tlI2NceCHbzU_Bean.create(Unknown Source)
at io.quarkus.arc.impl.RequestContext$1.get(RequestContext.java:79)
at io.quarkus.arc.impl.RequestContext$1.get(RequestContext.java:75)
at io.quarkus.arc.generator.Default_jakarta_enterprise_context_RequestScoped_ContextInstances.c2(Unknown Source)
at io.quarkus.arc.generator.Default_jakarta_enterprise_context_RequestScoped_ContextInstances.computeIfAbsent(Unknown Source)
at io.quarkus.arc.impl.RequestContext.getIfActive(RequestContext.java:75)
at io.quarkus.arc.impl.ClientProxies.getSingleContextDelegate(ClientProxies.java:28)
at jakarta.ws.rs.core.ContextProducers_ProducerMethod_headers_VA74pGGn-tu4h7_tlI2NceCHbzU_ClientProxy.arc$delegate(Unknown Source)
at jakarta.ws.rs.core.ContextProducers_ProducerMethod_headers_VA74pGGn-tu4h7_tlI2NceCHbzU_ClientProxy.getHeaderString(Unknown Source)
at com.example.RequestBean.<init>(RequestBean.java:12)
at com.example.RequestBean_Bean.doCreate(Unknown Source)
at com.example.RequestBean_Bean.create(Unknown Source)
at com.example.RequestBean_Bean.create(Unknown Source)
at io.quarkus.arc.impl.RequestContext$1.get(RequestContext.java:79)
at io.quarkus.arc.impl.RequestContext$1.get(RequestContext.java:75)
at io.quarkus.arc.generator.Default_jakarta_enterprise_context_RequestScoped_ContextInstances.c0(Unknown Source)
at io.quarkus.arc.generator.Default_jakarta_enterprise_context_RequestScoped_ContextInstances.computeIfAbsent(Unknown Source)
at io.quarkus.arc.impl.RequestContext.getIfActive(RequestContext.java:75)
at io.quarkus.arc.impl.ClientProxies.getSingleContextDelegate(ClientProxies.java:28)
at com.example.RequestBean_ClientProxy.arc$delegate(Unknown Source)
at com.example.RequestBean_ClientProxy.getAcceptLanguage(Unknown Source)
at com.example.GreetingService.getGreetings(GreetingService.java:16)
at com.example.GreetingService_ClientProxy.getGreetings(Unknown Source)
at com.example.Scheduler.scheduledTask(Scheduler.java:21)
at com.example.Scheduler_Subclass.scheduledTask$$superforward(Unknown Source)
at com.example.Scheduler_Subclass$$function$$1.apply(Unknown Source)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:73)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:62)
at io.quarkus.arc.impl.ActivateRequestContextInterceptor.invoke(ActivateRequestContextInterceptor.java:124)
at io.quarkus.arc.impl.ActivateRequestContextInterceptor.aroundInvoke(ActivateRequestContextInterceptor.java:33)
at io.quarkus.arc.impl.ActivateRequestContextInterceptor_Bean.intercept(Unknown Source)
at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42)
at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:30)
at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:27)
at com.example.Scheduler_Subclass.scheduledTask(Unknown Source)
at com.example.Scheduler_ClientProxy.scheduledTask(Unknown Source)
at com.example.Scheduler_ScheduledInvoker_scheduledTask_b06a23f86c5479393959068a663c2a2a98c84093.invokeBean(Unknown Source)
at io.quarkus.scheduler.common.runtime.DefaultInvoker.invoke(DefaultInvoker.java:24)
at io.quarkus.scheduler.common.runtime.StatusEmitterInvoker.invoke(StatusEmitterInvoker.java:35)
at io.quarkus.scheduler.runtime.SimpleScheduler$ScheduledTask.doInvoke(SimpleScheduler.java:443)
at io.quarkus.scheduler.runtime.SimpleScheduler$ScheduledTask$2.call(SimpleScheduler.java:425)
at io.quarkus.scheduler.runtime.SimpleScheduler$ScheduledTask$2.call(SimpleScheduler.java:422)
at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$0(ContextImpl.java:178)
at io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:279)
at io.vertx.core.impl.ContextImpl.lambda$internalExecuteBlocking$2(ContextImpl.java:210)
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:1512)
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)
Relevant dependency:
<quarkus.platform.version>3.8.5</quarkus.platform.version>
...
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-scheduler</artifactId>
</dependency>
EDIT 2: Solutions that do work, but are not ok.
- Rework service -> service is huge, dont have time.
- External cron job calls working endpoint -> i cant control external apps, problems with Authorization
- calling shell with curl my endpoint -> seems weird, problems with Authorization
- Use code from test in scheduler
given()
.when()
.get("/hello")
.then()
.statusCode(200);
-> This looks very nice compared to 1-3 solutions, but having restassured import in main code feels wrong. Is it wrong?
HttpHeadersbean cannot work outside of an HTTP request. You need to find another way how to obtain the "current" language in the context of a scheduler.