diff --git a/spring-boot-actuator/pom.xml b/spring-boot-actuator/pom.xml index 75fa518e090..bcb23ce3136 100644 --- a/spring-boot-actuator/pom.xml +++ b/spring-boot-actuator/pom.xml @@ -193,11 +193,6 @@ - - org.springframework.integration - spring-integration-jmx - true - org.springframework.integration spring-integration-core @@ -363,6 +358,11 @@ spring-data-rest-webmvc test + + org.springframework.integration + spring-integration-jmx + test + org.springframework.security spring-security-test diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/PublicMetricsAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/PublicMetricsAutoConfiguration.java index 2aa3aa126c0..27526cc4ad3 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/PublicMetricsAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/PublicMetricsAutoConfiguration.java @@ -46,13 +46,15 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnJava; import org.springframework.boot.autoconfigure.condition.ConditionalOnJava.JavaVersion; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.SearchStrategy; import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvider; import org.springframework.cache.CacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.integration.monitor.IntegrationMBeanExporter; +import org.springframework.integration.config.EnableIntegrationManagement; +import org.springframework.integration.support.management.IntegrationManagementConfigurer; import org.springframework.lang.UsesJava7; /** @@ -61,6 +63,7 @@ import org.springframework.lang.UsesJava7; * @author Stephane Nicoll * @author Phillip Webb * @author Johannes Edmeier + * @author Artem Bilan * @since 1.2.0 */ @Configuration @@ -139,18 +142,26 @@ public class PublicMetricsAutoConfiguration { } @Configuration - @ConditionalOnClass(IntegrationMBeanExporter.class) - @ConditionalOnBean(IntegrationMBeanExporter.class) + @ConditionalOnClass(EnableIntegrationManagement.class) @ConditionalOnJava(JavaVersion.SEVEN) @UsesJava7 static class IntegrationMetricsConfiguration { + @Bean(name = IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME) + @ConditionalOnMissingBean(value = IntegrationManagementConfigurer.class, name = IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME, search = SearchStrategy.CURRENT) + public IntegrationManagementConfigurer managementConfigurer() { + IntegrationManagementConfigurer configurer = new IntegrationManagementConfigurer(); + configurer.setDefaultCountsEnabled(true); + configurer.setDefaultStatsEnabled(true); + return configurer; + } + @Bean @ConditionalOnMissingBean(name = "springIntegrationPublicMetrics") public MetricReaderPublicMetrics springIntegrationPublicMetrics( - IntegrationMBeanExporter exporter) { + IntegrationManagementConfigurer managementConfigurer) { return new MetricReaderPublicMetrics( - new SpringIntegrationMetricReader(exporter)); + new SpringIntegrationMetricReader(managementConfigurer)); } } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReader.java index 459a67bafa1..9ce87767301 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReader.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReader.java @@ -22,24 +22,29 @@ import java.util.List; import org.springframework.boot.actuate.metrics.Metric; import org.springframework.boot.actuate.metrics.reader.MetricReader; -import org.springframework.integration.monitor.IntegrationMBeanExporter; +import org.springframework.integration.support.management.IntegrationManagementConfigurer; +import org.springframework.integration.support.management.MessageChannelMetrics; +import org.springframework.integration.support.management.MessageHandlerMetrics; +import org.springframework.integration.support.management.MessageSourceMetrics; +import org.springframework.integration.support.management.PollableChannelManagement; import org.springframework.integration.support.management.Statistics; import org.springframework.lang.UsesJava7; /** * A {@link MetricReader} for Spring Integration metrics (as provided by - * spring-integration-jmx). + * {@link IntegrationManagementConfigurer}). * * @author Dave Syer + * @author Artem Bilan * @since 1.3.0 */ @UsesJava7 public class SpringIntegrationMetricReader implements MetricReader { - private final IntegrationMBeanExporter exporter; + private final IntegrationManagementConfigurer configurer; - public SpringIntegrationMetricReader(IntegrationMBeanExporter exporter) { - this.exporter = exporter; + public SpringIntegrationMetricReader(IntegrationManagementConfigurer configurer) { + this.configurer = configurer; } @Override @@ -49,51 +54,80 @@ public class SpringIntegrationMetricReader implements MetricReader { @Override public Iterable> findAll() { - IntegrationMBeanExporter exporter = this.exporter; - List> metrics = new ArrayList>(); - for (String name : exporter.getChannelNames()) { - String prefix = "integration.channel." + name; - metrics.addAll(getStatistics(prefix + ".errorRate", - exporter.getChannelErrorRate(name))); - metrics.add(new Metric(prefix + ".sendCount", - exporter.getChannelSendCountLong(name))); - metrics.addAll(getStatistics(prefix + ".sendRate", - exporter.getChannelSendRate(name))); - metrics.add(new Metric(prefix + ".receiveCount", - exporter.getChannelReceiveCountLong(name))); - } - for (String name : exporter.getHandlerNames()) { - metrics.addAll(getStatistics("integration.handler." + name + ".duration", - exporter.getHandlerDuration(name))); - } - metrics.add(new Metric("integration.activeHandlerCount", - exporter.getActiveHandlerCount())); - metrics.add(new Metric("integration.handlerCount", - exporter.getHandlerCount())); - metrics.add(new Metric("integration.channelCount", - exporter.getChannelCount())); - metrics.add(new Metric("integration.queuedMessageCount", - exporter.getQueuedMessageCount())); - return metrics; + List> result = new ArrayList>(); + String[] channelNames = this.configurer.getChannelNames(); + String[] handlerNames = this.configurer.getHandlerNames(); + String[] sourceNames = this.configurer.getSourceNames(); + addChannelMetrics(result, channelNames); + addHandlerMetrics(result, handlerNames); + addSourceMetrics(result, sourceNames); + result.add(new Metric("integration.handlerCount", handlerNames.length)); + result.add(new Metric("integration.channelCount", channelNames.length)); + result.add(new Metric("integration.sourceCount", sourceNames.length)); + return result; } - private Collection> getStatistics(String name, - Statistics statistic) { + private void addChannelMetrics(List> result, String[] names) { + for (String name : names) { + addChannelMetrics(result, name, this.configurer.getChannelMetrics(name)); + } + } + + private void addChannelMetrics(List> result, String name, + MessageChannelMetrics metrics) { + String prefix = "integration.channel." + name; + result.addAll(getStatistics(prefix + ".errorRate", metrics.getErrorRate())); + result.add(new Metric(prefix + ".sendCount", metrics.getSendCountLong())); + result.addAll(getStatistics(prefix + ".sendRate", metrics.getSendRate())); + if (metrics instanceof PollableChannelManagement) { + result.add(new Metric(prefix + ".receiveCount", + ((PollableChannelManagement) metrics).getReceiveCountLong())); + } + } + + private void addHandlerMetrics(List> result, String[] names) { + for (String name : names) { + addHandlerMetrics(result, name, this.configurer.getHandlerMetrics(name)); + } + } + + private void addHandlerMetrics(List> result, String name, + MessageHandlerMetrics metrics) { + String prefix = "integration.handler." + name; + result.addAll(getStatistics(prefix + ".duration", metrics.getDuration())); + long activeCount = metrics.getActiveCountLong(); + result.add(new Metric(prefix + ".activeCount", activeCount)); + } + + private void addSourceMetrics(List> result, String[] names) { + for (String name : names) { + addSourceMetrics(result, name, this.configurer.getSourceMetrics(name)); + } + } + + private void addSourceMetrics(List> result, String name, + MessageSourceMetrics sourceMetrics) { + String prefix = "integration.source." + name; + result.add(new Metric(prefix + ".messageCount", + sourceMetrics.getMessageCountLong())); + } + + private Collection> getStatistics(String name, Statistics stats) { List> metrics = new ArrayList>(); - metrics.add(new Metric(name + ".mean", statistic.getMean())); - metrics.add(new Metric(name + ".max", statistic.getMax())); - metrics.add(new Metric(name + ".min", statistic.getMin())); - metrics.add( - new Metric(name + ".stdev", statistic.getStandardDeviation())); - metrics.add(new Metric(name + ".count", statistic.getCountLong())); + metrics.add(new Metric(name + ".mean", stats.getMean())); + metrics.add(new Metric(name + ".max", stats.getMax())); + metrics.add(new Metric(name + ".min", stats.getMin())); + metrics.add(new Metric(name + ".stdev", stats.getStandardDeviation())); + metrics.add(new Metric(name + ".count", stats.getCountLong())); return metrics; } @Override public long count() { - int totalChannelCount = this.exporter.getChannelCount() * 11; - int totalHandlerCount = this.exporter.getHandlerCount() * 5; - return totalChannelCount + totalHandlerCount + 4; + int totalChannelCount = this.configurer.getChannelNames().length; + int totalHandlerCount = this.configurer.getHandlerNames().length; + int totalSourceCount = this.configurer.getSourceNames().length; + return totalChannelCount + totalHandlerCount + totalSourceCount; } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/PublicMetricsAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/PublicMetricsAutoConfigurationTests.java index 3027b7759f0..27c2f4dd14c 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/PublicMetricsAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/PublicMetricsAutoConfigurationTests.java @@ -92,7 +92,7 @@ public class PublicMetricsAutoConfigurationTests { public void metricReaderPublicMetrics() throws Exception { load(); assertThat(this.context.getBeansOfType(MetricReaderPublicMetrics.class)) - .hasSize(1); + .hasSize(2); } @Test diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderNoJmxTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderNoJmxTests.java new file mode 100644 index 00000000000..18efb7f3597 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderNoJmxTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 2012-2016 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 + * + * http://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.boot.actuate.metrics.integration; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.actuate.autoconfigure.PublicMetricsAutoConfiguration; +import org.springframework.boot.actuate.endpoint.MetricReaderPublicMetrics; +import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link SpringIntegrationMetricReader}. + * + * @author Artem Bilan + */ +@RunWith(SpringRunner.class) +@SpringBootTest("spring.jmx.enabled=false") +@DirtiesContext +public class SpringIntegrationMetricReaderNoJmxTests { + + @Autowired + @Qualifier("springIntegrationPublicMetrics") + private MetricReaderPublicMetrics integrationMetricReader; + + @Test + public void test() { + assertThat(this.integrationMetricReader.metrics().size() > 0).isTrue(); + } + + @Configuration + @Import({ IntegrationAutoConfiguration.class, PublicMetricsAutoConfiguration.class }) + protected static class TestConfiguration { + + } + +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderTests.java index 9f4ba580ac5..f8a01b0903d 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/integration/SpringIntegrationMetricReaderTests.java @@ -26,7 +26,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; -import org.springframework.integration.monitor.IntegrationMBeanExporter; +import org.springframework.integration.support.management.IntegrationManagementConfigurer; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; @@ -36,6 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link SpringIntegrationMetricReader}. * * @author Dave Syer + * @author Artem Bilan */ @RunWith(SpringRunner.class) @SpringBootTest("spring.jmx.enabled=true") @@ -55,8 +56,9 @@ public class SpringIntegrationMetricReaderTests { protected static class TestConfiguration { @Bean - public SpringIntegrationMetricReader reader(IntegrationMBeanExporter exporter) { - return new SpringIntegrationMetricReader(exporter); + public SpringIntegrationMetricReader reader( + IntegrationManagementConfigurer managementConfigurer) { + return new SpringIntegrationMetricReader(managementConfigurer); } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java index 1f280dc9cf6..e5e61e58d71 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfiguration.java @@ -21,8 +21,6 @@ import javax.management.MBeanServer; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -35,6 +33,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.integration.config.EnableIntegration; +import org.springframework.integration.config.EnableIntegrationManagement; import org.springframework.integration.jmx.config.EnableIntegrationMBeanExport; import org.springframework.integration.monitor.IntegrationMBeanExporter; import org.springframework.integration.support.management.IntegrationManagementConfigurer; @@ -67,17 +66,10 @@ public class IntegrationAutoConfiguration { protected static class IntegrationJmxConfiguration implements EnvironmentAware, BeanFactoryAware { - private final IntegrationManagementConfigurer configurer; - private BeanFactory beanFactory; private RelaxedPropertyResolver propertyResolver; - protected IntegrationJmxConfiguration( - @Qualifier(IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME) ObjectProvider configurerProvider) { - this.configurer = configurerProvider.getIfAvailable(); - } - @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; @@ -100,17 +92,24 @@ public class IntegrationAutoConfiguration { if (StringUtils.hasLength(server)) { exporter.setServer(this.beanFactory.getBean(server, MBeanServer.class)); } - if (this.configurer != null) { - if (this.configurer.getDefaultCountsEnabled() == null) { - this.configurer.setDefaultCountsEnabled(true); - } - if (this.configurer.getDefaultStatsEnabled() == null) { - this.configurer.setDefaultStatsEnabled(true); - } - } return exporter; } } + @Configuration + @ConditionalOnClass({ EnableIntegrationManagement.class, + EnableIntegrationMBeanExport.class }) + @ConditionalOnMissingBean(value = IntegrationManagementConfigurer.class, name = IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME, search = SearchStrategy.CURRENT) + @ConditionalOnProperty(prefix = "spring.jmx", name = "enabled", havingValue = "true", matchIfMissing = true) + protected static class IntegrationManagementConfiguration { + + @Configuration + @EnableIntegrationManagement(defaultCountsEnabled = "true", defaultStatsEnabled = "true") + protected static class EnableIntegrationManagementConfiguration { + + } + + } + } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java index c5932505bbc..c42df154aed 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/integration/IntegrationAutoConfigurationTests.java @@ -31,6 +31,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.integration.support.channel.HeaderChannelRegistry; +import org.springframework.integration.support.management.IntegrationManagementConfigurer; import org.springframework.jmx.export.MBeanExporter; import org.springframework.test.context.support.TestPropertySourceUtils; @@ -86,12 +87,17 @@ public class IntegrationAutoConfigurationTests { MBeanServer mBeanServer = this.context.getBean(MBeanServer.class); assertDomains(mBeanServer, true, "org.springframework.integration", "org.springframework.integration.monitor"); + Object bean = this.context + .getBean(IntegrationManagementConfigurer.MANAGEMENT_CONFIGURER_NAME); + assertThat(bean).isNotNull(); } @Test public void disableJmxIntegration() { load("spring.jmx.enabled=false"); assertThat(this.context.getBeansOfType(MBeanServer.class)).hasSize(0); + assertThat(this.context.getBeansOfType(IntegrationManagementConfigurer.class)) + .isEmpty(); } @Test diff --git a/spring-boot-starters/spring-boot-starter-integration/pom.xml b/spring-boot-starters/spring-boot-starter-integration/pom.xml index 5a2a1219b33..18871ee4fad 100644 --- a/spring-boot-starters/spring-boot-starter-integration/pom.xml +++ b/spring-boot-starters/spring-boot-starter-integration/pom.xml @@ -34,9 +34,5 @@ org.springframework.integration spring-integration-java-dsl - - org.springframework.integration - spring-integration-jmx - diff --git a/spring-boot-starters/spring-boot-starter-integration/src/main/resources/META-INF/spring.provides b/spring-boot-starters/spring-boot-starter-integration/src/main/resources/META-INF/spring.provides index 66fb5df913c..63514baf3be 100644 --- a/spring-boot-starters/spring-boot-starter-integration/src/main/resources/META-INF/spring.provides +++ b/spring-boot-starters/spring-boot-starter-integration/src/main/resources/META-INF/spring.provides @@ -1 +1 @@ -provides: spring-integration-core,spring-integration-java-dsl,spring-integration-jmx \ No newline at end of file +provides: spring-integration-core,spring-integration-java-dsl