2008-11-24 12 views
16

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

मैंने उन दोनों सर्टलेट्स के साथ खेलने की कोशिश की है जिनमें "लोड-ऑन-स्टार्टअप" सेट है, और एक ServletContextListener चीजों को पाने के लिए, और सेट अप करने में सक्षम नहीं हैं, या तो क्योंकि वहां नहीं है एक FacesContext उपलब्ध नहीं है, या क्योंकि मैं जेएसएफ पर्यावरण से बीन का संदर्भ नहीं दे सकता।

क्या वेब ऐप स्टार्टअप पर जेएसएफ बीन शुरू करने का कोई तरीका है?

उत्तर

14

तो FacesContext, यह एक JSF अनुरोध जीवन चक्र के साथ जुड़े एक सूत्र के बाहर काम नहीं करेगा। एक FacesContext ऑब्जेक्ट प्रत्येक अनुरोध के लिए बनाया गया है और अनुरोध के अंत में निपटाया गया है। static call के माध्यम से इसे लाने का कारण यह है क्योंकि यह अनुरोध की शुरुआत में ThreadLocal पर सेट है। एक FacesContext का जीवन चक्र ServletContext के साथ कोई संबंध नहीं है।

शायद यह पर्याप्त नहीं है (ऐसा लगता है कि आप पहले से ही इस मार्ग से नीचे आ गए हैं), लेकिन आप जो चाहते हैं उसे करने के लिए ServletContextListener का उपयोग करने में सक्षम होना चाहिए। बस सुनिश्चित करें कि FacesContext को कोई भी कॉल जेएसपी के अनुरोध थ्रेड में रखा गया है।

web.xml:

<listener> 
    <listener-class>appobj.MyApplicationContextListener</listener-class> 
</listener> 

कार्यान्वयन:

public class MyApplicationContextListener implements ServletContextListener { 

    private static final String FOO = "foo"; 

    public void contextInitialized(ServletContextEvent event) { 
     MyObject myObject = new MyObject(); 
     event.getServletContext().setAttribute(FOO, myObject); 
    } 

    public void contextDestroyed(ServletContextEvent event) { 
     MyObject myObject = (MyObject) event.getServletContext().getAttribute(
       FOO); 
     try { 
      event.getServletContext().removeAttribute(FOO); 
     } finally { 
      myObject.dispose(); 
     } 
    } 

} 

आप (यदि कोई अन्य चर एक ही नाम के साथ मौजूद है या बस सीधे) JSF आवेदन गुंजाइश के माध्यम से इस वस्तु को संबोधित कर सकते हैं:

<f:view> 
    <h:outputText value="#{applicationScope.foo.value}" /> 
    <h:outputText value="#{foo.value}" /> 
</f:view> 

यदि आप किसी जेएसएफ प्रबंधित बीन में ऑब्जेक्ट को पुनर्प्राप्त करना चाहते हैं, तो आप इसेसे प्राप्त कर सकते हैं:

FacesContext.getCurrentInstance() 
      .getExternalContext().getApplicationMap().get("foo"); 
+0

यह समाप्त हो गया - मैं जेएसएफ कोड में इसे सुलभ बनाने के लिए "setAttribute" बिट खो रहा था। धन्यवाद! –

0

श्रोताओं या लोड-ऑन-स्टार्टअप का उपयोग करना, इस प्रयास करें: अपने कोड कॉल http://www.thoughtsabout.net/blog/archives/000033.html

+0

मैंने पहले उस चाल का उपयोग किया है, लेकिन यह ServletContextListener के साथ काम नहीं करता है क्योंकि आपके पास चेहरे कॉन्टेक्स्ट = संदर्भ फ़ैक्टरी के लिए अनुरोध/प्रतिक्रिया नहीं है।getFacesContext (servletContext, अनुरोध, प्रतिक्रिया, जीवन चक्र); यदि कोई परम शून्य है तो यह विफल हो जाता है। लोड-ऑन-स्टार्टअप/इनिट के साथ एक ही समस्या। –

+0

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

0

JSF में आप इसे संभाल करने के लिए एक SystemEventListener उपयोग कर सकते हैं 2 +। आप इसे आरंभ करने के लिए PostConstructApplicationEvent पर कार्रवाई करने के लिए सेट करेंगे।

public class SystemEventListenerImpl implements SystemEventListener { 

    @Override 
    public void processEvent(SystemEvent event) throws AbortProcessingException { 
    Application application = (Application) event.getSource(); 
    //TODO 
    } 

    @Override 
    public boolean isListenerForSource(Object source) { 
    return (source instanceof Application); 
    } 
} 

यह आपको बस एक मूल्य गुजर तुलना में बहुत अधिक करने की अनुमति देगा:

<system-event-listener> 
    <system-event-listener-class> 
    listeners.SystemEventListenerImpl 
    </system-event-listener-class> 
    <system-event-class> 
    javax.faces.event.PostConstructApplicationEvent 
    </system-event-class>      
</system-event-listener> 

कार्यान्वयन कुछ ऐसा दिखाई देगा।

+1

ध्यान दें कि ओपी जेएसएफ 1.x का उपयोग कर रहा है (प्रश्न पूछे जाने पर जेएसएफ 2.x मौजूद नहीं था)। जेएसएफ 2.x के लिए एक तरह से एक आसान तरीका है: बस एक '@ManagedBean (उत्सुक = सच) @ ApplicationScoped'। एक्सएमएल या इंटरफेस गड़बड़ की कोई ज़रूरत नहीं है। यह भी देखें http://stackoverflow.com/questions/3600534/jsf-how-do-i-force-an-plication-scoped-bean-to-instantiate-at-application-st/3600740#3600740 – BalusC

+0

मैं वापस गया और प्रश्न पढ़ें, और आपका उत्तर JSF 2.x के लिए उत्सुक लोडिंग के बारे में अपने प्रश्न के अंतिम भाग को हल करता है। अच्छी पकड़। –

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