Asynchronous 带有Vaadin的EJB异步线程,注入不工作(Vaadin 8,Vaadin CDI,EJB ManagedExecutorService线程)

Asynchronous 带有Vaadin的EJB异步线程,注入不工作(Vaadin 8,Vaadin CDI,EJB ManagedExecutorService线程),asynchronous,ejb,vaadin,cdi,vaadin8,Asynchronous,Ejb,Vaadin,Cdi,Vaadin8,我是Vaadin框架和JavaEE的新手。 我正在使用VaadinFramework8.1.6,VaadinCDI插件2.0.0,运行在Tomee7.0.2服务器上。 我正在尝试使用EJB管理的线程池(ManagedExecutorService)进行异步/后台数据加载。 我在使用注射的豆子时遇到问题 所有注入的bean都可以在单线程UI中正常工作。当我想在后台线程中使用一些注入bean时,其中一些bean无法访问 Vaadin CDI用户界面 @CDIUI("") @Theme("myuith

我是Vaadin框架和JavaEE的新手。 我正在使用VaadinFramework8.1.6,VaadinCDI插件2.0.0,运行在Tomee7.0.2服务器上。 我正在尝试使用EJB管理的线程池(ManagedExecutorService)进行异步/后台数据加载。 我在使用注射的豆子时遇到问题

所有注入的bean都可以在单线程UI中正常工作。当我想在后台线程中使用一些注入bean时,其中一些bean无法访问

Vaadin CDI用户界面

@CDIUI("")
@Theme("myuitheme")
@Push
public class MyUI extends UI {

    // ...

    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
    @VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
        public static class MyUIServlet extends VaadinCDIServlet {
        }
    }
数据服务

@NormalUIScoped
public class DataService {

    // consts, functions, ...

    public Data getData(String param) {
        // call REST service, load, decode and aggregate data
        // ...
    }
}
MyView

@CDIView(value=MyView.VIEWNAME, supportsParameters=true)
public class MyView extends Panel implements View {

    public final static String VIEWNAME = "main";

    @Resource
    private ManagedExecutorService executor;

    @Inject
    private MyUI ui;

    @Inject
    private DataService dataService;

    public void fun1() {
        System.out.println("fun1, thread_id: " + Thread.currentThread().getId());
        Future<Data> dataFuture = executor.submit(() -> loadData(param));
        // ...
    }

    private Data loadData(String param) {

        // launched in executor thread
        System.out.println("loadData, thread_id: " + Thread.currentThread().getId());

        // accessing injected ui works fine, the ui is updated correctly
        ui.access(() -> {
            clearMyView();
        }

        // accessing injected dataService doesn't work
        // exception: java.lang.IllegalStateException
        Data data = dataService.getData(param);

        ui.access(() -> {
            updateMyView(data);
        }

        return data;
    }

    //...

}
@CDIView(value=MyView.VIEWNAME,supportsParameters=true)
公共类MyView扩展面板实现视图{
公共最终静态字符串VIEWNAME=“main”;
@资源
私有ManagedExecutorService执行器;
@注入
私人密室;
@注入
私有数据服务数据服务;
公共图书馆1({
System.out.println(“fun1,thread_id:+thread.currentThread().getId());
Future dataFuture=executor.submit(()->loadData(param));
// ...
}
私有数据加载数据(字符串参数){
//在执行器线程中启动
System.out.println(“loadData,thread_id:+thread.currentThread().getId());
//访问注入的ui工作正常,ui更新正确
ui.access(()->{
clearMyView();
}
//访问注入的数据服务不起作用
//异常:java.lang.IllegalStateException
数据数据=dataService.getData(参数);
ui.access(()->{
更新视图(数据);
}
返回数据;
}
//...
}
日志

fun1,螺纹编号:77

加载数据,线程id:102

例外情况

java.lang.IllegalStateException:无法恢复的会话数据 DataService,WebBeansType:MANAGED,名称:null,API 类型:[xxx.DataService,java.lang.Object], 限定符:[javax.enterprise.inject.Default,javax.enterprise.inject.Any] 在 com.vaadin.cdi.internal.UIScopedContext.getContextualStorage(UIScopedContext.java:68) 在 org.apache.deltaspike.core.util.context.AbstractContext.get(AbstractContext.java:113) 在 com.vaadin.cdi.internal.AbstractVaadinContext.get(AbstractVaadinContext.java:154) 位于com.vaadin.cdi.internal.ContextWrapper.get(ContextWrapper.java:49) 在 org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.getContextAlinstance(NormalScopedBeanInterceptorHandler.java:101) 在 org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.get(NormalScopedBeanInterceptorHandler.java:71) 在 xxx.myui.data.DataService$$OwbNormalScopeProxy0.getData(xxx/myui/data/DataService.java) 位于xxx.myui.view.MyView.loadData(MyView.java:855) xxx.myui.view.MyView.lambda$27(MyView.java:645) org.apache.openejb.threads.task.cucalable$1.call(cucalable.java:34) 位于org.apache.openejb.threads.task.CUTask.invoke(CUTask.java:100) org.apache.openejb.threads.task.CUCallable.call(CUCallable.java:31) 位于java.util.concurrent.FutureTask.run(未知源代码) 位于的java.util.concurrent.ThreadPoolExecutor.runWorker(未知源) java.util.concurrent.ThreadPoolExecutor$Worker.run(未知源代码)位于 java.lang.Thread.run(未知源)


有什么问题吗?

您是否有注释的特定原因
@NormalUIScoped
?如果没有,则此更改有效

// @NormalUIScoped // why is this ?
@UIScoped @Stateful
public class DataService {
   ...
}

谢谢。这似乎很好。根据Vaadin CDI文档(),我一直在使用
@NormalUIScoped
@UIScoped
似乎是注入直接bean引用的有限版本,
@NormalUIScoped
是“正常的”CDI是一种注入代理对象的方法。但是这个代理在另一个线程中运行时,在查找它的bean时会遇到问题。