X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Forg%2Fonap%2Faai%2Fsa%2Frest%2FBulkApi.java;h=3a7b797f84e6f0e9ba2289e32d525cd4b17e939f;hb=ecd35f117eb0118f9cbd96fe132a1c359214bfc7;hp=143f248189281194ab5035af7af831d43c2974cc;hpb=22c477621c40c4762cceb67a1d18749bff68fb87;p=aai%2Fsearch-data-service.git diff --git a/src/main/java/org/onap/aai/sa/rest/BulkApi.java b/src/main/java/org/onap/aai/sa/rest/BulkApi.java index 143f248..3a7b797 100644 --- a/src/main/java/org/onap/aai/sa/rest/BulkApi.java +++ b/src/main/java/org/onap/aai/sa/rest/BulkApi.java @@ -1,9 +1,9 @@ -/** +/** * ============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,240 +17,194 @@ * 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.rest; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.fge.jsonschema.main.JsonSchema; import com.github.fge.jsonschema.main.JsonSchemaFactory; - +import java.io.IOException; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.servlet.http.HttpServletRequest; +import org.onap.aai.cl.api.LogFields; +import org.onap.aai.cl.api.LogLine; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; import org.onap.aai.sa.searchdbabstraction.elasticsearch.dao.DocumentStoreInterface; import org.onap.aai.sa.searchdbabstraction.elasticsearch.exception.DocumentStoreOperationException; import org.onap.aai.sa.searchdbabstraction.entity.OperationResult; import org.onap.aai.sa.searchdbabstraction.logging.SearchDbMsgs; -import org.openecomp.cl.api.LogFields; -import org.openecomp.cl.api.LogLine; -import org.openecomp.cl.api.Logger; -import org.openecomp.cl.eelf.LoggerFactory; - -import java.io.IOException; -import java.util.concurrent.atomic.AtomicBoolean; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.Path; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; /** - * This class encapsulates the REST end points associated with performing - * bulk operations against the document store. + * This class encapsulates the REST end points associated with performing bulk operations against the document store. */ -@Path("/bulk") public class BulkApi { - /** - * Indicates whether or not we have performed the one-time static - * initialization required for performing schema validation. - */ - protected static AtomicBoolean validationInitialized = new AtomicBoolean(false); - - /** - * Factory used for importing our payload schema for validation purposes. - */ - protected static JsonSchemaFactory schemaFactory = null; - - /** - * Imported payload schema that will be used by our validation methods. - */ - protected static JsonSchema schema = null; + /** + * Indicates whether or not we have performed the one-time static initialization required for performing schema + * validation. + */ + protected static AtomicBoolean validationInitialized = new AtomicBoolean(false); - protected SearchServiceApi searchService = null; + /** + * Factory used for importing our payload schema for validation purposes. + */ + protected static JsonSchemaFactory schemaFactory = null; - // Instantiate the loggers. - private static Logger logger = LoggerFactory.getInstance().getLogger(BulkApi.class.getName()); - private static Logger auditLogger = LoggerFactory.getInstance() - .getAuditLogger(BulkApi.class.getName()); + /** + * Imported payload schema that will be used by our validation methods. + */ + protected static JsonSchema schema = null; + protected SearchServiceApi searchService = null; - /** - * Create a new instance of the BulkApi end point. - */ - public BulkApi(SearchServiceApi searchService) { - this.searchService = searchService; - } + // Instantiate the loggers. + private static Logger logger = LoggerFactory.getInstance().getLogger(BulkApi.class.getName()); + private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(BulkApi.class.getName()); + private static final String MSG_STACK_TRACE = "Stack Trace:\n"; - /** - * Processes client requests containing a set of operations to be - * performed in bulk. - * - *

Method: POST - * - * @param operations - JSON structure enumerating the operations to be - * performed. - * @param request - Raw HTTP request. - * @param headers - HTTP headers. - * @return - A standard REST response structure. - */ - public Response processPost(String operations, - HttpServletRequest request, - HttpHeaders headers, - DocumentStoreInterface documentStore, - ApiUtils apiUtils) { - - - // Initialize the MDC Context for logging purposes. - ApiUtils.initMdcContext(request, headers); - - // Set a default result code and entity string for the request. - int resultCode = 500; - String resultString = "Unexpected error"; - - if (logger.isDebugEnabled()) { - logger.debug("SEARCH: Process Bulk Request - operations = [" - + operations.replaceAll("\n", "") + " ]"); + /** + * Create a new instance of the BulkApi end point. + */ + public BulkApi(SearchServiceApi searchService) { + this.searchService = searchService; } - try { - - // Validate that the request is correctly authenticated before going - // any further. - if (!searchService.validateRequest(headers, request, - ApiUtils.Action.POST, ApiUtils.SEARCH_AUTH_POLICY_NAME)) { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Authentication failure."); - - return buildResponse(Response.Status.FORBIDDEN.getStatusCode(), - "Authentication failure.", request, apiUtils); - } - } catch (Exception e) { - - // This is a catch all for any unexpected failure trying to perform - // the authentication. - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, - "Unexpected authentication failure - cause: " + e.getMessage()); - if (logger.isDebugEnabled()) { - logger.debug("Stack Trace:\n" + e.getStackTrace()); - } - - return buildResponse(Response.Status.FORBIDDEN.getStatusCode(), - "Authentication failure - cause " + e.getMessage(), - request, - apiUtils); + /** + * Processes client requests containing a set of operations to be performed in bulk. + * + *

+ * Method: POST + * + * @param operations - JSON structure enumerating the operations to be performed. + * @param request - Raw HTTP request. + * @param headers - HTTP headers. + * @return - A standard REST response structure. + */ + public ResponseEntity processPost(String operations, HttpServletRequest request, HttpHeaders headers, + DocumentStoreInterface documentStore) { + ApiUtils.initMdcContext(request, headers); + + if (logger.isDebugEnabled()) { + logger.debug("SEARCH: Process Bulk Request - operations = [" + operations.replaceAll("\n", "") + " ]"); + } + + // We expect a payload containing a JSON structure enumerating the operations to be performed. + if (operations == null) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Missing operations list payload"); + return buildResponse(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Missing payload", request); + } + + try { + // Validate that the request is correctly authenticated before going any further. + if (!searchService.validateRequest(headers, request, ApiUtils.Action.POST, + ApiUtils.SEARCH_AUTH_POLICY_NAME)) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Authentication failure."); + + return buildResponse(HttpStatus.FORBIDDEN.value(), "Authentication failure.", request); + } + } catch (Exception e) { + // This is a catch all for any unexpected failure trying to perform the authentication. + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, + "Unexpected authentication failure - cause: " + e.getMessage()); + if (logger.isDebugEnabled()) { + logger.debug(MSG_STACK_TRACE + e.getStackTrace()); + } + + return buildResponse(HttpStatus.FORBIDDEN.value(), "Authentication failure - cause " + e.getMessage(), + request); + } + + // Marshal the supplied json string into a Java object. + ObjectMapper mapper = new ObjectMapper(); + BulkRequest[] requests = null; + try { + requests = mapper.readValue(operations, BulkRequest[].class); + } catch (IOException e) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Failed to marshal operations list: " + e.getMessage()); + if (logger.isDebugEnabled()) { + logger.debug(MSG_STACK_TRACE + e.getStackTrace()); + } + // Populate the result code and entity string for our HTTP response + // and return the response to the client.. + return buildResponse(HttpStatus.BAD_REQUEST.value(), "Unable to marshal operations: " + e.getMessage(), + request); + } + + // Verify that our parsed operations list actually contains some valid operations. + if (requests.length == 0) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Empty operations list in bulk request"); + + // Populate the result code and entity string for our HTTP response + // and return the response to the client.. + return buildResponse(HttpStatus.BAD_REQUEST.value(), "Empty operations list in bulk request", request); + } + + int resultCode; + String resultString; + + try { + // Now, forward the set of bulk operations to the DAO for processing. + OperationResult result = documentStore.performBulkOperations(requests); + + resultCode = result.getResultCode(); + resultString = (result.getFailureCause() == null) ? result.getResult() : result.getFailureCause(); + } catch (DocumentStoreOperationException e) { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, + "Unexpected failure communicating with document store: " + e.getMessage()); + if (logger.isDebugEnabled()) { + logger.debug(MSG_STACK_TRACE + e.getStackTrace()); + } + + resultCode = HttpStatus.INTERNAL_SERVER_ERROR.value(); + resultString = "Unexpected failure processing bulk operations: " + e.getMessage(); + } + + ResponseEntity response = + ResponseEntity.status(resultCode).contentType(MediaType.APPLICATION_JSON).body(resultString); + + if ((response.getStatusCodeValue() >= 200) && (response.getStatusCodeValue() < 300)) { + logger.info(SearchDbMsgs.PROCESSED_BULK_OPERATIONS); + } else { + logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, response.getBody()); + } + + return buildResponse(resultCode, resultString, request); } - // We expect a payload containing a JSON structure enumerating the - // operations to be performed. - if (operations == null) { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Missing operations list payload"); - - return buildResponse(resultCode, "Missing payload", request, apiUtils); + /** + * This method generates an audit log and returns an HTTP response object. + * + * @param resultCode - The result code to report. + * @param resultString - The result string to report. + * @param request - The HTTP request to extract data from for the audit log. + * @return - An HTTP response object. + */ + private ResponseEntity buildResponse(int resultCode, String resultString, HttpServletRequest request) { + ResponseEntity response = + ResponseEntity.status(resultCode).contentType(MediaType.APPLICATION_JSON).body(resultString); + + // Generate our audit log. + String unknownLogField = "Unknown"; + auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, resultCode) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, ApiUtils.getHttpStatusString(resultCode)), + (request != null) ? request.getMethod() : unknownLogField, + (request != null) ? request.getRequestURL().toString() : unknownLogField, + (request != null) ? request.getRemoteHost() : unknownLogField, + Integer.toString(response.getStatusCodeValue())); + + // Clear the MDC context so that no other transaction inadvertently + // uses our transaction id. + ApiUtils.clearMdcContext(); + + return response; } - - - // Marshal the supplied json string into a Java object. - ObjectMapper mapper = new ObjectMapper(); - BulkRequest[] requests = null; - try { - requests = mapper.readValue(operations, BulkRequest[].class); - - } catch (IOException e) { - - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, - "Failed to marshal operations list: " + e.getMessage()); - if (logger.isDebugEnabled()) { - logger.debug("Stack Trace:\n" + e.getStackTrace()); - } - - // Populate the result code and entity string for our HTTP response - // and return the response to the client.. - return buildResponse(javax.ws.rs.core.Response.Status.BAD_REQUEST.getStatusCode(), - "Unable to marshal operations: " + e.getMessage(), - request, - apiUtils); - } - - // Verify that our parsed operations list actually contains some valid - // operations. - if (requests.length == 0) { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, "Empty operations list in bulk request"); - - - // Populate the result code and entity string for our HTTP response - // and return the response to the client.. - return buildResponse(javax.ws.rs.core.Response.Status.BAD_REQUEST.getStatusCode(), - "Empty operations list in bulk request", - request, - apiUtils); - } - try { - - // Now, forward the set of bulk operations to the DAO for processing. - OperationResult result = documentStore.performBulkOperations(requests); - - // Populate the result code and entity string for our HTTP response. - resultCode = result.getResultCode(); - resultString = (result.getFailureCause() == null) - ? result.getResult() : result.getFailureCause(); - - } catch (DocumentStoreOperationException e) { - - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, - "Unexpected failure communicating with document store: " + e.getMessage()); - if (logger.isDebugEnabled()) { - logger.debug("Stack Trace:\n" + e.getStackTrace()); - } - - // Populate the result code and entity string for our HTTP response. - resultCode = javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); - resultString = "Unexpected failure processing bulk operations: " + e.getMessage(); - } - - // Build our HTTP response. - Response response = Response.status(resultCode).entity(resultString).build(); - - // Log the result. - if ((response.getStatus() >= 200) && (response.getStatus() < 300)) { - logger.info(SearchDbMsgs.PROCESSED_BULK_OPERATIONS); - } else { - logger.warn(SearchDbMsgs.BULK_OPERATION_FAILURE, (String) response.getEntity()); - } - - // Finally, return the HTTP response to the client. - return buildResponse(resultCode, resultString, request, apiUtils); - } - - - /** - * This method generates an audit log and returns an HTTP response object. - * - * @param resultCode - The result code to report. - * @param resultString - The result string to report. - * @param request - The HTTP request to extract data from for the audit log. - * @return - An HTTP response object. - */ - private Response buildResponse(int resultCode, String resultString, - HttpServletRequest request, ApiUtils apiUtils) { - - Response response = Response.status(resultCode).entity(resultString).build(); - - // Generate our audit log. - auditLogger.info(SearchDbMsgs.PROCESS_REST_REQUEST, - new LogFields() - .setField(LogLine.DefinedFields.RESPONSE_CODE, resultCode) - .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, - ApiUtils.getHttpStatusString(resultCode)), - (request != null) ? request.getMethod() : "Unknown", - (request != null) ? request.getRequestURL().toString() : "Unknown", - (request != null) ? request.getRemoteHost() : "Unknown", - Integer.toString(response.getStatus())); - - // Clear the MDC context so that no other transaction inadvertently - // uses our transaction id. - ApiUtils.clearMdcContext(); - - return response; - } }