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.gamma.workflow.service;
23 import java.io.StringReader;
24 import java.util.HashMap;
27 import javax.ws.rs.Consumes;
28 import javax.ws.rs.POST;
29 import javax.ws.rs.Path;
30 import javax.ws.rs.Produces;
31 import javax.ws.rs.core.MediaType;
32 import javax.ws.rs.core.Response;
33 import javax.xml.parsers.DocumentBuilder;
34 import javax.xml.parsers.DocumentBuilderFactory;
36 import org.camunda.bpm.BpmPlatform;
37 import org.camunda.bpm.engine.MismatchingMessageCorrelationException;
38 import org.camunda.bpm.engine.ProcessEngineServices;
39 import org.camunda.bpm.engine.RuntimeService;
41 import org.w3c.dom.Document;
42 import org.w3c.dom.Element;
43 import org.w3c.dom.Node;
44 import org.w3c.dom.NodeList;
45 import org.xml.sax.InputSource;
47 import org.openecomp.mso.logger.MessageEnum;
48 import org.openecomp.mso.logger.MsoLogger;
51 * Listens for REST notifications from the VNF Adapter and injects each one
52 * into a waiting BPMN processes.
54 @Path("/vnfAdapterRestNotify")
55 public class VnfAdapterRestNotifyResource {
56 private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL);
57 private static final String LOGMARKER = "[VNF-REST-NOTIFY]";
59 private ProcessEngineServices pes4junit = null;
63 @Consumes(MediaType.APPLICATION_XML)
64 @Produces(MediaType.TEXT_PLAIN)
65 public Response notify(String content) {
66 LOGGER.debug(LOGMARKER + " Received VNF Adapter REST Notification:"
67 + System.lineSeparator() + content);
69 String messageId = null;
70 long startTime = System.currentTimeMillis();
73 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
74 factory.setNamespaceAware(true);
75 DocumentBuilder builder = factory.newDocumentBuilder();
76 InputSource source = new InputSource(new StringReader(content));
77 Document doc = builder.parse(source);
80 Element rootElement = doc.getDocumentElement();
81 NodeList childList = rootElement.getChildNodes();
83 for (int i = 0; i < childList.getLength(); i++) {
84 Node childNode = childList.item(i);
85 if (childNode.getNodeType() == Node.ELEMENT_NODE) {
86 Element childElement = (Element) childNode;
88 String childElementName = childElement.getLocalName();
89 if (childElementName == null) {
90 childElementName = childElement.getNodeName();
93 if ("messageId".equals(childElementName)) {
94 messageId = childElement.getTextContent();
98 } catch (Exception e) {
99 String msg = "Failed to parse VNF Adapter REST Notification: " + e;
100 LOGGER.debug(LOGMARKER + " " + msg);
101 LOGGER.error(MessageEnum.BPMN_GENERAL_EXCEPTION, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.DataError, LOGMARKER + ":" + msg, e);
103 return Response.status(400).entity(e).build();
106 if (messageId == null || messageId.isEmpty()) {
107 String msg = "No messageId in VNF Adapter REST Notification";
108 LOGGER.debug(LOGMARKER + " " + msg);
109 LOGGER.error(MessageEnum.BPMN_GENERAL_EXCEPTION, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.DataError, LOGMARKER + ":" + msg);
111 return Response.status(400).entity(msg).build();
114 MsoLogger.setServiceName("MSO." + "vnfAdapterRestNotify");
115 MsoLogger.setLogContext(messageId, "N/A");
117 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Call to MSO vnfAdapterRestNotify ");
120 ProcessEngineServices pes = getProcessEngineServices();
121 RuntimeService runtimeService = pes.getRuntimeService();
123 if (!isReadyforCorrelation(runtimeService, "VNFREST_messageId", messageId, "vnfAdapterRestCallbackMessage")) {
124 String msg = "No process is waiting to receive vnfAdapterRestCallbackMessage with VNFREST_messageId='" + messageId + "'";
125 LOGGER.debug(LOGMARKER + " " + msg);
126 LOGGER.error(MessageEnum.BPMN_GENERAL_EXCEPTION, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, LOGMARKER + ":" + msg);
128 LOGGER.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
129 LOGMARKER + "Call to MSO vnfAdapterRestNotify ", "BPMN", MsoLogger.getServiceName(), "vnfAdapterRestNotify");
131 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Call to MSO VnfAdapterNotifyService ");
134 return Response.status(500).entity(msg).build();
137 Map<String,Object> variables = new HashMap<String,Object>();
138 variables.put("VNFREST_messageId", messageId);
139 variables.put("VNFREST_callback", content);
141 runtimeService.createMessageCorrelation("vnfAdapterRestCallbackMessage").setVariables(variables)
142 .processInstanceVariableEquals("VNFREST_messageId", messageId).correlate();
144 LOGGER.debug(LOGMARKER + " Completed processing of VNF Adapter REST Notification");
145 } catch (MismatchingMessageCorrelationException e) {
146 LOGGER.debug(LOGMARKER + "[CORM] correlation id mismatch");
147 String msg = "vnfAdapterRestNotify received a notification with messageId='"
148 + messageId + "' but it could not be correlated to any active process - ignoring the request";
150 LOGGER.error(MessageEnum.BPMN_GENERAL_EXCEPTION, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, LOGMARKER, e);
152 LOGGER.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.InternalError,
153 LOGMARKER + "Completed vnfAdapterRestNotify with error ", "BPMN", MsoLogger.getServiceName(), "vnfAdapterRestNotify");
155 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.InternalError, "Completed vnfAdapterRestNotify with error ");
157 return Response.status(500).entity(msg).build();
159 LOGGER.recordMetricEvent ( startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc,
160 LOGMARKER + "Completed vnfAdapterRestNotify", "BPMN", MsoLogger.getServiceName(), "vnfAdapterRestNotify");
162 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Completed vnfAdapterRestNotify");
164 return Response.status(204).build();
167 private boolean isReadyforCorrelation(RuntimeService runtimeService,
168 String correlationVariable, String correlationValue, String messageName) {
169 long waitingInstances = runtimeService.createExecutionQuery()
170 .messageEventSubscriptionName(messageName)
171 .processVariableValueEquals(correlationVariable, correlationValue)
175 while (waitingInstances == 0 && retries > 0) {
178 } catch (InterruptedException e) {
179 LOGGER.error(MessageEnum.BPMN_GENERAL_EXCEPTION, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.UnknownError, LOGMARKER, e);
184 waitingInstances = runtimeService.createExecutionQuery()
185 .messageEventSubscriptionName(messageName)
186 .processVariableValueEquals(correlationVariable, correlationValue)
192 return waitingInstances != 0;
195 private ProcessEngineServices getProcessEngineServices() {
196 if (pes4junit == null) {
197 return BpmPlatform.getDefaultProcessEngine();
203 public void setProcessEngineServices4junit(ProcessEngineServices pes) {