Giter VIP home page Giter VIP logo

easy-props's Introduction


Easy Props
The simple, stupid properties library for Java™

MIT license Build Status Maven Central Javadocs


Latest news

  • 15/11/2020: Version 4.0.0 is now released! You can find all details about the changes in the release notes.

What is Easy Props?

Easy Props is a library to inject configuration properties in Java objects declaratively using annotations. Let's see a quick example. Suppose you have an object of type Bean which should be configured with:

  • An Integer property threshold from a system property passed to the JVM with -Dthreshold=100
  • A String property bean.name from a properties file named myProperties.properties

To load these properties in the Bean object using Easy Props, you annotate fields as follows:

public class Bean {

    @Property(source = "myProperties.properties", key = "bean.name")
    private String beanName;

    @SystemProperty(value = "threshold", defaultValue = "50")
    private int threshold;

    //getters and setters omitted

}

and instruct the library to inject these properties in the annotated fields:

//Instantiate your object
Bean bean = new Bean();

//Create a PropertiesInjector and inject properties in your object
aNewPropertiesInjector().injectProperties(bean);

That's it! Easy Props will:

  • introspect the Bean instance looking for fields annotated with @Property and @SystemProperty
  • convert each property value to the target field's type
  • and inject that value into the annotated field

You can also configure your object at construction time:

public class Bean {

    @Property(source = "myProperties.properties", key = "bean.name")
    private String beanName;

    @SystemProperty(value = "threshold", defaultValue = "50")
    private int threshold;

    public Bean () {
        aNewPropertiesInjector().injectProperties(this);
    }

    //getters and setters omitted

}

Now just create your object and it will be configured and ready to use.

Without Easy Props, you would write something like this:

public class Bean {

    private int threshold;

    private String beanName;

    public Bean() {

        //Load 'threshold' property from system properties
        String thresholdProperty = System.getProperty("threshold");
        if ( thresholdProperty != null ) {
            try {
                threshold = Integer.parseInt(thresholdProperty);
            } catch (NumberFormatException e) {
                // log exception
                threshold = 50; //default threshold value;
            }
        }

        //Load 'bean.name' property from properties file
        Properties properties = new Properties();
        try {
            InputStream inputStream = this.getClass().getClassLoader()
                        .getResourceAsStream("myProperties.properties");
            if (inputStream != null) {
                properties.load(inputStream);
                beanName = properties.getProperty("bean.name");
            }
        } catch (IOException ex) {
            // log exception
            beanName = "FOO"; // default bean name value
        }

    }

    //getters and setters omitted

}

As you can see, a lot of boilerplate code is written to load just two properties, convert them to the target field type, etc. Easy Props takes care of all this boilerplate with a couple of intuitive annotations, which makes your code cleaner, more readable and maintainable.

In this quick example, you have seen two types of properties sources (system and resource bundle). Easy Props can inject properties from many other sources like databases, JNDI contexts, environment variables and more!

Even better, Easy Props allows you write your own annotations and inject properties from custom configuration sources. Checkout the complete reference in the project's wiki.

Why Easy Props?

Dependency injection frameworks allow you to inject properties in Java objects and they do it well. But in order to benefit from this feature, your code should run inside a DI container, or at least, the object in which you are trying to inject properties must be managed by a DI container. What if your code does not run inside a DI container? This is where Easy Props comes to play, to allow you to benefit from properties injection without requiring your code to run inside a DI container.

Core features

  • Lightweight library with no dependencies
  • Type safe access to configuration properties
  • Declarative configuration with intuitive annotations
  • Ability to inject properties from custom configuration sources
  • Ability to hot reload configuration automatically at runtime
  • Ability to manage configuration at runtime via JMX

Contribution

You are welcome to contribute to the project with pull requests on GitHub.

If you found a bug or want to request a feature, please use the issue tracker.

Awesome contributors

Thank you all for your contributions!

License

Easy Props is released under the terms of the MIT license:

The MIT License (MIT)

Copyright (c) 2020 Mahmoud Ben Hassine ([email protected])

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

easy-props's People

Contributors

dependabot[bot] avatar fmbenhassine avatar michaelcouck avatar natlantisprog avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

easy-props's Issues

Allow to register custom type converters

It would be useful to allow programmatic registration of additional Apache BeanUtils converters into a PropertyInjector to expand the default set of data type coercion from Strings.

This could be exposed with a new method on PropertyInjectorBuilder for example. Something like registerConverter(<class>, <converter>)

I noticed for example that bean fields of type java.util.Date are not supported out of the box. With Apache BeanUtils it is necessary to add a new converter specifying the date pattern.

DateConverter converter = new DateConverter();
converter.setPattern("dd/mm/yyyy");
ConvertUtils.register(converter, Date.class);

