2010-01-13 9 views
7

Sto creando un input CAPTCHA utilizzando SimpleCaptcha e ho convalidato l'input Captcha. Sono stato creato un captcha con i seguenti codici.Il servlet Captcha causa java.lang.IllegalStateException: PWC3999: Impossibile creare una sessione dopo che la risposta è stata commessa

codice HTML:

<form action="submit_proceed.do" method="post"> 
<img src="captchaImg" /><input type="text" name="captcha" value=""><br /> 
<input type="submit" value="Submit" name="submit" /> 
</form> 

Codice JavaServlet:

import java.io.IOException; 
import java.io.PrintWriter; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import java.util.List; 
import java.util.Iterator; 
import nl.captcha.Captcha; 

protected void doPost(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException { 
response.setContentType("text/html;charset=UTF-8"); 
PrintWriter out = response.getWriter(); 

List errorMsgs = new LinkedList(); 
try{ 
    // Validate Captcha 
    HttpSession session = request.getSession(true); 
    String userCaptcha = request.getParameter("captcha"); 
    Captcha captcha = (Captcha) session.getAttribute(Captcha.NAME); 
    if (!captcha.isCorrect(userCaptcha)) { 
     errorMsgs.add("Please input the correct Captcha value."); 
    } 
} catch (RuntimeException e) { 
    errorMsgs.add("An unexpected error: " + e.getMessage()); 
    RequestDispatcher view = request.getRequestDispatcher("/error.view"); 
    view.forward(request, response); 
} 

Tuttavia ho continuato a questo errore:

StandardWrapperValve[Captcha]: PWC1406: Servlet.service() for servlet Captcha threw exception 
java.lang.IllegalStateException: PWC3999: Cannot create a session after the response has been committed 

Come si crea una sessione sul mio servlet? Come posso risolvere questo problema?

Grazie mille.

+1

da dove riceve la sessione? ci sono alcune parti importanti del tuo metodo mancanti? Dov'è 'HttpSession session = request.getSession();' o dichiarazione simile? come acquisisci l'oggetto della sessione? – WildWezyr

+0

@WildWezyr: Penso di averlo eliminato per errore dopo il test, aggiunto al codice, HttpSession session = request.getSession (true); –

risposta

16

Cannot create a session after the response has been committed

Il messaggio di eccezione è abbastanza chiaro. Ci sono mezzi di uno stato illegale. Non è più possibile impostare/modificare le intestazioni di risposta quando la risposta è già stata confermata. Viene inviata una risposta quando le intestazioni sono già state inviate al lato client. Questo è un punto di senza ritorno.

La risposta verrà confermata ogni volta che l'outputstream è stato scaricato (in) direttamente.Ciò può accadere quando si scrive più di 2K alla risposta (dipende comunque dalla configurazione del server), oppure lo ha fatto manualmente flush() oppure ha effettuato una chiamata sendRedirect().

Ogni volta che è necessario creare la sessione, il server deve impostare un cookie nell'intestazione della risposta in modo che possa identificare il client specifico e associarlo a un'istanza HttpSession nella memoria del server. Ma questo non è possibile se la risposta è già stata commessa, quindi questa eccezione.

Indietro causa principale di questo problema:

Servlet.service() for servlet Captcha threw exception

È il servlet con la servlet-name di Captcha che ha causato il problema. È necessario controllare/eseguire il debug dell'intera catena richiesta-risposta per vedere quali servlet/filtri sono stati invocati e quale di essi potrebbe aver impegnato la risposta prima del il servlet Captcha è riuscito a creare la sessione. Non posso aiutarti più lontano in quanto queste informazioni mancano nel tuo topicstart.

Almeno, nell'esempio di codice dato finora, vedo che sei inutilmente chiamando response.getWriter(). Non sono sicuro di come sia il codice del mondo reale, forse hai spogliato alcune righe, ma è probabile che tu ci stia scrivendo e questa potrebbe essere la causa principale del problema. Se scrivi troppo o fai un flush, allora il resopnse verrà eseguito. Non scrivere nella risposta all'interno di un servlet che dovrebbe essere un controller. Lì normalmente usi la JSP per. O se è a scopo di debug, utilizzare lo stdout (System.out.println()) o uno Logger.

+1

@BalusC: sì hai ragione. è perfettamente il problema con la sessione. E captcha sta davvero creando il problema. Gestito per risolvere il problema spostando la sessione setAttribute prima che venga generata l'immagine captcha. Grazie. –

0

Sembra che abbia già inviato l'intestazione al client prima di gestire il post. Se si crea una sessione, il server deve inviare l'ID di sessione al client. Questo di solito viene fatto inviando un cookie. Suppongo che controlli il tuo codice per sapere se esegui la gestione delle azioni prima di inviare qualcosa al client.

0

creare una sessione aggiungendo questo javax.servlet.http.HttpSession session = request.getSession();


try{ 
javax.servlet.http.HttpSession session = request.getSession(); 
    // Validate Captcha 
    String userCaptcha = request.getParameter("captcha"); 
    Captcha captcha = (Captcha) session.getAttribute(Captcha.NAME); 
    if (!captcha.isCorrect(userCaptcha)) { 
     errorMsgs.add("Please input the correct Captcha value."); 
    } 
} catch (RuntimeException e) { 
    ... 
} 
+0

quale valore ci aspetteremmo allora session.getAttribute (Captcha.NAME); ritornare? – djna

0

Questa linea

(Captcha) session.getAttribute(Captcha.NAME); 

implica che la sessione dovrebbe già esistere prima questa particolare richiesta è in elaborazione, quindi mi chiedo è che c'è un po 'di inizializzazione che si suppone di fare prima di inviare il modulo originale. Questo dovrebbe essere specificato dal framework che stai utilizzando.

Per esempio si potrebbe avere un serlvet iniziale che

creates the image, figures out the value of Capcha.Name 
creates the session 
session.setAttribute(Capcha.NAME, theName) 
emit the html (or forward() to a JSP) 

si potrebbe fare tutto in un JSP, o si potrebbe avere il servlet in avanti a uno.

Esistono esempi di utilizzo di questa libreria catcha che è possibile esaminare?

+0

@djna: Come inizializzare prima di inviare il modulo originale? –

+0

@djna: sto usando Simple Captcha, http://simplecaptcha.sourceforge.net/index.html, ma indicano solo un esempio in jsp. Ho davvero bisogno di convertirlo in servlet. –

1

Sposta questa linea:

HttpSession session = request.getSession(true); 

di essere prima istruzione nel metodo doPost.

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

    HttpSession session = request.getSession(true); 

    response.setContentType("text/html;charset=UTF-8"); 

    //... 
} 

Questo dovrebbe aiutare.

+0

@WildWezyr: spostato verso l'alto, ma il messaggio di eccezione esiste ancora. –

+0

@jl: sei sicuro di aver ricostruito e ridistribuito correttamente la tua webapp prima del test ;-)? questo è il caso in cui si verificano correzioni che dovrebbero funzionare ma sembrano non ... – WildWezyr

+0

@WildWezyr: io ricostruisco, pulisco e carico tramite netbeans. –

2

Il codice di errore è nel servlet nl.captcha.servlet.SimpleCaptchaServlet. Se lo si cambia in StickyCaptcha il problema andrà via, ma in particolare le seguenti sono le righe incriminate nel servlet SimpleCaptcha.

CaptchaServletUtil.writeImage(resp, captcha.getImage()); 
req.getSession().setAttribute(NAME, captcha); 

In realtà il codice sta scrivendo il file di immagine alla risposta (che di solito è maggiore di predefinita 2k).

Quindi per il momento è possibile utilizzare il StickyCaptcha o il checkout del codice e risolvere il problema.

Problemi correlati