2011-01-04 15 views
5

मुझे उसी सत्र के लिए सत्र स्कोप्ड सीडीआई बीन के दो उदाहरण मिल गए हैं। मैं इस धारणा के तहत था कि सीडीआई द्वारा मेरे लिए एक उदाहरण उत्पन्न होगा, लेकिन यह दो उत्पन्न हुआ। क्या मैं गलत समझ रहा हूं कि सीडीआई कैसे काम करता है, या मुझे एक बग मिला?सीडीआई सत्र स्कोप्ड बीन एक ही सत्र में दो उदाहरणों में परिणाम

<?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://java.sun.com/jsf/html" 
    xmlns:f="http://java.sun.com/jsf/core"> 
<f:view contentType="text/html" encoding="UTF-8"> 
    <h:head> 
     <title>Test</title> 
    </h:head> 
    <h:body> 
     <h:form id="form"> 
      <h:inputText value="#{myBean.myField}"/> 
      <h:commandButton value="Submit"/> 
     </h:form> 
    </h:body> 
</f:view> 
</html> 

यहाँ तैनाती से उत्पादन होता है और पृष्ठ पर जाकर:

INFO: Loading application org.mycompany_myproject_war_1.0-SNAPSHOT at /myproject 
INFO: org.mycompany_myproject_war_1.0-SNAPSHOT was successfully deployed in 8,237 milliseconds. 
INFO: MyBean constructor called 
INFO: Session ID: 175355b0e10fe1d0778238bf4634 
INFO: MyBean constructor called 
INFO: Session ID: 175355b0e10fe1d0778238bf4634 

ग्लासफिश का उपयोग

package org.mycompany.myproject.session; 

import java.io.Serializable; 
import javax.enterprise.context.SessionScoped; 
import javax.faces.context.FacesContext; 
import javax.inject.Named; 
import javax.servlet.http.HttpSession; 

@Named @SessionScoped public class MyBean implements Serializable { 
    private String myField = null; 

    public MyBean() { 
     System.out.println("MyBean constructor called"); 

     FacesContext fc = FacesContext.getCurrentInstance(); 
     HttpSession session = (HttpSession)fc.getExternalContext().getSession(false); 
     String sessionId = session.getId(); 
     System.out.println("Session ID: " + sessionId); 
    } 

    public String getMyField() { 
     return myField; 
    } 

    public void setMyField(String myField) { 
     this.myField = myField; 
    } 
} 

यहाँ Facelet कोड है:

यहाँ सेम कोड है 3.0.1

+1