Add ability to fail fast by throwing an exception if a property is absent

I am trying to use @EnvironmentVariable annotation, currently if annotated environment variable is not set in the deployed environment the fields are left with "null" value.
I can see we have option to set a default value, can we also have an option to throw an exception if a given environment variable is not set. This allows us to fail the applications during configuration initialization.

Unable to load properties file in a web application

In Java Web project (servlet), it is not able to load the properties file located in classpath.

The problem is in this line : ClassLoader.getSystemClassLoader().getResourceAsStream which the system class loader is not able to see classpath of web application. instead this Thread.currentThread().getContextClassLoader(); class loader seem work with all situations.

There is more detail in https://stackoverflow.com/a/2523252/231010

Ability to define order of execution of annotation processors

Currently annotation processors are stored in a map and the keyset is used to iterate through them which can lead to different order of execution if a field is marked with multiple annotations.

Ideally, the convention is to have the following increasing order of precedence (as per what spring also has) and allow the property to be overridden from multiple source:
property in file -> environment variable -> system property

    PropertyInjector() {
        annotationProcessors = new HashMap<>();
        typeConverters = new HashMap<>();
        // TODO the day we decide to remove the dependency to apache commons-beanutils, register built-in converters here

        //register built-in annotation processors
        annotationProcessors.put(SystemProperty.class, new SystemPropertyAnnotationProcessor());
        annotationProcessors.put(Property.class, new PropertyAnnotationProcessor());
        annotationProcessors.put(I18NProperty.class, new I18NPropertyAnnotationProcessor());
        annotationProcessors.put(Properties.class, new PropertiesAnnotationProcessor());
        annotationProcessors.put(DBProperty.class, new DBPropertyAnnotationProcessor());
        annotationProcessors.put(JNDIProperty.class, new JNDIPropertyAnnotationProcessor());
        annotationProcessors.put(MavenProperty.class, new MavenPropertyAnnotationProcessor());
        annotationProcessors.put(ManifestProperty.class, new ManifestPropertyAnnotationProcessor());
        annotationProcessors.put(EnvironmentVariable.class, new EnvironmentVariableAnnotationProcessor());
    }

    void injectProperty(final Field field, final Object object) throws PropertyInjectionException {
        //Introspect the field for each registered annotation, and delegate its processing to the corresponding annotation processor
        for (Class<? extends Annotation> annotationType : annotationProcessors.keySet()) {

configuration through Consul feature request

I would like to request that compatibility be added in for configuration management tools such as consul or etcd.
They both have a decent http API .
I'm thinking something along the lines of a core configuration through http and layers for specific software.
thank you

Add support for default values in all annotations

As of v3.0.0, only @SystemProperty and @EnvironmentVariable annotations provide the ability to specify a default value when the property is absent.

For consistency, all other annotations should provide a way to specify a default value as well.

Database properties should not be logged

Similar to #15, database properties should not be shown in the warning (as it may contain sensitive data like connection parameters) when the requested key is not found. Only the source configuration file should be logged.

Environment variables should not be logged

When a configured environment variable is not set, the library is printing out a warning stating the same, which is good, but in the log message it is also printing out all the environment variables which could be dangerous as some environment variables might have sensitive data like passwords. These logs could get shipped out to a log collector (like splunk) which can be viewed by the entire organization (at least in our case).

  @EnvironmentVariable("ENVIRONMENT")
  private String environment;

And logs are like,

WARNING [org.jeasy.props.processors.EnvironmentVariableAnnotationProcessor processAnnotation] - Environment variable 'ENVIRONMENT' on field 'environment' of type 'com.test..Config' not found in environment variables: [all the env vars]

Add ability to inject properties in private classes

Hi,

This is more a feature request than a bug ;)

With non-public classes, where the setters are either constructed manually or using a tool like lombok, the setter is not found. Perhaps a Class#methods() is the accessor for the setter methods, but presumably these are not visible. Perhaps a direct field setter option on the property annotation whereby the field is set directly, and not using a method?

Regards,
Michael

Prefix db properties with org.jeasy.props

As of v3.1, database properties used by the DBPropertyAnnotationProcessor are expected to be named like db.driver, db.url, etc. This is error prone as those names are generic and might be used for other purposes. Those properties are better prefixed with org.jeasy.props to prevent any ambiguity.

Empty values interrupt injection (PropertyAnnotationProcessor)

It is not unusal to have empty values in a property file. Unfortunately an empty value leads to an exception and further properties are not injected. Is this a bug or should this be the normal behaviour?
MY.KEY_1=value1
MY.KEY_2=value2
MY.KEY_3= <<<<<<<<<<<<<< throws exception and interrupts injection
MY.KEY_4=value4

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.