2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.mso.bpmn.common.workflow.service;
23 import java.util.HashMap;
26 import javax.jws.WebMethod;
27 import javax.jws.WebParam;
28 import javax.jws.WebResult;
29 import javax.jws.WebService;
30 import javax.ws.rs.core.Context;
31 import javax.xml.ws.WebServiceContext;
33 import org.camunda.bpm.BpmPlatform;
34 import org.camunda.bpm.engine.MismatchingMessageCorrelationException;
35 import org.camunda.bpm.engine.ProcessEngineServices;
36 import org.camunda.bpm.engine.RuntimeService;
37 import org.openecomp.mso.bpmn.common.adapter.sdnc.SDNCAdapterCallbackRequest;
38 import org.openecomp.mso.bpmn.common.adapter.sdnc.SDNCAdapterResponse;
39 import org.openecomp.mso.bpmn.common.adapter.sdnc.SDNCCallbackAdapterPortType;
40 import org.openecomp.mso.bpmn.core.PropertyConfiguration;
41 import org.openecomp.mso.logger.MessageEnum;
42 import org.openecomp.mso.logger.MsoLogger;
47 @WebService(serviceName="SDNCAdapterCallbackService", targetNamespace="http://org.openecomp/workflow/sdnc/adapter/schema/v1")
48 public class SDNCAdapterCallbackServiceImpl implements SDNCCallbackAdapterPortType {
50 private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL);
51 private final int DEFAULT_RETRY_ATTEMPTS = 60;
52 private final int DEFAULT_SLEEP_TIME = 500;
54 private final String logMarker = "[SDNC-CALLBACK]";
56 @Context WebServiceContext wsContext;
58 private volatile ProcessEngineServices pes4junit = null;
60 @WebMethod(operationName = "SDNCAdapterCallback")
61 @WebResult(name = "SDNCAdapterResponse", targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/schema/v1", partName = "SDNCAdapterCallbackResponse")
62 public SDNCAdapterResponse sdncAdapterCallback(
63 @WebParam(name = "SDNCAdapterCallbackRequest", targetNamespace = "http://org.openecomp/workflow/sdnc/adapter/schema/v1", partName = "SDNCAdapterCallbackRequest")
64 SDNCAdapterCallbackRequest sdncAdapterCallbackRequest) {
66 //Callback URL to use http://localhost:28080/mso/SDNCAdapterCallbackService
67 ProcessEngineServices pes = getProcessEngineServices();
68 RuntimeService runtimeService = pes.getRuntimeService();
69 String receivedRequestId = sdncAdapterCallbackRequest.getCallbackHeader().getRequestId();
70 MsoLogger.setServiceName("MSO." + "sdncAdapter");
71 MsoLogger.setLogContext(receivedRequestId, "N/A");
72 msoLogger.debug(logMarker + "Received callback response:" + sdncAdapterCallbackRequest.toString());
73 SDNCAdapterResponse sdncAdapterResponse;
74 long startTime = System.currentTimeMillis();
76 /* Check to make sure the process instance is reay for correlation*/
77 isReadyforCorrelation(runtimeService, receivedRequestId);
79 msoLogger.debug(logMarker + "*** Received MSO sdncAdapterCallbackService ******");
81 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Call to MSO sdncAdapterCallbackService");
83 msoLogger.debug(logMarker + "Callback response string:\n" + sdncAdapterCallbackRequest.toString());
85 String reqId = receivedRequestId;
86 Map<String,Object> variables = new HashMap<String,Object>();
87 variables.put("SDNCA_requestId", reqId );
88 variables.put("sdncAdapterCallbackRequest", sdncAdapterCallbackRequest.toString());
90 /*Correlating the response with the running instance*/
92 // NOTE: the following loop is a workaround for problems we've had
93 // with reliability of the runtime service. It seems that queries
94 // sometimes return results, and sometimes they don't. This might
95 // be a problem in mysql only. We aren't sure if it affects camunda
96 // on oracle or mariadb. The workaround is to repeat the request
97 // a number of times until it succeeds. If it doesn't succeed after
98 // 60 tries, then we give up.
100 int maxAttempts = DEFAULT_RETRY_ATTEMPTS;
102 int sleepTime = DEFAULT_SLEEP_TIME;
104 Map<String,String> bpmnProperties = getMSOBPMNURNProperties();
105 if (bpmnProperties != null) {
107 maxAttempts = Integer.parseInt(bpmnProperties.get("mso.callbackRetryAttempts"));
108 msoLogger.debug(logMarker + "mso.callbackRetryAttempts=" + maxAttempts);
109 sleepTime = Integer.parseInt(bpmnProperties.get("mso.callbackRetrySleepTime"));
110 msoLogger.debug(logMarker + "mso.callbackRetrySleepTime:" + sleepTime);
111 } catch (Exception ex) {
113 msoLogger.info (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", logMarker
114 + "Error parsing mso.callbackRetrySleepTime/mso.callbackRetryAttempts:"
118 msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, logMarker
119 + "Error parsing mso.callbackRetrySleepTime/mso.callbackRetryAttempts:"
128 // sdncAdapterCallbackRequest is the message event name (defined in the bpmn process)
129 runtimeService.createMessageCorrelation("sdncAdapterCallbackRequest")
130 .setVariables(variables)
131 .processInstanceVariableEquals("SDNCA_requestId", reqId).correlate();
132 sdncAdapterResponse = new SDNCAdapterResponse();
133 msoLogger.debug(logMarker + "***** Completed processing of MSO sdncAdapterCallbackService ******");
135 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, logMarker
136 + "Completed the execution of MSO SDNCAdapterCallbackService.");
138 msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
139 logMarker + "Completed the execution of MSO SDNCAdapterCallbackService.", "BPMN",
140 MsoLogger.getServiceName(), "sdncAdapterCallback");
142 return sdncAdapterResponse;
143 } catch(MismatchingMessageCorrelationException e) {
144 msoLogger.debug(logMarker + "[CORM]correlation id mismatch (attempt " + attempt + "/" + maxAttempts + ")");
145 if (attempt == maxAttempts) {
146 // Couldn't correlate requestId to any active flow
147 //MsoLogger logger = MsoLogger.getMsoLogger("SDNCAdapterCallbackService");
149 "SDNC Adapter Callback Service received a SDNC Adapter Callback Request with RequestId '"
151 + "' but that RequestId could not be correlated to any active process - ignoring the Request";
152 sdncAdapterResponse = new SDNCAdapterExceptionResponse(e);
154 msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(),
155 MsoLogger.ErrorCode.UnknownError, logMarker + ":" + msg, e);
157 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, logMarker
158 + "Completed the execution of MSO SDNCAdapterCallbackService." );
160 msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
161 logMarker + "Completed the execution of MSO SDNCAdapterCallbackService.", "BPMN",
162 MsoLogger.getServiceName(), "sdncAdapterCallback");
164 return sdncAdapterResponse;
168 Thread.sleep(sleepTime);
169 } catch (InterruptedException e2) {
171 "SDNC Adapter Callback Service received a SDNC Adapter Callback Request with RequestId '"
173 + "' but correlation was interrupted";
174 sdncAdapterResponse = new SDNCAdapterExceptionResponse(e);
176 msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(),
177 MsoLogger.ErrorCode.UnknownError, logMarker + ":" + msg, e);
179 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, logMarker
180 + "Completed the execution of MSO SDNCAdapterCallbackService.");
182 msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
183 logMarker + "Completed the execution of MSO SDNCAdapterCallbackService.", "BPMN",
184 MsoLogger.getServiceName(), "sdncAdapterCallback");
186 return sdncAdapterResponse;
195 private Map<String,String> getMSOBPMNURNProperties() {
196 PropertyConfiguration propertyConfiguration = PropertyConfiguration.getInstance();
197 Map<String,String> props = propertyConfiguration.getProperties("mso.bpmn.urn.properties");
201 private void isReadyforCorrelation(RuntimeService runtimeService,
202 String receivedRequestId) {
203 long waitingInstances = runtimeService.createExecutionQuery() //
204 .messageEventSubscriptionName("sdncAdapterCallbackRequest")
205 .processVariableValueEquals("SDNCA_requestId", receivedRequestId).count();
206 //Workaround for performance testing, explicit wait for a second for the transactions to be committed
209 } catch (InterruptedException e1) {
213 while (waitingInstances==0 && retries > 0) {
216 } catch (InterruptedException e) {
218 msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(),
219 MsoLogger.ErrorCode.UnknownError, logMarker, e);
221 } // you can still play with the numbers
222 waitingInstances = runtimeService.createExecutionQuery() //
223 .messageEventSubscriptionName("sdncAdapterCallbackRequest")
224 .processVariableValueEquals("SDNCA_requestId", receivedRequestId).count();
229 private ProcessEngineServices getProcessEngineServices() {
230 if (pes4junit == null) {
231 return BpmPlatform.getDefaultProcessEngine();
237 @WebMethod(exclude=true)
238 public void setProcessEngineServices4junit(ProcessEngineServices pes) {
242 public class SDNCAdapterExceptionResponse extends SDNCAdapterResponse {
243 private Exception ex;
245 public SDNCAdapterExceptionResponse(Exception ex) {
250 public Exception getException() {