Merge "add instance group support to SO"
[so.git] / bpmn / so-bpmn-infrastructure-common / src / main / groovy / org / onap / so / bpmn / infrastructure / scripts / UpdateCustomE2EServiceInstance.groovy
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2018 Huawei Technologies Co., Ltd. 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
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
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=========================================================
21  */
22
23 package org.onap.so.bpmn.infrastructure.scripts;
24
25 import static org.apache.commons.lang3.StringUtils.*;
26
27 import javax.ws.rs.NotFoundException
28
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.json.JSONArray
33 import org.json.JSONObject
34 import org.onap.aai.domain.yang.ServiceInstance
35 import org.onap.so.bpmn.common.scripts.AbstractServiceTaskProcessor
36 import org.onap.so.bpmn.common.scripts.ExceptionUtil
37 import org.onap.so.bpmn.common.scripts.MsoUtils
38 import org.onap.so.bpmn.core.WorkflowException
39 import org.onap.so.bpmn.core.domain.Resource
40 import org.onap.so.bpmn.core.json.JsonUtils
41 import org.onap.so.bpmn.core.UrnPropertiesReader
42 import org.onap.so.client.aai.AAIObjectType
43 import org.onap.so.client.aai.AAIResourcesClient
44 import org.onap.so.client.aai.entities.AAIResultWrapper
45 import org.onap.so.client.aai.entities.uri.AAIResourceUri
46 import org.onap.so.client.aai.entities.uri.AAIUriFactory
47 import org.springframework.web.util.UriUtils
48 import org.slf4j.Logger
49 import org.slf4j.LoggerFactory
50
51 import groovy.json.*
52
53 /**
54  * This groovy class supports the <class>UpdateCustomE2EServiceInstance.bpmn</class> process.
55  * AlaCarte flow for 1702 ServiceInstance Update
56  *
57  */
58 public class UpdateCustomE2EServiceInstance extends AbstractServiceTaskProcessor {
59         private static final Logger logger = LoggerFactory.getLogger( UpdateCustomE2EServiceInstance.class);
60
61         String Prefix="UPDSI_"
62         ExceptionUtil exceptionUtil = new ExceptionUtil()
63         JsonUtils jsonUtil = new JsonUtils()
64
65
66         public void preProcessRequest (DelegateExecution execution) {
67                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
68                 execution.setVariable("prefix",Prefix)
69                 String msg = ""
70                 logger.info( " *** preProcessRequest() *** ")
71
72                 try {
73
74                         String siRequest = execution.getVariable("bpmnRequest")
75                         utils.logAudit(siRequest)
76
77                         String requestId = execution.getVariable("mso-request-id")
78                         execution.setVariable("msoRequestId", requestId)
79                         logger.info( "Input Request:" + siRequest + " reqId:" + requestId)
80
81                         String serviceInstanceId = execution.getVariable("serviceInstanceId")
82                         if (isBlank(serviceInstanceId)) {
83                                 msg = "Input serviceInstanceId' is null"
84                                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
85                         }
86
87                         //subscriberInfo for aai
88                         String globalSubscriberId = jsonUtil.getJsonValue(siRequest, "requestDetails.subscriberInfo.globalSubscriberId")
89                         if (isBlank(globalSubscriberId)) {
90                                 msg = "Input globalSubscriberId' is null"
91                                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
92                         } else {
93                                 execution.setVariable("globalSubscriberId", globalSubscriberId)
94                         }
95
96                         //requestDetails
97                         execution.setVariable("source", jsonUtil.getJsonValue(siRequest, "requestDetails.requestInfo.source"))
98                         execution.setVariable("serviceInstanceName", jsonUtil.getJsonValue(siRequest, "requestDetails.requestInfo.instanceName"))
99                         execution.setVariable("disableRollback", jsonUtil.getJsonValue(siRequest, "requestDetails.requestInfo.suppressRollback"))
100                         String productFamilyId = jsonUtil.getJsonValue(siRequest, "requestDetails.requestInfo.productFamilyId")
101                         if (isBlank(productFamilyId))
102                         {
103                                 msg = "Input productFamilyId is null"
104                                 logger.info( msg)
105                         } else {
106                                 execution.setVariable("productFamilyId", productFamilyId)
107                         }
108
109                          //user params
110                  String userParams = jsonUtil.getJsonValue(siRequest, "requestDetails.requestParameters.userParams")
111              logger.info( "userParams:" + userParams)
112                  List<String> paramList = jsonUtil.StringArrayToList(execution, userParams)
113                  String uuiRequest = jsonUtil.getJsonValue(paramList.get(0), "UUIRequest")
114                         if (isBlank(uuiRequest)) {
115                                 msg = "Input uuiRequest is null"
116                                 logger.info( msg)
117                                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
118                         } else
119                         {
120                                 execution.setVariable("uuiRequest", uuiRequest)
121                         }
122
123                         logger.info( "uuiRequest:\n" + uuiRequest)
124
125                         //serviceType for aai
126                         String serviceType = jsonUtil.getJsonValue(uuiRequest, "service.serviceType")
127                         if (isBlank(serviceType)) {
128                                 msg = "Input serviceType is null"
129                                 logger.info( msg)
130                                 exceptionUtil.buildAndThrowWorkflowException(execution, 500, msg)
131                         } else {
132                                 execution.setVariable("serviceType", serviceType)
133                         }
134
135                         // target model info
136                         String modelInvariantUuid = jsonUtil.getJsonValue(uuiRequest, "service.serviceInvariantUuid")
137                         logger.info("modelInvariantUuid: " + modelInvariantUuid)
138                         execution.setVariable("modelInvariantUuid", modelInvariantUuid)
139                         execution.setVariable("model-invariant-id-target", modelInvariantUuid)
140
141                         String modelUuid = jsonUtil.getJsonValue(uuiRequest, "service.serviceUuid")
142                         logger.info("modelUuid: " + modelUuid)
143                         execution.setVariable("modelUuid", modelUuid)
144                         execution.setVariable("model-version-id-target", modelUuid)
145
146                         String serviceModelName = jsonUtil.getJsonValue(uuiRequest, "service.parameters.templateName")
147                         logger.info("serviceModelName: " + serviceModelName)
148                         if(serviceModelName == null) {
149                                 serviceModelName = ""
150                         }
151                         execution.setVariable("serviceModelName", serviceModelName)
152
153                         //operationId
154                         String operationId = jsonUtil.getJsonValue(siRequest, "operationId")
155                         if (isBlank(operationId)) {
156                                 operationId = UUID.randomUUID().toString()
157                          }
158                         execution.setVariable("operationId", operationId)
159                         execution.setVariable("operationType", "update")
160                         execution.setVariable("hasResourcetoUpdate", false)
161
162                 } catch (BpmnError e) {
163                         throw e;
164                 } catch (Exception ex){
165                         msg = "Exception in preProcessRequest " + ex.getMessage()
166                         logger.info( msg)
167                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
168                 }
169                 logger.info(" ***** Exit preProcessRequest *****")
170         }
171
172         /**
173          * Gets the service instance and its relationships from aai
174          */
175         public void getServiceInstance(DelegateExecution execution) {
176                 try {
177                         String serviceInstanceId = execution.getVariable('serviceInstanceId')
178                         String globalSubscriberId = execution.getVariable('globalSubscriberId')
179                         String serviceType = execution.getVariable('serviceType')
180
181                         AAIResourcesClient resourceClient = new AAIResourcesClient()
182                         AAIResourceUri serviceInstanceUri = AAIUriFactory.createResourceUri(AAIObjectType.SERVICE_INSTANCE, globalSubscriberId, serviceType, serviceInstanceId)
183                         AAIResultWrapper wrapper = resourceClient.get(serviceInstanceUri, NotFoundException.class)
184
185                         Optional<ServiceInstance> si = wrapper.asBean(ServiceInstance.class)
186                         execution.setVariable("serviceInstanceName", si.get().getServiceInstanceName())
187                         execution.setVariable("model-invariant-id-original", si.get().getModelInvariantId())
188                         execution.setVariable("model-version-id-original", si.get().getModelVersionId())
189
190                         JSONObject ob = new JSONObject(wrapper.getJson())
191                         JSONArray ar = ob.getJSONObject("relationship-list").getJSONArray("relationship")
192
193                         execution.setVariable("serviceRelationShip", ar.toString())
194
195
196                 }catch(BpmnError e) {
197                         throw e;
198                 }catch(NotFoundException e) {
199                         exceptionUtil.buildAndThrowWorkflowException(execution, 404, "Service-instance does not exist AAI")
200                 }catch(Exception ex) {
201                         String msg = "Internal Error in getServiceInstance: " + ex.getMessage()
202                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
203                 }
204         }
205
206         public void preCompareModelVersions(DelegateExecution execution) {
207                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
208         }
209
210         public void postCompareModelVersions(DelegateExecution execution) {
211                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
212                 logger.debug( " ======== STARTED postCompareModelVersions Process ======== ")
213
214                 def hasResourcetoUpdate = false
215                 def hasResourcetoAdd = false
216                 def hasResourcetoDelete = false
217                 List<Resource> addResourceList =  execution.getVariable("addResourceList")
218                 List<Resource> delResourceList =  execution.getVariable("delResourceList")
219
220                 if(addResourceList != null && !addResourceList.isEmpty()) {
221                         hasResourcetoAdd = true
222                 }
223
224                 if(delResourceList != null && !delResourceList.isEmpty()) {
225                         hasResourcetoDelete = true
226                 }
227
228                 hasResourcetoUpdate = hasResourcetoAdd || hasResourcetoDelete
229                 execution.setVariable("hasResourcetoUpdate", hasResourcetoUpdate)
230
231                 logger.debug( "======== COMPLETED postCompareModelVersions Process ======== ")
232         }
233
234         /**
235          * Init the service Operation Status
236          */
237         public void prepareInitServiceOperationStatus(DelegateExecution execution){
238                 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
239                 logger.debug( " ======== STARTED prepareInitServiceOperationStatus Process ======== ")
240                 try{
241                         String serviceId = execution.getVariable("serviceInstanceId")
242                         String operationId = execution.getVariable("operationId")
243                         String operationType = execution.getVariable("operationType")
244                         String userId = ""
245                         String result = "processing"
246                         String progress = "0"
247                         String reason = ""
248                         String operationContent = "Prepare service updating"
249                         logger.debug( "Generated new operation for Service Instance serviceId:" + serviceId + " operationId:" + operationId)
250                         serviceId = UriUtils.encode(serviceId,"UTF-8")
251                         execution.setVariable("serviceInstanceId", serviceId)
252                         execution.setVariable("operationId", operationId)
253                         execution.setVariable("operationType", operationType)
254
255                         def dbAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.openecomp.db.endpoint", execution)
256                         execution.setVariable("CVFMI_dbAdapterEndpoint", dbAdapterEndpoint)
257                         logger.debug( "DB Adapter Endpoint is: " + dbAdapterEndpoint)
258
259                         String payload =
260                                 """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
261                         xmlns:ns="http://org.onap.so/requestsdb">
262                         <soapenv:Header/>
263                         <soapenv:Body>
264                             <ns:updateServiceOperationStatus xmlns:ns="http://org.onap.so/requestsdb">
265                             <serviceId>${MsoUtils.xmlEscape(serviceId)}</serviceId>
266                             <operationId>${MsoUtils.xmlEscape(operationId)}</operationId>
267                             <operationType>${MsoUtils.xmlEscape(operationType)}</operationType>
268                             <userId>${MsoUtils.xmlEscape(userId)}</userId>
269                             <result>${MsoUtils.xmlEscape(result)}</result>
270                             <operationContent>${MsoUtils.xmlEscape(operationContent)}</operationContent>
271                             <progress>${MsoUtils.xmlEscape(progress)}</progress>
272                             <reason>${MsoUtils.xmlEscape(reason)}</reason>
273                         </ns:updateServiceOperationStatus>
274                     </soapenv:Body>
275                 </soapenv:Envelope>"""
276
277                         payload = utils.formatXml(payload)
278                         execution.setVariable("CVFMI_updateServiceOperStatusRequest", payload)
279                         logger.error( "Outgoing updateServiceOperStatusRequest: \n" + payload)
280                         utils.logAudit("CreateVfModuleInfra Outgoing updateServiceOperStatusRequest Request: " + payload)
281
282                 }catch(Exception e){
283                         logger.debug( "Exception Occured Processing prepareInitServiceOperationStatus. Exception is:\n" + e)
284                         execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during prepareInitServiceOperationStatus Method:\n" + e.getMessage())
285                 }
286                 logger.debug( "======== COMPLETED prepareInitServiceOperationStatus Process ======== ")
287         }
288
289         /**
290          * Update the service Operation Status
291          */
292         public void preUpdateServiceOperationStatus(DelegateExecution execution){
293                 def method = getClass().getSimpleName() + '.preUpdateServiceOperationStatus(' +'execution=' + execution.getId() +')'
294                 def isDebugEnabled = execution.getVariable("isDebugLogEnabled")
295                 logger.info("Entered " + method)
296
297                 try{
298                         String serviceId = execution.getVariable("serviceInstanceId")
299                         String operationId = execution.getVariable("operationId")
300                         String operationType = execution.getVariable("operationType")
301                         String serviceName = execution.getVariable("serviceInstanceName")
302                         String result = execution.getVariable("operationResult")
303                         String progress = execution.getVariable("progress")
304                         String reason = execution.getVariable("operationReason")
305                         String userId = ""
306                         logger.info( "progress: " + progress )
307
308                         String operationContent = "Prepare service : " + execution.getVariable("operationStatus")
309
310                         logger.info( "Generated new operation for Service Instance serviceId:" + serviceId + " operationId:" + operationId)
311                         serviceId = UriUtils.encode(serviceId,"UTF-8")
312                         execution.setVariable("serviceInstanceId", serviceId)
313                         execution.setVariable("operationId", operationId)
314                         execution.setVariable("operationType", operationType)
315
316             def dbAdapterEndpoint = UrnPropertiesReader.getVariable("mso.adapters.openecomp.db.endpoint", execution)
317             execution.setVariable("CVFMI_dbAdapterEndpoint", dbAdapterEndpoint)
318                         logger.info( "DB Adapter Endpoint is: " + dbAdapterEndpoint)
319
320                         String payload =
321                                 """<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
322                         xmlns:ns="http://org.onap.so/requestsdb">
323                         <soapenv:Header/>
324                         <soapenv:Body>
325                             <ns:updateServiceOperationStatus xmlns:ns="http://org.onap.so/requestsdb">
326                             <serviceId>${MsoUtils.xmlEscape(serviceId)}</serviceId>
327                             <operationId>${MsoUtils.xmlEscape(operationId)}</operationId>
328                             <operationType>${MsoUtils.xmlEscape(operationType)}</operationType>
329                             <userId>${MsoUtils.xmlEscape(userId)}</userId>
330                             <result>${MsoUtils.xmlEscape(result)}</result>
331                             <operationContent>${MsoUtils.xmlEscape(operationContent)}</operationContent>
332                             <progress>${MsoUtils.xmlEscape(progress)}</progress>
333                             <reason>${MsoUtils.xmlEscape(reason)}</reason>
334                         </ns:updateServiceOperationStatus>
335                     </soapenv:Body>
336                 </soapenv:Envelope>"""
337
338                         payload = utils.formatXml(payload)
339                         execution.setVariable("CVFMI_updateServiceOperStatusRequest", payload)
340                         logger.error( "Outgoing preUpdateServiceOperationStatus: \n" + payload)
341
342
343                 }catch(Exception e){
344                         logger.info( "Exception Occured Processing preUpdateServiceOperationStatus. Exception is:\n" + e)
345                         execution.setVariable("CVFMI_ErrorResponse", "Error Occurred during preUpdateServiceOperationStatus Method:\n" + e.getMessage())
346                 }
347                 logger.info( "======== COMPLETED preUpdateServiceOperationStatus Process ======== ")
348                 logger.info( "Exited " + method)
349         }
350
351         public void sendSyncResponse (DelegateExecution execution) {
352                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
353                 logger.info( " *** sendSyncResponse *** ")
354
355                 try {
356                         String operationId = execution.getVariable("operationId")
357                         def hasResourcetoUpdate = execution.getVariable("hasResourcetoUpdate")
358
359                         String updateServiceResp = ""
360                         if(hasResourcetoUpdate) {
361                                 // RESTResponse for API Handler (APIH) Reply Task
362                                 updateServiceResp = """{"operationId":"${operationId}"}""".trim()
363                         }
364                         else {
365                                 updateServiceResp =  """{"OperationResult":"No Resource to Add or Delete or Service Instance not found in AAI."}"""
366                         }
367
368                         logger.info( " sendSyncResponse to APIH:" + "\n" + updateServiceResp)
369                         sendWorkflowResponse(execution, 202, updateServiceResp)
370                         execution.setVariable("sentSyncResponse", true)
371
372                 } catch (Exception ex) {
373                         String msg = "Exceptuion in sendSyncResponse:" + ex.getMessage()
374                         logger.info( msg)
375                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
376                 }
377                 logger.info(" ***** Exit sendSyncResopnse *****")
378         }
379
380         public void sendSyncError (DelegateExecution execution) {
381                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
382                 logger.info( " *** sendSyncError *** ")
383
384                 try {
385                         String errorMessage = ""
386                         int errorCode = 7000
387                         if (execution.getVariable("WorkflowException") instanceof WorkflowException) {
388                                 WorkflowException wfe = execution.getVariable("WorkflowException")
389                                 errorMessage = wfe.getErrorMessage()
390                                 errorCode = wfe.getErrorCode()
391                         } else {
392                                 errorMessage = "Sending Sync Error."
393                         }
394
395                         String buildworkflowException =
396                                         """<aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
397                                         <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorMessage)}</aetgt:ErrorMessage>
398                                         <aetgt:ErrorCode>${MsoUtils.xmlEscape(errorCode)}</aetgt:ErrorCode>
399                                    </aetgt:WorkflowException>"""
400
401                         utils.logAudit(buildworkflowException)
402                         sendWorkflowResponse(execution, 500, buildworkflowException)
403
404                 } catch (Exception ex) {
405                         logger.info( " Sending Sync Error Activity Failed. " + "\n" + ex.getMessage())
406                 }
407
408         }
409
410         public void prepareCompletionRequest (DelegateExecution execution) {
411                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
412                 logger.info( " *** prepareCompletion *** ")
413
414                 try {
415                         String requestId = execution.getVariable("msoRequestId")
416                         String serviceInstanceId = execution.getVariable("serviceInstanceId")
417                         String source = execution.getVariable("source")
418
419                         String msoCompletionRequest =
420                                         """<aetgt:MsoCompletionRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
421                                                                 xmlns:ns="http://org.onap/so/request/types/v1">
422                                                 <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
423                                                         <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
424                                                         <action>UPDATE</action>
425                                                         <source>${MsoUtils.xmlEscape(source)}</source>
426                                                 </request-info>
427                                                 <status-message>Service Instance was updated successfully.</status-message>
428                                                 <serviceInstanceId>${MsoUtils.xmlEscape(serviceInstanceId)}</serviceInstanceId>
429                                                 <mso-bpel-name>UpdateCustomE2EServiceInstance</mso-bpel-name>
430                                         </aetgt:MsoCompletionRequest>"""
431
432                         // Format Response
433                         String xmlMsoCompletionRequest = utils.formatXml(msoCompletionRequest)
434
435                         execution.setVariable("completionRequest", xmlMsoCompletionRequest)
436                         logger.info( " Overall SUCCESS Response going to CompleteMsoProcess - " + "\n" + xmlMsoCompletionRequest)
437
438                 } catch (Exception ex) {
439                         String msg = " Exception in prepareCompletion:" + ex.getMessage()
440                         logger.info( msg)
441                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg)
442                 }
443                 logger.info( "*** Exit prepareCompletionRequest ***")
444         }
445
446         public void prepareFalloutRequest(DelegateExecution execution){
447                 def isDebugEnabled=execution.getVariable("isDebugLogEnabled")
448                 logger.info( " *** prepareFalloutRequest *** ")
449
450                 try {
451                         WorkflowException wfex = execution.getVariable("WorkflowException")
452                         logger.info( " Input Workflow Exception: " + wfex.toString())
453                         String requestId = execution.getVariable("msoRequestId")
454                         String source = execution.getVariable("source")
455                         String requestInfo =
456                                         """<request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
457                                         <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
458                                         <action>UPDATE</action>
459                                         <source>${MsoUtils.xmlEscape(source)}</source>
460                                    </request-info>"""
461
462                         String falloutRequest = exceptionUtil.processMainflowsBPMNException(execution, requestInfo)
463                         execution.setVariable("falloutRequest", falloutRequest)
464                 } catch (Exception ex) {
465                         logger.info( "Exception prepareFalloutRequest:" + ex.getMessage())
466                         String errorException = "  Bpmn error encountered in UpdateCustomE2EServiceInstance flow. FalloutHandlerRequest,  buildErrorResponse() - " + ex.getMessage()
467                         String requestId = execution.getVariable("msoRequestId")
468                         String falloutRequest =
469                                         """<aetgt:FalloutHandlerRequest xmlns:aetgt="http://org.onap/so/workflow/schema/v1"
470                                                                      xmlns:ns="http://org.onap/so/request/types/v1"
471                                                                      xmlns:wfsch="http://org.onap/so/workflow/schema/v1">
472                                            <request-info xmlns="http://org.onap/so/infra/vnf-request/v1">
473                                               <request-id>${MsoUtils.xmlEscape(requestId)}</request-id>
474                                               <action>UPDATE</action>
475                                               <source>UUI</source>
476                                            </request-info>
477                                                 <aetgt:WorkflowException xmlns:aetgt="http://org.onap/so/workflow/schema/v1">
478                                                         <aetgt:ErrorMessage>${MsoUtils.xmlEscape(errorException)}</aetgt:ErrorMessage>
479                                                         <aetgt:ErrorCode>7000</aetgt:ErrorCode>
480                                                 </aetgt:WorkflowException>
481                                         </aetgt:FalloutHandlerRequest>"""
482
483                         execution.setVariable("falloutRequest", falloutRequest)
484                 }
485                 logger.info( "*** Exit prepareFalloutRequest ***")
486         }
487 }