Search code examples
springspring-integrationspring-cloudspring-cloud-config

Config refresh isn't working inside route declaration


I'm using Config Server from spring-cloud. I wish to refresh app's configuration without have to restart it.

This is my scenario:

1) Single configuration in application.yml, stored in git

job:
 demo:
  testMessage: 'My ID is 123'

2) Actuator in the client and annotation @RefreshScope in the controller.

@RefreshScope
@Component
@RestController
public class DemoController {

  @Value("${job.demo.testMessage}")
  String testMessage;

  @RequestMapping(value = "/", produces = "application/json")
  public List<String> index() {
      List<String> env = Arrays.asList(
            "config 1 is: " + testMessage
      );
      return env;
  }
}

3) One flow with Spring Integration:

@RefreshScope
@Slf4j
@Setter
@Component
@ConfigurationProperties(prefix = "job.demo")
public class DemoFlow {

    private String testMessage;

    @Bean
    public IntegrationFlow putDemoModelFlow() {
        return IntegrationFlows.from(Http.inboundChannelAdapter("/demoFlow"))
            .handle(new DemoHandler())
            .handle(m -> log.info("[LOGGING DEMO] {}" , m.getPayload()))
            .get();
    }

    private class DemoHandler implements GenericHandler {

        @Override
        public String handle(Object payload, Map headers) {
            return new StringBuilder().append(testMessage)
                .append(" ").toString();
        }
    }
}

4) I update the configuration and push to git

job:
 demo:
  testMessage: 'My ID is 789'

5) Run the refresh

curl -d{} http://localhost:8002/refresh

In the rest call to controller, everything worked fine, the config was updated.

["config 1 is: My ID is 789"]

But in the rest call to integration flow, the config wasn't update:

[LOGGING DEMO] My ID is 123

There are some particular behavior of the bean that is preventing to refresh the configuration?

Thanks.


Solution

  • I don't believe that putting the @Configuration class in @RefreshScope will put the beans declared therein into that scope.

    Further, the IntegrationFlow @Bean generates a number of beans internally and they certainly won't be put in that scope. You should not attempt to "refresh" an integration flow, it will likely cause runtime problems.

    Instead, you should put the property in a separate class from the flow and inject that into your DemoHandler @Bean.