Commons Configuration
  1. Commons Configuration
  2. CONFIGURATION-213

[configuration] Load file configurations from the classpath

    Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: Nightly Builds
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None
    • Environment:

      Operating System: other
      Platform: All

      Description

      Config files are loaded from the directory of the configuration.xml instead of
      the classpath. This prevents using Configuration where projects use other
      projects and the configuration files can be anywhere on the classpath,
      including inside JAR files.

        Activity

        Hide
        Emmanuel Bourg added a comment -

        Actually they are loaded from the working directory and not the location of the
        configuration.xml file. I agree that would be nice to be able to load them from
        the classpath.

        Show
        Emmanuel Bourg added a comment - Actually they are loaded from the working directory and not the location of the configuration.xml file. I agree that would be nice to be able to load them from the classpath.
        Hide
        Michael Mattox added a comment -

        I didn't realize it was the working dir. That's even worse than I thought.

        I spent an hour going through the code and I just can't figure out where it
        loads in the config files. I'm willing to make a patch for it if someone can
        just point me in the right direction.

        -Michael

        Show
        Michael Mattox added a comment - I didn't realize it was the working dir. That's even worse than I thought. I spent an hour going through the code and I just can't figure out where it loads in the config files. I'm willing to make a patch for it if someone can just point me in the right direction. -Michael
        Hide
        Emmanuel Bourg added a comment -

        I think the problem resides in PropertiesConfiguration, there is no mechanism
        there to load the file from the classpath. The ConfigurationFactory creates a
        new PropertiesConfiguration, sets the filename from the xml file and then call
        load() to populate the configuration.

        I haven't checked but I guess we have the same issue with XMLConfigurations

        Show
        Emmanuel Bourg added a comment - I think the problem resides in PropertiesConfiguration, there is no mechanism there to load the file from the classpath. The ConfigurationFactory creates a new PropertiesConfiguration, sets the filename from the xml file and then call load() to populate the configuration. I haven't checked but I guess we have the same issue with XMLConfigurations
        Hide
        Oliver Heger added a comment -

        ConfigurationFactory provides means to specify a base path or URL from which
        configuration files are loaded. Refer to the API doc of the setBasePath()
        method. If this method was not called, the location of the configuration factory
        XML file is used as base path. Relative URLs specified in the XML file are
        resolved using this base path. It is also possible to specify absolute URLs for
        the configuration files to load.

        Loading configuration files from the class path is not yet supported and I agree
        that this is a useful feature. As Emmanuel pointed out loading of the
        configuration files is done by instantiating a Configuration object of the right
        type and invoking its load() method.

        With the actual design I think it won't be easy to implement loading from class
        path as an additional and optional feature. For the long run I would suggest a
        more sophisticated mechanism for locating configuration files, e.g. a couple of
        ConfigurationLocator classes that know how to find a configuration file in the
        class path, at a specified URL, in the user's home directory, relative to
        another location etc. And I still propose to separate the loading of
        configuration objects from the objects itself by introducing a hierarchy of
        ConfigurationLoader classes.

        Oliver

        Show
        Oliver Heger added a comment - ConfigurationFactory provides means to specify a base path or URL from which configuration files are loaded. Refer to the API doc of the setBasePath() method. If this method was not called, the location of the configuration factory XML file is used as base path. Relative URLs specified in the XML file are resolved using this base path. It is also possible to specify absolute URLs for the configuration files to load. Loading configuration files from the class path is not yet supported and I agree that this is a useful feature. As Emmanuel pointed out loading of the configuration files is done by instantiating a Configuration object of the right type and invoking its load() method. With the actual design I think it won't be easy to implement loading from class path as an additional and optional feature. For the long run I would suggest a more sophisticated mechanism for locating configuration files, e.g. a couple of ConfigurationLocator classes that know how to find a configuration file in the class path, at a specified URL, in the user's home directory, relative to another location etc. And I still propose to separate the loading of configuration objects from the objects itself by introducing a hierarchy of ConfigurationLoader classes. Oliver
        Hide
        Michael Mattox added a comment -

        I came up with a solution for XML files but I can't get it to work for
        properties, it breaks the tests. For XML I did this:

        public class HierarchicalDOM4JConfiguration ...

        /**

        • Loads and parses an XML document. The file to be loaded must have
        • been specified before.
        • @throws Exception if an error occurs
          */
          public void load() throws ConfigurationException {

        // first try to find file on the classpath
        URL url = getClass().getResource("/" + file);
        if (url != null) {
        File f = new File(url.getFile());
        if (f.exists())

        { load(url); }

        } else {
        // file is not on the classpath, so use the old
        method
        try

        { load(ConfigurationUtils.getURL(getBasePath(), getFileName())); }

        catch (MalformedURLException mue)

        { throw new ConfigurationException("Could not load from " + getBasePath() + ", " + getFileName()); }

        }
        }

        and for properties:

        public class PropertiesConfiguration ...

        protected InputStream getPropertyStream(String resourceName) throws
        IOException {
        InputStream resource = null;

        resource = getClass().getResourceAsStream("/" + extractFileName
        (resourceName));
        if (resource != null)

        { return resource; }

        URL url = null;
        try

        { url = ConfigurationUtils.getURL(getBasePath(), resourceName); }

        /* try */
        catch (MalformedURLException uex)

        { throw new IOException("Cannot obtain URL for resource " + resourceName); }

        /* catch */

        resource = url.openStream();

        setBasePath(url.toString());
        setIncludesAllowed(true);

        return resource;
        }

        I hope that helps. I think some serious design rethinking needs to take place
        to implement this. I really hope this will be come a priority, I don't find it
        very useful that all the config files must be located in the same directory as
        the configuration.xml. For now we can work around this by copying our config
        files and not embedding them in the JARs but I really don't like this approach.

        Michael

        Show
        Michael Mattox added a comment - I came up with a solution for XML files but I can't get it to work for properties, it breaks the tests. For XML I did this: public class HierarchicalDOM4JConfiguration ... /** Loads and parses an XML document. The file to be loaded must have been specified before. @throws Exception if an error occurs */ public void load() throws ConfigurationException { // first try to find file on the classpath URL url = getClass().getResource("/" + file); if (url != null) { File f = new File(url.getFile()); if (f.exists()) { load(url); } } else { // file is not on the classpath, so use the old method try { load(ConfigurationUtils.getURL(getBasePath(), getFileName())); } catch (MalformedURLException mue) { throw new ConfigurationException("Could not load from " + getBasePath() + ", " + getFileName()); } } } and for properties: public class PropertiesConfiguration ... protected InputStream getPropertyStream(String resourceName) throws IOException { InputStream resource = null; resource = getClass().getResourceAsStream("/" + extractFileName (resourceName)); if (resource != null) { return resource; } URL url = null; try { url = ConfigurationUtils.getURL(getBasePath(), resourceName); } /* try */ catch (MalformedURLException uex) { throw new IOException("Cannot obtain URL for resource " + resourceName); } /* catch */ resource = url.openStream(); setBasePath(url.toString()); setIncludesAllowed(true); return resource; } I hope that helps. I think some serious design rethinking needs to take place to implement this. I really hope this will be come a priority, I don't find it very useful that all the config files must be located in the same directory as the configuration.xml. For now we can work around this by copying our config files and not embedding them in the JARs but I really don't like this approach. Michael
        Hide
        Emmanuel Bourg added a comment -

        Is this the right fix until we rethink the configuration location mechanism ?
        This change implies that the file in the classpath overwrites the one in the
        local path, but someone may be interested in the opposite behaviour, i.e the
        local file overwrites the one in the classpath.

        Show
        Emmanuel Bourg added a comment - Is this the right fix until we rethink the configuration location mechanism ? This change implies that the file in the classpath overwrites the one in the local path, but someone may be interested in the opposite behaviour, i.e the local file overwrites the one in the classpath.
        Hide
        Michael Mattox added a comment -

        How about this:

        If the file exists in the same directory as the configuration.xml, it is used.
        This satisfies the current behavior and won't break existing apps.

        if the file does not exist in the same directory as the configuration.xml, it
        is searched on the classpath. To me this is perfectly logical because if the
        file doesn't exist in the same dir, this is a "last ditch effort" to find it
        before raising an exception and possibly aborting the program.

        I really need to find a solution to this because as it is now the only way for
        us to use Configuration is to put all our config files in the same directory.
        This causes lots of problems for distribution. For example, our common.jar has
        properties used only for tests. Those should not be distributed. I'm really
        stuck on this.

        If I have time I plan to implement this solution before I leave on vacation.
        if anyone else has some ideas please let me know.

        Michael

        Show
        Michael Mattox added a comment - How about this: If the file exists in the same directory as the configuration.xml, it is used. This satisfies the current behavior and won't break existing apps. if the file does not exist in the same directory as the configuration.xml, it is searched on the classpath. To me this is perfectly logical because if the file doesn't exist in the same dir, this is a "last ditch effort" to find it before raising an exception and possibly aborting the program. I really need to find a solution to this because as it is now the only way for us to use Configuration is to put all our config files in the same directory. This causes lots of problems for distribution. For example, our common.jar has properties used only for tests. Those should not be distributed. I'm really stuck on this. If I have time I plan to implement this solution before I leave on vacation. if anyone else has some ideas please let me know. Michael
        Hide
        Emmanuel Bourg added a comment -

        Taking the bug, I'm working on a patch.

        Show
        Emmanuel Bourg added a comment - Taking the bug, I'm working on a patch.
        Hide
        Emmanuel Bourg added a comment -

        File based configurations are now loaded from the classpath if the file is not
        found in the base directory. Let us know how it works for you Michael.

        Show
        Emmanuel Bourg added a comment - File based configurations are now loaded from the classpath if the file is not found in the base directory. Let us know how it works for you Michael.

          People

          • Assignee:
            Unassigned
            Reporter:
            Michael Mattox
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development