From a1cbd93d6b02b7d1e18e67f5199fca7100a9acd2 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 10 Feb 2015 21:14:19 -0800 Subject: [PATCH] Ensure local Elasticsearch nodes are closed Update ElasticsearchAutoConfiguration to ensure that local nodes are closed when the context is closed. Prior to this commit the close() method of the Client would be called which had no effect for local Nodes. Fixes gh-2480 --- .../ElasticsearchAutoConfiguration.java | 41 +++++++++++++------ .../SampleElasticsearchApplication.java | 4 +- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchAutoConfiguration.java index d115b76310b..51931ec1cc2 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * 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. @@ -19,6 +19,11 @@ package org.springframework.boot.autoconfigure.elasticsearch; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.elasticsearch.client.Client; +import org.elasticsearch.client.transport.TransportClient; +import org.elasticsearch.common.lease.Releasable; +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.node.Node; +import org.elasticsearch.node.NodeBuilder; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -27,6 +32,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.client.NodeClientFactoryBean; import org.springframework.data.elasticsearch.client.TransportClientFactoryBean; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; /** @@ -49,13 +55,12 @@ public class ElasticsearchAutoConfiguration implements DisposableBean { @Autowired private ElasticsearchProperties properties; - private Client client; + private Releasable releasable; @Bean public Client elasticsearchClient() { try { - this.client = createClient(); - return this.client; + return createClient(); } catch (Exception ex) { throw new IllegalStateException(ex); @@ -70,10 +75,12 @@ public class ElasticsearchAutoConfiguration implements DisposableBean { } private Client createNodeClient() throws Exception { - NodeClientFactoryBean factory = new NodeClientFactoryBean(true); - factory.setClusterName(this.properties.getClusterName()); - factory.afterPropertiesSet(); - return factory.getObject(); + ImmutableSettings.Builder settings = ImmutableSettings.settingsBuilder().put( + "http.enabled", String.valueOf(false)); + Node node = new NodeBuilder().settings(settings) + .clusterName(this.properties.getClusterName()).local(true).node(); + this.releasable = node; + return node.client(); } private Client createTransportClient() throws Exception { @@ -81,18 +88,28 @@ public class ElasticsearchAutoConfiguration implements DisposableBean { factory.setClusterName(this.properties.getClusterName()); factory.setClusterNodes(this.properties.getClusterNodes()); factory.afterPropertiesSet(); - return factory.getObject(); + TransportClient client = factory.getObject(); + this.releasable = client; + return client; } @Override public void destroy() throws Exception { - if (this.client != null) { + if (this.releasable != null) { try { if (logger.isInfoEnabled()) { logger.info("Closing Elasticsearch client"); } - if (this.client != null) { - this.client.close(); + if (this.releasable != null) { + try { + this.releasable.close(); + } + catch (NoSuchMethodError ex) { + // Earlier versions of Elasticsearch had a different method name + ReflectionUtils.invokeMethod( + ReflectionUtils.findMethod(Releasable.class, "release"), + this.releasable); + } } } catch (final Exception ex) { diff --git a/spring-boot-samples/spring-boot-sample-data-elasticsearch/src/main/java/sample/data/elasticsearch/SampleElasticsearchApplication.java b/spring-boot-samples/spring-boot-sample-data-elasticsearch/src/main/java/sample/data/elasticsearch/SampleElasticsearchApplication.java index 969d0b7525a..002e9df81c4 100644 --- a/spring-boot-samples/spring-boot-sample-data-elasticsearch/src/main/java/sample/data/elasticsearch/SampleElasticsearchApplication.java +++ b/spring-boot-samples/spring-boot-sample-data-elasticsearch/src/main/java/sample/data/elasticsearch/SampleElasticsearchApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * 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. @@ -62,6 +62,6 @@ public class SampleElasticsearchApplication implements CommandLineRunner { } public static void main(String[] args) throws Exception { - SpringApplication.run(SampleElasticsearchApplication.class, "--debug"); + SpringApplication.run(SampleElasticsearchApplication.class, "--debug").close(); } }