访问CDI SessionScoped bean在Java 8并行流中不起作用

格雷格·诺

我无法理解为什么此代码不起作用。基本上,我想在parallelStream()函数期间从CDI ViewScoped Bean访问CDI SessionScoped Bean,但遇到了以下异常:

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

它在Wildfly 10.1中运行。

ViewScoped bean:

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;

@ViewScoped
@Named
public class TestController implements Serializable {
    private static final long serialVersionUID = 1L;

    @Inject SessionController sessionController;

    public void works() {
        List<Function<String, String>> functions = new ArrayList<>();
        functions.add((String input) -> {
            return sessionController.getSomething();
        });
        functions.add((String input) -> {
            return sessionController.getSomethingElse();
        });
        functions.stream().forEach(f -> f.apply("input"));
    }

    public void doesNotWork() {
        List<Function<String, String>> functions = new ArrayList<>();
        functions.add((String input) -> {
            return sessionController.getSomething();
        });
        functions.add((String input) -> {
            return sessionController.getSomethingElse();
        });
        functions.parallelStream().forEach(f -> f.apply("input"));
    }
}

SessionScoped bean:

import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named
@SessionScoped
public class SessionController implements Serializable {
    private static final long serialVersionUID = 1L;

    public String getSomething() {
        return "something";
    }
    public String getSomethingElse() {
        return "else";
    }
}

XHTML:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui">

    <h:head />

    <h:body>
        <h:form>
            <p:commandButton value="Works" action="#{testController.works}" />
            <br />
            <p:commandButton value="Does Not Work" action="#{testController.doesNotWork}" />
        </h:form>
    </h:body>
</html>

堆栈跟踪:

Caused by: org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.SessionScoped
    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)
    at com.SessionController$Proxy$_$$_WeldClientProxy.getSomething(Unknown Source)
    at com.TestController.lambda$3(TestController.java:33)
    at com.TestController.lambda$5(TestController.java:38)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
    at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

我们有理论认为会话可能是特定于线程的,但是没有确凿的证据。

也想知道是否有解决方法。实际的代码要比这复杂得多,因此我们无法在不失去并行流优势的情况下预先预加载SessionController结果。

ilia属

我认为您碰到的是使用并行流意味着您将在多个线程中运行。现在,这是CDI和上下文的问题,因为您需要进行上下文传播-例如,在主线程中,您当前具有(例如)会话上下文处于活动状态,但是当您创建另一个线程时,该线程在此处不处于活动状态。

规范中的第6.3章对此进行了更深入的描述,但为了给您提供简短的信息,默认情况下无法传播到其他线程的上下文这样做有充分的理由-这将非常昂贵(同步),并且您将需要解决非常奇怪的情况的负载,例如拥有一个线程无效会话,从而在其他线程对其进行操作时停用会话上下文。还有更多这样的情况。

此外,没有内置的解决方法。但是,您可以做的是实现自己的范围或增强现有的会话范围,但是我想那将非常复杂。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

从 CompletableFuture 线程中的主线程访问 SessionScoped bean 不起作用

SessionScoped托管bean注入不起作用

@SessionScoped CDI bean在注入时是不同的实例

从WebSocket @ServerEndpoint使用CDI @SessionScoped bean

@Schedule无法从@SessionScoped CDI bean获取数据

在同一会话中多次从另一个SessionScoped bean访问一个SessionScoped bean创建了一个新实例

同一会话中多个Sessionscoped Bean实例

无法访问其他Servlet中的SessionScoped实体

无法在HttpSessionListener中注入CDI @SessionScoped

无法将sessionScoped受管Bean注入其他受管Bean中

GWT和Java EE SessionScoped bean不持久

@SessionScoped bean是否有并发问题?

Sessionscoped托管bean不保存jsf变量

为什么不能在另一个bean的构造函数中获得SessionScoped bean的值?

通过<jsp:useBean>访问的会话范围的CDI bean似乎与servlet中的不同。

Servlet是Java EE中的CDI /托管Bean吗

需要能够@Inject Serializable Set到@SessionScoped bean

从另一个CDI bean获得对CDI bean的访问

当bean type参数是类型变量时,CDI typesafe分辨率在焊接2.2.6中不起作用

可访问性强制启用在android jelly bean中不起作用

Java LocalDate在Spring Bean中不起作用

libgdx中的音乐流不起作用(JAVA)

@Named @Sessionscoped的@PostConstruct在单个请求中多次调用

如何从 Java 类中的托管 bean 访问属性值?

是否可以将CDI Bean注入Java EE 6中的静态变量中?

黄瓜CDI注入不适用于src / main / java中的bean

需要CDI容器的单元测试导致java.lang.IllegalStateException:无法访问CDI

如何删除CDI会话作用域的bean

Servlet和CDI bean的作用域