Drop support for auto-configuring an embedded Elasticsearch node

Elastic have announced [1] that embedded Elasticsearch is no longer
supported. This commit brings us into line with that announcement by
removing the auto-configuration that would create an Elasticsearch
Node and NodeClient.

To use the Elasticsearch auto-configuration, a user must now provide
the address of one or more cluster nodes
(via the spring.elastisearch.cluster-nodes property) which will then
be used to create a TransportClient.

See gh-9374

[1] https://www.elastic.co/blog/elasticsearch-the-server
This commit is contained in:
Andy Wilkinson
2017-06-15 16:29:46 +01:00
parent dbabfc224c
commit 4a030d5a7a
13 changed files with 268 additions and 354 deletions

View File

@@ -16,34 +16,18 @@
package org.springframework.boot.autoconfigure.data.elasticsearch;
import java.io.Closeable;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
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.settings.Settings;
import org.elasticsearch.node.InternalSettingsPreparer;
import org.elasticsearch.node.Node;
import org.elasticsearch.plugins.Plugin;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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.ClassUtils;
import org.springframework.util.StringUtils;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
@@ -55,101 +39,25 @@ import org.springframework.util.StringUtils;
* @since 1.1.0
*/
@Configuration
@ConditionalOnClass({ Client.class, TransportClientFactoryBean.class,
NodeClientFactoryBean.class })
@ConditionalOnClass({ Client.class, TransportClientFactoryBean.class })
@ConditionalOnProperty(prefix = "spring.data.elasticsearch", name = "cluster-nodes", matchIfMissing = false)
@EnableConfigurationProperties(ElasticsearchProperties.class)
public class ElasticsearchAutoConfiguration implements DisposableBean {
private static final Map<String, String> DEFAULTS;
static {
Map<String, String> defaults = new LinkedHashMap<>();
defaults.put("http.enabled", String.valueOf(false));
defaults.put("transport.type", "local");
defaults.put("path.home", System.getProperty("user.dir"));
DEFAULTS = Collections.unmodifiableMap(defaults);
}
private static final Set<String> TRANSPORT_PLUGINS;
static {
Set<String> plugins = new LinkedHashSet<>();
plugins.add("org.elasticsearch.transport.Netty4Plugin");
plugins.add("org.elasticsearch.transport.Netty3Plugin");
TRANSPORT_PLUGINS = Collections.unmodifiableSet(plugins);
}
private static final Log logger = LogFactory
.getLog(ElasticsearchAutoConfiguration.class);
public class ElasticsearchAutoConfiguration {
private final ElasticsearchProperties properties;
private Closeable closeable;
public ElasticsearchAutoConfiguration(ElasticsearchProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean
public Client elasticsearchClient() {
try {
return createClient();
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
private Client createClient() throws Exception {
if (StringUtils.hasLength(this.properties.getClusterNodes())) {
return createTransportClient();
}
return createNodeClient();
}
private Client createNodeClient() throws Exception {
Settings.Builder settings = Settings.builder();
for (Map.Entry<String, String> entry : DEFAULTS.entrySet()) {
if (!this.properties.getProperties().containsKey(entry.getKey())) {
settings.put(entry.getKey(), entry.getValue());
}
}
settings.put(this.properties.getProperties());
settings.put("cluster.name", this.properties.getClusterName());
Node node = createNode(settings.build());
this.closeable = node;
node.start();
return node.client();
}
private Node createNode(Settings settings) {
Collection<Class<? extends Plugin>> plugins = findPlugins();
if (plugins.isEmpty()) {
return new Node(settings);
}
return new PluggableNode(settings, plugins);
}
@SuppressWarnings("unchecked")
private Collection<Class<? extends Plugin>> findPlugins() {
for (String candidate : TRANSPORT_PLUGINS) {
if (ClassUtils.isPresent(candidate, null)) {
Class<? extends Plugin> pluginClass = (Class<? extends Plugin>) ClassUtils
.resolveClassName(candidate, null);
return Collections.singleton(pluginClass);
}
}
return Collections.emptySet();
}
private Client createTransportClient() throws Exception {
public TransportClient elasticsearchClient() throws Exception {
TransportClientFactoryBean factory = new TransportClientFactoryBean();
factory.setClusterNodes(this.properties.getClusterNodes());
factory.setProperties(createProperties());
factory.afterPropertiesSet();
TransportClient client = factory.getObject();
this.closeable = client;
return client;
}
@@ -160,34 +68,4 @@ public class ElasticsearchAutoConfiguration implements DisposableBean {
return properties;
}
@Override
public void destroy() throws Exception {
if (this.closeable != null) {
try {
if (logger.isInfoEnabled()) {
logger.info("Closing Elasticsearch client");
}
this.closeable.close();
}
catch (final Exception ex) {
if (logger.isErrorEnabled()) {
logger.error("Error closing Elasticsearch client: ", ex);
}
}
}
}
/**
* {@link Node} subclass to support {@link Plugin Plugins}.
*/
private static class PluggableNode extends Node {
PluggableNode(Settings preparedSettings,
Collection<Class<? extends Plugin>> classpathPlugins) {
super(InternalSettingsPreparer.prepareEnvironment(preparedSettings, null),
classpathPlugins);
}
}
}

View File

@@ -37,8 +37,7 @@ public class ElasticsearchProperties {
private String clusterName = "elasticsearch";
/**
* Comma-separated list of cluster node addresses. If not specified, starts a client
* node.
* Comma-separated list of cluster node addresses.
*/
private String clusterNodes;

View File

@@ -230,6 +230,10 @@ public class SpringBootWebSecurityConfiguration {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.requestMatchers(
(request) -> request.getHeader("Host").equals("whatever"))
.permitAll();
http.requestMatcher(new RequestMatcher() {
@Override
public boolean matches(HttpServletRequest request) {

View File

@@ -16,15 +16,17 @@
package org.springframework.boot.autoconfigure.data.elasticsearch;
import java.util.List;
import org.assertj.core.api.Assertions;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -38,6 +40,7 @@ import static org.mockito.Mockito.mock;
* Tests for {@link ElasticsearchAutoConfiguration}.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
public class ElasticsearchAutoConfigurationTests {
@@ -46,57 +49,11 @@ public class ElasticsearchAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
@Before
public void preventElasticsearchFromConfiguringNetty() {
System.setProperty("es.set.netty.runtime.available.processors", "false");
}
@After
public void close() {
if (this.context != null) {
this.context.close();
}
System.clearProperty("es.set.netty.runtime.available.processors");
}
@Test
public void createNodeClientWithDefaults() {
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues
.of("spring.data.elasticsearch.properties.monitor.process.refresh_interval:2s",
"spring.data.elasticsearch.properties.path.home:target")
.applyTo(this.context);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
ElasticsearchAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(Client.class).length).isEqualTo(1);
NodeClient client = (NodeClient) this.context.getBean(Client.class);
assertThat(client.settings().get("monitor.process.refresh_interval"))
.isEqualTo("2s");
assertThat(client.settings().get("transport.type")).isEqualTo("local");
assertThat(client.settings().get("http.enabled")).isEqualTo("false");
}
@Test
public void createNodeClientWithOverrides() {
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues
.of("spring.data.elasticsearch.properties.monitor.process.refresh_interval:2s",
"spring.data.elasticsearch.properties.path.home:target",
"spring.data.elasticsearch.properties.transport.type:local",
"spring.data.elasticsearch.properties.node.data:true",
"spring.data.elasticsearch.properties.http.enabled:true")
.applyTo(this.context);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
ElasticsearchAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(Client.class).length).isEqualTo(1);
NodeClient client = (NodeClient) this.context.getBean(Client.class);
assertThat(client.settings().get("monitor.process.refresh_interval"))
.isEqualTo("2s");
assertThat(client.settings().get("transport.type")).isEqualTo("local");
assertThat(client.settings().get("node.data")).isEqualTo("true");
assertThat(client.settings().get("http.enabled")).isEqualTo("true");
}
@Test
@@ -106,25 +63,28 @@ public class ElasticsearchAutoConfigurationTests {
PropertyPlaceholderAutoConfiguration.class,
ElasticsearchAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(Client.class).length).isEqualTo(1);
assertThat(this.context.getBean("myClient"))
Assertions.assertThat(this.context.getBeanNamesForType(Client.class).length)
.isEqualTo(1);
Assertions.assertThat(this.context.getBean("myClient"))
.isSameAs(this.context.getBean(Client.class));
}
@Test
public void createTransportClient() throws Exception {
// We don't have a local elasticsearch server so use an address that's missing
// a port and check the exception
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues
.of("spring.data.elasticsearch.cluster-nodes:localhost",
"spring.data.elasticsearch.properties.path.home:target")
.applyTo(this.context);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
ElasticsearchAutoConfiguration.class);
this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("port");
this.context.refresh();
new ElasticsearchNodeTemplate().doWithNode((node) -> {
TestPropertyValues
.of("spring.data.elasticsearch.cluster-nodes:localhost:"
+ node.getTcpPort(),
"spring.data.elasticsearch.properties.path.home:target/es/client")
.applyTo(this.context);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
ElasticsearchAutoConfiguration.class);
this.context.refresh();
List<DiscoveryNode> connectedNodes = this.context
.getBean(TransportClient.class).connectedNodes();
assertThat(connectedNodes).hasSize(1);
});
}
@Configuration

View File

@@ -48,43 +48,55 @@ public class ElasticsearchDataAutoConfigurationTests {
@Test
public void templateExists() {
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues
.of("spring.data.elasticsearch.properties.path.data:target/data",
"spring.data.elasticsearch.properties.path.logs:target/logs")
.applyTo(this.context);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
ElasticsearchAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class);
this.context.refresh();
assertHasSingleBean(ElasticsearchTemplate.class);
new ElasticsearchNodeTemplate().doWithNode((node) -> {
TestPropertyValues
.of("spring.data.elasticsearch.properties.path.data:target/data",
"spring.data.elasticsearch.properties.path.logs:target/logs",
"spring.data.elasticsearch.cluster-nodes:localhost:"
+ node.getTcpPort())
.applyTo(this.context);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
ElasticsearchAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class);
this.context.refresh();
assertHasSingleBean(ElasticsearchTemplate.class);
});
}
@Test
public void mappingContextExists() {
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues
.of("spring.data.elasticsearch.properties.path.data:target/data",
"spring.data.elasticsearch.properties.path.logs:target/logs")
.applyTo(this.context);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
ElasticsearchAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class);
this.context.refresh();
assertHasSingleBean(SimpleElasticsearchMappingContext.class);
new ElasticsearchNodeTemplate().doWithNode((node) -> {
TestPropertyValues
.of("spring.data.elasticsearch.properties.path.data:target/data",
"spring.data.elasticsearch.properties.path.logs:target/logs",
"spring.data.elasticsearch.cluster-nodes:localhost:"
+ node.getTcpPort())
.applyTo(this.context);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
ElasticsearchAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class);
this.context.refresh();
assertHasSingleBean(SimpleElasticsearchMappingContext.class);
});
}
@Test
public void converterExists() {
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues
.of("spring.data.elasticsearch.properties.path.data:target/data",
"spring.data.elasticsearch.properties.path.logs:target/logs")
.applyTo(this.context);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
ElasticsearchAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class);
this.context.refresh();
assertHasSingleBean(ElasticsearchConverter.class);
new ElasticsearchNodeTemplate().doWithNode((node) -> {
TestPropertyValues
.of("spring.data.elasticsearch.properties.path.data:target/data",
"spring.data.elasticsearch.properties.path.logs:target/logs",
"spring.data.elasticsearch.cluster-nodes:localhost:"
+ node.getTcpPort())
.applyTo(this.context);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
ElasticsearchAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class);
this.context.refresh();
assertHasSingleBean(ElasticsearchConverter.class);
});
}
private void assertHasSingleBean(Class<?> type) {

View File

@@ -0,0 +1,111 @@
/*
* 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.autoconfigure.data.elasticsearch;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.function.Consumer;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.node.InternalSettingsPreparer;
import org.elasticsearch.node.Node;
import org.elasticsearch.node.NodeValidationException;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.transport.Transport;
/**
* Helper class for managing an Elasticsearch {@link Node}.
*
* @author Andy Wilkinson
*/
public class ElasticsearchNodeTemplate {
public void doWithNode(Consumer<ElasticsearchNode> consumer) {
System.setProperty("es.set.netty.runtime.available.processors", "false");
Node node = null;
try {
node = startNode();
consumer.accept(new ElasticsearchNode(node));
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
finally {
if (node != null) {
try {
node.close();
}
catch (Exception ex) {
// Continue
}
}
System.clearProperty("es.set.netty.runtime.available.processors");
}
}
private Node startNode() throws NodeValidationException {
Node node = new NettyTransportNode();
node.start();
return node;
}
private static final class NettyTransportNode extends Node {
private NettyTransportNode() {
super(InternalSettingsPreparer.prepareEnvironment(Settings.builder()
.put("path.home", "target/es/node").put("transport.type", "netty4")
.put("http.enabled", true).put("node.portsfile", true)
.put("http.port", 0).put("transport.tcp.port", 0).build(), null),
Arrays.asList(Netty4Plugin.class));
new File("target/es/node/logs").mkdirs();
}
}
public final class ElasticsearchNode {
private final Node node;
private ElasticsearchNode(Node node) {
this.node = node;
}
public int getTcpPort() {
return this.node.injector().getInstance(Transport.class).boundAddress()
.publishAddress().getPort();
}
public int getHttpPort() {
try {
for (String line : Files
.readAllLines(Paths.get("target/es/node/logs/http.ports"))) {
if (line.startsWith("127.0.0.1")) {
return Integer.parseInt(line.substring(line.indexOf(":") + 1));
}
}
throw new IllegalStateException("HTTP port not found");
}
catch (IOException ex) {
throw new IllegalStateException("Failed to read HTTP port", ex);
}
}
}
}

View File

@@ -23,6 +23,7 @@ import org.junit.Test;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.data.alt.elasticsearch.CityElasticsearchDbRepository;
import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchNodeTemplate.ElasticsearchNode;
import org.springframework.boot.autoconfigure.data.elasticsearch.city.City;
import org.springframework.boot.autoconfigure.data.elasticsearch.city.CityRepository;
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
@@ -37,6 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link ElasticsearchRepositoriesAutoConfiguration}.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
public class ElasticsearchRepositoriesAutoConfigurationTests {
@@ -49,46 +51,45 @@ public class ElasticsearchRepositoriesAutoConfigurationTests {
@Test
public void testDefaultRepositoryConfiguration() throws Exception {
this.context = new AnnotationConfigApplicationContext();
addElasticsearchProperties(this.context);
this.context.register(TestConfiguration.class,
ElasticsearchAutoConfiguration.class,
ElasticsearchRepositoriesAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBean(CityRepository.class)).isNotNull();
assertThat(this.context.getBean(Client.class)).isNotNull();
new ElasticsearchNodeTemplate().doWithNode((node) -> {
load(TestConfiguration.class, node);
assertThat(this.context.getBean(CityRepository.class)).isNotNull();
assertThat(this.context.getBean(Client.class)).isNotNull();
});
}
@Test
public void testNoRepositoryConfiguration() throws Exception {
this.context = new AnnotationConfigApplicationContext();
addElasticsearchProperties(this.context);
this.context.register(EmptyConfiguration.class,
ElasticsearchAutoConfiguration.class,
ElasticsearchRepositoriesAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBean(Client.class)).isNotNull();
new ElasticsearchNodeTemplate().doWithNode((address) -> {
load(EmptyConfiguration.class, address);
assertThat(this.context.getBean(Client.class)).isNotNull();
});
}
@Test
public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
new ElasticsearchNodeTemplate().doWithNode((address) -> {
load(CustomizedConfiguration.class, address);
assertThat(this.context.getBean(CityElasticsearchDbRepository.class))
.isNotNull();
});
}
private void load(Class<?> config, ElasticsearchNode node) {
this.context = new AnnotationConfigApplicationContext();
addElasticsearchProperties(this.context);
this.context.register(CustomizedConfiguration.class,
ElasticsearchAutoConfiguration.class,
addElasticsearchProperties(this.context, node);
this.context.register(config, ElasticsearchAutoConfiguration.class,
ElasticsearchRepositoriesAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBean(CityElasticsearchDbRepository.class)).isNotNull();
}
private void addElasticsearchProperties(AnnotationConfigApplicationContext context) {
TestPropertyValues.of("spring.data.elasticsearch.properties.path.home:target")
private void addElasticsearchProperties(AnnotationConfigApplicationContext context,
ElasticsearchNode node) {
TestPropertyValues.of("spring.data.elasticsearch.properties.path.home:target",
"spring.data.elasticsearch.cluster-nodes:localhost:" + node.getTcpPort())
.applyTo(context);
}

View File

@@ -16,21 +16,18 @@
package org.springframework.boot.autoconfigure.elasticsearch.jest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.Gson;
import io.searchbox.action.Action;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.client.config.HttpClientConfig;
import io.searchbox.client.http.JestHttpClient;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.After;
@@ -39,16 +36,10 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration;
import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchNodeTemplate;
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -122,22 +113,31 @@ public class JestAutoConfigurationTests {
@Test
public void jestCanCommunicateWithElasticsearchInstance() throws IOException {
new File("target/elastic/logs").mkdirs();
load(HttpPortConfiguration.class,
"spring.data.elasticsearch.properties.path.home:target/elastic",
"spring.data.elasticsearch.properties.http.enabled:true",
"spring.data.elasticsearch.properties.http.port:0",
"spring.data.elasticsearch.properties.node.portsfile:true");
JestClient client = this.context.getBean(JestClient.class);
Map<String, String> source = new HashMap<>();
source.put("a", "alpha");
source.put("b", "bravo");
Index index = new Index.Builder(source).index("foo").type("bar").build();
client.execute(index);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("a", "alpha"));
assertThat(client.execute(new Search.Builder(searchSourceBuilder.toString())
.addIndex("foo").build()).getResponseCode()).isEqualTo(200);
new ElasticsearchNodeTemplate().doWithNode((node) -> {
load("spring.elasticsearch.jest.uris=http://localhost:" + node.getHttpPort());
JestClient client = this.context.getBean(JestClient.class);
Map<String, String> source = new HashMap<>();
source.put("a", "alpha");
source.put("b", "bravo");
Index index = new Index.Builder(source).index("foo").type("bar").build();
execute(client, index);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchQuery("a", "alpha"));
assertThat(
execute(client,
new Search.Builder(searchSourceBuilder.toString())
.addIndex("foo").build()).getResponseCode())
.isEqualTo(200);
});
}
private JestResult execute(JestClient client, Action<? extends JestResult> action) {
try {
return client.execute(action);
}
catch (IOException ex) {
throw new RuntimeException(ex);
}
}
private void load(String... environment) {
@@ -199,53 +199,4 @@ public class JestAutoConfigurationTests {
}
@Configuration
@Import(ElasticsearchAutoConfiguration.class)
static class HttpPortConfiguration {
@Bean
public static BeanPostProcessor portPropertyConfigurer() {
return new PortPropertyConfigurer();
}
private static final class PortPropertyConfigurer
implements BeanPostProcessor, ApplicationContextAware {
private ConfigurableApplicationContext applicationContext;
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof NodeClient) {
this.applicationContext.getBean(JestProperties.class)
.setUris(Arrays.asList("http://localhost:" + readHttpPort()));
}
return bean;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
}
private int readHttpPort() {
try {
for (String line : Files
.readAllLines(Paths.get("target/elastic/logs/http.ports"))) {
if (line.startsWith("127.0.0.1")) {
return Integer
.parseInt(line.substring(line.indexOf(":") + 1));
}
}
throw new FatalBeanException("HTTP port not found");
}
catch (IOException ex) {
throw new FatalBeanException("Failed to read HTTP port", ex);
}
}
}
}
}