Files
spring-cloud-config/spring-platform-config-client
Dave Syer 67c0aa9dbf Ensure /refresh reloads bootstrap configurations
Some changes a while back had switched off refreshing the bootstrap config
(because of the way it was being detected in an existing environment to prevent
an infinite loop). This change fixes that by adding a dummy property source
during bootstrap and then removing it again.
2014-07-17 08:26:10 +01:00
..
2014-06-27 08:33:55 +01:00
2014-06-16 14:41:25 +01:00

Spring Platform Components

This project contains boilerplate patterns for distributed application components, making those patterns easy to implement with Spring (and Spring Boot in particular).

Spring Boot Features

Bootstrap Listener - A SpringApplication with the platform components on its classpath will have an extended bootstrap phase, allowing new strategies for configuration management and other non-functional features to be added to the application before it is initialized. The implementation is similar to @EnableAutoConfiguration, allowing new jars to contribute additional features by defining BootstrapConfiguration classes in the form of @Configuration. Instead of being added to the application's context they are added to a special "bootstrap" context, which is then used to extract ApplicationContextInitializers to apply to the application before it is created. A typical use case would be to locate and install additional environment properties so that the application can adapt to its environment in a completely flexible way.

Autoconfiguration - An application using @EnableAutoConfiguration will pick up beans for the components below, notably RefreshEndpoint, EnvironmentManager and RefreshScope.

RefreshEndpoint

Re-initializes the bootstrap environment, and sends a EnvironmentChangeEvent if any properties changed. Both the RefreshScope and the ConfigurationPropertiesRebinder respond to this event. Exposed at /refresh.

EnvironmentManager and EnvironmentManagerEndpoint

The EnvironmentManager allows you to modify the Spring Environment in a running application. It adds a PropertySource with high priority to the Environment (so properties set there will take precedence). If you have the Actuator and are in a webapp then the EnvironmentManagerEndpoint will also expose "/env" with POST for updating the EnvironmentManager remotely. E.g. run the app locally:

@Configuration
@EnableAutoConfiguration
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

then interact with the Environment:

$ curl localhost:8080/env/message
Hello
$ curl localhost:8080/env -d message=Foo
$ curl localhost:8080/env/message
Foo

Doing this (or the equivalent operation over JMX) will trigger an event that leads to rebinding of @ConfigurationProperties (see below).

ConfigurationPropertiesRebinder

Spring beans that are @ConfigurationProperties can be rebound if the Environment changes. Example:

	@ConfigurationProperties
	protected static class ServiceProperties {
		private String message;
		public String getMessage() {
			return message;
		}
		public void setMessage(String message) {
			this.message = message;
		}
	}

then inject ServiceProperties into an application component using @Autowired and use it to govern the behaviour. When the Environment changes do this

    @Autowired
    private ConfigurationPropertiesRebinder rebinder;
    
    ...
    
		rebinder.rebind();

The ConfigurationPropertiesRebinder is also a @ManagedResource so you can ping the rebind() operation remotely.

RefreshScope

Spring beans in scope="refresh" are re-initialized on the next method call after a refresh. Example:

	@Configuration
	@EnableConfigurationProperties(TestProperties.class)
	@EnableAutoConfiguration
	protected static class TestConfiguration {
		
		@Autowired
		private TestProperties properties;
		
		@Bean
		@RefreshScope
		public ExampleService service() {
			ExampleService service = new ExampleService();
			service.setMessage(properties.getMessage());
			service.setDelay(properties.getDelay());
			return service;
		}
		
	}

then update the TestProperties (e.g. via JMX or something), and

	@Autowired
	private RefreshScope scope;

...

		// ...and then refresh, so the bean is re-initialized:
		scope.refresh("service");