2010-09-23 14 views
8

पर फिर से इंजेक्शन मैं अगर मैं सिर्फ एक एनोटेशन या विन्यास आइटम याद कहीं अगर मैं क्या कर रहा हूँ गलत है यकीन नहीं है, या नहीं है।JSF - सत्र-दायरे में कामयाब सेम निर्भरता सत्र अक्रमांकन

मैं SessionData नाम के एक सत्र-दायरे सेम के साथ एक JSF आवेदन है: यहाँ की स्थिति है। इस बीन में एक अनुप्रयोग-स्कोप्ड बीन संदर्भ (प्रकार ApplicationData) का निर्माण समय पर इंजेक्शन किया गया है। जब सत्र पहली बार बनाया जाता है तो यह ठीक काम करता है। जैसा कि यहाँ दिखाया निर्भरता इंजेक्शन faces-config.xml फ़ाइल में <managed-bean> तत्वों के साथ किया जाता है:

<managed-bean> 
    <managed-bean-name>sessionData</managed-bean-name> 
    <managed-bean-class>my.package.SessionData</managed-bean-class> 
    <managed-bean-scope>session</managed-bean-scope> 
    <managed-property> 
     <property-name>applicationData</property-name> 
     <property-class>my.package.ApplicationData</property-class> 
     <value>#{applicationData}</value> 
    </managed-property> 
</managed-bean> 
<managed-bean> 
    <managed-bean-name>applicationData</managed-bean-name> 
    <managed-bean-class>my.package.ApplicationData</managed-bean-class> 
    <managed-bean-scope>application</managed-bean-scope> 
</managed-bean> 

क्योंकि यह मतलब नहीं है मेरी SessionData वस्तु के लिए ApplicationData वस्तु शामिल जब यह धारावाहिक है, मैं ApplicationData संदर्भ में चिह्नित किया है मेरी SessionData वस्तु में क्षणिक रूप में:

transient private ApplicationData applicationData; 

सभी अच्छे जब तक वेब अनुप्रयोग बंद कर दिया है (मेरे बिलाव 6.x कंटेनर में) और सत्र धारावाहिक हो रहा है। जब मैं एप्लिकेशन को पुनरारंभ करता हूं और सत्र deserialized हैं, ApplicationData के लिए मेरा संदर्भ जेएसएफ द्वारा फिर से इंजेक्शन नहीं है। मुझे पता है कि deserialization एक मूल्य के बिना क्षणिक क्षेत्रों छोड़ने के लिए माना जाता है। क्या जेएसएफ को सिग्नल करने का कोई तरीका है कि इस सत्र-स्कोप्ड ऑब्जेक्ट को इसकी निर्भरताओं को deserialization के बाद फिर से सेट करने की आवश्यकता है?

मैं अपने वेब आवेदन कंटेनर के रूप में MyFaces JSF 1.2 और बिलाव 6.0.26 उपयोग कर रहा हूँ।

+1

यह सुझाव दिया गया था कि मैं एक readObject() विधि प्रदान करता हूं और FacesContext का उपयोग कर deserialization के दौरान मैन्युअल रूप से ApplicationData ऑब्जेक्ट सेट करता हूं। मुझे नहीं लगता कि यह काम करेगा क्योंकि FacesContext केवल अनुरोध के जीवनकाल के दौरान उपलब्ध है। आवेदन स्टार्टअप पर deserialization हो रहा है। –

+2

सही, इसलिए मैंने अपना जवाब हटा दिया। यह अधिक जटिल प्रतीत होता है (इसलिए प्रश्न के लिए +1) – Bozho

उत्तर

5

हालांकि समाधान Bozho द्वारा की पेशकश की काम कर सकता था, मैं एक आवेदन है कि वर्तमान में उनका उपयोग न में प्रॉक्सी वस्तुओं को पेश करने नहीं करना चाहती। मेरा समाधान आदर्श से कम है, लेकिन यह काम पूरा हो जाता है।

मैं जगह में क्षणिक क्षेत्र छोड़ दिया:

transient private ApplicationData _applicationData; 

मैं भी जगह में सेटर छोड़ दिया तो JSF शुरू में संदर्भ सेट कर सकते हैं जब SessionData वस्तु पहली बार बनाई गई है:

public void setApplicationData(ApplicationData applicationData) { 
    _applicationData = applicationData; 
} 

मेरे द्वारा किए गए परिवर्तन गेटटर विधि में थे। SessionData ऑब्जेक्ट में विधियों को अब _applicationData फ़ील्ड तक सीधे पहुंचने की आवश्यकता है और इसके बजाय गेटर के माध्यम से संदर्भ प्राप्त करें। गेटर पहले एक शून्य संदर्भ की जांच करेगा। यदि यह शून्य है, तो प्रबंधित बीन FacesContext के माध्यम से प्राप्त किया जाता है। यहां बाधा यह है कि FacesContext केवल अनुरोध के जीवनकाल के दौरान उपलब्ध है।

