java.lang.IllegalStateException:Impossibile (inoltrare | inviareRedirect | creare sessione) dopo che la risposta è stata confermata

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

Domanda

Questo metodo lancia

java.lang.IllegalStateException:Impossibile inoltrare dopo che la risposta è stata confermata

e non riesco a individuare il problema.Qualsiasi aiuto?

    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);
    }
È stato utile?

Soluzione

Un malinteso comune tra i principianti è che pensano che la chiamata di a forward(), sendRedirect(), O sendError() uscirebbe magicamente e "salterebbe" fuori dal blocco del metodo, ignorando così il resto del codice.Per esempio:

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

Ciò quindi in realtà non è vero.Certamente non si comportano in modo diverso rispetto a qualsiasi altro metodo Java (tranne System#exit() Ovviamente).Quando il someCondition nell'esempio sopra è true e quindi stai chiamando forward() Dopo sendRedirect() O sendError() sulla stessa richiesta/risposta, allora la possibilità è grande che otterrai l'eccezione:

java.lang.IllegalStateException:Impossibile inoltrare dopo che la risposta è stata confermata

Se la if l'istruzione chiama a forward() e poi chiamerai sendRedirect() O sendError(), verrà lanciata l'eccezione seguente:

java.lang.IllegalStateException:Impossibile chiamare sendRedirect() dopo che la risposta è stata confermata

Per risolvere questo problema, è necessario aggiungere a return; dichiarazione successiva

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

...o per introdurre un blocco else.

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

Per individuare la causa principale nel tuo codice, cerca semplicemente qualsiasi riga che chiami a forward(), sendRedirect() O sendError() senza uscire dal blocco del metodo o saltare il resto del codice.Questo può trovarsi all'interno dello stesso servlet prima della particolare riga di codice, ma anche in qualsiasi servlet o filtro che sia stato chiamato prima del particolare servlet.

In caso di sendError(), se il tuo unico scopo è impostare lo stato della risposta, utilizza setStatus() Invece.


Un'altra causa probabile è che la servlet scriva nella risposta mentre a forward() sarà chiamato, o è stato chiamato con lo stesso metodo.

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

La dimensione predefinita del buffer di risposta è 2KB nella maggior parte dei server, quindi se scrivi più di 2KB su di esso, verrà eseguito il commit e forward() fallirà allo stesso modo:

java.lang.IllegalStateException:Impossibile inoltrare dopo che la risposta è stata confermata

La soluzione è ovvia, basta non scrivere nella risposta nel servlet.Questa è la responsabilità del JSP.Basta impostare un attributo di richiesta in questo modo request.setAttribute("data", "some string") e poi stamparlo in JSP in questo modo ${data}.Guarda anche la nostra pagina wiki dei servlet per imparare a usare le servlet nel modo giusto.


Ancora un'altra causa probabile è che il forward(), sendRedirect() O sendError() i metodi vengono richiamati tramite codice Java incorporato in un file JSP in forma antiquata <% scriptlets %>, una pratica che era ufficialmente scoraggiato dal 2001.Per esempio:

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

        <% sendRedirect(); %>

        ...
    </body>
</html>

Il problema qui è che JSP scrive internamente immediatamente il testo del modello (ad es.codice HTML) tramite out.write("<!DOCTYPE html> ... etc ...") non appena viene incontrato.Si tratta quindi essenzialmente dello stesso problema spiegato nella sezione precedente.

La soluzione è ovvia, basta non scrivere codice Java in un file JSP.Questa è la responsabilità di una normale classe Java come un Servlet o un Filtro.Guarda anche la nostra pagina wiki dei servlet per imparare a usare le servlet nel modo giusto.


Guarda anche:


Non correlato al tuo problema concreto, il tuo codice JDBC perde risorse.Risolvi anche quello.Per suggerimenti, vedere anche Con quale frequenza è necessario chiudere Connection, Statement e ResultSet in JDBC?

Altri suggerimenti

anche l'aggiunta di un'istruzione return fa apparire questa eccezione, per la quale l'unica soluzione è questo codice:

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

In genere viene visualizzato questo errore dopo aver già eseguito un reindirizzamento e quindi provare a inviare altri dati al flusso di output.Nei casi in cui l'ho visto in passato, spesso è uno dei filtri che tenta di reindirizzare la pagina e quindi la inoltra comunque al servlet.Non riesco a vedere nulla di immediatamente sbagliato nel servlet, quindi potresti provare a dare un'occhiata anche a tutti i filtri che hai in atto.

Modificare:Qualche ulteriore aiuto per diagnosticare il problema...

Il primo passo per diagnosticare questo problema è accertare esattamente dove viene generata l'eccezione.Supponiamo che venga lanciato dalla linea

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

Ma potresti scoprire che viene lanciato più avanti nel codice, dove stai tentando di eseguire l'output nel flusso di output dopo aver provato a eseguire l'inoltro.Se proviene dalla riga precedente, significa che da qualche parte prima di questa riga hai:

  1. dati di output nel flusso di output, o
  2. fatto un altro reindirizzamento in anticipo.

Buona fortuna!

Questo perché la tua servlet sta tentando di accedere a un oggetto di richiesta che non esiste più.L'istruzione forward o include di una servlet non interrompe l'esecuzione del blocco del metodo.Continua fino alla fine del blocco del metodo o alla prima istruzione di ritorno proprio come qualsiasi altro metodo Java.

Il modo migliore per risolvere questo problema è semplicemente impostare la pagina (dove supponi di inoltrare la richiesta) in modo dinamico secondo la tua logica.Questo è:

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 fai l'avanzamento solo una volta all'ultima riga...

puoi anche risolvere questo problema usando l'istruzione return dopo ogni forward() o inserire ogni forward() nel blocco if...else

Ho rimosso

        super.service(req, res);

Allora ha funzionato bene per me

Colpo...

Ho appena avuto lo stesso errore.Ho notato che stavo invocando super.doPost(request, response); quando si sovrascrive il doPost() metodo oltre a invocare esplicitamente il costruttore della superclasse

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

Non appena ho commentato il super.doPost(request, response); dall'interno doPost() dichiarazione ha funzionato perfettamente...

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

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

}

Inutile dire che devo rileggere super() migliori pratiche: p

Dovresti aggiungere ritorno istruzione mentre si inoltra o reindirizza il flusso.

Esempio:

se inoltrato,

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

in caso di reindirizzamento,

    response.sendRedirect(roundTripURI);
    return;

Dopo il metodo return forward puoi semplicemente fare questo:

return null;

Interromperà l’ambito attuale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top