简体   繁体   中英

Spring boot @Value annotation returning null

I have a java class, shown below, that is creating a rest template with connection and read timeouts and also creates a retry template that is executing retries whenever a connection and read timeout occurs. I am reading in the values from an application.properties file but for some reason I am getting null values for the values being read in. I have no idea what I can do to fix this. Any advice on this would be appreciated.

public class Retry {

@Value("${read.Timeout.InMilliSeconds:-1}")
private Integer readTimeoutInMilliSeconds;

@Value("${connect.Timeout.InMilliSeconds:-1}")
private Integer connectTimeoutInMilliSeconds;

@Value("${backOff.Period.InMilliSeconds:-1}")
private Integer backOffPeriodInMilliSeconds;

@Value("${max.Attempts:-1}")
private Integer maxAttempts;

@Bean
public RestTemplate restTemplate() {

    RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
    return restTemplate;
}

private HttpComponentsClientHttpRequestFactory getClientHttpRequestFactory() {

    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
    requestFactory.setReadTimeout(readTimeoutInMilliSeconds);
    requestFactory.setConnectTimeout(connectTimeoutInMilliSeconds);
    return requestFactory;
}

@Bean
public RetryTemplate retryTemplate() {

    Map<Class<? extends Throwable>, Boolean> retryableExpressions = new HashMap<>();

    // connection and read timeouts
    retryableExpressions.put(ResourceAccessException.class, true);

    // 404
    retryableExpressions.put(RestClientException.class, false);

    SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy(maxAttempts, retryableExpressions);

    FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
    backOffPolicy.setBackOffPeriod(backOffPeriodInMilliSeconds);

    RetryTemplate retryTemplate = new RetryTemplate();
    retryTemplate.setRetryPolicy(simpleRetryPolicy);
    retryTemplate.setBackOffPolicy(backOffPolicy);

    return retryTemplate;
}

@Bean
public RetryRestTemplate retryRestTemplate() {
    return new RetryRestTemplate(
            restTemplate(),
            retryTemplate());
   }
}

application.properties

read.Timeout.InMilliSeconds=10000
connect.Timeout.InMilliSeconds=10000
backOff.PeriodInMilliSeconds=10000
max.Attempts=5

stack trace

Caused by: java.lang.NullPointerException: null
at com.beans.Retry.getClientHttpRequestFactory(Retry.java:43)
at com.beans.Retry.restTemplate(Retry.java:36)
at com.beans.Services.retryRestTemplate(Services.java:82)
at com.beans.Services$$EnhancerBySpringCGLIB$$819e8a9c.CGLIB$retryRestTemplate$3(<generated>)
at com.beans.Services$$EnhancerBySpringCGLIB$$819e8a9c$$FastClassBySpringCGLIB$$65931da6.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.beans.Services$$EnhancerBySpringCGLIB$$819e8a9c.retryRestTemplate(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 213 common frames omitted

Process finished with exit code 1

RetryRestTemplate

public class RetryRestTemplate {

private RestTemplate restTemplate;
private RetryTemplate retryTemplate;

public RetryRestTemplate(RestTemplate restTemplate, RetryTemplate retryTemplate) {
    this.restTemplate = this.restTemplate;
    this.retryTemplate = this.retryTemplate;
}

public ResponseEntity getForEntity(URI uri, Class c) {
    return retryTemplate.execute(retryContext -> {
        System.out.println("Check");
        return restTemplate.getForEntity(uri, c);
    });
}

public ResponseEntity exchange(String url, HttpMethod get, HttpEntity headers, Class c) {
    return retryTemplate.execute(retryContext -> {
        return restTemplate.exchange(url, get, headers, c);
    });
}

public <T extends Object> ResponseEntity<T> postForEntity(String apiUrl, HttpEntity<Object> entityRequest, Class<T> responseClass) {
    return retryTemplate.execute(retryContext -> {
        return restTemplate.postForEntity(apiUrl, entityRequest, responseClass);
    });
}

}

Class Retry maybe is not managed by Spring. Adding @Configuration upon Retry class.

@Configuration
public class Retry {
}

Try to move @Value(...) into corresponging methods as input parameters as follows:

private HttpComponentsClientHttpRequestFactory getClientHttpRequestFactory(
    @Value("${read.Timeout.InMilliSeconds:-1}") Integer readTimeoutInMilliSeconds,
    @Value("${connect.Timeout.InMilliSeconds:-1}") Integer connectTimeoutInMilliSeconds) {
    ...
}

@Bean
public RetryTemplate retryTemplate(
    @Value("${backOff.Period.InMilliSeconds:-1}") Integer backOffPeriodInMilliSeconds,
    @Value("${max.Attempts:-1}") Integer maxAttempts) {
    ...
}

Or you can also try to create a constructor for Retry and use @Value for constructor arguments:

private Integer readTimeoutInMilliSeconds;
private Integer connectTimeoutInMilliSeconds;
private Integer backOffPeriodInMilliSeconds;
private Integer maxAttempts;

Retry(@Value("${read.Timeout.InMilliSeconds:-1}") Integer readTimeoutInMilliSeconds,
      @Value("${connect.Timeout.InMilliSeconds:-1}") Integer connectTimeoutInMilliSeconds,
      @Value("${backOff.Period.InMilliSeconds:-1}") Integer backOffPeriodInMilliSeconds,
      @Value("${max.Attempts:-1}") Integer maxAttempts) {
    this.readTimeoutInMilliSeconds = readTimeoutInMilliSeconds;
    this.connectTimeoutInMilliSeconds = connectTimeoutInMilliSeconds;
    this.backOffPeriodInMilliSeconds = backOffPeriodInMilliSeconds;
    this.maxAttempts = maxAttempts;
}

Apart from @Value annotation, there is other way to get properties value. By using the Environment Interface's instance.

Follow the below steps:

  1. Add @Component annotation on Retry.java
  2. Import and Autowired Environment in your Retry.java

     import org.springframework.core.env.Environment @Autowired private Environment env;
  3. Get value of the property from env. For example,

    env.getProperty("read.Timeout.InMilliSeconds","-1");

There are several other flavors also to the value of the property. You can check it out on this .

2 Things:
1) As others said add configuration
2)Check if you're using Retry as Autowired in any class for which object is created. If any bean class is used in an instantiated object, it returns null.

Please add the following annotations in your Retry.java

@Configuration
@PropertySource("classpath:application.properties")

and change your @Value annotations like below

@Value("#{'${read.Timeout.InMilliSeconds:-1}'}")
private Integer readTimeoutInMilliSeconds;

And it should work!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM