null ptr check
[appc.git] / appc-dispatcher / appc-request-handler / appc-request-handler-core / src / main / java / org / onap / appc / requesthandler / impl / AbstractRequestHandlerImpl.java
index 8b56dda..cd9011f 100644 (file)
@@ -2,7 +2,7 @@
  * ============LICENSE_START=======================================================
  * ONAP : APPC
  * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  * Copyright (C) 2017 Amdocs
  * =============================================================================
@@ -18,7 +18,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
  * ============LICENSE_END=========================================================
  */
 
@@ -26,21 +25,23 @@ package org.onap.appc.requesthandler.impl;
 
 import com.att.eelf.configuration.EELFLogger;
 import com.att.eelf.configuration.EELFManager;
-import com.att.eelf.i18n.EELFResourceManager;
 import org.apache.commons.lang.ObjectUtils;
-import org.onap.appc.requesthandler.constant.Constants;
+import org.apache.commons.lang.StringUtils;
 import org.onap.appc.configuration.Configuration;
 import org.onap.appc.configuration.ConfigurationFactory;
-import org.onap.appc.domainmodel.lcm.*;
+import org.onap.appc.domainmodel.lcm.Flags;
+import org.onap.appc.domainmodel.lcm.RequestContext;
+import org.onap.appc.domainmodel.lcm.RequestStatus;
+import org.onap.appc.domainmodel.lcm.ResponseContext;
+import org.onap.appc.domainmodel.lcm.RuntimeContext;
+import org.onap.appc.domainmodel.lcm.Status;
+import org.onap.appc.domainmodel.lcm.TransactionRecord;
+import org.onap.appc.domainmodel.lcm.VNFOperation;
 import org.onap.appc.exceptions.APPCException;
-import org.onap.appc.executor.CommandExecutor;
-import org.onap.appc.executor.UnstableVNFException;
+import org.onap.appc.exceptions.InvalidInputException;
 import org.onap.appc.executor.objects.LCMCommandStatus;
 import org.onap.appc.executor.objects.Params;
-import org.onap.appc.executor.objects.UniqueRequestIdentifier;
-import org.onap.appc.i18n.Msg;
-import org.onap.appc.lifecyclemanager.objects.LifecycleException;
-import org.onap.appc.lifecyclemanager.objects.NoTransitionDefinedException;
+import org.onap.appc.lockmanager.api.LockException;
 import org.onap.appc.logging.LoggingConstants;
 import org.onap.appc.logging.LoggingUtils;
 import org.onap.appc.messageadapter.MessageAdapter;
@@ -53,53 +54,54 @@ import org.onap.appc.metricservice.metric.MetricType;
 import org.onap.appc.metricservice.policy.PublishingPolicy;
 import org.onap.appc.metricservice.publisher.LogPublisher;
 import org.onap.appc.requesthandler.RequestHandler;
-import org.onap.appc.requesthandler.exceptions.*;
-import org.onap.appc.requesthandler.helper.RequestRegistry;
+import org.onap.appc.requesthandler.exceptions.RequestValidationException;
 import org.onap.appc.requesthandler.helper.RequestValidator;
 import org.onap.appc.requesthandler.objects.RequestHandlerInput;
 import org.onap.appc.requesthandler.objects.RequestHandlerOutput;
 import org.onap.appc.transactionrecorder.TransactionRecorder;
-import org.onap.appc.transactionrecorder.objects.TransactionRecord;
+import org.onap.appc.transactionrecorder.objects.TransactionConstants;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.ServiceReference;
 import org.slf4j.MDC;
 
 import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.text.SimpleDateFormat;
 import java.time.Instant;
