0

I have an application.yml file with the following:

topics:
  input:
    - name: topic1
      partitions: 3
      replicas: 1
    - name: topic2
      partitions: 6
      replicas: 2

I would like to be able to update or add a new topic object at runtime.

I have tried the following for updating an existing object:

java -jar app.jar --topics.input[0].name="topicX"

and the following for adding another object to the list:

java -jar app.jar --topics.input[2].name="topicX" --topics.input[2].partitions=6 --topics.input[2].replicas=2

I am accessing the properties in the following way:

@Component
@ConfigurationProperties(prefix = "topics")
@Validated
public class TopicsConfiguration {

  @NotEmpty
  @NotNull
  private List<TopicConfiguration> input = new ArrayList<>();

  public List<TopicConfiguration> getInputTopics() {
    return input;
  }

  public void setFacts(List<TopicConfiguration> input) {
    this.input = input;
  }

}

Where TopicConfiguration is just a POJO with the 3 fields listed.

When I don't try and modify any of the property objects at runtime this works exactly as I expect, however I can not update the property list at all. When I try and update an existing object I get an NPE. When I try and add a new object to the list I get:

Property: topics.input[2].name
    Value: lmnop
    Origin: "topics.input[2].name" from property source "commandLineArgs"
    Reason: The elements [topics.input[2].name,topics.input[2].partitions,topics.input[2].replicas] were left unbound.

I would just like to know if there is any way to update or add an element to the list at runtime so that users of my project don't have to modify application.yml if they want to update this configuration.

wearebob
  • 376
  • 2
  • 15
  • show us the code you use to update the list, its kindof hard to help you if you dont post the code that gives you a NPE........ – Toerktumlare Jul 08 '19 at 23:01
  • The code is posted above, `java -jar app.jar --topics.input[0].name="topicX"` is how I am trying to do it. I am not attempting to update the list while the app is running, just provide it a new value as I start it up – wearebob Jul 09 '19 at 14:25
  • So you want to store a dynamic updateable list with objects in a properties file? Straight up id say that there is no functionality for that. Who would you even want to do that? Thats not what properties are built for. – Toerktumlare Jul 09 '19 at 15:14
  • Maybe I'm misusing it then. The reason I want to do it is that we just give a Docker image to people that want to run our service. Most users will just want to listen to the default Kafka topic, but some may need to listen to multiple topics, so this was supposed to be a way for them to be able to still run the Docker image as is whiloe providing more topics to listen to. – wearebob Jul 09 '19 at 16:12
  • Okey, im gonna look into this when i get home in an hour or so – Toerktumlare Jul 09 '19 at 16:53

2 Answers2

2

okey so i did some research and some testing and came up with the following:

you cannot update a defined list in application.yml

if you run:

java -jar myApp.jar -my-list[2].name=foo

it will fail, because as soon as you want to pass the list the list will override the current list in application.yml and you are trying to pass in the 3rd item in the list when there is nothing at index 0 and 1.

it is not a dynamic list, it as an array.

You need to pass the entire list:

java -jar myApp.jar -my-list[0].name=foo -my-list[1].name=bar -my-list[2].name=foobar 

So if you are going to pass a list in from cmd, you must always define the list from scratch.

Toerktumlare
  • 12,548
  • 3
  • 35
  • 54
0

So you want to reload your application.properties or application.yml in your Spring Boot application on the fly without having to make another code commit to another deployment? If I understood that right then here is how you can do it.

Read the these links and also google more on Spring Boot Actuator Reload Properties or Spring Scheduling. We can't provide you an out-written code to get this working but there is plenty of examples to examine and try out.

Links:

  1. Actuator Refresh
  2. Spring Scheduling

If I were you, I would prefer Actuator method as it avoids confusion and is cleaner.

Killer Beast
  • 469
  • 6
  • 21
  • This will be helpful for other circumstances, but in my case right now I don't need to restart the application. I just need to provide a command line argument at startup to modify a property. Like in section 5.7 [here](https://www.baeldung.com/properties-with-spring) – wearebob Jul 09 '19 at 14:35
  • 1
    One way to do it is to have spring profiles with respective `application.yaml` (say `prod-application.yaml`, `dev-application.yaml`, etc) – Killer Beast Jul 09 '19 at 15:11