Load dynamic objects from application.properties in Spring Boot

Viewed 863

I currently have a microservice in Spring Boot, where I have some properties stored in application.properties. Right now, it is configured for one store only. But I want to change the logic so that stores can be added dynamically without needing to change any code.

I have created a model java class for a store, and it looks like this:

public class Store {
    private String username;
    private String password;
    private String hostname;
    private int port;
}

My application.properties looks like this today:

system.connection.username=TestUser
system.connection.password=123456
system.connection.hostname=12.34.56.78
system.connection.port=1234

But I want to be able to specify which store it is, and be able to add more stores by just adding them into the application.properties, like this:

system.connection.Store1.username=TestUser1
system.connection.Store1.password=123456
system.connection.Store1.hostname=12.34.56.78
system.connection.Store1.port=1234

system.connection.Store2.username=TestUser2
system.connection.Store2.password=859382
system.connection.Store2.hostname=34.34.34.34
system.connection.Store2.port=4444

Then add this into some hashmap, and be able to check for and retrieve the variables for a specific store from any of my other classes.

For this, I have tried the following:

@Configuration
@ConfigurationProperties(prefix = "system.connection")
class StoresConfiguration(
    val stores: HashMap<String, Store> = HashMap()
) {

    fun getStore(storeName: String): Store? {
        return stores.get(storeName)
    }


}

But getStore only returns null, and even if I check stores.size it is 0. So where am I doing wrong, and how can I do this effectively? I have thought about just skipping the crap and just making a folder called "stores" and put json files in it, and read from there. So that each Store is just a json file, so at startup the app scans the folder and for every json file makes a Store object. But I don't know if that is a good solution. This is my first time working with Spring Boot. Thanks for any help!

2 Answers

Would this be helpful? This is using an indexed list in a ConfigurationProperties class.

@ConfigurationProperties("system.connection")
// use a fitting name here
public class Stores {

    // reference your Store type
    private final List<Store> store = new ArrayList<>();

    public List<Store> getStore() {
        return this.store;
    }

}
system.connection.store[0].username=foo
system.connection.store[0].password=pass1
...
system.connection.store[1].username=bar
system.connection.store[1].password=pass2

Later an example with a map is also given in the above link, but the list approach with the indices might better fit your needs.

By playing around a little bit, I managed to solve the issue. I reverted my class back to Kotlin, and made some adjustments on how I retrieve the values. This is how you can load dynamic objects from application.properties in Spring Boot with Kotlin:

Suppose you have an object class called Store.kt

data class Store(
    var name: String ?= null,
    var username: String ?= null,
    var password: String ?= null,
    var hostname: String ?= null,
    var port: Int ?= null,
)

In your application.properties

system.stores.Store1.name=Test1
system.stores.Store1.username=test1
system.stores.Store1.password=123456
system.stores.Store1.hostname=12.34.56.78
system.stores.Store1.port=1234

system.stores.Store2.name=Test2
system.stores.Store2.username=test2
system.stores.Store2.password=123456
system.stores.Store2.hostname=12.34.56.78
system.stores.Store2.port=1234

This is in your StoresConfiguration.kt

@Configuration
@ConfigurationProperties(prefix = "system")
class StoreConfiguration(
    var stores: HashMap<String, Store> = HashMap()
) {

    fun getStore(storeName: String) : Store? {
        return stores.get(storeName)
    }


}

Then suppose you want to get the objects and use them in one of your service classes:

@Service
class StoreService(

    private val storeConfiguration: StoreConfiguration,

) { 

fun test() {

val MyStore = storeConfiguration.getStore("Store1")

if (MyStore != null) {

// Do whatever you want to do with your object

} else {

// If your object does not exist

}

}

}
Related