X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Forg%2Fonap%2Faai%2Fsa%2Fsearchdbabstraction%2Felasticsearch%2Fdao%2FElasticSearchHttpController.java;h=98a254c836af4bf67570a0d878342899465c1592;hb=82658daad05f982a8358581623f44a1554238a48;hp=060107e9468c514e785cc7915f24ea29a4d7bf17;hpb=50becb8a60c614344c85cccb20830395283a4454;p=aai%2Fsearch-data-service.git 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 060107e..98a254c 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 @@ -2,8 +2,8 @@ * ============LICENSE_START======================================================= * org.onap.aai * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,18 +17,15 @@ * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ package org.onap.aai.sa.searchdbabstraction.elasticsearch.dao; -import com.att.aft.dme2.internal.google.common.base.Throwables; +import com.google.common.base.Throwables; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.emory.mathcs.backport.java.util.Arrays; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; @@ -51,6 +48,7 @@ import org.onap.aai.sa.searchdbabstraction.entity.SearchOperationResult; import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; import org.onap.aai.sa.searchdbabstraction.util.AggregationParsingUtil; import org.onap.aai.sa.searchdbabstraction.util.DocumentSchemaUtil; +import org.onap.aai.sa.searchdbabstraction.util.ElasticSearchPayloadTranslator; import org.onap.aai.sa.searchdbabstraction.util.SearchDbConstants; import org.onap.aai.cl.api.LogFields; import org.onap.aai.cl.api.LogLine; @@ -59,6 +57,8 @@ import org.onap.aai.cl.eelf.LoggerFactory; import org.onap.aai.cl.mdc.MdcContext; import org.onap.aai.cl.mdc.MdcOverride; import org.onap.aai.sa.rest.DocumentSchema; +import org.onap.aai.sa.searchdbabstraction.entity.SuggestHit; +import org.onap.aai.sa.searchdbabstraction.entity.SuggestHits; import java.io.BufferedReader; import java.io.File; @@ -76,10 +76,13 @@ import java.net.ProtocolException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; -import javax.ws.rs.core.Response.Status; + +import org.springframework.http.HttpStatus; + /** @@ -177,7 +180,7 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { //result.setResult("{\"index\": \"" + index + ", \"type\": \"" + DEFAULT_TYPE + "\"}"); } - } catch (DocumentStoreOperationException e) { + } catch (DocumentStoreOperationException | IOException e) { result.setFailureCause("Document store operation failure. Cause: " + e.getMessage()); } @@ -185,6 +188,27 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { return result; } + @Override + public OperationResult createDynamicIndex(String index, String dynamicSchema) { + OperationResult result = new OperationResult(); + result.setResultCode(500); + + try { + result = createTable(index, dynamicSchema); + + // ElasticSearch will return us a 200 code on success when we + // want to report a 201, so translate the result here. + result.setResultCode((result.getResultCode() == 200) ? 201 : result.getResultCode()); + if (isSuccess(result)) { + result.setResult("{\"url\": \"" + ApiUtils.buildIndexUri(index) + "\"}"); + } + } catch (DocumentStoreOperationException e) { + result.setFailureCause("Document store operation failure. Cause: " + e.getMessage()); + } + + return result; + } + @Override public OperationResult deleteIndex(String indexName) throws DocumentStoreOperationException { @@ -327,6 +351,7 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { try { conn.setRequestMethod("PUT"); + conn.setRequestProperty("Content-Type", "application/json"); } catch (ProtocolException e) { shutdownConnection(conn); throw new DocumentStoreOperationException("Failed to set HTTP request method to PUT.", e); @@ -342,7 +367,12 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { sb.append(indexMappings); sb.append("}}"); - attachContent(conn, sb.toString()); + try { + attachContent(conn, ElasticSearchPayloadTranslator.translateESPayload(sb.toString())); + } catch(IOException e) { + logger.error(SearchDbMsgs.INDEX_CREATE_FAILURE, e); + throw new DocumentStoreOperationException(e.getMessage(), e); + } logger.debug("\ncreateTable(), Sending 'PUT' request to URL : " + conn.getURL()); logger.debug("Request content: " + sb.toString()); @@ -362,29 +392,76 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { return opResult; } + /** + * Will send the passed in JSON payload to Elasticsearch using the + * provided index name in an attempt to create the index. + * + * @param indexName - The name of the index to be created + * @param settingsAndMappings - The actual JSON object that will define the index + * @return - The operation result of writing into Elasticsearch + * @throws DocumentStoreOperationException + */ + protected OperationResult createTable(String indexName, String settingsAndMappings) throws DocumentStoreOperationException { + OperationResult result = new OperationResult(); + result.setResultCode(500); + result.setResult(INTERNAL_SERVER_ERROR_ELASTIC_SEARCH_OPERATION_FAULT); + + // 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"); + conn.setRequestProperty("Content-Type", "application/json"); + } catch (ProtocolException e) { + shutdownConnection(conn); + throw new DocumentStoreOperationException("Failed to set HTTP request method to PUT.", e); + } + + try { + attachContent(conn, ElasticSearchPayloadTranslator.translateESPayload(settingsAndMappings)); + } catch(IOException e) { + logger.error(SearchDbMsgs.INDEX_CREATE_FAILURE, e); + throw new DocumentStoreOperationException(e.getMessage()); + } + handleResponse(conn, result); + + // Generate a metrics log so we can track how long the operation took. + metricsLogger.info(SearchDbMsgs.CREATE_INDEX_TIME, + new LogFields() + .setField(LogLine.DefinedFields.RESPONSE_CODE, result.getResultCode()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, result.getResultCode()), + override, + indexName); + + return result; + } + @Override - public DocumentOperationResult createDocument(String indexName, + public DocumentOperationResult createDocument(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 // create because it could be configured to implicitly create a non-existent index, // which can lead to hard-to-debug behaviour with queries down the road. OperationResult indexExistsResult = checkIndexExistence(indexName); if ((indexExistsResult.getResultCode() < 200) || (indexExistsResult.getResultCode() >= 300)) { - + DocumentOperationResult opResult = new DocumentOperationResult(); - opResult.setResultCode(Status.NOT_FOUND.getStatusCode()); + opResult.setResultCode(HttpStatus.NOT_FOUND.value()); opResult.setResult("Document Index '" + indexName + "' does not exist."); opResult.setFailureCause("Document Index '" + indexName + "' does not exist."); return opResult; } } - + if (document.getId() == null || document.getId().isEmpty()) { return createDocumentWithoutId(indexName, document); } else { @@ -399,13 +476,13 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { DocumentOperationResult opResult = checkDocumentExistence(indexName, document.getId()); - if (opResult.getResultCode() != Status.NOT_FOUND.getStatusCode()) { - if (opResult.getResultCode() == Status.OK.getStatusCode()) { + if (opResult.getResultCode() != HttpStatus.NOT_FOUND.value()) { + if (opResult.getResultCode() == HttpStatus.CONFLICT.value()) { opResult.setFailureCause("A document with the same id already exists."); } else { opResult.setFailureCause("Failed to verify a document with the specified id does not already exist."); } - opResult.setResultCode(Status.CONFLICT.getStatusCode()); + opResult.setResultCode(HttpStatus.CONFLICT.value()); return opResult; } @@ -493,9 +570,9 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { private void attachDocument(HttpURLConnection conn, DocumentStoreDataEntity doc) throws DocumentStoreOperationException { - conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); +// conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + conn.setRequestProperty("Content-Type", "application/json"); conn.setRequestProperty("Connection", "Close"); - attachContent(conn, doc.getContentInJson()); } @@ -549,28 +626,28 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { } @Override - public DocumentOperationResult updateDocument(String indexName, + 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 // create because it could be configured to implicitly create a non-existent index, // which can lead to hard-to-debug behaviour with queries down the road. OperationResult indexExistsResult = checkIndexExistence(indexName); if ((indexExistsResult.getResultCode() < 200) || (indexExistsResult.getResultCode() >= 300)) { - + DocumentOperationResult opResult = new DocumentOperationResult(); - opResult.setResultCode(Status.NOT_FOUND.getStatusCode()); + opResult.setResultCode(HttpStatus.NOT_FOUND.value()); opResult.setResult("Document Index '" + indexName + "' does not exist."); opResult.setFailureCause("Document Index '" + indexName + "' does not exist."); return opResult; } } - + DocumentOperationResult opResult = new DocumentOperationResult(); // Initialize operation result with a failure codes / fault string @@ -586,6 +663,7 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { try { conn.setRequestMethod("PUT"); + conn.setRequestProperty("Content-Type", "application/json"); } catch (ProtocolException e) { shutdownConnection(conn); throw new DocumentStoreOperationException("Failed to set HTTP request method to PUT.", e); @@ -759,6 +837,7 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { try { conn.setRequestMethod("POST"); + conn.setRequestProperty("Content-Type", "application/json"); } catch (ProtocolException e) { shutdownConnection(conn); throw new DocumentStoreOperationException("Failed to set HTTP request method to POST.", e); @@ -785,6 +864,53 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { return opResult; } + + public SearchOperationResult suggestionQueryWithPayload(String indexName, String query) + throws DocumentStoreOperationException { + + SearchOperationResult opResult = new SearchOperationResult(); + + if (logger.isDebugEnabled()) { + logger.debug("Querying Suggestion index: " + indexName + " with query string: " + query); + } + + // Initialize operation result with a failure codes / fault string + opResult.setResultCode(500); + opResult.setResult(INTERNAL_SERVER_ERROR_ELASTIC_SEARCH_OPERATION_FAULT); + + 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"); + conn.setRequestProperty("Content-Type", "application/json"); + } catch (ProtocolException e) { + shutdownConnection(conn); + throw new DocumentStoreOperationException("Failed to set HTTP request method to POST.", e); + } + + attachContent(conn, query); + + logger.debug("\nsearch(), Sending 'POST' request to URL : " + conn.getURL()); + logger.debug("Request body = Elasticsearch query = " + query); + + handleResponse(conn, opResult); + buildSuggestResult(opResult, indexName); + + metricsLogger.info(SearchDbMsgs.QUERY_DOCUMENT_TIME, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, opResult.getResultCode()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, opResult.getResult()), + override, indexName, query); + + shutdownConnection(conn); + + return opResult; + } + private void attachContent(HttpURLConnection conn, String content) throws DocumentStoreOperationException { OutputStream outputStream = null; @@ -871,8 +997,8 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { throw new DocumentStoreOperationException("Failed getting the response body payload.", e); } - if (resultCode == Status.CONFLICT.getStatusCode()) { - opResult.setResultCode(Status.PRECONDITION_FAILED.getStatusCode()); + if (resultCode == HttpStatus.CONFLICT.value()) { + opResult.setResultCode(HttpStatus.PRECONDITION_FAILED.value()); } else { opResult.setResultCode(resultCode); } @@ -1631,4 +1757,64 @@ public class ElasticSearchHttpController implements DocumentStoreInterface { } -} + private void buildSuggestResult(SearchOperationResult result, String index) + throws DocumentStoreOperationException { + + JSONParser parser = new JSONParser (); + JSONObject root; + try { + root = (JSONObject) parser.parse ( result.getResult () ); + if (result.getResultCode () >= 200 && result.getResultCode () <= 299) { + JSONArray hitArray = (JSONArray) root.get ( "suggest-vnf" ); + JSONObject hitdata = (JSONObject) hitArray.get ( 0 ); + JSONArray optionsArray = (JSONArray) hitdata.get ( "options" ); + SuggestHits suggestHits = new SuggestHits (); + suggestHits.setTotalHits ( String.valueOf ( optionsArray.size () ) ); + + ArrayList suggestHitArray = new ArrayList (); + + for (int i = 0; i < optionsArray.size (); i++) { + JSONObject hit = (JSONObject) optionsArray.get ( i ); + + SuggestHit suggestHit = new SuggestHit (); + suggestHit.setScore ( (hit.get ( "score" ) != null) ? hit.get ( "score" ).toString () : "" ); + suggestHit.setText ( (hit.get ( "text" ) != null) ? hit.get ( "text" ).toString () : "" ); + Document doc = new Document (); + if (hit.get ( "_version" ) != null) { + doc.setEtag ( (hit.get ( "_version" ) != null) ? hit.get ( "_version" ).toString () : "" ); + } + doc.setUrl ( buildDocumentResponseUrl ( index, + (hit.get ( "_id" ) != null) ? hit.get ( "_id" ).toString () : "" ) ); + + doc.setContent ( (JSONObject) hit.get ( "payload" ) ); + suggestHit.setDocument ( doc ); + suggestHitArray.add ( suggestHit ); + } + suggestHits.setHits ( suggestHitArray.toArray ( new SuggestHit[suggestHitArray.size ()] ) ); + result.setSuggestResult ( suggestHits ); + + JSONObject aggregations = (JSONObject) root.get ( "aggregations" ); + if (aggregations != null) { + AggregationResult[] aggResults = + AggregationParsingUtil.parseAggregationResults ( aggregations ); + AggregationResults aggs = new AggregationResults (); + aggs.setAggregations ( aggResults ); + result.setAggregationResult ( aggs ); + } + + // success + } else { + JSONObject error = (JSONObject) root.get ( "error" ); + if (error != null) { + result.setError ( + new ErrorResult ( error.get ( "type" ).toString (), error.get ( "reason" ).toString () ) ); + } + } + } catch (Exception e) { + throw new DocumentStoreOperationException ( + "Failed to parse Elastic Search response." + result.getResult () ); + } + } + + + }