I’ve trying to solve that Vaadin problem with multiple browser tabs. Currently only solution is to override Application#getWindow() and create additional main windows. That doesn’t solve the real problem, which is that all tabs share the same application class instance when they should have separate instances.
It seems that real source of these problems is that web browser uses same http session for all browser tabs that are using same target URL. Vaadin seems to link application instances to http session. If the session is same for all tabs, then there is only one instance of your application class.
I think I may have now somewhat better solution. It’s not perfect, but my tests doesn’t give any out-of-sync errors and each tab has completely separate set of windows.
I don’t know how to force web browser to use different http sessions for tabs. Does anybody know? If there is a way, then much simpler and better solution could be created. Although I cannot force new http sessions, I can make Vaadin to create separate instances of my application class for each browser tab. Vaadin doesn’t create separate application instances if both http session and the application URL are same. If session cannot be changed, then let’s change the URL.
So first step is to generate different URLs for browser tabs. Normally your URL is like “www.fobar.com/testapp”. Let’s changed it so that there is variable part like “www.foobar.com/testapp/session12345” which is different for tabs. This can be done by extending com.vaadin.terminal.gwt.server.ApplicationServlet or com.vaadin.terminal.gwt.server.AbstractApplicationServlet. Anyway, you need to override javax.servlet.http.HttpServlet#service() method so that you can get requests before Vaadin gets them. Test if the URL contains that “sessionNNNN” part. If it doesn’t, create new URL which has it and make that part unique for example by using current time in milliseconds or some random number. Now use HttpServletResponse#redirect(), which forces web browser to resend request with your new URL. You need to check if URL’s path info starts with “/UIDL/” or with “/VAADIN/”, you must not redirect. That’s because those paths must be located right under your original servlet path. Does anybody know if there are other special prefixes?
Now we have unique URL for each browser tab. That’s not enough. Because we have kind of changed servlet path, we have to use request wrapper to change how Vaadin sees some aspects of the http request. Create new class which extends javax.servlet.http.HttpServletRequestWrapper and override methods getPathInfo() and getServletPath(). Give also that generated “sessionNNNN” block to constructor, so that those overriden methods can do their work.
Write getPathInfo() so that it first asks path info from super and then test if result contains that “sessionNNNN” pattern. If it is there, then remove it. Remeber that if result is now empty string, you must return null. See javadoc for those methods. Method getServletPath() must be changed so that you add that “sessionNNNN” to returned string. It helps if you add System.err.println and compare what these methods return without that redirecting stuff. Then you have better idea when you should return null, empty string and when there must be “/” at end and so on.
Last step is to use our wrapper class and wrap the http request with it and pass result to super class. Now Vaadin creates automatically new application instance for new tab, because the URL is different.
I also added new cookie containing “SESSION-ID” to response, but that’s not necessary. If you like to use cookies, remeber to add path to your cookies. The path you add is what you get by calling our.wrapper.class#getServletPath(). Without path all tabbed sessions sees same value for your cookie, which is probably not what you want.
So that’s my solution. There are some things to consider. If you are using authentication packages, does it work correctly because the http session is same? Cookies doesn’t work as expected unless they have their path set. What you want to happen if user copies URL from one tab to another? You propably need to check if URL is copied and then create new session. Hint: The URL is most likely copied if it contains that session string, but there is no “referer” http header in the request. The missing “referer” is also way to find when new browser tab is connecting to your application. There should be perhaps some kind of expiration system to prevent use of old tabbed sessions.
If someone is interested in example codes, I can provide them.