प्रतिक्रिया होने के बाद java.lang.IllegalStateException: आगे नहीं भेजा जा सकता है (आगे | sendRedirect | सत्र बनाएँ)।


96

यह विधि फेंकता है

java.lang.IllegalStateException: प्रतिसाद के बाद आगे नहीं किया जा सकता

और मैं समस्या को बताने में असमर्थ हूं। कोई मदद?

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

4
इस तरह से देखना मुश्किल है, लेकिन ऐसा लगता है कि आप अपने आउटपुट को आगे भेजने से पहले ही भेज चुके हैं। क्या आप कृपया पूरा कोड प्रिंट कर सकते हैं और जांच सकते हैं कि क्या आपके पास कोई फ़िल्टर नहीं है?
कार्तोच

जवाबों:


244

शुरुआत करने वालों के बीच एक आम गलतफहमी यह है कि उन्हें लगता है कि विधि ब्लॉक से एक forward(), sendRedirect()या, sendError()जादुई तरीके से बाहर निकलना और "कूदना" पड़ेगा, जिससे कोड के अवशेष की अनदेखी होगी। उदाहरण के लिए:

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

यह इस प्रकार वास्तव में सच नहीं है। वे निश्चित रूप से किसी भी अन्य जावा विधियों ( System#exit()पाठ्यक्रम की अपेक्षा ) से अलग व्यवहार नहीं करते हैं । जब someConditionउपरोक्त उदाहरण में है trueऔर आप इस तरह से या एक ही अनुरोध / प्रतिक्रिया के forward()बाद बुला रहे हैं , तो मौका बड़ा है कि आपको अपवाद मिलेगा:sendRedirect()sendError()

java.lang.IllegalStateException: प्रतिसाद के बाद आगे नहीं किया जा सकता

यदि ifस्टेटमेंट कॉल करता है forward()और आप बाद में कॉल कर रहे हैं sendRedirect()या sendError(), तो नीचे दिए गए अपवाद को फेंक दिया जाएगा:

java.lang.IllegalStateException: प्रतिसाद किए जाने के बाद SendRedirect () को कॉल नहीं किया जा सकता

इसे ठीक करने के लिए, आपको या तो return;बाद में एक बयान जोड़ना होगा

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

... या एक और ब्लॉक शुरू करने के लिए।

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

अपने कोड में मूल कारण को रद्द करने के लिए, बस किसी भी लाइन को खोजें, जो कॉल करता है forward(), sendRedirect()याsendError() विधि ब्लॉक से बाहर आए बिना या कोड के अवशेष को छोड़ देती है। यह विशेष कोड लाइन से पहले एक ही सर्वलेट के अंदर हो सकता है, लेकिन किसी भी सर्वलेट या फ़िल्टर में भी जिसे विशेष सर्वलेट से पहले कहा जाता था।

के मामले में sendError(), यदि आपका एकमात्र उद्देश्य प्रतिसाद स्थिति स्थापित करने के लिए है, का उपयोग setStatus()करने के बजाय।


एक और संभावित कारण यह है कि सर्वलेट प्रतिक्रिया के लिए लिखता है जबकि एक forward()को बुलाया जाएगा, या उसी पद्धति में बुलाया गया है।

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

प्रतिक्रिया बफर आकार 2KB के अधिकांश सर्वर में चूक करता है, इसलिए यदि आप इसे 2KB से अधिक लिखते हैं, तो यह प्रतिबद्ध forward()होगा और उसी तरह विफल हो जाएगा:

java.lang.IllegalStateException: प्रतिसाद के बाद आगे नहीं किया जा सकता

समाधान स्पष्ट है, बस सर्वलेट में प्रतिक्रिया के लिए नहीं लिखें। यह JSP की जिम्मेदारी है। आप बस एक अनुरोध विशेषता सेट करें request.setAttribute("data", "some string")और फिर इसे JSP में प्रिंट करें ${data}। सर्वलेट्स का सही तरीके से उपयोग करने का तरीका जानने के लिए हमारे सर्वलेट्स विकी पेज भी देखें ।


एक और संभावित कारण यह है कि सर्वलेट प्रतिक्रिया के लिए एक फ़ाइल डाउनलोड लिखता है जिसके बाद उदाहरण के लिए forward()इसे कहा जाता है।

protected void doXxx() {
    out.write(bytes);
    // ... 
    forward(); // Fail!
}

यह तकनीकी रूप से संभव नहीं है। आपको forward()कॉल हटाने की आवश्यकता है । एंड्यूसर वर्तमान में खुले पेज पर रहेगा। यदि आप वास्तव में फ़ाइल डाउनलोड के बाद पृष्ठ को बदलने का इरादा रखते हैं, तो आपको लक्ष्य पृष्ठ के फ़ाइल डाउनलोड लॉजिक को पेज लोड करने की आवश्यकता है।


फिर भी एक और संभावित कारण यह है कि forward(), sendRedirect()या sendError()विधियों को पुराने जमाने के तरीके के रूप में एक जेएसपी फ़ाइल में एम्बेडेड जावा कोड के माध्यम से लागू किया जाता है <% scriptlets %>, एक अभ्यास जिसे आधिकारिक तौर पर 2001 के बाद से हतोत्साहित किया गया था । उदाहरण के लिए:

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

        <% sendRedirect(); %>
        
        ...
    </body>
</html>

यहां समस्या यह है कि जेएसपी आंतरिक रूप से तुरंत टेम्प्लेट टेक्स्ट (यानी एचटीएमएल कोड) लिखता है out.write("<!DOCTYPE html> ... etc ...")जैसे ही उसका सामना होता है। यह इस प्रकार अनिवार्य रूप से पिछली अनुभाग में बताई गई समस्या है।

समाधान स्पष्ट है, बस एक JSP फ़ाइल में जावा कोड न लिखें। यह सर्वलेट या फ़िल्टर जैसे सामान्य जावा वर्ग की ज़िम्मेदारी है। सर्वलेट्स का सही तरीके से उपयोग करने का तरीका जानने के लिए हमारे सर्वलेट्स विकी पेज भी देखें ।


यह सभी देखें:


असंबंधित अपने ठोस समस्या के लिए, अपने JDBC- कोड संसाधन लीक कर रहा है। उसे भी ठीक कर लें। संकेत के लिए, यह भी देखें कि JDBC में कितनी बार कनेक्शन, स्टेटमेंट और रिजल्ट बंद होना चाहिए?


2
ब्रेक के साथ आपका मतलब है break;? इसका मतलब यह होगा कि कोड कुछ forया whileलूप के अंदर था जिसमें लूप के forward()दौरान बार-बार कॉल किया गया था (जो इस प्रकार गलत है, आपको लूप से छुटकारा पाने के लिए केवल एक बार आगे कॉल करना चाहिए - क्योंकि लूप से छुटकारा पाने के लिए यह स्पष्ट रूप से आवश्यक नहीं है) ।
बालुसक

@BalusC क्या आपको इस संबंधित समस्या पर एक विचार है? stackoverflow.com/questions/18658021/…
21

@confile: मैं ग्रेल्स नहीं करता, लेकिन कॉल स्टैक के आधार पर, यह अभी भी एक forward()कॉल कर रहा है जबकि इसे ऐसा नहीं करना चाहिए। JSF, जो मैं परिचित हूं, वह भी तब तक करता है जब तक कि आप स्पष्ट रूप से कॉल नहीं करते हैं FacesContext#responseComplete()। यह संबंधित प्रश्न (जो मैंने "ग्रेस रोकने की प्रतिक्रिया" का उपयोग करते हुए कीवर्ड पाया) सहायक हो सकता है: stackoverflow.com/questions/5708654/…
BalusC

@BalusC Grails मूल रूप से Java है, लेकिन समस्या Servlets से संबंधित है। क्या आपके पास कोई अन्य विचार है जो मैं कर सकता हूं जैसा कि आपने सुझाव दिया, मैं प्रत्येक रेंडर, पुनर्निर्देशित और अग्रेषित करने के बाद वापसी करता हूं।
ज़ब्त

@confile: मुझे पता है। मैंने पहले ही कारण का जवाब दे दिया है: ग्रेल्स अभी भी एक forward()कॉल कर रहा है जबकि उसे ऐसा नहीं करना चाहिए। समाधान कार्यात्मक रूप से स्पष्ट है: इसे ऐसा न करने के लिए कहें। इसका कोई मतलब नहीं था कि आपने प्रोग्राम को काम पर ले लिया है। तकनीकी तौर पर, मुझे नहीं पता कि ग्रेल्स को कैसे बताया जाए। लेकिन मुझे पता है कि बहुत से अन्य एमवीसी फ्रेमवर्क इसका समर्थन करते हैं (जेएसएफ, स्प्रिंग एमवीसी, विकेट इत्यादि जैसे प्रतिक्रिया को खुद से प्रतिक्रिया नहीं करने के लिए निर्देश दिया जा रहा है), मुझे आश्चर्य होगा कि यदि यह ग्रिल्स में असंभव है।
बालुस

19

यहां तक ​​कि रिटर्न स्टेटमेंट जोड़ने से यह अपवाद सामने आता है, जिसके लिए केवल समाधान ही यह कोड है:

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

6

आमतौर पर आप यह त्रुटि तब देखते हैं जब आप पहले ही पुनर्निर्देशित कर चुके होते हैं और फिर आउटपुट स्ट्रीम में कुछ और डेटा आउटपुट करने का प्रयास करते हैं। उन मामलों में जहां मैंने इसे अतीत में देखा है, यह अक्सर उन फ़िल्टर में से एक है जो पृष्ठ को पुनर्निर्देशित करने की कोशिश कर रहा है, और फिर अभी भी सर्वलेट के माध्यम से आगे की ओर। मैं सर्वलेट के साथ तुरंत कुछ भी गलत नहीं देख सकता, इसलिए आप किसी भी फिल्टर पर एक नज़र रखने की कोशिश कर सकते हैं जो आपके पास भी है।

संपादित करें : समस्या के निदान में कुछ और मदद ...

इस समस्या का निदान करने के लिए पहला कदम यह पता लगाना है कि अपवाद कहां फेंका जा रहा है। हम यह मान रहे हैं कि इसे लाइन द्वारा फेंका जा रहा है

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

लेकिन आप पा सकते हैं कि इसे बाद में कोड में फेंक दिया जा रहा है, जहाँ आप आगे की कोशिश करने के बाद आउटपुट स्ट्रीम में आउटपुट करने की कोशिश कर रहे हैं। यदि यह उपरोक्त रेखा से आ रहा है, तो इसका मतलब है कि इस रेखा से पहले कहीं आपके पास:

  1. आउटपुट स्ट्रीम में आउटपुट डेटा, या
  2. पहले से एक और पुनर्निर्देशित किया।

सौभाग्य!


2

ऐसा इसलिए है क्योंकि आपका सर्वलेट अनुरोध ऑब्जेक्ट तक पहुंचने का प्रयास कर रहा है, जो अब मौजूद नहीं है .. एक सर्वलेट के फॉरवर्ड या स्टेटमेंट में विधि ब्लॉक का निष्पादन बंद नहीं होता है। यह किसी अन्य जावा विधि की तरह विधि खंड या पहले वापसी विवरण के अंत तक जारी रहता है।

इस समस्या को हल करने का सबसे अच्छा तरीका सिर्फ पृष्ठ (जहां आप अनुरोध को आगे बढ़ाने के लिए मानते हैं) को अपने तर्क के अनुसार गतिशील रूप से सेट करें। अर्थात्:

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
}