/** 
* Get a reference to the ApplicationData object 
* @return ApplicationData 
* @throws IllegalStateException May be thrown if this method is called 
* outside of a request and the ApplicationData object needs to be 
* obtained via the FacesContext 
*/ 
private ApplicationData getApplicationData() { 
    if (_applicationData == null) { 
     _applicationData = JSFUtilities.getManagedBean(
      "applicationData", // name of managed bean 
      ApplicationData.class); 
     if (_applicationData == null) { 
      throw new IllegalStateException(
       "Cannot get reference to ApplicationData object"); 
     } 
    } 
    return _applicationData; 
} 

किसी को भी परवाह नहीं करते हैं, तो यहाँ मेरी getManagedBean() विधि के लिए कोड है:

/** 
* <p>Retrieve a JSF managed bean instance by name. If the bean has 
* never been accessed before then it will likely be instantiated by 
* the JSF framework during the execution of this method.</p> 
* 
* @param managedBeanKey String containing the name of the managed bean 
* @param clazz Class object that corresponds to the managed bean type 
* @return T 
* @throws IllegalArgumentException Thrown when the supplied key does 
* not resolve to any managed bean or when a managed bean is found but 
* the object is not of type T 
*/ 
public static <T> T getManagedBean(String managedBeanKey, Class<T> clazz) 
     throws IllegalArgumentException { 
    Validate.notNull(managedBeanKey); 
    Validate.isTrue(!managedBeanKey.isEmpty()); 
    Validate.notNull(clazz); 
    FacesContext facesContext = FacesContext.getCurrentInstance(); 
    if (facesContext == null) { 
     return null; 
    } 
    Validate.notNull(facesContext.getApplication()); 
    ELResolver resolver = facesContext.getApplication().getELResolver(); 
    Validate.notNull(resolver); 
    ELContext elContext = facesContext.getELContext(); 
    Validate.notNull(elContext); 
    Object managedBean = resolver.getValue(
     elContext, null, managedBeanKey); 
    if (!elContext.isPropertyResolved()) { 
     throw new IllegalArgumentException(
      "No managed bean found for key: " + managedBeanKey); 
    } 
    if (managedBean == null) { 
     return null; 
    } else { 
     if (clazz.isInstance(managedBean)) { 
      return clazz.cast(managedBean); 
     } else { 
      throw new IllegalArgumentException(
       "Managed bean is not of type [" + clazz.getName() + 
       "] | Actual type is: [" + managedBean.getClass().getName()+ 
       "]"); 
     } 
    } 
} 

और मेरी मान्य पर कॉल न चुनें। विकास के साथ किए जाने के बाद मैं उन्हें निकाल दूंगा! :)

+4

['आवेदन # मूल्यांकन ExpressionGet() '] में एक शॉर्टकट है (http://download.oracle.com/javaee/6/api/javax/faces/application/ Application.html # evaluateExpressionGet% 28javax.faces.context.FacesContext,% 20java.lang.String,% 20java.lang.Class% 29)। यह भी देखें [यह उत्तर] (http://stackoverflow.com/questions/2633112/jsf-get-managed-bean-by-name/2633733#2633733)। – BalusC

1

आप एक विधि जोड़ सकते हैं:

private void readObject(java.io.ObjectInputStream in) 
throws IOException, ClassNotFoundException { 
    in.defaultReadObject(); 
    applicationData = initializeApplicationData(); 
} 

और initializeApplicationData में आप एक गतिशील प्रॉक्सी ऑब्जेक्ट का उपयोग कर सकते हैं। CGLIB या javassist का उपयोग करना प्रॉक्सी बनाता है कि, प्रत्येक विधि आमंत्रण से पहले एक आंतरिक फ़ील्ड सेट करता है - असली ApplicationData। यदि यह null है, तो मिल वर्तमान FacesContext (जो उस बिंदु पर पहुँचा जा सकेगा) और द्वारा वहां से प्रबंधित सेम मिलती है:

FacesContext facesContext = FacesContext.getCurrentInstance(); 
originalApplicationData = (ApplicationData)facesContext.getApplication() 
    .createValueBinding("#{applicationData}").getValue(facesContext); 

और उसके तरीकों के प्रतिनिधि।

यह एक बदसूरत कामकाज है, लेकिन मुझे लगता है कि यह काम करेगा।

+0

यह जावसिस्ट का उपयोग करने वाला मेरा पहला समय होगा, इसलिए मुझे आपके समाधान के उस हिस्से को पचाने के लिए कुछ समय की आवश्यकता होगी। धन्यवाद। –

+0

यह काफी आसान है। बस ट्यूटोरियल का पालन करें - आपका प्रॉक्सी केस सबसे आसान है :) – Bozho

संबंधित मुद्दे