Ian W.
Ian W.

Reputation: 53

How to check for a valid session in JSF application?

Before I explain the situation, I'll preface it by saying that the application I'm working on is old, outdated, needs to be rewritten, etc. but the company I work for doesn't care and is just looking for a quick bandage to this problem. Also, I'm just some random dude who they gave this app to and, despite knowing next to nothing about all this, they somehow consider me the subject matter expert.

I have a .xhtml page that users go to in order to pay bills. We use SiteMinder to control access to the application, and through this there has been set a two hour inactivity timeout limit for the application. However, we have recently implemented some new payment features from a third party vendor that make use of modal windows. If a user sits on this .xhtml page for an hour and fifty nine minutes, invokes the modal window (via a button click), and goes to complete various actions in the modal, then when they're done the third party vendor considers the action successful (since they are unaware of our timeout) but we do not receive any responses from them since the session has timed out on our end. This is a problem, because users can schedule future payments, and if we do not get a response from the vendor, we have nothing to store in our database which we eventually use to trigger the scheduled payment.

How can I determine if the user's session is still valid when they click to invoke the third party modal window? Here's what one of the buttons looks like:

<p:commandButton id="makePaymentButton" 
    value="Make Payment" onclick="makePayment(/*args*/);"
</p:commandButton>

Basically, instead of immediately invoking the modal window, I want to first check and ensure that the user's session is still valid. Since is there is not page navigation or server interaction when this button is clicked, the modal simply renders whether or not the user's session has expired.

Upvotes: 3

Views: 1754

Answers (2)

Vsevolod Golovanov
Vsevolod Golovanov

Reputation: 4206

To know if the session is still valid, you'd need to ask the server. But you have to be careful, so that your "asking" request wouldn't automatically create a new session itself. The most surefire way is to ditch JSF altogether and create a simple Servlet.

public class CheckSessionServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/plain");

        HttpSession session = request.getSession(false);
        if (session == null) {
            // no session, let's respond 404
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        } else {
            // session exists - return a succesful status
            response.setStatus(HttpServletResponse.SC_NO_CONTENT);
        }
    }

}

Do an AJAX POST request with JS to this servlet, and then act on the request outcome.

In order to prevent session timing out while the user if filling out the 3rd party dialog, you may want to touch the session to bump its timeout:

        } else {
            // session exists - bump timeout & return a succesful status
            session.setAttribute("someUnusedAttribute", 123);
            response.setStatus(HttpServletResponse.SC_NO_CONTENT);
        }

And if the session is expired then you can refresh the page (with JS) to allow user to start anew. Or show a simple message to user, explaining that the session is gone and he needs to start again.

You can do all this without touching the legacy JSF stuff.

Upvotes: 2

fxrobin
fxrobin

Reputation: 652

If you use standard render Kit use :

<h:commandButton id="makePaymentButton"
                 value="Make Payment" 
                 actionListener="your action listener which may return an exception if the session control fails">
    <f:ajax onevent="makePayment(/*args*/)" />
</h:commandButton>

If you use Primefaces use "oncomplete", "onsuccess" :

<p:commandButton id="makePaymentButton" 
                 value="Make Payment" 
                 actionListener="your action listener which may return an exception if the session control fails" 
                 onsuccess="makePayment(/*args*/)" />

Then, in the actionListener you can get the session :

HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);

Caution : the session reference might be null, then check what you need with it.

Dont forget to place <f:view transient="true"> ... </f:view> in order to disable the automatic creation of a JSESSIONID.

Upvotes: 4

Related Questions