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)
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();
....
}
}