0
votes

I have a problem with Injecting @RequestScoped Bean into Runnable class.

This is my Resource class

@ApplicationScoped
@Path("/process")
public class TestResource {
    private static ExecutorService executor = Executors.newFixedThreadPool(20);

    @POST
    public void process(Integer id, @Suspended AsyncResponse ar) {
        TestRunnable testRunnable = new TestRunnable();
        testRunnable.setId(id);

        executor.execute(() -> {
            testRunnable.run();

            ar.resume("OK");
        });
    }

And here is my TestRunnable class:

public class TestRunnable implements Runnable {
    private Integer id;

    private ServiceBean serviceBean;

    public void asyncProcess() {
        serviceBean = CDI.current().select(ServiceBean.class).get();
        serviceBean.process(id);
    }

    @Override
    public void run() {
        asyncProcess();
    }

    public void setId(Integer id) {
        this.id = id;
    }
}

When I try to connect to the endpoint I get the following error?

WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped

I am sure that the problem lies in wrong injection of my ServiceBean...

1
If you are getting this exception from the statement testRunnable.run(); AND you are running on a fairly recent application server, you can try injecting the ManagedExecutorService, instead of creating your own: @Resource ManagedExecutorService executor. The rest of the code remains the same. If this works for you, you can even configure the application server to produce a customized ManagedExecutorService (e.g. with 20 threads).Nikos Paraskevopoulos

1 Answers

1
votes

I am sure that the problem lies in wrong injection of my ServiceBean

Nope. The problem is exactly as the exception message says:

No active contexts for scope type javax.enterprise.context.RequestScoped

There is no request scope avaliable at all.

The request scope is only available to the code running within the original thread created by the HTTP request. But you're here basically creating a new thread which runs completely independently (asynchronously!) from the original thread created by the HTTP request.

Pass the desired data from the request scope as a constructor argument instead.

TestRunnable testRunnable = new TestRunnable(serviceBean);

Or even better, move the process() logic into TestRunnable itself.

TestRunnable testRunnable = new TestRunnable(id);