From ee28715d1cbb0e0080bced7def554c96e41622ef Mon Sep 17 00:00:00 2001 From: Ivan Mrsulja Date: Mon, 24 Jun 2024 10:15:55 +0200 Subject: [PATCH] Completed implementation of missing ES engine methods. Improved documentation and configuration mechanisms. --- .../elasticsearch/ElasticSearchEngine.java | 77 ++++++++++--------- .../Elasticsearch_notes_on_the_first_draft.md | 3 + 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/elasticsearch/ElasticSearchEngine.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/elasticsearch/ElasticSearchEngine.java index 80b1da984a..e4c0d840ec 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/elasticsearch/ElasticSearchEngine.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/elasticsearch/ElasticSearchEngine.java @@ -2,12 +2,11 @@ package edu.cornell.mannlib.vitro.webapp.searchengine.elasticsearch; +import java.io.IOException; import java.util.Arrays; import java.util.Collection; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - +import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.modules.Application; import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; @@ -17,11 +16,15 @@ import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchResponse; import edu.cornell.mannlib.vitro.webapp.searchengine.base.BaseSearchInputDocument; import edu.cornell.mannlib.vitro.webapp.searchengine.base.BaseSearchQuery; -import edu.cornell.mannlib.vitro.webapp.utils.configuration.Property; -import edu.cornell.mannlib.vitro.webapp.utils.configuration.Validation; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; /** - * A first draft of an Elasticsearch implementation. + * A first version of an Elasticsearch engine implementation. */ public class ElasticSearchEngine implements SearchEngine { private static final Log log = LogFactory.getLog(ElasticSearchEngine.class); @@ -32,47 +35,47 @@ public class ElasticSearchEngine implements SearchEngine { private String baseUrl; - @Property(uri = "http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationSetup#hasBaseUrl") - public void setBaseUrl(String url) { - if (baseUrl == null) { - if (url.endsWith("/")) { - url = url.substring(0, url.length() - 1); - } - baseUrl = url; - } else { - throw new IllegalStateException( - "Configuration includes multiple base URLs: " + url - + ", and " + baseUrl); - } - } - - @Validation - public void validate() throws Exception { - if (baseUrl == null) { - throw new IllegalStateException( - "Configuration did not include a base URL."); - } - } - // ---------------------------------------------------------------------- // The instance // ---------------------------------------------------------------------- @Override - public void startup(Application application, ComponentStartupStatus ss) { - log.warn("ElasticSearchEngine.startup() not implemented."); // TODO + public void startup(Application application, ComponentStartupStatus css) { + String elasticUrlString = ConfigurationProperties.getInstance().getProperty("vitro.local.elastic.url", ""); + if (elasticUrlString.isEmpty()) { + css.fatal("Can't connect to ElasticSearch engine. " + + "runtime.properties must contain a value for " + + "vitro.local.elastic.url"); + } + + baseUrl = elasticUrlString; } @Override public void shutdown(Application application) { - // TODO Flush the buffers - log.warn("ElasticSearchEngine.shutdown not implemented."); + try { + new ESFlusher(baseUrl).flush(true); + } catch (SearchEngineException e) { + log.warn("Unexpected error upon Elasticsearch engine shutdown. A component has thrown an error: " + + e.getMessage()); + } } @Override public void ping() throws SearchEngineException { - // TODO What's the simplest we can do? Another smoke test? - log.warn("ElasticSearchEngine.ping() not implemented."); // TODO + HttpHead httpHead = new HttpHead(baseUrl); + + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + try (CloseableHttpResponse response = httpClient.execute(httpHead)) { + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != 200) { + throw new SearchEngineException( + "Failed to ping Elasticsearch - ES responded with status code " + statusCode); + } + } + } catch (SearchEngineException | IOException e) { + throw new SearchEngineException("Failed to put to Elasticsearch - request failed"); + } } @Override @@ -87,7 +90,7 @@ public void add(SearchInputDocument... docs) throws SearchEngineException { @Override public void add(Collection docs) - throws SearchEngineException { + throws SearchEngineException { new ESAdder(baseUrl).add(docs); } @@ -108,7 +111,7 @@ public void deleteById(String... ids) throws SearchEngineException { @Override public void deleteById(Collection ids) - throws SearchEngineException { + throws SearchEngineException { new ESDeleter(baseUrl).deleteByIds(ids); } @@ -131,7 +134,7 @@ public SearchQuery createQuery(String queryText) { @Override public SearchResponse query(SearchQuery query) - throws SearchEngineException { + throws SearchEngineException { return new ESQuery(baseUrl).query(query); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/elasticsearch/Elasticsearch_notes_on_the_first_draft.md b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/elasticsearch/Elasticsearch_notes_on_the_first_draft.md index eedcb318da..626630c318 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/elasticsearch/Elasticsearch_notes_on_the_first_draft.md +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/searchengine/elasticsearch/Elasticsearch_notes_on_the_first_draft.md @@ -11,6 +11,8 @@ * Create a search index with the appropriate mapping (see below). * Check out VIVO and this branch of Vitro (see below), and do the usual installation procedure. * Modify `{vitro_home}/config/applicationSetup.n3` to use this driver (see below). +* Modify the `vitro.local.elastic.url` configuration property to contain ES index base URL +* Comment out (or completely remove) the `vitro.local.solr.url` property * Start elasticsearch * Start VIVO @@ -202,6 +204,7 @@ Again, any location and port may be used, but they must match the "base URL" in ; :hasBaseUrl "http://localhost:9200/vivo" . ``` +Note that `hasBaseUrl "http://localhost:9200/vivo" .` can be omitted. ## Enhance the contents of the search index ### An example: Publication URIs in the author's search document