5 Replies Latest reply on Oct 26, 2012 8:29 AM by daniele_athome

    ResourceBundle: merging multiple properties file

    daniele_athome

      Hello, i'm Daniele, i'm new to this community, i searched a lot before opening a new topic, and here I am.

       

      I have a parent portlet that has many derivative portlets (children, as they extend the parent portlet). The children portlets have their own resource bundles, but of course they need resource bundle data from the parent portlet too: so I was forced to use a java class to be able to create a bundle extending the parent portlet bundle.

       

      My objective is to convert those in properties files: they are much easier to manage, and they don't require any rebuild. I tried in many ways:

       

      • creating a new ResourceBundle similar to PropertyResourceBundle which loads from multiple property files, but that would require to patch the actual PropertyResourceBundle in JRE (I really don't want to do that)
      • creating a wrapper to PortletConfig to return the right ResourceBundle; but that would require to write also the bundle lookup code (e.g. seeing the <resource-bundle> tag, by the way there is no standard way to read that).
      • creating a custom java bundle which would load from multiple properties file itself, and then including that bundle in the <resource-bundle> tag, but that would require a single java file for each language next to the actual properties file with the internationalized strings.

       

      Really I don't know how to do that in a proper way.

      Thank you

      Daniele

        • 1. Re: ResourceBundle: merging multiple properties file
          rannath

          I did it like so:

           

          public class ExpandingResourceBundle extends ResourceBundle {
               private DataStructure lookup;
               
               public ExpandingResourceBundle(InputStream stream) {
                    -read in from file using stream //PropertyResourceBundle uses HashMap(Properties) to make it work
                    -store in lookup
               }
               public ExpandingResourceBundle(Reader reader) {
                    -read in from file using reader //PropertyResourceBundle uses HashMap(Properties) to make it work
                    -store in lookup
               }
          
               public Object handleGetObject(String key) {
                    -return Object from lookup
               }
          
               public Enumeration getKeys() {
                    return keysSet() of this an all parents //from Map or equivalent in your data structure
               }
               
               public void addResources(InputStream stream) {
                    -read in from file using stream //PropertyResourceBundle uses HashMap(Properties) to make it work
                    -add to in lookup
               }
               
               public void addResources(Reader reader) {
                    -read in from file using stream //PropertyResourceBundle uses HashMap(Properties) to make it work
                    -add to in lookup
               }
               
               protected Set handleKeySet() {
                    -return keySet() of this only
               }
          }
          

           

          I'll leave it as an exercise for you to do the actual implementation, though I would suggest googling code samples (I built this from the suggestions at: http://stackoverflow.com/questions/1318347/how-to-use-java-property-files with some error checking  adding a boolean hasKey(str) as a wrapper around Propeties(Hashtable)'s containsKey(str)).

           

          Not sure if this is the "right" way but it definately works.

          • 2. Re: ResourceBundle: merging multiple properties file
            daniele_athome

            Hi Patrick, thanks for answering.

            Actually that was the solution I tried, but after that I realized that to use the .properties file natively from a portlet <resource-bundle> tag I had to modify the Properties class of java runtime, or otherwise a class inside GateIn itself, because of the way it works.

            The portlet container first looks in the <resource-bundle> tag, checking if the fully-qualified name in the tag points to a Java class or to a properties file.

            If it's the latter, the resource bundle loader (whatever class it is) loads the properties file using class Properties from the Java runtime.

             

            Actually I succeded (out of curiosity) to modify the native Properties class and it actually works, using a special property key name "include" which loads another properties file (the path taken from the property value). But it's a bit odd - I mean modifying java runtime. Properties file should have native support for external file inclusion.

             

            Anyway, for the moment, I wrote a servlet which, at application startup, merges two or more properties files into one big properties file; so when GateIn will read bundles, it will find the whole properties files just created by the servlet.

            • 3. Re: ResourceBundle: merging multiple properties file
              hoang_to

              GateIn PC supports extending resource bundle of portlets. A side of resources defined in portlet definition 's <resource-bundle> element, .properties files having path defined as "sharedResourceBundle" of ResourceBundleService are made accessible from portlet.

               

              So to fullfill your wish, an aleternative way is to declared .properties file of your parent portlet as "sharedResourceBundle" in ResourceBundleService.

               

              The drawback is that the shared resource are visible from every portlet

              • 4. Re: ResourceBundle: merging multiple properties file
                daniele_athome

                Thank you Minh, but that still doesn't fit my case, sorry.

                However, I decided to apply a small patch to GateIn 3.1.0. I didn't optimize it at all, my primary concern was to modify as little code as possible (configuring the whole GateIn project in Eclipse is a very hard work).

                 

                The patch makes the class PropertiesClassLoader to load another .properties file if it finds an "include" property key. The value of that key will be used to load the other bundle file, using it as the parent bundle.

                 

                I've attached my patch to this message.

                Thank you

                • 5. Re: ResourceBundle: merging multiple properties file
                  daniele_athome

                  Here is an updated and tested version of my patch. It was tested against GateIn 3.1.0 and 3.2.0.

                  The patch makes the class PropertiesClassLoader to load another .properties file if it finds an "include" property key. The value of that key will be used to load the other bundle file, using it as the parent bundle.