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)