2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package com.att.bpm.scripts
23 import org.openecomp.mso.bpmn.core.WorkflowException
25 import org.camunda.bpm.engine.delegate.BpmnError
26 import org.camunda.bpm.engine.runtime.Execution
27 import org.apache.commons.lang3.*
29 import static org.apache.commons.lang3.StringUtils.*;
34 class ExceptionUtil extends AbstractServiceTaskProcessor {
40 * Instead use <method>MapAAIExceptionToWorkflowException</method>
42 * To Be Removed Once Refactoring Main Flow Error Handling Is Complete
47 String MapAAIExceptionToWorkflowExceptionOld(String response, Execution execution)
49 def utils=new MsoUtils()
50 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
51 def prefix=execution.getVariable("prefix")
52 def errorMsg = execution.getVariable(prefix+"ErrorResponse")
53 utils.log("DEBUG","=========== Begin MapAAIExceptionToWorkflowException ===========",isDebugEnabled)
56 String errorCode = '5000'
57 utils.log("DEBUG","response: " + response, isDebugEnabled)
59 //String msg = utils.getNodeXml(response, "Fault")
60 variables = utils.getMultNodes(response, "variable")
61 text = utils.getNodeText1(response, "text")
62 } catch (Exception ex) {
63 //Ignore the exception - cases include non xml payload
64 utils.log("DEBUG","error mapping error, ignoring: " + ex,isDebugEnabled)
68 if(variables.size()>=4){
69 text = text.replaceFirst("%1", variables[0])
70 text = text.replaceFirst("%2", variables[1])
71 text = text.replaceFirst("%3", variables[2])
72 text = text.replaceFirst("%4", variables[3])
74 String modifiedErrorMessage = 'Received error from A&AI (' + text +')'
75 utils.log("DEBUG", "ModifiedErrorMessage " + modifiedErrorMessage, isDebugEnabled)
76 // let $ModifiedErrorMessage := concat( 'Received error from A',$exceptionaai:ampersand,'AI (' ,functx:replace-multi($ErrorMessage,$from,$Variables ),')')
77 String message = """<aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
78 <aetgt:ErrorMessage>$modifiedErrorMessage</aetgt:ErrorMessage>
79 <aetgt:ErrorCode>$errorCode</aetgt:ErrorCode>
80 </aetgt:WorkflowException>"""
81 execution.setVariable(prefix+"ErrorResponse",message)
82 utils.log("ERROR","Fault:"+ execution.getVariable(prefix+"ErrorResponse"))
86 errorCode = MapErrorCode(errorMsg)
87 String mappedErrorMessage = MapErrorMessage(errorMsg, errorCode)
89 String message = """<aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
90 <aetgt:ErrorMessage>$mappedErrorMessage</aetgt:ErrorMessage>
91 <aetgt:ErrorCode>$errorCode</aetgt:ErrorCode>
92 </aetgt:WorkflowException>"""
93 utils.log("DEBUG", "mappedErrorMessage " + mappedErrorMessage, isDebugEnabled)
94 execution.setVariable(prefix+"ErrorResponse",message)
95 utils.log("ERROR","Fault:"+ execution.getVariable(prefix+"ErrorResponse"))
97 } catch(Exception ex) {
98 utils.log("DEBUG","error mapping error, return null: " + ex,isDebugEnabled)
106 * This error handling method maps an AAI Exception response to a
107 * WorkflowException Object. It then sets the WorkflowException Object
108 * on the execution as "WorkflowException".
110 * This method formats the exception from AAI into the WorkflowException's
111 * errorMessage that CCD expects.
113 * @param execution the execution
114 * @param response the aai exception
116 WorkflowException MapAAIExceptionToWorkflowException(String response, Execution execution)
118 def utils=new MsoUtils()
119 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
120 def prefix=execution.getVariable("prefix")
121 def errorMsg = execution.getVariable(prefix+"ErrorResponse")
122 utils.log("DEBUG","=========== Begin MapAAIExceptionToWorkflowException ===========",isDebugEnabled)
125 String errorCode = '5000'
126 WorkflowException wfex
127 utils.log("DEBUG","response: " + response, isDebugEnabled)
129 //String msg = utils.getNodeXml(response, "Fault")
130 variables = utils.getMultNodes(response, "variable")
131 text = utils.getNodeText1(response, "text")
132 } catch (Exception ex) {
133 //Ignore the exception - cases include non xml payload
134 utils.log("DEBUG","error mapping error, ignoring: " + ex,isDebugEnabled)
138 if(variables.size()>=4){
139 text = text.replaceFirst("%1", variables[0])
140 text = text.replaceFirst("%2", variables[1])
141 text = text.replaceFirst("%3", variables[2])
142 text = text.replaceFirst("%4", variables[3])
144 String modifiedErrorMessage = 'Received error from A&AI (' + text +')'
145 utils.log("DEBUG", "ModifiedErrorMessage " + modifiedErrorMessage, isDebugEnabled)
146 // let $ModifiedErrorMessage := concat( 'Received error from A',$exceptionaai:ampersand,'AI (' ,functx:replace-multi($ErrorMessage,$from,$Variables ),')')
147 buildWorkflowException(execution, 5000, modifiedErrorMessage)
149 wfex = execution.getVariable("WorkflowException")
150 utils.log("ERROR","Fault:"+ wfex)
154 errorCode = MapErrorCode(errorMsg)
155 String mappedErrorMessage = MapErrorMessage(errorMsg, errorCode)
157 int errorCodeInt = Integer.parseInt(errorCode)
158 buildWorkflowException(execution, errorCodeInt, mappedErrorMessage)
160 utils.log("DEBUG", "mappedErrorMessage " + mappedErrorMessage, isDebugEnabled)
161 wfex = execution.getVariable("WorkflowException")
162 utils.log("ERROR","Fault:"+ wfex, isDebugEnabled)
164 } catch(Exception ex) {
165 utils.log("DEBUG","error mapping error, return null: " + ex, isDebugEnabled)
173 * This error handling method maps an AAI Exception response to a
174 * WorkflowException Object. It then sets the WorkflowException Object
175 * on the execution as "WorkflowException".
177 * This method takes the exact exception inside the <Fault> tags from AAI Response
178 * and puts it into the WorkflowException's errorMessage.
180 * @param execution the execution
181 * @param response the aai exception
183 WorkflowException MapAAIExceptionToWorkflowExceptionGeneric(Execution execution, String response, int resCode){
184 def utils=new MsoUtils()
185 def isDebugLogEnabled = execution.getVariable("isDebugLogEnabled")
186 utils.log("DEBUG", "Start MapAAIExceptionToWorkflowExceptionGeneric Process", isDebugLogEnabled)
188 WorkflowException wfex
190 if(utils.nodeExists(response, "Fault")){
191 String fault = utils.getNodeXml(response, "Fault")
192 fault = utils.removeXmlPreamble(fault)
193 fault = fault.replace("<Fault>", "").replace("</Fault>", "")
194 fault = fault.replaceAll("\\s+\\s+", "") // Removes extra white spaces
195 buildWorkflowException(execution, resCode, fault)
196 }else if(utils.nodeExists(response, "RESTFault")){
197 String rFault = utils.getNodeXml(response, "RESTFault")
198 buildWorkflowException(execution, resCode, rFault)
200 buildWorkflowException(execution, resCode, "Received a bad response from AAI")
202 } catch (Exception ex) {
203 utils.log("DEBUG", "Exception Occured during MapAAIExceptionToWorkflowExceptionGeneric: " + ex, isDebugLogEnabled)
204 buildWorkflowException(execution, resCode, "Internal Error - Occured in MapAAIExceptionToWorkflowExceptionGeneric")
207 utils.log("DEBUG", "Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugLogEnabled)
208 utils.log("DEBUG", "Completed MapAAIExceptionToWorkflowExceptionGeneric Process", isDebugLogEnabled)
213 *This method build a WorkflowException using the adapters response.
215 *@param String response
216 *@param String adapter
218 *@return WorkflowException wfex
220 WorkflowException MapAdapterExecptionToWorkflowException(String response, Execution execution, String adapter){
221 def utils=new MsoUtils()
222 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
223 def prefix=execution.getVariable("prefix")
224 utils.log("DEBUG","=========== Start MapAdapterExecptionToWorkflowException Process ===========",isDebugEnabled)
228 WorkflowException wfex
230 errorCode = MapCategoryToErrorCode(utils.getNodeText(response, "category"))
231 errorMessage = MapAdapterErrorMessage(utils.getNodeText(response, "message"), errorCode, adapter)
233 int errorCodeInt = Integer.parseInt(errorCode)
234 buildWorkflowException(execution, errorCodeInt, errorMessage)
235 }catch (Exception ex) {
236 utils.log("DEBUG", "Exception Occured during MapAdapterExecptionToWorkflowException: " + ex, isDebugEnabled)
237 buildWorkflowException(execution, 2500, "Internal Error - Occured in MapAdapterExecptionToWorkflowException")
239 wfex = execution.getVariable("WorkflowException")
241 utils.log("DEBUG","=========== Completed MapAdapterExecptionToWorkflowException Process ===========",isDebugEnabled)
249 * Instead use <method>buildWorkflowException(Execution execution, int errorCode, String errorMessage)</method> method below
251 * To Be Removed Once Refactoring Of Main Flow Error Handling Is Complete
255 String buildWorkflowExceptionXml(String errorCode, String errorMessage) {
256 return """<aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
257 <aetgt:ErrorMessage>${errorMessage}</aetgt:ErrorMessage>
258 <aetgt:ErrorCode>${errorCode}</aetgt:ErrorCode>
259 </aetgt:WorkflowException>"""
263 * This method takes a WorkflowException Object and builds
264 * WorkflowException Xml. This method should only be used
265 * for the purpose of sending an error response.
267 *@param - WorkflowException Object
269 *@return - String WorkflowException Xml
273 String buildErrorResponseXml(WorkflowException wfex) {
276 String mes = wfex.getErrorMessage()
277 int code = wfex.getErrorCode()
279 """<aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
280 <aetgt:ErrorMessage>${mes}</aetgt:ErrorMessage>
281 <aetgt:ErrorCode>${code}</aetgt:ErrorCode>
282 </aetgt:WorkflowException>"""
286 """<aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
287 <aetgt:ErrorMessage>Internal Error</aetgt:ErrorMessage>
288 <aetgt:ErrorCode>2500</aetgt:ErrorCode>
289 </aetgt:WorkflowException>"""
295 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.
296 5010 Could not communicate with A&AI Asynchronous During orchestration of the recipe, a connection with A&AI could not be established.
297 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.
299 String MapErrorCode(String errorMessage)
301 if(errorMessage==null){
304 errorMessage = errorMessage.toLowerCase();
305 if(errorMessage.contains('timed out') || errorMessage.contains('timeout'))
307 else if (errorMessage.contains('connection'))
313 String MapErrorMessage(String errorMessage, String errorCode)
315 if(errorMessage == null){
318 if( errorCode.equals('5010'))
319 return 'Could not communicate with A&AI'
320 else if (errorCode.equals('5020'))
321 return 'No response from A&AI'
323 return 'Received error from A&AI (' +errorMessage +')'
326 String MapCategoryToErrorCode(String errorCategory)
328 if(errorCategory.equals('OPENSTACK'))
330 else if (errorCategory.equals('IO'))
332 else if (errorCategory.equals('INTERNAL'))
334 else if (errorCategory.equals('USERDATA'))
341 String MapAdapterErrorMessage(String errorMessage, String errorCode, String adapter)
343 if(errorCode.equals('5100'))
344 return 'Received error from Platform Orchestrator: ' + errorMessage
345 else if(errorCode.equals('5110'))
346 return 'Could not communicate with Platform Orchestrator'
348 return 'Received error from ' + adapter + ': ' + errorMessage
351 String MapSDNCResponseCodeToErrorCode(String sdncResponseCode)
353 if (sdncResponseCode == '500') {
355 } else if ( sdncResponseCode == '408') {
357 } else if ( sdncResponseCode == '60010') {
365 * This error handling method builds a WorkflowException Object. It sets it on
366 * the execution as "WorkflowException".
368 * @param execution the execution
369 * @param errorCode the error code
370 * @param errorMessage the error message
372 public void buildWorkflowException(Execution execution, int errorCode, String errorMessage) {
373 MsoUtils utils = new MsoUtils()
374 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
375 String processKey = getProcessKey(execution);
376 utils.log("DEBUG", "Building a WorkflowException for " + processKey, isDebugLogEnabled)
378 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);
379 execution.setVariable("WorkflowException", exception);
380 utils.log("DEBUG", "Outgoing WorkflowException is " + exception, isDebugLogEnabled)
384 * This error handling method builds a WorkflowException Object and throws a
385 * MSOWorkflowException. It throws a "MSOWorkflowException" BpmnError after
386 * setting the WorkflowException Object on the execution as "WorkflowException".
388 * @param execution the execution
389 * @param errorCode the error code
390 * @param errorMessage the error message
392 public void buildAndThrowWorkflowException(Execution execution, int errorCode, String errorMessage) {
393 def isDebugLogEnabled = execution.getVariable('isDebugLogEnabled')
394 String processKey = getProcessKey(execution);
395 utils.log("Building a WorkflowException for Subflow " + processKey, isDebugLogEnabled)
397 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);
398 execution.setVariable("WorkflowException", exception);
399 utils.log("DEBUG", "Outgoing WorkflowException is " + exception, isDebugLogEnabled)
400 utils.log("DEBUG", "Throwing MSOWorkflowException", isDebugLogEnabled)
401 throw new BpmnError("MSOWorkflowException")
405 * This method is executed after an MSOWorkflowException is caught by a
406 * subflow (during subflows "Error Handling Sub Process").
407 * It ensures the WorkflowException variable is populated before ending the
408 * subflow and also logs the subflows outgoing WorkflowException Variable.
413 public void processSubflowsBPMNException(Execution execution){
414 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
415 String processKey = getProcessKey(execution)
417 utils.log("DEBUG", "Started ProcessSubflowsBPMNException Method", isDebugEnabled)
418 if(execution.getVariable("WorkflowException") == null){
419 buildWorkflowException(execution, 2500, "Internal Error - Occured During " + processKey)
422 utils.log("DEBUG", processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugEnabled)
424 utils.log("DEBUG", "Caught Exception during ProcessSubflowsBPMNException Method: " + e, isDebugEnabled)
426 utils.log("DEBUG", "Completed ProcessSubflowsBPMNException Method", isDebugEnabled)
430 * This method is executed after an MSOWorkflowException is caught by a
431 * Mainflow. It builds and returns a FalloutHandler Request. It also
432 * verifies the WorkflowException variable is populated.
435 * @param - requestInfo
437 * @return - falloutHandlerRequest
440 public String processMainflowsBPMNException(Execution execution, String requestInfo){
441 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
442 String processKey = getProcessKey(execution)
444 utils.log("DEBUG", "Started ProcessMainflowBPMNException Method", isDebugEnabled)
445 if(execution.getVariable("WorkflowException") == null || isBlank(requestInfo)){
446 buildWorkflowException(execution, 2500, "Internal Error - WorkflowException Object and/or RequestInfo is null! " + processKey)
448 requestInfo = utils.removeXmlPreamble(requestInfo)
449 WorkflowException wfex = execution.getVariable("WorkflowException")
450 String errorMessage = wfex.getErrorMessage()
451 int errorCode = wfex.getErrorCode()
453 String falloutHandlerRequest =
454 """<aetgt:FalloutHandlerRequest xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1"
455 xmlns:ns="http://ecomp.att.com/mso/request/types/v1"
456 xmlns:wfsch="http://ecomp.att.com/mso/workflow/schema/v1">
458 <aetgt:WorkflowException xmlns:aetgt="http://ecomp.att.com/mso/workflow/schema/v1">
459 <aetgt:ErrorMessage>${errorMessage}</aetgt:ErrorMessage>
460 <aetgt:ErrorCode>${errorCode}</aetgt:ErrorCode>
461 </aetgt:WorkflowException>
462 </aetgt:FalloutHandlerRequest>"""
464 utils.log("DEBUG", processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"), isDebugEnabled)
465 utils.log("DEBUG", processKey + " Outgoing FalloutHandler Request is: " + falloutHandlerRequest, isDebugEnabled)
467 return falloutHandlerRequest
470 utils.log("DEBUG", "Caught Exception during ProcessMainflowBPMNException Method: " + e, isDebugEnabled)
473 utils.log("DEBUG", "Completed ProcessMainflowBPMNException Method", isDebugEnabled)
477 * This method is executed after an Java Exception is caught.
478 * It sets the WorkflowException variable and throws an MSOWorkflowException.
483 public void processSubflowsJavaException(Execution execution){
484 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
485 String processKey = getProcessKey(execution)
487 utils.log("DEBUG", "Caught a Java Exception in " + processKey, isDebugEnabled)
488 utils.log("DEBUG", "Started processJavaException Method", isDebugEnabled)
489 buildAndThrowWorkflowException(execution, 2500, "Catch a Java Lang Exception in " + processKey)
494 utils.log("DEBUG", "Caught Exception during processJavaException Method: " + e, isDebugEnabled)
495 buildAndThrowWorkflowException(execution, 2500, "Internal Error - During Process Java Exception")
497 utils.log("DEBUG", "Completed processJavaException Method", isDebugEnabled)
501 public void preProcessRequest(Execution execution) {
502 // TODO Auto-generated method stub