java.lang.IllegalStateException:Impossibile (inoltrare | inviareRedirect | creare sessione) dopo che la risposta è stata confermata
-
22-09-2019 - |
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);
}
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:
- dati di output nel flusso di output, o
- 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.