15

I would like a simple, preferably annotation-based way to inject external properties into a java program, without using the spring framework (org.springframework.beans.factory.annotation.Value;)

SomeClass.java

@Value("${some.property.name}")
private String somePropertyName;

application.yml

some:
  property:
    name: someValue

Is there a recommended way to do this in the standard library?

ealfonso
  • 6,622
  • 5
  • 39
  • 67

4 Answers4

33

I ended up using apache commons configuration:

pom.xml:

<dependency>
      <groupId>commons-configuration</groupId>
      <artifactId>commons-configuration</artifactId>
      <version>1.6</version>
    </dependency>

src/.../PropertiesLoader.java

PropertiesConfiguration config = new PropertiesConfiguration();
config.load(PROPERTIES_FILENAME);
config.getInt("someKey");

/src/main/resources/application.properties

someKey: 2

I did not want to turn my library into a Spring application (I wanted @Value annotations, but no application context + @Component, extra beans, extra Spring ecosystem/baggage which doesn't make sense in my project).

ealfonso
  • 6,622
  • 5
  • 39
  • 67
  • 12
    Thank you answering your question. I know this is a bad comment, but it's rare for people to come back and help others that may have the same problems. So thanks. – AFP_555 Nov 10 '17 at 13:40
  • Are you saying you used this to read "application.yml" (emphasis on yml), OR you used this library and (reverted back) to read application.properties file? – granadaCoder Apr 02 '19 at 18:01
  • I probably read from application.properties using this library, I don't think yml vs properties mattered to me at the time, but I don't remember. – ealfonso Apr 02 '19 at 21:23
  • Ok. Yeah, I like the syntax of application.yml, but the spring-baggage is too much to bear for just that component. @AnnotationEasyPeezey. – granadaCoder Apr 03 '19 at 15:22
  • 4
    I'm surprised that this is the accepted answer with that many upvotes. The original question seemed to be asking for a pure JSR-330 way to achieve what `@Value` does in Spring, e.g. something like `@Inject @Named("some.property.name") private String somePropertyName;` (which AFAIK is not actually supported by any of the frameworks that implement JSR-330). Also, the accepted answer is not annotation-based and, moreover, does not even use dependency injection at all. In my mind, this does not answer the question at all. – raner Mar 19 '20 at 23:55
  • Where does the question ask about pure JSR-330, or that annotations are a hard requirement? – ealfonso Mar 23 '20 at 08:09
7

Define application properties here /src/main/resources/application.properties

Define PropertiesLoader class

public class PropertiesLoader {

    public static Properties loadProperties() throws IOException {
        Properties configuration = new Properties();
        InputStream inputStream = PropertiesLoader.class
          .getClassLoader()
          .getResourceAsStream("application.properties");
        configuration.load(inputStream);
        inputStream.close();
        return configuration;
    }
}

Inject property value in the required class like below,

    Properties conf = PropertiesLoader.loadProperties();
    String property = conf.getProperty(key);
Alexey Osetsky
  • 168
  • 2
  • 10
Stone
  • 583
  • 6
  • 8
0

I stumbled upon this answer on google, yet i'm not satisfied.

In the end I created Environment class that uses both application properties from @Stone answer and hardcoded env variables. But Im still looking for better options, since I cannot modify ENV_VARIABLE name inside application.propeties, which is what I originally wanted.

public class EnvironmentPlainJava {

    public int httpsPort() {
        return Integer.parseInt(PropertiesLoader.loadProperties().getProperty("https.port"));
    }

    public String keyStorePath() {
        return System.getenv("KEY_STORE_PATH");
    }
}
0

For reference, here is an idiomatic Kotlin version of the @Stone code (using ClassPathResource Spring utility class - doesn't require running Spring!):

fun loadProperties(properties: String = "application.properties"): Properties =
    ClassPathResource(properties).inputStream.use { inputStream ->
        Properties().also {
            it.load(inputStream)
        }
    }
David Kubecka
  • 127
  • 1
  • 7