2016-01-29 9 views
5

हमारे पास वाइल्डफ्ल 8 पर एक जेएसएफ एप्लीकेशन है जो डब्ल्यूएआर के WEB-INF\classes फ़ोल्डर में जर्मन और अंग्रेजी के लिए संदेश बंडल और faces-config.xml में एक कॉन्फ़िगरेशन और स्थानीय लोगों को सूचीबद्ध करने में कॉन्फ़िगरेशन द्वारा टेक्स्ट को अंतरराष्ट्रीयकरण के साथ पारंपरिक रूप से तंत्र का उपयोग करता है। एप्लिकेशन में डेटाबेस कनेक्शन नहीं है, लेकिन दूसरे एप्लिकेशन के साथ संवाद करने के लिए आरईएसटी सेवाओं का उपयोग करता है।कैसे युद्ध के बाहर JSF संदेश बंडल डाल करने के लिए तो यह पुनः तैनाती के बिना संपादित किया जा सकता?

अब हम और अधिक आसानी से पाठ बदलने के लिए, जब एक पाठ बदलने के लिए एक नया युद्ध फ़ाइल एक तैनाती का निर्माण और क्या करने वाले नहीं है, जिसका अर्थ में सक्षम होना चाहिए। तो मुझे एक्सएचटीएमएल पृष्ठों के भीतर पहले इस्तेमाल करने में सक्षम होने के दौरान, WAR के बाहर संदेश बंडल रखने के लिए एक तंत्र की आवश्यकता है।

टेक्स्ट को बदलने और एप्लिकेशन को संदेशों को पुनरारंभ किए बिना संदेशों को रीफ्रेश करना होगा (प्राथमिकता 2), और बाहरी बंडल द्वारा अधिलेखित WAR के भीतर एक डिफ़ॉल्ट बंडल रखने के लिए, 3)।

मेरे सोचा सेम scoped और पहले इस्तेमाल ईएल नाम के तहत एक गेटर बेनकाब एक आवेदन के भीतर एक संपत्ति फ़ाइल को पढ़ने के लिए अपाचे कॉमन्स विन्यास की तरह कुछ का उपयोग किया गया। लेकिन किसी भी तरह से ऐसा लगता है कि मौजूदा तंत्र को फिर से कार्यान्वित करना है और यह किसी भी तरह से आसान होना चाहिए, शायद जावा ईई कोर के साथ भी।

किसी को इस तरह से इस तंत्र का इस्तेमाल किया और मुझे विवरण पर कुछ उदाहरण/विवरण को इंगित कर सकते हैं या सूचीबद्ध आवश्यकता (रों) लागू करने के लिए एक बेहतर विचार है गया है?

+0

क्या यह सहायक है? http://stackoverflow.com/q/4499732 – BalusC

+0

@ बाल्लूसी वैसे, जब पहले से ठोकर खा रहा है, तो सवाल के विवरण में नहीं देखा गया है, क्योंकि यह डेटाबेस के माध्यम से इसे संभालने का संदर्भ देता है, जो मेरे पास नहीं है - लेकिन मुझे लगता है आप 'संसाधन बंडल' को विस्तारित करने के हिस्से का जिक्र कर रहे हैं? तो 'getItSomehow'part में इसे फ़ाइल ऑपरेशन के माध्यम से लोड किया जाना चाहिए? उस स्थिति में यह इसे संभालने का एक तरीका हो सकता है। केवल दो वैकल्पिक आवश्यकताएं यहां शामिल होने के लिए स्पष्ट नहीं हैं। –

+0

@ बाल्लूसी ओके, 2) समझ में आता है, 1) शायद गलत समझा जा सकता है - मुझे फ़ाइल में बदलावों को प्रतिबिंबित करने की आवश्यकता नहीं है, लेकिन फ़ाइल को बदलने में सक्षम हो और फिर बंडल का पुनः लोड ट्रिगर करें। - यदि आप टिप्पणी को उत्तर में रखने के लिए समय बिताना चाहते हैं, तो मुझे बक्षीस सौंपने में खुशी होगी। –

उत्तर

6

युद्ध के बाहर जेएसएफ संदेश बंडल कैसे डालें?

दो तरीके:

  1. Add its path to the runtime classpath of the server

  2. Create a custom ResourceBundle implementation with a Control


पाठ परिवर्तन और आवेदन

