Evandro Pomatti
Evandro Pomatti

Reputation: 15144

WebSocket endpoint and CDI injection: No active contexts for scope RequestScoped

I want to inject a @RequestScoped CDI bean in my Java EE 7 WebSocket endpoint.

However I am getting error WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped.

What am I doing wrong and why it is not possible?

@Named
@RequestScoped
public class Storage {

}

Which I @Inject in the endpoint like this:

@ServerEndpoint("/serverpush")
public class ContratoEndpoint {

    @Inject
    private Storage storage;

}

And I am getting the following stack trace:

org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped
    at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:689)
    at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:90)
    at org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:165)
    at org.jboss.weld.bean.ContextualInstance.getIfExists(ContextualInstance.java:63)
    at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:83)
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.getInstance(ProxyMethodHandler.java:125)

Upvotes: 4

Views: 3081

Answers (3)

CarlosGoncalves
CarlosGoncalves

Reputation: 406

Although Request Scope is not active in WebSockets (including Atmosphere) you can manually activate it using the approach proposed in a previous answer.

However, since CDI 2.0, you can use the @ActivateRequestContext annotation (from javax.enterprise.context.control.ActivateRequestContext) interceptor to do just that.

Either annotate the class or the method where you want to have Request Scope and this will activate it at the beginning of method execution and deactivate it when it finishes,

Upvotes: 0

Rouliboy
Rouliboy

Reputation: 1377

As @John mentioned, RequestContext is not active in WebSocket methods. Instead of using Deltaspike (which is a good option), you can also write your own Interceptor to activate/deactivate weld RequestContext.

As you are using Wildfly, you can use weld as a provided dependency :

<dependency>
    <groupId>org.jboss.weld</groupId>
    <artifactId>weld-core</artifactId>
    <version>2.2.12.Final</version>
    <scope>provided</scope>
</dependency>

Then you can define an InterceptorBinding @RequestContextOperation :

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.interceptor.InterceptorBinding;

@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface RequestContextOperation
{

}

And the corresponding RequestContextInterceptor where we activate/deactivate the RequestContext:

import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

import org.jboss.weld.context.RequestContext;
import org.jboss.weld.context.unbound.Unbound;

@Interceptor
@RequestContextOperation
public class RequestContextInterceptor {

    /** The RequestContext */
    @Inject
    @Unbound
    private RequestContext m_requestContext;

    /**
     * 
     * @param p_invocationContext
     * @return
     * @throws Exception
     */
    @AroundInvoke
    public Object activateRequestContext(final InvocationContext p_invocationContext) throws Exception {
        try {
            m_requestContext.activate();
            return p_invocationContext.proceed();
        } finally {
            m_requestContext.invalidate();
            m_requestContext.deactivate();
        }
    }
}

You can then use the @RequestContextOperation annotation on your class or on a specific method :

@ServerEndpoint("/serverpush")
public class ContratoEndpoint {

    @Inject
    private Storage storage;

    @OnMessage
    @RequestContextOperation
    public String handleMessage(String message){

        // Here the @RequestScoped bean is valid thanks to the @RequestContextOperation InterceptorBinding
        storage.yourMethod();
        ....
    }

}

Upvotes: 3

John Ament
John Ament

Reputation: 11723

WebSockets do not initialize a request scope context for their method invocations. You can use deltaspike context control to manually start a request context for the method invocation.

Upvotes: 2

Related Questions