web-dev-qa-db-fra.com

java.lang.IllegalStateException: impossible (transmission | sendRedirect | créer une session) après la validation de la réponse

Cette méthode jette 

Java.lang.IllegalStateException: Impossible de transférer une fois la réponse validée

et je suis incapable de repérer le problème. De l'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);
    }
84
sansknwoledge

Un malentendu courant parmi les partants est qu’ils pensent que l’appel de forward(), sendRedirect() ou sendError() sortirait comme par magie et "sortirait" du bloc de méthode, ignorant ainsi 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 réellement pas vrai. Elles ne se comportent certainement pas différemment des autres méthodes Java (attend de System#exit() bien sûr). Lorsque someCondition dans l'exemple ci-dessus est true et que vous appelez donc forward() après sendRedirect() ou sendError() sur la même demande/réponse, le risque est alors big d'obtenir l'exception:

Java.lang.IllegalStateException: impossible de transférer après validation de la réponse

Si l'instruction if appelle une forward() et que vous appelez ensuite sendRedirect() ou sendError(), une exception ci-dessous sera levée:

Java.lang.IllegalStateException: impossible d'appeler sendRedirect () après la validation de la réponse

Pour résoudre ce problème, vous devez soit ajouter une instruction return; après.

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

... ou d'introduire un bloc else.

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

Pour identifier la cause fondamentale de votre code, il suffit de rechercher une ligne qui appelle un forward(), un sendRedirect() ou un sendError() sans quitter le bloc de méthode ni ignorer le reste du code. Cela peut se trouver dans le même servlet avant la ligne de code particulière, mais également dans un servlet ou un filtre appelé auparavant.

Dans le cas de sendError(), si votre seul objectif est de définir le statut de la réponse, utilisez plutôt setStatus().


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

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

La taille du tampon de réponse par défaut dans la plupart des serveurs est de 2 Ko. Par conséquent, si vous écrivez plus de 2 Ko, le fichier sera validé et forward() échouera de la même manière:

Java.lang.IllegalStateException: Impossible de transférer une fois la réponse validée

La solution est évidente, mais n'écrivez pas dans la réponse du servlet. C'est la responsabilité du JSP. Vous venez de définir un attribut de requête tel que so request.setAttribute("data", "some string"), puis de l’imprimer dans JSP de la même manière que ${data}. Voir aussi notre page wiki Servlets pour apprendre à utiliser correctement les Servlets.

Voir également:


Sans rapport avec votre problème concret, votre code JDBC perd des ressources. Corrige ça aussi. Pour des astuces, voir aussi À quelle fréquence Connection, Statement et ResultSet doivent-ils être fermés dans JDBC?

218
BalusC

même l'ajout d'une instruction return provoque cette exception pour laquelle la seule solution est ce code:

if(!response.isCommitted())
// Place another redirection
19
user1503117

En règle générale, vous voyez cette erreur après avoir déjà effectué une redirection, puis essayez de générer davantage de données dans le flux de sortie. Dans les cas où j’ai déjà vu cela auparavant, c’est souvent l’un des filtres qui tente de rediriger la page, puis est transmis au servlet. Je ne vois rien de mal immédiatement dans la servlet. Vous voudrez peut-être jeter un coup d'œil aux filtres que vous avez également mis en place.

Modifier: Encore plus d’aide pour diagnostiquer le problème…

La première étape pour diagnostiquer ce problème consiste à 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);

Toutefois, vous constaterez peut-être qu’il est renvoyé ultérieurement dans le code, où vous essayez d’afficher le flux de sortie après avoir essayé d’effectuer le transfert. Si cela vient de la ligne ci-dessus, alors cela signifie que quelque part avant cette ligne, vous avez soit:

  1. les données de sortie dans le flux de sortie, ou
  2. fait une autre redirection au préalable.

Bonne chance! 

6
Paul Wagland

En effet, votre servlet tente d'accéder à un objet de requête qui n'existe plus ... ... L'instruction forward ou include d'un servlet n'arrête pas l'exécution du bloc de méthode. Elle se poursuit jusqu'à la fin du bloc de méthode ou de la première instruction de retour, comme toute autre méthode Java.

La meilleure façon de résoudre ce problème consiste simplement à définir la page (où vous supposez transférer la demande) de manière dynamique en fonction de votre logique. C'est:

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 la transmission qu'une seule fois à la dernière ligne ...

vous pouvez également résoudre ce problème en utilisant l'instruction return après chaque forward () ou en plaçant chaque forward () dans if ... else block

2
Suman Sengupta

J'ai enlevé 

        super.service(req, res);

Alors ça a bien fonctionné pour moi

2
Kartik_Agarwal

Bosse...

Je viens d'avoir la même erreur. J'ai remarqué que j'appelais super.doPost(request, response); en redéfinissant la méthode doPost() et en appelant explicitement le constructeur de la superclasse. 

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

Dès que j'ai commenté la déclaration super.doPost(request, response); dans doPost(), cela a parfaitement fonctionné ...

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

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

}

Inutile de dire que je dois relire les meilleures pratiques de super(): p

2
John Rambo

Après la méthode de retour en avant, vous pouvez simplement faire ceci:

return null;

Cela rompra la portée actuelle.

0
Amir Amiri

Vous devez ajouter return statement pendant le transfert ou la redirection du flux.

Exemple: 

si forwardind,

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

si vous redirigez,

    response.sendRedirect(roundTripURI);
    return;
0
Ashish Mishra