Calling Application.close() from different thread

We are implementing logout feature. For our logout to work, there can be some triggers which are sent by the server asynchronously and base don those triggers we need to decide whether to logout or not.

That essentially means we need to call Application.close() on a separate there and not on main UI thread. But when we do that, we do not see any redirect for logout URL and page remains where it was initially. We are using ICEPush to push to the browser but that is also not working since application is already closed and we always get Session Expired error.

How should I fix this to call Application.close() on different thread and still achieve the same effect as if main UI thread called it?

thanks
dheeraj

To my understanding, it is not possible for the servlet container to send the output of changes to user if the request is not made by the user. That is, if method call to application or any other class in it is not performed by the thread created by the servlet container, it is not possible to send changes (redirections) to user. That’s why you don’t see redirection to logout url. And for the ICEPush, it’s not able to send anything to the user because application and session is already closed, as you said.

Maybe you should try some other approach instead of closing the application from separate (manually started) thread. For example could you set some flag for the application that is should logout after next request from “UI thread”? In general, creating own threads in web container environment is always a bad idea, sorry.

Thanks Peter, yes I agree, in general having different threads in container is not good idea. Unfortunately, there are 2 reasons we need to have our threads
a) Vaadin by nature is asynchronous, means for example if I need to show some dialog before application can be closed, I cannot hold the container UI thread to get confirmation for that dialog because after showing the dialog (adding dialog in window) the call continues and so on

b) When logout is clicked call is made from web container to our proprietary server, this server can send some message asynchronously that needs to be shown in the browser, if we invoke this logout call on same UI thread, since UI thread is still busy (since the call from server has not returned yet), we can never show that dialog coming from proprietary server, so we need to invoke the logout on different thread so that main UI thread is free to receive and show the dialog message coming from proprietary server and so on.

Hope this makes our requirements clear, based on this, do you have any other suggestion?

So basically before logging out, you want to make a round trip to another server to perform some log out logic and receive a message that will be shown to the user in Vaadin application before logging out?

And your current solution is based to asynchronous call to this external server from Vaadin application, so that when you log out from the application, you asynchronously make request to this other server and then continue with the logging out procedure? And now when this other server completes it’s asynchronous request Vaadin application is not able to show the result (=message) because it has already logged out?

I am having a similar problem:

  1. User presses the Save button
  2. The buttonClicked() method is invoked:
    A. The buttonClicked() method displays a notification saying “Saving changes…”
    B. The buttonClicked() method upates the database with the changes
    C. The buttonClicked() method closes the application

However, the notification is never shown, the application page is shown for several seconds (without the notification), and then the user is taken to the logout page.

I think the reason for this is because the entire buttonClicked() method is synchronous to vaadin. Only when the buttonClicked() method returns does vaadin send any relevant changes made by the method back to the browser.

In my case, I am requesting a notification be displayed but I am also closing the application within the same method which redirects to the logout page.

What I want is a fairly typical user experience:

  1. User presses the Save button
  2. User sees the notification “Saving changes…”
  3. Database updates are performed (takes a few seconds) during which the notification continues to be displayed
  4. The application closes and user is take to the ‘logout’ page

So, thinking that I needed to return from the buttonClicked() method immediately after requesting the notification (before updating the database and closing the application), I tried creating a new thread in the buttonClicked() method which would do those things.

There is good news and bad news:

  • The good news is that now I see the notification (because the buttonClicked() method now returns immediately after the notification is requested).
  • The bad news is that the application is not closing. That is, it is not being re-directed to the logout page (presumably because there is no server-to-browser communication which takes place when the non-browser-initiated thread is complete.)

Has anyone come up with a solution to this problem? I imagine it must be fairly common.

It would be nice to have a server-side flush() method. After I request an notification, I could call the application.flush() method, meaning, do this NOW! It would be similar to what happens when you return from a method (send any outstanding changes to the browser), but you stay in the method. Then I could do some other tasks, like updating the database and closing the application, before returning from the method in the normal way.

Well, the database-update should not require the application to be open, so you could spawn a new thread updating the database and closing the application right afterwards (I mean after the thread was spawned). Works of course only in cases where potential errors must not be communicated towards the user.

A flush()-method on the server would be rather irritating as it would work only once per roundtrip. Once the server has sent its response, it cannot sent anything else, so after the manually flush no more updates would be sent to the client.

I have tried using ICEPush, but that seems to require the servlet 2.5 api and my run time environment has 2.4 :frowning:

So now I am trying to use a ProgressIndicator.

(To review, the user clicks a Save button and I want to display a friendly notification, save changes to the database and close the application. Easy peasy, right? No…)

In the buttonClicked() method, I now:

  1. Make visible the (formerly invisible) progress indicator
  2. Show a friendly notification
  3. Start a thread to save changes to the database
  4. return

The notification is displayed as desired this time (yay!) because now I am returning quickly from the buttonClick() method allowing the browser to see the notification before the application closes.

The background thread then:

  1. Updates the database
  2. Occasionally updates the value of the progress indicator
  3. When the update is complete, it sets the value to 1.0

The last problem is to close the application.

I tried doing this in background thread. That didn’t work. So I tried putting a listener on the progress indicator, which tells me when the value I am setting changes and, specifically, when it reaches 1.0. When it does, I call application.close().

In either case (closing the application in the background thread or in the progress indicator listener), in the GUI, I get:
[b]

[color=#ff0000]
Session Expired
Take note of any unsaved data, and [u]
click here
[/u] to continue.
[/color]

[/b]
(So close and yet so far.)

It appears that the application.close() call is
immediately
expiring the session (even though we are in the middle of a browser-server-browser round-trip), and the browser detects this and displays the above Session Expired message. What I want it to do is to close the application and go to the logout page.

Without the background thread, I get to the logout page, but I do not get the notification message (because the notification message and the application close are being sent back to the browser together, and apparently there is either no time to display the notification, or the application close supersedes it).

With the background thread and the progress indicator, I the notification message is displayed (good), but then I get a session error is displayed (bad) when the application is closed and I do not get sent to the logout page (because the application actually IS being closed ? and closes the session at the same time ? which the browser detects as a session error instead of an application close ?).

Suggestions? I’ve already spent too long on this…