टेक्स्ट को बदलने तुच्छ हो जाएगा पुनः आरंभ करने के बिना आवेदन में संदेशों को ताज़ा करें। हालांकि, ताज़ा करना तुच्छ नहीं है। Mojarra आंतरिक रूप से इसे आक्रामक रूप से कैश करता है। अगर आप रास्ते में जाना चाहते हैं तो इसे ध्यान में रखना होगा 1. अर्जुन तिजम्स ने इस संबंधित प्रश्न में अपने आंतरिक संसाधन बंडल कैश को साफ़ करने के लिए एक मोज़रा विशिष्ट चाल पोस्ट की है: How to reload resource bundle in web application?

यदि टेक्स्ट बदलना वेबैप में होता है स्वयं, तो आप बस सहेजने के तरीके में कैश क्लीनअप कर सकते हैं। हालांकि पाठ बदलने बाह्य हो सकता है, तो आप एक file system watch service रजिस्टर करने के लिए किसी भी तरह से 1 स्पष्ट बंडल कैश के लिए, या के लिए जिस तरह से 2 पुनः लोड आंतरिक handleGetObject() में परिवर्तन (tutorial here) और फिर पर सुनने की जरूरत होगी।


युद्ध के भीतर एक डिफ़ॉल्ट बंडल, जो युद्ध में बाहरी बंडल द्वारा ओवरराइट है

जब उन्हें classpath से लोड हो रहा है, तो डिफ़ॉल्ट रूप इसका उल्टा है (संसाधन हैं उच्च वर्गीकरण प्राथमिकता है), इसलिए यह निश्चित रूप से रास्ता 1 को खरोंच करता है और हमें 2 तरीके से छोड़ देता है।

नीचे 2 का किकऑफ उदाहरण है। यह मानता है कि आप संपत्ति संसाधन बुन का उपयोग कर रहे हैं text के आधार नाम के साथ डेल (यानी। कोई पैकेज नहीं) और बाहरी पथ /var/webapp/i18n में स्थित है।

public class YourBundle extends ResourceBundle { 

    protected static final Path EXTERNAL_PATH = Paths.get("/var/webapp/i18n"); 
    protected static final String BASE_NAME = "text"; 
    protected static final Control CONTROL = new YourControl(); 

    private static final WatchKey watcher; 

    static { 
     try { 
      watcher = EXTERNAL_PATH.register(FileSystems.getDefault().newWatchService(), StandardWatchEventKinds.ENTRY_MODIFY); 
     } catch (IOException e) { 
      throw new ExceptionInInitializerError(e); 
     } 
    } 

    private Path externalResource; 
    private Properties properties; 

    public YourBundle() { 
     Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); 
     setParent(ResourceBundle.getBundle(BASE_NAME, locale, CONTROL)); 
    } 

    private YourBundle(Path externalResource, Properties properties) { 
     this.externalResource = externalResource; 
     this.properties = properties; 
    } 

    @Override 
    protected Object handleGetObject(String key) { 
     if (properties != null) { 
      if (!watcher.pollEvents().isEmpty()) { // TODO: this is naive, you'd better check resource name if you've multiple files in the folder and keep track of others. 
       synchronized(properties) { 
        try (InputStream input = new FileInputStream(externalResource.toFile())) { 
         properties.load(input); 
        } catch (IOException e) { 
         throw new IllegalStateException(e); 
        } 
       } 
      } 

      return properties.get(key); 
     } 

     return parent.getObject(key); 
    } 

    @Override 
    @SuppressWarnings({ "rawtypes", "unchecked" }) 
    public Enumeration<String> getKeys() { 
     if (properties != null) { 
      Set keys = properties.keySet(); 
      return Collections.enumeration(keys); 
     } 

     return parent.getKeys(); 
    } 

    protected static class YourControl extends Control { 

     @Override 
     public ResourceBundle newBundle 
      (String baseName, Locale locale, String format, ClassLoader loader, boolean reload) 
       throws IllegalAccessException, InstantiationException, IOException 
     { 
      String resourceName = toResourceName(toBundleName(baseName, locale), "properties"); 
      Path externalResource = EXTERNAL_PATH.resolve(resourceName); 
      Properties properties = new Properties(); 

      try (InputStream input = loader.getResourceAsStream(resourceName)) { 
       properties.load(input); // Default (internal) bundle. 
      } 

      try (InputStream input = new FileInputStream(externalResource.toFile())) { 
       properties.load(input); // External bundle (will overwrite same keys). 
      } 

      return new YourBundle(externalResource, properties); 
     } 

    } 

} 

ताकि इसे चलाने रजिस्टर faces-config.xml में नीचे के रूप में करने के लिए प्राप्त करने के लिए।

<application> 
    <resource-bundle> 
     <base-name>com.example.YourBundle</base-name> 
     <var>i18n</var> 
    </resource-bundle> 
</application> 
+0

बहुत व्यापक रूप से उपयोग के रूप में, धन्यवाद। –

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

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