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:
parent
50ca35bdae
commit
7afe1d16a6
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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,\
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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`
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue