3

I have a login form (login.jsp) with two input fields, username and password.

I am using POST via Ajax to access the login servlet.

I want the user to login, and if the login is successful, be redirected to another page called 'search.jsp'. If unsuccessful, a 'login failed' message is returned as the Ajax responseText to be inserted into a paragraph in the 'login.jsp' page.

I have everything working, my login servlet accesses the database via a separate bean, and an object of that bean is returned with its properties ready to use. So all is good to there.

But, after the username and password pass muster with the database, I'm then using RequestDispatcher to forward to the new landing page (search.jsp).

Here is my doPost()

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String username,password;
    username = request.getParameter("p");
    password = request.getParameter("q");       

    try {
        LoginService ls = new LoginService(username,password);
        User user = ls.getUserDetails();            

        if(user.getUsername()!=null && user.getPassword()!=null){
            FormService filler = new FormService();
            Form fields = filler.getFields();

            request.setAttribute("user",user); 
            request.setAttribute("fields1",fields);
            request.setAttribute("fields2",fields);
            request.setAttribute("fields3",fields);


            HttpSession session = request.getSession(true);
            //set attribute for the session
            session.setAttribute("user",user.getUsername());

//Now, the RequestDispatcher.forward() is not forwarding to the new page!
//The whole 'search.jsp' page is being stuffed back into the 'login.jsp' page

            RequestDispatcher rd = request.getRequestDispatcher("search.jsp");
            rd.forward(request,response);               
            return;
        }
        else{
            PrintWriter out = response.getWriter();
            out.println("login failed!");
            return;
        }
    } catch (Exception e) {         
        e.printStackTrace();
    }       
}

But instead of forwarding the request and response to the new jsp page 'search.jsp', the whole search.jsp page is being stuffed back into the the original login.jsp page - in the html element which holds the Ajax responseText in when login fails.

The forward() method in the servlet works when the servlet is called from the form action attribute, but not when the servlet is called the javascript file containing the Ajax code.

berzerk
  • 65
  • 1
  • 3
  • 8
  • Since you making a AJAX call to do the login, you should return out.println("login success!"); when it succeeds. After the response is received, use conditional javascript to change the location of the page or just display failure message. – rickz Jan 04 '12 at 01:46
  • ricz I'm not sure what you mean - I'm thinking the successsful login should be implied when the user is redirected to the new page - it is this redirect that I can't get to work. – berzerk Jan 04 '12 at 01:55
  • The AJAX call receives a response and puts the responseText where you tell it to put it. If you want to change the location of the browser page,then use javascript to change it. – rickz Jan 04 '12 at 02:10
  • See http://www.roseindia.net/javascript/javascript-location-replace.shtml – rickz Jan 04 '12 at 02:11
  • Or maybe http://www.ezineasp.net/Samples/Javascript/Location-Object/Location-Href/Default.aspx – rickz Jan 04 '12 at 02:13
  • I just tried the Javascript redirects from inside the onreadystatechange() function and got a 500 error. So I guess Ajax is only good for when you want to insert returned data into an element on the same page that made the Ajax call to the servlet. – berzerk Jan 04 '12 at 02:25
  • Thanks for your replies rickz - I've just gone back to a conditional test in the login form page which displays

    login unsuccessful

    when a 'failedLogin' attribute is set in the else in my doPost() - when login is unsuccessful.
    – berzerk Jan 04 '12 at 02:50

1 Answers1

4

But instead of forwarding the request and response to the new jsp page 'search.jsp', the whole search.jsp page is being stuffed back into the the original login.jsp page - in the html element which holds the Ajax responseText in when login fails.

That's indeed the expected behaviour. You're handling the request/response using JavaScript. Your JavaScript code has retrieved the response of search.jsp as responseText and is putting it in the HTML element.

You need to change this approach. You need to let the response return the necessary data which sufficiently informs JavaScript so that it can handle the response properly. A commonly used data format for this is JSON.

Something like

response.setContentType("application/json");

if (user != null) {
    // ...

    response.getWriter().write("{ 'success': true, 'location': 'search.jsp' }");
} else {
    response.getWriter().write("{ 'success': false, 'message': 'Unknown login' }");
}

and in JS:

var responseJson = eval('(' + xhr.responseText + ')');

if (responseJson.success) {
    window.location = responseJson.location;
} else {
    document.getElementById('message').innerHTML = responseJson.message;
}

If you want to handle this unobtrusively, so that the same servlet is reuseable on normal (non-ajax) HTTP requests (so that your webapp still works when the client has JS disabled!) then you could check if the X-Requested-With header equals to XmlHTTPRequest.

if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With")) {
    // Handle ajax response (e.g. return JSON data object).
} else {
    // Handle normal response (e.g. forward and/or set message as attribute).
}

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555