package org.ff4j.elastic; /* * #%L * ff4j-store-elastic * %% * Copyright (C) 2013 - 2016 FF4J * %% * 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. * #L% */ import java.io.IOException; import java.net.URL; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.elasticsearch.client.Client; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.node.NodeBuilder; import org.ff4j.core.Feature; import org.ff4j.exception.FeatureAccessException; import org.ff4j.property.Property; import org.ff4j.utils.Util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.searchbox.action.Action; import io.searchbox.client.JestClient; import io.searchbox.client.JestClientFactory; import io.searchbox.client.JestResult; import io.searchbox.client.config.HttpClientConfig; import io.searchbox.core.SearchResult; import io.searchbox.indices.CreateIndex; import io.searchbox.indices.DeleteIndex; import io.searchbox.indices.IndicesExists; /** * Poor design by clun, to be challenged !! */ public class ElasticConnection { /** Logger for the class. */ private final Logger logger = LoggerFactory.getLogger(ElasticConnection.class); private ElasticConnectionMode connectionMode; private Client esClient; private JestClient jestClient; private String indexName; private Set<URL> urlSet; /** * Proposal to initiate a connection to a elastic cluster. * * @param mode * choose client to be used * @param url * target nodes of the cluster (optional) */ public ElasticConnection(ElasticConnectionMode mode, String indexName, URL... url) { Util.assertParamHasNotNull(mode, "ElasticConnectionMode"); Util.assertParamHasNotNull(indexName, "indexName"); Util.assertParamHasNotNull(url, "url"); this.indexName = indexName; this.connectionMode = mode; this.urlSet = Util.set(url); try { switch (mode) { case NATIVE_CLIENT: initNativeClient(); break; case TRANSPORT_CLIENT: initTransportClient(); break; case JEST_CLIENT: initJestClient(); break; default: initJestClient(); } } catch (IOException e) { // dedicated runtime exception ElasticConnectionException ? } } private void initTransportClient() { TransportClient tClient = new TransportClient(); if (!Util.isEmpty(urlSet)) { for (URL url : urlSet) { tClient.addTransportAddress(new InetSocketTransportAddress(url.getHost(), url.getPort())); } } esClient = tClient; } private void initNativeClient() { esClient = NodeBuilder.nodeBuilder().client(true).node().client(); boolean indexExists = esClient.admin().indices().prepareExists(indexName).execute().actionGet().isExists(); if (indexExists) { esClient.admin().indices().prepareDelete(indexName).execute().actionGet(); } esClient.admin().indices().prepareCreate(indexName).execute().actionGet(); } private void initJestClient() throws IOException { JestClientFactory factory = new JestClientFactory(); // Custom feature converter is required Gson gson = new GsonBuilder() // .registerTypeAdapter(Feature.class, new FeatureConverter()) // .registerTypeAdapter(Property.class, new PropertyConverter()) // .create(); factory.setHttpClientConfig(new HttpClientConfig.Builder(mapUrl()) // .multiThreaded(true) // .gson(gson) // .build()); jestClient = factory.getObject(); boolean indexExists = jestClient.execute(new IndicesExists.Builder(indexName).build()).isSucceeded(); if (indexExists) { jestClient.execute(new DeleteIndex.Builder(indexName).build()); } jestClient.execute(new CreateIndex.Builder(indexName).build()); } /** * Common behaviour to execute JEST query. * * @param request * target request * @return */ public <T extends JestResult> JestResult execute(Action<T> request, boolean allowFailure) { JestResult sr = null; try { sr = getJestClient().execute(request); if (null == sr) { throw new FeatureAccessException("Cannot query elastic seach, result was null : check your query"); } if (!allowFailure && !sr.isSucceeded()) { throw new FeatureAccessException( "Query to Elastic failed - " + sr.getErrorMessage() + " (query=" + request.toString() + ")"); } return sr; } catch (IOException e) { logger.error(e.getMessage(), e); throw new FeatureAccessException( "Error with query to Elastic - " + request.toString() + " An exception occured ", e); } } public <T extends JestResult> JestResult execute(Action<T> request) { return execute(request, false); } public <T extends JestResult> SearchResult search(Action<T> request) { return search(request, false); } /** * Syntax suger to search. * * @param request * jest request * @return jest result */ public <T extends JestResult> SearchResult search(Action<T> request, boolean allowFailure) { return (SearchResult) execute(request, allowFailure); } /** * Before Lambda... */ private Collection<String> mapUrl() { Collection<String> collec = new HashSet<String>(); for (URL url : urlSet) { collec.add(url.toString()); } return collec; } /** * Getter accessor for attribute 'connectionMode'. * * @return current value of 'connectionMode' */ public ElasticConnectionMode getConnectionMode() { return connectionMode; } /** * Setter accessor for attribute 'connectionMode'. * * @param connectionMode * new value for 'connectionMode ' */ public void setConnectionMode(ElasticConnectionMode connectionMode) { this.connectionMode = connectionMode; } /** * Getter accessor for attribute 'esClient'. * * @return current value of 'esClient' */ public Client getEsClient() { return esClient; } /** * Setter accessor for attribute 'esClient'. * * @param esClient * new value for 'esClient ' */ public void setEsClient(Client esClient) { this.esClient = esClient; } /** * Getter accessor for attribute 'jestClient'. * * @return current value of 'jestClient' */ public JestClient getJestClient() { return jestClient; } /** * Setter accessor for attribute 'jestClient'. * * @param jestClient * new value for 'jestClient ' */ public void setJestClient(JestClient jestClient) { this.jestClient = jestClient; } /** * Getter accessor for attribute 'indexName'. * * @return current value of 'indexName' */ public String getIndexName() { return indexName; } /** * Setter accessor for attribute 'indexName'. * * @param indexName * new value for 'indexName ' */ public void setIndexName(String indexName) { this.indexName = indexName; } /** * Getter accessor for attribute 'urlSet'. * * @return current value of 'urlSet' */ public Set<URL> getUrlSet() { return urlSet; } /** * Setter accessor for attribute 'urlSet'. * * @param urlSet * new value for 'urlSet ' */ public void setUrlSet(Set<URL> urlSet) { this.urlSet = urlSet; } }