Glyn
Glyn

Reputation: 1995

GWT Java - How to close the window (Log Out)

I have read that to Log Out of the application you need to close the window and I found this code:

This answer has what you are looking for: How to run JavaScript function from GWT Java with JSNI?

Specifically in Java:

myButton.addClickHandler(new ClickHandler(){
public void onClick(ClickEvent event) {
closeWindow();
};
});

public static native void closeWindow() /*-{ $wnd.closeWindow();}-*/;

Then in JavaScript in your app's .html page:

<script type="text/javascript" language="javascript">
function closeWindow() {
window.open('','_self','');
window.close();
}</script>

I have implemented this in my application by:

    //Log Out Button
    Button logOutButton = new Button("Log Out");
    logOutButton.addClickHandler(new ClickHandler(){
        public void onClick(ClickEvent event) {
        closeWindow();
        }
    });

    public static native void closeWindow() /*-{ $wnd.closeWindow();}-*/;

And the HTML:

<!doctype html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">

        <!--                                                               -->
        <!-- Consider inlining CSS to reduce the number of requested files -->
        <!--                                                               -->
        <!-- <link type="text/css" rel="stylesheet" href="org.AwardTracker.AwardTracker.AwardTracker.css"> -->

        <!--                                           -->
        <!-- Any title is fine                         -->
        <!--                                           -->
        <title>Wrapper HTML for AwardTracker</title>

        <!--                                           -->
        <!-- This script loads your compiled module.   -->
        <!-- If you add any GWT meta tags, they must   -->
        <!-- be added before this line.                -->
        <!--                                           -->
        <!-- script language="javascript" src="org.AwardTracker.AwardTracker/org.AwardTracker.AwardTracker.nocache.js" --><!-- /script -->
        <script src="org.AwardTracker.AwardTracker/org.AwardTracker.AwardTracker.nocache.js">
            <type="text/javascript">
            function closeWindow() {
                window.open('','_self','');
                window.close();
            }
        </script>

    </head>

    <!--                                           -->
    <!-- The body can have arbitrary html, or      -->
    <!-- we leave the body empty because we want   -->
    <!-- to create a completely dynamic ui         -->
    <!--                                           -->
    <body>

        <!-- OPTIONAL: include this if you want history support -->
        <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"></iframe>

    </body>

</html>

However, I get the following error on the lines:

closeWindow(); 

"The method closeWindow() is undefined for the type new ClickHandler(){}"

public static native void closeWindow() /*-{ $wnd.closeWindow();}-*/;

Multiple markers at this line - Syntax error, insert "EnumBody" to complete BlockStatement - Syntax error on token "void", @ expected - Syntax error, insert "enum Identifier" to complete EnumHeaderName

Thank you to all who responded. Based on your responses... I am using sessions like (via RemoteServiceServlet) in my app. Therefore, as per below in the responses, I need to invalidate session first followed by removal of element from dom. So tried the following:

On the client side:

        logOutButton.addClickHandler(new ClickHandler(){
            public void onClick(ClickEvent event) {
            //Invalidate the session and then reload the application.
            AsyncCallback<Void> callback = new InvalidateSessionHandler<Void>(SelectPersonView.this);
            rpc.invalidateSession(callback);
            }
        });

class InvalidateSessionHandler<T> implements AsyncCallback<Void> {
    SelectPersonView view;

    public InvalidateSessionHandler(SelectPersonView view) {
        this.view = view;
    }

    public void onFailure(Throwable ex) {
        System.out.println("RPC call failed - InvalidateSessionHandler - Notify Administrator.");
        Window.alert("Connection failed - please retry.");
    }

    public void onSuccess(Void result) {
        //Reload the application.
        Window.Location.assign("/");    
    }
}

On the server side:

public void invalidateSession() {
    getThreadLocalRequest().getSession().invalidate(); // kill session 
}

This seems to work. However, I am having trouble testing more than one session locally and I do not have a test server I can deploy to. So can I please ask for someone who knows what they are doing in this space to check it to ensure I am not introducing issues into production. My greatest concern is that this will log everyone out. I am particularly toey because I had a situation where sessions were not compartmentalised and users could see other people's data. This has been fixed and I do not want to break that fix!!

Upvotes: 0

Views: 1055

Answers (3)

Glyn
Glyn

Reputation: 1995

This is the final code I used: I am using sessions (via RemoteServiceServlet) in my app. Therefore I need to invalidate the session first followed by removal of element from dom. So the following is the final code:

On the client side:

        logOutButton.addClickHandler(new ClickHandler(){
            public void onClick(ClickEvent event) {
            //Invalidate the session and then reload the application.
            AsyncCallback<Void> callback = new InvalidateSessionHandler<Void>(SelectPersonView.this);
            rpc.invalidateSession(callback);
            }
        });

class InvalidateSessionHandler<T> implements AsyncCallback<Void> {
    SelectPersonView view;

    public InvalidateSessionHandler(SelectPersonView view) {
        this.view = view;
    }

    public void onFailure(Throwable ex) {
        System.out.println("RPC call failed - InvalidateSessionHandler - Notify Administrator.");
        Window.alert("Connection failed - please retry.");
    }

    public void onSuccess(Void result) {
        //Reload the application.
        Window.Location.assign("/");    
    }
}

On the server side:

public void invalidateSession() {
    getThreadLocalRequest().getSession().invalidate(); // kill session 
}

getThreadLocalRequest().getSession().invalidate(); returns me to my login window. Window.Location.assign("/"); returns me to the tomcat page. So use which ever suits you.

Upvotes: 0

Gurpreet Singh
Gurpreet Singh

Reputation: 400

Javascript can only close the page if it is opened by same script. So closeWindow() won't even work. So :

  1. If you are not using sessions in your app i.e. you think that only closing the window is a goal to achieve. Then simply delete that iframe from DOM rather closing page. (You can do that by using js.)

document.getElementById('iframeid').innerHTML = '';

  1. If you are using sessions like (via RemoteServiceServlet) in your app, then you need to invalidate session first followed by removal of element from dom. (For this i am not sure how to do.)

Or

Instead of removal, you can just reload the iframe (which is considered to be as a reload of your app):

document.getElementById('iframeid').src = document.getElementById('iframeid').src

Upvotes: 1

Andrei Volgin
Andrei Volgin

Reputation: 41089

  1. You cannot close a window using JavaScript if the window was opened by a user. You can only close a new window that was opened by your app.

  2. Closing window will have no effect on user authentication as most authentication mechanisms rely on server sessions or cookies.

If your authentication is session-based, when a user clicks on the Log Out button you need to (1) invalidate user's session, and (2) reload your app, which will display default entry point for non-authenticated users (home page or login page).

Upvotes: 4

Related Questions