Add Jest support

This commit adds auto-configuration support for Jest, an HTTP client for
Elasticsearch. If Jest is present, a `JestClient` targeting a local
elasticsearch instance is auto-configured. Several properties from the
`spring.jest.*` namespace allows to tune the client.

Closes gh-6032
This commit is contained in:
Stephane Nicoll 2016-06-13 11:12:49 +02:00
parent 50ca35bdae
commit 7afe1d16a6
8 changed files with 322 additions and 2 deletions

View File

@ -110,6 +110,11 @@
<artifactId>reactor-spring-context</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>

View File

@ -0,0 +1,80 @@
/*
* 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.autoconfigure.jest;
import com.google.gson.Gson;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestClientFactory;
import io.searchbox.client.config.HttpClientConfig;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
/**
* {@link EnableAutoConfiguration Auto-Configuration} for Jest.
*
* @author Stephane Nicoll
* @since 1.4.0
*/
@Configuration
@ConditionalOnClass(JestClient.class)
@EnableConfigurationProperties(JestProperties.class)
@AutoConfigureAfter(GsonAutoConfiguration.class)
public class JestAutoConfiguration {
private final JestProperties properties;
private final ObjectProvider<Gson> gsonProvider;
public JestAutoConfiguration(JestProperties properties, ObjectProvider<Gson> gsonProvider) {
this.properties = properties;
this.gsonProvider = gsonProvider;
}
@Bean
@ConditionalOnMissingBean
public JestClient jestClient() {
JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(createHttpClientConfig());
return factory.getObject();
}
protected HttpClientConfig createHttpClientConfig() {
HttpClientConfig.Builder builder = new HttpClientConfig
.Builder(this.properties.getUris());
if (StringUtils.hasText(this.properties.getUsername())) {
builder.defaultCredentials(this.properties.getUsername(),
this.properties.getPassword());
}
Gson gson = this.gsonProvider.getIfUnique();
if (gson != null) {
builder.gson(gson);
}
return builder.connTimeout(this.properties.getConnectionTimeout())
.readTimeout(this.properties.getReadTimeout())
.build();
}
}

View File

@ -0,0 +1,98 @@
/*
* 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.autoconfigure.jest;
import java.util.Collections;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration properties for Jest.
*
* @author Stephane Nicoll
* @since 1.4.0
*/
@ConfigurationProperties("spring.jest")
public class JestProperties {
/**
* Comma-separated list of the elasticsearch instances to use.
*/
private List<String> uris = Collections.singletonList("http://localhost:9200");
/**
* Login user.
*/
private String username;
/**
* Login password.
*/
private String password;
/**
* Connection timeout in milliseconds.
*/
private int connectionTimeout = 3000;
/**
* Read timeout in milliseconds.
*/
private int readTimeout = 3000;
public List<String> getUris() {
return this.uris;
}
public void setUris(List<String> uris) {
this.uris = uris;
}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public int getConnectionTimeout() {
return this.connectionTimeout;
}
public void setConnectionTimeout(int connectionTimeout) {
this.connectionTimeout = connectionTimeout;
}
public int getReadTimeout() {
return this.readTimeout;
}
public void setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
}
}

View File

@ -50,6 +50,7 @@ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\

View File

