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.infrastructure.scripts
25 import org.camunda.bpm.engine.delegate.BpmnError
26 import org.camunda.bpm.engine.delegate.DelegateExecution
27 import org.onap.aai.domain.yang.VolumeGroup
28 import org.onap.so.bpmn.common.scripts.AaiUtil;
29 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor;
30 import org.onap.so.bpmn.common.scripts.ExceptionUtil;
31 import org.onap.so.bpmn.common.scripts.MsoUtils
32 import org.onap.so.bpmn.common.scripts.VidUtils;
33 import org.onap.so.bpmn.core.UrnPropertiesReader
34 import org.onap.so.bpmn.core.WorkflowException
35 import org.onap.so.client.aai.AAIObjectType
36 import org.onap.so.client.aai.entities.AAIResultWrapper
37 import org.onap.so.client.aai.entities.uri.AAIResourceUri
38 import org.onap.so.client.aai.entities.uri.AAIUriFactory
39 import org.onap.so.constants.Defaults
40 import org.onap.so.logger.ErrorCode
41 import org.onap.so.logger.MessageEnum
42 import org.slf4j.Logger
43 import org.slf4j.LoggerFactory
44 import groovy.json.JsonSlurper
46 import javax.ws.rs.NotFoundException
49 * This groovy class supports the <class>DeleteVfModuleVolume.bpmn</class> process.
51 public class DeleteVfModuleVolumeInfraV1 extends AbstractServiceTaskProcessor {
52 private static final Logger logger = LoggerFactory.getLogger( DeleteVfModuleVolumeInfraV1.class);
54 private XmlParser xmlParser = new XmlParser()
56 * This method is executed during the preProcessRequest task of the <class>DeleteVfModuleVolume.bpmn</class> process.
59 public InitializeProcessVariables(DelegateExecution execution){
60 execution.setVariable('prefix', 'DELVfModVol_')
61 execution.setVariable("DELVfModVol_volumeRequest", null)
62 execution.setVariable('DELVfModVol_requestInfo', null)
63 execution.setVariable('DELVfModVol_requestId', null)
64 execution.setVariable('DELVfModVol_source', null)
65 execution.setVariable('DELVfModVol_volumeInputs', null)
66 execution.setVariable('DELVfModVol_volumeOutputs', null)
67 execution.setVariable('DELVfModVol_volumeGroupId', null)
68 execution.setVariable('DELVfModVol_vnfType', null)
69 execution.setVariable('DELVfModVol_serviceId', null)
70 execution.setVariable('DELVfModVol_cloudRegion', null)
71 execution.setVariable('DELVfModVol_tenantId', null)
72 execution.setVariable('DELVfModVol_volumeParams', null)
73 execution.setVariable('DELVfModVol_volumeGroupHeatStackId', null)
74 execution.setVariable('DELVfModVol_volumeGroupTenantId', null)
75 execution.setVariable("DELVfModVol_queryAAIVolGrpResponse", null)
76 execution.setVariable('DELVfModVol_messageId', null)
77 execution.setVariable('DELVfModVol_deleteVnfARequest', null)
78 execution.setVariable('DELVfModVol_updateInfraRequest', null)
79 execution.setVariable('DELVfModVol_CompleteMsoProcessRequest', null)
80 execution.setVariable('DELVfModVol_WorkflowException', null)
81 execution.setVariable('DELVfModVol_TransactionSuccessIndicator', false)
82 execution.setVariable("DELVfModVol_isErrorMessageException", false)
83 execution.setVariable('DELVfModVol_syncResponseSent', false)
87 * Perform initial processing, such as request validation, initialization of variables, etc.
90 public void preProcessRequest (DelegateExecution execution) {
91 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
92 preProcessRequest(execution, isDebugEnabled)
96 * This method is executed during the preProcessRequest task of the <class>DeleteVfModuleVolume.bpmn</class> process.
99 public void preProcessRequest (DelegateExecution execution, isDebugLogEnabled) {
101 InitializeProcessVariables(execution)
103 String createVolumeIncoming = validateRequest(execution)
105 // check if request is xml or json
107 def jsonSlurper = new JsonSlurper()
108 Map reqMap = jsonSlurper.parseText(createVolumeIncoming)
109 logger.debug(" Request is in JSON format.")
111 def serviceInstanceId = execution.getVariable('serviceInstanceId')
112 def volumeGroupId = execution.getVariable('volumeGroupId')
113 def vidUtils = new VidUtils(this)
114 createVolumeIncoming = vidUtils.createXmlVolumeRequest(reqMap, 'DELETE_VF_MODULE_VOL', serviceInstanceId, volumeGroupId)
115 execution.setVariable("DELVfModVol_isVidRequest", true)
117 catch(groovy.json.JsonException je) {
118 logger.debug(" Request is in XML format.")
119 // assume request is in XML format - proceed as usual to process XML request
122 String request = utils.getNodeXml(createVolumeIncoming, "volume-request").drop(38).trim().replace("tag0:","").replace(":tag0","")
123 execution.setVariable("DELVfModVol_volumeRequest", request)
125 def requestInfo = getRequiredNodeXml(execution, request, 'request-info')
126 execution.setVariable('DELVfModVol_requestInfo', requestInfo)
127 String requestId = execution.getVariable("mso-request-id")
128 if (requestId == null || requestId == "") {
129 requestId = getRequiredNodeText(execution, requestInfo, 'request-id')
131 execution.setVariable('DELVfModVol_requestId', requestId)
132 execution.setVariable('DELVfModVol_source', getNodeTextForce(requestInfo, 'source'))
134 def volumeInputs = getRequiredNodeXml(execution, request, 'volume-inputs')
135 execution.setVariable('DELVfModVol_volumeInputs', volumeInputs)
136 execution.setVariable('DELVfModVol_volumeGroupId', getRequiredNodeText(execution, volumeInputs, 'volume-group-id'))
137 execution.setVariable('DELVfModVol_vnfType', getRequiredNodeText(execution, volumeInputs, 'vnf-type'))
138 execution.setVariable('DELVfModVol_serviceId', utils.getNodeText(volumeInputs, 'service-id'))
139 execution.setVariable('DELVfModVol_tenantId', getRequiredNodeText(execution, volumeInputs, 'tenant-id'))
140 execution.setVariable('DELVfModVol_messageId', UUID.randomUUID().toString())
141 execution.setVariable('DELVfModVol_volumeOutputs', utils.getNodeXml(request, 'volume-outputs', false))
142 execution.setVariable('DELVfModVol_volumeParams', utils.getNodeXml(request, 'volume-params'))
143 execution.setVariable('DELVfModVol_cloudRegion', utils.getNodeText(request, 'aic-cloud-region'))
145 setBasicDBAuthHeader(execution, isDebugLogEnabled)
147 logger.debug('Request: ' + createVolumeIncoming)
150 public void sendSyncResponse (DelegateExecution execution, isDebugEnabled) {
152 String volumeRequest = execution.getVariable("DELVfModVol_volumeRequest")
153 logger.debug(" DELVfModVol_volumeRequest - " + "\n" + volumeRequest)
154 // RESTResponse (for API Handler (APIH) Reply Task)
155 String deleteVolumeRequest =
156 """<rest:RESTResponse xmlns:rest="http://schemas.activebpel.org/REST/2007/12/01/aeREST.xsd" statusCode="200">
157 <rest:payload xmlns:rest="http://schemas.activebpel.org/REST/2007/12/01/aeREST.xsd"
158 contentType="text/xml">
161 </rest:RESTResponse>""".trim()
163 def isVidRequest = execution.getVariable('DELVfModVol_isVidRequest')
164 def syncResponse = ''
167 def serviceInstanceId = execution.getVariable('serviceInstanceId')
168 def volumeGroupId = execution.getVariable('volumeGroupId')
169 def requestId = execution.getVariable('DELVfModVol_requestId')
170 syncResponse = """{"requestReferences":{"instanceId":"${volumeGroupId}","requestId":"${requestId}"}}""".trim()
173 syncResponse = utils.formatXml(deleteVolumeRequest)
176 execution.setVariable('DELVfModVol_syncResponseSent', true)
178 sendWorkflowResponse(execution, 200, syncResponse)
182 public void sendSyncError (DelegateExecution execution, isDebugEnabled) {
183 WorkflowException we = execution.getVariable('WorkflowException')
184 def errorCode = we?.getErrorCode()
185 def errorMessage = we?.getErrorMessage()
186 //default to 400 since only invalid request will trigger this method
187 sendWorkflowResponse(execution, 400, errorMessage)
191 public void callRESTQueryAAICloudRegion (DelegateExecution execution, isDebugEnabled) {
193 String cloudRegion = execution.getVariable('DELVfModVol_cloudRegion')
195 AaiUtil aaiUtil = new AaiUtil(this)
197 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.CLOUD_REGION, Defaults.CLOUD_OWNER.toString(), cloudRegion)
198 def queryCloudRegionRequest = aaiUtil.createAaiUri(uri)
200 execution.setVariable("DELVfModVol_queryCloudRegionRequest", queryCloudRegionRequest)
202 cloudRegion = aaiUtil.getAAICloudReqion(execution, queryCloudRegionRequest, "PO", cloudRegion)
204 ExceptionUtil exceptionUtil = new ExceptionUtil()
206 if ((cloudRegion != "ERROR")) {
207 if(execution.getVariable("DELVfModVol_queryCloudRegionReturnCode") == "404"){
208 execution.setVariable("DELVfModVol_aicCloudRegion", "AAIAIC25")
210 execution.setVariable("DELVfModVol_aicCloudRegion", cloudRegion)
212 execution.setVariable("DELVfModVol_cloudRegion", cloudRegion)
213 execution.setVariable("DELVfModVol_isCloudRegionGood", true)
216 logger.debug("AAI Query Cloud Region Unsuccessful.")
217 execution.setVariable("DELVfModVol_isCloudRegionGood", false)
218 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "AAI Query Cloud Region Unsuccessful. Return Code: " + execution.getVariable("DELVfModVol_queryCloudRegionReturnCode"))
221 logger.debug(" is Cloud Region Good: " + execution.getVariable("DELVfModVol_isCloudRegionGood"))
225 * Query volume group by id
228 public void queryAAIForVolumeGroup(DelegateExecution execution, isDebugLogEnabled) {
230 ExceptionUtil exceptionUtil = new ExceptionUtil()
232 def volumeGroupId = execution.getVariable('DELVfModVol_volumeGroupId')
233 if(volumeGroupId == null) {
234 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, 'volume-group-id is not provided in the request')
235 throw new Exception('volume-group-id is not provided in the request')
237 String cloudRegion = execution.getVariable('DELVfModVol_aicCloudRegion')
240 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(), cloudRegion, volumeGroupId)
241 AAIResultWrapper volumeGroupWrapper = getAAIClient().get(uri)
243 if (!volumeGroupWrapper.isEmpty()) {
244 Optional<VolumeGroup> volumeGroupOp = volumeGroupWrapper.asBean(VolumeGroup.class)
245 execution.setVariable("DELVfModVol_queryAAIVolGrpResponse", volumeGroupOp.get())
246 def heatStackId = volumeGroupOp.get().getHeatStackId() ?: ""
247 execution.setVariable('DELVfModVol_volumeGroupHeatStackId', heatStackId)
249 if ( volumeGroupWrapper.getRelationships().isPresent() && !volumeGroupWrapper.getRelationships().get().getRelatedAAIUris(AAIObjectType.VF_MODULE).isEmpty()) {
250 logger.debug('Volume Group ' + volumeGroupId + ' currently in use')
251 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume Group ${volumeGroupId} currently in use - found vf-module relationship.")
254 def volumeGroupTenantId = getTenantIdFromVolumeGroup(volumeGroupWrapper)
255 if (volumeGroupTenantId == null) {
256 logger.debug("Could not find Tenant Id element in Volume Group with Volume Group Id ${volumeGroupId}")
257 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Could not find Tenant Id element in Volume Group with Volume Group Id ${volumeGroupId}")
260 execution.setVariable('DELVfModVol_volumeGroupTenantId', volumeGroupTenantId)
261 logger.debug('Received Tenant Id ' + volumeGroupTenantId + ' from AAI for Volume Group with Volume Group Id ' + volumeGroupId)
263 logger.debug("Volume Group ${volumeGroupId} not found in AAI")
264 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume Group ${volumeGroupId} not found in AAI. Response code: 404")
266 }catch (BpmnError e){
268 }catch (Exception e){
269 WorkflowException aWorkflowException = exceptionUtil.MapAAIExceptionToWorkflowException(e.getMessage(), execution)
270 throw new BpmnError("MSOWorkflowException")
275 * Extract the Tenant Id from the Volume Group information returned by AAI.
277 * @param volumeGroupXml Volume Group XML returned by AAI.
278 * @return the Tenant Id extracted from the Volume Group information. 'null' is returned if
279 * the Tenant Id is missing or could not otherwise be extracted.
281 private String getTenantIdFromVolumeGroup(AAIResultWrapper wrapper) {
282 if(wrapper.getRelationships().isPresent()) {
283 List<AAIResourceUri> tenantURIList = wrapper.getRelationships().get().getRelatedAAIUris(AAIObjectType.TENANT)
284 if(!tenantURIList.isEmpty()){
285 return tenantURIList.get(0).getURIKeys().get("tenant-id")
291 private boolean hasVnfRelationship(String volumeGroupXml) {
292 def Node volumeGroupNode = xmlParser.parseText(volumeGroupXml)
293 def Node relationshipList = utils.getChildNode(volumeGroupNode, 'relationship-list')
294 if (relationshipList != null) {
295 def NodeList relationships = utils.getIdenticalChildren(relationshipList, 'relationship')
296 for (Node relationship in relationships) {
297 def Node relatedTo = utils.getChildNode(relationship, 'related-to')
298 if ((relatedTo != null) && (relatedTo.text().equals('generic-vnf'))) {
299 def Node relatedLink = utils.getChildNode(relationship, 'related-link')
300 if (relatedLink !=null && relatedLink.text() != null){
309 public void prepareVnfAdapterDeleteRequest(DelegateExecution execution, isDebugLogEnabled) {
310 def cloudRegion = execution.getVariable('DELVfModVol_cloudRegion')
311 def tenantId = execution.getVariable('DELVfModVol_tenantId')
312 def volumeGroupId = execution.getVariable('DELVfModVol_volumeGroupId')
313 def volumeGroupHeatStackId = execution.getVariable('DELVfModVol_volumeGroupHeatStackId')
314 def requestId = execution.getVariable('DELVfModVol_requestId')
315 def serviceId = execution.getVariable('DELVfModVol_serviceId')
317 def messageId = execution.getVariable('DELVfModVol_messageId')
318 def notificationUrl = createCallbackURL(execution, "VNFAResponse", messageId)
319 def useQualifiedHostName = UrnPropertiesReader.getVariable("mso.use.qualified.host", execution)
320 if ('true'.equals(useQualifiedHostName)) {
321 notificationUrl = utils.getQualifiedHostNameForCallback(notificationUrl)
324 String vnfAdapterRestRequest = """
325 <deleteVolumeGroupRequest>
326 <cloudSiteId>${MsoUtils.xmlEscape(cloudRegion)}</cloudSiteId>
327 <tenantId>${MsoUtils.xmlEscape(tenantId)}</tenantId>
328 <volumeGroupId>${MsoUtils.xmlEscape(volumeGroupId)}</volumeGroupId>
329 <volumeGroupStackId>${MsoUtils.xmlEscape(volumeGroupHeatStackId)}</volumeGroupStackId>
330 <skipAAI>true</skipAAI>
332 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
333 <serviceInstanceId>${MsoUtils.xmlEscape(serviceId)}</serviceInstanceId>
335 <messageId>${MsoUtils.xmlEscape(messageId)}</messageId>
336 <notificationUrl>${MsoUtils.xmlEscape(notificationUrl)}</notificationUrl>
337 </deleteVolumeGroupRequest>
339 vnfAdapterRestRequest = utils.formatXml(vnfAdapterRestRequest)
340 execution.setVariable('DELVfModVol_deleteVnfARequest', vnfAdapterRestRequest)
341 logger.debug('Request for VNFAdapter Rest:\n' + vnfAdapterRestRequest)
345 public void deleteVolGrpId(DelegateExecution execution, isDebugEnabled) {
348 VolumeGroup volumeGroup = execution.getVariable("DELVfModVol_queryAAIVolGrpResponse")
349 String groupId = volumeGroup.getVolumeGroupId()
350 String cloudRegion = execution.getVariable('DELVfModVol_aicCloudRegion')
352 ExceptionUtil exceptionUtil = new ExceptionUtil()
354 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.VOLUME_GROUP, Defaults.CLOUD_OWNER.toString(), cloudRegion, groupId)
355 getAAIClient().delete(uri)
356 logger.debug("Volume group $groupId deleted.")
357 }catch(NotFoundException e){
358 exceptionUtil.buildAndThrowWorkflowException(execution, 2500, "Volume group $groupId not found for delete in AAI Response code: 404")
359 }catch(Exception e1){
360 WorkflowException aWorkflowException = exceptionUtil.MapAAIExceptionToWorkflowException(e1.getMessage(), execution)
361 throw new BpmnError("MSOWorkflowException")
366 public void prepareDBRequest (DelegateExecution execution, isDebugLogEnabled) {
368 WorkflowException workflowExceptionObj = execution.getVariable("WorkflowException")
369 ExceptionUtil exceptionUtil = new ExceptionUtil();
370 def requestId = execution.getVariable('DELVfModVol_requestId')
371 def volOutputs = execution.getVariable('DELVfModVol_volumeOutputs')
372 def statusMessage = "VolumeGroup successfully deleted"
374 def requestStatus = "COMPLETE"
376 if (workflowExceptionObj != null) {
377 statusMessage = (workflowExceptionObj.getErrorMessage())
378 execution.setVariable("DELVfModVol_WorkflowExceptionMessage", statusMessage)
379 execution.setVariable("DELVfModVol_WorkflowExceptionCode", workflowExceptionObj.getErrorCode())
380 requestStatus = "FAILURE"
384 String updateInfraRequest = """
385 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
386 xmlns:req="http://org.onap.so/requestsdb">
389 <req:updateInfraRequest>
390 <requestId>${MsoUtils.xmlEscape(requestId)}</requestId>
391 <lastModifiedBy>BPMN</lastModifiedBy>
392 <statusMessage>${MsoUtils.xmlEscape(statusMessage)}</statusMessage>
393 <requestStatus>${MsoUtils.xmlEscape(requestStatus)}</requestStatus>
394 <progress>${MsoUtils.xmlEscape(progress)}</progress>
395 <vnfOutputs>${MsoUtils.xmlEscape(volOutputs)}</vnfOutputs>
396 </req:updateInfraRequest>
401 updateInfraRequest = utils.formatXml(updateInfraRequest)
402 execution.setVariable('DELVfModVol_updateInfraRequest', updateInfraRequest)
403 logger.debug('Request for Update Infra Request:\n' + updateInfraRequest)
408 public void prepareCompletionHandlerRequest (DelegateExecution execution, isDebugLogEnabled) {
409 def requestId = execution.getVariable("mso-request-id")
410 def source = execution.getVariable("DELVfModVol_source")
412 String msoCompletionRequest =
413 """<aetgt:MsoCompletionRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
414 xmlns:ns="http://org.onap/so/request/types/v1">
415 <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
416 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
417 <action>DELETE</action>
418 <source>${MsoUtils.xmlEscape(source)}</source>
420 <aetgt:status-message>Volume Group has been deleted successfully.</aetgt:status-message>
421 <aetgt:mso-bpel-name>BPMN VF Module Volume action: DELETE</aetgt:mso-bpel-name>
422 </aetgt:MsoCompletionRequest>"""
424 String xmlMsoCompletionRequest = utils.formatXml(msoCompletionRequest)
425 execution.setVariable('DELVfModVol_CompleteMsoProcessRequest', xmlMsoCompletionRequest)
426 logger.debug(" Overall SUCCESS Response going to CompleteMsoProcess - " + "\n" + xmlMsoCompletionRequest)
432 public void prepareFalloutHandler (DelegateExecution execution) {
434 execution.setVariable("DELVfModVol_Success", false)
435 String requestId = execution.getVariable("DELVfModVol_requestId")
436 String source = execution.getVariable("DELVfModVol_source")
438 WorkflowException workflowExceptionObj = execution.getVariable("WorkflowException")
439 def errorMessage = workflowExceptionObj.getErrorMessage()
440 def errorCode = workflowExceptionObj.getErrorCode()
442 String falloutHandlerRequest =
443 """<aetgt:FalloutHandlerRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
444 xmlns:ns="http://org.onap/so/request/types/v1"
445 xmlns:wfsch="http://org.onap/so/workflow/schema/v1">
446 <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
447 <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
448 <action>DELETE</action>
449 <source>${MsoUtils.xmlEscape(source)}</source>
451 <aetgt:WorkflowException>
452 <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorMessage)}</aetgt:ErrorMessage>
453 <aetgt:ErrorCode>${MsoUtils.xmlEscape(errorCode)}</aetgt:ErrorCode>
454 </aetgt:WorkflowException>
455 </aetgt:FalloutHandlerRequest>"""
458 String xmlHandlerRequest = utils.formatXml(falloutHandlerRequest)
459 logger.debug(xmlHandlerRequest)
461 execution.setVariable("DELVfModVol_FalloutHandlerRequest", xmlHandlerRequest)
462 logger.error("{} {} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
463 "Overall Error Response going to FalloutHandler", "BPMN",
464 ErrorCode.UnknownError.getValue(), "\n" + xmlHandlerRequest);
469 * Create a WorkflowException for the error case where the Tenant Id from
470 * AAI did not match the Tenant Id in the incoming request.
472 * @param execution The flow's execution instance.
474 public void handleTenantIdMismatch(DelegateExecution execution, isDebugLogEnabled) {
476 def volumeGroupId = execution.getVariable('DELVfModVol_volumeGroupId')
477 def aicCloudRegion = execution.getVariable('DELVfModVol_aicCloudRegion')
478 def tenantId = execution.getVariable('DELVfModVol_tenantId')
479 def volumeGroupTenantId = execution.getVariable('DELVfModVol_volumeGroupTenantId')
481 def String errorMessage = 'TenantId ' + tenantId + ' in incoming request does not match Tenant Id ' + volumeGroupTenantId +
482 ' retrieved from AAI for Volume Group Id ' + volumeGroupId
483 logger.error("{} {} {} {}", MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
484 "Error in DeleteVfModuleVolume: " + "\n" + errorMessage, "BPMN",
485 ErrorCode.UnknownError.getValue());
487 ExceptionUtil exceptionUtil = new ExceptionUtil()
488 exceptionUtil.buildWorkflowException(execution, 5000, errorMessage)