Enable passing sources explicitly #36

Closed
alexeyr opened this Issue Jun 30, 2013 · 10 comments

Comments

Projects
None yet
2 participants
@alexeyr

alexeyr commented Jun 30, 2013

Sometimes it may be desirable to determine source location at runtime, and pass them to ConfigFactory explicitly (e.g. if we want to find config files relative to the jar file's directory http://stackoverflow.com/questions/2837263/how-do-i-get-the-directory-that-the-currently-executing-jar-file-is-in).

@lviggiano

This comment has been minimized.

Show comment
Hide comment
@lviggiano

lviggiano Jun 30, 2013

Owner

Hi Alexeyr

There are several ways that could possibly help:

  1. The @Sources annotation does support variable expansion from system properties:
    class Example {
        MyConfig cfg = createMyConfig();

        @Sources("file:${mypath}/myconfig.properties");
        interface MyConfig extends Config {
        }

       static MyConfig createMyConfig() {
           String myPath = ...;
           System.setProperty("mypath", myPath);
           return ConfigFactory.create(MyConfig.class);
       }

One could also specify -Dmypath=... to the JVM at the command line, ie. from a batch file.

You can also use ${user.dir} in the @Sources annotation, that is contained in the System properties by default when the JVM starts and points to the work dir from which the JVM has been launched, as somebody suggested on StackOverflow as well.

By default, the url specifed with file: protocol are relative to the workdir (unless they start with a / char), so if you specify:

    @Sources("file:etc/myconfig.properties");
    interface MyConfig extends Config { ... }

the path etc/myconfig.properties will be relative to the path from where you launched the JVM.
So, for instance, if you launch the JVM from the directory /home/luigi/myapp/ this will be resolved as /home/luigi/myapp/etc/myconfig.properties.

  1. OWNER supports a feature called 'importing properties', so basically you can load properties as you prefer then wrap into an OWNER Config object:
     Properties props = new Properties();
     props.load(new FileInputStream(new File("path/to/whatever.properties"))); 
     MyConfig cfg = ConfigFactory.create(MyConfig.class, props);
  1. On the master branch (that will be released on the next version) it is possible to config objects to implement the Mutable interface, that allows the Config object to be altered. If you like I can add some ways to load properties programmatically from an InputStream:
     interface MyConfig extends Config, Mutable { ... }

     MyConfig cfg = ConfigFactory.create(MyConfig.class);

     cfg.load(new FileInputStream(...)); 
     // or 
     cfg.load(new FileReader(...));
     // or 
     cfg.loadFromXML(new FileInputStream(...));

Those methods will delegate the loading to the internal Properties object. At the moment those methods are not available, but I think I may add them. What do you think?

Option 3 will be (eventually) available in version 1.0.4 and superior. Option 1 and 2 should already work with released version 1.0.3 (and 1.0.2 too).

Let me know.

Owner

lviggiano commented Jun 30, 2013

Hi Alexeyr

There are several ways that could possibly help:

  1. The @Sources annotation does support variable expansion from system properties:
    class Example {
        MyConfig cfg = createMyConfig();

        @Sources("file:${mypath}/myconfig.properties");
        interface MyConfig extends Config {
        }

       static MyConfig createMyConfig() {
           String myPath = ...;
           System.setProperty("mypath", myPath);
           return ConfigFactory.create(MyConfig.class);
       }

One could also specify -Dmypath=... to the JVM at the command line, ie. from a batch file.

You can also use ${user.dir} in the @Sources annotation, that is contained in the System properties by default when the JVM starts and points to the work dir from which the JVM has been launched, as somebody suggested on StackOverflow as well.

By default, the url specifed with file: protocol are relative to the workdir (unless they start with a / char), so if you specify:

    @Sources("file:etc/myconfig.properties");
    interface MyConfig extends Config { ... }

the path etc/myconfig.properties will be relative to the path from where you launched the JVM.
So, for instance, if you launch the JVM from the directory /home/luigi/myapp/ this will be resolved as /home/luigi/myapp/etc/myconfig.properties.

  1. OWNER supports a feature called 'importing properties', so basically you can load properties as you prefer then wrap into an OWNER Config object:
     Properties props = new Properties();
     props.load(new FileInputStream(new File("path/to/whatever.properties"))); 
     MyConfig cfg = ConfigFactory.create(MyConfig.class, props);
  1. On the master branch (that will be released on the next version) it is possible to config objects to implement the Mutable interface, that allows the Config object to be altered. If you like I can add some ways to load properties programmatically from an InputStream:
     interface MyConfig extends Config, Mutable { ... }

     MyConfig cfg = ConfigFactory.create(MyConfig.class);

     cfg.load(new FileInputStream(...)); 
     // or 
     cfg.load(new FileReader(...));
     // or 
     cfg.loadFromXML(new FileInputStream(...));

Those methods will delegate the loading to the internal Properties object. At the moment those methods are not available, but I think I may add them. What do you think?

Option 3 will be (eventually) available in version 1.0.4 and superior. Option 1 and 2 should already work with released version 1.0.3 (and 1.0.2 too).

Let me know.

@alexeyr

This comment has been minimized.

Show comment
Hide comment
@alexeyr

alexeyr Jun 30, 2013

Yes, option 3 fits what I want quite well and this isn't an immediate requirement.

alexeyr commented Jun 30, 2013

Yes, option 3 fits what I want quite well and this isn't an immediate requirement.

@lviggiano

This comment has been minimized.

Show comment
Hide comment
@lviggiano

lviggiano Jun 30, 2013

Owner

Ok, I will add the load methods. It's very quick to do and it will be included in the next released version. I'll probably implement it today, so you can test with the master branch. I can send you the jar if you need to verify that it does what you need and you don't have time to package it by yourself.

Owner

lviggiano commented Jun 30, 2013

Ok, I will add the load methods. It's very quick to do and it will be included in the next released version. I'll probably implement it today, so you can test with the master branch. I can send you the jar if you need to verify that it does what you need and you don't have time to package it by yourself.

@alexeyr

This comment has been minimized.

Show comment
Hide comment
@alexeyr

alexeyr Jun 30, 2013

And now I thought that it won't play well with hot reload and change events coming in 1.0.4. Unless this could also be easily added?

alexeyr commented Jun 30, 2013

And now I thought that it won't play well with hot reload and change events coming in 1.0.4. Unless this could also be easily added?

@lviggiano

This comment has been minimized.

Show comment
Hide comment
@lviggiano

lviggiano Jun 30, 2013

Owner

Hot reload is optional (if you don't specify the @HotReload annotation it won't be enabled). If you decide to load properties manually, you need to implement hot reload by your own if you want it.

The HotReload only works with file: (or jar:file:) URLs specified by @Sources annotation. It's quite inconvenient to monitor for changes in InputStreams or Reader objects.

Owner

lviggiano commented Jun 30, 2013

Hot reload is optional (if you don't specify the @HotReload annotation it won't be enabled). If you decide to load properties manually, you need to implement hot reload by your own if you want it.

The HotReload only works with file: (or jar:file:) URLs specified by @Sources annotation. It's quite inconvenient to monitor for changes in InputStreams or Reader objects.

@lviggiano

This comment has been minimized.

Show comment
Hide comment
@lviggiano

lviggiano Jun 30, 2013

Owner

I could possibly add something like:

@Sources("file:${mypath}/myconfig.properties");   // notice ${mypath} here
interface MyConfig extends Config { ... }

ConfigFactory.setProperty("mypath", "/foo/bar/baz"); // ${mypath} will be expanded as "/foo/bar/baz"
MyConfig cfg = ConfigFactory.create(MyConfig.class);
Owner

lviggiano commented Jun 30, 2013

I could possibly add something like:

@Sources("file:${mypath}/myconfig.properties");   // notice ${mypath} here
interface MyConfig extends Config { ... }

ConfigFactory.setProperty("mypath", "/foo/bar/baz"); // ${mypath} will be expanded as "/foo/bar/baz"
MyConfig cfg = ConfigFactory.create(MyConfig.class);
@alexeyr

This comment has been minimized.

Show comment
Hide comment
@alexeyr

alexeyr Jun 30, 2013

Yes, this seems to cover cases I can think of.

alexeyr commented Jun 30, 2013

Yes, this seems to cover cases I can think of.

@lviggiano

This comment has been minimized.

Show comment
Hide comment
@lviggiano

lviggiano Jun 30, 2013

Owner

👍

Owner

lviggiano commented Jun 30, 2013

👍

lviggiano added a commit that referenced this issue Jun 30, 2013

added props to ConfigFactory so that user can set some context
environment variables for the ConfigFactory and change the way
it works (and in future also to configure the OWNER global
behavior). See issue #36 on github.
@lviggiano

This comment has been minimized.

Show comment
Hide comment
@lviggiano

lviggiano Jun 30, 2013

Owner

Implemented.
See 61605e7 and 0449ecd.

Things to do before closing:

  • document in the website or the wiki.
Owner

lviggiano commented Jun 30, 2013

Implemented.
See 61605e7 and 0449ecd.

Things to do before closing:

  • document in the website or the wiki.
@lviggiano

This comment has been minimized.

Show comment
Hide comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment