Search code examples
asynchronousejbvaadincdivaadin8

EJB async thread with Vaadin, inject not working (Vaadin 8, Vaadin-CDI, EJB ManagedExecutorService thread)


I'm new into Vaadin Framework and Java EE. I'm using Vaadin Framework 8.1.6, Vaadin-CDI plugin 2.0.0, running on TomEE 7.0.2 server. I'm trying to make asynchronous/background data loading using EJB managed thread pool (ManagedExecutorService). I have problems using some injected beans.

All injected beans are working fine in single-threaded UI. When I want to use some injected beans in background thread, some of them cannot be accessed.

Vaadin-CDI UI

@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 {
        }
    }

DataService

@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;
    }

    //...

}

Log

fun1, thread_id: 77

loadData, thread_id: 102

Exception

java.lang.IllegalStateException: Session data not recoverable for DataService, WebBeansType:MANAGED, Name:null, API Types:[xxx.DataService,java.lang.Object], Qualifiers:[javax.enterprise.inject.Default,javax.enterprise.inject.Any] at com.vaadin.cdi.internal.UIScopedContext.getContextualStorage(UIScopedContext.java:68) at org.apache.deltaspike.core.util.context.AbstractContext.get(AbstractContext.java:113) at com.vaadin.cdi.internal.AbstractVaadinContext.get(AbstractVaadinContext.java:154) at com.vaadin.cdi.internal.ContextWrapper.get(ContextWrapper.java:49) at org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.getContextualInstance(NormalScopedBeanInterceptorHandler.java:101) at org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.get(NormalScopedBeanInterceptorHandler.java:71) at xxx.myui.data.DataService$$OwbNormalScopeProxy0.getData(xxx/myui/data/DataService.java) at xxx.myui.view.MyView.loadData(MyView.java:855) at xxx.myui.view.MyView.lambda$27(MyView.java:645) at org.apache.openejb.threads.task.CUCallable$1.call(CUCallable.java:34) at org.apache.openejb.threads.task.CUTask.invoke(CUTask.java:100) at org.apache.openejb.threads.task.CUCallable.call(CUCallable.java:31) at java.util.concurrent.FutureTask.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source)

What is wrong ?


Solution

  • Did you have some specific reason for annotation @NormalUIScoped? If not this change works

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