0

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.

  1. Rework service -> service is huge, dont have time.
  2. External cron job calls working endpoint -> i cant control external apps, problems with Authorization
  3. calling shell with curl my endpoint -> seems weird, problems with Authorization
  4. 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?

1
  • 2
    Clearly the HttpHeaders bean 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. Commented Aug 6, 2024 at 14:05

1 Answer 1

1

You can try to use Quarkus RestClient to access the /hello path. If you need to deal with authentication, you can do something like:

Class to access API

import com.fasterxml.jackson.databind.JsonNode;
import jakarta.ws.rs.*;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

@RegisterRestClient
public interface Api {
    @GET
    @Path("/hello")
    JsonNode hello(@HeaderParam("Authorization") String token);
}

And then your Scheduled thing

@RestClient
Api api;
@Scheduled(every = "10s")
void doTheJob(){
  String token;
  // do something to get the token
  api.hello(token);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.