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 org.onap.so.logger.ErrorCode
27 import static org.apache.commons.lang3.StringUtils.*
29 import com.google.common.xml.XmlEscapers
31 import org.apache.commons.lang3.*
32 import org.camunda.bpm.engine.delegate.BpmnError
33 import org.camunda.bpm.engine.delegate.DelegateExecution
34 import org.onap.so.bpmn.core.WorkflowException
35 import org.onap.so.logger.MessageEnum
36 import org.slf4j.Logger
37 import org.slf4j.LoggerFactory
44 class ExceptionUtil extends AbstractServiceTaskProcessor {
45 private static final Logger logger = LoggerFactory.getLogger( ExceptionUtil.class);
50 * This error handling method maps an AAI Exception response to a
51 * WorkflowException Object. It then sets the WorkflowException Object
52 * on the execution as "WorkflowException".
54 * This method formats the exception from AAI into the WorkflowException's
55 * errorMessage that CCD expects.
57 * @param execution the execution
58 * @param response the aai exception
60 WorkflowException MapAAIExceptionToWorkflowException(String response, DelegateExecution execution)
62 def utils=new MsoUtils()
63 def prefix=execution.getVariable("prefix")
64 def errorMsg = execution.getVariable(prefix+"ErrorResponse")
65 logger.trace("Begin MapAAIExceptionToWorkflowException ")
68 String errorCode = '5000'
69 WorkflowException wfex
70 logger.debug("response: " + response)
73 //String msg = utils.getNodeXml(response, "Fault")
74 variables = utils.getMultNodes(response, "variable")
75 text = utils.getNodeText(response, "text")
76 } catch (Exception ex) {
77 //Ignore the exception - cases include non xml payload
78 logger.debug("error mapping error, ignoring: " + ex)
82 if(variables.size()>=4){
83 text = text.replaceFirst("%1", variables[0])
84 text = text.replaceFirst("%2", variables[1])
85 text = text.replaceFirst("%3", variables[2])
86 text = text.replaceFirst("%4", variables[3])
88 String modifiedErrorMessage = 'Received error from A&AI (' + text +')'
89 logger.debug("ModifiedErrorMessage " + modifiedErrorMessage)
90 // let $ModifiedErrorMessage := concat( 'Received error from A',$exceptionaai:ampersand,'AI (' ,functx:replace-multi($ErrorMessage,$from,$Variables ),')')
91 buildWorkflowException(execution, 5000, modifiedErrorMessage)
93 wfex = execution.getVariable("WorkflowException")
94 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), "Fault", "BPMN",
95 ErrorCode.UnknownError.getValue(), wfex.errorMessage);
99 errorCode = MapErrorCode(errorMsg)
100 String mappedErrorMessage = MapErrorMessage(errorMsg, errorCode)
102 int errorCodeInt = Integer.parseInt(errorCode)
103 buildWorkflowException(execution, errorCodeInt, mappedErrorMessage)
105 logger.debug("mappedErrorMessage " + mappedErrorMessage)
106 wfex = execution.getVariable("WorkflowException")
107 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), "Fault", "BPMN",
108 ErrorCode.UnknownError.getValue(), wfex.errorMessage);
110 } catch(Exception ex) {
111 logger.debug("error mapping error, return null: " + ex)
117 logger.debug("Exception occured during MapAAIExceptionToWorkflowException: " + e)
118 buildWorkflowException(execution, 5000, "Error mapping AAI Response to WorkflowException")
123 * This error handling method maps an AAI Exception response to a
124 * WorkflowException Object. It then sets the WorkflowException Object
125 * on the execution as "WorkflowException".
127 * This method takes the exact exception inside the <Fault> tags from AAI Response
128 * and puts it into the WorkflowException's errorMessage.
130 * @param execution the execution
131 * @param response the aai exception
133 WorkflowException MapAAIExceptionToWorkflowExceptionGeneric(DelegateExecution execution, String response, int resCode){
134 def utils=new MsoUtils()
135 logger.debug("Start MapAAIExceptionToWorkflowExceptionGeneric Process")
137 WorkflowException wfex
139 if(utils.nodeExists(response, "Fault")){
140 String fault = utils.getNodeXml(response, "Fault")
141 fault = utils.removeXmlPreamble(fault)
142 fault = fault.replace("<Fault>", "").replace("</Fault>", "")
143 fault = fault.replaceAll("\\s+\\s+", "") // Removes extra white spaces
144 buildWorkflowException(execution, resCode, fault)
145 }else if(utils.nodeExists(response, "RESTFault")){
146 String rFault = utils.getNodeXml(response, "RESTFault")
147 buildWorkflowException(execution, resCode, rFault)
149 buildWorkflowException(execution, resCode, "Received a bad response from AAI")
151 } catch (Exception ex) {
152 logger.debug("Exception Occured during MapAAIExceptionToWorkflowExceptionGeneric: " + ex)
153 buildWorkflowException(execution, resCode, "Internal Error - Occured in MapAAIExceptionToWorkflowExceptionGeneric")
156 logger.debug("Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"))
157 logger.debug("Completed MapAAIExceptionToWorkflowExceptionGeneric Process")
161 * This method takes a WorkflowException Object and builds
162 * WorkflowException Xml. This method should only be used
163 * for the purpose of sending a sync error response or for
164 * creating a FalloutHandler request.
166 *@param - WorkflowException Object
168 *@return - String WorkflowException Xml
172 String buildErrorResponseXml(WorkflowException wfex) {
175 String mes = XmlEscapers.xmlContentEscaper().escape(wfex.getErrorMessage())
176 int code = wfex.getErrorCode()
178 """<aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
179 <aetgt:ErrorMessage>${MsoUtils.xmlEscape(mes)}</aetgt:ErrorMessage>
180 <aetgt:ErrorCode>${MsoUtils.xmlEscape(code)}</aetgt:ErrorCode>
181 </aetgt:WorkflowException>"""
185 """<aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
186 <aetgt:ErrorMessage>Internal Error</aetgt:ErrorMessage>
187 <aetgt:ErrorCode>2500</aetgt:ErrorCode>
188 </aetgt:WorkflowException>"""
194 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.
195 5010 Could not communicate with A&AI Asynchronous During orchestration of the recipe, a connection with A&AI could not be established.
196 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.
200 * Utility Method for MapAAIExceptionToWorkflowException
202 *@param - String ErrorMessage
204 *@return - String ErrorCode
207 private String MapErrorCode(String errorMessage)
209 if(errorMessage==null){
212 errorMessage = errorMessage.toLowerCase();
213 if(errorMessage.contains('timed out') || errorMessage.contains('timeout'))
215 else if (errorMessage.contains('connection'))
223 * Utility Method for MapAAIExceptionToWorkflowException
225 *@param - String ErrorMessage
226 *@param - String ErrorCode
228 *@return - String ErrorMessage
231 private String MapErrorMessage(String errorMessage, String errorCode)
233 if(errorMessage == null){
236 if( errorCode.equals('5010')){
237 return 'Could not communicate with A&AI'
238 }else if (errorCode.equals('5020')){
239 return 'No response from A&AI'
241 return 'Received error from A&AI (' +errorMessage +')'
247 * Utility Method for Mapping SDNC
248 * Adapter Response Codes
250 *@param - String sdncResponseCode
252 *@return - String code
255 String MapSDNCResponseCodeToErrorCode(String sdncResponseCode)
257 if (sdncResponseCode == '500') {
259 } else if ( sdncResponseCode == '408') {
261 } else if ( sdncResponseCode == '60010') {
269 * This error handling method builds a WorkflowException Object. It sets it on
270 * the execution as "WorkflowException".
272 * @param execution the execution
273 * @param errorCode the error code
274 * @param errorMessage the error message
276 public void buildWorkflowException(DelegateExecution execution, int errorCode, String errorMessage) {
277 MsoUtils utils = new MsoUtils()
278 String processKey = getProcessKey(execution);
279 logger.debug("Building a WorkflowException for " + processKey)
281 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);
282 execution.setVariable("WorkflowException", exception);
283 logger.debug("Outgoing WorkflowException is " + exception)
287 * This error handling method builds a WorkflowException Object and throws a
288 * MSOWorkflowException. It throws a "MSOWorkflowException" BpmnError after
289 * setting the WorkflowException Object on the execution as "WorkflowException".
291 * @param execution the execution
292 * @param errorCode the error code
293 * @param errorMessage the error message
295 public void buildAndThrowWorkflowException(DelegateExecution execution, int errorCode, String errorMessage) {
296 String processKey = getProcessKey(execution);
297 logger.debug("Building a WorkflowException for Subflow " + processKey)
299 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);
300 execution.setVariable("WorkflowException", exception);
301 logger.debug("Outgoing WorkflowException is " + exception)
302 logger.debug("Throwing MSOWorkflowException")
303 throw new BpmnError(errorCode.toString(), String.format("MSOWorkflowException: %s", errorMessage))
307 * This method is executed after an MSOWorkflowException is caught by a
308 * subflow (during subflows "Error Handling Sub Process").
309 * It ensures the WorkflowException variable is populated before ending the
310 * subflow and also logs the subflows outgoing WorkflowException Variable.
315 public void processSubflowsBPMNException(DelegateExecution execution){
316 String processKey = getProcessKey(execution)
318 logger.debug("Started ProcessSubflowsBPMNException Method")
319 if(execution.getVariable("WorkflowException") == null){
320 buildWorkflowException(execution, 2500, "Internal Error - Occured During " + processKey)
323 logger.debug(processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"))
325 logger.debug("Caught Exception during ProcessSubflowsBPMNException Method: " + e)
327 logger.debug("Completed ProcessSubflowsBPMNException Method")
331 * This method is executed after an MSOWorkflowException is caught by a
332 * Mainflow. It builds and returns a FalloutHandler Request. It also
333 * verifies the WorkflowException variable is populated.
336 * @param - requestInfo
338 * @return - falloutHandlerRequest
341 public String processMainflowsBPMNException(DelegateExecution execution, String requestInfo){
342 String processKey = getProcessKey(execution)
344 logger.debug("Started ProcessMainflowBPMNException Method")
345 if(execution.getVariable("WorkflowException") == null || isBlank(requestInfo)){
346 buildWorkflowException(execution, 2500, "Internal Error - WorkflowException Object and/or RequestInfo is null! " + processKey)
348 requestInfo = utils.removeXmlPreamble(requestInfo)
349 WorkflowException wfex = execution.getVariable("WorkflowException")
350 String errorMessage = XmlEscapers.xmlContentEscaper().escape(wfex.getErrorMessage())
351 int errorCode = wfex.getErrorCode()
353 String falloutHandlerRequest =
354 """<aetgt:FalloutHandlerRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
355 xmlns:ns="http://org.onap/so/request/types/v1"
356 xmlns:wfsch="http://org.onap/so/workflow/schema/v1">
358 <aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
359 <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorMessage)}</aetgt:ErrorMessage>
360 <aetgt:ErrorCode>${MsoUtils.xmlEscape(errorCode)}</aetgt:ErrorCode>
361 </aetgt:WorkflowException>
362 </aetgt:FalloutHandlerRequest>"""
364 logger.debug(processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"))
365 logger.debug(processKey + " Outgoing FalloutHandler Request is: " + falloutHandlerRequest)
367 return falloutHandlerRequest
370 logger.debug("Caught Exception during ProcessMainflowBPMNException Method: " + e)
373 logger.debug("Completed ProcessMainflowBPMNException Method")
378 * This method is executed after an Java Exception is caught
379 * It sets the WorkflowException variable. The method can be used in either mainflow or subflows.
384 public void processJavaException(DelegateExecution execution){
385 String processKey = getProcessKey(execution)
387 logger.debug("Caught a Java Exception in " + processKey)
388 logger.debug("Started processJavaException Method")
389 // if the BPMN flow java error handler sets "BPMN_javaExpMsg", append it to the WFE
390 String javaExpMsg = execution.getVariable("BPMN_javaExpMsg")
391 String errorMessage = execution.getVariable("gUnknownError")
392 String wfeExpMsg = "Catch a Java Lang Exception in " + processKey
393 if (javaExpMsg != null && !javaExpMsg.empty) {
394 wfeExpMsg = wfeExpMsg + ": " + javaExpMsg
396 if (errorMessage != null && !errorMessage.empty) {
397 logger.error("Unknown Error: " + errorMessage);
399 logger.error("Java Error: " + wfeExpMsg);
400 buildWorkflowException(execution, 2500, wfeExpMsg)
407 logger.debug("Caught Exception during processJavaException Method: " + e)
408 buildWorkflowException(execution, 2500, "Internal Error - During Process Java Exception")
410 logger.debug("Completed processJavaException Method")
414 public void preProcessRequest(DelegateExecution execution) {
415 // TODO Auto-generated method stub
419 public String getErrorMessage(WorkflowException wfe, String processKey) {
421 return "Unexpected error encountered in " + processKey
424 return wfe.getErrorMessage()
428 public int getErrorCode(WorkflowException wfe) {
433 return wfe.getErrorCode()