1

In SpringBoot, I am trying to read the application.properties to Map<String, ServiceModel>, which should be

application.properties

input.default.host=Default
input.default.ip=127.0.0.1
input.default.desc=Default Desc

input.serviceA.host=ServiceA
input.serviceA.ip=192.168.21.1
input.serviceA.desc=ServiceA Desc

input.serviceB.host=ServiceB
input.serviceB.ip=192.168.21.22
input.serviceB.desc=ServiceB Desc

Whenever I try to print it using getServiceProperty(String key) the Map properties are always null, as if they are not initialized.

Here are the details of the classes -

@Component
@ConfigurationProperties(prefix = "input")
public class ServiceModelConfiguration {
  private Map<String, ServiceModel> properties;

  public Map<String, ServiceModel> getProperties() {
    return properties;
  }
  public void setProperties(Map<String, ServiceModel> properties) {
    this.properties = properties;
  }

  public ServiceModel getServiceProperty(String key) {
    ServiceModel specificProperty = properties.get(key);
    return specificProperty;
  }

  public static class ServiceModel {
    private String host;
    private String ip;
    private String desc;

    public ServiceModel(String host, String ip, String desc) {
      this.host = host;
      this.ip = ip;
      this.desc = desc;
    }

    // Getters
    // Setters
  }
}
@Service
public class PrintServices {
  private final ServiceModelConfiguration serviceModelConfiguration;

  @Autowired
  public PrintServices(ServiceModelConfiguration serviceModelConfiguration) {
    this.serviceModelConfiguration = serviceModelConfiguration;
  }
  public void printAllServiceProperties() {
    System.out.println("Host: "
        + serviceModelConfiguration.getServiceProperty("serviceA").getHost());
    System.out.println("IP: "
        + serviceModelConfiguration.getServiceProperty("serviceA").getIp());
    System.out.println("Desc: "
        + serviceModelConfiguration.getServiceProperty("serviceA").getDesc());
  }
}
@SpringBootApplication
@EnableConfigurationProperties(ServiceModelConfiguration.class)
public class ConfigApplication implements CommandLineRunner {
  @Autowired private PrintServices printServices;

  public static void main(String[] args) {
    SpringApplication.run(ConfigApplication.class, args);
  }

  @Override
  public void run(String... args) throws Exception {
    printServices.printAllServiceProperties();
  }
}

4 Answers 4

4

keep your propperties like this. The @ConfigurationProperties(prefix = "input") maps only direct fields inside ServiceModelConfiguration.

input.properties.default.host=Default
input.properties.default.ip=127.0.0.1
input.properties.default.desc=Default Desc

input.properties.serviceA.host=ServiceA
input.properties.serviceA.ip=192.168.21.1
input.properties.serviceA.desc=ServiceA Desc

input.properties.serviceB.host=ServiceB
input.properties.serviceB.ip=192.168.21.22
input.properties.serviceB.desc=ServiceB Desc
Sign up to request clarification or add additional context in comments.

Comments

1

There is no need to provide prefix here. Just remove prefix.

@Component
@ConfigurationProperties
public class ServiceModelConfiguration {
  private Map<String, ServiceModel> properties;

  public Map<String, ServiceModel> getProperties() {
    return properties;
  }
  public void setProperties(Map<String, ServiceModel> properties) {
    this.properties = properties;
  }

  public ServiceModel getServiceProperty(String key) {
    ServiceModel specificProperty = properties.get(key);
    return specificProperty;
  }

  public static class ServiceModel {
    private String host;
    private String ip;
    private String desc;

    public ServiceModel(String host, String ip, String desc) {
      this.host = host;
      this.ip = ip;
      this.desc = desc;
    }

    // Getters
    // Setters
  }
}

Comments

1

If you want to use simple "input" prefix, which is trying to pickup properties form the root, you will need to update your application.properties file content with .properties prefix, like @rahulP suggested.

But, as far as you are trying to map ServiceModel - better will be to update prefix and properties with input.service prefix, see https://docs.spring.io/spring-boot/reference/features/external-config.html#features.external-config.typesafe-configuration-properties:

@ConfigurationProperties(prefix = "input.services")

application.properties:

input.services.default.host=Default
input.services.default.ip=127.0.0.1
input.services.default.desc=Default Desc

input.services.serviceA.host=ServiceA
input.services.serviceA.ip=192.168.21.1
input.services.serviceA.desc=ServiceA Desc

input.services.serviceB.host=ServiceB
input.services.serviceB.ip=192.168.21.22
input.services.serviceB.desc=ServiceB Desc

Also I think you are missing default contructor in ServiceModel, which is required for Spring.

Comments

0

@rahulP's method works.

The reason for this error is that in the ServiceModelConfiguration class, properties is a Map<String, ServiceModel>. This means that Spring Boot would expect to have a node in the configuration file that corresponds to the properties and that contains multiple key-value pairs under this node, each corresponding to a ServiceModel.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.