+import java.util.Date;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.Properties;
-
-import static com.att.eelf.configuration.Configuration.*;
+import java.util.UUID;
+import java.util.TimeZone;
+import static com.att.eelf.configuration.Configuration.MDC_INSTANCE_UUID;
+import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID;
+import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
+import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;
+import static com.att.eelf.configuration.Configuration.MDC_SERVICE_INSTANCE_ID;
+import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
 
 /**
  * This class provides application logic for the Request/Response Handler Component.
- *
  */
 public abstract class AbstractRequestHandlerImpl implements RequestHandler {
 
     private RequestValidator requestValidator;
 
-
-
-    private RequestRegistry requestRegistry;
-
-    private CommandExecutor commandExecutor;
-
-    private TransactionRecorder transactionRecorder;
+    protected TransactionRecorder transactionRecorder;
 
     private MessageAdapter messageAdapter;
 
-    private static MetricRegistry metricRegistry;
+    static MetricRegistry metricRegistry;
 
     private boolean isMetricEnabled = false;
 
-    protected static final Configuration configuration = ConfigurationFactory.getConfiguration();
+    protected final Configuration configuration = ConfigurationFactory.getConfiguration();
 
-    private static final EELFLogger logger = EELFManager.getInstance().getLogger(AbstractRequestHandlerImpl.class);
+    private final EELFLogger logger = EELFManager.getInstance().getLogger(AbstractRequestHandlerImpl.class);
 
-    public AbstractRequestHandlerImpl() {
-        requestRegistry = new RequestRegistry();
+    AbstractRequestHandlerImpl() {
         messageAdapter = new MessageAdapterImpl();
         messageAdapter.init();
         Properties properties = configuration.getProperties();
@@ -123,242 +125,181 @@ public abstract class AbstractRequestHandlerImpl implements RequestHandler {
         this.messageAdapter = messageAdapter;
     }
 
-
-
-    public void setRequestRegistry(RequestRegistry requestRegistry) {
-        this.requestRegistry = requestRegistry;
-    }
-
-    public void setCommandExecutor(CommandExecutor commandExecutor) {
-        this.commandExecutor = commandExecutor;
-    }
-
-
     /**
      * It receives requests from the north-bound REST API (Communication) Layer and
      * performs following validations.
      * 1. VNF exists in A&AI for the given targetID (VnfID)
      * 2. For the current VNF  Orchestration Status, the command can be executed
      * 3. For the given VNF type and Operation, there exists work-flow definition in the APPC database
-     * If any of the validation fails, it returns appropriate response
+     * If any of the validation fails, it returns appropriate response     *
      *
-     * @param input RequestHandlerInput object which contains request header and  other request parameters like command , target Id , payload etc.
+     * @param input RequestHandlerInput object which contains request header and  other request parameters like
+     *              command , target Id , payload etc.
      * @return response for request as enum with Return code and message.
      */
     @Override
     public RequestHandlerOutput handleRequest(RequestHandlerInput input) {
         if (logger.isTraceEnabled())
             logger.trace("Entering to handleRequest with RequestHandlerInput = " + ObjectUtils.toString(input) + ")");
-        Params params ;
-        String vnfId, vnfType = null, errorMessage = null;
-        Instant startTime = Instant.now();
-        RequestHandlerOutput output = null;
-        setInitialLogProperties(input.getRequestContext());
-
-        RuntimeContext runtimeContext = new RuntimeContext();
-        runtimeContext.setRequestContext(input.getRequestContext());
-        runtimeContext.setTimeStart(startTime);
-        runtimeContext.setRpcName(input.getRpcName());
-
-        final ResponseContext responseContext = new ResponseContext();
-        responseContext.setStatus(new Status(0,""));
-        responseContext.setAdditionalContext(new HashMap<>(4));
-        responseContext.setCommonHeader(input.getRequestContext().getCommonHeader());
+        String errorMessage = null;
+        RequestStatus requestStatus;
+        TransactionRecord transactionRecord = createTransactionRecord(input);
+        RuntimeContext runtimeContext = createRuntimeContext(input, transactionRecord);
+        ResponseContext responseContext = createResponseContext(input);
         runtimeContext.setResponseContext(responseContext);
-        runtimeContext.getResponseContext().setStatus(new Status(0,""));
-
-        vnfId = runtimeContext.getRequestContext().getActionIdentifiers().getVnfId();
-
+        RequestHandlerOutput output = new RequestHandlerOutput();
         try {
-
+            transactionRecorder.store(transactionRecord);
             requestValidator.validateRequest(runtimeContext);
 
-            handleRequest(runtimeContext);
+            setInitialLogProperties(input.getRequestContext());
 
-            final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
-            if (statusCode % 100 == 2 || statusCode % 100 == 3) {
-                createTransactionRecord(runtimeContext);
-            }
-            output = new RequestHandlerOutput();
+            handleRequest(runtimeContext);
             output.setResponseContext(runtimeContext.getResponseContext());
-
-        } catch (VNFNotFoundException e) {
-            errorMessage = e.getMessage();
-            String logMessage = EELFResourceManager.format(Msg.APPC_NO_RESOURCE_FOUND, vnfId);
-            storeErrorMessageToLog(runtimeContext, LoggingConstants.TargetNames.AAI, "", logMessage);
-            params = new Params().addParam("vnfId", vnfId);
-            output = buildRequestHandlerOutput(LCMCommandStatus.VNF_NOT_FOUND, params);
-        } catch (NoTransitionDefinedException e) {
-            errorMessage = e.getMessage();
-            String logMessage = EELFResourceManager.format(Msg.VF_UNDEFINED_STATE, input.getRequestContext().getCommonHeader().getOriginatorId(), input.getRequestContext().getAction().name());
-            params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
-            output = buildRequestHandlerOutput(LCMCommandStatus.NO_TRANSITION_DEFINE, params);
-            storeErrorMessageToLog(runtimeContext,
-                    LoggingConstants.TargetNames.APPC,
-                    LoggingConstants.TargetNames.STATE_MACHINE,
-                    logMessage);
-        } catch (LifecycleException e) {
+        } catch (RequestValidationException e) {
             errorMessage = e.getMessage();
-            params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
-            output = buildRequestHandlerOutput(LCMCommandStatus.INVALID_VNF_STATE, params);
-        } catch (UnstableVNFException e) {
-            errorMessage = e.getMessage();
-            params = new Params().addParam("vnfId", vnfId);
-            output = buildRequestHandlerOutput(LCMCommandStatus.UNSTABLE_VNF, params);
-        } catch (WorkflowNotFoundException e) {
-            errorMessage = e.getMessage();
-            String vnfTypeVersion = e.vnfTypeVersion;
-            params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("vnfTypeVersion", vnfTypeVersion);
-            output = buildRequestHandlerOutput(LCMCommandStatus.WORKFLOW_NOT_FOUND, params);
-        } catch (DGWorkflowNotFoundException e) {
-            errorMessage = e.getMessage();
-            String logMessage = EELFResourceManager.format(Msg.APPC_WORKFLOW_NOT_FOUND, vnfType, input.getRequestContext().getAction().name());
-            storeErrorMessageToLog(runtimeContext,
-                    LoggingConstants.TargetNames.APPC,
-                    LoggingConstants.TargetNames.WORKFLOW_MANAGER,
-                    logMessage);
-            params = new Params().addParam("actionName", input.getRequestContext().getAction().name())
-                    .addParam("dgModule", e.workflowModule).addParam("dgName", e.workflowName).addParam("dgVersion", e.workflowVersion);
-            output = buildRequestHandlerOutput(LCMCommandStatus.DG_WORKFLOW_NOT_FOUND, params);
-        } catch (RequestExpiredException e) {
-            errorMessage = e.getMessage();
-            params = new Params().addParam("actionName", input.getRequestContext().getAction().name());
-            output = buildRequestHandlerOutput(LCMCommandStatus.EXPIRED_REQUEST, params);
+            logger.error(errorMessage, e);
+            if (!StringUtils.isEmpty(e.getLogMessage()))
+                storeErrorMessageToLog(runtimeContext, e.getTargetEntity(), e.getTargetService(), e.getLogMessage());
+            output = buildRequestHandlerOutput(e.getLcmCommandStatus(), e.getParams());
         } catch (InvalidInputException e) {
+            logger.error("InvalidInputException : " + e.getMessage(), e);
             errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
-            params = new Params().addParam("errorMsg", errorMessage);
-            output = buildRequestHandlerOutput(LCMCommandStatus.INVALID_INPUT_PARAMETER, params);
-        } catch (DuplicateRequestException e) {
-            errorMessage = e.getMessage();
-            output = buildRequestHandlerOutput(LCMCommandStatus.DUPLICATE_REQUEST, null);
-        } catch (MissingVNFDataInAAIException e) {
-            params = new Params().addParam("attributeName",e.getMissingAttributeName())
-                    .addParam("vnfId",vnfId);
-            output = buildRequestHandlerOutput(LCMCommandStatus.MISSING_VNF_DATA_IN_AAI,params);
-            errorMessage = output.getResponseContext().getStatus().getMessage();
-        } catch (LCMOperationsDisabledException e) {
-            errorMessage = e.getMessage();
-            params = new Params().addParam("errorMsg", errorMessage);
-            output = buildRequestHandlerOutput(LCMCommandStatus.REJECTED, params);
+            output = buildRequestHandlerOutput(LCMCommandStatus.INVALID_INPUT_PARAMETER, new Params().addParam
+                ("errorMsg", errorMessage));
+        } catch (LockException e) {
+            logger.error("LockException : " + e.getMessage(), e);
+            Params params = new Params().addParam("errorMsg", e.getMessage());
+            fillStatus(runtimeContext, LCMCommandStatus.LOCKED_VNF_ID, params);
+            output = buildRequestHandlerOutput(LCMCommandStatus.LOCKED_VNF_ID, params);
         } catch (Exception e) {
+            logger.error("Exception : " + e.getMessage(), e);
             storeErrorMessageToLog(runtimeContext, "", "", "Exception = " + e.getMessage());
             errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
-            params = new Params().addParam("errorMsg", errorMessage);
+            Params params = new Params().addParam("errorMsg", errorMessage);
             output = buildRequestHandlerOutput(LCMCommandStatus.UNEXPECTED_ERROR, params);
         } finally {
+            final int statusCode = output.getResponseContext().getStatus().getCode();
+            if (statusCode == LCMCommandStatus.ACCEPTED.getResponseCode()) {
+                requestStatus = RequestStatus.ACCEPTED;
+            } else if (statusCode == LCMCommandStatus.SUCCESS.getResponseCode()) {
+                requestStatus = RequestStatus.SUCCESSFUL;
+                if (isMetricEnabled)
+                    ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
+            } else {
+                requestStatus = (statusCode == LCMCommandStatus.EXPIRED_REQUEST.getResponseCode()) ? RequestStatus
+                    .TIMEOUT : RequestStatus.REJECTED;
+                if (isMetricEnabled)
+                    ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementRejectedRequest();
+            }
             try {
-                if (logger.isDebugEnabled() && errorMessage != null)
+                if (errorMessage != null && logger.isDebugEnabled())
                     logger.debug("error occurred in handleRequest " + errorMessage);
-                logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.ACCEPTED.getResponseCode():  " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode()));
-                logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.SUCCESS.getResponseCode():  " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode()));
-
+                logger.debug("output.getResponseContext().getStatus().getCode():  " + statusCode);
                 runtimeContext.setResponseContext(output.getResponseContext());
-                if ((null == output) || !(output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode())) {
-                    if (isMetricEnabled) {
-                        if((output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode())) {
-                            ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
-                        }else {
-                            ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementRejectedRequest();
-                        }
-                    }
-                    removeRequestFromRegistry(input.getRequestContext().getCommonHeader());
-                }
             } finally {
-                storeAuditLogRecord(runtimeContext);
-                storeMetricLogRecord(runtimeContext);
-                clearRequestLogProperties();
+                runtimeContext.getTransactionRecord().setRequestState(requestStatus);
+                runtimeContext.getTransactionRecord().setResultCode(output.getResponseContext().getStatus().getCode());
+                updateTransactionStatus(runtimeContext.getTransactionRecord());
+                recordAndClearLogProperties(runtimeContext);
             }
         }
         if (logger.isTraceEnabled()) {
-            logger.trace("Exiting from handleRequest with (RequestHandlerOutput = " + ObjectUtils.toString(output.getResponseContext()) + ")");
+            logger.trace("Exiting from handleRequest with (RequestHandlerOutput = " +
+                ObjectUtils.toString(output.getResponseContext()) + ")");
         }
         return output;
     }
 
-    protected void storeErrorMessageToLog(RuntimeContext runtimeContext, String targetEntity, String targetServiceName, String additionalMessage) {
-        LoggingUtils.logErrorMessage(runtimeContext.getResponseContext().getStatus() != null ?
-                        String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()) : "",
-                runtimeContext.getResponseContext().getStatus() != null ?
-                        String.valueOf(runtimeContext.getResponseContext().getStatus().getMessage()) : "",
-                targetEntity,
-                targetServiceName,
-                additionalMessage,
-                this.getClass().getCanonicalName());
+    private ResponseContext createResponseContext(RequestHandlerInput input) {
+        final ResponseContext responseContext = new ResponseContext();
+        responseContext.setStatus(new Status());
+        responseContext.setAdditionalContext(new HashMap<>(4));
+        responseContext.setCommonHeader(input.getRequestContext().getCommonHeader());
+        return responseContext;
     }
 
-    private void createTransactionRecord(RuntimeContext runtimeContext) {
-        TransactionRecord transactionRecord = new TransactionRecord();
-        transactionRecord.setTimeStamp(runtimeContext.getResponseContext().getCommonHeader().getTimeStamp());
-        transactionRecord.setRequestID(runtimeContext.getResponseContext().getCommonHeader().getRequestId());
-        transactionRecord.setStartTime(runtimeContext.getTimeStart());
-        transactionRecord.setEndTime(Instant.now());
-        transactionRecord.setTargetID(runtimeContext.getVnfContext().getId());
-        transactionRecord.setTargetType(runtimeContext.getVnfContext().getType());
-        transactionRecord.setOperation(runtimeContext.getRequestContext().getAction().name());
-        transactionRecord.setResultCode(String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()));
-        transactionRecord.setDescription(runtimeContext.getResponseContext().getStatus().getMessage());
-        transactionRecorder.store(transactionRecord);
+    private void updateTransactionStatus(TransactionRecord record) {
+        Map<TransactionConstants.TRANSACTION_ATTRIBUTES, String> updateColumns = new HashMap<>();
+        if (!StringUtils.isBlank(record.getTargetType())) {
+            updateColumns.put(TransactionConstants.TRANSACTION_ATTRIBUTES.TARGET_TYPE, record.getTargetType());
+        }
+        updateColumns.put(TransactionConstants.TRANSACTION_ATTRIBUTES.STATE, record.getRequestState());
+        updateColumns.put(TransactionConstants.TRANSACTION_ATTRIBUTES.RESULT_CODE,
+                String.valueOf(record.getResultCode()));
+        if (RequestStatus.valueOf(record.getRequestState()).isTerminal()) {
+            Date endTime = new Date();
+            updateColumns.put(TransactionConstants.TRANSACTION_ATTRIBUTES.END_TIME,
+                    dateToStringConverterMillis(endTime));
+        }
+        try {
+            transactionRecorder.update(record.getTransactionId(), updateColumns);
+        } catch (APPCException e) {
+            logger.error("Error accessing database", e);
+        }
     }
 
-    protected abstract void handleRequest(RuntimeContext runtimeContext) ;
-
-    protected void callWfOperation(RuntimeContext runtimeContext) {
-        int remainingTTL = calculateRemainingTTL(runtimeContext.getRequestContext().getCommonHeader());
-        if (remainingTTL > 0) {
-            if (logger.isDebugEnabled()) {
-                logger.debug("Calling command Executor with remaining TTL value: " + remainingTTL);
-            }
-
-            RuntimeContext clonedContext = cloneContext(runtimeContext);
-
-            try {
-                commandExecutor.executeCommand(clonedContext);
-                if(logger.isTraceEnabled()) {
-                    logger.trace("Command was added to queue successfully for vnfID = " + ObjectUtils.toString(runtimeContext.getRequestContext().getActionIdentifiers().getVnfId()));
-                }
-                fillStatus(runtimeContext, LCMCommandStatus.ACCEPTED, null);
-                if (isMetricEnabled) {
-                    ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
-                }
-            } catch (APPCException e) {
-                String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
-                Params params = new Params().addParam("errorMsg", errorMessage);
-                fillStatus(runtimeContext, LCMCommandStatus.UNEXPECTED_ERROR, params);
-            }
+    private RuntimeContext createRuntimeContext(RequestHandlerInput input, TransactionRecord transactionRecord) {
+        RuntimeContext runtimeContext;
+        runtimeContext = new RuntimeContext();
+        runtimeContext.setRequestContext(input.getRequestContext());
+        runtimeContext.setTimeStart(transactionRecord.getStartTime());
+        runtimeContext.setRpcName(input.getRpcName());
+        runtimeContext.setTransactionRecord(transactionRecord);
+        return runtimeContext;
+    }
 
+    private TransactionRecord createTransactionRecord(RequestHandlerInput input) {
+        Instant startTime = Instant.now();
+        TransactionRecord record = new TransactionRecord();
+        record.setTransactionId(UUID.randomUUID().toString());
+        record.setRequestState(RequestStatus.RECEIVED);
+        record.setRequestId(input.getRequestContext().getCommonHeader().getRequestId());
+        record.setSubRequestId(input.getRequestContext().getCommonHeader().getSubRequestId());
+        record.setOriginatorId(input.getRequestContext().getCommonHeader().getOriginatorId());
+        record.setOriginTimestamp(input.getRequestContext().getCommonHeader().getTimeStamp().toInstant());
+        record.setStartTime(startTime);
+        record.setOperation(VNFOperation.valueOf(input.getRequestContext().getAction().name()));
+        record.setTargetId(input.getRequestContext().getActionIdentifiers().getVnfId());
+        record.setVnfcName(input.getRequestContext().getActionIdentifiers().getVnfcName());
+        record.setVserverId(input.getRequestContext().getActionIdentifiers().getVserverId());
+        record.setVfModuleId(input.getRequestContext().getActionIdentifiers().getVfModuleId());
+        record.setServiceInstanceId(input.getRequestContext().getActionIdentifiers().getServiceInstanceId());
+        Flags.Mode mode;
+        if (input.getRequestContext().getCommonHeader().getFlags() != null &&
+            input.getRequestContext().getCommonHeader().getFlags().getMode() != null) {
+            mode = input.getRequestContext().getCommonHeader().getFlags().getMode();
         } else {
-            fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST, null);
-            storeErrorMessageToLog(runtimeContext,
-                    LoggingConstants.TargetNames.APPC,
-                    LoggingConstants.TargetNames.REQUEST_HANDLER,
-                    EELFResourceManager.format(Msg.APPC_EXPIRED_REQUEST,
-                            runtimeContext.getRequestContext().getCommonHeader().getOriginatorId(),
-                            runtimeContext.getRequestContext().getActionIdentifiers().getVnfId(),
-                            String.valueOf(runtimeContext.getRequestContext().getCommonHeader().getFlags().getTtl())));
+            mode = Flags.Mode.NORMAL;
         }
+        record.setMode(mode);
+        return record;
     }
 
-    protected void fillStatus(RuntimeContext runtimeContext, LCMCommandStatus lcmCommandStatus, Params params) {
-        runtimeContext.getResponseContext().setStatus(new Status(lcmCommandStatus.getResponseCode(),lcmCommandStatus.getFormattedMessage(params)));
+    private void recordAndClearLogProperties(RuntimeContext runtimeContext) {
+        storeAuditLogRecord(runtimeContext);
+        storeMetricLogRecord(runtimeContext);
+        clearRequestLogProperties();
     }
 
-    /*
-     * Workaround to clone context in order to prevent sharing of ResponseContext by two threads (one to set Accepted
-     * status code and other - depending on DG status). Other properties should not be a problem
-     */
-    private RuntimeContext cloneContext(RuntimeContext runtimeContext) {
-        RuntimeContext other = new RuntimeContext();
-        other.setRequestContext(runtimeContext.getRequestContext());
-        other.setResponseContext(new ResponseContext());
-        other.getResponseContext().setStatus(new Status(0,""));
-        other.getResponseContext().setCommonHeader(runtimeContext.getRequestContext().getCommonHeader());
-        other.setVnfContext(runtimeContext.getVnfContext());
-        other.setRpcName(runtimeContext.getRpcName());
-        other.setTimeStart(runtimeContext.getTimeStart());
-        other.setIsLockAcquired(runtimeContext.isLockAcquired());
-        return other;
+    void storeErrorMessageToLog(RuntimeContext runtimeContext, String targetEntity, String targetServiceName,
+                                String additionalMessage) {
+        LoggingUtils.logErrorMessage(runtimeContext.getResponseContext().getStatus() != null ?
+                String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()) : "",
+            runtimeContext.getResponseContext().getStatus() != null ?
+                String.valueOf(runtimeContext.getResponseContext().getStatus().getMessage()) : "",
+            targetEntity,
+            targetServiceName,
+            additionalMessage,
+            this.getClass().getCanonicalName());
     }
 
+    protected abstract void handleRequest(RuntimeContext runtimeContext);
+
+    void fillStatus(RuntimeContext runtimeContext, LCMCommandStatus lcmCommandStatus, Params params) {
+        runtimeContext.getResponseContext().getStatus().setCode(lcmCommandStatus.getResponseCode());
+        runtimeContext.getResponseContext().getStatus().setMessage(lcmCommandStatus.getFormattedMessage(params));
+    }
 
     private void clearRequestLogProperties() {
         try {
@@ -368,20 +309,10 @@ public abstract class AbstractRequestHandlerImpl implements RequestHandler {
             MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME);
             MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY);
         } catch (Exception e) {
-            //do nothing
+            logger.error("Error clearing MDC log properties. " + e.getMessage(), e);
         }
     }
 
-    private void removeRequestFromRegistry(CommonHeader commonHeader) {
-        if (logger.isTraceEnabled())
-            logger.trace("Entering to removeRequestFromRegistry with RequestHeader = " + ObjectUtils.toString(commonHeader));
-        requestRegistry.removeRequest(
-                new UniqueRequestIdentifier(commonHeader.getOriginatorId(),
-                        commonHeader.getRequestId(),
-                        commonHeader.getSubRequestId()));
-    }
-
-
     private void setInitialLogProperties(RequestContext requestContext) {
 
         try {
@@ -391,97 +322,28 @@ public abstract class AbstractRequestHandlerImpl implements RequestHandler {
             }
             MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, requestContext.getCommonHeader().getOriginatorId());
             MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
-            try {
-                MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); //Don't change it to a .getHostName() again please. It's wrong!
-                MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
-                MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
-                MDC.put(MDC_SERVICE_NAME, requestContext.getAction().name());
-                MDC.put(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY, requestContext.getActionIdentifiers().getVnfId());
-
-            } catch (Exception e) {
-                logger.debug(e.getMessage());
-            }
-        } catch (RuntimeException e) {
-            //ignore
-        }
-    }
-
-
-    private int calculateRemainingTTL(CommonHeader commonHeader) {
-        if (logger.isTraceEnabled()) {
-            logger.trace("Entering to calculateRemainingTTL with RequestHeader = " + ObjectUtils.toString(commonHeader));
-        }
-        long usedTimeInMillis = (System.currentTimeMillis() - commonHeader.getTimeStamp().toEpochMilli());
-        logger.debug("usedTimeInMillis = " + usedTimeInMillis);
-        int usedTimeInSeconds = Math.round(usedTimeInMillis / 1000);
-        logger.debug("usedTimeInSeconds = " + usedTimeInSeconds);
-        Integer inputTTL = this.getInputTTL(commonHeader);
-        logger.debug("inputTTL = " + inputTTL);
-        Integer remainingTTL = inputTTL - usedTimeInSeconds;
-        logger.debug("Remaining TTL = " + remainingTTL);
-        if (logger.isTraceEnabled())
-            logger.trace("Exiting from calculateRemainingTTL with (remainingTTL = " + ObjectUtils.toString(remainingTTL) + ")");
-        return remainingTTL;
-    }
-
-    private Integer getInputTTL(CommonHeader header) {
-        if (logger.isTraceEnabled())
-            logger.trace("Entering in getInputTTL with RequestHeader = " + ObjectUtils.toString(header));
-        if (!isValidTTL(String.valueOf(header.getFlags().getTtl()))) {
-            String defaultTTLStr = configuration.getProperty("org.onap.appc.workflow.default.ttl", String.valueOf(Constants.DEFAULT_TTL));
-            Integer defaultTTL = Integer.parseInt(defaultTTLStr);
-            if (logger.isTraceEnabled())
-                logger.trace("Exiting from getInputTTL with (defaultTTL = " + ObjectUtils.toString(defaultTTL) + ")");
-            return defaultTTL;
+            //Don't change it to a.getHostName() again please. It's wrong!
+            MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName());
+            MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
+            MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
+            MDC.put(MDC_SERVICE_NAME, requestContext.getAction().name());
+            MDC.put(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY, requestContext.getActionIdentifiers().getVnfId());
+        } catch (UnknownHostException e) {
+            logger.error("Error occured while setting initial log properties", e);
         }
-        if (logger.isTraceEnabled())
-            logger.trace("Exiting from getInputTTL with (inputTTL = " + ObjectUtils.toString(header.getFlags().getTtl()) + ")");
-
-        return header.getFlags().getTtl();
-    }
-
-    private boolean isValidTTL(String ttl) {
-        if (ttl == null || ttl.length() == 0) {
-            if (logger.isTraceEnabled())
-                logger.trace("Exiting from getInputTTL with (result = false)");
-            return false;
-        }
-        try {
-            Integer i = Integer.parseInt(ttl);
-            return (i > 0);
-        } catch (NumberFormatException e) {
-            if (logger.isTraceEnabled())
-                logger.trace("Exiting from getInputTTL with (result = false)");
-            return false;
-        }
-    }
-
-    private Boolean isLoggingEnabled() {
-        String defaultFlagStr = configuration.getProperty("org.onap.appc.localTransactionRecorder.enable", String.valueOf(Constants.DEFAULT_LOGGING_FLAG));
-        return Boolean.parseBoolean(defaultFlagStr);
     }
 
     private static RequestHandlerOutput buildRequestHandlerOutput(LCMCommandStatus response, Params params) {
         RequestHandlerOutput output = new RequestHandlerOutput();
         ResponseContext responseContext = new ResponseContext();
-        org.onap.appc.domainmodel.lcm.Status status = new org.onap.appc.domainmodel.lcm.Status(response.getResponseCode(),response.getFormattedMessage(params));
+        org.onap.appc.domainmodel.lcm.Status status = new org.onap.appc.domainmodel.lcm.Status();
+        status.setCode(response.getResponseCode());
+        status.setMessage(response.getFormattedMessage(params));
         responseContext.setStatus(status);
         output.setResponseContext(responseContext);
         return output;
     }
 
-    /**
-     * This method perform operations required before execution of workflow starts. It retrieves next state for current operation from Lifecycle manager and update it in AAI.
-     *
-     * @param vnfId String of VNF ID
-     * @param readOnlyActivity boolean indicator
-     * @param  requestIdentifierString - string contains id uniquely represents the request
-     * @param forceFlag boolean indicator
-     * @throws UnstableVNFException when failed
-     */
-    @Override
-    public abstract void onRequestExecutionStart(String vnfId, boolean readOnlyActivity, String requestIdentifierString, boolean forceFlag) throws UnstableVNFException ;
-
     /**
      * This method perform following operations required after execution of workflow.
      * It posts asynchronous response to message bus (DMaaP).
@@ -489,107 +351,88 @@ public abstract class AbstractRequestHandlerImpl implements RequestHandler {
      * Removes request from request registry.
      * Generate audit logs.
      * Adds transaction record to database id if transaction logging is enabled.
-     *
-     * @param isAAIUpdated boolean flag which indicate AAI upodate status after request completion.
      */
     @Override
-    public void onRequestExecutionEnd(RuntimeContext runtimeContext, boolean isAAIUpdated) {
+    public void onRequestExecutionEnd(RuntimeContext runtimeContext) {
         if (logger.isTraceEnabled()) {
-            logger.trace("Entering to onRequestExecutionEnd with runtimeContext = " + ObjectUtils.toString(runtimeContext));
+            logger.trace("Entering to onRequestExecutionEnd with runtimeContext = " +
+                ObjectUtils.toString(runtimeContext));
         }
-
-        postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
-        requestRegistry.removeRequest(
-                new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
-                        runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
-                        runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
-
+        postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(),
+            runtimeContext.getResponseContext());
+        final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
+        RequestStatus requestStatus =
+            (statusCode == LCMCommandStatus.SUCCESS.getResponseCode()) ?
+                RequestStatus.SUCCESSFUL : RequestStatus.FAILED;
+        runtimeContext.getTransactionRecord().setRequestState(requestStatus);
+        runtimeContext.getTransactionRecord().setResultCode(runtimeContext.getResponseContext().getStatus().getCode());
+        updateTransactionStatus(runtimeContext.getTransactionRecord());
         storeAuditLogRecord(runtimeContext);
-        if (isLoggingEnabled()) {
-            createTransactionRecord(runtimeContext);
-        }
     }
 
     private void storeAuditLogRecord(RuntimeContext runtimeContext) {
         LoggingUtils.logAuditMessage(runtimeContext.getTimeStart(),
-                Instant.now(),
-                String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
-                runtimeContext.getResponseContext().getStatus().getMessage(),
-                this.getClass().getCanonicalName());
+            Instant.now(),
+            String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
+            runtimeContext.getResponseContext().getStatus().getMessage(),
+            this.getClass().getCanonicalName());
     }
 
     private void storeMetricLogRecord(RuntimeContext runtimeContext) {
         LoggingUtils.logMetricsMessage(runtimeContext.getTimeStart(),
-                Instant.now(),
-                LoggingConstants.TargetNames.APPC,
-                runtimeContext.getRequestContext().getAction().name(),
-                runtimeContext.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode() ? LoggingConstants.StatusCodes.COMPLETE : LoggingConstants.StatusCodes.ERROR,
-                String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
-                runtimeContext.getResponseContext().getStatus().getMessage(),
-                this.getClass().getCanonicalName());
+            Instant.now(),
+            LoggingConstants.TargetNames.APPC,
+            runtimeContext.getRequestContext().getAction().name(),
+            runtimeContext.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode()
+                ? LoggingConstants.StatusCodes.COMPLETE : LoggingConstants.StatusCodes.ERROR,
+            String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
+            runtimeContext.getResponseContext().getStatus().getMessage(),
+            this.getClass().getCanonicalName());
     }
 
