Best practices for record locking using Vaadin 7's lack of browser close ev

We are migrating our applications from Vaadin 6 to Vaadin 7.1.3. The browsers we are supporting are the latest version of Firefox (currently 23.0.1) and IE 9, and we are migrating to Vaadin 7 so we can support IE 10. We have implemented record locking in our applications so that when a user accesses a record, a lock is put on it, and no other user can access that record. Once they leave the record, the lock is removed. Because we are not supporting Opera, in our Vaadin 6 applications, we would override the close() method to contain code to release all locks the application was holding on to if the browser tab or window was closed.

As has been mentioned on the forums many times, Vaadin 7 no longer supports browser close events, and instead relies on three missed heartbeats to determine if the client side has closed. To support this, I moved the code that clears out locked records from the overriden close() method to detach(), and updated the web.xml with the following context-param:


<context-param>
        <param-name>heartbeatInterval</param-name>
        <param-value>1</param-value>
</context-param>

My understanding is that this means if I leave the UI, either by navigating way, closing the browser, or closing the tab, and then access the UI again, upon reaccessing the application, the old UI should be cleaned out, calling my detach method, and therefore unlocking my records. To test this, I ran my application, opened a record to cause it to lock, closed the browser, waited a few seconds, opened the browser and tried to access the same record again, only to find it locked.

After some searching, I decided to try adding this to my web.xml as well:


<session-config>
    	<session-timeout>1</session-timeout>
</session-config>

After adding this, I found that I could lock a record, close my browser, and wait a minute (I added a SessionDestroyListener so I know when the session times out), that when I ran the application again, the detach method is ran and any previously locked records are unlocked.

The Point: I’m trying to get some feel for some best practices here. I feel that a minute is too long of a wait for a record to be unlocked, and that a heartbeat of 1s, or even 20s is too frequent, and that a session timeout of 1 minute is too short. Also, I haven’t read anything suggesting that detach will not be called until there is a missed heartbeat AND the session times out. Is this a feature, or a bug? Or is there a way to call detach, or determine if three heartbeats are missed without having to wait for the session to time out? OR am I completely off here and there is a different approach I should be taking?

Thanks in advance!

Best practice is NOT to lock records for any long period , do atomic operations ( startTransaction , do stuff , rollback or commit ) and handle version exceptions when the user tried to do an operation on a stale record ( old version ).

If you have a situation where the user MUST lock a record, you should do this on the data level and not on transaction record level…

Thanks Petrus, and well said. This definitely confirms my suspicion that a minute is too long a wait to unlock a locked record, and I’ve found plenty of articles in a Google search to support that.

So lets assume this lock is necessary (because for all intents and purposes, at this point in time it is), and it needs to be released when the application is closed. This means the question should probably be “Is there anything else that can be done in Vaadin to get the detach method called in faster than one minute after a browser or browser tab is closed?”

Thanks again!

For any who come across this problem, this is the approach I took, which (mostly) solves the problem.

Following the example in
this post
, I added the following code to be ran during the initialization of my UI class:

JavaScript.getCurrent().addFunction("catchClose", new JavaScriptFunction() {
private static final long serialVersionUID = 1L;
    @Override
    public void call(JSONArray arguments) throws JSONException {
     VaadinSession.getCurrent().close();
    }
});

Page.getCurrent().getJavaScript().execute(
"window.addEventListener('beforeunload', "
         + "function() {"
                 + "var e = window.event;"
                    + "e.returnValue = false;"
                    + "catchClose(); "
                    + "return '';"
+ "}, false);"
 );

Then, in my UI, I overrode the detach() method to perform all of my clean up. Using this approach, I can call the clean up immediately when the browser or tab is closed, but it will also be called on a session time out.

The only problem I am having with this is with the Javascript. It works fine in Firefox, but in Chrome and IE 10 when the session is destroyed a prompt is still displayed asking the user if they want to continue to leave the page. This will obviously cause errors if they choose to stay. I assume this is an error with my Javascript, so I have started a new discussion for this issue on
StackOverflow
.