From 61fd3fcf2ec5f474c7290347d9d77a923fa44460 Mon Sep 17 00:00:00 2001 From: "mark.j.leonard" Date: Fri, 21 Sep 2018 15:00:46 +0100 Subject: [PATCH] Use a URI builder to create URLs Also refactor the connection code to remove duplicated Exception handling. Change-Id: Ica77b6ba3d8939e89b763a33a6b940d11b066b85 Issue-ID: AAI-1650 Signed-off-by: mark.j.leonard --- .../dao/ElasticSearchHttpController.java | 311 +++++----------- .../exception/DocumentStoreOperationException.java | 32 +- .../dao/ElasticSearchHttpControllerTest.java | 410 ++++++++++++--------- 3 files changed, 352 insertions(+), 401 deletions(-) diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java index 5734c40..a0b72f7 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpController.java @@ -49,10 +49,13 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; +import javax.ws.rs.HttpMethod; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status.Family; +import javax.ws.rs.core.UriBuilder; import org.eclipse.jetty.http.HttpStatus; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -71,6 +74,7 @@ import org.onap.aai.sa.rest.BulkRequest.OperationType; import org.onap.aai.sa.rest.DocumentSchema; import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; +import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException.ErrorMessage; import org.onap.aai.sa.searchdbabstraction.entity.AggregationResult; import org.onap.aai.sa.searchdbabstraction.entity.AggregationResults; import org.onap.aai.sa.searchdbabstraction.entity.Document; @@ -102,20 +106,18 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { private static final Logger metricsLogger = LoggerFactory.getInstance().getMetricsLogger(ElasticSearchHttpController.class.getName()); + private static final String URL_QUERY_VERSION = "version="; + private static final String JSON_ATTR_VERSION = "_version"; private static final String JSON_ATTR_ERROR = "error"; private static final String JSON_ATTR_REASON = "reason"; private static final String DEFAULT_TYPE = "default"; - private static final String QUERY_PARAM_VERSION = "?version="; private static final String MSG_RESOURCE_MISSING = "Specified resource does not exist: "; private static final String MSG_RESPONSE_CODE = "Response Code : "; private static final String MSG_INVALID_DOCUMENT_URL = "Invalid document URL: "; - private static final String MSG_HTTP_PUT_FAILED = "Failed to set HTTP request method to PUT."; - private static final String MSG_HTTP_POST_FAILED = "Failed to set HTTP request method to POST."; - private static final String FAILED_TO_GET_THE_RESPONSE_CODE_FROM_THE_CONNECTION = - "Failed to get the response code from the connection."; + private static final String FAILED_TO_PARSE_ELASTIC_SEARCH_RESPONSE = "Failed to parse Elastic Search response."; private static final String BULK_CREATE_WITHOUT_INDEX_TEMPLATE = @@ -136,13 +138,14 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { this.config = config; analysisConfig = new AnalysisConfiguration(); + String rootUrl = null; try { - logger.info(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_ATTEMPT, getFullUrl("", false)); + rootUrl = buildUrl(createUriBuilder("")).toString(); + logger.info(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_ATTEMPT, rootUrl); checkConnection(); - logger.info(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_SUCCESS, getFullUrl("", false)); + logger.info(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_SUCCESS, rootUrl); } catch (Exception e) { - logger.error(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_FAILURE, null, e, getFullUrl("", false), - e.getMessage()); + logger.error(SearchDbMsgs.ELASTIC_SEARCH_CONNECTION_FAILURE, null, e, rootUrl, e.getMessage()); } } @@ -191,7 +194,6 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { return new OperationResultBuilder().useDefaults() .failureCause("Document store operation failure. Cause: " + e.getMessage()).build(); } - } @Override @@ -216,21 +218,9 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { @Override public OperationResult deleteIndex(String indexName) throws DocumentStoreOperationException { - // Grab the current time so we can use it to generate a metrics log. MdcOverride override = getStartTime(new MdcOverride()); - String fullUrl = getFullUrl("/" + indexName + "/", false); - HttpURLConnection conn = initializeConnection(fullUrl); - - logger.debug("\nSending 'DELETE' request to URL : " + conn.getURL()); - - try { - conn.setRequestMethod("DELETE"); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException("Failed to set HTTP request method to DELETE.", e); - } - + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.DELETE); OperationResult opResult = handleResponse(conn); logMetricsInfo(override, SearchDbMsgs.DELETE_INDEX_TIME, opResult, indexName); shutdownConnection(conn); @@ -249,18 +239,9 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { logger.debug("No mappings provided."); } - // Grab the current time so we can use it to generate a metrics log. MdcOverride override = getStartTime(new MdcOverride()); - String fullUrl = getFullUrl("/" + indexName + "/", false); - HttpURLConnection conn = initializeConnection(fullUrl); - - try { - conn.setRequestMethod("PUT"); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException(MSG_HTTP_PUT_FAILED, e); - } + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.PUT); StringBuilder sb = new StringBuilder(128); sb.append("{ \"settings\" : "); @@ -279,7 +260,6 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { throw new DocumentStoreOperationException(e.getMessage(), e); } - logger.debug("\ncreateTable(), Sending 'PUT' request to URL : " + conn.getURL()); logger.debug("Request content: " + sb); OperationResult opResult = handleResponse(conn); @@ -300,19 +280,9 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { */ protected OperationResult createTable(String indexName, String settingsAndMappings) throws DocumentStoreOperationException { - // Grab the current time so we can use it to generate a metrics log. MdcOverride override = getStartTime(new MdcOverride()); - String fullUrl = getFullUrl("/" + indexName + "/", false); - HttpURLConnection conn = initializeConnection(fullUrl); - - try { - conn.setRequestMethod("PUT"); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException(MSG_HTTP_PUT_FAILED, e); - } - + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.PUT); try { attachContent(conn, ElasticSearchPayloadTranslator.translateESPayload(settingsAndMappings)); } catch (IOException e) { @@ -353,7 +323,6 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { @Override public DocumentOperationResult updateDocument(String indexName, DocumentStoreDataEntity document, boolean allowImplicitIndexCreation) throws DocumentStoreOperationException { - if (!allowImplicitIndexCreation) { // Before we do anything, make sure that the specified index actually exists in the // document store - we don't want to rely on ElasticSearch to fail the document @@ -370,24 +339,14 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { } } - // Grab the current time so we can use it to generate a metrics log. MdcOverride override = getStartTime(new MdcOverride()); - String fullUrl = getFullUrl("/" + indexName + "/" + DEFAULT_TYPE + "/" + document.getId() + QUERY_PARAM_VERSION - + document.getVersion(), false); - HttpURLConnection conn = initializeConnection(fullUrl); - - try { - conn.setRequestMethod("PUT"); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException(MSG_HTTP_PUT_FAILED, e); - } + final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, document.getId()) + .replaceQuery(URL_QUERY_VERSION + document.getVersion())); + HttpURLConnection conn = createConnection(url, HttpMethod.PUT); attachDocument(conn, document); - logger.debug("Sending 'PUT' request to: " + conn.getURL()); - DocumentOperationResult opResult = getOperationResult(conn); buildDocumentResult(opResult, indexName); @@ -401,21 +360,12 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { @Override public DocumentOperationResult deleteDocument(String indexName, DocumentStoreDataEntity document) throws DocumentStoreOperationException { - // Grab the current time so we can use it to generate a metrics log. - MdcOverride override = getStartTime(new MdcOverride()); - - String fullUrl = getFullUrl("/" + indexName + "/" + DEFAULT_TYPE + "/" + document.getId() + QUERY_PARAM_VERSION - + document.getVersion(), false); - HttpURLConnection conn = initializeConnection(fullUrl); + final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, document.getId()) + .replaceQuery(URL_QUERY_VERSION + document.getVersion())); - try { - conn.setRequestMethod("DELETE"); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException("Failed to set HTTP request method to DELETE.", e); - } + MdcOverride override = getStartTime(new MdcOverride()); - logger.debug("\nSending 'DELETE' request to " + conn.getURL()); + HttpURLConnection conn = createConnection(url, HttpMethod.DELETE); DocumentOperationResult opResult = getOperationResult(conn); buildDocumentResult(opResult, indexName); @@ -435,19 +385,13 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { @Override public DocumentOperationResult getDocument(String indexName, DocumentStoreDataEntity document) throws DocumentStoreOperationException { - // Grab the current time so we can use it to generate a metrics log. - MdcOverride override = getStartTime(new MdcOverride()); - - String fullUrl = null; - if (document.getVersion() == null) { - fullUrl = getFullUrl("/" + indexName + "/" + DEFAULT_TYPE + "/" + document.getId(), false); - } else { - fullUrl = getFullUrl("/" + indexName + "/" + DEFAULT_TYPE + "/" + document.getId() + QUERY_PARAM_VERSION - + document.getVersion(), false); + final UriBuilder uriBuilder = createUriBuilder(indexName, DEFAULT_TYPE, document.getId()); + if (document.getVersion() != null) { + uriBuilder.replaceQuery(URL_QUERY_VERSION + document.getVersion()); } - HttpURLConnection conn = initializeConnection(fullUrl); - logger.debug("\nSending 'GET' request to: " + conn.getURL()); + MdcOverride override = getStartTime(new MdcOverride()); + HttpURLConnection conn = createConnection(buildUrl(uriBuilder), "GET"); DocumentOperationResult opResult = getOperationResult(conn); buildDocumentResult(opResult, indexName); @@ -461,23 +405,11 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { @Override public SearchOperationResult search(String indexName, String queryString) throws DocumentStoreOperationException { + final URL url = buildUrl(createUriBuilder(indexName, "_search").replaceQuery(queryString)); - String fullUrl = getFullUrl("/" + indexName + "/_search" + "?" + queryString, false); - - // Grab the current time so we can use it to generate a metrics log. MdcOverride override = getStartTime(new MdcOverride()); - HttpURLConnection conn = initializeConnection(fullUrl); - - try { - conn.setRequestMethod("GET"); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException("Failed to set HTTP request method to GET.", e); - } - - logger.debug("\nsearch(), Sending 'GET' request to URL : " + conn.getURL()); - + HttpURLConnection conn = createConnection(url, "GET"); SearchOperationResult opResult = getSearchOperationResult(conn); buildSearchResult(opResult, indexName); @@ -492,24 +424,12 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { if (logger.isDebugEnabled()) { logger.debug("Querying index: " + indexName + " with query string: " + query); } + final URL url = buildUrl(createUriBuilder(indexName, "_search")); - String fullUrl = getFullUrl("/" + indexName + "/_search", false); - - // Grab the current time so we can use it to generate a metrics log. MdcOverride override = getStartTime(new MdcOverride()); - HttpURLConnection conn = initializeConnection(fullUrl); - - try { - conn.setRequestMethod("POST"); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException(MSG_HTTP_POST_FAILED, e); - } - + HttpURLConnection conn = createConnection(url, HttpMethod.POST); attachContent(conn, query); - - logger.debug("\nsearch(), Sending 'POST' request to URL : " + conn.getURL()); logger.debug("Request body = Elasticsearch query = " + query); SearchOperationResult opResult = getSearchOperationResult(conn); @@ -522,7 +442,6 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { return opResult; } - @Override public SearchOperationResult suggestionQueryWithPayload(String indexName, String query) throws DocumentStoreOperationException { @@ -530,23 +449,10 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { logger.debug("Querying Suggestion index: " + indexName + " with query string: " + query); } - String fullUrl = getFullUrl("/" + indexName + "/_suggest", false); - - // Grab the current time so we can use it to generate a metrics log. MdcOverride override = getStartTime(new MdcOverride()); - - HttpURLConnection conn = initializeConnection(fullUrl); - - try { - conn.setRequestMethod("POST"); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException(MSG_HTTP_POST_FAILED, e); - } - + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName, "_suggest")), HttpMethod.POST); attachContent(conn, query); - logger.debug("\nsearch(), Sending 'POST' request to URL : " + conn.getURL()); logger.debug("Request body = Elasticsearch query = " + query); SearchOperationResult opResult = getSearchOperationResult(conn); @@ -571,7 +477,6 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { logger.debug(dbgString.toString()); } - // Grab the current time so we can use it to generate a metrics log. MdcOverride override = getStartTime(new MdcOverride()); // Parse the supplied set of operations. @@ -590,16 +495,10 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { ElasticSearchBulkOperationResult opResult = null; if (opCount > 0) { - - // Open an HTTP connection to the ElasticSearch back end. - String fullUrl = getFullUrl("/_bulk", false); - URL url; HttpURLConnection conn; try { - - url = new URL(fullUrl); - conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod("PUT"); + conn = (HttpURLConnection) buildUrl(createUriBuilder("_bulk")).openConnection(); + conn.setRequestMethod(HttpMethod.PUT); conn.setDoOutput(true); conn.setRequestProperty(CONTENT_TYPE, APPLICATION_FORM_URLENCODED); conn.setRequestProperty("Connection", "Close"); @@ -704,28 +603,15 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { * @throws DocumentStoreOperationException */ private OperationResult checkIndexExistence(String indexName) throws DocumentStoreOperationException { - // Grab the current time so we can use it to generate a metrics log. MdcOverride override = getStartTime(new MdcOverride()); - String fullUrl = getFullUrl("/" + indexName, false); - HttpURLConnection conn = initializeConnection(fullUrl); - - try { - conn.setRequestMethod("HEAD"); - - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException("Failed to set HTTP request method to HEAD.", e); - } - - logger.debug("Sending 'HEAD' request to: " + conn.getURL()); - + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder(indexName)), HttpMethod.HEAD); int resultCode; try { resultCode = conn.getResponseCode(); - } catch (IOException e) { + } catch (IOException ex) { shutdownConnection(conn); - throw new DocumentStoreOperationException(FAILED_TO_GET_THE_RESPONSE_CODE_FROM_THE_CONNECTION, e); + throw new DocumentStoreOperationException(ErrorMessage.NO_RESPONSE_CODE, ex); } logger.debug(MSG_RESPONSE_CODE + resultCode); @@ -751,22 +637,14 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { return opResult; } - // Grab the current time so we can use it to generate a metrics log. + final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, document.getId())); MdcOverride override = getStartTime(new MdcOverride()); - String fullUrl = getFullUrl("/" + indexName + "/" + DEFAULT_TYPE + "/" + document.getId(), false); - HttpURLConnection conn = initializeConnection(fullUrl); + HttpURLConnection conn = createConnection(url, HttpMethod.PUT); - try { - conn.setRequestMethod("PUT"); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException(MSG_HTTP_PUT_FAILED, e); - } attachDocument(conn, document); - logger.debug("Sending 'PUT' request to: " + conn.getURL()); opResult = getOperationResult(conn); buildDocumentResult(opResult, indexName); @@ -780,23 +658,12 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { private DocumentOperationResult createDocumentWithoutId(String indexName, DocumentStoreDataEntity document) throws DocumentStoreOperationException { - // Grab the current time so we can use it to generate a metrics log. - MdcOverride override = getStartTime(new MdcOverride()); - - String fullUrl = getFullUrl("/" + indexName + "/" + DEFAULT_TYPE, false); - HttpURLConnection conn = initializeConnection(fullUrl); - - try { - conn.setRequestMethod("POST"); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException(MSG_HTTP_POST_FAILED, e); - } + final URL url = buildUrl(createUriBuilder(indexName, DEFAULT_TYPE)); + MdcOverride override = getStartTime(new MdcOverride()); + HttpURLConnection conn = createConnection(url, HttpMethod.POST); attachDocument(conn, document); - logger.debug("Sending 'POST' request to: " + conn.getURL()); - DocumentOperationResult response = getOperationResult(conn); buildDocumentResult(response, indexName); @@ -815,27 +682,15 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { private DocumentOperationResult checkDocumentExistence(String indexName, String docId) throws DocumentStoreOperationException { - // Grab the current time so we can use it to generate a metrics log. MdcOverride override = getStartTime(new MdcOverride()); - - String fullUrl = getFullUrl("/" + indexName + "/" + DEFAULT_TYPE + "/" + docId, false); - HttpURLConnection conn = initializeConnection(fullUrl); - - try { - conn.setRequestMethod("HEAD"); - } catch (ProtocolException e) { - shutdownConnection(conn); - throw new DocumentStoreOperationException("Failed to set HTTP request method to HEAD.", e); - } - - logger.debug("Sending 'HEAD' request to: " + conn.getURL()); - + HttpURLConnection conn = + createConnection(buildUrl(createUriBuilder(indexName, DEFAULT_TYPE, docId)), HttpMethod.HEAD); int resultCode; try { resultCode = conn.getResponseCode(); - } catch (IOException e) { + } catch (IOException ex) { shutdownConnection(conn); - throw new DocumentStoreOperationException(FAILED_TO_GET_THE_RESPONSE_CODE_FROM_THE_CONNECTION, e); + throw new DocumentStoreOperationException(ErrorMessage.NO_RESPONSE_CODE, ex); } logger.debug(MSG_RESPONSE_CODE + resultCode); @@ -871,16 +726,8 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { } } - private HttpURLConnection initializeConnection(String fullUrl) throws DocumentStoreOperationException { - URL url = null; + private HttpURLConnection initializeConnection(URL url) throws DocumentStoreOperationException { HttpURLConnection conn = null; - - try { - url = new URL(fullUrl); - } catch (MalformedURLException e) { - throw new DocumentStoreOperationException("Error building a URL with " + url, e); - } - try { conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty(CONTENT_TYPE, APPLICATION_JSON); @@ -903,9 +750,9 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { try { resultCode = conn.getResponseCode(); - } catch (IOException e) { + } catch (IOException ex) { shutdownConnection(conn); - throw new DocumentStoreOperationException(FAILED_TO_GET_THE_RESPONSE_CODE_FROM_THE_CONNECTION, e); + throw new DocumentStoreOperationException(ErrorMessage.NO_RESPONSE_CODE, ex); } logger.debug(MSG_RESPONSE_CODE + resultCode); @@ -980,8 +827,7 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { // Grab the current time... long startTimeInMs = System.currentTimeMillis(); - // ...and add it as an attribute to the supplied MDC Override - // object. + // ...and add it as an attribute to the supplied MDC Override object. SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); override.addAttribute(MdcContext.MDC_START_TIME, formatter.format(startTimeInMs)); @@ -1003,37 +849,48 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { return Family.familyOf(statusCode).equals(Family.SUCCESSFUL); } - private OperationResult checkConnection() throws IOException { - String fullUrl = getFullUrl("/_cluster/health", false); - URL url = null; - HttpURLConnection conn = null; + private UriBuilder createUriBuilder(String path, String... paths) { + UriBuilder builder = UriBuilder.fromPath(path); + for (String other : paths) { + builder.path(other); + } + builder.host(config.getIpAddress()); + String port = Optional.ofNullable(config.getHttpPort()).orElse("0"); + builder.port(Integer.valueOf(port)); + builder.scheme("http"); + return builder; + } - url = new URL(fullUrl); - conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod("GET"); - conn.setDoOutput(true); - logger.debug("getClusterHealth(), Sending 'GET' request to URL : " + url); + private URL buildUrl(UriBuilder builder) throws DocumentStoreOperationException { + try { + return builder.build().toURL(); + } catch (MalformedURLException e) { + logger.error(SearchDbMsgs.EXCEPTION_DURING_METHOD_CALL, "buildUrl", e.getLocalizedMessage()); + throw new DocumentStoreOperationException("Error building a URL with " + builder.toString(), e); + } + } + private HttpURLConnection createConnection(final URL url, final String method) + throws DocumentStoreOperationException { + HttpURLConnection conn = initializeConnection(url); + try { + logger.debug("\nSending '" + method + "' request to URL : " + conn.getURL()); + conn.setRequestMethod(method); + } catch (ProtocolException e) { + shutdownConnection(conn); + throw new DocumentStoreOperationException(ErrorMessage.SET_REQUEST_METHOD_FAILED, e, method); + } + return conn; + } + + private OperationResult checkConnection() throws IOException, DocumentStoreOperationException { + HttpURLConnection conn = createConnection(buildUrl(createUriBuilder("_cluster/health")), HttpMethod.GET); int resultCode = conn.getResponseCode(); logger.debug("getClusterHealth() response Code : " + resultCode); - shutdownConnection(conn); - return new OperationResultBuilder().resultCode(resultCode).build(); } - private String getFullUrl(String resourceUrl, boolean isSecure) { - - final String host = config.getIpAddress(); - final String port = config.getHttpPort(); - - if (isSecure) { - return String.format("https://%s:%s%s", host, port, resourceUrl); - } else { - return String.format("http://%s:%s%s", host, port, resourceUrl); - } - } - private void shutdownConnection(HttpURLConnection connection) { if (connection == null) { return; diff --git a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java index 69cab3f..7db6c4e 100644 --- a/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java +++ b/src/main/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/exception/DocumentStoreOperationException.java @@ -22,14 +22,32 @@ package org.onap.aai.sa.searchdbabstraction.elasticsearch.exception; public class DocumentStoreOperationException extends Exception { - private static final long serialVersionUID = -7689309913743200670L; + private static final long serialVersionUID = -7689309913743200670L; - public DocumentStoreOperationException(String message, Exception ex) { - super(message, ex); - } + public enum ErrorMessage { + NO_RESPONSE_CODE( + "Failed to get the response code from the connection." + ), + SET_REQUEST_METHOD_FAILED( + "Failed to set HTTP request method to %s." + ); + private String message; - public DocumentStoreOperationException(String message) { - super(message); - } + ErrorMessage(String msg) { + this.message = msg; + } + } + + public DocumentStoreOperationException(ErrorMessage error, Exception ex, Object... args) { + super(String.format(error.message, args), ex); + } + + public DocumentStoreOperationException(String message, Exception ex) { + super(message, ex); + } + + public DocumentStoreOperationException(String message) { + super(message); + } } diff --git a/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java b/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java index e68534c..3cfb58a 100644 --- a/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java +++ b/src/test/java/org/onap/aai/sa/searchdbabstraction/elasticsearch/dao/ElasticSearchHttpControllerTest.java @@ -20,219 +20,295 @@ */ package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; -import org.json.JSONException; +import static org.hamcrest.CoreMatchers.anyOf; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.either; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.assertThat; + +import java.util.Properties; import org.json.JSONObject; -import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import org.onap.aai.sa.rest.DocumentSchema; import org.onap.aai.sa.searchdbabstraction.elasticsearch.config.ElasticSearchConfig; import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; -import java.util.Properties; - @Ignore("All tests in this classes require an Elasticsearch instance to run locally") public class ElasticSearchHttpControllerTest { - private static ElasticSearchHttpController elasticSearch; - private static AAIEntityTestObject testDocument; - - private static final String indexMappings = "{\r\n \"properties\": {\r\n \"entityType\": {\r\n \"type\": \"string\"\r\n },\r\n \"edgeTagQueryEntityFieldName\": {\r\n \"type\": \"string\",\r\n \"index\": \"no\"\r\n },\r\n \"edgeTagQueryEntityFieldValue\": {\r\n \"type\": \"string\",\r\n \"index\": \"no\"\r\n },\r\n \"searchTagIDs\" : {\r\n \"type\" : \"string\"\r\n },\r\n \"searchTags\": {\r\n \"type\": \"string\",\r\n \"analyzer\": \"nGram_analyzer\",\r\n \"search_analyzer\": \"whitespace_analyzer\"\r\n }\r\n }\r\n}"; - private static final String indexSettings = "{\r\n \"analysis\": {\r\n \"filter\": {\r\n \"nGram_filter\": {\r\n \"type\": \"nGram\",\r\n \"min_gram\": 1,\r\n \"max_gram\": 50,\r\n \"token_chars\": [\r\n \"letter\",\r\n \"digit\",\r\n \"punctuation\",\r\n \"symbol\"\r\n ]\r\n }\r\n },\r\n \"analyzer\": {\r\n \"nGram_analyzer\": {\r\n \"type\": \"custom\",\r\n \"tokenizer\": \"whitespace\",\r\n \"filter\": [\r\n \"lowercase\",\r\n \"asciifolding\",\r\n \"nGram_filter\"\r\n ]\r\n },\r\n \"whitespace_analyzer\": {\r\n \"type\": \"custom\",\r\n \"tokenizer\": \"whitespace\",\r\n \"filter\": [\r\n \"lowercase\",\r\n \"asciifolding\"\r\n ]\r\n }\r\n }\r\n }\r\n}"; - - @Before - public void setUp() throws Exception { - Properties properties = new Properties(); - properties.put(ElasticSearchConfig.ES_IP_ADDRESS, "127.0.0.1"); - properties.put(ElasticSearchConfig.ES_HTTP_PORT, "9200"); -// ElasticSearchConfig config = new ElasticSearchConfig(properties); - ElasticSearchConfig config = new ElasticSearchConfig(properties); - elasticSearch = new ElasticSearchHttpController(config); - - testDocument = new AAIEntityTestObject(); - testDocument.setId("test123"); - testDocument.setEntityType("service-instance"); - testDocument.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); - testDocument.setEdgeTagQueryEntityFieldValue("123456"); - testDocument.setSearchTagIDs("0"); - testDocument.setSearchTags("service-instance-id"); - - } -// - @Test - public void testCreateTable() throws Exception { - OperationResult result = elasticSearch.createTable("test", "aai-entities", indexSettings, indexMappings); - System.out.println(result); - } - - @Test - public void testsuggestionQueryWithPayload() throws Exception { - Assert.assertNotNull(elasticSearch.suggestionQueryWithPayload("autoSuggest", "suggest-index")); - } -// - @Test - public void testCreateDocument() throws Exception { - OperationResult result = elasticSearch.createDocument("test", testDocument, false); - System.out.println(result); - - DocumentStoreDataEntityImpl ds = new DocumentStoreDataEntityImpl(); - ds.setId(testDocument.getId()); - - result = elasticSearch.getDocument("test", ds); - System.out.println(result); - } - - @Test - public void testUpdateDocument() throws Exception { - testDocument.setEdgeTagQueryEntityFieldValue("567890"); - - OperationResult result = elasticSearch.updateDocument("test", testDocument, false); - System.out.println(result); - - result = elasticSearch.getDocument("test", testDocument); - System.out.println(result); - } - - @Test - public void testDeleteDocument() throws Exception { - OperationResult result = elasticSearch.deleteDocument("test", testDocument); - System.out.println(result); - - result = elasticSearch.getDocument("test", testDocument); - System.out.println(result); - } - - @Test - public void testBulkCreateDocuments() throws Exception { - for (int i = 0; i < 10; i++) { - AAIEntityTestObject doc = new AAIEntityTestObject(); - doc.setId("test-" + i); - doc.setEntityType("service-instance"); - doc.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); - doc.setEdgeTagQueryEntityFieldValue("123456" + i); - doc.setSearchTagIDs("" + i); - doc.setSearchTags("service-instance-id"); + static { + // Set the location of the payload translation JSON file. + System.setProperty("CONFIG_HOME", "src/test/resources/json"); + } - OperationResult result = elasticSearch.createDocument("test", doc, false); - System.out.println(result); + private static ElasticSearchHttpController elasticSearch; + private static AAIEntityTestObject testDocument; + + private static final String TEST_INDEX_NAME = "test"; + + private static final String indexMappings = + "{\r\n \"properties\": {\r\n \"entityType\": {\r\n \"type\": \"text\"\r\n },\r\n" + + " \"edgeTagQueryEntityFieldName\": {\r\n \"type\": \"text\",\r\n \"index\": \"false\"\r\n },\r\n" + + " \"edgeTagQueryEntityFieldValue\": {\r\n \"type\": \"text\",\r\n \"index\": \"false\"\r\n },\r\n \"searchTagIDs\" : {\r\n \"type\" : \"text\"\r\n },\r\n \"searchTags\": {\r\n \"type\": \"text\",\r\n \"analyzer\": \"nGram_analyzer\",\r\n \"search_analyzer\": \"whitespace_analyzer\"\r\n }\r\n }\r\n}"; + private static final String indexSettings = + "{\r\n \"analysis\": {\r\n \"filter\": {\r\n \"nGram_filter\": {\r\n \"type\": \"nGram\",\r\n \"min_gram\": 1,\r\n \"max_gram\": 50,\r\n \"token_chars\": [\r\n \"letter\",\r\n \"digit\",\r\n \"punctuation\",\r\n \"symbol\"\r\n ]\r\n }\r\n },\r\n \"analyzer\": {\r\n \"nGram_analyzer\": {\r\n \"type\": \"custom\",\r\n \"tokenizer\": \"whitespace\",\r\n \"filter\": [\r\n \"lowercase\",\r\n \"asciifolding\",\r\n \"nGram_filter\"\r\n ]\r\n },\r\n \"whitespace_analyzer\": {\r\n \"type\": \"custom\",\r\n \"tokenizer\": \"whitespace\",\r\n \"filter\": [\r\n \"lowercase\",\r\n \"asciifolding\"\r\n ]\r\n }\r\n }\r\n }\r\n}"; + + @Before + public void setUp() throws Exception { + Properties properties = new Properties(); + properties.put(ElasticSearchConfig.ES_IP_ADDRESS, "127.0.0.1"); + properties.put(ElasticSearchConfig.ES_HTTP_PORT, "9200"); + elasticSearch = new ElasticSearchHttpController(new ElasticSearchConfig(properties)); + + testDocument = new AAIEntityTestObject(); + testDocument.setId("test123"); + testDocument.setEntityType("service-instance"); + testDocument.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); + testDocument.setEdgeTagQueryEntityFieldValue("123456"); + testDocument.setSearchTagIDs("0"); + testDocument.setSearchTags("service-instance-id"); } - } - @Test - public void serchByEntityType() throws Exception { - OperationResult result = elasticSearch.search("test", "q=instance"); - System.out.println(result); - } + @Test + public void testGetInstance() throws Exception { + ElasticSearchHttpController.getInstance(); + } - @Test - public void serchByTagIDs() throws Exception { - OperationResult result = elasticSearch.search("test", "q=9"); - System.out.println(result); - } + @Test + public void testCreateIndex() throws Exception { + testDeleteIndex(); + OperationResult result = elasticSearch.createIndex(TEST_INDEX_NAME, new DocumentSchema()); + assertThat(result.getResult(), containsString("/search/indexes/test")); + assertThat(result.getResultCode(), is(201)); - @Test - public void serchByTags() throws Exception { - OperationResult result = elasticSearch.search("test", "q=service"); - System.out.println(result); - } + result = elasticSearch.createIndex(TEST_INDEX_NAME, new DocumentSchema()); + assertThat(result.getResult(), containsString("already exists")); + assertThat(result.getResultCode(), is(400)); + } - @Test - public void testCreateDocumentWithoutId() throws Exception { - AAIEntityTestObject doc = new AAIEntityTestObject(); - doc.setEntityType("service-instance"); - doc.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); - doc.setEdgeTagQueryEntityFieldValue("1111111"); - doc.setSearchTagIDs("321"); - doc.setSearchTags("service-instance-id"); + @Test(expected = IllegalArgumentException.class) + public void testCreateDynamicIndexEmptySchema() throws Exception { + elasticSearch.createDynamicIndex(TEST_INDEX_NAME, ""); + } - OperationResult result = elasticSearch.createDocument("test", doc, false); - System.out.println(result); - } + @Test + public void testCreateDynamicIndex() throws Exception { + String indexName = "test_dynamic"; + elasticSearch.deleteIndex(indexName); - @Test - public void testDeleteIndex() throws Exception { - OperationResult result = elasticSearch.deleteIndex("test"); - System.out.println(result); - } -// - class AAIEntityTestObject implements DocumentStoreDataEntity { - private String id; - private String entityType; - private String edgeTagQueryEntityFieldName; - private String edgeTagQueryEntityFieldValue; - private String searchTagIDs; - private String searchTags; + OperationResult result = elasticSearch.createDynamicIndex(indexName, + "{\"mappings\":{\"_doc\":{\"dynamic_templates\":[{\"strings_as_text\":{\"match_mapping_type\":\"string\",\"mapping\":{\"type\":\"text\"}}}]}}}"); + assertThat(result.getResult(), containsString("/search/indexes/test")); + assertThat(result.getResultCode(), is(201)); - public void setId(String id) { - this.id = id; + elasticSearch.deleteIndex(indexName); } - @Override - public String getId() { - return this.id; + @Test + public void testCreateTable() throws Exception { + OperationResult result = + elasticSearch.createTable(TEST_INDEX_NAME, "aai-entities", indexSettings, indexMappings); + assertThat(result.getResult(), containsString("\"index\":\"test\"}")); + assertThat(result.getResultCode(), either(is(200)).or(is(400))); } - public String getEntityType() { - return entityType; + @Test + public void testCreateDocument() throws Exception { + OperationResult result = elasticSearch.createDocument(TEST_INDEX_NAME, testDocument, false); + assertThat(result.getResult(), not(equalTo(""))); + + DocumentStoreDataEntityImpl ds = new DocumentStoreDataEntityImpl(); + ds.setId(testDocument.getId()); + + result = elasticSearch.getDocument(TEST_INDEX_NAME, ds); + assertThat(result.getResult(), not(equalTo(""))); } - public void setEntityType(String entityType) { - this.entityType = entityType; + @Test + public void testCreateDocumentInvalidIndex() throws Exception { + OperationResult result = elasticSearch.createDocument("index_does_not_exist", testDocument, false); + assertThat(result.getResultCode(), is(404)); + assertThat(result.getResult(), not(equalTo(""))); } - public String getEdgeTagQueryEntityFieldName() { - return edgeTagQueryEntityFieldName; + @Test + public void testUpdateDocument() throws Exception { + testDocument.setEdgeTagQueryEntityFieldValue("567890"); + + OperationResult result = elasticSearch.getDocument(TEST_INDEX_NAME, testDocument); + if (result.getResultCode() == 404) { + testCreateDocument(); + } + // assertThat(result.getResultCode(), anyOf(equalTo(200), equalTo(412))); + // assertThat(result.getResult(), containsString("\"found\":true")); + + result = elasticSearch.updateDocument(TEST_INDEX_NAME, testDocument, false); + assertThat(result.getResultCode(), anyOf(equalTo(200), equalTo(412))); + + result = elasticSearch.getDocument(TEST_INDEX_NAME, testDocument); + assertThat(result.getResult(), containsString("test123")); } - public void setEdgeTagQueryEntityFieldName(String edgeTagQueryEntityFieldName) { - this.edgeTagQueryEntityFieldName = edgeTagQueryEntityFieldName; + @Test + public void testDeleteDocument() throws Exception { + OperationResult result = elasticSearch.deleteDocument(TEST_INDEX_NAME, testDocument); + assertThat(result.getResult(), containsString(TEST_INDEX_NAME)); + + result = elasticSearch.getDocument(TEST_INDEX_NAME, testDocument); + assertThat(result.getResult(), containsString("test123")); } - public String getEdgeTagQueryEntityFieldValue() { - return edgeTagQueryEntityFieldValue; + @Test + public void testBulkCreateDocuments() throws Exception { + for (int i = 0; i < 10; i++) { + AAIEntityTestObject doc = new AAIEntityTestObject(); + doc.setId("test-" + i); + doc.setEntityType("service-instance"); + doc.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); + doc.setEdgeTagQueryEntityFieldValue("123456" + i); + doc.setSearchTagIDs("" + i); + doc.setSearchTags("service-instance-id"); + + // OperationResult result = elasticSearch.createDocument(TEST_INDEX_NAME, doc, false); + // assertThat(result.getResultCode(), anyOf(equalTo(201), equalTo(400))); + } } - public void setEdgeTagQueryEntityFieldValue(String edgeTagQueryEntityFieldValue) { - this.edgeTagQueryEntityFieldValue = edgeTagQueryEntityFieldValue; + @Test + public void serchByEntityType() throws Exception { + OperationResult result = elasticSearch.search(TEST_INDEX_NAME, "q=instance"); + assertThat(result.getResult(), not(equalTo(""))); } - public String getSearchTagIDs() { - return searchTagIDs; + @Test + public void serchByTagIDs() throws Exception { + OperationResult result = elasticSearch.search(TEST_INDEX_NAME, "q=9"); + assertThat(result.getResult(), not(equalTo(""))); } - public void setSearchTagIDs(String searchTagIDs) { - this.searchTagIDs = searchTagIDs; + @Test + public void serchByTags() throws Exception { + OperationResult result = elasticSearch.search(TEST_INDEX_NAME, "q=service"); + assertThat(result.getResult(), not(equalTo(""))); } - public String getSearchTags() { - return searchTags; + @Test + public void searchWithPayload() throws Exception { + testCreateIndex(); + OperationResult result = + elasticSearch.searchWithPayload(TEST_INDEX_NAME, "{\"query\":{\"term\":{\"user\":\"fred\"}}}"); + assertThat(result.getResult(), containsString("successful")); + assertThat(result.getResultCode(), is(equalTo(200))); } - public void setSearchTags(String searchTags) { - this.searchTags = searchTags; + /** + * The _suggest endpoint appears to be deprecated in ES 5.x and above. + */ + @Test + public void suggestionQueryWithPayload() throws Exception { + testCreateIndex(); + OperationResult result = elasticSearch.suggestionQueryWithPayload(TEST_INDEX_NAME, + "{\"my-suggestion\":{\"text\":\"fred\",\"term\":{\"field\":\"body\"}}}"); + assertThat(result.getResult(), containsString("error")); + assertThat(result.getResultCode(), is(equalTo(400))); } - @Override - public String getVersion() { - return "1"; + @Test + public void testCreateDocumentWithoutId() throws Exception { + AAIEntityTestObject doc = new AAIEntityTestObject(); + doc.setEntityType("service-instance"); + doc.setEdgeTagQueryEntityFieldName("service-instance.service-instance-id"); + doc.setEdgeTagQueryEntityFieldValue("1111111"); + doc.setSearchTagIDs("321"); + doc.setSearchTags("service-instance-id"); + + OperationResult result = elasticSearch.createDocument(TEST_INDEX_NAME, doc, false); + assertThat(result.getResult(), not(equalTo(""))); } - @Override - public String getContentInJson() { - try { - return new JSONObject() - .put("entityType", entityType) - .put("edgeTagQueryEntityFieldName", edgeTagQueryEntityFieldName) - .put("edgeTagQueryEntityFieldValue", edgeTagQueryEntityFieldValue) - .put("searchTagIDs", searchTagIDs) - .put("searchTags", searchTags).toString(); - } catch (JSONException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return null; - } + @Test + public void testDeleteIndex() throws Exception { + OperationResult result = elasticSearch.deleteIndex(TEST_INDEX_NAME); + assertThat(result.getResultCode(), anyOf(equalTo(200), equalTo(404))); + assertThat(result.getResult(), not(equalTo(""))); } - } + class AAIEntityTestObject implements DocumentStoreDataEntity { + private String id; + private String entityType; + private String edgeTagQueryEntityFieldName; + private String edgeTagQueryEntityFieldValue; + private String searchTagIDs; + private String searchTags; + + public void setId(String id) { + this.id = id; + } + + @Override + public String getId() { + return this.id; + } + + public String getEntityType() { + return entityType; + } + + public void setEntityType(String entityType) { + this.entityType = entityType; + } + + public String getEdgeTagQueryEntityFieldName() { + return edgeTagQueryEntityFieldName; + } + + public void setEdgeTagQueryEntityFieldName(String edgeTagQueryEntityFieldName) { + this.edgeTagQueryEntityFieldName = edgeTagQueryEntityFieldName; + } + + public String getEdgeTagQueryEntityFieldValue() { + return edgeTagQueryEntityFieldValue; + } + + public void setEdgeTagQueryEntityFieldValue(String edgeTagQueryEntityFieldValue) { + this.edgeTagQueryEntityFieldValue = edgeTagQueryEntityFieldValue; + } + + public String getSearchTagIDs() { + return searchTagIDs; + } + + public void setSearchTagIDs(String searchTagIDs) { + this.searchTagIDs = searchTagIDs; + } + + public String getSearchTags() { + return searchTags; + } + + public void setSearchTags(String searchTags) { + this.searchTags = searchTags; + } + + @Override + public String getVersion() { + return "1"; + } + + @Override + public String getContentInJson() { + return new JSONObject(). // + put("entityType", entityType) // + .put("edgeTagQueryEntityFieldName", edgeTagQueryEntityFieldName) + .put("edgeTagQueryEntityFieldValue", edgeTagQueryEntityFieldValue) // + .put("searchTagIDs", searchTagIDs) // + .put("searchTags", searchTags) // + .toString(); + } + } } -- 2.16.6