Set @Value to use @ConfigurationProperties prefix

Viewed 5551

I'm using a properties file with the value: com.abc.cpuUtilization.okThreshold = 0.5

I want to use the following configuration class:

@Component
@ConfigurationProperties(prefix="com.abc")
public class SystemConfiguration{

  @Value("${cpuUtilization.okThreshold}")
  private Double cpuUtilizationOkThreshold;

  // getters and setters of cpuUtilizationOkThreshold
  }
}

But I get an exception of Could not resolve placeholder 'cpuUtilization.okThreshold'

When setting @Value to be: "${com.abc.cpuUtilization.okThreshold}" it works, but it makes the code look ugly and cumbersome.

Is there a way to configure this class, so I will not have to write the whole prefix for the @Value annotation?

6 Answers

Spring configuration properties scanning works like package scanning.

The @Value annotation works with the full property name, or a raw string value. And so the value you set should be. Assume to have the com.abc.cpu-utilization.okThreshold=0.5 property.

  • Solution 1: your SystemConfiguration modify the prefix and delete the @Value:

    @Getter
    @Setter
    @Configuration
    @ConfigurationProperties(prefix = "com.abc.cpu-utilization")
    public class SystemConfiguration {
       private Double okThreshold;
    }
    
  • Solution 2: your SystemConfiguration could point to com.abc and contain an inner configuration for the cpu-utilization intermediate package:

    @Getter
    @Setter
    @Configuration
    @ConfigurationProperties(prefix = "com.abc")
    public class SystemConfiguration {
       private CpuUtilizationConfig cpuUtilization;
    }
    
    @Data
    public class CpuUtilizationConfig {
        private Double okThreshold;
    }
    

Note that okThreshold and cpuUtilization directly reflect the property naming we have prior defined. Then, Spring will do the magic :-)

See:

As thepaoloboi said, The @ConfigurationProperties(prefix="com.abc") annotation will allow you to bind fields via their name. If you specify a prefix of "com.abc" and you have a variable named "cpuUtilization", the value of the variable will be that of the "com.abc.cpuUtilization" property.

The @Value annotation fetches the property with the exact same name. @Value("${cpuUtilization.threshold}") will fetch the property with that exact name. It does not take the prefix into account.

For congiuation propertiestion you just need to add the values in proeprties file with the same key with the variable.

in application.properties.

com.abc.cpuUtilization.okThreshold=123

Your class should be:

@Component
@ConfigurationProperties(prefix="com.abc.cpuUtilization")
public class SystemConfiguration{

  private Double okThreshold;

  }
}

The @ConfigurationProperties(prefix="com.abc") annotation will allow you to bind fields via their name. As @Olgun YILDIZ stated, if you specify a prefix of "com.abc" and you have a variable named "cpuUtilization" , the value of the variable will be that of the "com.abc.cpuUtilization" property. (In fact, you could even name your variable "cpuutilization" , "cpu_utilization" , "cpu-utilization" or "CPU_UTILIZATION" because of Spring's relaxed rules for binding properties).

The @Value annotation fetches the property with the exact same name. @Value("${cpuUtilization.threshold}") will fetch the property with that exact name. It does not take the prefix into account.

Either you do as @Olgun suggested (prefix of "com.abc.cpuUtilization" and variable name "okThreshold" ) or you set the whole property name in the @Value.

@ConfigurationProperties works best with hierarchical properties that all have the same prefix therefore, you add a prefix of com.abc.cpuUtilization.Your POJO class Should be like

@Configuration
@ConfigurationProperties(prefix="com.abc.cpuUtilization")
public class SystemConfiguration{

  private Double okThreshold;

  public Double getOkThreshold() {
        return okThreshold;
    }

    public void setOkThreshold(Double okThreshold) {
        this.okThreshold = okThreshold;
    }

  }
}

If you don't use @Configuration in the POJO, then you need to add @EnableConfigurationProperties(ConfigProperties.class) in the main Spring application class to bind the properties into the POJO. Then you can set value in application.properties

com.abc.cpuUtilization.okThreshold=0.5

Refer:https://www.baeldung.com/configuration-properties-in-spring-boot

First of all, change your "cpuUtilization.okThreshold" value to com.abc.cpuUtilization-okThreshold = 0.5

Then in the config class:

@Component
@ConfigurationProperties("com.abc")
public class SystemConfiguration{

  private Double cpuUtilizationOkThreshold;

  // getters and setters of cpuUtilizationOkThreshold
  }
}

Try to configure without using "prefix" and without using the @Value annotation, it worked for me.

Related