Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support arbitrary sources for loading properties from #70

Closed
wants to merge 3 commits into from
Closed

Support arbitrary sources for loading properties from #70

wants to merge 3 commits into from

Conversation

pgaschuetz
Copy link

Hi,

in reference to #14

I would like to propose the attached pull request to support loading properties from arbitrary sources.
In detail, the pull request:

  • changed all internal occurrences of java.net.URL to java.net.URI
  • refactored some logic from org.aeonbits.owner.loaders.Loader into a new AbstractFileBasedLoader
  • Introduced AbstractNamedCustomLoader, which can be easily extended to support pretty much any source of configurations

see CustomNamedLoaderTest for a demonstration

There is definitely room for improvement, especially HotReloading is not implemented yet, but this should be relatively trivial by moving the WatchableFile logic into Loader

Apart from some minor internal API changes, this pull request should not change any existing functionality. All tests run fine.

Please let me know what you think.

Refactor owner to use URIs instead of URLs throughout the code in preparation for being able to register custom Source Loaders
* org.aeonbits.owner.loaders.Loader#load has been refactored to accept a URI instead of an InputStream as the source. This change has been made to prepare owner to allow for loaders with arbitrary sources

* introduced ConfigurationSourceNotFoundException, which is now thrown instead of an IOException, if a URI cannot be found/processed by a Loader
* added support for custom loaders
* added AbstractNamedCustomLoader, which can be easily extended to load data from arbitrary sources (ie. JDBC, JNDI, etc)
@lviggiano
Copy link
Collaborator

I'll review this asap in detail.
Thanks.

@lviggiano
Copy link
Collaborator

While I find interesting to use URI in place of URL, I am not fully convinced by the rest. I'll learn more from your branch as soon as I can (very busy recently with work and life, so sorry in advance for the delay).

At first sight, using URI in place of URL is good since it allows to have user-defined specifications to identify resources, without the need to configure a URLStreamHandler (java is not very flexible in that). Loaders are in charge of accepting URI, but they can possibly be responsible to access acceptable URIs returning the InputStream (task, that at the moment is done via ConfigUR*Factory and normally it would require an URLStreamHandler). But it looks like the problem is more complex than that: Loaders were initially thought for file formats, while the "protocol" is independent from that and may require something like a ProtocolHandler.

Your code contains interesting ideas. I need more time to study it in deep and to fully understand it. I admit I didn't consider to use URI in place of URL on the first place for my ignorance on the topic.

@pgaschuetz
Copy link
Author

Thanks for your reply!
As I said, there's definetly a lot of room for improvement and the main idea was to get it working in the first place and keep the number of changes to a minimum.

@lviggiano
Copy link
Collaborator

Thanks to you. I'll get back to this asap with more thoughts. Maybe we can abstract the logic on how to do some things on URIs, with an interface like:

// this is just a draft of an idea
interface ProtocolHandler {
    // returns a long identifying last modified time; useful for hot reload
    long lastModified(URI uri);

    // returns the content of the uri
    InputStream openStream(URI uri);

    // eventually
    boolean accept(URI uri);
}

// then

ConfigFactory.registerProtocolHandler(new JDBCProtocolHandler(...));

just a thought.

So loader can still work on file types, while protocol handler can be used to access different resource locations.

@pgaschuetz
Copy link
Author

  • lastModified definitely makes sense

For the others, I'm not too sure, whether I understand this correctly.

  • The idea of having a "custom loader" also specify a defaultSpecFor() was that Config classes without @ Sources could be easily distinguished when loading:
interface foo.bar.SimpleConfig implements Config {
  ...
}

// inside ie. CustomJdbcLoader
SQL = "SELECT key,value FROM config WHERE identifier = " + getFragment()
// where getFragment() would return "foo.bar.SimpleConfig"
  • openStream would probably not work with ie. a JDBC datasource, unless one would serialize a properties file into a single column

My initial idea was that owner should not care, where its datasources are located and how they are to be read

@lviggiano
Copy link
Collaborator

A little update.

Commit 156a8b2 is basically a cherry pick of the URL->URI substition.

I'll probably split the Loader class in two parts:

  • a protocol handler, to handle specific (and custom) protocols
  • a parser, to handle data interpretation and transformation to java.util.Properties from different sources
    resolved by the protocols

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants