परिचय
ViewExpiredException
जब भी फेंक दिया जाएगा javax.faces.STATE_SAVING_METHOD
करने के लिए सेट कर दिया जाता server
(डिफ़ॉल्ट) और enduser के माध्यम से एक दृश्य पर एक HTTP POST अनुरोध भेजता है <h:form>
के साथ <h:commandLink>
, <h:commandButton>
या <f:ajax>
, जबकि संबद्ध दृश्य राज्य अब सत्र में उपलब्ध नहीं है।
दृश्य स्थिति की पहचान एक छिपे हुए इनपुट फ़ील्ड javax.faces.ViewState
के मान के रूप में की जाती है <h:form>
। राज्य की बचत विधि के साथ server
, इसमें केवल दृश्य स्थिति ID होती है जो सत्र में क्रमबद्ध दृश्य स्थिति का संदर्भ देती है। इसलिए, जब सत्र किसी कारण से समाप्त हो जाता है (या तो सर्वर या क्लाइंट साइड में समय समाप्त हो जाता है, या सत्र कुकी ब्राउज़र में किसी कारण से, या HttpSession#invalidate()
सर्वर में कॉल करके , या सत्र कुकीज़ के साथ सर्वर विशिष्ट बग के कारण बनाए नहीं रखा जाता है) WildFly में जाना जाता है ), फिर क्रमबद्ध दृश्य स्थिति सत्र में अब उपलब्ध नहीं है और एंड्यूसर को यह अपवाद मिलेगा। सत्र के कामकाज को समझने के लिए, यह भी देखें कि सर्वलेट्स कैसे काम करते हैं? तात्कालिकता, सत्र, साझा चर और बहु-प्रसार ।
सत्र में जेएसएफ स्टोर करने वाले विचारों की मात्रा पर एक सीमा भी है। जब सीमा हिट होती है, तो हाल ही में उपयोग किए गए दृश्य समाप्त हो जाएंगे। Com.sun.faces.numberOfViewsInSession बनाम com.sun.faces.numberOfLogicalViews भी देखें ।
राज्य बचत विधि के साथ सेट करने के लिए client
, javax.faces.ViewState
छिपे हुए इनपुट फ़ील्ड में पूरे क्रमबद्ध दृश्य स्थिति के बजाय समाहित है, इसलिए ViewExpiredException
सत्र समाप्त होने पर एंड्यूसर नहीं मिलेगा । यह अभी भी एक क्लस्टर वातावरण पर हो सकता है ("ERROR: MAC ने सत्यापित नहीं किया है" रोगसूचक है) और / या जब क्लाइंट साइड स्टेट कॉन्फ़िगर किया गया है और / या जब सर्वर पुनः आरंभ के दौरान एईएस को फिर से जेनरेट करता है तो कार्यान्वयन-विशिष्ट टाइमआउट होता है। , यह भी देखें कि क्लस्टरिंग वातावरण में ViewExpiredException हो रही है , जबकि राज्य की बचत विधि क्लाइंट पर सेट है और उपयोगकर्ता सत्र इसे हल करने के लिए मान्य है।
समाधान के बावजूद, सुनिश्चित करें कि आप उपयोग नहीं करते हैं enableRestoreView11Compatibility
। यह मूल दृश्य स्थिति को पुनर्स्थापित नहीं करता है। यह मूल रूप से दृश्य को पुनः बनाता है और सभी संबद्ध दृश्य खरोंच से सेम को काटता है और इस प्रकार मूल डेटा (राज्य) के सभी खो देता है। जैसा कि एप्लिकेशन एक भ्रमित तरीके से व्यवहार करेगा ("अरे, मेरे इनपुट मान कहां हैं .. ??"), यह उपयोगकर्ता अनुभव के लिए बहुत बुरा है। बेहतर स्टेटलेस व्यूज़ का उपयोग करें या <o:enableRestorableView>
इसके बजाय आप इसे केवल सभी व्यूज़ के बजाय किसी विशिष्ट दृश्य पर प्रबंधित कर सकते हैं।
के रूप में क्यों JSF इस जवाब को देखने राज्य, सिर को बचाने के लिए की जरूरत है: क्यों JSF सर्वर पर यूआई घटकों के राज्य की बचत होती है?
पृष्ठ नेविगेशन पर ViewExpiredException से बचना
बचने के लिए ViewExpiredException
जब राज्य की बचत के लिए लॉगआउट के बाद वापस नेविगेट करते समय उदाहरण के लिए server
, केवल लॉगआउट पर्याप्त नहीं होने के बाद POST अनुरोध को पुनर्निर्देशित करना। आपको गतिशील जेएसएफ पृष्ठों को कैश न करने के लिए ब्राउज़र को भी निर्देश देने की आवश्यकता है , अन्यथा जब आप उस पर जीईटी अनुरोध भेजते हैं (जैसे बैक बटन द्वारा) तो सर्वर से एक ताजा अनुरोध करने के बजाय ब्राउज़र उन्हें कैश से दिखा सकता है।
javax.faces.ViewState
संचित पृष्ठ का छिपा क्षेत्र एक दृश्य के राज्य ID मान जो मौजूदा सत्र में अब मान्य नहीं है हो सकता है। यदि आप पृष्ठ-टू-पेज नेविगेशन के लिए GET (नियमित लिंक / बटन) के बजाय POST (कमांड लिंक / बटन) का उपयोग कर रहे हैं, और कैश्ड पेज पर ऐसे कमांड लिंक / बटन पर क्लिक करते हैं, तो यह बदले में होगा एक के साथ विफल ViewExpiredException
।
JSF 2.0 में लॉगआउट के बाद एक रीडायरेक्ट आग करने के लिए, या तो जोड़ने <redirect />
के लिए <navigation-case>
(यदि हो तो) प्रश्न में, या जोड़ने ?faces-redirect=true
के लिए outcome
मूल्य।
<h:commandButton value="Logout" action="logout?faces-redirect=true" />
या
public String logout() {
// ...
return "index?faces-redirect=true";
}
गतिशील जेएसएफ पृष्ठों को कैश न करने के लिए ब्राउज़र को निर्देश देने के लिए, Filter
जो सर्वलेट नाम पर मैप किया गया है FacesServlet
और ब्राउज़र कैश को अक्षम करने के लिए आवश्यक प्रतिक्रिया हेडर जोड़ता है। उदाहरण के लिए
@WebFilter(servletNames={"Faces Servlet"}) // Must match <servlet-name> of your FacesServlet.
public class NoCacheFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
res.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response);
}
// ...
}
पृष्ठ ताज़ा करने पर ViewExpiredException से बचना
ViewExpiredException
वर्तमान बचत को ताज़ा करने से बचने के लिए जब राज्य की बचत निर्धारित की जाती है server
, तो आपको न केवल यह सुनिश्चित करने की ज़रूरत होती है कि आप विशेष रूप से GET (नियमित लिंक / बटन) द्वारा पेज-टू-पेज नेविगेशन कर रहे हैं, बल्कि आपको यह सुनिश्चित करने की भी आवश्यकता है रूपों को जमा करने के लिए आप विशेष रूप से अजाक्स का उपयोग कर रहे हैं। यदि आप किसी भी रूप में (गैर-अजाक्स) रूप में फॉर्म जमा कर रहे हैं, तो आप या तो व्यू को स्टेटलेस (बाद में सेक्शन देखें), या POST के बाद रीडायरेक्ट भेजेंगे (पिछले सेक्शन को देखें)।
ViewExpiredException
ऑन पेज रिफ्रेश होने पर डिफॉल्ट कॉन्फ़िगरेशन बहुत दुर्लभ स्थिति में होता है। यह केवल तब हो सकता है जब सत्र में जेएसएफ स्टोर करने वाले विचारों की सीमा पर हिट हो। इसलिए, यह केवल तब होगा जब आपने मैन्युअल रूप से उस सीमा को बहुत कम कर दिया हो, या आप "पृष्ठभूमि" में लगातार नए विचार बना रहे हों (जैसे कि एक ही पेज में बुरी तरह से लागू किए गए ajax पोल या बुरी तरह से लागू किए गए 404 द्वारा एक ही पृष्ठ की टूटी हुई छवियों पर त्रुटि पृष्ठ)। उस सीमा पर विस्तार के लिए com.sun.faces.numberOfViewsInSession बनाम com.sun.faces.numberOfLogicalViews भी देखें । एक अन्य कारण एक दूसरे के विरोधाभासी वर्ग संघर्ष में जेएसएफ पुस्तकालयों की नकल करना है। JSF को स्थापित करने की सही प्रक्रिया हमारे JSF विकी पेज में उल्लिखित है ।
हैंडलिंग ViewExpiredException
आप एक अपरिहार्य हैंडल करना चाहते हैं जब ViewExpiredException
एक मनमाना पेज जो पहले से ही कुछ ब्राउज़र टैब / विंडो में खोला गया था जब आप किसी अन्य टैब / विंडो में लॉग आउट कर रहे हैं पर एक पोस्ट कार्रवाई के बाद, तो आप एक निर्दिष्ट करना चाहते हैं error-page
के लिए में है कि web.xml
जो चला जाता है "आपका सत्र समाप्त हो गया है" पृष्ठ पर। उदाहरण के लिए
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/WEB-INF/errorpages/expired.xhtml</location>
</error-page>
यदि आप वास्तव में घर या लॉगिन पृष्ठ पर आगे रीडायरेक्ट करना चाहते हैं, तो त्रुटि पृष्ठ में एक मेटा रीफ़्रेश हेडर आवश्यक होने पर उपयोग करें ।
<!DOCTYPE html>
<html lang="en">
<head>
<title>Session expired</title>
<meta http-equiv="refresh" content="0;url=#{request.contextPath}/login.xhtml" />
</head>
<body>
<h1>Session expired</h1>
<h3>You will be redirected to login page</h3>
<p><a href="#{request.contextPath}/login.xhtml">Click here if redirect didn't work or when you're impatient</a>.</p>
</body>
</html>
( 0
में content
, रीडायरेक्ट से पहले सेकंड की राशि का प्रतिनिधित्व करता है 0
इस प्रकार का अर्थ है "तुरंत redirect", तो आप उपयोग कर सकते हैं जैसे 3
रीडायरेक्ट के साथ 3 सेकंड देने के लिए ब्राउज़र प्रतीक्षा करें)
ध्यान दें कि अजाक्स अनुरोधों के दौरान अपवादों को संभालने के लिए एक विशेष की आवश्यकता होती है ExceptionHandler
। JSF / PrimeFaces ajax अनुरोध पर सत्र टाइमआउट और ViewExpiredException हैंडलिंग भी देखें । आप ओमनीफेस FullAjaxExceptionHandler
शोकेस पेज पर एक लाइव उदाहरण पा सकते हैं (यह गैर-अजाक्स अनुरोधों को भी शामिल करता है)।
यह भी ध्यान दें कि आपके "सामान्य" त्रुटि पृष्ठ को उदाहरण <error-code>
के 500
बजाय या पर मैप किया जाना चाहिए , अन्यथा ऐसे सभी अपवाद जो अभी भी सामान्य त्रुटि पृष्ठ में समाप्त हो जाएंगे। Java.lang में दिखाया गया ViewExpiredException भी देखें। वेब में त्रुटि-पृष्ठ । xml ।<exception-type>
java.lang.Exception
java.lang.Throwable
ServletException
ViewExpiredException
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/errorpages/general.xhtml</location>
</error-page>
स्टेटलेस विचार
जेएसएफ विचारों को स्टेटलेस मोड में चलाने के लिए एक पूरी तरह से अलग विकल्प है। इस तरह से जेएसएफ राज्य में से कुछ भी नहीं बचाया जाएगा और विचार कभी भी समाप्त नहीं होंगे, लेकिन बस हर अनुरोध पर खरोंच से पुनर्निर्माण किया जाएगा। आप की स्थापना करके राज्यविहीन विचारों चालू कर सकते हैं transient
की विशेषता <f:view>
के लिए true
:
<f:view transient="true">
</f:view>
इस तरह javax.faces.ViewState
छिपे हुए क्षेत्र को "stateless"
मोअज़रा में एक निश्चित मूल्य मिलेगा (इस बिंदु पर MyFaces की जाँच नहीं की गई है)। ध्यान दें कि यह सुविधा Mojarra 2.1.19 और 2.2.0 में पेश की गई थी और पुराने संस्करणों में उपलब्ध नहीं है।
नतीजा यह है कि आप अब scoped सेम का उपयोग नहीं कर सकते। वे अब अनुरोधित स्कोप बीन्स की तरह व्यवहार करेंगे। नुकसान में से एक यह है कि आपको छिपे हुए इनपुट और / या ढीले अनुरोध मापदंडों के साथ फ़िडलिंग करके राज्य को ट्रैक करना होगा। मुख्य रूप से उन रूपों के साथ इनपुट फ़ील्ड के साथ rendered
, readonly
या disabled
एज़ैक्स घटनाओं द्वारा नियंत्रित होने वाली विशेषताएँ प्रभावित होंगी।
ध्यान दें कि <f:view>
जरूरी नहीं कि पूरे दृश्य में अद्वितीय हो और / या केवल मास्टर टेम्पलेट में निवास करें। यह टेम्प्लेट क्लाइंट में redeclare और नेस्ट करने के लिए भी पूरी तरह से वैध है। यह मूल रूप से माता <f:view>
- पिता को "विस्तारित" करता है । जैसे मास्टर टेम्पलेट:
<f:view contentType="text/html">
<ui:insert name="content" />
</f:view>
और टेम्पलेट क्लाइंट में:
<ui:define name="content">
<f:view transient="true">
<h:form>...</h:form>
</f:view>
</f:view>
आप इसे सशर्त बनाने के लिए <f:view>
एक में लपेट भी सकते <c:if>
हैं। ध्यान दें कि यह पूरे दृश्य पर लागू होगा , न केवल नेस्टेड सामग्री पर, जैसे <h:form>
ऊपर के उदाहरण में।
यह सभी देखें
असंबंधित ठोस समस्या, शुद्ध पेज-टू-पृष्ठ नेविगेशन के लिए HTTP POST का उपयोग कर के लिए बहुत उपयोगकर्ता / एसईओ अनुकूल नहीं है। JSF 2.0 में तुम सच में पसंद किए जाने वाले <h:link>
या <h:button>
अधिक <h:commandXxx>
सादे वेनिला पेज-टू-पृष्ठ नेविगेशन के लिए लोगों को।
इसलिए इसके बजाय उदा
<h:form id="menu">
<h:commandLink value="Foo" action="foo?faces-redirect=true" />
<h:commandLink value="Bar" action="bar?faces-redirect=true" />
<h:commandLink value="Baz" action="baz?faces-redirect=true" />
</h:form>
बेहतर है
<h:link value="Foo" outcome="foo" />
<h:link value="Bar" outcome="bar" />
<h:link value="Baz" outcome="baz" />
यह सभी देखें