1

I am trying to read some properties from application.properties. I have created a configuration class with @Component and @ConfigurationProperties annotations.

When I am trying to access the configuration from a controller class, its working fine. But when I am trying to access the configuration from one component class, its throwing a null pointer exception.

Following are the application.properties and classes.

application.properties

elasticsearch.ip=localhost

InputManagementController.java

@RestController
public class InputManagementController {


    @Autowired
    private Configuration configuration;

    @GetMapping("/crawler/start")
    public String start(){
        try{

            System.out.println(configuration.getIp()); ----> getting value localhost
            ElasticsearchInterface es=new ElasticsearchInterface();
            es.getInputs();
        }catch (Exception e){
            e.printStackTrace();
        }
        return "started";
    }
}

ElasticsearchInterface.java

@Component
public class ElasticsearchInterface {


    @Autowired
    private Configuration configuration;

    public List<Map<String, Object>> getInputs() {
            System.out.println(configuration.getIp()); ---> getting java.lang.NullPointerException here
        return null;

    }

}

Configuration.java

@Component
@ConfigurationProperties("elasticsearch")
public class Configuration {

    private String ip;
    private int port;
    private String cluster;

    public String getIp() {
        return ip;
    }
    public void setIp(String ip) {
        this.ip = ip;
    }

}
din_oops
  • 698
  • 1
  • 9
  • 27
  • instead of Component annotation use Configuration annotation on top of Configuration.java class @user – Ryuzaki L Jul 01 '18 at 16:07
  • @Deadpool still getting the same error – din_oops Jul 01 '18 at 16:12
  • it's working for me, are these class in same package? or different? and also check this dependency org.springframework.boot spring-boot-configuration-processor true – Ryuzaki L Jul 01 '18 at 16:58
  • `ElasticsearchInterface es=new ElasticsearchInterface();` doesn't work, you have to inject ElasticsearchInterface as well, so that it's managed by Spring. – dunni Jul 01 '18 at 19:40
  • You are doing it all wrong, you need to use @Configuration annotation so that your class is going to be created in the Spring Context automatically. Because that you don't mark your Configuration class with @ Configuration annotation, it is not created as a bean and you get null pointer exception. Also you should use @ Value annotation so that you define which properties you are going to read. I've explained how to do this correctly via my answer below. – Levent Divilioglu Jul 01 '18 at 22:36
  • @dunni I don't think that's a duplicate with that question referenced in your comment. In this question, the root cause of the problem is about Configuration. – Levent Divilioglu Jul 01 '18 at 23:46
  • @Deadpool added that dependency. all files are in same package. still getting the the same error – din_oops Jul 02 '18 at 08:46
  • @LeventDivilioglu added @ Configuration annotation . also added @ Value .. Still getting the same error – din_oops Jul 02 '18 at 09:08
  • @dunni tried @ inject annotation also. still not working – din_oops Jul 02 '18 at 09:09
  • What exactly did you try? Please update it in your question. – dunni Jul 02 '18 at 09:24
  • @LeventDivilioglu `@ConfigurationProperties` is an alternative to using `@Value` annotations, and technically you need neither `@Component` nor `@Configuration` on that annotated class (check the Spring Boot reference for more information: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-typesafe-configuration-properties) – dunni Jul 02 '18 at 09:25

1 Answers1

4

A - How To Read Custom Property From application.properties In Spring Boot

A-1) Application Properties file

On of the default location of application.properties file is src/main/resources. Create this folder and also this file. Assuming your scenario, put the following properties inside application.properties file;

myconfig.ip=192.168.166.42
myconfig.port=8090

A-2) Configuration Class : AppConfig

In order to read the properties file, you need a class with @Configuration annotation. You need appropriate fields with @Value annotation for all the properties that you need to read. In addition, also you need the getter methods for these fields marked with @Value annotation. Please note that naming this class as "Configuration" is a very bad choice because there is also an annotation with the same name, thus I name it as "AppConfig"

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Value("${myconfig.ip}")
    private String ip;

    @Value("${myconfig.port}")
    private int port;

    public String getIp() {
        return ip;
    }

    public int getPort() {
        return port;
    }

}

A-3) Demo

Then you create a fields of this AppConfig class which is written above, and mark it with @Autowired annotation. Then you can read the properties files easily;

@RestController
@RequestMapping("/")
public class InputManagementController {

    @Autowired
    private AppConfig config;

    @RequestMapping("/test")
    public String test() {
        return String.format(
                "Configuration Parameters: Port: %s, Ip: %s", 
                config.getPort(),
                config.getIp()
        );
    }

}

A-4) Output

enter image description here

B - Solution To Problem

B-1) InputManagementController.java

@RestController
public class InputManagementController {

    @Autowired
    private AppConfig configuration;

    @Autowired
    private ElasticSearchInterface elasticSearchInterface;

    @GetMapping("/crawler/start")
    public String start() {
        try {

            System.out.println(configuration.getIp());
            es.getInputs();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "started";
    }
}

B-2) ElasticSearchInterface.java

@Component
public class ElasticSearchInterface {

    @Autowired
    private AppConfig configuration;

    public List<Map<String, Object>> getInputs() {
        System.out.println(configuration.getIp());

        return null;
    }

}

B-3) AppConfig.java

@Configuration
public class AppConfig {

    @Value("${myconfig.ip}")
    private String ip;

    @Value("${myconfig.port}")
    private int port;

    public String getIp() {
        return ip;
    }

    public int getPort() {
        return port;
    }

}
Levent Divilioglu
  • 11,198
  • 5
  • 59
  • 106
  • Thanks for the detailed writeup. I tried AppConfig class But Still I am getting the same error. I am able to read the properties within the controller class. But i am still not able to read the properties in my service class ElasticsearchInterface. Still its throwing a null pointer exception. – din_oops Jul 02 '18 at 09:12
  • The problem there is, you are using a new operator instead of using autowiring. Create an interface, implement it, and use the interface as a field in your class then autowire it. The reason you are getting null pointer exception is your class instance is not on Spring Context. I've updated my answer, added a second section. – Levent Divilioglu Jul 02 '18 at 09:36
  • 1
    Thank you. Its working now :) – din_oops Jul 02 '18 at 11:13
  • 1
    Thank you Levent Divilioglu for writeup. Perfect amount of info I needed. – BeHappy May 23 '21 at 04:13