java.lang.IllegalStateException: Ne peut pas (avant | sendRedirect | créer session) après la réponse a été commise

StackOverflow https://stackoverflow.com/questions/2123514

Question

Cette méthode renvoie

  

java.lang.IllegalStateException: ne peut pas transmettre après la réponse a été commise

et je suis incapable de repérer 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);
    }
Était-ce utile?

La solution

Un malentendu fréquent chez les débutants est qu'ils pensent que l'appel d'un forward(), sendRedirect() ou sendError() serait par magie sortir et « sauter » hors du bloc de méthode, en ignorant par la présente le reste du code. Par exemple:

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

Ceci est donc en réalité pas vrai. Ils ne se comportent certainement pas différemment des autres méthodes Java (attendent de System#exit() bien sûr). Lorsque le someCondition dans l'exemple ci-dessus est true et vous appelez ainsi forward() après sendRedirect() ou sendError() sur la même demande / réponse, puis la chance est grand que vous obtiendrez l'exception:

  

java.lang.IllegalStateException: ne peut pas transmettre après la réponse a été commise

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

  

java.lang.IllegalStateException: Impossible d'appeler sendRedirect () après la réponse a été commise

Pour résoudre ce problème, vous devez soit d'ajouter une déclaration de return; après

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

... ou d'introduire un autre bloc.

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

Pour Naildown la cause racine dans votre code, il suffit de chercher une ligne qui appelle un forward(), sendRedirect() ou sendError() sans quitter le bloc de méthode ou de sauter le reste du code. Cela peut être à l'intérieur de la même servlet avant la ligne de code particulier, mais aussi dans un servlet ou un filtre qui a été été appelé avant le servlet particulier.

En cas de sendError(), si votre seul but est de définir l'état de 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!
}

Les valeurs par défaut de la taille du tampon de réponse dans la plupart serveur à 2 Ko, donc si vous écrivez plus de 2 Ko à lui, alors il sera engagé et forward() échouera de la même façon:

  

java.lang.IllegalStateException: ne peut pas transmettre après la réponse a été commise

La solution est évidente, il suffit de ne pas écrire à la réponse du servlet. C'est la responsabilité de la JSP. Vous venez de définir un attribut de requête comme si request.setAttribute("data", "some string") puis l'imprimer en JSP comme si ${data}. Voir aussi notre Servlets page wiki pour apprendre à utiliser Servlets la bonne façon.


Une autre cause probable est que le forward(), les méthodes de sendRedirect() ou sendError() sont appelés via le code Java intégré dans un fichier JSP sous forme de vieux <% scriptlets %> manière façonné, une pratique qui était officiellement découragées depuis 2001 . Par exemple:

<!DOCTYPE html>
<html lang="en">
    <head>
        ... 
    </head>
    <body>
        ...

        <% sendRedirect(); %>

        ...
    </body>
</html>

Le problème ici est que JSP interne écrit immédiatement modèle de texte (par exemple le code HTML) par l'intermédiaire out.write("<!DOCTYPE html> ... etc ...") dès qu'il a rencontré. Ceci est donc essentiellement le même problème, comme expliqué dans la section précédente.

La solution est évidente, il suffit de ne pas écrire du code Java dans un fichier JSP. C'est la responsabilité d'une classe Java normale comme un Servlet ou un filtre. Voir aussi notre Servlets page wiki pour apprendre à utiliser Servlets la bonne façon.


Voir aussi:


Aucun lien à votre travproblème te, votre code JDBC ressources fuite. Fix aussi. Pour des conseils, voir aussi Quelle est la fréquence de connexion , Déclaration et ResultSet être fermés dans JDBC?

Autres conseils

même en ajoutant une déclaration de retour soulève cette exception, pour laquelle seule solution est ce code:

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

En général, vous voyez cette erreur une fois que vous avez déjà fait une redirection, puis essayer de transmettre certaines données plus au flux de sortie. Dans les cas où je l'ai vu dans le passé, il est souvent l'un des filtres qui essaie de rediriger la page, puis transmet toujours par la servlet. Je ne vois rien de mal immédiatement avec le servlet, alors vous pourriez vouloir essayer d'avoir un oeil à tous les filtres que vous avez mis en place aussi bien.

Modifier : plus d'aide à diagnostiquer le problème ...

La première étape pour diagnostiquer ce problème est de savoir exactement où est jeté l'exception. Nous partons du principe qu'il est jeté par la ligne

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

Mais vous trouverez peut-être qu'il est jeté plus tard dans le code, où vous essayez de sortie vers le flux de sortie après avoir essayé de faire l'avant. Si elle vient de la ligne ci-dessus, cela signifie que quelque part avant cette ligne, vous avez soit:

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

Bonne chance!

Ceci est parce que votre servlet tente d'accéder à un objet de la demande qui est plus exister .. Un servlet est en avant ou instruction include ne pas arrêter l'exécution du bloc de méthode. Il continue à la fin du bloc de méthode ou première déclaration de retour comme toute autre méthode java.

La meilleure façon de résoudre ce problème il suffit de définir la page (où vous supposez de transmettre la demande) de façon dynamique selon 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 faire l'avant qu'une seule fois à la dernière ligne ...

vous pouvez également résoudre ce problème en utilisant la déclaration de retour après chaque avant () ou chaque avant de mettre () en bloc if ... else

supprimé

        super.service(req, res);

Alors il a bien fonctionné pour moi

Bump ...

Je viens d'avoir la même erreur. J'ai remarqué que j'invoquait super.doPost(request, response); lorsque redéfinissant la méthode doPost() ainsi que d'invoquer explicitement le constructeur superclasse

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

Dès que je commentais le super.doPost(request, response); à partir de la déclaration de doPost() cela a fonctionné parfaitement ...

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

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

}

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

Vous devez ajouter retour déclaration lorsque vous transférez ou de rediriger le flux.

Exemple:

si forwardind,

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

si la redirection,

    response.sendRedirect(roundTripURI);
    return;

Après le retour méthode avant que vous pouvez simplement faire ceci:

return null;

Il brisera la portée actuelle.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top