Merge "Reorder modifiers"
[so.git] / bpmn / MSOCommonBPMN / src / main / java / org / openecomp / mso / bpmn / common / workflow / service / WorkflowResource.java
1 /*-\r
2  * ============LICENSE_START=======================================================\r
3  * ONAP - SO\r
4  * ================================================================================\r
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.\r
6  * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.\r
7  * ================================================================================\r
8  * Licensed under the Apache License, Version 2.0 (the "License");\r
9  * you may not use this file except in compliance with the License.\r
10  * You may obtain a copy of the License at\r
11  * \r
12  *      http://www.apache.org/licenses/LICENSE-2.0\r
13  * \r
14  * Unless required by applicable law or agreed to in writing, software\r
15  * distributed under the License is distributed on an "AS IS" BASIS,\r
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
17  * See the License for the specific language governing permissions and\r
18  * limitations under the License.\r
19  * ============LICENSE_END=========================================================\r
20  */\r
21 \r
22 package org.openecomp.mso.bpmn.common.workflow.service;\r
23 \r
24 import java.util.HashMap;\r
25 import java.util.List;\r
26 import java.util.Map;\r
27 import java.util.UUID;\r
28 import java.util.concurrent.atomic.AtomicLong;\r
29 \r
30 import javax.ws.rs.Consumes;\r
31 import javax.ws.rs.POST;\r
32 import javax.ws.rs.Path;\r
33 import javax.ws.rs.PathParam;\r
34 import javax.ws.rs.Produces;\r
35 import javax.ws.rs.core.Context;\r
36 import javax.ws.rs.core.Response;\r
37 import javax.ws.rs.core.UriInfo;\r
38 \r
39 import org.camunda.bpm.engine.HistoryService;\r
40 import org.camunda.bpm.engine.ProcessEngineException;\r
41 import org.camunda.bpm.engine.ProcessEngineServices;\r
42 import org.camunda.bpm.engine.RuntimeService;\r
43 import org.camunda.bpm.engine.history.HistoricVariableInstance;\r
44 import org.camunda.bpm.engine.runtime.ProcessInstance;\r
45 import org.camunda.bpm.engine.variable.VariableMap;\r
46 import org.camunda.bpm.engine.variable.Variables;\r
47 import org.camunda.bpm.engine.variable.Variables.SerializationDataFormats;\r
48 import org.camunda.bpm.engine.variable.impl.VariableMapImpl;\r
49 import org.openecomp.mso.bpmn.core.WorkflowException;\r
50 import org.openecomp.mso.logger.MessageEnum;\r
51 import org.openecomp.mso.logger.MsoLogger;\r
52 import org.slf4j.MDC;\r
53 \r
54 @Path("/workflow")\r
55 public class WorkflowResource extends ProcessEngineAwareService {\r
56         \r
57         private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL);\r
58         private static final String LOGMARKER = "[WRKFLOW-RESOURCE]";\r
59 \r
60         private static final int DEFAULT_WAIT_TIME = 30000;\r
61 \r
62         @Context\r
63         private UriInfo uriInfo = null;\r
64 \r
65         /**\r
66          * Starts the process instance and responds to client synchronously\r
67          * If the request does not contain mso-service-request-timeout then it waits for the value specified in DEFAULT_WAIT_TIME\r
68          * Note: value specified in mso-service-request-timeout is in seconds\r
69          * During polling time, if there is an exception encountered in the process execution then polling is stopped and the error response is \r
70          * returned to the client\r
71          * @param processKey\r
72          * @param variableMap\r
73          * @return\r
74          */\r
75         @POST\r
76         @Path("/services/{processKey}")\r
77         @Produces("application/json")\r
78         @Consumes("application/json")\r
79         public Response startProcessInstanceByKey(@PathParam("processKey") String processKey,\r
80                         VariableMapImpl variableMap) {\r
81 \r
82                 Map<String, Object> inputVariables = getInputVariables(variableMap);    \r
83                 setLogContext(processKey, inputVariables);\r
84 \r
85                 WorkflowResponse workflowResponse = new WorkflowResponse();\r
86                 long startTime = System.currentTimeMillis();\r
87                 ProcessInstance processInstance = null;\r
88 \r
89                 try {\r
90                         //Kickoff the process\r
91                         ProcessThread thread = new ProcessThread(inputVariables,processKey,msoLogger);\r
92                         thread.start();\r
93 \r
94                         Map<String, Object> responseMap = null;\r
95 \r
96                         //wait for process to be completed\r
97                         long waitTime = getWaitTime(inputVariables);\r
98                         long now = System.currentTimeMillis();\r
99                         long start = now;\r
100                         long endTime = start + waitTime;\r
101                         long pollingInterval = 500;\r
102 \r
103                         // TEMPORARY LOGIC FOR UNIT TEST REFACTORING\r
104                         // If this is a unit test (method is invoked directly), wait a max\r
105                         // of 5 seconds after process ended for a result.  In production,\r
106                         // wait up to 60 seconds.\r
107                         long timeToWaitAfterProcessEnded = uriInfo == null ? 5000 : 60000;\r
108                         AtomicLong timeProcessEnded = new AtomicLong(0);\r
109                         boolean endedWithNoResponse = false;\r
110 \r
111                         while (now <= endTime) {\r
112                                 Thread.sleep(pollingInterval);\r
113 \r
114                                 now = System.currentTimeMillis();\r
115 \r
116                                 // Increase the polling interval over time\r
117 \r
118                                 long elapsed = now - start;\r
119 \r
120                                 if (elapsed > 60000) {\r
121                                         pollingInterval = 5000;\r
122                                 } else if (elapsed > 10000) {\r
123                                         pollingInterval = 1000;\r
124                                 }\r
125                                 Exception exception = thread.getException();\r
126                                 if (exception != null) {\r
127                                         throw new Exception(exception);\r
128                                 }\r
129 \r
130                                 processInstance = thread.getProcessInstance();\r
131 \r
132                                 if (processInstance == null) {\r
133                                         msoLogger.debug(LOGMARKER + processKey + " process has not been created yet");\r
134                                         continue;\r
135                                 }\r
136 \r
137                                 String processInstanceId = processInstance.getId();\r
138                                 workflowResponse.setProcessInstanceId(processInstanceId);                               \r
139 \r
140                                 responseMap = getResponseMap(processInstance, processKey, timeProcessEnded);\r
141 \r
142                                 if (responseMap == null) {\r
143                                         msoLogger.debug(LOGMARKER + processKey + " has not produced a response yet");\r
144 \r
145                                         if (timeProcessEnded.longValue() != 0) {\r
146                                                 long elapsedSinceEnded = System.currentTimeMillis() - timeProcessEnded.longValue();\r
147 \r
148                                                 if (elapsedSinceEnded > timeToWaitAfterProcessEnded) {\r
149                                                         endedWithNoResponse = true;\r
150                                                         break;\r
151                                                 }\r
152                                         }\r
153                                 } else {\r
154                                         processResponseMap(workflowResponse, responseMap);\r
155                                         recordEvents(processKey, workflowResponse, startTime);\r
156                                         return Response.status(workflowResponse.getMessageCode()).entity(workflowResponse).build();\r
157                                 }\r
158                         }\r
159 \r
160                         //if we dont get response after waiting then send timeout response\r
161 \r
162                         String state;\r
163                         String processInstanceId;\r
164 \r
165                         if (processInstance == null) {\r
166                                 processInstanceId = "N/A";\r
167                                 state = "NOT STARTED";\r
168                         } else {\r
169                                 processInstanceId = processInstance.getProcessInstanceId();\r
170                                 state = isProcessEnded(processInstanceId) ? "ENDED" : "NOT ENDED";\r
171                         }\r
172 \r
173                         workflowResponse.setMessage("Fail");\r
174                         if (endedWithNoResponse) {\r
175                                 workflowResponse.setContent("Process ended without producing a response");\r
176                         } else {\r
177                                 workflowResponse.setContent("Request timed out, process state: " + state);\r
178                         }\r
179                         workflowResponse.setProcessInstanceId(processInstanceId);\r
180                         recordEvents(processKey, workflowResponse, startTime);\r
181                         workflowResponse.setMessageCode(500);\r
182                         return Response.status(500).entity(workflowResponse).build();\r
183                 } catch (Exception ex) {\r
184                         msoLogger.debug(LOGMARKER + "Exception in startProcessInstance by key",ex);\r
185                         workflowResponse.setMessage("Fail" );\r
186                         workflowResponse.setContent("Error occurred while executing the process: " + ex.getMessage());\r
187                         if (processInstance != null) workflowResponse.setProcessInstanceId(processInstance.getId());\r
188                         \r
189                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG,  "BPMN", MDC.get(processKey), \r
190                                         MsoLogger.ErrorCode.UnknownError, LOGMARKER + workflowResponse.getMessage()\r
191                                         + " for processKey: " + processKey + " with content: " + workflowResponse.getContent());\r
192                         \r
193                         workflowResponse.setMessageCode(500);\r
194                         recordEvents(processKey, workflowResponse, startTime);\r
195                         return Response.status(500).entity(workflowResponse).build();\r
196                 }\r
197         }\r
198 \r
199         /**\r
200          * Returns the wait time, this is used by the resource on how long it should wait to send a response\r
201          * If none specified DEFAULT_WAIT_TIME is used\r
202          * @param inputVariables\r
203          * @return\r
204          */\r
205         private int getWaitTime(Map<String, Object> inputVariables)\r
206         {\r
207                 String timeout = inputVariables.get("mso-service-request-timeout") == null\r
208                         ? null : inputVariables.get("mso-service-request-timeout").toString();          \r
209 \r
210                 if (timeout != null) {\r
211                         try {\r
212                                 return Integer.parseInt(timeout)*1000;\r
213                         } catch (NumberFormatException nex) {\r
214                                 msoLogger.debug("Invalid input for mso-service-request-timeout");\r
215                         }\r
216                 }\r
217                 return DEFAULT_WAIT_TIME;\r
218         }\r
219         \r
220         private void recordEvents(String processKey, WorkflowResponse response, long startTime) {\r
221                 \r
222                 msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, \r
223                                 LOGMARKER + response.getMessage() + " for processKey: "\r
224                                 + processKey + " with content: " + response.getContent(), "BPMN", MDC.get(processKey), null);\r
225                 \r
226                 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, \r
227                                 LOGMARKER + response.getMessage() + " for processKey: "\r
228                                 + processKey + " with content: " + response.getContent());\r
229         }\r
230 \r
231         private void setLogContext(String processKey, Map<String, Object> inputVariables) {\r
232                 MsoLogger.setServiceName("MSO." + processKey);\r
233                 if (inputVariables != null) {\r
234                         MsoLogger.setLogContext(getValueFromInputVariables(inputVariables, "mso-request-id"),\r
235                                 getValueFromInputVariables(inputVariables, "mso-service-instance-id"));\r
236                 }\r
237         }\r
238 \r
239         private String getValueFromInputVariables(Map<String,Object> inputVariables, String key) {\r
240                 Object value = inputVariables.get(key);\r
241                 if (value == null) {\r
242                         return "N/A";\r
243                 } else {\r
244                         return value.toString();\r
245                 }\r
246         }\r
247         \r
248         /**\r
249          * Checks to see if the specified process is ended.\r
250          * @param processInstanceId the process instance ID\r
251          * @return true if the process is ended\r
252          */\r
253         private boolean isProcessEnded(String processInstanceId) {\r
254                 ProcessEngineServices pes = getProcessEngineServices();\r
255                 try {\r
256                         return pes.getRuntimeService().createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult() == null ? true : false ;\r
257                 } catch (Exception e) {\r
258                         msoLogger.debug("Exception :",e);\r
259                         return true;\r
260                 }        \r
261         }\r
262 \r
263         private void processResponseMap(WorkflowResponse workflowResponse, Map<String, Object> responseMap) {\r
264                 Object object = responseMap.get("Response");\r
265                 String content = object == null ? null : String.valueOf(object);\r
266                 if (content == null){\r
267                         object = responseMap.get("WorkflowResponse");\r
268                         content = object == null ? null : String.valueOf(object);\r
269                 }\r
270 \r
271                 workflowResponse.setContent(content); \r
272 \r
273                 object = responseMap.get("ResponseCode");\r
274                 String responseCode = object == null ? null : String.valueOf(object);\r
275 \r
276                 try {\r
277                         workflowResponse.setMessageCode(Integer.parseInt(responseCode));\r
278                 } catch(NumberFormatException nex) {\r
279                         msoLogger.debug(LOGMARKER + "Failed to parse ResponseCode: " + responseCode);\r
280                         workflowResponse.setMessageCode(-1);\r
281                 }\r
282 \r
283                 Object status = responseMap.get("Status");\r
284 \r
285                 if ("Success".equalsIgnoreCase(String.valueOf(status))) {\r
286                         workflowResponse.setMessage("Success");\r
287                 } else if ("Fail".equalsIgnoreCase(String.valueOf(status))) {\r
288                         workflowResponse.setMessage("Fail");\r
289                 } else {\r
290                         msoLogger.debug(LOGMARKER + "Unrecognized Status: " + responseCode);\r
291                         workflowResponse.setMessage("Fail");\r
292                 }\r
293         }\r
294 \r
295         /**\r
296          * @version 1.0\r
297          * Triggers the workflow in a separate thread\r
298          */\r
299         private class ProcessThread extends Thread {\r
300                 private final Map<String,Object> inputVariables;\r
301                 private final String processKey;\r
302                 private final MsoLogger msoLogger;\r
303                 private final String businessKey;\r
304                 private ProcessInstance processInstance = null;\r
305                 private Exception exception = null;\r
306 \r
307                 public ProcessThread(Map<String, Object> inputVariables, String processKey, MsoLogger msoLogger) {\r
308                         this.inputVariables = inputVariables;\r
309                         this.processKey = processKey;\r
310                         this.msoLogger = msoLogger;\r
311                         this.businessKey = UUID.randomUUID().toString();\r
312                 }\r
313 \r
314                 /**\r
315                  * If an exception occurs when starting the process instance, it may\r
316                  * be obtained by calling this method.  Note that exceptions are only\r
317                  * recorded while the process is executing in its original thread.\r
318                  * Once a process is suspended, exception recording stops.\r
319                  * @return the exception, or null if none has occurred\r
320                  */\r
321                 public Exception getException() {\r
322                         return exception;\r
323                 }\r
324 \r
325                 \r
326                 public ProcessInstance getProcessInstance() {\r
327                         return this.processInstance;\r
328                 }\r
329                 \r
330                 /**\r
331                  * Sets the process instance exception.\r
332                  * @param exception the exception\r
333                  */\r
334                 private void setException(Exception exception) {\r
335                         this.exception = exception;\r
336                 }\r
337 \r
338                 public void run() {\r
339                         setLogContext(processKey, inputVariables);\r
340 \r
341                         long startTime = System.currentTimeMillis();\r
342                         \r
343                         try {\r
344                                 msoLogger.debug(LOGMARKER + "***Received MSO startProcessInstanceByKey with processKey:"\r
345                                         + processKey + " and variables: " + inputVariables);\r
346                                 \r
347                                 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, LOGMARKER\r
348                                                 + "Call to MSO workflow/services in Camunda. Received MSO startProcessInstanceByKey with"\r
349                                                 + " processKey:" + processKey\r
350                                                 + " businessKey:" + businessKey\r
351                                                 + " variables: " + inputVariables);\r
352                                                 \r
353                                 RuntimeService runtimeService = getProcessEngineServices().getRuntimeService();\r
354 \r
355                                 // Note that this method doesn't return until the process suspends\r
356                                 // itself or finishes.  We provide a business key so we can identify\r
357                                 // the process instance immediately.\r
358                                 processInstance = runtimeService.startProcessInstanceByKey(\r
359                                         processKey, inputVariables);\r
360 \r
361                         } catch (Exception e) {\r
362                                 msoLogger.debug(LOGMARKER + "ProcessThread caught an exception executing "\r
363                                         + processKey + ": " + e);\r
364                                 setException(e);\r
365                         }\r
366                 }\r
367 \r
368         }\r
369 \r
370         private Map<String, Object> getInputVariables(VariableMapImpl variableMap) {\r
371                 VariableMap inputVariables = Variables.createVariables();\r
372                 @SuppressWarnings("unchecked")\r
373                 Map<String, Object> vMap = (Map<String, Object>) variableMap.get("variables");\r
374                 for (String key : vMap.keySet()) { //variabe name vn\r
375                         @SuppressWarnings("unchecked")\r
376                         Map<String, Object> valueMap = (Map<String,Object>)vMap.get(key); //value, type\r
377                         inputVariables.putValueTyped(key, Variables\r
378                         .objectValue(valueMap.get("value"))\r
379                         .serializationDataFormat(SerializationDataFormats.JAVA) // tells the engine to use java serialization for persisting the value\r
380                         .create());\r
381                 }\r
382                 return inputVariables;\r
383         }\r
384 \r
385         /**\r
386          * Attempts to get a response map from the specified process instance.\r
387          * @return the response map, or null if it is unavailable\r
388          */\r
389         private Map<String, Object> getResponseMap(ProcessInstance processInstance,\r
390                         String processKey, AtomicLong timeProcessEnded) {\r
391 \r
392                 String responseMapVariable = processKey + "ResponseMap";\r
393                 String processInstanceId = processInstance.getId();\r
394 \r
395                 // Query the runtime service to see if a response map is ready.\r
396 \r
397 /*              RuntimeService runtimeService = getProcessEngineServices().getRuntimeService();\r
398                 List<Execution> executions = runtimeService.createExecutionQuery()\r
399                         .processInstanceId(processInstanceId).list();\r
400 \r
401                 for (Execution execution : executions) {\r
402                         @SuppressWarnings("unchecked")\r
403                         Map<String, Object> responseMap = (Map<String, Object>)\r
404                                 getVariableFromExecution(runtimeService, execution.getId(),\r
405                                         responseMapVariable);\r
406 \r
407                         if (responseMap != null) {\r
408                                 msoLogger.debug(LOGMARKER + "Obtained " + responseMapVariable\r
409                                         + " from process " + processInstanceId + " execution "\r
410                                         + execution.getId());\r
411                                 return responseMap;\r
412                         }\r
413                 }\r
414 */\r
415                 //Querying history seem to return consistent results compared to querying the runtime service\r
416 \r
417                 boolean alreadyEnded = timeProcessEnded.longValue() != 0;\r
418 \r
419                 if (alreadyEnded || isProcessEnded(processInstance.getId())) {\r
420                         if (!alreadyEnded) {\r
421                                 timeProcessEnded.set(System.currentTimeMillis());\r
422                         }\r
423 \r
424                         // Query the history service to see if a response map exists.\r
425 \r
426                         HistoryService historyService = getProcessEngineServices().getHistoryService();\r
427                         @SuppressWarnings("unchecked")\r
428                         Map<String, Object> responseMap = (Map<String, Object>)\r
429                                 getVariableFromHistory(historyService, processInstance.getId(),\r
430                                         responseMapVariable);\r
431 \r
432                         if (responseMap != null) {\r
433                                 msoLogger.debug(LOGMARKER + "Obtained " + responseMapVariable\r
434                                         + " from process " + processInstanceId + " history");\r
435                                 return responseMap;\r
436                         }\r
437 \r
438                         // Query the history service for old-style response variables.\r
439 \r
440                         String prefix = (String) getVariableFromHistory(historyService, processInstanceId, "prefix");\r
441 \r
442                         if (prefix != null) {\r
443                                 \r
444                                 // Check for 'WorkflowResponse' variable\r
445                                 Object workflowResponseObject = getVariableFromHistory(historyService, processInstanceId, "WorkflowResponse");\r
446                                 String workflowResponse = workflowResponseObject == null ? null : String.valueOf(workflowResponseObject);\r
447                                 msoLogger.debug(LOGMARKER + "WorkflowResponse: " + workflowResponse);\r
448                                 \r
449                                 if (workflowResponse != null) {\r
450                                         Object responseCodeObject = getVariableFromHistory(historyService, processInstanceId, prefix + "ResponseCode");\r
451                                         String responseCode = responseCodeObject == null ? null : String.valueOf(responseCodeObject);\r
452                                         msoLogger.debug(LOGMARKER + prefix + "ResponseCode: " + responseCode);\r
453                                         responseMap = new HashMap<>();\r
454                                         responseMap.put("WorkflowResponse", workflowResponse);\r
455                                         responseMap.put("ResponseCode", responseCode);\r
456                                         responseMap.put("Status", "Success");\r
457                                         return responseMap;\r
458                                 }\r
459                                 \r
460                                 \r
461                                 // Check for 'WorkflowException' variable\r
462                                 WorkflowException workflowException = null;\r
463                                 String workflowExceptionText = null;\r
464 \r
465                                 Object workflowExceptionObject = getVariableFromHistory(historyService, processInstanceId, "WorkflowException");\r
466                                 if(workflowExceptionObject != null) {\r
467                                         if(workflowExceptionObject instanceof WorkflowException) {\r
468                                                 workflowException = (WorkflowException) workflowExceptionObject;\r
469                                                 workflowExceptionText = workflowException.toString();\r
470                                                 responseMap = new HashMap<>();\r
471                                                 responseMap.put("WorkflowException", workflowExceptionText);\r
472                                                 responseMap.put("ResponseCode", workflowException.getErrorCode());\r
473                                                 responseMap.put("Status", "Fail");\r
474                                                 return responseMap;\r
475                                         }\r
476                                         else if (workflowExceptionObject instanceof String) {\r
477                                                 Object object = getVariableFromHistory(historyService, processInstanceId, prefix + "ResponseCode");\r
478                                                 String responseCode = object == null ? null : String.valueOf(object);\r
479                                                 workflowExceptionText = (String) workflowExceptionObject;\r
480                                                 responseMap = new HashMap<>();\r
481                                                 responseMap.put("WorkflowException", workflowExceptionText);\r
482                                                 responseMap.put("ResponseCode", responseCode);\r
483                                                 responseMap.put("Status", "Fail");\r
484                                                 return responseMap;\r
485                                         }\r
486                                         \r
487                                 }\r
488                                 msoLogger.debug(LOGMARKER + "WorkflowException: " + workflowExceptionText);\r
489                                 \r
490                                 // BEGIN LEGACY SUPPORT.  TODO: REMOVE THIS CODE\r
491                                 Object object = getVariableFromHistory(historyService, processInstanceId, processKey + "Response");\r
492                                 String response = object == null ? null : String.valueOf(object);\r
493                                 msoLogger.debug(LOGMARKER + processKey + "Response: " + response);\r
494 \r
495                                 if (response != null) {\r
496                                         object = getVariableFromHistory(historyService, processInstanceId, prefix + "ResponseCode");\r
497                                         String responseCode = object == null ? null : String.valueOf(object);\r
498                                         msoLogger.debug(LOGMARKER + prefix + "ResponseCode: " + responseCode);\r
499                                         responseMap = new HashMap<>();\r
500                                         responseMap.put("Response", response);\r
501                                         responseMap.put("ResponseCode", responseCode);\r
502                                         responseMap.put("Status", "Success");\r
503                                         return responseMap;\r
504                                 }\r
505         \r
506                                 object = getVariableFromHistory(historyService, processInstanceId, prefix + "ErrorResponse");\r
507                                 String errorResponse = object == null ? null : String.valueOf(object);\r
508                                 msoLogger.debug(LOGMARKER + prefix + "ErrorResponse: " + errorResponse);\r
509 \r
510                                 if (errorResponse != null) {\r
511                                         object = getVariableFromHistory(historyService, processInstanceId, prefix + "ResponseCode");\r
512                                         String responseCode = object == null ? null : String.valueOf(object);\r
513                                         msoLogger.debug(LOGMARKER + prefix + "ResponseCode: " + responseCode);\r
514                                         responseMap = new HashMap<>();\r
515                                         responseMap.put("Response", errorResponse);\r
516                                         responseMap.put("ResponseCode", responseCode);\r
517                                         responseMap.put("Status", "Fail");\r
518                                         return responseMap;\r
519                                 }\r
520                                 // END LEGACY SUPPORT.  TODO: REMOVE THIS CODE\r
521                         }\r
522                 }\r
523                 return null;\r
524         }\r
525         \r
526         /**\r
527          * Gets a variable value from the specified execution.\r
528          * @return the variable value, or null if the variable could not be\r
529          * obtained\r
530          */\r
531         private Object getVariableFromExecution(RuntimeService runtimeService,\r
532                         String executionId, String variableName) {\r
533                 try {\r
534                         return runtimeService.getVariable(executionId, variableName);\r
535                 } catch (ProcessEngineException e) {\r
536                         // Most likely cause is that the execution no longer exists.\r
537                         msoLogger.debug("Error retrieving execution " + executionId\r
538                                 + " variable " + variableName + ": " + e);\r
539                         return null;\r
540                 }\r
541         }\r
542         /**\r
543          * Gets a variable value from specified historical process instance.\r
544          * @return the variable value, or null if the variable could not be\r
545          * obtained\r
546          */\r
547         private Object getVariableFromHistory(HistoryService historyService,\r
548                         String processInstanceId, String variableName) {\r
549                 try {\r
550                         HistoricVariableInstance v = historyService.createHistoricVariableInstanceQuery()\r
551                                 .processInstanceId(processInstanceId).variableName(variableName).singleResult();\r
552                         return v == null ? null : v.getValue();\r
553                 } catch (Exception e) {\r
554                         msoLogger.debug("Error retrieving process " + processInstanceId\r
555                                 + " variable " + variableName + " from history: " + e);\r
556                         return null;\r
557                 }\r
558         }\r
559         \r
560         @POST\r
561         @Path("/services/{processKey}/{processInstanceId}")\r
562         @Produces("application/json")\r
563         @Consumes("application/json")\r
564         public WorkflowResponse getProcessVariables(@PathParam("processKey") String processKey, @PathParam("processInstanceId") String processInstanceId) {\r
565                 //TODO filter only set of variables\r
566                 WorkflowResponse response = new WorkflowResponse();\r
567 \r
568                 long startTime = System.currentTimeMillis();\r
569                 try {\r
570                         ProcessEngineServices engine = getProcessEngineServices();\r
571                         List<HistoricVariableInstance> variables = engine.getHistoryService().createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();\r
572                         Map<String,String> variablesMap = new HashMap<>();\r
573                         for (HistoricVariableInstance variableInstance: variables) {\r
574                                 variablesMap.put(variableInstance.getName(), variableInstance.getValue().toString());\r
575                         }\r
576 \r
577                         msoLogger.debug(LOGMARKER + "***Received MSO getProcessVariables with processKey:" + processKey + " and variables: " + variablesMap.toString());\r
578                         \r
579                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, LOGMARKER \r
580                                         + "Call to MSO workflow/services in Camunda. Received MSO getProcessVariables with processKey:" \r
581                                         + processKey + " and variables: " \r
582                                         + variablesMap.toString());\r
583                         \r
584                         \r
585                         response.setVariables(variablesMap);\r
586                         response.setMessage("Success");\r
587                         response.setContent("Successfully retrieved the variables"); \r
588                         response.setProcessInstanceId(processInstanceId);\r
589 \r
590                         msoLogger.debug(LOGMARKER + response.getMessage() + " for processKey: " + processKey + " with content: " + response.getContent());\r
591                 } catch (Exception ex) {\r
592                         response.setMessage("Fail");\r
593                         response.setContent("Failed to retrieve the variables," + ex.getMessage()); \r
594                         response.setProcessInstanceId(processInstanceId);\r
595                         \r
596                         msoLogger.error (MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, "BPMN", MDC.get(processKey), MsoLogger.ErrorCode.UnknownError, LOGMARKER \r
597                                         + response.getMessage() \r
598                                         + " for processKey: " \r
599                                         + processKey \r
600                                         + " with content: " \r
601                                         + response.getContent());\r
602                         msoLogger.debug("Exception :",ex);\r
603                 }\r
604                 \r
605                 msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, \r
606                                 LOGMARKER + response.getMessage() + " for processKey: "\r
607                                 + processKey + " with content: " + response.getContent(), "BPMN", MDC.get(processKey), null);\r
608                 \r
609                 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, \r
610                                 LOGMARKER + response.getMessage() + " for processKey: "\r
611                                 + processKey + " with content: " + response.getContent());\r
612                 \r
613                 return response;\r
614         }\r
615 }\r