Shahrukh Ali
Shahrukh Ali

Reputation: 46

How to configure config.yml in Spring boot using some config class

I am new to Java and spring boot. I am trying to create simple application where some data will be read from config.yml file like url and file for different server to update the data from file. My config.yml looks like this.

appserver1:
   url: http://localhost:8080/api1
   file: \file1.txt
appserver2:
   url: http://localhost:8081/api2
   file: \file2.txt
appserver3:
   url: http://localhost:8082/api3
   file: \file3.txt

I created 3 class where naming AppServer1 , AppServer2 and AppServer3 all have only 2 property containing URL and file path.

public class AppServer1 {
    private String URL;
    private String filePath;
    public String getURL() {
        return URL;
    }
    public void setURL(String URL) {
        this.URL = URL;
    }
    public String getFilePath() {
        return filePath;
    }
    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }
}

How can I make the configuration such that I can use the above classes as Autowired where ever I need to access the AppServer1 or AppServer2 or AppServer3 all over my project. For eg. - If I want to use AppServer1 details I can directly Autowired AppServer1 and use the URL and File path in that class.

I have tried 1 solution using @Value but wanted to know if there is any other as if my config file is big so using @Value will be too hard. Below is the code I tried.

@Configuration
public class AppServer1 {
    @Value("${appserver1.url}")
    private String url;
    @Value("${appserver1.file}")
    private String file;

    @Bean
    AppServer1 beanExample() {
        return new AppServer1(url, file);
    }
}

Is there any annotation which can be used with @Configuration to directly identify the config data and used as Autowired.

Thanks.

Upvotes: 1

Views: 2425

Answers (2)

Anish B.
Anish B.

Reputation: 16439

First of all, don't use custom YML files as there is an issue in spring boot for custom YML support and it's still not resolved by Spring Team.

Read my answer here about why it doesn't support and also the workaround solution is attached in that answer.

Go for .properties file for now. Just create a config.properties file.

appserver1.url=http://localhost:8080/api1
appserver1.file=\\file1.txt

appserver2.url=http://localhost:8081/api2
appserver2.file=\\file2.txt

appserver3.url=http://localhost:8082/api3
appserver3.file=\\file3.txt

Then create your 3 class with same exact name (camelcase) of the field specified in the properties file.

AppServer1.java

@Component
@PropertySource("classpath:config.properties")
@ConfigurationProperties(prefix = "appserver1")
public class AppServer1 {
    private String url;

    private String file;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getFile() {
        return file;
    }

    public void setFile(String file) {
        this.file = file;
    }

    @Override
    public String toString() {
        return "AppServer1 [url=" + url + ", file=" + file + "]";
    }

}

AppServer2.java

@Component
@PropertySource("classpath:config.properties")
@ConfigurationProperties(prefix = "appserver2")
public class AppServer2 {
    private String url;

    private String file;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getFile() {
        return file;
    }

    public void setFile(String file) {
        this.file = file;
    }

    @Override
    public String toString() {
        return "AppServer2 [url=" + url + ", file=" + file + "]";
    }

}

AppServer3.java

@Component
@PropertySource("classpath:config.properties")
@ConfigurationProperties(prefix = "appserver3")
public class AppServer1 {
    private String url;

    private String file;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getFile() {
        return file;
    }

    public void setFile(String file) {
        this.file = file;
    }

    @Override
    public String toString() {
        return "AppServer3 [url=" + url + ", file=" + file + "]";
    }

}

SampleController to test :

@RestController
public class SampleController {
    
    @Autowired
    private AppServer1 appServer;
    
    @GetMapping("appserver")
    public AppServer1 server() {
        return appServer;
    }

}

As soon as, you hit the api - http://localhost:8080/appserver

{
"url": "http://localhost:8080/api1",
"file": "\\file1.txt"
}

Upvotes: 0

Panagiotis Bougioukos
Panagiotis Bougioukos

Reputation: 18899

  • @PropertySource will be needed to load the custom yml that you have named config.yml

  • @ConfigurationProperties will be needed with a prefix in order to read the correct set of properties inside the yml

  • @Component will be needed to make that configuration class be converted into a spring bean which could be autowired

  • You also need to change the field of the class from filePath to file to match the property in your yml. Also change the field URL to url, to match again with the property.

     @PropertySource("classpath:config.yml")
     @ConfigurationProperties(prefix = appserver1)
     @EnableConfigurationProperties()
     public class AppServer1 {
         private String url;
         private String file;
         public String getUrl() {
             return url;
         }
         public void setUrl(String Url) {
             this.url = url;
         }
         public String getFile() {
             return file;
         }
         public void setFile(String file) {
             this.file = file;
         }
     }
    

If you want you can avoid @Component and use another annotations which is for that reason: Just go to the class where you need to be able to autowire those AppServers and add the following annotation @EnableConfigurationProperties ({AppServer1.class, AppServer2.class, AppServer3.class})

Upvotes: 2

Related Questions