java.lang.illegalStateException: não pode (encaminhar | Sendredirect | Criar sessão) após a resposta ter sido cometida

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

Pergunta

Este método joga

java.lang.illegalStateException: não pode encaminhar após a resposta ter sido cometida

E não consigo identificar o problema. Qualquer ajuda?

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

Solução

Um mal -entendido comum entre os iniciantes é que eles pensam que o chamado de um forward(), sendRedirect(), ou sendError() Sairia magicamente e "pularia" para fora do bloco de métodos, ignorando o remanescente do código. Por exemplo:

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

Isso, portanto, não é realmente verdadeiro. Eles certamente não se comportam de maneira diferente de qualquer outro método Java (espere de System#exit() é claro). Quando o someCondition no exemplo acima é true E você está ligando assim forward() depois sendRedirect() ou sendError() Na mesma solicitação/resposta, então a chance é grande que você terá a exceção:

java.lang.illegalStateException: não pode encaminhar após a resposta ter sido cometida

Se o if Declaração chama a forward() E você está depois ligando sendRedirect() ou sendError(), então a exceção abaixo será lançada:

java.lang.illegalStateException: não é possível ligar para sendRedirect () depois que a resposta foi cometida

Para consertar isso, você precisa adicionar um return; declaração depois

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

... ou para apresentar um bloco else.

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

Para pregar a causa raiz do seu código, basta procurar qualquer linha que chama um forward(), sendRedirect() ou sendError() sem sair do bloqueio do método ou pular o remanescente do código. Isso pode estar dentro do mesmo servlet antes da linha de código específica, mas também em qualquer servlet ou filtro que tenha sido chamado antes do servlet específico.

No caso de sendError(), se seu único objetivo é definir o status de resposta, use setStatus() em vez de.


Outra causa provável é que o servlet grava para a resposta enquanto um forward() será chamado ou foi chamado no mesmo método.

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

O tamanho do buffer de resposta é inadimplente na maioria dos servidores para 2kb; portanto, se você escrever mais de 2kb, ele será comprometido e será comprometido e forward() falhará da mesma maneira:

java.lang.illegalStateException: não pode encaminhar após a resposta ter sido cometida

A solução é óbvia, apenas não escreva para a resposta no servlet. Essa é a responsabilidade do JSP. Você acabou de definir um atributo de solicitação como assim request.setAttribute("data", "some string") e então imprima -o no jsp como assim ${data}. Veja também Página da nossa wiki de servlets Para aprender a usar os servlets da maneira certa.


Mais uma causa provável é que o forward(), sendRedirect() ou sendError() Os métodos são invocados via código Java incorporado em um arquivo JSP na forma de maneira antiga <% scriptlets %>, uma prática que era Oficialmente desanimado desde 2001. Por exemplo:

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

        <% sendRedirect(); %>

        ...
    </body>
</html>

O problema aqui é que o JSP internamente grava imediatamente o texto do modelo (ou seja, código HTML) via out.write("<!DOCTYPE html> ... etc ...") Assim que é encontrado. Portanto, esse é essencialmente o mesmo problema explicado na seção anterior.

A solução é óbvia, apenas não escreva o código Java em um arquivo JSP. Essa é de responsabilidade de uma classe Java normal, como um servlet ou um filtro. Veja também Página da nossa wiki de servlets Para aprender a usar os servlets da maneira certa.


Veja também:


Não relacionado Para o seu problema concreto, seu código JDBC está vazando recursos. Corrija isso também. Para dicas, veja também Com que frequência a conexão, a instrução e o resultado do resultado devem ser fechados no JDBC?

Outras dicas

Mesmo a adição de uma declaração de retorno traz à tona esta exceção, para a qual apenas a solução é este código:

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

Normalmente, você vê esse erro depois de já ter feito um redirecionamento e, em seguida, tenta produzir mais dados para o fluxo de saída. Nos casos em que eu vi isso no passado, geralmente é um dos filtros que está tentando redirecionar a página e depois ainda a encaminha para o servlet. Não consigo ver nada imediatamente errado com o servlet, então você também pode tentar dar uma olhada nos filtros que você possui.

Editar: Alguma ajuda para diagnosticar o problema ...

O primeiro passo para diagnosticar esse problema é verificar exatamente onde a exceção está sendo lançada. Estamos assumindo que está sendo jogado pela linha

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

Mas você pode achar que ele está sendo jogado posteriormente no código, onde está tentando emitir o fluxo de saída depois de tentar fazer o avanço. Se estiver proveniente da linha acima, significa que em algum lugar antes desta linha você tem:

  1. dados de saída para o fluxo de saída, ou
  2. fez outro redirecionamento de antemão.

Boa sorte!

Isso ocorre porque seu servlet está tentando acessar um objeto de solicitação que não existe mais. Ele continua até o final do bloqueio do método ou a primeira declaração de retorno, como qualquer outro método Java.

A melhor maneira de resolver esse problema basta definir a página (onde você supõe encaminhar a solicitação) dinamicamente de acordo com sua lógica. Aquilo é:

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
}

E faça o avanço apenas uma vez na última linha ...

Você também pode corrigir esse problema usando a instrução RETURN após cada forward () ou colocar cada adiante () em If ... else Block

Eu removi

        super.service(req, res);

Então funcionou bem para mim

Ressalto...

Eu só tive o mesmo erro. Eu notei que estava invocando super.doPost(request, response); Ao substituir o doPost() método, bem como invocar explicitamente o construtor de superclasse

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

Assim que comentei o super.doPost(request, response); de dentro doPost() declaração funcionou perfeitamente ...

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

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

}

Escusado será dizer que preciso reler super() Melhores práticas: P

Você deve adicionar Retorna Declaração enquanto você está encaminhando ou redirecionando o fluxo.

Exemplo:

Se forwardind,

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

Se redirecionar,

    response.sendRedirect(roundTripURI);
    return;

Após o retorno do método de retorno, você pode simplesmente fazer isso:

return null;

Isso quebrará o escopo atual.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top