2 * ============LICENSE_START=======================================================
\r
4 * ================================================================================
\r
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * ================================================================================
\r
7 * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * you may not use this file except in compliance with the License.
\r
9 * You may obtain a copy of the License at
\r
11 * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * Unless required by applicable law or agreed to in writing, software
\r
14 * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * See the License for the specific language governing permissions and
\r
17 * limitations under the License.
\r
18 * ============LICENSE_END=========================================================
\r
21 package org.openecomp.mso.bpmn.common.workflow.service;
\r
23 import java.util.HashMap;
\r
24 import java.util.Map;
\r
26 import javax.jws.WebMethod;
\r
27 import javax.jws.WebParam;
\r
28 import javax.jws.WebResult;
\r
29 import javax.jws.WebService;
\r
30 import javax.ws.rs.core.Context;
\r
31 import javax.xml.ws.WebServiceContext;
\r
33 import org.camunda.bpm.BpmPlatform;
\r
34 import org.camunda.bpm.engine.MismatchingMessageCorrelationException;
\r
35 import org.camunda.bpm.engine.ProcessEngineServices;
\r
36 import org.camunda.bpm.engine.RuntimeService;
\r
37 import org.camunda.bpm.engine.runtime.ExecutionQuery;
\r
38 import org.openecomp.mso.bpmn.common.adapter.sdnc.SDNCAdapterCallbackRequest;
\r
39 import org.openecomp.mso.bpmn.common.adapter.sdnc.SDNCAdapterResponse;
\r
40 import org.openecomp.mso.bpmn.common.adapter.sdnc.SDNCCallbackAdapterPortType;
\r
41 import org.openecomp.mso.bpmn.core.PropertyConfiguration;
\r
42 import org.openecomp.mso.logger.MessageEnum;
\r
43 import org.openecomp.mso.logger.MsoLogger;
\r
48 @WebService(serviceName="SDNCAdapterCallbackService", targetNamespace="http://org.openecomp/workflow/sdnc/adapter/schema/v1")
\r
49 public class SDNCAdapterCallbackServiceImpl implements SDNCCallbackAdapterPortType {
\r
51 private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL);
\r
52 private final int DEFAULT_RETRY_ATTEMPTS = 60;
\r
53 private final int DEFAULT_SLEEP_TIME = 500;
\r
55 private final String logMarker = "[SDNC-CALLBACK]";
\r
57 @Context WebServiceContext wsContext;
\r
59 private volatile ProcessEngineServices pes4junit = null;
\r
61 @WebMethod(operationName = "SDNCAdapterCallback")
\r
62 @WebResult(name = "SDNCAdapterResponse", targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/schema/v1", partName = "SDNCAdapterCallbackResponse")
\r
63 public SDNCAdapterResponse sdncAdapterCallback(
\r
64 @WebParam(name = "SDNCAdapterCallbackRequest", targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/schema/v1", partName = "SDNCAdapterCallbackRequest")
\r
65 SDNCAdapterCallbackRequest sdncAdapterCallbackRequest) {
\r
67 //Callback URL to use http://localhost:28080/mso/SDNCAdapterCallbackService
\r
68 ProcessEngineServices pes = getProcessEngineServices();
\r
69 RuntimeService runtimeService = pes.getRuntimeService();
\r
70 String receivedRequestId = sdncAdapterCallbackRequest.getCallbackHeader().getRequestId();
\r
71 MsoLogger.setServiceName("MSO." + "sdncAdapter");
\r
72 MsoLogger.setLogContext(receivedRequestId, "N/A");
\r
73 msoLogger.debug(logMarker + "Received callback response:" + sdncAdapterCallbackRequest.toString());
\r
74 SDNCAdapterResponse sdncAdapterResponse;
\r
75 long startTime = System.currentTimeMillis();
\r
77 /*Correlating the response with the running instance*/
\r
79 // NOTE: the following loop is a workaround for problems we've had
\r
80 // with reliability of the runtime service. It seems that queries
\r
81 // sometimes return results, and sometimes they don't. This might
\r
82 // be a problem in mysql only. We aren't sure if it affects camunda
\r
83 // on oracle or mariadb. The workaround is to repeat the request
\r
84 // a number of times until it succeeds. If it doesn't succeed after
\r
85 // 60 tries, then we give up.
\r
87 int maxAttempts = DEFAULT_RETRY_ATTEMPTS;
\r
89 int sleepTime = DEFAULT_SLEEP_TIME;
\r
91 Map<String,String> bpmnProperties = getMSOBPMNURNProperties();
\r
92 if (bpmnProperties != null) {
\r
94 maxAttempts = Integer.parseInt(bpmnProperties.get("mso.callbackRetryAttempts"));
\r
95 msoLogger.debug(logMarker + "mso.callbackRetryAttempts=" + maxAttempts);
\r
96 sleepTime = Integer.parseInt(bpmnProperties.get("mso.callbackRetrySleepTime"));
\r
97 msoLogger.debug(logMarker + "mso.callbackRetrySleepTime:" + sleepTime);
\r
98 } catch (Exception ex) {
\r
100 msoLogger.debug (logMarker
\r
101 + "Error parsing mso.callbackRetrySleepTime/mso.callbackRetryAttempts:"
\r
108 /* Check to make sure the process instance is reay for correlation*/
\r
110 isReadyforCorrelation(runtimeService, receivedRequestId, maxAttempts, sleepTime );
\r
111 }catch(Exception e){
\r
113 "SDNC Adapter Callback Service received a SDNC Adapter Callback Request with RequestId '"
\r
114 + receivedRequestId
\r
115 + "' but that RequestId doesn't exist or has timed out waiting for the callback";
\r
116 sdncAdapterResponse = new SDNCAdapterExceptionResponse(e);
\r
118 msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(),
\r
119 MsoLogger.ErrorCode.UnknownError, logMarker + ":" + msg, e);
\r
121 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, logMarker
\r
122 + "Completed the execution of MSO SDNCAdapterCallbackService." );
\r
124 msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
\r
125 logMarker + "Completed the execution of MSO SDNCAdapterCallbackService.", "BPMN",
\r
126 MsoLogger.getServiceName(), "sdncAdapterCallback");
\r
128 return sdncAdapterResponse;
\r
131 msoLogger.debug(logMarker + "*** Received MSO sdncAdapterCallbackService ******");
\r
133 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Call to MSO sdncAdapterCallbackService");
\r
135 msoLogger.debug(logMarker + "Callback response string:\n" + sdncAdapterCallbackRequest.toString());
\r
137 String reqId = receivedRequestId;
\r
138 Map<String,Object> variables = new HashMap<String,Object>();
\r
139 variables.put("SDNCA_requestId", reqId );
\r
140 variables.put("sdncAdapterCallbackRequest", sdncAdapterCallbackRequest.toString());
\r
143 // sdncAdapterCallbackRequest is the message event name (defined in the bpmn process)
\r
144 runtimeService.createMessageCorrelation("sdncAdapterCallbackRequest")
\r
145 .setVariables(variables)
\r
146 .processInstanceVariableEquals("SDNCA_requestId", reqId).correlate();
\r
147 sdncAdapterResponse = new SDNCAdapterResponse();
\r
148 msoLogger.debug(logMarker + "***** Completed processing of MSO sdncAdapterCallbackService ******");
\r
150 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, logMarker
\r
151 + "Completed the execution of MSO SDNCAdapterCallbackService.");
\r
153 msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
\r
154 logMarker + "Completed the execution of MSO SDNCAdapterCallbackService.", "BPMN",
\r
155 MsoLogger.getServiceName(), "sdncAdapterCallback");
\r
157 return sdncAdapterResponse;
\r
158 } catch(MismatchingMessageCorrelationException e) {
\r
159 msoLogger.debug(logMarker + "[CORM]correlation id mismatch (attempt " + attempt + "/" + maxAttempts + ")");
\r
160 if (attempt == maxAttempts) {
\r
161 // Couldn't correlate requestId to any active flow
\r
162 //MsoLogger logger = MsoLogger.getMsoLogger("SDNCAdapterCallbackService");
\r
164 "SDNC Adapter Callback Service received a SDNC Adapter Callback Request with RequestId '"
\r
165 + receivedRequestId
\r
166 + "' but that RequestId could not be correlated to any active process - ignoring the Request";
\r
167 sdncAdapterResponse = new SDNCAdapterExceptionResponse(e);
\r
169 msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(),
\r
170 MsoLogger.ErrorCode.UnknownError, logMarker + ":" + msg, e);
\r
172 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, logMarker
\r
173 + "Completed the execution of MSO SDNCAdapterCallbackService." );
\r
175 msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
\r
176 logMarker + "Completed the execution of MSO SDNCAdapterCallbackService.", "BPMN",
\r
177 MsoLogger.getServiceName(), "sdncAdapterCallback");
\r
179 return sdncAdapterResponse;
\r
183 Thread.sleep(sleepTime);
\r
184 } catch (InterruptedException e2) {
\r
186 "SDNC Adapter Callback Service received a SDNC Adapter Callback Request with RequestId '"
\r
187 + receivedRequestId
\r
188 + "' but correlation was interrupted";
\r
189 sdncAdapterResponse = new SDNCAdapterExceptionResponse(e);
\r
191 msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(),
\r
192 MsoLogger.ErrorCode.UnknownError, logMarker + ":" + msg, e);
\r
194 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, logMarker
\r
195 + "Completed the execution of MSO SDNCAdapterCallbackService.");
\r
197 msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
\r
198 logMarker + "Completed the execution of MSO SDNCAdapterCallbackService.", "BPMN",
\r
199 MsoLogger.getServiceName(), "sdncAdapterCallback");
\r
201 return sdncAdapterResponse;
\r
210 private Map<String,String> getMSOBPMNURNProperties() {
\r
211 PropertyConfiguration propertyConfiguration = PropertyConfiguration.getInstance();
\r
212 Map<String,String> props = propertyConfiguration.getProperties("mso.bpmn.urn.properties");
\r
216 private void isReadyforCorrelation(RuntimeService runtimeService,
\r
217 String receivedRequestId, int retries, int sleepTime){
\r
218 ExecutionQuery waitingInstances = null;
\r
219 long waitingInstancesCount = 0;
\r
221 //Workaround for performance testing, explicit wait for a second for the transactions to be committed
\r
222 //Also check to make sure the process didn't timeout before trying to correlate
\r
225 waitingInstances = runtimeService.createExecutionQuery() //
\r
226 .messageEventSubscriptionName("sdncAdapterCallbackRequest")
\r
227 .processVariableValueEquals("SDNCA_requestId", receivedRequestId);
\r
228 waitingInstancesCount = waitingInstances.count();
\r
230 msoLogger.debug(logMarker + "waitingInstancesCount: " + waitingInstancesCount);
\r
232 Thread.sleep(sleepTime);
\r
233 } catch (InterruptedException e) {
\r
235 msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(),
\r
236 MsoLogger.ErrorCode.UnknownError, logMarker, e);
\r
239 }while (waitingInstancesCount==0 && retries > 0);
\r
240 if(waitingInstancesCount > 0){
\r
241 msoLogger.debug(logMarker + "waitingInstancesCount before timeout check: " + waitingInstancesCount);
\r
242 waitingInstancesCount = waitingInstances.processVariableValueEquals("asynchronousResponseTimeout", false).count();
\r
243 msoLogger.debug(logMarker + "waitingInstancesCount after timeout check: " + waitingInstancesCount);
\r
244 if(waitingInstancesCount<=0){
\r
245 msoLogger.debug(logMarker + "detected timeout on flow to correlate");
\r
246 throw new IllegalStateException("process timed out");
\r
249 //flow may have already ended, so can't check timeout variable. Throw exception?
\r
250 msoLogger.debug(logMarker + "no flow to correlate to");
\r
251 throw new IllegalStateException("no flow to correlate to");
\r
255 private ProcessEngineServices getProcessEngineServices() {
\r
256 if (pes4junit == null) {
\r
257 return BpmPlatform.getDefaultProcessEngine();
\r
263 @WebMethod(exclude=true)
\r
264 public void setProcessEngineServices4junit(ProcessEngineServices pes) {
\r
268 public class SDNCAdapterExceptionResponse extends SDNCAdapterResponse {
\r
269 private Exception ex;
\r
271 public SDNCAdapterExceptionResponse(Exception ex) {
\r
276 public Exception getException() {
\r