2011-07-30 20 views
9

मैं निम्न समस्या का सामना करना पड़ रहा हूँ के बाद खो: एक पृष्ठ में, मैं अपने आवेदन के सभी उपयोगकर्ताओं की सूची और प्रत्येक के लिए एक "संपादित करें" बटन है, जो एक ?id=<userid> साथ "GET" लिंक है।
JSF viewparam सत्यापन त्रुटि

संपादन पृष्ठ में मेटाडेटा में <f:viewParam name="id" value="#{editUserBean.id}"/> है।
यदि मैंने कुछ इनपुट गलतियां की हैं और सबमिट करते हैं (मैं सीडीआई वेल्ड बीन सत्यापन का उपयोग करता हूं), पृष्ठ फिर से प्रदर्शित होता है, लेकिन मैंने URL में ?id=... खो दिया है और इसलिए मैं जिस उपयोगकर्ता को संपादित कर रहा हूं उसका उपयोगकर्ता आईडी खो देता हूं।

मैंने JSF validation error, lost value में वर्णित एक समान समस्या को देखा है, लेकिन सशक्त (या बदतर, टॉमहॉक के साथ, जो ओवरकिल दिखता है) के साथ समाधान बहुत गड़बड़ कोड की आवश्यकता है।

मैंने सीडीआई के साथ "वार्तालाप" जोड़ने का प्रयास किया है, और यह काम कर रहा है, लेकिन ऐसा लगता है कि यह मेरे लिए बहुत अधिक है।

क्या सत्यापन त्रुटियों के मामले में दृश्य पैरामीटर को संरक्षित करने के लिए जेएसएफ में एक सरल समाधान मौजूद है?

[मेरे पर्यावरण: Tomcat7 + MyFaces 2.1.0 + हाइबरनेट सत्यापनकर्ता 4.2.0 + CDI (वेल्ड) 1.1.2]

+3

आप अपने प्रस्तुत कार्रवाई में उपयोग कर रहे हैं 'includeViewParams = TRUE'? – bluefoot

+0

नहीं, लेकिन मेरे एक्शन हैंडलर को नहीं कहा जाता है: सबमिट सत्यापन चरण में पहले विफल रहता है। – DenisGL

उत्तर

7

दिलचस्प मामले (यदि आप viewParam राज्यविहीन स्टेटफुल पर गूगल आप कुछ और अधिक जानकारी मिल जाएगा)। हर किसी के लिए, निम्न न्यूनतम कोड reproduces इस:

Facelet:

<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:f="http://java.sun.com/jsf/core" 
> 

    <f:metadata> 
     <f:viewParam id="id" name="id" value="#{viewParamBean.id}"/> 
    </f:metadata> 

    <h:body> 

     <h:messages /> 

     #{viewParamBean.id} <br/> 

     <h:form> 
      <h:inputText value="#{viewParamBean.text}" > 
       <f:validateLength minimum="2"/> 
      </h:inputText> 

      <h:commandButton value="test" action="#{viewParamBean.actionMethod}"/> 
     </h:form> 

    </h:body> 
</html> 

बीन:

@ManagedBean 
@RequestScoped 
public class ViewParamBean { 

    private long id;  
    private String text; 

    public void actionMethod() { 

    } 

    public long getId() { 
     return id; 
    } 

    public void setId(long id) { 
     this.id = id; 
    } 

    public String getText() { 
     return text; 
    } 

    public void setText(String text) { 
     this.text = text; 
    }  
} 

यदि आप viewparam.xhtml?id=12 साथ Facelet फोन यह 12 परदे पर प्रदर्शित करेगा। यदि आप फिर कुछ मान्य इनपुट करते हैं, उदा। aaaaa, आईडी यूआरएल से गायब हो जाएगी, लेकिन स्क्रीन पर प्रदर्शित होती रहती है (यूई घटकों की राज्य की प्रकृति के स्वामित्व में)।

हालांकि ... जैसा कि ओपी ने बताया है, जैसे ही कोई वैधकर्ता त्रुटि होती है (जैसे a दर्ज करना), आईडी स्थायी रूप से खो जाएगी। बाद में वैध इनपुट दर्ज करना इसे वापस नहीं लाएगा। यह लगभग एक बग की तरह लगता है, लेकिन मैंने दोनों Mojarra 2.1 और Myfaces 2.1 की कोशिश की और दोनों का एक ही व्यवहार है।

अद्यतन:

public void encodeAll(FacesContext context) throws IOException { 
    if (context == null) { 
     throw new NullPointerException(); 
    } 

    // if there is a value expression, update view parameter w/ latest value after render 
    // QUESTION is it okay that a null string value may be suppressing the view parameter value? 
    // ANSWER: I'm not sure. 
    setSubmittedValue(getStringValue(context)); 
} 

और फिर अधिक विशेष रूप से इस विधि:

public String getStringValue(FacesContext context) { 
    String result = null; 
    if (hasValueExpression()) { 
     result = getStringValueFromModel(context); 
    } else { 
     result = (null != rawValue) ? rawValue : (String) getValue(); 
    } 
    return result; 
} 

