berzerk
berzerk

Reputation: 65

JSP: RequestDispatcher.forward() not forwarding when servlet called via Ajax POST

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.

Upvotes: 3

Views: 11778

Answers (1)

BalusC
BalusC

Reputation: 1109222

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:

Upvotes: 4

Related Questions