com.github.alexcojocaru.mojo.elasticsearch.v2.client.ElasticsearchClient Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch-maven-plugin Show documentation
Show all versions of elasticsearch-maven-plugin Show documentation
A Maven plugin to run a single node Elasticsearch cluster during the integration test phase of a build
package com.github.alexcojocaru.mojo.elasticsearch.v2.client;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.commons.lang3.Validate;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.maven.plugin.logging.Log;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.alexcojocaru.mojo.elasticsearch.v2.InstanceConfiguration;
/**
* A REST client for Elasticsearch.
*
* @author Alex Cojocaru
*/
public class ElasticsearchClient implements Closeable
{
private final ObjectMapper mapper;
private final HttpClient httpClient;
private final PoolingHttpClientConnectionManager connectionManager;
private final Log log;
private final String hostname;
private final int port;
private ElasticsearchClient(
Log log,
ObjectMapper mapper,
HttpClient httpClient,
PoolingHttpClientConnectionManager connectionManager,
String hostname,
int port)
{
this.log = log;
this.mapper = mapper;
this.httpClient = httpClient;
this.connectionManager = connectionManager;
this.hostname = hostname;
this.port = port;
}
@Override
public void close()
{
connectionManager.close();
}
public T get(String path, Class clazz) throws ElasticsearchClientException
{
String uri = String.format("http://%s:%d%s", hostname, port, path);
log.debug(String.format("Sending GET request to %s", uri));
HttpGet request = new HttpGet(uri);
request.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.getMimeType());
String content = executeRequest(request);
T result = deserialize(content, clazz);
return result;
}
public T get(String path, String entity, Class clazz) throws ElasticsearchClientException
{
String uri = String.format("http://%s:%d%s", hostname, port, path);
log.debug(String.format("Sending GET request to %s with entity '%s'", uri, entity));
HttpGetWithEntity request = new HttpGetWithEntity(uri);
request.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.getMimeType());
request.setEntity(new StringEntity(entity, ContentType.APPLICATION_JSON));
String content = executeRequest(request);
T result = deserialize(content, clazz);
return result;
}
public void put(String path, String entity) throws ElasticsearchClientException
{
String uri = String.format("http://%s:%d%s", hostname, port, path);
log.info(String.format("Sending PUT request to %s with entity '%s'", uri, entity));
HttpPut request = new HttpPut(uri);
request.setEntity(new StringEntity(entity, ContentType.APPLICATION_JSON));
executeRequest(request);
}
public T post(String path, String entity, Class clazz)
throws ElasticsearchClientException
{
String uri = String.format("http://%s:%d%s", hostname, port, path);
log.debug(String.format("Sending POST request to %s with entity '%s'", uri, entity));
HttpPost request = new HttpPost(uri);
request.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.getMimeType());
request.setEntity(new StringEntity(entity, ContentType.APPLICATION_JSON));
String content = executeRequest(request);
T result = deserialize(content, clazz);
return result;
}
public void delete(String path) throws ElasticsearchClientException
{
String uri = String.format("http://%s:%d%s", hostname, port, path);
log.debug(String.format("Sending DELETE request to %s", uri));
HttpDelete request = new HttpDelete(uri);
executeRequest(request);
}
protected String readContent(HttpEntity entity)
throws UnsupportedOperationException, IOException
{
try (BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent())))
{
StringBuilder content = new StringBuilder();
String line;
while ((line = br.readLine()) != null)
{
content.append(line);
}
return content.toString();
}
}
@SuppressWarnings("unchecked")
public T deserialize(String content, Class clazz) throws ElasticsearchClientException
{
if (clazz == String.class)
{
return (T)content;
}
Validate.notNull(mapper, "Has the ElasticsearchClient been initialized?");
try
{
return mapper.readValue(content, clazz);
}
catch (IOException ex)
{
throw new ElasticsearchClientException(String.format(
"Cannot deserialize the content '%s' to class %s", content, clazz));
}
}
protected String executeRequest(HttpRequestBase request) throws ElasticsearchClientException
{
Validate.notNull(httpClient, "Has the ElasticsearchClient been initialized?");
try
{
HttpResponse response = httpClient.execute(request);
int statusCode = response.getStatusLine().getStatusCode();
String content = readContent(response.getEntity());
log.debug(String.format(
"Response with status code %d and content: %s", statusCode, content));
// some PUT requests return 200, some 201 :-O
if (statusCode != 200 && statusCode != 201)
{
throw new ElasticsearchClientException(request.getMethod(), statusCode, content);
}
return content;
}
catch (IOException e)
{
throw new ElasticsearchClientException(e);
}
finally
{
request.releaseConnection();
}
}
public static class Builder
{
private Log log;
private String hostname;
private int port;
private int socketTimeout;
public Builder withLog(Log log)
{
this.log = log;
return this;
}
public Builder withHostname(String hostname)
{
this.hostname = hostname;
return this;
}
public Builder withPort(int port)
{
this.port = port;
return this;
}
public Builder withSocketTimeout(int socketTimeout)
{
this.socketTimeout = socketTimeout;
return this;
}
public Builder withInstanceConfiguration(InstanceConfiguration config)
{
this.log = config.getClusterConfiguration().getLog();
this.socketTimeout = config.getClusterConfiguration().getClientSocketTimeout();
this.port = config.getHttpPort();
return this;
}
public ElasticsearchClient build()
{
PoolingHttpClientConnectionManager connectionManager = buildHttpClientManager(
socketTimeout);
return new ElasticsearchClient(
log,
buildObjectMapper(),
buildHttpClient(connectionManager),
connectionManager,
hostname,
port);
}
private ObjectMapper buildObjectMapper()
{
return new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
private static PoolingHttpClientConnectionManager buildHttpClientManager(int socketTimeout)
{
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(3);
cm.setDefaultMaxPerRoute(2);
cm.setValidateAfterInactivity(1);
cm.setDefaultSocketConfig(SocketConfig.custom()
.setSoTimeout(socketTimeout)
.setSoLinger(0)
.setTcpNoDelay(true)
.build());
Runtime.getRuntime().addShutdownHook(new Thread()
{
@Override
public void run()
{
cm.close();
}
});
return cm;
}
private static HttpClient buildHttpClient(HttpClientConnectionManager connectionManager)
{
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(1500)
.setConnectionRequestTimeout(1500)
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig)
// use the default retry handler:
// https://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d5e305
.build();
return httpClient;
}
}
}