From b39c59e97a622984f3e71c0df55d9a4bd27e2e3e Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Sun, 25 Jun 2017 12:45:55 -0700 Subject: [PATCH 1/4] Add missing whitespace in log Closes gh-9597 --- .../springframework/boot/devtools/restart/ChangeableUrls.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/ChangeableUrls.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/ChangeableUrls.java index c6061f93a3..f43b065a93 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/ChangeableUrls.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/ChangeableUrls.java @@ -147,7 +147,7 @@ final class ChangeableUrls implements Iterable { urls.add(referenced.toURI().toURL()); } else { - System.err.println("Ignoring Class-Path entry " + entry + " found in" + System.err.println("Ignoring Class-Path entry " + entry + " found in " + jarFile.getName() + " as " + referenced + " does not exist"); } From 3b0cbea6826cf8814fc8762ab2a24b1431ddfe56 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 26 Jun 2017 09:07:07 +0200 Subject: [PATCH 2/4] Remove dead code --- .../jdbc/DataSourceAutoConfiguration.java | 27 ------------------- .../jdbc/DataSourceInitializer.java | 1 - 2 files changed, 28 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java index bc8c23f4c9..45e68f59d6 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java @@ -19,13 +19,7 @@ package org.springframework.boot.autoconfigure.jdbc; import javax.sql.DataSource; import javax.sql.XADataSource; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; import org.springframework.boot.autoconfigure.condition.ConditionMessage; @@ -63,9 +57,6 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; @Import({ Registrar.class, DataSourcePoolMetadataProvidersConfiguration.class }) public class DataSourceAutoConfiguration { - private static final Log logger = LogFactory - .getLog(DataSourceAutoConfiguration.class); - @Bean @ConditionalOnMissingBean public DataSourceInitializer dataSourceInitializer(DataSourceProperties properties, @@ -73,24 +64,6 @@ public class DataSourceAutoConfiguration { return new DataSourceInitializer(properties, applicationContext); } - /** - * Determines if the {@code dataSource} being used by Spring was created from - * {@link EmbeddedDataSourceConfiguration}. - * @param beanFactory the bean factory - * @return true if the data source was auto-configured. - */ - public static boolean containsAutoConfiguredDataSource( - ConfigurableListableBeanFactory beanFactory) { - try { - BeanDefinition beanDefinition = beanFactory.getBeanDefinition("dataSource"); - return EmbeddedDataSourceConfiguration.class.getName() - .equals(beanDefinition.getFactoryBeanName()); - } - catch (NoSuchBeanDefinitionException ex) { - return false; - } - } - @Configuration @Conditional(EmbeddedDatabaseCondition.class) @ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializer.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializer.java index 54e064851b..f62b23806c 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializer.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializer.java @@ -45,7 +45,6 @@ import org.springframework.util.StringUtils; * @author Eddú Meléndez * @author Stephane Nicoll * @author Kazuki Shimizu - * @since 1.1.0 * @see DataSourceAutoConfiguration */ class DataSourceInitializer implements ApplicationListener { From 4c97dcb53ae0a7cba4859ba60af2bf6474bad39f Mon Sep 17 00:00:00 2001 From: Eric Spiegelberg Date: Mon, 19 Jun 2017 19:54:16 -0500 Subject: [PATCH 3/4] Add health indicator for Neo4j See gh-9557 --- .../HealthIndicatorAutoConfiguration.java | 28 ++++- .../actuate/health/Neo4jHealthIndicator.java | 64 +++++++++++ ...itional-spring-configuration-metadata.json | 6 ++ ...HealthIndicatorAutoConfigurationTests.java | 41 +++++++ .../health/Neo4jHealthIndicatorTests.java | 100 ++++++++++++++++++ 5 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Neo4jHealthIndicator.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/Neo4jHealthIndicatorTests.java 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 95d7008019..6b1c5c528a 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 @@ -26,6 +26,7 @@ import javax.sql.DataSource; import com.couchbase.client.java.Bucket; import com.datastax.driver.core.Cluster; import org.apache.solr.client.solrj.SolrClient; +import org.neo4j.ogm.session.SessionFactory; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.InitializingBean; @@ -42,6 +43,7 @@ import org.springframework.boot.actuate.health.JmsHealthIndicator; import org.springframework.boot.actuate.health.LdapHealthIndicator; import org.springframework.boot.actuate.health.MailHealthIndicator; import org.springframework.boot.actuate.health.MongoHealthIndicator; +import org.springframework.boot.actuate.health.Neo4jHealthIndicator; import org.springframework.boot.actuate.health.OrderedHealthAggregator; import org.springframework.boot.actuate.health.RabbitHealthIndicator; import org.springframework.boot.actuate.health.RedisHealthIndicator; @@ -59,6 +61,7 @@ import org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoCo import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration; import org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration; import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; +import org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; @@ -91,6 +94,7 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; * @author Phillip Webb * @author Tommy Ludwig * @author Eddú Meléndez + * @author Eric Spiegelberg * @since 1.1.0 */ @Configuration @@ -102,7 +106,7 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; LdapDataAutoConfiguration.class, MailSenderAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class, RabbitAutoConfiguration.class, RedisAutoConfiguration.class, - SolrAutoConfiguration.class }) + SolrAutoConfiguration.class, Neo4jDataAutoConfiguration.class }) @EnableConfigurationProperties({ HealthIndicatorProperties.class }) @Import({ ElasticsearchHealthIndicatorConfiguration.ElasticsearchClientHealthIndicatorConfiguration.class, @@ -257,6 +261,28 @@ public class HealthIndicatorAutoConfiguration { } + @Configuration + @ConditionalOnClass(SessionFactory.class) + @ConditionalOnBean(SessionFactory.class) + @ConditionalOnEnabledHealthIndicator("neo4j") + public static class Neo4jHealthIndicatorConfiguration extends + CompositeHealthIndicatorConfiguration { + + private final Map sessionFactories; + + public Neo4jHealthIndicatorConfiguration( + Map sessionFactories) { + this.sessionFactories = sessionFactories; + } + + @Bean + @ConditionalOnMissingBean(name = "neo4jHealthIndicator") + public HealthIndicator neo4jHealthIndicator() { + return createHealthIndicator(this.sessionFactories); + } + + } + @Configuration @ConditionalOnBean(MongoTemplate.class) @ConditionalOnEnabledHealthIndicator("mongo") diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Neo4jHealthIndicator.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Neo4jHealthIndicator.java new file mode 100644 index 0000000000..3292bc9577 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Neo4jHealthIndicator.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2017 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 java.util.Collections; +import java.util.Map; + +import org.neo4j.ogm.model.Result; +import org.neo4j.ogm.session.Session; +import org.neo4j.ogm.session.SessionFactory; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * {@link HealthIndicator} that tests the status of a Neo4j by executing a Cypher + * statement. + * + * @author Eric Spiegelberg + */ +@ConfigurationProperties(prefix = "management.health.neo4j", ignoreUnknownFields = false) +public class Neo4jHealthIndicator extends AbstractHealthIndicator { + + private final SessionFactory sessionFactory; + + /** + * The Cypher statement used to verify Neo4j is up. + */ + public static final String CYPHER = "match (n) return count(n) as nodes"; + + /** + * Create a new {@link Neo4jHealthIndicator} using the specified + * {@link SessionFactory}. + * @param sessionFactory the SessionFactory + */ + public Neo4jHealthIndicator(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + @Override + protected void doHealthCheck(Health.Builder builder) throws Exception { + Session session = this.sessionFactory.openSession(); + + Result result = session.query(CYPHER, Collections.emptyMap()); + Iterable> results = result.queryResults(); + int nodes = (int) results.iterator().next().get("nodes"); + + builder.up().withDetail("nodes", nodes); + } + +} 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 4ad754d369..4e7549cbb2 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 @@ -181,6 +181,12 @@ "description": "Enable Mail health check.", "defaultValue": true }, + { + "name": "management.health.neo4j.enabled", + "type": "java.lang.Boolean", + "description": "Enable Neo4j health check.", + "defaultValue": true + }, { "name": "management.info.build.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 98bc14741b..1da53430f0 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 @@ -23,6 +23,7 @@ import javax.sql.DataSource; import io.searchbox.client.JestClient; import org.junit.After; import org.junit.Test; +import org.neo4j.ogm.session.SessionFactory; import org.springframework.boot.actuate.health.ApplicationHealthIndicator; import org.springframework.boot.actuate.health.CassandraHealthIndicator; @@ -38,6 +39,7 @@ import org.springframework.boot.actuate.health.JmsHealthIndicator; import org.springframework.boot.actuate.health.LdapHealthIndicator; import org.springframework.boot.actuate.health.MailHealthIndicator; import org.springframework.boot.actuate.health.MongoHealthIndicator; +import org.springframework.boot.actuate.health.Neo4jHealthIndicator; import org.springframework.boot.actuate.health.RabbitHealthIndicator; import org.springframework.boot.actuate.health.RedisHealthIndicator; import org.springframework.boot.actuate.health.SolrHealthIndicator; @@ -76,6 +78,7 @@ import static org.mockito.Mockito.mock; * @author Stephane Nicoll * @author Andy Wilkinson * @author Eddú Meléndez + * @author Eric Spiegelberg */ public class HealthIndicatorAutoConfigurationTests { @@ -578,6 +581,34 @@ public class HealthIndicatorAutoConfigurationTests { .isEqualTo(ApplicationHealthIndicator.class); } + @Test + public void neo4jHealthIndicator() throws Exception { + TestPropertyValues.of("management.health.diskspace.enabled:false") + .applyTo(this.context); + this.context.register(Neo4jConfiguration.class, ManagementServerProperties.class, + HealthIndicatorAutoConfiguration.class); + this.context.refresh(); + Map beans = this.context + .getBeansOfType(HealthIndicator.class); + assertThat(beans.size()).isEqualTo(1); + assertThat(beans.values().iterator().next().getClass()) + .isEqualTo(Neo4jHealthIndicator.class); + } + + @Test + public void notNeo4jHealthIndicator() throws Exception { + TestPropertyValues.of("management.health.diskspace.enabled:false", + "management.health.neo4j.enabled:false").applyTo(this.context); + this.context.register(Neo4jConfiguration.class, ManagementServerProperties.class, + HealthIndicatorAutoConfiguration.class); + this.context.refresh(); + Map beans = this.context + .getBeansOfType(HealthIndicator.class); + assertThat(beans.size()).isEqualTo(1); + assertThat(beans.values().iterator().next().getClass()) + .isEqualTo(ApplicationHealthIndicator.class); + } + @Configuration @EnableConfigurationProperties protected static class DataSourceConfig { @@ -659,4 +690,14 @@ public class HealthIndicatorAutoConfigurationTests { } + @Configuration + protected static class Neo4jConfiguration { + + @Bean + public SessionFactory sessionFactory() { + return mock(SessionFactory.class); + } + + } + } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/Neo4jHealthIndicatorTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/Neo4jHealthIndicatorTests.java new file mode 100644 index 0000000000..fa4983e417 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/Neo4jHealthIndicatorTests.java @@ -0,0 +1,100 @@ +/* + * Copyright 2012-2017 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 java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.neo4j.ogm.exception.CypherException; +import org.neo4j.ogm.model.Result; +import org.neo4j.ogm.session.Session; +import org.neo4j.ogm.session.SessionFactory; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link Neo4jHealthIndicator}. + * + * @author Eric Spiegelberg + */ +public class Neo4jHealthIndicatorTests { + + private Result result; + private Session session; + private SessionFactory sessionFactory; + + private Neo4jHealthIndicator neo4jHealthIndicator; + + private Map emptyParameters = new HashMap<>(); + + @Before + public void before() { + this.result = mock(Result.class); + this.session = mock(Session.class); + this.sessionFactory = mock(SessionFactory.class); + + given(this.sessionFactory.openSession()).willReturn(this.session); + + this.neo4jHealthIndicator = new Neo4jHealthIndicator(this.sessionFactory); + } + + @Test + public void neo4jUp() { + given(this.session.query(Neo4jHealthIndicator.CYPHER, this.emptyParameters)) + .willReturn(this.result); + + int nodeCount = 500; + Map expectedCypherDetails = new HashMap<>(); + expectedCypherDetails.put("nodes", nodeCount); + + List> queryResults = new ArrayList<>(); + queryResults.add(expectedCypherDetails); + + given(this.result.queryResults()).willReturn(queryResults); + + Health health = this.neo4jHealthIndicator.health(); + assertThat(health.getStatus()).isEqualTo(Status.UP); + + Map details = health.getDetails(); + int nodeCountFromDetails = (int) details.get("nodes"); + + Assert.assertEquals(nodeCount, nodeCountFromDetails); + + } + + @Test + public void neo4jDown() { + + CypherException cypherException = new CypherException("Error executing Cypher", + "Neo.ClientError.Statement.SyntaxError", + "Unable to execute invalid Cypher"); + + given(this.session.query(Neo4jHealthIndicator.CYPHER, this.emptyParameters)) + .willThrow(cypherException); + + Health health = this.neo4jHealthIndicator.health(); + assertThat(health.getStatus()).isEqualTo(Status.DOWN); + } + +} From 01272fa0cc9d51ed93f9b6c76af141adfff2f8ff Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 26 Jun 2017 11:04:34 +0200 Subject: [PATCH 4/4] Polish "Add health indicator for Neo4j" Closes gh-9557 --- .../HealthIndicatorAutoConfiguration.java | 46 +++++++++---------- .../actuate/health/Neo4jHealthIndicator.java | 12 ++--- .../health/Neo4jHealthIndicatorTests.java | 30 ++++-------- .../appendix-application-properties.adoc | 1 + 4 files changed, 39 insertions(+), 50 deletions(-) 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 6b1c5c528a..834b7e4804 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 @@ -105,8 +105,8 @@ import org.springframework.mail.javamail.JavaMailSenderImpl; JestAutoConfiguration.class, JmsAutoConfiguration.class, LdapDataAutoConfiguration.class, MailSenderAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class, - RabbitAutoConfiguration.class, RedisAutoConfiguration.class, - SolrAutoConfiguration.class, Neo4jDataAutoConfiguration.class }) + Neo4jDataAutoConfiguration.class, RabbitAutoConfiguration.class, + RedisAutoConfiguration.class, SolrAutoConfiguration.class }) @EnableConfigurationProperties({ HealthIndicatorProperties.class }) @Import({ ElasticsearchHealthIndicatorConfiguration.ElasticsearchClientHealthIndicatorConfiguration.class, @@ -261,6 +261,27 @@ public class HealthIndicatorAutoConfiguration { } + @Configuration + @ConditionalOnBean(MongoTemplate.class) + @ConditionalOnEnabledHealthIndicator("mongo") + public static class MongoHealthIndicatorConfiguration extends + CompositeHealthIndicatorConfiguration { + + private final Map mongoTemplates; + + public MongoHealthIndicatorConfiguration( + Map mongoTemplates) { + this.mongoTemplates = mongoTemplates; + } + + @Bean + @ConditionalOnMissingBean(name = "mongoHealthIndicator") + public HealthIndicator mongoHealthIndicator() { + return createHealthIndicator(this.mongoTemplates); + } + + } + @Configuration @ConditionalOnClass(SessionFactory.class) @ConditionalOnBean(SessionFactory.class) @@ -283,27 +304,6 @@ public class HealthIndicatorAutoConfiguration { } - @Configuration - @ConditionalOnBean(MongoTemplate.class) - @ConditionalOnEnabledHealthIndicator("mongo") - public static class MongoHealthIndicatorConfiguration extends - CompositeHealthIndicatorConfiguration { - - private final Map mongoTemplates; - - public MongoHealthIndicatorConfiguration( - Map mongoTemplates) { - this.mongoTemplates = mongoTemplates; - } - - @Bean - @ConditionalOnMissingBean(name = "mongoHealthIndicator") - public HealthIndicator mongoHealthIndicator() { - return createHealthIndicator(this.mongoTemplates); - } - - } - @Configuration @ConditionalOnBean(RedisConnectionFactory.class) @ConditionalOnEnabledHealthIndicator("redis") diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Neo4jHealthIndicator.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Neo4jHealthIndicator.java index 3292bc9577..3bc5e87497 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Neo4jHealthIndicator.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/Neo4jHealthIndicator.java @@ -23,23 +23,21 @@ import org.neo4j.ogm.model.Result; import org.neo4j.ogm.session.Session; import org.neo4j.ogm.session.SessionFactory; -import org.springframework.boot.context.properties.ConfigurationProperties; - /** * {@link HealthIndicator} that tests the status of a Neo4j by executing a Cypher * statement. * * @author Eric Spiegelberg + * @since 2.0.0 */ -@ConfigurationProperties(prefix = "management.health.neo4j", ignoreUnknownFields = false) public class Neo4jHealthIndicator extends AbstractHealthIndicator { - private final SessionFactory sessionFactory; - /** * The Cypher statement used to verify Neo4j is up. */ - public static final String CYPHER = "match (n) return count(n) as nodes"; + static final String CYPHER = "match (n) return count(n) as nodes"; + + private final SessionFactory sessionFactory; /** * Create a new {@link Neo4jHealthIndicator} using the specified @@ -54,7 +52,7 @@ public class Neo4jHealthIndicator extends AbstractHealthIndicator { protected void doHealthCheck(Health.Builder builder) throws Exception { Session session = this.sessionFactory.openSession(); - Result result = session.query(CYPHER, Collections.emptyMap()); + Result result = session.query(CYPHER, Collections.EMPTY_MAP); Iterable> results = result.queryResults(); int nodes = (int) results.iterator().next().get("nodes"); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/Neo4jHealthIndicatorTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/Neo4jHealthIndicatorTests.java index fa4983e417..b9c253e11d 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/Neo4jHealthIndicatorTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/Neo4jHealthIndicatorTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.actuate.health; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -37,60 +38,49 @@ import static org.mockito.Mockito.mock; * Tests for {@link Neo4jHealthIndicator}. * * @author Eric Spiegelberg + * @author Stephane Nicoll */ public class Neo4jHealthIndicatorTests { - private Result result; private Session session; - private SessionFactory sessionFactory; private Neo4jHealthIndicator neo4jHealthIndicator; - private Map emptyParameters = new HashMap<>(); - @Before public void before() { - this.result = mock(Result.class); this.session = mock(Session.class); - this.sessionFactory = mock(SessionFactory.class); - - given(this.sessionFactory.openSession()).willReturn(this.session); - - this.neo4jHealthIndicator = new Neo4jHealthIndicator(this.sessionFactory); + SessionFactory sessionFactory = mock(SessionFactory.class); + given(sessionFactory.openSession()).willReturn(this.session); + this.neo4jHealthIndicator = new Neo4jHealthIndicator(sessionFactory); } @Test public void neo4jUp() { - given(this.session.query(Neo4jHealthIndicator.CYPHER, this.emptyParameters)) - .willReturn(this.result); + Result result = mock(Result.class); + given(this.session.query(Neo4jHealthIndicator.CYPHER, Collections.EMPTY_MAP)) + .willReturn(result); int nodeCount = 500; Map expectedCypherDetails = new HashMap<>(); expectedCypherDetails.put("nodes", nodeCount); - List> queryResults = new ArrayList<>(); queryResults.add(expectedCypherDetails); - - given(this.result.queryResults()).willReturn(queryResults); + given(result.queryResults()).willReturn(queryResults); Health health = this.neo4jHealthIndicator.health(); assertThat(health.getStatus()).isEqualTo(Status.UP); - Map details = health.getDetails(); int nodeCountFromDetails = (int) details.get("nodes"); Assert.assertEquals(nodeCount, nodeCountFromDetails); - } @Test public void neo4jDown() { - CypherException cypherException = new CypherException("Error executing Cypher", "Neo.ClientError.Statement.SyntaxError", "Unable to execute invalid Cypher"); - - given(this.session.query(Neo4jHealthIndicator.CYPHER, this.emptyParameters)) + given(this.session.query(Neo4jHealthIndicator.CYPHER, Collections.EMPTY_MAP)) .willThrow(cypherException); Health health = this.neo4jHealthIndicator.health(); diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 7b4f2c8db1..fb06267013 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -1214,6 +1214,7 @@ content into your application; rather pick only the properties that you need. management.health.ldap.enabled=true # Enable LDAP health check. management.health.mail.enabled=true # Enable Mail health check. management.health.mongo.enabled=true # Enable MongoDB health check. + management.health.neo4j.enabled=true # Enable Neo4j health check. management.health.rabbit.enabled=true # Enable RabbitMQ health check. management.health.redis.enabled=true # Enable Redis health check. management.health.solr.enabled=true # Enable Solr health check.