@ -0,0 +1,104 @@
/*
* 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.autoconfigure.jest;
import com.google.gson.Gson;
import io.searchbox.client.JestClient;
import io.searchbox.client.http.JestHttpClient;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link JestAutoConfiguration}.
*
* @author Stephane Nicoll
*/
public class JestAutoConfigurationTests {
protected AnnotationConfigApplicationContext context;
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void jestClientOnLocalhostByDefault() {
load();
assertThat(this.context.getBeansOfType(JestClient.class)).hasSize(1);
}
@Test
public void customJestClient() {
load(CustomJestClient.class, "spring.jest.uris=http://localhost:9200");
assertThat(this.context.getBeansOfType(JestClient.class)).hasSize(1);
}
@Test
public void customGson() {
load(CustomGson.class, "spring.jest.uris=http://localhost:9200");
JestHttpClient client = (JestHttpClient) this.context.getBean(JestClient.class);
assertThat(client.getGson()).isSameAs(this.context.getBean("customGson"));
}
private void load(String... environment) {
load(null, environment);
}
private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(context, environment);
if (config != null) {
context.register(config);
}
context.register(GsonAutoConfiguration.class, JestAutoConfiguration.class);
context.refresh();
this.context = context;
}
@Configuration
static class CustomJestClient {
@Bean
public JestClient customJestClient() {
return mock(JestClient.class);
}
}
@Configuration
static class CustomGson {
@Bean
public Gson customGson() {
return new Gson();
}
}
}

View File

@ -106,6 +106,7 @@
<jdom2.version>2.0.6</jdom2.version>
<jedis.version>2.8.1</jedis.version>
<jersey.version>2.23</jersey.version>
<jest.version>2.0.3</jest.version>
<jetty.version>9.2.17.v20160517</jetty.version>
<jetty-jsp.version>2.2.0.v201112011158</jetty-jsp.version>
<jmustache.version>1.12</jmustache.version>
@ -928,6 +929,11 @@
<artifactId>reactor-spring-webmvc</artifactId>
<version>${reactor-spring.version}</version>
</dependency>
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>${jest.version}</version>
</dependency>
<dependency>
<groupId>io.undertow</groupId>
<artifactId>undertow-core</artifactId>

View File

@ -629,6 +629,13 @@ content into your application; rather pick only the properties that you need.
spring.h2.console.settings.trace=false # Enable trace output.
spring.h2.console.settings.web-allow-others=false # Enable remote access.
# JEST (ElasticSearch HTTP client) ({sc-spring-boot-autoconfigure}/jest/JestProperties.{sc-ext}[JestProperties])
spring.jest.connection-timeout=3000 # Connection timeout in milliseconds.
spring.jest.password= # Login password.
spring.jest.read-timeout=3000 # Read timeout in milliseconds.
spring.jest.uris=http://localhost:9200 # Comma-separated list of the elasticsearch instances to use.
spring.jest.username= # Login user.
# JOOQ ({sc-spring-boot-autoconfigure}/jooq/JooqAutoConfiguration.{sc-ext}[JooqAutoConfiguration])
spring.jooq.sql-dialect= # SQLDialect JOOQ used when communicating with the configured datasource. For instance `POSTGRES`

View File

@ -3315,12 +3315,31 @@ real-time search and analytics engine. Spring Boot offers basic auto-configurati
the Elasticsearch and abstractions on top of it provided by
https://github.com/spring-projects/spring-data-elasticsearch[Spring Data Elasticsearch].
There is a `spring-boot-starter-data-elasticsearch` '`Starter`' for collecting the
dependencies in a convenient way.
dependencies in a convenient way. Spring Boot also supports
https://github.com/searchbox-io/Jest[Jest].
[[boot-features-connecting-to-elasticsearch-jest]]
==== Connecting to Elasticsearch using Spring Data
If you have `Jest` on the classpath, you can inject an auto-configured `JestClient`
targeting `http://localhost:9200` by default. You can further tune how the client is
configured:
[source,properties,indent=0]
----
spring.jest.uris=http://search.example.com:9200
spring.jest.read-timeout=10000
spring.jest.username=user
spring.jest.password=secret
----
To take full control over the registration, define a `JestClient` bean.
[[boot-features-connecting-to-elasticsearch]]
==== Connecting to Elasticsearch
[[boot-features-connecting-to-elasticsearch-spring-data]]
==== Connecting to Elasticsearch using Spring Data
You can inject an auto-configured `ElasticsearchTemplate` or Elasticsearch `Client`
instance as you would any other Spring Bean. By default the instance will embed a
local in-memory server (a `Node` in ElasticSearch terms) and use the current working