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 org.onap.so.bpmn.common.scripts
23 import static org.apache.commons.lang3.StringUtils.*
25 import com.google.common.xml.XmlEscapers
27 import org.apache.commons.lang3.*
28 import org.camunda.bpm.engine.delegate.BpmnError
29 import org.camunda.bpm.engine.delegate.DelegateExecution
30 import org.onap.so.bpmn.core.WorkflowException
31 import org.onap.so.logger.MessageEnum
32 import org.onap.so.logger.MsoLogger
39 class ExceptionUtil extends AbstractServiceTaskProcessor {
40 private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, ExceptionUtil.class);
45 * This error handling method maps an AAI Exception response to a
46 * WorkflowException Object. It then sets the WorkflowException Object
47 * on the execution as "WorkflowException".
49 * This method formats the exception from AAI into the WorkflowException's
50 * errorMessage that CCD expects.
52 * @param execution the execution
53 * @param response the aai exception
55 WorkflowException MapAAIExceptionToWorkflowException(String response, DelegateExecution execution)
57 def utils=new MsoUtils()
58 def prefix=execution.getVariable("prefix")
59 def errorMsg = execution.getVariable(prefix+"ErrorResponse")
60 msoLogger.trace("Begin MapAAIExceptionToWorkflowException ")
63 String errorCode = '5000'
64 WorkflowException wfex
65 msoLogger.debug("response: " + response)
68 //String msg = utils.getNodeXml(response, "Fault")
69 variables = utils.getMultNodes(response, "variable")
70 text = utils.getNodeText(response, "text")
71 } catch (Exception ex) {
72 //Ignore the exception - cases include non xml payload
73 msoLogger.debug("error mapping error, ignoring: " + ex)
77 if(variables.size()>=4){
78 text = text.replaceFirst("%1", variables[0])
79 text = text.replaceFirst("%2", variables[1])
80 text = text.replaceFirst("%3", variables[2])
81 text = text.replaceFirst("%4", variables[3])
83 String modifiedErrorMessage = 'Received error from A&AI (' + text +')'
84 msoLogger.debug("ModifiedErrorMessage " + modifiedErrorMessage)
85 // let $ModifiedErrorMessage := concat( 'Received error from A',$exceptionaai:ampersand,'AI (' ,functx:replace-multi($ErrorMessage,$from,$Variables ),')')
86 buildWorkflowException(execution, 5000, modifiedErrorMessage)
88 wfex = execution.getVariable("WorkflowException")
89 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, "Fault", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, wfex.errorMessage);
93 errorCode = MapErrorCode(errorMsg)
94 String mappedErrorMessage = MapErrorMessage(errorMsg, errorCode)
96 int errorCodeInt = Integer.parseInt(errorCode)
97 buildWorkflowException(execution, errorCodeInt, mappedErrorMessage)
99 msoLogger.debug("mappedErrorMessage " + mappedErrorMessage)
100 wfex = execution.getVariable("WorkflowException")
101 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, "Fault", "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, wfex.errorMessage);
103 } catch(Exception ex) {
104 msoLogger.debug("error mapping error, return null: " + ex)
110 msoLogger.debug("Exception occured during MapAAIExceptionToWorkflowException: " + e)
111 buildWorkflowException(execution, 5000, "Error mapping AAI Response to WorkflowException")
116 * This error handling method maps an AAI Exception response to a
117 * WorkflowException Object. It then sets the WorkflowException Object
118 * on the execution as "WorkflowException".
120 * This method takes the exact exception inside the <Fault> tags from AAI Response
121 * and puts it into the WorkflowException's errorMessage.
123 * @param execution the execution
124 * @param response the aai exception
126 WorkflowException MapAAIExceptionToWorkflowExceptionGeneric(DelegateExecution execution, String response, int resCode){
127 def utils=new MsoUtils()
128 msoLogger.debug("Start MapAAIExceptionToWorkflowExceptionGeneric Process")
130 WorkflowException wfex
132 if(utils.nodeExists(response, "Fault")){
133 String fault = utils.getNodeXml(response, "Fault")
134 fault = utils.removeXmlPreamble(fault)
135 fault = fault.replace("<Fault>", "").replace("</Fault>", "")
136 fault = fault.replaceAll("\\s+\\s+", "") // Removes extra white spaces
137 buildWorkflowException(execution, resCode, fault)
138 }else if(utils.nodeExists(response, "RESTFault")){
139 String rFault = utils.getNodeXml(response, "RESTFault")
140 buildWorkflowException(execution, resCode, rFault)
142 buildWorkflowException(execution, resCode, "Received a bad response from AAI")
144 } catch (Exception ex) {
145 msoLogger.debug("Exception Occured during MapAAIExceptionToWorkflowExceptionGeneric: " + ex)
146 buildWorkflowException(execution, resCode, "Internal Error - Occured in MapAAIExceptionToWorkflowExceptionGeneric")
149 msoLogger.debug("Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"))
150 msoLogger.debug("Completed MapAAIExceptionToWorkflowExceptionGeneric Process")
154 * This method takes a WorkflowException Object and builds
155 * WorkflowException Xml. This method should only be used
156 * for the purpose of sending a sync error response or for
157 * creating a FalloutHandler request.
159 *@param - WorkflowException Object
161 *@return - String WorkflowException Xml
165 String buildErrorResponseXml(WorkflowException wfex) {
168 String mes = XmlEscapers.xmlContentEscaper().escape(wfex.getErrorMessage())
169 int code = wfex.getErrorCode()
171 """<aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
172 <aetgt:ErrorMessage>${MsoUtils.xmlEscape(mes)}</aetgt:ErrorMessage>
173 <aetgt:ErrorCode>${MsoUtils.xmlEscape(code)}</aetgt:ErrorCode>
174 </aetgt:WorkflowException>"""
178 """<aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
179 <aetgt:ErrorMessage>Internal Error</aetgt:ErrorMessage>
180 <aetgt:ErrorCode>2500</aetgt:ErrorCode>
181 </aetgt:WorkflowException>"""
187 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.
188 5010 Could not communicate with A&AI Asynchronous During orchestration of the recipe, a connection with A&AI could not be established.
189 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.
193 * Utility Method for MapAAIExceptionToWorkflowException
195 *@param - String ErrorMessage
197 *@return - String ErrorCode
200 private String MapErrorCode(String errorMessage)
202 if(errorMessage==null){
205 errorMessage = errorMessage.toLowerCase();
206 if(errorMessage.contains('timed out') || errorMessage.contains('timeout'))
208 else if (errorMessage.contains('connection'))
216 * Utility Method for MapAAIExceptionToWorkflowException
218 *@param - String ErrorMessage
219 *@param - String ErrorCode
221 *@return - String ErrorMessage
224 private String MapErrorMessage(String errorMessage, String errorCode)
226 if(errorMessage == null){
229 if( errorCode.equals('5010')){
230 return 'Could not communicate with A&AI'
231 }else if (errorCode.equals('5020')){
232 return 'No response from A&AI'
234 return 'Received error from A&AI (' +errorMessage +')'
240 * Utility Method for Mapping SDNC
241 * Adapter Response Codes
243 *@param - String sdncResponseCode
245 *@return - String code
248 String MapSDNCResponseCodeToErrorCode(String sdncResponseCode)
250 if (sdncResponseCode == '500') {
252 } else if ( sdncResponseCode == '408') {
254 } else if ( sdncResponseCode == '60010') {
262 * This error handling method builds a WorkflowException Object. It sets it on
263 * the execution as "WorkflowException".
265 * @param execution the execution
266 * @param errorCode the error code
267 * @param errorMessage the error message
269 public void buildWorkflowException(DelegateExecution execution, int errorCode, String errorMessage) {
270 MsoUtils utils = new MsoUtils()
271 String processKey = getProcessKey(execution);
272 msoLogger.debug("Building a WorkflowException for " + processKey)
274 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);
275 execution.setVariable("WorkflowException", exception);
276 msoLogger.debug("Outgoing WorkflowException is " + exception)
280 * This error handling method builds a WorkflowException Object and throws a
281 * MSOWorkflowException. It throws a "MSOWorkflowException" BpmnError after
282 * setting the WorkflowException Object on the execution as "WorkflowException".
284 * @param execution the execution
285 * @param errorCode the error code
286 * @param errorMessage the error message
288 public void buildAndThrowWorkflowException(DelegateExecution execution, int errorCode, String errorMessage) {
289 String processKey = getProcessKey(execution);
290 msoLogger.debug("Building a WorkflowException for Subflow " + processKey)
292 WorkflowException exception = new WorkflowException(processKey, errorCode, errorMessage);
293 execution.setVariable("WorkflowException", exception);
294 msoLogger.debug("Outgoing WorkflowException is " + exception)
295 msoLogger.debug("Throwing MSOWorkflowException")
296 throw new BpmnError("MSOWorkflowException")
300 * This method is executed after an MSOWorkflowException is caught by a
301 * subflow (during subflows "Error Handling Sub Process").
302 * It ensures the WorkflowException variable is populated before ending the
303 * subflow and also logs the subflows outgoing WorkflowException Variable.
308 public void processSubflowsBPMNException(DelegateExecution execution){
309 String processKey = getProcessKey(execution)
311 msoLogger.debug("Started ProcessSubflowsBPMNException Method")
312 if(execution.getVariable("WorkflowException") == null){
313 buildWorkflowException(execution, 2500, "Internal Error - Occured During " + processKey)
316 msoLogger.debug(processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"))
318 msoLogger.debug("Caught Exception during ProcessSubflowsBPMNException Method: " + e)
320 msoLogger.debug("Completed ProcessSubflowsBPMNException Method")
324 * This method is executed after an MSOWorkflowException is caught by a
325 * Mainflow. It builds and returns a FalloutHandler Request. It also
326 * verifies the WorkflowException variable is populated.
329 * @param - requestInfo
331 * @return - falloutHandlerRequest
334 public String processMainflowsBPMNException(DelegateExecution execution, String requestInfo){
335 String processKey = getProcessKey(execution)
337 msoLogger.debug("Started ProcessMainflowBPMNException Method")
338 if(execution.getVariable("WorkflowException") == null || isBlank(requestInfo)){
339 buildWorkflowException(execution, 2500, "Internal Error - WorkflowException Object and/or RequestInfo is null! " + processKey)
341 requestInfo = utils.removeXmlPreamble(requestInfo)
342 WorkflowException wfex = execution.getVariable("WorkflowException")
343 String errorMessage = XmlEscapers.xmlContentEscaper().escape(wfex.getErrorMessage())
344 int errorCode = wfex.getErrorCode()
346 String falloutHandlerRequest =
347 """<aetgt:FalloutHandlerRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
348 xmlns:ns="http://org.onap/so/request/types/v1"
349 xmlns:wfsch="http://org.onap/so/workflow/schema/v1">
351 <aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
352 <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorMessage)}</aetgt:ErrorMessage>
353 <aetgt:ErrorCode>${MsoUtils.xmlEscape(errorCode)}</aetgt:ErrorCode>
354 </aetgt:WorkflowException>
355 </aetgt:FalloutHandlerRequest>"""
357 msoLogger.debug(processKey + " Outgoing WorkflowException is: " + execution.getVariable("WorkflowException"))
358 msoLogger.debug(processKey + " Outgoing FalloutHandler Request is: " + falloutHandlerRequest)
360 return falloutHandlerRequest
363 msoLogger.debug("Caught Exception during ProcessMainflowBPMNException Method: " + e)
366 msoLogger.debug("Completed ProcessMainflowBPMNException Method")
371 * This method is executed after an Java Exception is caught
372 * It sets the WorkflowException variable. The method can be used in either mainflow or subflows.
377 public void processJavaException(DelegateExecution execution){
378 String processKey = getProcessKey(execution)
380 msoLogger.debug("Caught a Java Exception in " + processKey)
381 msoLogger.debug("Started processJavaException Method")
382 // if the BPMN flow java error handler sets "BPMN_javaExpMsg", append it to the WFE
383 String javaExpMsg = execution.getVariable("BPMN_javaExpMsg")
384 String wfeExpMsg = "Catch a Java Lang Exception in " + processKey
385 if (javaExpMsg != null && !javaExpMsg.empty) {
386 wfeExpMsg = wfeExpMsg + ": " + javaExpMsg
388 buildWorkflowException(execution, 2500, wfeExpMsg)
393 msoLogger.debug("Caught Exception during processJavaException Method: " + e)
394 buildWorkflowException(execution, 2500, "Internal Error - During Process Java Exception")
396 msoLogger.debug("Completed processJavaException Method")
400 public void preProcessRequest(DelegateExecution execution) {
401 // TODO Auto-generated method stub
405 public String getErrorMessage(WorkflowException wfe, String processKey) {
407 return "Unexpected error encountered in " + processKey
410 return wfe.getErrorMessage()
414 public int getErrorCode(WorkflowException wfe) {
419 return wfe.getErrorCode()