diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/searchEngine/SearchEngine.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/searchEngine/SearchEngine.java index b44d77586..c347fb7bf 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/searchEngine/SearchEngine.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/searchEngine/SearchEngine.java @@ -9,6 +9,11 @@ import edu.cornell.mannlib.vitro.webapp.modules.Application; /** * The principle interface for the SearchEngine. All search-related objects are * created by these methods. + * + * All methods that throw SearchEngineException should attempt to distinguish + * whether the exception is caused because the SearchEngine is not responding. + * In that case, they should throw a SearchEngineNotRespondingException, so the + * client code can choose to respond accordingly. */ public interface SearchEngine extends Application.Module { @@ -86,7 +91,7 @@ public interface SearchEngine extends Application.Module { * Query the search index and return the results. Response is never null. */ SearchResponse query(SearchQuery query) throws SearchEngineException; - + /** * Find the number of documents in the search index. */ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/searchEngine/SearchEngineNotRespondingException.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/searchEngine/SearchEngineNotRespondingException.java new file mode 100644 index 000000000..255921538 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/searchEngine/SearchEngineNotRespondingException.java @@ -0,0 +1,27 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.modules.searchEngine; + +/** + * Indicates that a request to the SearchEngine has timed out, or given some + * other indication that no response will be coming. + */ +public class SearchEngineNotRespondingException extends SearchEngineException { + + public SearchEngineNotRespondingException() { + super(); + } + + public SearchEngineNotRespondingException(String message) { + super(message); + } + + public SearchEngineNotRespondingException(Throwable cause) { + super(cause); + } + + public SearchEngineNotRespondingException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/solr/SolrSearchEngine.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/solr/SolrSearchEngine.java index 848de8acf..7f9114a38 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/solr/SolrSearchEngine.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchengine/solr/SolrSearchEngine.java @@ -3,6 +3,7 @@ package edu.cornell.mannlib.vitro.webapp.searchengine.solr; import java.io.IOException; +import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -19,6 +20,7 @@ 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; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineException; +import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineNotRespondingException; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchInputDocument; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchQuery; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchResponse; @@ -72,8 +74,8 @@ public class SolrSearchEngine implements SearchEngine { try { server.ping(); } catch (SolrServerException | IOException e) { - throw new SearchEngineException( - "Solr server did not respont to ping.", e); + throw appropriateException("Solr server did not respond to ping.", + e); } } @@ -93,8 +95,8 @@ public class SolrSearchEngine implements SearchEngine { try { server.add(SolrConversionUtils.convertToSolrInputDocuments(docs)); } catch (SolrServerException | IOException e) { - throw new SearchEngineException( - "Solr server failed to add documents " + docs, e); + throw appropriateException("Solr server failed to add documents " + + docs, e); } } @@ -103,8 +105,7 @@ public class SolrSearchEngine implements SearchEngine { try { server.commit(); } catch (SolrServerException | IOException e) { - throw new SearchEngineException("Failed to commit to Solr server.", - e); + throw appropriateException("Failed to commit to Solr server.", e); } } @@ -113,8 +114,7 @@ public class SolrSearchEngine implements SearchEngine { try { server.commit(wait, wait); } catch (SolrServerException | IOException e) { - throw new SearchEngineException("Failed to commit to Solr server.", - e); + throw appropriateException("Failed to commit to Solr server.", e); } } @@ -128,7 +128,7 @@ public class SolrSearchEngine implements SearchEngine { try { server.deleteById(new ArrayList<>(ids)); } catch (SolrServerException | IOException e) { - throw new SearchEngineException( + throw appropriateException( "Solr server failed to delete documents: " + ids, e); } } @@ -138,7 +138,7 @@ public class SolrSearchEngine implements SearchEngine { try { server.deleteByQuery(query); } catch (SolrServerException | IOException e) { - throw new SearchEngineException( + throw appropriateException( "Solr server failed to delete documents: " + query, e); } } @@ -162,14 +162,32 @@ public class SolrSearchEngine implements SearchEngine { QueryResponse response = server.query(solrQuery); return SolrConversionUtils.convertToSearchResponse(response); } catch (SolrServerException e) { - throw new SearchEngineException( + throw appropriateException( "Solr server failed to execute the query" + query, e); } } @Override public int documentCount() throws SearchEngineException { - SearchResponse response = query(createQuery("*:*")); - return (int) response.getResults().getNumFound(); + SearchResponse response = query(createQuery("*:*")); + return (int) response.getResults().getNumFound(); } + + /** + * If there is a SocketTimeoutException in the causal chain for this + * exception, then wrap it in a SearchEngineNotRespondingException instead + * of a generic SearchEngineException. + */ + private SearchEngineException appropriateException(String message, + Exception e) { + Throwable cause = e; + while (cause != null) { + if (cause instanceof SocketTimeoutException) { + return new SearchEngineNotRespondingException(message, e); + } + cause = cause.getCause(); + } + return new SearchEngineException(message, e); + } + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/SearchIndexerSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/SearchIndexerSetup.java index bb94ab607..ad7d9f177 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/SearchIndexerSetup.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/SearchIndexerSetup.java @@ -15,6 +15,7 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils; import edu.cornell.mannlib.vitro.webapp.modules.Application; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; +import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineNotRespondingException; import edu.cornell.mannlib.vitro.webapp.modules.searchIndexer.SearchIndexer; import edu.cornell.mannlib.vitro.webapp.modules.searchIndexer.SearchIndexer.Event; import edu.cornell.mannlib.vitro.webapp.modules.searchIndexer.SearchIndexer.Event.Type; @@ -118,6 +119,9 @@ public class SearchIndexerSetup implements ServletContextListener { private void commitChanges() { try { searchEngine.commit(); + } catch (SearchEngineNotRespondingException e) { + log.error("Failed to commit the changes: " + + "the search engine is not responding."); } catch (Exception e) { log.error("Failed to commit the changes.", e); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/RebuildIndexTask.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/RebuildIndexTask.java index bf1d0e3ac..60be6dc7e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/RebuildIndexTask.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/RebuildIndexTask.java @@ -17,6 +17,7 @@ import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils; import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineException; +import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineNotRespondingException; import edu.cornell.mannlib.vitro.webapp.modules.searchIndexer.SearchIndexer.Event; import edu.cornell.mannlib.vitro.webapp.modules.searchIndexer.SearchIndexerStatus; import edu.cornell.mannlib.vitro.webapp.modules.searchIndexer.SearchIndexerStatus.RebuildCounts; @@ -105,6 +106,9 @@ public class RebuildIndexTask implements Task { try { searchEngine.deleteByQuery(query); searchEngine.commit(); + } catch (SearchEngineNotRespondingException e) { + log.warn("Failed to delete outdated documents from the search index: " + + "the search engine is not responding."); } catch (SearchEngineException e) { log.warn("Failed to delete outdated documents " + "from the search index", e); @@ -114,8 +118,12 @@ public class RebuildIndexTask implements Task { private int getDocumentCount() { try { return searchEngine.documentCount(); + } catch (SearchEngineNotRespondingException e) { + log.warn("Failed to get document count from the search index: " + + "the search engine is not responding."); + return 0; } catch (SearchEngineException e) { - log.warn("Failed to get docoument count from the search index.", e); + log.warn("Failed to get document count from the search index.", e); return 0; } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateDocumentWorkUnit.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateDocumentWorkUnit.java index ffaf6dcb6..c0840f05b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateDocumentWorkUnit.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateDocumentWorkUnit.java @@ -31,6 +31,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; +import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineNotRespondingException; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchInputDocument; import edu.cornell.mannlib.vitro.webapp.modules.searchIndexer.SearchIndexerUtils; import edu.cornell.mannlib.vitro.webapp.searchindex.documentBuilding.DocumentModifier; @@ -65,6 +66,9 @@ public class UpdateDocumentWorkUnit implements Runnable { modifiers.modifyDocument(ind, doc); addIndexedTime(doc); searchEngine.add(doc); + } catch (SearchEngineNotRespondingException e) { + log.warn("Failed to add '" + ind + "' to the search index: " + + "the search engine is not responding."); } catch (Exception e) { log.warn("Failed to add '" + ind + "' to the search index.", e); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateUrisTask.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateUrisTask.java index 9afa10249..9634616f5 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateUrisTask.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/searchindex/tasks/UpdateUrisTask.java @@ -21,6 +21,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; +import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineNotRespondingException; import edu.cornell.mannlib.vitro.webapp.modules.searchIndexer.SearchIndexer.Event; import edu.cornell.mannlib.vitro.webapp.modules.searchIndexer.SearchIndexerStatus; import edu.cornell.mannlib.vitro.webapp.modules.searchIndexer.SearchIndexerStatus.UriCounts; @@ -131,6 +132,9 @@ public class UpdateUrisTask implements Task { searchEngine.deleteById(SearchIndexerUtils.getIdForUri(uri)); status.incrementDeletes(); log.debug("deleted '" + uri + "' from search index."); + } catch (SearchEngineNotRespondingException e) { + log.warn("Failed to delete '" + uri + "' from search index: " + + "the search engine is not responding."); } catch (Exception e) { log.warn("Failed to delete '" + uri + "' from search index", e); } @@ -142,6 +146,9 @@ public class UpdateUrisTask implements Task { searchEngine.deleteById(SearchIndexerUtils.getIdForUri(uri)); status.incrementExclusions(); log.debug("excluded '" + uri + "' from search index."); + } catch (SearchEngineNotRespondingException e) { + log.warn("Failed to exclude '" + uri + "' from search index: " + + "the search engine is not responding.", e); } catch (Exception e) { log.warn("Failed to exclude '" + uri + "' from search index", e); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java index 3ab74ccf6..3c61a06fa 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/searchengine/SearchQueryUtils.java @@ -13,10 +13,7 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListQueryResults; -import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; -import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngineException; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchQuery; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchQuery.Order; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchResponse;