Java.lang.IllegalStateException: impossible (session forward | sendRedirect | create) après que la réponse a été engagée

cette méthode lance

de java.lang.IllegalStateException: Ne peut pas en avant après la réponse a été commis

et je ne vois pas le problème. Toute aide?

    int noOfRows = Integer.parseInt(request.getParameter("noOfRows"));
    String chkboxVal = "";
    // String FormatId=null;
    Vector vRow = new Vector();
    Vector vRow1 = new Vector();
    String GroupId = "";
    String GroupDesc = "";
    for (int i = 0; i < noOfRows; i++) {
        if ((request.getParameter("chk_select" + i)) == null) {
            chkboxVal = "notticked";
        } else {
            chkboxVal = request.getParameter("chk_select" + i);
            if (chkboxVal.equals("ticked")) {
                fwdurl = "true";
                Statement st1 = con.createStatement();
                GroupId = request.getParameter("GroupId" + i);
                GroupDesc = request.getParameter("GroupDesc" + i);
                ResultSet rs1 = st1
                        .executeQuery("select FileId,Description from cs2k_Files "
                                + " where FileId like 'M%' and co_code = "
                                + ccode);
                ResultSetMetaData rsm = rs1.getMetaData();
                int cCount = rsm.getColumnCount();

                while (rs1.next()) {
                    Vector vCol1 = new Vector();
                    for (int j = 1; j <= cCount; j++) {
                        vCol1.addElement(rs1.getObject(j));
                    }
                    vRow.addElement(vCol1);
                }
                rs1 = st1
                        .executeQuery("select FileId,NotAllowed from cs2kGroupSub "
                                + " where FileId like 'M%' and GroupId = '"
                                + GroupId + "'" + " and co_code = " + ccode);
                rsm = rs1.getMetaData();
                cCount = rsm.getColumnCount();

                while (rs1.next()) {
                    Vector vCol2 = new Vector();
                    for (int j = 1; j <= cCount; j++) {
                        vCol2.addElement(rs1.getObject(j));
                    }
                    vRow1.addElement(vCol2);
                }

                // throw new Exception("test");

                break;
            }
        }
    }
    if (fwdurl.equals("true")) {
        // throw new Exception("test");
        // response.sendRedirect("cs2k_GroupCopiedUpdt.jsp") ;
        request.setAttribute("GroupId", GroupId);
        request.setAttribute("GroupDesc", GroupDesc);
        request.setAttribute("vRow", vRow);
        request.setAttribute("vRow1", vRow1);
        getServletConfig().getServletContext().getRequestDispatcher(
                "/GroupCopiedUpdt.jsp").forward(request, response);
    }
82
demandé sur BalusC 2010-01-23 17:47:56

8 réponses

un malentendu courant parmi les débutants est qu'ils pensent que l'appel d'un forward() , sendRedirect() , ou sendError() sortirait magiquement et" sauterait " hors du bloc de méthode, ignorant par là le reste du code. Par exemple:

protected void doPost() {
    if (someCondition) {
        sendRedirect();
    }
    forward(); // This is STILL invoked when someCondition is true!
}

ce n'est donc pas vrai. Ils ne se comportent certainement pas différemment des autres méthodes Java (expect of System#exit() of course). Lorsque le someCondition dans l'exemple ci-dessus est true et vous appelez donc forward() après sendRedirect() ou sendError() sur la même demande/ réponse, alors la chance est grand que vous obtiendrez l'exception:

de java.lang.IllegalStateException: Ne peut pas en avant après la réponse a été commis

si la déclaration if appelle un forward() et que vous appelez ensuite sendRedirect() ou sendError() , alors l'exception ci-dessous sera être jeté:

de java.lang.IllegalStateException: Ne peut pas appeler sendRedirect() après que la réponse ait été commis

pour corriger cela, vous devez soit ajouter un return; déclaration après

protected void doPost() {
    if (someCondition) {
        sendRedirect();
        return;
    }
    forward();
}

... ou pour introduire un autre bloc.

protected void doPost() {
    if (someCondition) {
        sendRedirect();
    } else {
        forward();
    }
}

pour clouer la cause racine dans votre code, il suffit de rechercher n'importe quelle ligne qui appelle un forward() , sendRedirect() ou sendError() sans quitter le bloc de méthode ni sauter le reste du code. Cela peut être dans le même servlet avant la ligne de code particulière, mais aussi dans n'importe quel servlet ou filtre qui a été appelé avant le servlet particulier.

dans le cas de sendError() , si votre seul but est de définir le statut de la réponse, utilisez setStatus() à la place.


une autre cause probable est que le servlet écrit à la réponse alors qu'un forward() sera appelé, ou a été appelé dans la même méthode.

protected void doPost() {
    out.write("some string");
    // ... 
    forward(); // Fail!
}

la taille de tampon de réponse par défaut dans la plupart des serveurs à 2KB, donc si vous écrivez Plus de 2KB à elle, alors il sera engagé et forward() échouera de la même manière:

de java.lang.IllegalStateException: Ne peut pas en avant après la réponse a été commis

La Solution

est évidente, il suffit de ne pas écrire à la réponse dans le servlet. C'est la responsabilité de la JSP. Vous définissez simplement un attribut request comme request.setAttribute("data", "some string") et l'Imprimez dans JSP comme ${data} . Voir aussi notre page wiki de Servlets pour apprendre à utiliser les Servlets de la bonne manière.

voir aussi:


sans rapport avec votre problème concret, votre code JDBC fuit des ressources. Correctif. Pour les indices, voir aussi à quelle fréquence doit-on fermer Connection, Statement et ResultSet dans JDBC?

213
répondu BalusC 2017-05-23 10:31:19

même l'ajout d'une déclaration de retour soulève cette exception, pour laquelle seule la solution est ce code:

if(!response.isCommitted())
// Place another redirection
19
répondu user1503117 2014-06-30 06:08:32

typiquement vous voyez cette erreur après que vous avez déjà fait une redirection et ensuite essayer de produire plus de données au flux de sortie. Dans le cas où j'ai vu cela dans le passé, il est souvent l'un des filtres qui essaie de rediriger la page, et puis encore avant dans la servlet. Je ne vois rien qui ne va pas avec le servlet, donc vous pourriez essayer d'avoir un coup d'oeil à tous les filtres que vous avez en place aussi bien.

Edit : un peu plus d'aide pour diagnostiquer le problème ...

La première étape pour diagnostiquer ce problème est de déterminer exactement où l'exception est levée. Nous supposons qu'il est jeté par la ligne

getServletConfig().getServletContext()
                  .getRequestDispatcher("/GroupCopiedUpdt.jsp")
                  .forward(request, response);

mais vous pourriez trouver qu'il est lancé plus tard dans le code, où vous essayez de sortir au flux de sortie après que vous avez essayé de faire le forward. S'il vient de la ligne ci-dessus, alors il signifie que quelque part avant cette ligne vous avez l'un ou l'autre:

  1. données de sortie au flux de sortie, ou
  2. fait une autre redirection à l'avance.

bonne chance!

6
répondu Paul Wagland 2010-01-23 15:55:45

c'est parce que votre servlet essaie d'accéder à un objet request qui n'existe plus.. L'instruction forward ou include d'un servlet n'arrête pas l'exécution du bloc de méthode. Il continue jusqu'à la fin du bloc de méthode ou de la première instruction de retour comme n'importe quelle autre méthode java.

la meilleure façon de résoudre ce problème vient de régler la page (où vous supposez transmettre la requête) dynamiquement selon votre logique. C'est-à-dire:

protected void doPost(request , response){
String returnPage="default.jsp";
if(condition1){
 returnPage="page1.jsp";
}
if(condition2){
   returnPage="page2.jsp";
}
request.getRequestDispatcher(returnPage).forward(request,response); //at last line
}

et ne faites l'avant qu'une seule fois à la dernière ligne...

vous pouvez également corriger ce problème en utilisant l'instruction return après chaque forward() ou mettre chaque forward() dans if...autre bloc

2
répondu Suman Sengupta 2014-11-20 17:59:18

j'ai enlevé

        super.service(req, res);

Puis il a travaillé très bien pour moi

2
répondu Kartik_Agarwal 2015-08-14 07:21:16

Bump...

j'ai eu la même erreur. J'ai remarqué que j'invoquais super.doPost(request, response); quand j'ai surpassé la méthode doPost() en plus d'invoquer explicitement le constructeur de superclasses

    public ScheduleServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

dès que j'ai commenté le super.doPost(request, response); de l'intérieur de doPost() déclaration il a fonctionné parfaitement...

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

        //super.doPost(request, response);
        // More code here...

}

inutile de dire que j'ai besoin de relire super() best practices: p

2
répondu John Rambo 2016-08-12 17:45:20

vous devez ajouter return statement pendant que vous faites suivre ou rediriger le flux.

exemple:

si forwardind,

    request.getRequestDispatcher("/abs.jsp").forward(request, response);
    return;

si la redirection,

    response.sendRedirect(roundTripURI);
    return;
0
répondu Ashish Mishra 2014-09-05 07:38:31

après la méthode return forward vous pouvez simplement faire ceci:

return null;

il va briser la portée actuelle.

0
répondu Amir Amiri 2018-05-26 09:35:56