कुछ निरीक्षण के बाद, समस्या लगती है `UIViewParameter '(Mojarra) की इस पद्धति में होने की

क्योंकि hasValueExpression() सत्य है, यह मॉडल (बैकिंग बीन) से मूल्य प्राप्त करने का प्रयास करेगा। लेकिन चूंकि इस बीन को अनुरोध किया गया था कि इस अनुरोध के लिए इसका कोई मूल्य नहीं होगा, क्योंकि सत्यापन अभी विफल रहा है और इस प्रकार कोई मूल्य निर्धारित नहीं किया गया है।असल में, UIViewParameter का राज्य मूल्य जो भी बैकिंग बीन डिफ़ॉल्ट रूप से लौटाता है (आमतौर पर शून्य, लेकिन यह निश्चित रूप से आपके बीन पर निर्भर करता है) द्वारा अधिलेखित किया जाता है।

एक वर्कअराउंड अपने बीन @ViewScoped बनाने के लिए है, जो अक्सर एक बेहतर दायरा है (मुझे लगता है कि आप किसी सेवा से उपयोगकर्ता को प्राप्त करने के लिए पैरामीटर का उपयोग करते हैं, और शायद यह हर पोस्टबैक में बार-बार ऐसा करने के लिए अनावश्यक है) ।

एक और विकल्प UIViewParameter का अपना संस्करण बनाना है जो वैधता विफल होने पर मॉडल से मूल्य प्राप्त करने का प्रयास नहीं करता है (मूल रूप से अन्य सभी UIInput घटक करते हैं)।

+1

रुचि रखने वालों के लिए; मैं इसके लिए एक मुद्दा बना रहा हूं: http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1029 अगर आप इसे ठीक करना चाहते हैं तो कृपया इसके लिए वोट दें। –

+0

मैंने इस मुद्दे के परिणामस्वरूप एक और अजीब व्यवहार देखा है (Mojarra (2.1.2) के साथ, लेकिन MyFaces (2.1.0) के साथ नहीं): यदि दृश्य पैरामीटर 'आवश्यक =' सत्य '' के रूप में सेट किया गया है, तो एक अजाक्स अनुरोध सत्यापन चरण में विफल हो जाएगा। – DenisGL

+3

एफवाईआई: पैच किए गए 'UIViewParameter' OmniFaces के' 'के रूप में उपलब्ध है। यह भी देखें http://showcase.omnifaces.org/components/viewParam – BalusC

1

आप वास्तव में ढीला नहीं है दृश्य पैरामीटर। f: viewParam राज्यपूर्ण है, भले ही यह यूआरएल में न हो, फिर भी यह वहां है। बसम को देखने के लिए बाएं सेटर में ब्रेक पॉइंट या system.out डालें।

+0

बहुत बहुत धन्यवाद, मुझे यहां एक दिलचस्प लेख मिला [लिंक] (http://jdevelopment.nl/stateless-stateful-jsf-view-parameters/)। हालांकि, मुझे अभी भी समस्या है: यदि कोई त्रुटि के बिना मेरा फॉर्म सबमिट करता है, तो दृश्य परम से जुड़ा सेटटर कहा जाता है, लेकिन अगर मैं अपने इनपुट में गलती करता हूं और फिर सबमिट करता हूं तो मान खो जाता है। – DenisGL

+1

UIViewParameter वास्तव में राज्य जैसा है जैसा कि मैंने उस आलेख में वर्णन किया है, लेकिन उस घटक के 'एन्कोड' विधि में समस्याग्रस्त कोड के कारण, यह बैकिंग बीन में मौजूद डिफ़ॉल्ट मान के साथ इसे ओवरराइट करता है। मेरा अद्यतन उत्तर देखें। –

+0

ठीक है, यह सामान्य रूप से अव्यवस्थित है लेकिन कुछ डिज़ाइन निरीक्षण के कारण सत्यापन त्रुटियों के दौरान मूल्य वास्तव में खो जाता है। मान लीजिए मैंने कुछ नया सीखा! –

0

मेरे पास मेरे आवेदन में समान है। मैंने @ViewAccessScoped पर स्विच किया जो कि अधिक सुरुचिपूर्ण कार्यान्वयन की अनुमति देता है।

0
<f:metadata> 
     <f:viewParam id="id" name="id" value="#{baen.id}"/> 
    </f:metadata> 

या जब आप पहली बार, यूआरएल से पैरामीटर प्राप्त सत्र नक्शे में यह बचाने के लिए और है कि नक्शे से उपयोग जारी है, और बचाने के लिए/या प्रपत्र स्वच्छ नक्शा अद्यतन करने के बाद।

0

यह मुश्किल है, लेकिन आप इतिहास एपीआई के साथ दृश्य पैरामीटर बहाल करने की कोशिश कर सकते हैं:

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" 
     xmlns:h="http://xmlns.jcp.org/jsf/html" 
     xmlns:f="http://xmlns.jcp.org/jsf/core" 
     xmlns:ui="http://xmlns.jcp.org/jsf/facelets"> 
    <f:metadata > 
     <f:viewParam name="param1" value="#{backingBean.viewParam1}" /> 
     <f:viewParam name="param2" value="#{backingBean.viewParam2}" /> 
     <f:viewAction action="#{view.viewMap.put('queryString', request.queryString)}" /> 
    </f:metadata> 
    <h:head> 
     <title>Facelet Title</title> 
    </h:head> 
    <h:body> 
     <ui:fragment rendered="#{facesContext.postback}" > 
      <script type="text/javascript"> 
       var url = '?#{view.viewMap.get('queryString')}'; 
       history.replaceState({}, document.title, url); 
      </script> 
     </ui:fragment> 
     <h:form> 
      <h:inputText id="name" value="#{backingBean.name}" /> 
      <h:message for="name" style="color: red" /> 
      <br /> 
      <h:commandButton value="go" action="#{backingBean.go}" /> 
     </h:form> 
     <h:messages globalOnly="true" /> 
    </h:body> 
</html> 
संबंधित मुद्दे