Only refresh if the event targets the app. Fixes #68
This commit is contained in:
@@ -52,11 +52,8 @@ import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
@@ -68,7 +65,8 @@ import org.springframework.util.PathMatcher;
|
||||
@EnableConfigurationProperties(BusProperties.class)
|
||||
@AutoConfigureBefore(BindingServiceConfiguration.class)
|
||||
// so stream bindings work properly
|
||||
@AutoConfigureAfter(LifecycleMvcEndpointAutoConfiguration.class)
|
||||
@AutoConfigureAfter({ LifecycleMvcEndpointAutoConfiguration.class,
|
||||
ServiceMatcherAutoConfiguration.class })
|
||||
// so actuator endpoints have needed dependencies
|
||||
public class BusAutoConfiguration implements ApplicationEventPublisherAware {
|
||||
|
||||
@@ -191,29 +189,6 @@ public class BusAutoConfiguration implements ApplicationEventPublisherAware {
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
protected static class MatcherConfiguration {
|
||||
|
||||
@BusPathMatcher
|
||||
// There is a @Bean of type PathMatcher coming from Spring MVC
|
||||
@ConditionalOnMissingBean(name = BusAutoConfiguration.BUS_PATH_MATCHER_NAME)
|
||||
@Bean(name = BusAutoConfiguration.BUS_PATH_MATCHER_NAME)
|
||||
public PathMatcher busPathMatcher() {
|
||||
return new DefaultBusPathMatcher(new AntPathMatcher(":"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServiceMatcher serviceMatcher(@BusPathMatcher PathMatcher pathMatcher,
|
||||
BusProperties properties, Environment environment) {
|
||||
String[] configNames = environment.getProperty(CLOUD_CONFIG_NAME_PROPERTY,
|
||||
String[].class, new String[] {});
|
||||
ServiceMatcher serviceMatcher = new ServiceMatcher(pathMatcher,
|
||||
properties.getId(), configNames);
|
||||
return serviceMatcher;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ Endpoint.class })
|
||||
@ConditionalOnBean(HttpTraceRepository.class)
|
||||
|
||||
@@ -41,12 +41,12 @@ public class BusRefreshAutoConfiguration {
|
||||
@ConditionalOnProperty(value = "spring.cloud.bus.refresh.enabled",
|
||||
matchIfMissing = true)
|
||||
@ConditionalOnBean(ContextRefresher.class)
|
||||
public RefreshListener refreshListener(ContextRefresher contextRefresher) {
|
||||
return new RefreshListener(contextRefresher);
|
||||
public RefreshListener refreshListener(ContextRefresher contextRefresher,
|
||||
ServiceMatcher serviceMatcher) {
|
||||
return new RefreshListener(contextRefresher, serviceMatcher);
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnBean(ContextRefresher.class)
|
||||
@ConditionalOnClass(
|
||||
name = { "org.springframework.boot.actuate.endpoint.annotation.Endpoint",
|
||||
"org.springframework.cloud.context.scope.refresh.RefreshScope" })
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.bus;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
|
||||
import static org.springframework.cloud.bus.BusAutoConfiguration.CLOUD_CONFIG_NAME_PROPERTY;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnBusEnabled
|
||||
@EnableConfigurationProperties(BusProperties.class)
|
||||
public class ServiceMatcherAutoConfiguration {
|
||||
|
||||
@BusPathMatcher
|
||||
// There is a @Bean of type PathMatcher coming from Spring MVC
|
||||
@ConditionalOnMissingBean(name = BusAutoConfiguration.BUS_PATH_MATCHER_NAME)
|
||||
@Bean(name = BusAutoConfiguration.BUS_PATH_MATCHER_NAME)
|
||||
public PathMatcher busPathMatcher() {
|
||||
return new DefaultBusPathMatcher(new AntPathMatcher(":"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServiceMatcher serviceMatcher(@BusPathMatcher PathMatcher pathMatcher,
|
||||
BusProperties properties, Environment environment) {
|
||||
String[] configNames = environment.getProperty(CLOUD_CONFIG_NAME_PROPERTY,
|
||||
String[].class, new String[] {});
|
||||
ServiceMatcher serviceMatcher = new ServiceMatcher(pathMatcher,
|
||||
properties.getId(), configNames);
|
||||
return serviceMatcher;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,11 +21,13 @@ import java.util.Set;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.bus.ServiceMatcher;
|
||||
import org.springframework.cloud.context.refresh.ContextRefresher;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class RefreshListener
|
||||
implements ApplicationListener<RefreshRemoteApplicationEvent> {
|
||||
@@ -34,14 +36,38 @@ public class RefreshListener
|
||||
|
||||
private ContextRefresher contextRefresher;
|
||||
|
||||
private ServiceMatcher serviceMatcher;
|
||||
|
||||
@Deprecated
|
||||
// TODO Remove in 3.0.x
|
||||
public RefreshListener(ContextRefresher contextRefresher) {
|
||||
this(contextRefresher, null);
|
||||
}
|
||||
|
||||
public RefreshListener(ContextRefresher contextRefresher,
|
||||
ServiceMatcher serviceMatcher) {
|
||||
this.contextRefresher = contextRefresher;
|
||||
this.serviceMatcher = serviceMatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(RefreshRemoteApplicationEvent event) {
|
||||
Set<String> keys = this.contextRefresher.refresh();
|
||||
log.info("Received remote refresh request. Keys refreshed " + keys);
|
||||
log.info("Received remote refresh request.");
|
||||
// TODO Remove this in 3.0.x
|
||||
if (serviceMatcher == null) {
|
||||
log.warn(
|
||||
"RefreshListener does not have a ServiceMatcher, refresh will not be performed. Consider"
|
||||
+ "passing a ServiceMatcher in the constructor");
|
||||
return;
|
||||
}
|
||||
if (serviceMatcher.isForSelf(event)) {
|
||||
Set<String> keys = this.contextRefresher.refresh();
|
||||
log.info("Keys refreshed " + keys);
|
||||
}
|
||||
else {
|
||||
log.info("Refresh not performed, the event was targetting "
|
||||
+ event.getDestinationService());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.bus.BusPropertiesAutoConfiguration,\
|
||||
org.springframework.cloud.bus.ServiceMatcherAutoConfiguration,\
|
||||
org.springframework.cloud.bus.BusAutoConfiguration,\
|
||||
org.springframework.cloud.bus.BusRefreshAutoConfiguration,\
|
||||
org.springframework.cloud.bus.jackson.BusJacksonAutoConfiguration
|
||||
|
||||
@@ -38,6 +38,7 @@ public class BusAutoConfigurationClassPathTests {
|
||||
public void refreshListenerCreatedWithoutActuator() {
|
||||
new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(RefreshAutoConfiguration.class,
|
||||
ServiceMatcherAutoConfiguration.class,
|
||||
BusRefreshAutoConfiguration.class))
|
||||
.run(context -> assertThat(context).hasSingleBean(RefreshListener.class)
|
||||
.doesNotHaveBean(RefreshBusEndpoint.class));
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.bus;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.cloud.context.refresh.ContextRefresher;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = RefreshListenerIntegrationTests.MyApp.class,
|
||||
properties = { "management.endpoints.web.exposure.include=*",
|
||||
"spring.application.name=foobar" })
|
||||
public class RefreshListenerIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate rest;
|
||||
|
||||
@Autowired
|
||||
private ApplicationEventPublisher context;
|
||||
|
||||
@MockBean
|
||||
ContextRefresher contextRefresher;
|
||||
|
||||
@Test
|
||||
public void testEndpoint() {
|
||||
System.out.println(rest.getForObject("/actuator", String.class));
|
||||
assertThat(rest.postForEntity("/actuator/bus-refresh/demoapp", new HashMap<>(),
|
||||
String.class).getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
|
||||
assertThat(rest.postForEntity("/actuator/bus-refresh/foobar", new HashMap<>(),
|
||||
String.class).getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
|
||||
verify(contextRefresher, times(1)).refresh();
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
static class MyApp {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user