2010-01-13 9 views
7

tworzę wejście CAPTCHA za pomocą SimpleCaptcha i zrobił walidacji wejścia Captcha. Zostało utworzone wejście captcha z następującymi kodami.Captcha serwlet powoduje java.lang.IllegalStateException: PWC3999: Nie można utworzyć sesji po odpowiedź zostało popełnione

HTML kod:

<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> 

Kod 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); 
} 

Jednak Ciągle otrzymuję ten błąd:

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

Jak mogę utworzyć sesji na moim serwletu? Jak mogę rozwiązać ten problem?

Dziękuję bardzo.

+1

skąd masz sesję? czy brakuje niektórych ważnych elementów twojej metody? Gdzie jest 'HttpSession session = request.getSession();' lub podobne wyrażenie? jak zdobywasz obiekt sesji? – WildWezyr

+0

@WildWezyr: Myślę, że przypadkowo usunąłem to po testowaniu, dodałem do kodu, HttpSession session = request.getSession (true); –

Odpowiedz

16

Cannot create a session after the response has been committed

Wiadomość wyjątku jest całkiem jasna. Są środki nielegalnego państwa. Nie można ustawić/zmienić nagłówki odpowiedzi już gdy odpowiedź jest już popełnione. Odpowiedź zostaje zatwierdzona, gdy nagłówki są już wysłane do klienta. Jest to punkt bez powrotu.

Odpowiedź zostanie zatwierdzona za każdym razem, gdy strumień danych zostanie bezpośrednio przepłukany.Może się to zdarzyć, gdy do odpowiedzi zostanie wysłane więcej niż 2K (zależnie od konfiguracji serwera) lub ręcznie: flush() lub wykonano wywołanie sendRedirect().

Zawsze, gdy sesja musi zostać utworzona, serwer musi ustawić plik cookie w nagłówku odpowiedzi, aby mógł zidentyfikować konkretnego klienta i powiązać go z instancją HttpSession w pamięci serwera. Ale nie jest to możliwe, jeśli odpowiedź została już zatwierdzona, stąd ten wyjątek.

Powrót do głównej przyczyny tego problemu:

Servlet.service() for servlet Captcha threw exception

Jest aplet z servlet-name z Captcha który spowodował ten problem. Należy sprawdzić/debugować cały łańcuch żądanie-odpowiedź, aby zobaczyć, które serwlety/filtry są wywoływane i które z nich mogły zatwierdzić odpowiedź, aby serwlet mógł utworzyć sesję. Nie mogę ci więcej pomóc, ponieważ brakuje tych informacji w twoim temacie.

Przynajmniej w tym podanym przykładzie kodu widzę, że jesteś niepotrzebnie dzwoniąc pod numer response.getWriter(). Nie jestem pewien, jak wygląda kod świata rzeczywistego, być może usunąłeś kilka linii, ale są szanse, że faktycznie piszesz do niego i to może być przyczyną problemu. Jeśli napiszesz za dużo lub spuścisz kolor, to resopnse zostanie zatwierdzony. Czy nie napisz do odpowiedzi w Servlet, który ma być kontrolerem. Tam zwykle używasz JSP dla. Lub jeśli służy do debugowania, użyj stdout (System.out.println()) lub Logger.

+1

@BalusC: tak masz rację. to jest idealnie problem z sesją. I captcha rzeczywiście stwarza problem. Zarządzane w celu rozwiązania problemu poprzez przesunięcie sesji setAttribute przed wygenerowaniem obrazu captcha. Dzięki. –

0

Wydaje się, że już wysłał nagłówek do klienta przed zabiegiem w słupek. Jeśli utworzysz sesję, serwer musi wysłać identyfikator sesji do klienta. Zwykle odbywa się to poprzez wysłanie pliku cookie. Przypuszczam sprawdzić swój kod do tego, czy wykonać manipulację działania przed wysłaniem czegokolwiek z powrotem do klienta.

0

utworzyć sesję, dodając tę ​​ 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

jakiej wartości wówczas oczekiwalibyśmy session.getAttribute (Captcha.NAME); wracać? – djna

0

Linia ta

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

oznacza, że ​​sesja powinna już istnieć, zanim ten konkretny wniosek jest przetwarzany, dlatego zastanawiam się, czy jest jakiś sposób inicjalizacji jesteś robić przed wysłaniem oryginalną formę. To powinno być określone przez strukturę, z której korzystasz.

Na przykład można mieć wstępną serlvet że

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) 

można zrobić to wszystko w JSP, czy można mieć serwletu do przodu do jednego.

Czy istnieją przykłady wykorzystania tej biblioteki catcha można zbadać?

+0

@djna: Jak zainicjować przed wysłaniem oryginalnego formularza? –

+0

@djna: używam Simple Captcha, http://simplecaptcha.sourceforge.net/index.html, ale podają tylko przykład w jsp. Naprawdę muszę przekonwertować to na serwlet. –

1

Move to linia:

HttpSession session = request.getSession(true); 

być pierwszą instrukcją w metodzie doPost.

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

    HttpSession session = request.getSession(true); 

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

    //... 
} 

To powinno pomóc.

+0

@WildWezyr: Przesunięty do góry, ale komunikat o wyjątku nadal istnieje. –

+0

@jl: czy na pewno poprawnie przetworzyłeś i ponownie zainstalowałeś swoją aplikację przed testowaniem ;-)? Czasem zdarza się, że testowanie poprawek powinno działać, ale wydaje się, że nie ... – WildWezyr

+0

@WildWezyr: Przebudowuję i czyścimy i ładujemy za pomocą netbeans. –

2

Kod naruszający to nl.captcha.servlet.SimpleCaptchaServlet Serwlet. Jeśli zmienisz go na StickyCaptcha, problem zniknie, ale konkretnie poniższe linie są urażone w Servletie SimpleCaptcha.

Właściwie kod zapisuje plik obrazu do odpowiedzi (zwykle jest to więcej niż domyślnie 2k).

Tak więc na razie można użyć StickyCaptcha lub sprawdzić kod i naprawić problem.

Powiązane problemy