Vaadin CDI View, Navigator and CDI event does not work together

Hi,

I have been using Vaadin CDI and CDI event without any problem until I decide to add navigator, and things fall apart. At first I thought it was something wrong with the component. Then I created a simple, test application and found out that the problem is probably with the CDI and navigator. So here’s my code:

First, the UI, just a standard, CDIUI, that registeres a CDIViewProvider and navigates to the view.

[code]
package com.example.GridLayoutProblemDemo;

import javax.inject.Inject;
import com.vaadin.annotations.Theme;
import com.vaadin.cdi.CDIUI;
import com.vaadin.cdi.CDIViewProvider;
import com.vaadin.navigator.Navigator;
import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.UI;

/**

  • This UI is the application entry point. A UI may either represent a browser window

  • (or tab) or some part of an HTML page where a Vaadin application is embedded.

  • The UI is initialized using {@link #init(VaadinRequest)}. This method is intended to be

  • overridden to add component to the user interface and initialize non-component functionality.
    */
    @CDIUI(“”)
    @Theme(“mytheme”)
    public class MyUI extends UI {

    @Inject CDIViewProvider viewProvider;

    @Override
    protected void init(VaadinRequest vaadinRequest) {
    // this works
    // setContent(layout);
    Navigator navigator = new Navigator(this, this);
    navigator.addProvider(viewProvider);
    navigator.navigateTo(“grid”);
    }

}
[/code]The view is a CDIView, creates a button, which fires a CDI event everytime clicked. The view also observes the event and increases the number on the button as a response.

If the view is @UIScoped, @NormalUIScoped or @SessionScoped, the application breaks. I will further describe what happened. If there’s no scope annotation, it will work. But then how can I keep, if I want, an instance of this view around all the time during the user session even if it’s not on user’s screen?

package com.example.GridLayoutProblemDemo;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import com.vaadin.cdi.CDIView;
import com.vaadin.cdi.UIScoped;
import com.vaadin.navigator.View;
import com.vaadin.ui.Button;
import com.vaadin.ui.VerticalLayout;

// @UIScoped - tried, does not work, two instance
// @javax.enterprise.context.SessionScoped - tried, does not work, two instance
// @NormalUIScoped - tried, does not work
// no annotation - work, but what if I want to keep it during the session?
@UIScoped
@CDIView("grid")
public class DemoView extends VerticalLayout implements View, Serializable{

    private static final long serialVersionUID = 1L;
    private int serial=10;
    Button button;
    
    private String thisInfo() {
        return this.getClass().getName()+"/"+this;
    }

    
    @PostConstruct
    public void postConstruct() {
        System.err.println("Post construct:"+thisInfo());
    }
    
    @Inject javax.enterprise.event.Event<GridButtonClickEvent> event;
    
    public DemoView () {
        System.err.println("New: "+thisInfo());
        button = new Button(String.valueOf(serial));
        button.addClickListener(e->{
            event.fire(new GridButtonClickEvent());
        });
        addComponent(button);
    }

    public void onEvent(@Observes GridButtonClickEvent e) {
        System.err.println("Observed an event by: "+thisInfo());
        serial++;
        button.setCaption(String.valueOf(serial));
    }
}

The event, it’s just an empty object.

package com.example.GridLayoutProblemDemo;

public class GridButtonClickEvent {

}

Now the output:

=================================================================
Vaadin is running in DEBUG MODE.
Add productionMode=true to web.xml to disable debug features.
To show debug window, add ?debug to your application URL.

10:28:08,398 ERROR [stderr]
(default task-4) New: com.example.GridLayoutProblemDemo.DemoView/com.example.GridLayoutProblemDemo.DemoView@20aa91ce
10:28:08,409 ERROR [stderr]
(default task-4) Post construct:com.example.GridLayoutProblemDemo.DemoView/com.example.GridLayoutProblemDemo.DemoView@20aa91ce
10:28:14,192 ERROR [stderr]
(default task-6) New: com.example.GridLayoutProblemDemo.DemoView/com.example.GridLayoutProblemDemo.DemoView@2017b02c
10:28:14,192 ERROR [stderr]
(default task-6) Post construct:com.example.GridLayoutProblemDemo.DemoView/com.example.GridLayoutProblemDemo.DemoView@2017b02c
10:28:14,192 ERROR [stderr]
(default task-6) Observed an event by: com.example.GridLayoutProblemDemo.DemoView/com.example.GridLayoutProblemDemo.DemoView@2017b02c
10:28:18,207 ERROR [stderr]
(default task-7) Observed an event by: com.example.GridLayoutProblemDemo.DemoView/com.example.GridLayoutProblemDemo.DemoView@2017b02c
10:28:18,723 ERROR [stderr]
(default task-8) Observed an event by: com.example.GridLayoutProblemDemo.DemoView/com.example.GridLayoutProblemDemo.DemoView@2017b02c

Here’s what happened:

During the call navigator.navigateTo(“grid”) by the UI, an instance of the View was created. The view was shown on the browser.
After I clicked the button, a new instance of the View was created during the call “event.fire(new GridButtonClickEvent())”. This is strange. By being a UIScoped bean, I was expecting the container use the same object, rather than creating a new one.
Then, the fired event was observed by the second initiated View. The first View with the UI didn’t receive the event and didn’t respond to the click.

Am I doing something wrong here? Or is this a bug of Vaadin CDI or the framework? I am also attaching the demo project here.

I tested the above code with Vaadin 8.1.6, Vaadin-CDI 2.0.0, and server is WildFly Full 10.1.0.Final (WildFly Core 2.2.0.Final)

Thanks for helping me out!

Best regards,

Bing

38006.zip (31.1 KB)

Description of this fairly recently filed issue is a bit short, but looks like to be related. If you feel the same, could you add your comments to GitHub.

https://github.com/vaadin/cdi/issues/224

I’m not sure if it’s related. That description seems to complain CDI navigator does not fire certain event, while my problem is CDIView does not receive events. More specifically, the problem is:

  • UIScoped, NormalUIScoped or SessionScoped beans all should have just one instance per UI or user session
  • However. during event firing, it seems that the CDI container does not realize there is already an instance
  • Thus, a new instance was initiated, and that new instance received, or “observed” the event
  • However, the first CDIView, more importantly, the CDIView that was actually shown to the user, did not receive the event.

I’m not sure if it’s my problem, so I posted the code above. If you think it’s not my problem but actually an issue with Vaadin CDI, I will report an issue on Github.

Bing

It seems like a very old bug: https://github.com/vaadin/cdi/issues/134
Giving it some thumb ups to prioritize it a bit.


A^2

Or maybe not. Just reported as fixed in Vaadin CDI Add-on 3.0.0.alpha1

https://github.com/vaadin/cdi/issues/228


A^2

Yes, issue fixed in 3.0.0.alpha1, all good.

Bing