Servlet redirect to same page with error message
Asked Answered
C

1

14

I have a question about servlet redirection to the same initial page. The following is the scenario: Suppose a user want to buy an item, so he fills in the amount and submits it. The form is submitted to a servlet and the quantity available is checked against the available in the database. So if the amount of items ordered is more than the available the servlet redirects to the same page but with a message like "item is unavailable". So my question is how to implement this case. How to redirect to the same initial page with an error message. I don't want to use ajax here.

Here is how I have thought of it as : 1.)should I set a context attribute if error is generated and then check it again in initial page after re-direction and show the message that has been set.

What are the best practices for this kind of events?

Cliffcliffes answered 31/1, 2013 at 18:4 Comment(1)
Put your mouse on top of [servlets] tag which you placed on the question until a black box shows up and then click therein the info link. This issue is covered for long by the first Hello World example.Throwaway
S
41

The most common and recommended scenario (for the server side validation in Java serlvets/JSP world) is setting some error message as a request attribute (in the request scope) and then outputting this message in a JSP using Expression Language (see the example below). When the error message is not set - nothing will be shown.

But when storing an error message in a request, you should forward a request to the initial page. Setting a request attribute is not suitable when redirecting, because if you use a redirect it will be a totally NEW request and request attributes are reset between requests.

If you want to redirect a request to the referring page (the one from which you submitted data) then you can store an error message in a session (in the session scope), i.e. set a session attribute. But in this case, you also need to remove that attribute from the session when the submitted request is correct, because otherwise an error message will be available as long as the session lives.

As for the context attribute it is meant to be available to the whole web application (application scope) and for ALL users, plus it lives as long as the web application lives, which is hardly useful in your case. If you set an error message as an application attribute it will be visible to ALL users, not only to the one that submitted the wrong data.


OK, here is a primitive example.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <display-name>Test application</display-name>

    <servlet>
        <servlet-name>Order Servlet</servlet-name>
        <servlet-class>com.example.TestOrderServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Order Servlet</servlet-name>
        <url-pattern>/MakeOrder.do</url-pattern>
    </servlet-mapping>

</web-app>


order.jsp

<!DOCTYPE html>
<html>
<head>
    <title>Test Page</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
    <h1>Test page</h1>
    <form action="MakeOrder.do" method="post">
        <div style="color: #FF0000;">${errorMessage}</div>
        <p>Enter amount: <input type="text" name="itemAmount" /></p>
        <input type="submit" value="Submit Data" />
    </form>
</body>
</html>


Option №1: setting an error message as a request attribute

package com.example;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;

import java.io.IOException;

public class TestOrderServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
                    throws ServletException, IOException {
        int amount = 0;
        try {
            amount = Integer.parseInt(request.getParameter("itemAmount"));
        } catch (NumberFormatException e) {
            // do something or whatever
        }

        if ((amount > 0) && (amount < 100)) {   // an amount is OK
            request.getRequestDispatcher("/index.jsp").forward(request, response);
        } else {                                // invalid amount
            // Set some error message as a request attribute.
            if (amount <= 0) {
                request.setAttribute("errorMessage", "Please submit an amount of at least 1");
            } 
            if (amount > 100){
                request.setAttribute("errorMessage", "Amount of items ordered is too big. No more than 100 is currently available.");
            }
            // get back to order.jsp page using forward
            request.getRequestDispatcher("/order.jsp").forward(request, response);
        }
    }
}


Option №2: setting an error message as a session attribute

TestOrderServlet.java

package com.example;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;

import java.io.IOException;

public class TestOrderServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
                    throws ServletException, IOException {
        int amount = 0;
        try {
            amount = Integer.parseInt(request.getParameter("itemAmount"));
        } catch (NumberFormatException e) {
            // do something or whatever
        }

        if ((amount > 0) && (amount < 100)) {   // an amount is OK
            // If the session does not have an object bound with the specified name, the removeAttribute() method does nothing.
            request.getSession().removeAttribute("errorMessage");
            request.getRequestDispatcher("/index.jsp").forward(request, response);
        } else {                                // invalid amount
            // Set some error message as a Session attribute.
            if (amount <= 0) {
                request.getSession().setAttribute("errorMessage", "Please submit an amount of at least 1");
            } 
            if (amount > 100){
                request.getSession().setAttribute("errorMessage", "Amount of items ordered is too big. No more than 100 is currently available.");
            }
            // get back to the referer page using redirect
            response.sendRedirect(request.getHeader("Referer"));
        }
    }
}

Related reading:

Servility answered 1/2, 2013 at 2:7 Comment(3)
I do get redirect back to my login page with error, but if I login good and click back - it still shows me 'error message'.Ludwick
@AnnadatePiyush Well, this is expected behavior. The "Back" button functionality in browsers takes you "back in history" (usually using browser cache). If the last action was "error message" it is shown again. Read here for more: How does the Back button in a web browser work?.Servility
That helps. I need to be with session then.Ludwick

© 2022 - 2024 — McMap. All rights reserved.