2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Modifications Copyright (c) 2019 Samsung
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
23 package org.onap.so.bpmn.common.scripts
25 import static org.apache.commons.lang3.StringUtils.*
27 import com.google.common.xml.XmlEscapers
29 import org.apache.commons.lang3.*
30 import org.camunda.bpm.engine.delegate.BpmnError
31 import org.camunda.bpm.engine.delegate.DelegateExecution
32 import org.onap.so.bpmn.core.WorkflowException
33 import org.onap.so.logger.MessageEnum
34 import org.onap.so.logger.MsoLogger
35 import org.slf4j.Logger
36 import org.slf4j.LoggerFactory
43 class ExceptionUtil extends AbstractServiceTaskProcessor {
44 private static final Logger logger = LoggerFactory.getLogger( ExceptionUtil.class);
49 * This error handling method maps an AAI Exception response to a
50 * WorkflowException Object. It then sets the WorkflowException Object
51 * on the execution as "WorkflowException".
53 * This method formats the exception from AAI into the WorkflowException's
54 * errorMessage that CCD expects.
56 * @param execution the execution
57 * @param response the aai exception
59 WorkflowException MapAAIExceptionToWorkflowException(String response, DelegateExecution execution)
61 def utils=new MsoUtils()
62 def prefix=execution.getVariable("prefix")
63 def errorMsg = execution.getVariable(prefix+"ErrorResponse")
64 logger.trace("Begin MapAAIExceptionToWorkflowException ")
67 String errorCode = '5000'
68 WorkflowException wfex
69 logger.debug("response: " + response)
72 //String msg = utils.getNodeXml(response, "Fault")
73 variables = utils.getMultNodes(response, "variable")
74 text = utils.getNodeText(response, "text")
75 } catch (Exception ex) {
76 //Ignore the exception - cases include non xml payload
77 logger.debug("error mapping error, ignoring: " + ex)
81 if(variables.size()>=4){
82 text = text.replaceFirst("%1", variables[0])
83 text = text.replaceFirst("%2", variables[1])
84 text = text.replaceFirst("%3", variables[2])
85 text = text.replaceFirst("%4", variables[3])
87 String modifiedErrorMessage = 'Received error from A&AI (' + text +')'
88 logger.debug("ModifiedErrorMessage " + modifiedErrorMessage)
89 // let $ModifiedErrorMessage := concat( 'Received error from A',$exceptionaai:ampersand,'AI (' ,functx:replace-multi($ErrorMessage,$from,$Variables ),')')
90 buildWorkflowException(execution, 5000, modifiedErrorMessage)
92 wfex = execution.getVariable("WorkflowException")
93 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), "Fault", "BPMN",
94 MsoLogger.ErrorCode.UnknownError.getValue(), wfex.errorMessage);
98 errorCode = MapErrorCode(errorMsg)
99 String mappedErrorMessage = MapErrorMessage(errorMsg, errorCode)
101 int errorCodeInt = Integer.parseInt(errorCode)
102 buildWorkflowException(execution, errorCodeInt, mappedErrorMessage)
104 logger.debug("mappedErrorMessage " + mappedErrorMessage)
105 wfex = execution.getVariable("WorkflowException")
106 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), "Fault", "BPMN",
107 MsoLogger.ErrorCode.UnknownError.getValue(), wfex.errorMessage);
109 } catch(Exception ex) {
110 logger.debug("error mapping error, return null: " + ex)
116 logger.debug("Exception occured during MapAAIExceptionToWorkflowException: " + e)
117 buildWorkflowException(execution, 5000, "Error mapping AAI Response to WorkflowException")
122 * This error handling method maps an AAI Exception response to a
123 * WorkflowException Object. It then sets the WorkflowException Object
124 * on the execution as "WorkflowException".
126 * This method takes the exact exception inside the <Fault> tags from AAI Response
127 * and puts it into the WorkflowException's errorMessage.
129 * @param execution the execution
130 * @param response the aai exception
132 WorkflowException MapAAIExceptionToWorkflowExceptionGeneric(DelegateExecution execution, String response, int resCode){
133 def utils=new MsoUtils()
134 logger.debug("Start MapAAIExceptionToWorkflowExceptionGeneric Process")
136 WorkflowException wfex
138 if(utils.nodeExists(response, "Fault")){
139 String fault = utils.getNodeXml(response, "Fault")
140 fault = utils.removeXmlPreamble(fault)
141 fault = fault.replace("<Fault>", "").replace("</Fault>", "")
142 fault = fault.replaceAll("\\s+\\s+", "") // Removes extra white spaces
143 buildWorkflowException(execution, resCode, fault)
144 }else if(utils.nodeExists(response, "RESTFault")){
145 String rFault = utils.getNodeXml(response, "RESTFault")
146 buildWorkflowException(execution, resCode, rFault)
148 buildWorkflowException(execution, resCode, "Received a bad response from AAI")
150 } catch (Exception ex) {
151 logger.debug("Exception Occured during MapAAIExceptionToWorkflowExceptionGeneric: " + ex)
152 buildWorkflowException(execution, resCode, "Internal Error - Occured in MapAAIExceptionToWorkflowExceptionGeneric")
155 logger.debug("Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"))
156 logger.debug("Completed MapAAIExceptionToWorkflowExceptionGeneric Process")
160 * This method takes a WorkflowException Object and builds
161 * WorkflowException Xml. This method should only be used
162 * for the purpose of sending a sync error response or for
163 * creating a FalloutHandler request.
165 *@param - WorkflowException Object
167 *@return - String WorkflowException Xml
171 String buildErrorResponseXml(WorkflowException wfex) {
174 String mes = XmlEscapers.xmlContentEscaper().escape(wfex.getErrorMessage())
175 int code = wfex.getErrorCode()
177 """<aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
178 <aetgt:ErrorMessage>${MsoUtils.xmlEscape(mes)}</aetgt:ErrorMessage>
179 <aetgt:ErrorCode>${MsoUtils.xmlEscape(code)}</aetgt:ErrorCode>
180 </aetgt:WorkflowException>"""
184 """<aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
185 <aetgt:ErrorMessage>Internal Error</aetgt:ErrorMessage>
186 <aetgt:ErrorCode>2500</aetgt:ErrorCode>
187 </aetgt:WorkflowException>"""
193 5000 Received error from A&AI ($A&AI_ERROR) Asynchronous During orchestration of the recipe, A&AI returned an error. The error returned by A&AI is passed through in $A&AI_ERROR.
194 5010 Could not communicate with A&AI Asynchronous During orchestration of the recipe, a connection with A&AI could not be established.
195 5020 No response from A&AI Asynchronous During orchestration of the recipe, communication was established with A&AI, but no response was received within the configured timeout.
199 * Utility Method for MapAAIExceptionToWorkflowException
201 *@param - String ErrorMessage
203 *@return - String ErrorCode
206 private String MapErrorCode(String errorMessage)
208 if(errorMessage==null){
211 errorMessage = errorMessage.toLowerCase();
212 if(errorMessage.contains('timed out') || errorMessage.contains('timeout'))
214 else if (errorMessage.contains('connection'))
222 * Utility Method for MapAAIExceptionToWorkflowException
224 *@param - String ErrorMessage
225 *@param - String ErrorCode
227 *@return - String ErrorMessage
230 private String MapErrorMessage(String errorMessage, String errorCode)
232 if(errorMessage == null){
235 if( errorCode.equals('5010')){
236 return 'Could not communicate with A&AI'
237 }else if (errorCode.equals('5020')){
238 return 'No response from A&AI'
240 return 'Received error from A&AI (' +errorMessage +')'
246 * Utility Method for Mapping SDNC
247 * Adapter Response Codes
249 *@param - String sdncResponseCode
251 *@return - String code
254 String MapSDNCResponseCodeToErrorCode(String sdncResponseCode)
256 if (sdncResponseCode == '500') {
258 } else if ( sdncResponseCode == '408') {
260 } else if ( sdncResponseCode == '60010') {
268 * This error handling method builds a WorkflowException Object. It sets it on
269 * the execution as "WorkflowException".
271 * @param execution the execution
272 * @param errorCode the error code
273 * @param errorMessage the error message
275 public void buildWorkflowException(DelegateExecution execution, int errorCode, String errorMessage) {
276 MsoUtils utils = new MsoUtils()
277 String processKey = getProcessKey(execution);
278 logger.debug("Building a WorkflowException for " + processKey)
280 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);
281 execution.setVariable("WorkflowException", exception);
282 logger.debug("Outgoing WorkflowException is " + exception)
286 * This error handling method builds a WorkflowException Object and throws a
287 * MSOWorkflowException. It throws a "MSOWorkflowException" BpmnError after
288 * setting the WorkflowException Object on the execution as "WorkflowException".
290 * @param execution the execution
291 * @param errorCode the error code
292 * @param errorMessage the error message
294 public void buildAndThrowWorkflowException(DelegateExecution execution, int errorCode, String errorMessage) {
295 String processKey = getProcessKey(execution);
296 logger.debug("Building a WorkflowException for Subflow " + processKey)
298 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);
299 execution.setVariable("WorkflowException", exception);
300 logger.debug("Outgoing WorkflowException is " + exception)
301 logger.debug("Throwing MSOWorkflowException")
302 throw new BpmnError(errorCode.toString(), String.format("MSOWorkflowException: %s", errorMessage))
306 * This method is executed after an MSOWorkflowException is caught by a
307 * subflow (during subflows "Error Handling Sub Process").
308 * It ensures the WorkflowException variable is populated before ending the
309 * subflow and also logs the subflows outgoing WorkflowException Variable.
314 public void processSubflowsBPMNException(DelegateExecution execution){
315 String processKey = getProcessKey(execution)
317 logger.debug("Started ProcessSubflowsBPMNException Method")
318 if(execution.getVariable("WorkflowException") == null){
319 buildWorkflowException(execution, 2500, "Internal Error - Occured During " + processKey)
322 logger.debug(processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"))
324 logger.debug("Caught Exception during ProcessSubflowsBPMNException Method: " + e)
326 logger.debug("Completed ProcessSubflowsBPMNException Method")
330 * This method is executed after an MSOWorkflowException is caught by a
331 * Mainflow. It builds and returns a FalloutHandler Request. It also
332 * verifies the WorkflowException variable is populated.
335 * @param - requestInfo
337 * @return - falloutHandlerRequest
340 public String processMainflowsBPMNException(DelegateExecution execution, String requestInfo){
341 String processKey = getProcessKey(execution)
343 logger.debug("Started ProcessMainflowBPMNException Method")
344 if(execution.getVariable("WorkflowException") == null || isBlank(requestInfo)){
345 buildWorkflowException(execution, 2500, "Internal Error - WorkflowException Object and/or RequestInfo is null! " + processKey)
347 requestInfo = utils.removeXmlPreamble(requestInfo)
348 WorkflowException wfex = execution.getVariable("WorkflowException")
349 String errorMessage = XmlEscapers.xmlContentEscaper().escape(wfex.getErrorMessage())
350 int errorCode = wfex.getErrorCode()
352 String falloutHandlerRequest =
353 """<aetgt:FalloutHandlerRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
354 xmlns:ns="http://org.onap/so/request/types/v1"
355 xmlns:wfsch="http://org.onap/so/workflow/schema/v1">
357 <aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
358 <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorMessage)}</aetgt:ErrorMessage>
359 <aetgt:ErrorCode>${MsoUtils.xmlEscape(errorCode)}</aetgt:ErrorCode>
360 </aetgt:WorkflowException>
361 </aetgt:FalloutHandlerRequest>"""
363 logger.debug(processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"))
364 logger.debug(processKey + " Outgoing FalloutHandler Request is: " + falloutHandlerRequest)
366 return falloutHandlerRequest
369 logger.debug("Caught Exception during ProcessMainflowBPMNException Method: " + e)
372 logger.debug("Completed ProcessMainflowBPMNException Method")
377 * This method is executed after an Java Exception is caught
378 * It sets the WorkflowException variable. The method can be used in either mainflow or subflows.
383 public void processJavaException(DelegateExecution execution){
384 String processKey = getProcessKey(execution)
386 logger.debug("Caught a Java Exception in " + processKey)
387 logger.debug("Started processJavaException Method")
388 // if the BPMN flow java error handler sets "BPMN_javaExpMsg", append it to the WFE
389 String javaExpMsg = execution.getVariable("BPMN_javaExpMsg")
390 String errorMessage = execution.getVariable("gUnknownError")
391 String wfeExpMsg = "Catch a Java Lang Exception in " + processKey
392 if (javaExpMsg != null && !javaExpMsg.empty) {
393 wfeExpMsg = wfeExpMsg + ": " + javaExpMsg
395 if (errorMessage != null && !errorMessage.empty) {
396 logger.error("Unknown Error: " + errorMessage);
398 logger.error("Java Error: " + wfeExpMsg);
399 buildWorkflowException(execution, 2500, wfeExpMsg)
406 logger.debug("Caught Exception during processJavaException Method: " + e)
407 buildWorkflowException(execution, 2500, "Internal Error - During Process Java Exception")
409 logger.debug("Completed processJavaException Method")
413 public void preProcessRequest(DelegateExecution execution) {
414 // TODO Auto-generated method stub
418 public String getErrorMessage(WorkflowException wfe, String processKey) {
420 return "Unexpected error encountered in " + processKey
423 return wfe.getErrorMessage()
427 public int getErrorCode(WorkflowException wfe) {
432 return wfe.getErrorCode()