java.lang.IllegalStateException: ¿No (avance | sendRedirect | crear la sesión) después de la respuesta se ha cometido

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

Pregunta

Este método lanza

  

java.lang.IllegalStateException: no puede reenviar después de la respuesta se ha cometido

y yo soy incapaz de detectar el problema. Cualquier ayuda?

    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);
    }
¿Fue útil?

Solución

Un malentendido común entre los abridores es que piensan que la llamada de un forward(), sendRedirect() o sendError() mágicamente salir y "saltar" fuera del bloque de método, la presente ignorando el resto del código. Por ejemplo:

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

Esto es así en realidad no es cierto. Desde luego, no se comportan de manera diferente que cualquier otro método de Java (esperan de System#exit() por supuesto). Cuando el someCondition en el ejemplo anterior es true y que está llamando tanto forward() después sendRedirect() o sendError() en la misma petición / respuesta, entonces la probabilidad es grande que obtendrá la excepción:

  

java.lang.IllegalStateException: no puede reenviar después de la respuesta se ha cometido

Si la declaración if llama un forward() y que está llamando después sendRedirect() o sendError(), a continuación, a continuación excepción será lanzada:

  

java.lang.IllegalStateException: No se puede llamar sendRedirect () después de que la respuesta ha sido cometido

Para solucionar esto, se deben añadir una declaración return; después

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

... o para introducir un bloque más.

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

Para Naildown la causa fundamental de su código, sólo la búsqueda de cualquier línea que llama a un forward(), sendRedirect() o sendError() sin salir del bloque de método o saltarse el resto del código. Esto puede ser en el interior del mismo servlet antes de la línea de código en particular, pero también en cualquier servlet o el filtro que se ha llamado antes de que el servlet particular.

En caso de sendError(), si su único propósito es establecer el estado de respuesta, el uso setStatus() lugar.


Otra causa probable es que el servlet escribe en la respuesta mientras que un forward() se llama, o se le ha llamado en el mismo método.

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

La respuesta búfer de tamaño por defecto en la mayoría de servidor a 2 KB, por lo que si se escribe más de 2 KB a él, entonces se va a cometer un error y forward() será de la misma manera:

  

java.lang.IllegalStateException: no puede reenviar después de la respuesta se ha cometido

La solución es obvia, simplemente no escribir a la respuesta en el servlet. Esa es la responsabilidad de la JSP. Que acaba de establecer un atributo de la petición al igual que request.setAttribute("data", "some string") y luego imprimirlo en JSP como tal ${data}. Ver también nuestra página wiki servlets para aprender a usar servlets de la manera correcta.


Sin embargo, otra causa probable es que el forward(), métodos sendRedirect() o sendError() se invocan a través de código Java incrustado en un archivo JSP en forma de vieja manera <% scriptlets %> moda, una práctica que era desalienta oficialmente desde 2001 . Por ejemplo:

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

        <% sendRedirect(); %>

        ...
    </body>
</html>

El problema aquí es que JSP internamente escribe inmediatamente texto de la plantilla (es decir, código HTML) a través de out.write("<!DOCTYPE html> ... etc ...") tan pronto como se encontró. Esto es así esencialmente el mismo problema como se explica en la sección anterior.

La solución es obvia, simplemente no escribir código Java en un archivo JSP. Esa es la responsabilidad de una clase Java normal, como un servlet o un filtro. Ver también nuestra página wiki servlets para aprender a usar servlets de la manera correcta.


Ver también:


Sin relación para su concreTe problema, su código JDBC tiene una fuga de recursos. Fix eso también. En busca de pistas, consulta ¿Con qué frecuencia debe de conexión , Statement y ResultSet se cerrarán en JDBC?

Otros consejos

incluso la adición de una instrucción de retorno nos lleva a esta excepción, por lo que la única solución es este código:

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

Por lo general se ve este error después de que ya ha hecho una redirección y luego intentar sacar algunos datos más a la corriente de salida. En los casos en los que he visto esto en el pasado, a menudo es uno de los filtros que está tratando de redirigir a la página, y luego sigue hacia delante hasta el servlet. No puedo ver nada de inmediato mal con el servlet, por lo que es posible que desee para tratar de echar un vistazo a todos los filtros que usted tiene en su lugar también.

Editar : Un poco más ayuda en el diagnóstico del problema ...

El primer paso para el diagnóstico de este problema es determinar exactamente dónde se produce la excepción. Estamos suponiendo que está siendo lanzada por la línea

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

Sin embargo, es posible encontrar que está siendo lanzado más adelante en el código, en el que está tratando de salida para el flujo de salida después de haber tratado de hacer lo adelante. Si se viene de la línea de arriba, entonces significa que en algún lugar antes de esta línea tiene cualquiera:

  1. datos de salida con la corriente de salida, o
  2. hecho otra redirección de antemano.

Buena suerte!

Esto es porque su servlet está intentando acceder a un objeto de solicitud, que no es más existen .. Un servlet es hacia delante o include no se detiene la ejecución del bloque método. Se continúa hasta el final del bloque de método o primera instrucción de retorno al igual que cualquier otro método de Java.

La mejor manera de resolver este problema acaba de establecer la página (donde se supone que debe reenviar la petición) según la lógica dinámica. Es decir:

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
}

y hacer el delantero sólo una vez en la última línea ...

También puede solucionar este problema mediante sentencia de retorno después de cada avance () o poner a cada avance () si en bloque else ...

Quité

        super.service(req, res);

A continuación, funcionó bien para mí

Bump ...

Sólo tenía el mismo error. Noté que estaba invocando super.doPost(request, response); cuando reemplazando el método doPost() además de invocar explícitamente la superclase constructor

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

Tan pronto como me comentó el super.doPost(request, response); desde dentro comunicado doPost() funcionó perfectamente ...

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

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

}

No hace falta decir, que necesito para volver a leer sobre las mejores prácticas super(): p

Se debe agregar rendimiento declaración mientras se reenvíe o redirigir el flujo.

Ejemplo:

Si forwardind,

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

Si la reorientación,

    response.sendRedirect(roundTripURI);
    return;

Después de método de avance de retorno puede simplemente hacer esto:

return null;

Se romperá el ámbito actual.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top