-
-
-
     private void postMessageToDMaaP(VNFOperation operation, String rpcName, ResponseContext responseContext) {
         if (logger.isTraceEnabled()) {
-            logger.trace("Entering to postMessageToDMaaP with AsyncResponse = " + ObjectUtils.toString(responseContext));
+            logger.trace("Entering to postMessageToDMaaP with AsyncResponse = " +
+                ObjectUtils.toString(responseContext));
         }
         boolean callbackResponse = messageAdapter.post(operation, rpcName, responseContext);
         if (!callbackResponse) {
-            logger.error("DMaaP posting status: " + callbackResponse, "dmaapMessage: " + responseContext);
+            logger.error("DMaaP posting status: false", "dmaapMessage: " + responseContext);
         }
         if (logger.isTraceEnabled())
-            logger.trace("Exiting from postMessageToDMaaP with (callbackResponse = " + ObjectUtils.toString(callbackResponse) + ")");
-    }
-
-    /**
-     * This method perform following operations required if TTL ends when request still waiting in execution queue .
-     * It posts asynchronous response to message bus (DMaaP).
-     * Unlock VNF Id
-     * Removes request from request registry.
-     *
-     * @param runtimeContext AsyncResponse object which contains VNF Id        , timestamp , apiVersion, responseId, executionSuccess, payload, isExpired, action, startTime, vnfType, originatorId, subResponseId;
-     * @param updateAAI      boolean flag which indicate AAI upodate status after request completion.
-     */
-    @Override
-    public void onRequestTTLEnd(RuntimeContext runtimeContext, boolean updateAAI) {
-        if (logger.isTraceEnabled()) {
-            logger.trace("Entering to onRequestTTLEnd with " +
-                    "AsyncResponse = " + ObjectUtils.toString(runtimeContext) +
-                    ", updateAAI = " + ObjectUtils.toString(updateAAI));
-        }
-        logger.error(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage());
-        fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST_FAILURE, null);
-        postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
-
-        requestRegistry.removeRequest(
-                new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
-                        runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
-                        runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
+            logger.trace("Exiting from postMessageToDMaaP with (callbackResponse = " +
+                ObjectUtils.toString(callbackResponse) + ")");
     }
 
     private void initMetric() {
         if (logger.isDebugEnabled())
             logger.debug("Metric getting initialized");
         MetricService metricService = getMetricservice();
+        // Check for the metric service created before trying to create registry using
+        // the metricService object
+        if (metricService == null) {
+            // Cannot find service reference for org.onap.appc.metricservice.MetricService
+            throw new NullPointerException("org.onap.appc.metricservice.MetricService is null. " +
+                    "Failed to init Metric");
+        }
         metricRegistry = metricService.createRegistry("APPC");
         DispatchingFuntionMetric dispatchingFuntionMetric = metricRegistry.metricBuilderFactory().
-                dispatchingFunctionCounterBuilder().
-                withName("DISPATCH_FUNCTION").withType(MetricType.COUNTER).
-                withAcceptRequestValue(0)
-                .withRejectRequestValue(0)
-                .build();
+            dispatchingFunctionCounterBuilder().
+            withName("DISPATCH_FUNCTION").withType(MetricType.COUNTER).
+            withAcceptRequestValue(0)
+            .withRejectRequestValue(0)
+            .build();
         if (metricRegistry.register(dispatchingFuntionMetric)) {
             Metric[] metrics = new Metric[]{dispatchingFuntionMetric};
             LogPublisher logPublisher = new LogPublisher(metricRegistry, metrics);
             LogPublisher[] logPublishers = new LogPublisher[1];
             logPublishers[0] = logPublisher;
-            PublishingPolicy manuallyScheduledPublishingPolicy = metricRegistry.policyBuilderFactory().
-                    scheduledPolicyBuilder().withPublishers(logPublishers).
-                    withMetrics(metrics).
-                    build();
+            PublishingPolicy manuallyScheduledPublishingPolicy = metricRegistry.policyBuilderFactory()
+                .scheduledPolicyBuilder()
+                .withPublishers(logPublishers)
+                .withMetrics(metrics)
+                .build();
+
             if (logger.isDebugEnabled())
                 logger.debug("Policy getting initialized");
             manuallyScheduledPublishingPolicy.init();
@@ -598,7 +441,6 @@ public abstract class AbstractRequestHandlerImpl implements RequestHandler {
         }
     }
 
-
     private MetricService getMetricservice() {
         BundleContext bctx = FrameworkUtil.getBundle(MetricService.class).getBundleContext();
         ServiceReference sref = bctx.getServiceReference(MetricService.class.getName());
@@ -617,10 +459,19 @@ public abstract class AbstractRequestHandlerImpl implements RequestHandler {
      * * @return in progress requests count
      */
     @Override
-    public int getInprogressRequestCount() {
+    public int getInprogressRequestCount() throws APPCException {
         if (logger.isTraceEnabled()) {
             logger.trace("Entering to getInprogressRequestCount");
         }
-        return requestRegistry.getRegisteredRequestCount();
+        return transactionRecorder.getInProgressRequestsCount();
+    }
+
+    public static String dateToStringConverterMillis(Date date) {
+        SimpleDateFormat customDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+        customDate.setTimeZone(TimeZone.getTimeZone("UTC"));
+        if (date != null) {
+            return customDate.format(date);
+        }
+        return null;
     }
 }