Asme Just
Asme Just

Reputation: 1337

How to avoid duplicating data after refreshing JSP page?

After submitting a form, the data are sent to a servlet and stored in the database. T Then i use a request.getRequestDispatcher("CTN/ListPage.jsp").forward(request, response); to list the data on ListPage.jsp page but if I refresh that same page, the browser tell me that the data will be resent again in a warning message and then, the last stored data is duplicated,.. this seems to be a common problem after lot of search. So I try the RPG solution by changing:

request.getRequestDispatcher("CTN/ListPage.jsp").forward(request, response); to

response.sendRedirect(request.getContextPath() + "CTN/ListPage.jsp"); but I get a 404 error ... The requested resource () is not available.

How can I solve this problem?

UPDATE: Servlet code:

package com.CTN.controller;

import com.CTN.dao.MatiereDaoLocal;
import com.CTN.dao.SeanceDaoLocal;
import com.CTN.dao.SemestreDaoLocal;
import com.CTN.model.Matiere;
import com.CTN.model.Seance;
import java.io.IOException;
import java.util.List;
import javax.ejb.EJB;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author WORK
 */
@WebServlet(name = "NewSeanceAjouterServlet", urlPatterns = {"/NewSeanceAjouterServlet"})
public class NewSeanceAjouterServlet extends HttpServlet {


    @EJB
    private MatiereDaoLocal MatiereDao;
    @EJB
    private SeanceDaoLocal SeanceDao;
    @EJB
    private SemestreDaoLocal SemestreDao;

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {


        int matiereId = Integer.parseInt(request.getParameter("matiereId"));
        String seanceTitre = request.getParameter("seanceTitre");
        String seanceContenue = request.getParameter("seanceContenue");
        String seanceType = request.getParameter("seanceType");


        Matiere matiere = MatiereDao.getMatiere(matiereId);



        Seance nouveauSeance = new Seance();
        nouveauSeance.setSeanceTitre(seanceTitre);
        nouveauSeance.setSeanceContenue(seanceContenue);
        nouveauSeance.setSeanceType(seanceType);



        nouveauSeance.setMatiere(matiere);
        nouveauSeance.setSeanceTitre(seanceTitre);
        nouveauSeance.setSeanceContenue(seanceContenue);


        SeanceDao.addSeance(nouveauSeance);


        List<Seance> seances = SeanceDao.getAllSeanceByMatiereId(matiereId);
        List<Matiere> matieres = MatiereDao.getAllMatiereBySemestreId(matiere.getSemestre().getSemestreId());



        request.setAttribute("matieres", matieres); 
        request.setAttribute("seances", seances);

        response.sendRedirect("CTN/ListPage.jsp");

    }

JSP Page:

<div class="box">

                <form action="./NewSeanceAjouterServlet" method="POST">

                    <input id="texthidden" type="text" name="matiereId" value="${matiere.matiereId}" readonly="readonly" /> 

                    <p><span>titre</span></p>
                    <p>
                        <textarea name="seanceTitre"class="courstitre" id=""></textarea>
                        <br/> 
                    </p>

                    <div class="ajouter" >

                        <textarea class="courstext" name="seanceContenue"> </textarea> 

                        <select name="seanceType" selected="selected">                            
                            <option value="Cours">Cours</option>  
                            <option value="Voyage d'Etude">Voyage d'Etude</option>  
                            <option value="Devoir">Devoir</option>  
                            <option value="Examen">Examen</option>  
                        </select>

                        <input   class="button" type="submit" name="action" value="AJOUTER" />

                    </div> 
                </form>   
            </div>

Upvotes: 1

Views: 2820

Answers (2)

Jops
Jops

Reputation: 22715

This approach is different from what you're doing - this is the Synchronizer Token Pattern. This solution requires you to add a mechanism to identify the first request from the resubmissions.

The idea: Use a hidden token while presenting the request form itself, and use it to flag out the first request from any succeeding requests.

Once the first submit is received, you will receive back that token. Invalidate that token, so that you'll know that any future requests containing that token are repeat requests. With that information, you can stop your processing logic from writing into the database.

The token can be a random number, or the timestamp.

General flow:

  1. User hits your URL.

  2. It triggers a servlet where you add the token into the session.

    session.setAttribute("TOKEN", “12345");  // some random number
    
  3. Redirect your servlet to a JSP (which becomes the request form for the user) and there, prepare the token in a hidden field.

    <input type=hidden name=TOKEN value="<%= session.getAttribute("TOKEN") %>" />
    
  4. User submits.

  5. You check the TOKEN against that in the session. Then immediately set it to something else.

    if (tokenFromRequest == tokenFromSession) {
        session.setAttribute("TOKEN", "INVALID"); // or null
        // do your database activities
    } else { 
        // this is a resubmission, do nothing. Simply redirect to display page.
    }
    

PS: The one you're doing is the Post-Redirect-Get (PRG) Approach, that requires an extra network trip and has a small exposure when the refresh is pressed too fast such that the redirect has not yet been triggered. The solution above addresses both.

Upvotes: 0

Wand Maker
Wand Maker

Reputation: 18762

You need to redirect the user to list page.

It is a best practice to redirect user to a GET URL after POST. http://en.wikipedia.org/wiki/Post/Redirect/Get

Since sendRedirect accepts relative URL, I don't think you should add the context path to the URL to which you are redirecting. The error probably is because you are redirecting to a non existing URL. Try visiting the URL in browser directly and see whether it works.

Upvotes: 1

Related Questions