और अंतिम पंक्ति में केवल एक बार फॉरवर्ड करें ...

आप प्रत्येक आगे () के बाद रिटर्न स्टेटमेंट का उपयोग करके भी इस समस्या को ठीक कर सकते हैं या प्रत्येक को आगे () में डाल सकते हैं ... और ब्लॉक करें


2

मैने हटा दिया

        super.service(req, res);

तब इसने मेरे लिए ठीक काम किया


2

टक्कर ...

मेरी बस वही त्रुटि थी। मैंने देखा कि super.doPost(request, response);जब मैं इस doPost()पद्धति को ओवरराइड कर रहा था और साथ ही साथ सुपरक्लास कंस्ट्रक्टर को स्पष्ट रूप से आह्वान कर रहा था, तो मैं देख रहा था

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

जैसे ही मैंने टिप्पणी के super.doPost(request, response);भीतर से doPost()यह पूरी तरह से काम किया टिप्पणी ...

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

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

}

कहने की जरूरत नहीं है, मुझे super()सर्वोत्तम प्रथाओं पर फिर से पढ़ने की जरूरत है : पी


1

जब आप अग्रेषित कर रहे हों या प्रवाह को पुनर्निर्देशित कर रहे हों तो आपको रिटर्न स्टेटमेंट जोड़ना चाहिए ।

उदाहरण:

अगर फारवर्ड,

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

यदि पुनर्निर्देशन,

    response.sendRedirect(roundTripURI);
    return;

0

आगे की विधि वापस करने के बाद आप बस यह कर सकते हैं:

return null;

यह मौजूदा दायरे को तोड़ देगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.