मैं वास्तव में एक संबंधित एक करके ऊपर समस्या को सतर्क कर दिया गया था: एक निर्माता (या प्रारंभकर्ता ब्लॉक) में एक गैर अंतिम विधि बुला CDI साथ अवांछित प्रभाव का कारण बनता है। मैंने तब से पढ़ा है कि एक गैर-अंतिम विधि का उपयोग करने की सलाह नहीं दी जाती है (http://download.oracle.com/javase/tutorial/java/javaOO/initial.html)। यदि मैं एक सीडीआई बीन में एक सूची को intialize करने के लिए एक गैर-अंतिम विधि का उपयोग करता हूं तो intitializer दो बार कहा जाता है! नोट: सीडीआई अंतिम तरीकों की अनुमति नहीं देता है और एक रनटाइम अपवाद फेंक देगा जिसमें कहा गया है कि बीन प्रॉक्सीबल नहीं है। "फिक्स" गैर-अंतिम विधि को कॉल नहीं करना है और इनिटिलाइज़र ब्लॉक में सभी काम करना है। – Ryan

+0

मैंने देखा है कि यदि मैं @PostConstruct के साथ एनोटेटेड एक इनिट विधि को परिभाषित करता हूं जिसे इसे केवल एक बार बुलाया जाता है (बीन बनने के दो उदाहरणों के बावजूद)। मुझे लगता है कि सीडीआई मेरे बीन के उदाहरणों का एक पूल बना रहा है और पोस्ट निर्माण को कॉल करता है क्योंकि यह उन्हें पूल से बाहर खींचता है। मुझे लगता है कि वर्तमान HTTP सत्र के साथ पूल में अभी भी बीन के उदाहरण को जोड़ना अर्थहीन है। – Ryan

+1

नीचे मेरी प्रतिक्रिया देखें। 2 उदाहरण 1 प्रासंगिक उदाहरण है, दूसरा प्रॉक्सी है। @PostConstruct निश्चित रूप से केवल प्रासंगिक उदाहरण और प्रॉक्सी के लिए _not_ के लिए बुलाया जाएगा। – struberg

उत्तर

4

रयान, जैसा कि कोवरर पहले ही लिखा है, कन्स्ट्रक्टर को उस बीन के लिए प्रत्येक प्रॉक्सी के लिए भी बुलाया जाएगा। यह सभी प्रॉक्सी तंत्र का एक मानक व्यवहार है जो न केवल इंटरफ़ेस-प्रॉक्सीइंग प्रदान करता है (जैसे java.lang.reflect.proxy सामान) लेकिन वास्तविक वर्ग-प्रॉक्सीइंग।

यह भी कल्पना करें कि सीटी को प्रत्येक क्रमिकरण के लिए भी बुलाया जाएगा। तो यदि आप भारी लोड संतुलित क्लस्टर पर काम करते हैं, तो आप इसे कई बार देखेंगे। तो कृपया आम तौर पर बीन्स के लिए @ पोस्ट कॉन्स्ट्रक्ट का उपयोग करें।

LieGrue, Strub

+0

प्रतिक्रिया के लिए धन्यवाद। हालांकि मैं अभी भी आप में से किसी को समझ नहीं रहा हूं। मैं पोस्टकॉन्स्ट्रक्ट लाइफसाइक्ल कॉलबैक और प्रीरेंडर व्यू सिस्टम इवेंट जैसे उपयोग के लिए एक बीन तैयार करने के वैकल्पिक तरीकों से अवगत हूं; और यह बहुत अच्छा है। मेरा सवाल यह है कि एक सत्र के दो उदाहरण क्यों एक बहुत ही सरल परीक्षण में बनाया जा रहा है जिसमें केवल एक उपयोगकर्ता सर्वर को मार रहा है। मैं भार संतुलन और क्लस्टरिंग के साथ एक भारी लोड सर्वर के बारे में बात नहीं कर रहा हूं। एक से अधिक प्रॉक्सी बनाया जा रहा है? यदि हां, तो क्यों? या शायद प्रत्येक प्रॉक्सी बीन के दो उदाहरणों द्वारा समर्थित है? यदि हां, तो क्यों? – Ryan

+2

रयान, मुझे पता है कि सभी प्रॉक्सी सामान इतना आसान नहीं है, लेकिन 2 कन्स्ट्रक्टर इनवोकेशन प्राप्त करना बिल्कुल ठीक है। पहला उदाहरण प्रासंगिक उदाहरण है।यह बीन है जिसे आप सत्र कॉन्टेक्स्ट में संग्रहीत करेंगे। दूसरा उदाहरण प्रॉक्सी है। यदि आप डीबगर के साथ बारीकी से देखते हैं या आप कन्स्ट्रक्टर में कक्षा को प्रिंट करते हैं, तो आप देखेंगे कि यह वास्तव में आपके बीन का उप-वर्ग है! – struberg

+0

एक प्रॉक्सी है और एक वास्तविक बीन है। समझ गया। ऐसा लगता है कि सीडीआई का उपयोग करते समय आपको कन्स्ट्रक्टर में जो भी रखा गया है, उसे सावधान रहना चाहिए। – Ryan

3

यह संभावना है कि आपके सीडीआई कार्यान्वयन अंतर्निहित बीन्स डिफॉल्ट कन्स्ट्रक्टर को इंजेक्शन पॉइंट्स के लिए उपयोग करने के लिए प्रॉक्सी को नए करते समय कॉल करता है - यह वेवल्ड और ओपनवेबीन में उपयोग किया जाने वाला जावस्सिस्ट का डिफ़ॉल्ट व्यवहार है।

अपने डिफ़ॉल्ट कन्स्ट्रक्टर में भारी उठाने से बचें, इसे @PostConstruct में ले जाएं यदि आप कर सकते हैं!

+0

ठीक है, लेकिन दो क्यों बनाए जा रहे हैं? क्या सीडीआई पूल बनाता है? – Ryan

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