Waiting for modal Window to close

I am converting a Swing application to use Vaadin instead of Swing. There is a library layer in between the application-level code and Swing that hopefully will allow us to modify just the library without having to change the application.

There is a pattern that is used consistently throughout the application that will show a Swing JDialog and wait for its result (the user clicked OK or Cancel) before continuing. The application-level code for this looks something like:

private void onButtonClick()
{
  if (window.showModal() == WindowResult.OK)
    doSomething();
}

In this case, showModal() blocks until the user has closed the Window. In Vaadin 7, this translates as a UI.addWindow(window) call, but this returns immediately so the result is undefined. I’ve tried adding a CloseListener to the Window and then blocking until the CloseListener is triggered, but the browser just hangs without displaying the Window. In concept, this would look like this (my implementation is different using Thread wait/notify, but this demostrates the issue in a more readable way):

Window window = new Window(title);
window.addCloseListener(new CloseListener()
{
    public void windowClose(CloseEvent e)
    {
        okToContinue = true;
    }
});
ui.addWindow(window);
while (!okToContinue)
    Thread.sleep(100);

Can anyone think of a way to achieve what I am trying to do in Vaadin without changing the application-level code?

Hi,

I’d say you have to change your application-level code. In Vaadin (or any servlet-based web technology) you just can’t hang on waiting like that. The browser will want the response to the request (creating the sub window), and then another request-response cycle takes place when user clicks the ok button.

This pattern, although common in non-distributed UI settings, is fundamentally at odds with how the HTTP request/response mechanism works. You can’t leave the request handling thread waiting for something to happen - you have to write a response to the client informing it that you want an event when something happens, return from the request handling, and then at some point you get a new request informing you that the event you wanted did happen. It is practically never correct to wait/sleep/whatever on a thread that you didn’t spawn yourself as a dedicated worker/background thread.

So, the usual pattern is that if you want to happen when the close event is sent, you call from the event listener. You
could
replicate the “wait-till-closed” pattern in Vaadin as well, but then you’d have to move the application logic to a separate background thread and be very careful with synchronizing all access to the UI. The problem with this is that normally you can only send UI changes back to the client when the client requests those changes - you’d have to use the push functionality or polling to be able to notify the client asynchronously.

Thanks for the responses, guys. I was afraid you would say that.

After some investigation, having to do this kind of change to our application-level code will double or triple the time to make the switch to Vaadin. That amount of extra time will probably mean that we abandon the switch completely. So I’m hoping not to give up on a library-level change we could make.

Is it possible to send back the servlet response after adding the modal window but before we begin to block waiting for the window to close?

I know this would leave this request thread busy until that user closes their modal window, but there is a small number of users per installation and it will be easy to configure a thread pool large enough to handle this case. There’s also the matter of timing out if the user never closes their modal dialog, but I can handle all that - let’s just focus on whether or not there is a method to send back the response to the browser. Something like this:

Window window = new Window(title);
window.setModal(true);
window.addCloseListener(new CloseListener()
{
   public void windowClose(CloseEvent e)
   {
       okToContinue = true;
   }
});
ui.addWindow(window);
[color=#FF0000]
SomeVaadinObject.sendServletResponse();
[/color]
while (!okToContinue)
    Thread.sleep(100);

That will actually work if your project is able to use the Vaadin 7.1 server push functionality. In that case, you can simply call ui.push() whenever you want to refresh the client state. Push has its own issues, though, especially wrt reliability.

The problem with doing it without push is that a single server request may contain multiple “events” (or server RPC calls more generally). They should each be handled before committing the response, otherwise the application will end up in a confused state. And you can’t send incremental changes in the same response because the browser or proxies might buffer the response in unpredictable ways.

That said, I did get it to kinda work in a toy test case, writing and committing the response manually and then letting the thread sleep. Whether it’s at all useful in any real-world application is another question.