diff --git a/spring-boot-actuator/pom.xml b/spring-boot-actuator/pom.xml
index 48a866fda3e..508e125c14f 100644
--- a/spring-boot-actuator/pom.xml
+++ b/spring-boot-actuator/pom.xml
@@ -56,6 +56,11 @@
javax.servlet-api
true
+
+ org.apache.activemq
+ activemq-broker
+ true
+
org.hibernate
hibernate-validator
diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java
index c0c4f703fc1..52d46b19660 100644
--- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java
+++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java
@@ -19,10 +19,11 @@ package org.springframework.boot.actuate.autoconfigure;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
-
+import javax.jms.ConnectionFactory;
import javax.sql.DataSource;
import org.apache.solr.client.solrj.SolrServer;
+
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.ApplicationHealthIndicator;
@@ -32,6 +33,7 @@ import org.springframework.boot.actuate.health.DiskSpaceHealthIndicator;
import org.springframework.boot.actuate.health.DiskSpaceHealthIndicatorProperties;
import org.springframework.boot.actuate.health.HealthAggregator;
import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.boot.actuate.health.JmsHealthIndicator;
import org.springframework.boot.actuate.health.MailHealthIndicator;
import org.springframework.boot.actuate.health.MongoHealthIndicator;
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
@@ -49,6 +51,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadata;
import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvider;
import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProviders;
+import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration;
@@ -74,7 +77,7 @@ import org.springframework.mail.javamail.JavaMailSenderImpl;
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, MongoAutoConfiguration.class,
MongoDataAutoConfiguration.class, RedisAutoConfiguration.class,
RabbitAutoConfiguration.class, SolrAutoConfiguration.class,
- MailSenderAutoConfiguration.class })
+ MailSenderAutoConfiguration.class, JmsAutoConfiguration.class})
@EnableConfigurationProperties({ HealthIndicatorAutoConfigurationProperties.class })
public class HealthIndicatorAutoConfiguration {
@@ -316,4 +319,40 @@ public class HealthIndicatorAutoConfiguration {
}
}
+ @Configuration
+ @ConditionalOnBean(ConnectionFactory.class)
+ @ConditionalOnProperty(prefix = "management.health.jms", name = "enabled", matchIfMissing = true)
+ public static class JmsHealthIndicatorConfiguration {
+
+ @Autowired
+ private HealthAggregator healthAggregator;
+
+ @Autowired(required = false)
+ private Map connectionFactories;
+
+ @Bean
+ @ConditionalOnMissingBean(name = "jmsHealthIndicator")
+ public HealthIndicator jmsHealthIndicator() {
+ if (this.connectionFactories.size() == 1) {
+ ConnectionFactory connectionFactory = this.connectionFactories.values()
+ .iterator().next();
+ return createJmsHealthIndicator(connectionFactory);
+ }
+ CompositeHealthIndicator composite = new CompositeHealthIndicator(
+ this.healthAggregator);
+ for (Map.Entry entry : this.connectionFactories
+ .entrySet()) {
+ String name = entry.getKey();
+ ConnectionFactory connectionFactory = entry.getValue();
+ composite.addHealthIndicator(name, createJmsHealthIndicator(connectionFactory));
+ }
+ return composite;
+ }
+
+ private JmsHealthIndicator createJmsHealthIndicator(
+ ConnectionFactory connectionFactory) {
+ return new JmsHealthIndicator(connectionFactory);
+ }
+ }
+
}
diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/JmsHealthIndicator.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/JmsHealthIndicator.java
new file mode 100644
index 00000000000..5f310834230
--- /dev/null
+++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/JmsHealthIndicator.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012-2015 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.health;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+
+/**
+ * {@link HealthIndicator} for a JMS {@link ConnectionFactory}.
+ *
+ * @author Stephane Nicoll
+ * @since 1.3.0
+ */
+public class JmsHealthIndicator extends AbstractHealthIndicator {
+
+ private final ConnectionFactory connectionFactory;
+
+ public JmsHealthIndicator(ConnectionFactory connectionFactory) {
+ this.connectionFactory = connectionFactory;
+ }
+
+ @Override
+ protected void doHealthCheck(Health.Builder builder) throws Exception {
+ Connection conToClose = null;
+ try {
+ conToClose = this.connectionFactory.createConnection();
+ builder.up().withDetail("provider",
+ conToClose.getMetaData().getJMSProviderName());
+ } finally {
+ if (conToClose != null) {
+ conToClose.close();
+ }
+ }
+ }
+
+}
diff --git a/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index 9f4510dd870..c4a99c96466 100644
--- a/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-boot-actuator/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -34,6 +34,12 @@
"description": "Enable disk space health check.",
"defaultValue": true
},
+ {
+ "name": "management.health.jms.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable JMS health check.",
+ "defaultValue": true
+ },
{
"name": "management.health.mongo.enabled",
"type": "java.lang.Boolean",
diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java
index c3428977050..f3a0ee60569 100644
--- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java
+++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java
@@ -27,6 +27,7 @@ import org.springframework.boot.actuate.health.ApplicationHealthIndicator;
import org.springframework.boot.actuate.health.DataSourceHealthIndicator;
import org.springframework.boot.actuate.health.DiskSpaceHealthIndicator;
import org.springframework.boot.actuate.health.HealthIndicator;
+import org.springframework.boot.actuate.health.JmsHealthIndicator;
import org.springframework.boot.actuate.health.MailHealthIndicator;
import org.springframework.boot.actuate.health.MongoHealthIndicator;
import org.springframework.boot.actuate.health.RabbitHealthIndicator;
@@ -38,6 +39,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration;
import org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration;
+import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration;
@@ -56,6 +58,7 @@ import static org.junit.Assert.assertEquals;
* Tests for {@link HealthIndicatorAutoConfiguration}.
*
* @author Christian Dupuis
+ * @author Stephane Nicoll
*/
public class HealthIndicatorAutoConfigurationTests {
@@ -340,4 +343,37 @@ public class HealthIndicatorAutoConfigurationTests {
.getClass());
}
+ @Test
+ public void jmsHealthIndicator() {
+ this.context = new AnnotationConfigApplicationContext();
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "management.health.diskspace.enabled:false");
+ this.context.register(ActiveMQAutoConfiguration.class,
+ ManagementServerProperties.class, HealthIndicatorAutoConfiguration.class);
+ this.context.refresh();
+
+ Map beans = this.context
+ .getBeansOfType(HealthIndicator.class);
+ assertEquals(1, beans.size());
+ assertEquals(JmsHealthIndicator.class, beans.values().iterator().next()
+ .getClass());
+ }
+
+ @Test
+ public void notJmsHealthIndicator() {
+ this.context = new AnnotationConfigApplicationContext();
+ EnvironmentTestUtils.addEnvironment(this.context,
+ "management.health.jms.enabled:false",
+ "management.health.diskspace.enabled:false");
+ this.context.register(ActiveMQAutoConfiguration.class,
+ ManagementServerProperties.class, HealthIndicatorAutoConfiguration.class);
+ this.context.refresh();
+
+ Map beans = this.context
+ .getBeansOfType(HealthIndicator.class);
+ assertEquals(1, beans.size());
+ assertEquals(ApplicationHealthIndicator.class, beans.values().iterator().next()
+ .getClass());
+ }
+
}
diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/JmsHealthIndicatorTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/JmsHealthIndicatorTests.java
new file mode 100644
index 00000000000..1fabdbfc0e9
--- /dev/null
+++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/JmsHealthIndicatorTests.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-2015 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.health;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.ConnectionMetaData;
+import javax.jms.JMSException;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link JmsHealthIndicator}.
+ *
+ * @author Stephane Nicoll
+ */
+public class JmsHealthIndicatorTests {
+
+ @Test
+ public void jmsBrokerIsUp() throws JMSException {
+ ConnectionMetaData connectionMetaData = mock(ConnectionMetaData.class);
+ when(connectionMetaData.getJMSProviderName()).thenReturn("JMS test provider");
+ Connection connection = mock(Connection.class);
+ when(connection.getMetaData()).thenReturn(connectionMetaData);
+ ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
+ when(connectionFactory.createConnection()).thenReturn(connection);
+
+ JmsHealthIndicator indicator = new JmsHealthIndicator(connectionFactory);
+ Health health = indicator.health();
+ assertEquals(Status.UP, health.getStatus());
+ assertEquals("JMS test provider", health.getDetails().get("provider"));
+ verify(connection, times(1)).close();
+ }
+
+ @Test
+ public void jmsBrokerIsDown() throws JMSException {
+ ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
+ when(connectionFactory.createConnection()).thenThrow(new JMSException("test", "123"));
+ JmsHealthIndicator indicator = new JmsHealthIndicator(connectionFactory);
+ Health health = indicator.health();
+ assertEquals(Status.DOWN, health.getStatus());
+ assertEquals(null, health.getDetails().get("provider"));
+ }
+
+ @Test
+ public void jmsBrokerCouldNotRetrieveProviderMetadata() throws JMSException {
+ ConnectionMetaData connectionMetaData = mock(ConnectionMetaData.class);
+ when(connectionMetaData.getJMSProviderName()).thenThrow(new JMSException("test", "123"));
+ Connection connection = mock(Connection.class);
+ when(connection.getMetaData()).thenReturn(connectionMetaData);
+ ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
+ when(connectionFactory.createConnection()).thenReturn(connection);
+
+ JmsHealthIndicator indicator = new JmsHealthIndicator(connectionFactory);
+ Health health = indicator.health();
+ assertEquals(Status.DOWN, health.getStatus());
+ assertEquals(null, health.getDetails().get("provider"));
+ verify(connection, times(1)).close();
+ }
+
+}