Home > database >  Spring Boot @Value annotation picks up key from application.properties, but does not use it at run t
Spring Boot @Value annotation picks up key from application.properties, but does not use it at run t

Time:08-13

The value market with @Value isn't getting passed during run time. My code looks like this:

import com.example.MyClass;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig {
    @Value("${api.key}")
    private String apiKey;

@Bean
public MyClass getKey() {

    return new MyClass(apiKey);

}

}

When I hover my mouse over ${api.key} in IntelliJ it shows the key. And if I replace ${api.key} with the key itself, everything works perfectly fine. So the IDE knows that ${api.key} is the key from application.properties, but on run time, it doesn't use it, and I get a 401 error (because the field is null). Even if I go to application.properties and use "Find usages" on the api.key, it shows the right place in the code where it is used.

If I run mvn spring-boot:run, everything executes perfectly like it should, except the api-key is left null. If I write the key as a string instead of using @Value, it reads it and everything works like it should. It seems to be centered around that @Value isn't passed, although Spring Boot works in every other regard.

I have exhausted all suggestions I've found online, and nothing works. It's hard to list all attempts I've made, but I've tried everything I've seen. Configuring the pom, project structure, run configurations, adding @PropertySource, settings, and more. I even created the whole project from scratch to see if something had gotten tangled up while I tried to solve it.

It recognizes the properties, it runs Spring, it recognizes the key, but it just doesn't use it.

CodePudding user response:

I have faced a similar issue. I find that you can use the @Value annotation on a setter. This should work :

private String apiKey;
@Value("${api.key}")
    public String setApiKey(String apiKey) {
        this.apiKey = apiKey;
    }

I cannot not explain why or how this work, so if someone has any further explanations feel free to edit my answer.

CodePudding user response:

Try the following approach:


@Configuration
public class MyConfig {
    
   @Bean
   public MyClass getKey(@Value("${api.key}") String apiKey) {
       return new MyClass(apiKey);
   }
}

Another (even better) option is using configuration properties:

@ConfigurationProperties(prefix="api")
public class ApiConfigProperties {
   private String key;
   // getters, setters, no-op constructor
}

@Configuration
@EnableConfigurationProperties(ApiConfigProperties.class)
public class MyConfig {
    
  @Bean 
  public MyClass getKey(ApiConfigProperties config) {
      return new MyClass(config.getKey()); 
  } 

}

I usually prefer the second approach because it allows (with a plugin) the generation of a "special" JSON file that the IDE can read and support autocompletion. Another benefit is that the second way is easily debuggable (place a breakpoint in the setter - can't be easier) and allows the defaults specified in one place.

As for your option suggested in the question, I usually treat @Configuration as a DSL that creates beans, so I don't maintain any state on it. Since Configuration has happened to be a spring bean, it allows the auto wiring, but it doesn't mean that you should use it.

  • Related