Message between UI

Am trying to pass message from popup window to the parent window -

package com.example.vaadinexperiments;

import java.io.Serializable;
import java.lang.reflect.Method;

import javax.servlet.annotation.WebServlet;

import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.server.BrowserWindowOpener;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.JavaScript;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

@SuppressWarnings(“serial”)
@Theme(“vaadinexperiments”)
public class VaadinexperimentsUI extends UI {

@WebServlet(value = "/*", asyncSupported = true)
@VaadinServletConfiguration(productionMode = false, ui = VaadinexperimentsUI.class)
public static class Servlet extends VaadinServlet {
}

@Override
protected void init(VaadinRequest request) {
    final VerticalLayout layout = new VerticalLayout();
    layout.setMargin(true);
    setContent(layout);

    BrowserWindowOpener opener = new BrowserWindowOpener(MyPopupUI.class);
    opener.setFeatures("height=200,width=300,resizable");
    Button button = new Button("Pop It Up");
    opener.extend(button);
    
    layout.addComponent(button);
    
    addListener(new PopupCloseListener() {

        @Override
        public void popupClosed(PopupCloseEvent event) {
            Label newLabel = new Label(event.message);
            layout.addComponent(newLabel);
        }
        
    });
    
}

public static class MyPopupUI extends UI {
    @Override
    protected void init(VaadinRequest request) {
        getPage().setTitle("Popup Window");
        VerticalLayout content = new VerticalLayout();
        
        final TextField textField = new TextField("You name please");
        content.addComponent(textField);
        content.setComponentAlignment(textField, Alignment.TOP_CENTER);
        
        Button submitButton = new Button();
        submitButton.addClickListener(new Button.ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {
                String name = textField.getValue();                    
                JavaScript.eval("close()");
                getUI().close();
                fireEvent(new PopupCloseEvent(getUI(), name));
            }
            
        });

        content.addComponent(submitButton);
        content.setComponentAlignment(submitButton, Alignment.MIDDLE_CENTER);
        
        content.setSizeFull();
        setContent(content);
    }
    
}

public static class PopupCloseEvent extends Component.Event {
    public String message = "";
    public PopupCloseEvent(Component source, String message) {
        super(source);
        this.message = message;
    }
}

public interface PopupCloseListener extends Serializable {
    public void popupClosed(PopupCloseEvent event);
}

public void addListener(PopupCloseListener listener) {
    try {
        Method method = PopupCloseListener.class.getDeclaredMethod(
                "popupClosed", new Class[] { PopupCloseEvent.class });
        addListener(PopupCloseEvent.class, listener, method);
    } catch (final java.lang.NoSuchMethodException e) {
        throw new java.lang.RuntimeException(
                "Internal error, popupClosed method not found");
    }
}

public void removeListener(PopupCloseListener listener) {
    removeListener(PopupCloseEvent.class, listener);
}

}

The popupClosed method in the invoking UI is not getting invoked. Any Idea?

Let’s start with a question before answering your question :slight_smile: Do you have some specific reason why you really want to have a native browser popup window? Nowadays, using native popups are discouraged (although, there still are some valid use cases). If you just want to show data in a popup, I highly recommend using Vaadin’s
Window
. The limitation with that is that it’s just a simulated window, meaning, you cannot drag it outside your browser window (eg split content on two screens).

Now, to answer your question. There are multiple things wrong with your code, let’s go through them one by one.

First of all, you will have two UI classes, one instance of each UI. It’s your MyPopupUI that
sends
the event, while you attach your PopupCloseListener to the
VaadinexperimentsUI
. You never receive the event, because you are listening to the wrong object instance.

Secondly, even if you would listen to the correct UI instance, your code still wouldn’t work. That’s because you have two separate browser windows open, meaning, they each communicate
separately
with the server. So when you send a close event from your MyPopopUI and it’s received in the VaadinexpermentsUI, there’s no HTTP response going to the VaadinexperimentsUI that would actually trigger the layout change in the browser. You wouldn’t see the changes in the UI, until you trigger an HTTP request in the main browser window, for example, click a button. This can be solved by using
server push
. When using push, the server “pushes” any changes to the browser without there being an incoming HTTP request from the browser. In order to use push, you’ll need to annotate your UI with @Push and then wrap your UI changes inside an access() method (see documentation for details).

Thanks for the detailed answer. Yes, I have been using Vaadin Window for everything but just wanted to give a try with Native Popup.

So, if my uderstanding is correct, communication between two different UIs can be done only through Push. Please correct if my understanding is wrong.

Sorry for the late reply. Simplified, it’s not quite push that enables communication between two UIs. What push enables is sending “responses” to a UI instance outside the normal HTTP request-response cycle, which you need if you modify the UI’s state from some other thread that the thread handling an HTTP request originating from the modified UI. In your case, you have an HTTP request from UI “A”, but you modify the content of UI “B”. Without push, UI B will not get the changes before an action is triggered in the UI itself (eg, a button is clicked). Push enables us to send these modifications directly to the UI even though there is no event (= HTTP request) originating from that UI.

Makes Sense. Thanks.

Hello I need to implement something relative to this thread.
https://vaadin.com/forum#!/thread/15896058
Thanks in advance