Конечная точка WebSocket и инъекция CDI: нет активных контекстов для области действия RequestScoped
Я хочу ввести @RequestScoped
Компонент CDI в моей конечной точке Java EE 7 WebSocket.
Однако я получаю ошибку WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped
,
Что я делаю не так и почему это невозможно?
@Named
@RequestScoped
public class Storage {
}
Который я @Inject
в конечной точке, как это:
@ServerEndpoint("/serverpush")
public class ContratoEndpoint {
@Inject
private Storage storage;
}
И я получаю следующую трассировку стека:
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)
3 ответа
Как упомянул @Джон, RequestContext
не активен в методах WebSocket. Вместо того, чтобы использовать Deltaspike (что является хорошим вариантом), вы также можете написать свой собственный перехватчик, чтобы активировать / деактивировать сварку RequestContext
,
Поскольку вы используете Wildfly, вы можете использовать сварку в качестве предоставленной зависимости:
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core</artifactId>
<version>2.2.12.Final</version>
<scope>provided</scope>
</dependency>
Затем вы можете определить 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
{
}
И соответствующий RequestContextInterceptor
где мы активируем / деактивируем 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();
}
}
}
Затем вы можете использовать @RequestContextOperation
аннотации к вашему классу или к определенному методу:
@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();
....
}
}
WebSockets не инициализируют контекст области запроса для своих вызовов методов. Вы можете использовать контекстное управление deltaspike, чтобы вручную запустить контекст запроса для вызова метода.
Хотя Request Scope не активен в WebSockets (включая Atmosphere), вы можете активировать его вручную, используя подход, предложенный в предыдущем ответе .
Однако, начиная с CDI 2.0, вы можете использовать
Либо аннотируйте класс или метод, где вы хотите иметь область запроса, и это активирует его в начале выполнения метода и деактивирует его, когда он завершится,