Конечная точка 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, вы можете использоватьаннотация (из) перехватчик, чтобы сделать именно это.

Либо аннотируйте класс или метод, где вы хотите иметь область запроса, и это активирует его в начале выполнения метода и деактивирует его, когда он завершится,

Другие вопросы по тегам