Application.getWindow() is called many times

Hi Vaadin experts,

I have a fundamental problem that I really want your help. Here is the user requirements:

  1. User can open as many windows as they want, there shouldn’t be “out of sync” error
  2. User can click “refresh” button on the browser which refreshes the content of the page (fetched from database)
  3. User can use the URL (as bookmark or send to others by email)

All these three requirements are connected to getWindow() funcation. In order to solve the req.1. I put code in my Application class:


	public Window getWindow(String name) {
		Window w = super.getWindow(name);
		if(name.startsWith(XXXX) && w == null){
			w = new MyWindow(thisUser);
			w.setName(name);
			// retrieve content from database
			// set the content to MyWindow instance
			addWindow(w);
			w.open(new ExternalResource("../../../.." + w.getURL().getPath()));
		} else if (w == null) {
			w = new MyWindow(thisUser);
			w.setName(name);
			addWindow(w);
			w.open(new ExternalResource("../../../.." + w.getURL().getPath()));
		}	
		return w;
	}

In this way, user can open the same window in multiple tabs/windows in the browser. However, the problem with this code is, when user click refresh button (req.2), the data does not get refreshed, because w!=null, thus the exsiting w is returned. The same problem affects (req.3), if the window is opened, opening the url does not load the latest data but the existing window instead. Thus in order to meet req.2 and req.3, I replaced the code on LOC 5

6			w.setName(name);

with

6			w.setName(name + "&" + Math.random());

and remove LOC10. Now new window can be opened, refresh can be clicked because w is always null. However now the PROBLEM is the getWindow() is called so many times by Vaadin engine that 1. the content of the window is attached many times 2. the database connention is called many times as well. Which is very annoying and causes a performance issue.

How can we solve this issue? When will Vaadin 7 be released? Does that really solves the multi window problem?

Br,
Xuan

Application.getWindow will be called one or many times and its purpose is to return the correct Window instance. You should not do any additional processing there. It is called for every request and not only if the user refreshes the browser (why would he even want to refresh the browser?) e.g. if the user clicks on a button in the application getWindow() is called. You will introduce a lot of overhead if you do extra stuff there.

You can add a background thread that periodically polls the database and refreshes/updates the UI of one or more users. If you add Refresher, ICEPush or something similar the users will get the updates without refreshing the browser. Otherwise a refresh will render the updated version of the UI.

Not entirely sure what is the problem, probably the w.setName(name) for the created windows in the second if block - you should probably use automatic window name, which is the default if not set explicitly.

Remember that getWindow() is called every time a UI request is made from browser to the server, not just when a new window is created. It’s main purpose is to act as a switchboard to get the window object to which a request is sent, not to create new windows. The nice possibility to create new ones is just a side effect.

This code seems to work for the most common purposes:

@Override
public Window getWindow(String name) {
    // See if the window already exists in the application
    Window window = super.getWindow(name);
    
    // If a dynamically created window is requested, but
    // it does not exist yet, create it.
    if (window == null) {
        // Create the window object. The window name identifier
        // is generated dynamically.
        window = new Window("Book Examples (Secondary Window)");

        // Fill the window with stuff
        init(window);

        // Add it to the application as a regular
        // application-level window
        addWindow(window);
    }

    return window;
}

See the demo
here
.

Hi Marko,

Could you show me a bit more on:

        // Fill the window with stuff14        
       init(window);

In my code example, I was just trying to shorten the code so the database action appears in side the getWindow method. In the real project, the database actions are in attach() method on user defined component, (like your init function). However the effect is the same, it is just get called again.

I took a look on your “demo”. I think you acheived requirement 1 and 3, but I am not sure about 2. Let’s say your content is stored in database. If you

  1. open http://demo.vaadin.com/book-examples/book/#intro.walkthrough.helloworld
  2. goto database and change helloworld to foobar
  3. refresh the browser you just opened, put a breakpoint on getWindow and see how many times it gets hit when window==null

Thanks!

Br,
Xuan

Hi Artur,

Thanks for your reply! I have refresh button inside the window, but users are not willing to click that. The users prefer to use the refresh button on the browser. The thread is not a acceptable solution either, it causes even more data loading workload.

Br,
Xuan

The init(window) just sets the window layout with setContent() and adds components with addComponent(), etc.

The refresh issue requires that instead of simply returning a new window object, it has to use an automatically generated window URL extension, so that when refreshing, it returns the old window object instead of creating a new one. You need to call window.open(new ExternalResource(w.getURL())) for the new window, as described
here
.

Hi,

Thanks for your reply! I know the url solution, that’s the code in my example code. It has two problem, first it is not working for subwindow, so the subwindow cannot open the window again. Second, it is blinking as many times and the number of same window are opened. Eg, if the window X is opened once, X/1_1/ blink once. If open X again, X/1_2/ blink twice.

Br,
Xuan