Sorry for breaking your features - Part 2

Leif Åstrand
Leif Åstrand
On Nov 6, 2012 11:34:00 AM

In Sorry for breaking your features - Part 1, I explained why logout and dynamic theme selection can not be done in the same way as in Vaadin 6 and showed how to do the same with Vaadin 7. Today I will give you the same treatment for opening popup windows and downloading files.

Opening Popup Windows

Vaadin 6 lets you use Application.addWindow to register a new browser window followed by to open the window in the browser - at least in theory. The first problem with that approach is that web browsers are very suspicious of when the server asks for a popup to be opened whereas it’s considered acceptable when the command comes directly from the user.

In the scenario above, a request to the server is sent as direct consequence of some user action (e.g. clicking a button) but the command that should open the popup window comes as part of the response, which is just a secondary effect of the user’s action. This makes the browser suspect the popup contains something that the user didn’t ask for, and it will therefore block the popup unless the browser has been configured to accept popups from the domain.

This could be circumvented in Vaadin 6 by instead creating a Link pointing to Window.getURL() even though that approach also had some problems. If the user pressed the same button or link twice, the same Vaadin Window instance is might be opened in several browser windows. This easily leads to a situation where the state of one of the windows is no longer up to date, giving Vaadin no other choice than to display a scary Out of sync error message.

While you could keep your fingers crossed and hope for the best with the Out of sync issue, the problem with popup blockers was harder to avoid if the UI design stipulated something other than a link. The solution to this is the BrowserPopupOpener extension added in beta 6 that you can use to make any Vaadin component open a popup window when clicked - with the magic sauce being that information about the popup will already be present in the browser so it can be opened without asking the server for advice. An example of this is shown in the Opening a UI in a popup window tutorial.

To avoid wasting server-side memory for popup windows that may never get opened, you should bind the potentially opened popup to a UI class so that an actual instance of your UI will not be created until the popup is actually opened. This also solves the problem with Out of sync messages as a new UI instance is created for each popup. One remaining issue is however that you can’t easily send parameters to the new UI to dynamically choose what content to show in it. This will be redeemed through ticket #10093.

Offering a File for Download

This sounds very easy in theory, but there are once again some problems with the natural way of doing this using the Vaadin 6 API. The first problem is the same as with opening popup windows: browsers get suspicious if it’s the server and not the user that says that the file should be downloaded. Some browsers are quite sloppy with this as unwanted downloads are not as common as unwanted popup windows while other browsers are working in ways that can bring total havoc to the user experience. The workaround to this issue is however the same as for opening popup windows: the FileDownloader extension released in beta 6 can be attached to any component to make it start a download without first asking the server. Using Link is also a good solution when the UI design permits.

Another problem in Vaadin 6 has been that dynamic content is most easily generated by creating a StreamResource that got attached to the Application, where it usually consumed memory until the user’s session timed out. FileResource, ClassResource or any custom ApplicationResource did also leak memory in the same way unless very carefully managed by the application developer.

The remedy to this problem was the introduction of ConnectorResource which is instead tied to a component or extension. This means that when a component is no longer used, any dynamic Resource used by that component can also be discarded. This works very nicely for e.g. icons and similar files but would not help at all with downloads started using as those resource instances would then be kept along for the entire lifetime of the UI. The FileDownloader extension that solves the problem with browsers blocking downloads is luckily also helping here - the extension is attached to the component that starts the download which means that memory used by extension as well as its Resource is released when the target component is no longer used. The Letting the user download a file tutorial shows how this is done in practise.

There are a couple of situations where this doesn’t work, most notably if generating e.g. a report in the background while showing a progress indicator and then automatically starting the download once the file has been generated. The most reliable workaround to this is to instead open a window saying that the report has been generated and that it can be downloaded by clicking a Link or Button in the window. If this is not acceptable for usability reasons, you could instead use a RequestHandler for serving the file and manually constructing the URL that the RequestHandler handles. For constructing the URL, you can use Page.getLocation() that was added in beta 4.

The End - for now

We have changed many things, both big and small. We have however not always managed to tell you how to migrate the patterns that used to work in Vaadin 6 and we’re very sorry for this. We always try to improve relevant documentation as we learn about new problems, but we have a hard time identifying such situations unless you tell us how you used to do things.

There are currently no concrete plans for a Part 3 of this series, but we are keeping our eyes open for more changes that might need an explanation.

Leif Åstrand
Leif Åstrand
Leif Åstrand keeps an eye on the overall architecture of the Vaadin platform. He knows a thing or two about how Vaadin, Web Components, and the internet works.
Other posts by Leif Åstrand