0

I'm currently playing around with Vaadin 8.4.2 + CDI.

I got a simple view with a simple model class Person that has 2 Properties (lastname and firstname). I have a simple View (GreetPersonView) and a @ViewScopedcomponent (MessageDisplay) that is injected into the view. When the button is pressed, an event is fired and it the MessageDisplay class observes this event and when the event is fired it will display a simple message (see code below). Now, when MessageDisplay is ViewScoped, the Observer does not get triggered. When I change it to UIScoped, it works. Is this intended? Is this Bug in Vaadin?

@CDIView(GreetPersonView.VIEWNAME)
public class GreetPersonView extends CustomComponent implements View {
public final static String VIEWNAME = "greetperson";


private Person person;

@Inject
private javax.enterprise.event.Event<String> messageEvent;

@Inject
private MessageDisplay messageDisplay;

@Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
    person = new Person();

    VerticalLayout layout = new VerticalLayout();

    Binder<Person> binder = new Binder<>();
    person.setFirstName("John");
    person.setLastName("Doe");

    // An input field for editing injected data
    TextField firstName = new TextField("First name");
    layout.addComponent(firstName);
    TextField lastName = new TextField("Last name");
    layout.addComponent(lastName);

    binder.bind(firstName,
            Person::getFirstName,
            Person::setFirstName);
    binder.bind(lastName,
            Person::getLastName,
            Person::setLastName);

    binder.readBean(person);

    Button helloButton = new Button("Say Hello");
    layout.addComponent(helloButton);
    helloButton.addClickListener(e -> {
        try {
            binder.writeBean(person);
            messageEvent.fire(person.getFirstName() + " " + person.getLastName());
        } catch (ValidationException e1) {
            Notification.show("Person could not be saved, " +
                    "please check error messages for each field.");
        }
    });

    layout.addComponents(messageDisplay);

    setCompositionRoot(layout);

}
}


@ViewScoped
public class MessageDisplay extends Panel {
    private Label lblMessage;

    public MessageDisplay() {
        lblMessage = new Label("Nothing to show");
        setContent(lblMessage);
    }

    public void onMessageReceived(@Observes String message) {
        this.lblMessage.setValue("Hello " + message);
    }
}
Kukeltje
  • 12,223
  • 4
  • 24
  • 47
Patrick Zinner
  • 356
  • 4
  • 17

1 Answers1

0

CDI Events are POJOs. So first you should create custom event like MessageEvent, I assume that you want to have String message there are as data, and have getMessage() and setMessage() methods respectively as well as constructor with String parameter for message.

Then do

@Inject
private javax.enterprise.event.Event<MessageEvent> messageEvent;
...
messageEvent.fire(new MessageEvent(person.getFirstName() + " " + person.getLastName()));
...

And observe it

public void onMessageReceived(@Observes MessageEvent messageEvent) {
     this.lblMessage.setValue("Hello " + messageEvent.getMessage());
}
Tatu Lund
  • 9,949
  • 1
  • 12
  • 26
  • I'm sorry, but this answer is totally wrong. Because a) Event works with UIScope, b) your solution does not work either c) Event does not care which type you are using. – Patrick Zinner Jun 09 '18 at 13:07
  • Which version of CDI add-on you use? Which application container you use? In the end this should work. So you may have spotted a bug. Have you checked also this one https://github.com/vaadin/cdi/issues/235 ? – Tatu Lund Jun 09 '18 at 15:26
  • Event can be used, but usually in applications which are more complex than demos, you need many specific Events and hence typing the via this POJO approach is necessary. The point of my earlier answer was that I suspected there was a conflict, but apparently that was not a case. – Tatu Lund Jun 10 '18 at 08:48