Initial OpenECOMP MSO commit
[so.git] / bpmn / MSOGammaBPMN / src / main / java / org / openecomp / mso / bpmn / gamma / workflow / service / SDNCAdapterCallbackServiceImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * OPENECOMP - MSO
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.mso.bpmn.gamma.workflow.service;
22
23 import java.util.HashMap;
24 import java.util.Map;
25
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;
32
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
38 import com.att.domain2.workflow.sdnc.adapter.callback.wsdl.v1.SDNCCallbackAdapterPortType;
39 import com.att.domain2.workflow.sdnc.adapter.schema.v1.SDNCAdapterCallbackRequest;
40 import com.att.domain2.workflow.sdnc.adapter.schema.v1.SDNCAdapterResponse;
41 import org.openecomp.mso.bpmn.core.PropertyConfiguration;
42 import org.openecomp.mso.logger.MessageEnum;
43 import org.openecomp.mso.logger.MsoLogger;
44 /**
45  * @version 1.0
46  *  
47  */
48 @WebService(serviceName="SDNCAdapterCallbackService", targetNamespace="http://domain2.att.com/workflow/sdnc/adapter/schema/v1")
49 public class SDNCAdapterCallbackServiceImpl implements SDNCCallbackAdapterPortType {
50
51         private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL);
52         private final int DEFAULT_RETRY_ATTEMPTS = 60;
53         private final int DEFAULT_SLEEP_TIME = 500;
54
55         private final String logMarker = "[SDNC-CALLBACK]";
56
57         @Context WebServiceContext wsContext;
58
59         private volatile ProcessEngineServices pes4junit = null;
60
61         @WebMethod(operationName = "SDNCAdapterCallback")
62     @WebResult(name = "SDNCAdapterResponse", targetNamespace = "http://domain2.att.com/workflow/sdnc/adapter/schema/v1", partName = "SDNCAdapterCallbackResponse")
63     public SDNCAdapterResponse sdncAdapterCallback(
64             @WebParam(name = "SDNCAdapterCallbackRequest", targetNamespace = "http://domain2.att.com/workflow/sdnc/adapter/schema/v1", partName = "SDNCAdapterCallbackRequest")
65             SDNCAdapterCallbackRequest sdncAdapterCallbackRequest) {
66
67                 //Callback URL to use http://localhost:8080/mso/SDNCAdapterCallbackService
68                 ProcessEngineServices pes = getProcessEngineServices();
69                 RuntimeService runtimeService = pes.getRuntimeService();
70                 String receivedRequestId = sdncAdapterCallbackRequest.getCallbackHeader().getRequestId();
71                 msoLogger.setServiceName("MSO." + "sdncAdapter");
72                 msoLogger.setLogContext(receivedRequestId, "N/A");
73                 msoLogger.debug(logMarker + "Received callback response:" + sdncAdapterCallbackRequest.toString());
74                 SDNCAdapterResponse sdncAdapterResponse;
75                 long startTime = System.currentTimeMillis();
76
77                 /* Check to make sure the process instance is reay for correlation*/
78                 isReadyforCorrelation(runtimeService, receivedRequestId);
79
80                 msoLogger.debug(logMarker + "*** Received MSO sdncAdapterCallbackService ******");
81                 
82                 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Call to MSO sdncAdapterCallbackService");            
83                 
84                 msoLogger.debug(logMarker + "Callback response string:\n"  + sdncAdapterCallbackRequest.toString());
85
86                 String reqId = receivedRequestId;
87                 Map<String,Object> variables = new HashMap<String,Object>();
88                 variables.put("SDNCA_requestId", reqId );
89                 variables.put("sdncAdapterCallbackRequest", sdncAdapterCallbackRequest.toString());
90
91                 /*Correlating the response with the running instance*/
92
93                 // NOTE: the following loop is a workaround for problems we've had
94                 // with reliability of the runtime service.  It seems that queries
95                 // sometimes return results, and sometimes they don't.  This might
96                 // be a problem in mysql only.  We aren't sure if it affects camunda
97                 // on oracle or mariadb.  The workaround is to repeat the request
98                 // a number of times until it succeeds.  If it doesn't succeed after
99                 // 60 tries, then we give up.
100
101                 int maxAttempts = DEFAULT_RETRY_ATTEMPTS;
102                 int attempt = 1;
103                 int sleepTime = DEFAULT_SLEEP_TIME;
104
105                 Map<String,String> bpmnProperties = getMSOBPMNURNProperties();
106                 if (bpmnProperties != null) {
107                         try {
108                                 maxAttempts = Integer.parseInt(bpmnProperties.get("mso.callbackRetryAttempts"));
109                                 msoLogger.debug(logMarker + "mso.callbackRetryAttempts=" + maxAttempts);
110                                 sleepTime = Integer.parseInt(bpmnProperties.get("mso.callbackRetrySleepTime"));
111                                 msoLogger.debug(logMarker + "mso.callbackRetrySleepTime:" + sleepTime);
112                         } catch (Exception ex) {
113                                 
114                                 msoLogger.info (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", logMarker 
115                                                 + "Error parsing mso.callbackRetrySleepTime/mso.callbackRetryAttempts:" 
116                                                 + sleepTime + ":" 
117                                                 + maxAttempts);
118                                 
119                                 msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, logMarker 
120                                                 + "Error parsing mso.callbackRetrySleepTime/mso.callbackRetryAttempts:" 
121                                                 + sleepTime + ":" 
122                                                 + maxAttempts);
123                                 
124                         }
125                 }
126
127                 while (true) {
128                         try {
129                                 // sdncAdapterCallbackRequest is the message event name (defined in the bpmn process)
130                                 runtimeService.createMessageCorrelation("sdncAdapterCallbackRequest")
131                                         .setVariables(variables)
132                                         .processInstanceVariableEquals("SDNCA_requestId", reqId).correlate();
133                                 sdncAdapterResponse = new SDNCAdapterResponse();
134                                 msoLogger.debug(logMarker + "***** Completed processing of MSO sdncAdapterCallbackService ******");
135                                 
136                                 msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, logMarker 
137                                                 + "Completed the execution of MSO SDNCAdapterCallbackService.");
138                                 
139                                 msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, 
140                                                 logMarker + "Completed the execution of MSO SDNCAdapterCallbackService.", "BPMN", 
141                                                 MsoLogger.getServiceName(), "sdncAdapterCallback");
142                                 
143                                 return sdncAdapterResponse;
144                         } catch(MismatchingMessageCorrelationException e) {
145                                 msoLogger.debug(logMarker + "[CORM]correlation id mismatch (attempt " + attempt + "/" + maxAttempts + ")");
146                                 if (attempt == maxAttempts) {
147                                         // Couldn't correlate requestId to any active flow
148                                         //MsoLogger logger = MsoLogger.getMsoLogger("SDNCAdapterCallbackService");
149                                         String msg =
150                                                 "SDNC Adapter Callback Service received a SDNC Adapter Callback Request with RequestId '"
151                                                                 + receivedRequestId
152                                                                 + "' but that RequestId could not be correlated to any active process - ignoring the Request";
153                                         sdncAdapterResponse = new SDNCAdapterExceptionResponse(e);
154                                         
155                                         msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(), 
156                                                         MsoLogger.ErrorCode.UnknownError, logMarker + ":" + msg, e);
157                                         
158                                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, logMarker 
159                                                         + "Completed the execution of MSO SDNCAdapterCallbackService." );
160                                         
161                                         msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, 
162                                                         logMarker + "Completed the execution of MSO SDNCAdapterCallbackService.", "BPMN", 
163                                                         MsoLogger.getServiceName(), "sdncAdapterCallback");
164                                         
165                                         return sdncAdapterResponse;
166                                 }
167
168                                 try {
169                                         Thread.sleep(sleepTime);
170                                 } catch (InterruptedException e2) {
171                                         String msg =
172                                                 "SDNC Adapter Callback Service received a SDNC Adapter Callback Request with RequestId '"
173                                                                 + receivedRequestId
174                                                                 + "' but correlation was interrupted";
175                                         sdncAdapterResponse = new SDNCAdapterExceptionResponse(e);
176                                         
177                                         msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(), 
178                                                         MsoLogger.ErrorCode.UnknownError, logMarker + ":" + msg, e);
179                                         
180                                         msoLogger.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, logMarker 
181                                                         + "Completed the execution of MSO SDNCAdapterCallbackService.");
182                                         
183                                         msoLogger.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, 
184                                                         logMarker + "Completed the execution of MSO SDNCAdapterCallbackService.", "BPMN", 
185                                                         MsoLogger.getServiceName(), "sdncAdapterCallback");
186                                         
187                                         return sdncAdapterResponse;
188                                 }
189                         }
190
191                         attempt++;
192                 }
193         }
194
195
196         private Map<String,String> getMSOBPMNURNProperties() {
197                 PropertyConfiguration propertyConfiguration = PropertyConfiguration.getInstance();
198                 Map<String,String> props = propertyConfiguration.getProperties("mso.bpmn.urn.properties");
199                 return props;
200         }
201
202         private void isReadyforCorrelation(RuntimeService runtimeService,
203                         String receivedRequestId) {
204                 long waitingInstances = runtimeService.createExecutionQuery() //
205                                                                 .messageEventSubscriptionName("sdncAdapterCallbackRequest")
206                                                                 .processVariableValueEquals("SDNCA_requestId", receivedRequestId).count();
207                 //Workaround for performance testing, explicit wait for a second for the transactions to be committed
208                 try {
209                         Thread.sleep(1000);
210                 } catch (InterruptedException e1) {
211                 }
212
213                 int retries = 50;
214                 while (waitingInstances==0 && retries > 0) {
215                   try {
216                         Thread.sleep(100);
217                 } catch (InterruptedException e) {
218                         
219                         msoLogger.error (MessageEnum.BPMN_SDNC_CALLBACK_EXCEPTION, "BPMN", MsoLogger.getServiceName(), 
220                                         MsoLogger.ErrorCode.UnknownError, logMarker, e);
221                         
222                 } // you can still play with the numbers
223                   waitingInstances = runtimeService.createExecutionQuery() //
224                           .messageEventSubscriptionName("sdncAdapterCallbackRequest")
225                           .processVariableValueEquals("SDNCA_requestId", receivedRequestId).count();
226                   retries--;
227                 }
228         }
229
230         private ProcessEngineServices getProcessEngineServices() {
231                 if (pes4junit == null) {
232                         return BpmPlatform.getDefaultProcessEngine();
233                 } else {
234                         return pes4junit;
235                 }
236         }
237
238         @WebMethod(exclude=true)
239         public void setProcessEngineServices4junit(ProcessEngineServices pes) {
240                 pes4junit = pes;
241         }
242
243         public class SDNCAdapterExceptionResponse extends SDNCAdapterResponse {
244                 private Exception ex;
245
246                 public SDNCAdapterExceptionResponse(Exception ex) {
247                         super();
248                         this.ex = ex;
249                 }
250
251                 public Exception getException() {
252                         return ex;
253                 }
254         }
255 }