Implement http participant in CLAMP
Issue-ID: POLICY-3449
Signed-off-by: zrrmmua <ramesh.murugan.iyer@est.tech>
Change-Id: Ibfe23a6e98fb760a930b6080dc2291113b3cb4fa
diff --git a/participant/participant-impl/participant-impl-http/pom.xml b/participant/participant-impl/participant-impl-http/pom.xml
new file mode 100644
index 0000000..85d65e7
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/pom.xml
@@ -0,0 +1,50 @@
+<!--
+ ============LICENSE_START=======================================================
+ Copyright (C) 2021 Nordix Foundation.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ SPDX-License-Identifier: Apache-2.0
+ ============LICENSE_END=========================================================
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.policy.clamp.participant</groupId>
+ <artifactId>policy-clamp-participant-impl</artifactId>
+ <version>6.1.2-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>policy-clamp-participant-impl-http</artifactId>
+ <name>${project.artifactId}</name>
+ <description>HTTP participant, that performs CRUD operations on Microservices through REST</description>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ <phase>package</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/Application.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/Application.java
new file mode 100644
index 0000000..dc36392
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/Application.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.participant.http;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Starter.
+ *
+ */
+@SpringBootApplication
+public class Application {
+ /**
+ * Main class.
+ *
+ * @param args args
+ */
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/config/ParticipantConfig.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/config/ParticipantConfig.java
new file mode 100644
index 0000000..ce013a7
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/config/ParticipantConfig.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.participant.http.config;
+
+import org.onap.policy.clamp.controlloop.participant.http.main.handler.ControlLoopElementHandler;
+import org.onap.policy.clamp.controlloop.participant.intermediary.api.ParticipantIntermediaryApi;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ParticipantConfig {
+
+ /**
+ * Register ControlLoopElementListener.
+ *
+ * @param intermediaryApi the ParticipantIntermediaryApi
+ * @param clElementHandler the ControlLoop Element Handler
+ */
+ @Autowired
+ public void registerControlLoopElementListener(ParticipantIntermediaryApi intermediaryApi,
+ ControlLoopElementHandler clElementHandler) {
+ intermediaryApi.registerControlLoopElementListener(clElementHandler);
+ clElementHandler.setIntermediaryApi(intermediaryApi);
+ }
+}
diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/exception/HttpWebClientException.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/exception/HttpWebClientException.java
new file mode 100644
index 0000000..b10af88
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/exception/HttpWebClientException.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.participant.http.main.exception;
+
+
+import org.springframework.web.reactive.function.client.WebClientResponseException;
+
+public class HttpWebClientException extends WebClientResponseException {
+
+ public HttpWebClientException(int statusCode, String statusText) {
+ super(statusCode, statusText, null, null, null);
+ }
+}
diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/handler/ControlLoopElementHandler.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/handler/ControlLoopElementHandler.java
new file mode 100644
index 0000000..67948a9
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/handler/ControlLoopElementHandler.java
@@ -0,0 +1,148 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.participant.http.main.handler;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.ValidationException;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.tuple.Pair;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
+import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigRequest;
+import org.onap.policy.clamp.controlloop.participant.http.main.webclient.ClHttpClient;
+import org.onap.policy.clamp.controlloop.participant.intermediary.api.ControlLoopElementListener;
+import org.onap.policy.clamp.controlloop.participant.intermediary.api.ParticipantIntermediaryApi;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class handles implementation of controlLoopElement updates.
+ */
+@Component
+public class ControlLoopElementHandler implements ControlLoopElementListener, Closeable {
+
+ private static final Coder CODER = new StandardCoder();
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
+
+ private Map<ToscaConceptIdentifier, Pair<Integer, String>> restResponseMap = new ConcurrentHashMap<>();
+
+ @Setter
+ private ParticipantIntermediaryApi intermediaryApi;
+
+ /**
+ * Handle controlLoopElement statistics.
+ *
+ * @param controlLoopElementId controlloop element id
+ */
+ @Override
+ public void handleStatistics(UUID controlLoopElementId) throws PfModelException {
+ // Implementation not needed for http participant
+
+ }
+
+ /**
+ * Handle a control loop element state change.
+ *
+ * @param controlLoopElementId the ID of the control loop element
+ * @param currentState the current state of the control loop element
+ * @param newState the state to which the control loop element is changing to
+ * @throws PfModelException in case of a model exception
+ */
+ @Override
+ public void controlLoopElementStateChange(UUID controlLoopElementId, ControlLoopState currentState,
+ ControlLoopOrderedState newState) throws PfModelException {
+ // Implementation not needed for http participant
+ }
+
+ /**
+ * Callback method to handle an update on a control loop element.
+ *
+ * @param element the information on the control loop element
+ * @param controlLoopDefinition toscaServiceTemplate
+ */
+ @Override
+ public void controlLoopElementUpdate(ControlLoopElement element, ToscaServiceTemplate controlLoopDefinition) {
+
+ for (Map.Entry<String, ToscaNodeTemplate> nodeTemplate : controlLoopDefinition.getToscaTopologyTemplate()
+ .getNodeTemplates().entrySet()) {
+ // Fetching the node template of corresponding CL element
+ if (element.getDefinition().getName().equals(nodeTemplate.getKey())) {
+ try {
+ var configRequest = CODER.convert(nodeTemplate.getValue().getProperties(), ConfigRequest.class);
+ Set<ConstraintViolation<ConfigRequest>> violations = Validation.buildDefaultValidatorFactory()
+ .getValidator().validate(configRequest);
+ if (violations.isEmpty()) {
+ invokeHttpClient(configRequest);
+ } else {
+ LOGGER.error("Violations found in the config request parameters: {}", violations);
+ throw new ValidationException("Constraint violations in the config request");
+ }
+ } catch (CoderException | ValidationException e) {
+ LOGGER.error("Error invoking the http request for the config ", e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Invoke a runnable thread to execute http requests.
+ * @param configRequest ConfigRequest
+ */
+ public void invokeHttpClient(ConfigRequest configRequest) {
+ // Invoke runnable thread to execute https requests of all config entities
+ executor.execute(new ClHttpClient(configRequest, restResponseMap));
+ }
+
+ /**
+ * Closes this stream and releases any system resources associated
+ * with it. If the stream is already closed then invoking this
+ * method has no effect.
+ *
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ public void close() throws IOException {
+ executor.shutdown();
+ }
+}
diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/models/ConfigRequest.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/models/ConfigRequest.java
new file mode 100644
index 0000000..87cab88
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/models/ConfigRequest.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.participant.http.main.models;
+
+import java.util.List;
+import java.util.Map;
+import javax.validation.Valid;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.DefaultValue;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class ConfigRequest {
+
+ @NotBlank
+ private String baseUrl;
+
+ @NotNull
+ private Map<String, String> httpHeaders;
+
+ @NotNull
+ @Valid
+ private List<ConfigurationEntity> configurationEntities;
+
+ @Min(value = 1)
+ @DefaultValue("20")
+ private int uninitializedToPassiveTimeout;
+
+}
diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/models/ConfigurationEntity.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/models/ConfigurationEntity.java
new file mode 100644
index 0000000..8703a9d
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/models/ConfigurationEntity.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.participant.http.main.models;
+
+import java.util.List;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+@Data
+@AllArgsConstructor
+public class ConfigurationEntity {
+
+ @NotNull
+ private ToscaConceptIdentifier configurationEntityId;
+
+ @NotNull
+ @Valid
+ private List<RestParams> restSequence;
+}
diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/models/RestParams.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/models/RestParams.java
new file mode 100644
index 0000000..fc4e028
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/models/RestParams.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.participant.http.main.models;
+
+import java.util.Map;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+@Data
+@AllArgsConstructor
+public class RestParams {
+
+ @NotNull
+ private ToscaConceptIdentifier restRequestId;
+
+ @NotNull
+ private String httpMethod;
+
+ @NotNull
+ private String path;
+
+ @Min(100)
+ @Max(599)
+ private int expectedResponse;
+
+ private Map<String, Object> pathParams;
+
+ private Map<String, String> queryParams;
+
+ private String body;
+
+}
diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/webclient/ClHttpClient.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/webclient/ClHttpClient.java
new file mode 100644
index 0000000..0e0ea55
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/controlloop/participant/http/main/webclient/ClHttpClient.java
@@ -0,0 +1,135 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.participant.http.main.webclient;
+
+import java.lang.invoke.MethodHandles;
+import java.time.Duration;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.onap.policy.clamp.controlloop.participant.http.main.exception.HttpWebClientException;
+import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigRequest;
+import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigurationEntity;
+import org.onap.policy.clamp.controlloop.participant.http.main.models.RestParams;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.util.UriComponentsBuilder;
+import reactor.core.publisher.Mono;
+
+public class ClHttpClient implements Runnable {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private final ConfigRequest configRequest;
+
+ private Map<ToscaConceptIdentifier, Pair<Integer, String>> responseMap;
+
+ /**
+ * Constructor.
+ */
+ public ClHttpClient(ConfigRequest configRequest, Map<ToscaConceptIdentifier, Pair<Integer, String>> responseMap) {
+ this.configRequest = configRequest;
+ this.responseMap = responseMap;
+ }
+
+ /**
+ * Runnable to execute http requests.
+ */
+ @Override
+ public void run() {
+
+ var webClient = WebClient.builder()
+ .baseUrl(configRequest.getBaseUrl())
+ .defaultHeaders(httpHeaders -> httpHeaders.addAll(createHeaders(configRequest)))
+ .build();
+
+ for (ConfigurationEntity configurationEntity : configRequest.getConfigurationEntities()) {
+ LOGGER.info("Executing http requests for the config entity {}",
+ configurationEntity.getConfigurationEntityId());
+
+ executeRequest(webClient, configurationEntity);
+ }
+ }
+
+ private void executeRequest(WebClient client, ConfigurationEntity configurationEntity) {
+
+ // Iterate the sequence of http requests
+ for (RestParams request: configurationEntity.getRestSequence()) {
+ String response = null;
+ try {
+ var httpMethod = Objects.requireNonNull(HttpMethod.resolve(request.getHttpMethod()));
+ var uri = createUriString(request);
+ LOGGER.info("Executing HTTP request: {} for the Rest request id: {}", httpMethod,
+ request.getRestRequestId());
+
+ response = client.method(httpMethod)
+ .uri(uri)
+ .body(request.getBody() == null ? BodyInserters.empty()
+ : BodyInserters.fromValue(request.getBody()))
+ .exchangeToMono(clientResponse ->
+ clientResponse.statusCode().value() == request.getExpectedResponse()
+ ? clientResponse.bodyToMono(String.class)
+ : Mono.error(new HttpWebClientException(clientResponse.statusCode().value(),
+ clientResponse.bodyToMono(String.class).toString())))
+ .block(Duration.ofMillis(configRequest.getUninitializedToPassiveTimeout() * 1000L));
+
+ LOGGER.info("HTTP response for the {} request : {}", httpMethod, response);
+ responseMap.put(request.getRestRequestId(), new ImmutablePair<>(request.getExpectedResponse(),
+ response));
+
+ } catch (HttpWebClientException ex) {
+ LOGGER.error("Error occurred on the HTTP request ", ex);
+ responseMap.put(request.getRestRequestId(), new ImmutablePair<>(ex.getStatusCode().value(),
+ ex.getResponseBodyAsString()));
+ }
+ }
+ }
+
+ private HttpHeaders createHeaders(ConfigRequest request) {
+ var headers = new HttpHeaders();
+ for (Map.Entry<String, String> entry: request.getHttpHeaders().entrySet()) {
+ headers.add(entry.getKey(), entry.getValue());
+ }
+ return headers;
+ }
+
+ private String createUriString(RestParams restParams) {
+ var uriComponentsBuilder = UriComponentsBuilder.fromUriString(restParams.getPath());
+ // Add path params if present
+ if (restParams.getPathParams() != null) {
+ uriComponentsBuilder.uriVariables(restParams.getPathParams());
+ }
+ // Add query params if present
+ if (restParams.getQueryParams() != null) {
+ for (Map.Entry<String, String> entry : restParams.getQueryParams().entrySet()) {
+ uriComponentsBuilder.queryParam(entry.getKey(), entry.getValue());
+ }
+ }
+ return uriComponentsBuilder.build().toUriString();
+ }
+
+}
diff --git a/participant/participant-impl/participant-impl-http/src/main/resources/config/application.yaml b/participant/participant-impl/participant-impl-http/src/main/resources/config/application.yaml
new file mode 100644
index 0000000..1fd5284
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/main/resources/config/application.yaml
@@ -0,0 +1,27 @@
+participant:
+ intermediaryParameters:
+ reportingTimeInterval: 120000
+ description: Participant Description
+ participantId:
+ name: HttpParticipant0
+ version: 1.0.0
+ participantType:
+ name: org.onap.k8s.controlloop.HttpControlLoopParticipant
+ version: 2.3.4
+ clampControlLoopTopics:
+ topicSources:
+ - topic: POLICY-CLRUNTIME-PARTICIPANT
+ servers:
+ - ${topicServer:message-router}
+ topicCommInfrastructure: dmaap
+ fetchTimeout: 15000
+ topicSinks:
+ - topic: POLICY-CLRUNTIME-PARTICIPANT
+ servers:
+ - ${topicServer:message-router}
+ topicCommInfrastructure: dmaap
+
+ - topic: POLICY-NOTIFICATION
+ servers:
+ - ${topicServer:message-router}
+ topicCommInfrastructure: dmaap
diff --git a/participant/participant-impl/participant-impl-http/src/test/java/handler/ClElementHandlerTest.java b/participant/participant-impl/participant-impl-http/src/test/java/handler/ClElementHandlerTest.java
new file mode 100644
index 0000000..10b8103
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/test/java/handler/ClElementHandlerTest.java
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package handler;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Spy;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
+import org.onap.policy.clamp.controlloop.participant.http.main.handler.ControlLoopElementHandler;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import utils.CommonTestData;
+import utils.ToscaUtils;
+
+@ExtendWith(SpringExtension.class)
+class ClElementHandlerTest {
+
+ @InjectMocks
+ @Spy
+ private ControlLoopElementHandler controlLoopElementHandler = new ControlLoopElementHandler();
+
+ private CommonTestData commonTestData = new CommonTestData();
+
+ private static ToscaServiceTemplate serviceTemplate;
+
+ @BeforeAll
+ static void init() throws CoderException {
+ serviceTemplate = ToscaUtils.readControlLoopFromTosca();
+ }
+
+ @Test
+ void test_ControlLoopElementUpdate() {
+ doNothing().when(controlLoopElementHandler).invokeHttpClient(any());
+ ControlLoopElement element = commonTestData.getControlLoopElement();
+ assertDoesNotThrow(() -> controlLoopElementHandler
+ .controlLoopElementUpdate(element, serviceTemplate));
+ }
+}
diff --git a/participant/participant-impl/participant-impl-http/src/test/java/utils/CommonTestData.java b/participant/participant-impl/participant-impl-http/src/test/java/utils/CommonTestData.java
new file mode 100644
index 0000000..84957ed
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/test/java/utils/CommonTestData.java
@@ -0,0 +1,146 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package utils;
+
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState;
+import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigurationEntity;
+import org.onap.policy.clamp.controlloop.participant.http.main.models.RestParams;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+public class CommonTestData {
+
+ private static final Coder CODER = new StandardCoder();
+ private static final String TEST_KEY_NAME = "org.onap.domain.database.Http_PMSHMicroserviceControlLoopElement";
+
+
+ /**
+ * Get a controlLoop Element.
+ * @return controlLoopElement object
+ */
+ public ControlLoopElement getControlLoopElement() {
+ ControlLoopElement element = new ControlLoopElement();
+ element.setId(UUID.randomUUID());
+ element.setDefinition(new ToscaConceptIdentifier(TEST_KEY_NAME, "1.0.1"));
+ element.setOrderedState(ControlLoopOrderedState.PASSIVE);
+ return element;
+ }
+
+ /**
+ * Get query params.
+ * @return Map of query params
+ */
+ public Map<String, String> getQueryParams() {
+ return Map.of("name", "dummy", "version", "1.0");
+ }
+
+ /**
+ * Get path params.
+ * @return Map of path params
+ */
+ public Map<String, Object> getPathParams() {
+ return Map.of("id", "123", "name", "dummy");
+ }
+
+ /**
+ * Rest params with GET request.
+ * @return RestParams obj
+ */
+ public RestParams restParamsWithGet() {
+ return new RestParams(
+ new ToscaConceptIdentifier("getRequest", "1.0"),
+ "GET",
+ "get",
+ 200,
+ null,
+ getQueryParams(),
+ null
+ );
+ }
+
+ /**
+ * Rest params with POST request.
+ * @return RestParams obj
+ */
+ public RestParams restParamsWithPost() {
+ return new RestParams(
+ new ToscaConceptIdentifier("postRequest", "1.0"),
+ "POST",
+ "post",
+ 200,
+ null,
+ getQueryParams(),
+ "Test body"
+ );
+ }
+
+ /**
+ * Rest params with POST request.
+ * @return RestParams obj
+ */
+ public RestParams restParamsWithInvalidPost() {
+ return new RestParams(
+ new ToscaConceptIdentifier("postRequest", "1.0"),
+ "POST",
+ "post/{id}/{name}",
+ 200,
+ getPathParams(),
+ getQueryParams(),
+ "Test body"
+ );
+ }
+
+ /**
+ * Get invalid configuration entity.
+ * @return ConfigurationEntity obj
+ */
+ public ConfigurationEntity getInvalidConfigurationEntity() {
+ return new ConfigurationEntity(
+ new ToscaConceptIdentifier("config1", "1.0.1"),
+ List.of(restParamsWithGet(), restParamsWithInvalidPost())
+ );
+ }
+
+ /**
+ * Get configuration entity.
+ * @return ConfigurationEntity obj
+ */
+ public ConfigurationEntity getConfigurationEntity() {
+ return new ConfigurationEntity(
+ new ToscaConceptIdentifier("config1", "1.0.1"),
+ List.of(restParamsWithGet(), restParamsWithPost())
+ );
+ }
+
+ /**
+ * Get headers for config request.
+ * @return Map of headers
+ */
+ public Map<String, String> getHeaders() {
+ return Map.of("Content-Type", "application/json", "Accept", "application/json");
+ }
+
+}
diff --git a/participant/participant-impl/participant-impl-http/src/test/java/utils/ToscaUtils.java b/participant/participant-impl/participant-impl-http/src/test/java/utils/ToscaUtils.java
new file mode 100644
index 0000000..cf71248
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/test/java/utils/ToscaUtils.java
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package utils;
+
+import org.onap.policy.common.utils.coder.YamlJsonTranslator;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+
+/**
+ * Util class for Test scope.
+ */
+public class ToscaUtils {
+
+ private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator();
+ private static final String TOSCA_TEMPLATE_YAML = "src/test/resources/HttpParticipantConfig.yaml";
+
+
+ /**
+ * Read a service template yaml.
+ * @return ToscaServiceTemplate
+ */
+ public static ToscaServiceTemplate readControlLoopFromTosca() {
+ return serializeControlLoopYaml(TOSCA_TEMPLATE_YAML);
+ }
+
+ private static ToscaServiceTemplate serializeControlLoopYaml(String controlLoopFilePath) {
+ String controlLoopString = ResourceUtils.getResourceAsString(controlLoopFilePath);
+ return yamlTranslator.fromYaml(controlLoopString, ToscaServiceTemplate.class);
+ }
+}
diff --git a/participant/participant-impl/participant-impl-http/src/test/java/webclient/ClHttpClientTest.java b/participant/participant-impl/participant-impl-http/src/test/java/webclient/ClHttpClientTest.java
new file mode 100644
index 0000000..411974a
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/test/java/webclient/ClHttpClientTest.java
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package webclient;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.lang3.tuple.Pair;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigRequest;
+import org.onap.policy.clamp.controlloop.participant.http.main.models.ConfigurationEntity;
+import org.onap.policy.clamp.controlloop.participant.http.main.webclient.ClHttpClient;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import utils.CommonTestData;
+
+@ExtendWith(SpringExtension.class)
+class ClHttpClientTest {
+
+ private CommonTestData commonTestData = new CommonTestData();
+
+ private String testBaseUrl = "https://httpbin.org";
+
+ private Map<ToscaConceptIdentifier, Pair<Integer, String>> responseMap = new HashMap<>();
+
+
+ @Test
+ void test_validRequest() {
+ //Add valid rest requests POST, GET
+ ConfigurationEntity configurationEntity = commonTestData.getConfigurationEntity();
+
+ Map<String, String> headers = commonTestData.getHeaders();
+ ConfigRequest configRequest = new ConfigRequest(testBaseUrl, headers,
+ List.of(configurationEntity), 10);
+
+ ClHttpClient client = new ClHttpClient(configRequest, responseMap);
+ assertDoesNotThrow(client::run);
+ assertThat(responseMap).hasSize(2).containsKey(commonTestData
+ .restParamsWithGet().getRestRequestId());
+
+ Pair<Integer, String> restResponseMap = responseMap.get(commonTestData
+ .restParamsWithGet().getRestRequestId());
+ assertThat(restResponseMap.getKey()).isEqualTo(200);
+ }
+
+ @Test
+ void test_invalidRequest() {
+ //Add rest requests Invalid POST, Valid GET
+ ConfigurationEntity configurationEntity = commonTestData.getInvalidConfigurationEntity();
+
+ Map<String, String> headers = commonTestData.getHeaders();
+ ConfigRequest configRequest = new ConfigRequest(testBaseUrl, headers,
+ List.of(configurationEntity), 10);
+
+ ClHttpClient client = new ClHttpClient(configRequest, responseMap);
+ assertDoesNotThrow(client::run);
+ assertThat(responseMap).hasSize(2).containsKey(commonTestData
+ .restParamsWithGet().getRestRequestId());
+ Pair<Integer, String> response = responseMap
+ .get(commonTestData.restParamsWithInvalidPost().getRestRequestId());
+ assertThat(response.getKey()).isEqualTo(404);
+ }
+}
diff --git a/participant/participant-impl/participant-impl-http/src/test/resources/HttpParticipantConfig.yaml b/participant/participant-impl/participant-impl-http/src/test/resources/HttpParticipantConfig.yaml
new file mode 100644
index 0000000..43d0c26
--- /dev/null
+++ b/participant/participant-impl/participant-impl-http/src/test/resources/HttpParticipantConfig.yaml
@@ -0,0 +1,208 @@
+# ============LICENSE_START=======================================================
+# Copyright (C) 2021 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+tosca_definitions_version: tosca_simple_yaml_1_3
+data_types:
+ onap.datatypes.ToscaConceptIdentifier:
+ derived_from: tosca.datatypes.Root
+ properties:
+ name:
+ type: string
+ required: true
+ version:
+ type: string
+ required: true
+
+ org.onap.datatypes.policy.clamp.controlloop.httpControlLoopElement.RestRequest:
+ version: 1.0.0
+ derived_from: tosca.datatypes.Root
+ properties:
+ restRequestId:
+ type: onap.datatypes.ToscaConceptIdentifier
+ typeVersion: 1.0.0
+ required: true
+ description: The name and version of a REST request to be sent to a REST endpoint
+ httpMethod:
+ type: string
+ required: true
+ constraints:
+ - valid_values: [POST, PUT, GET, DELETE]
+ description: The REST method to use
+ path:
+ type: string
+ required: true
+ description: The path of the REST request relative to the base URL
+ body:
+ type: string
+ required: false
+ description: The body of the REST request for PUT and POST requests
+ expectedResponse:
+ type: integer
+ required: true
+ constraints:
+ - in_range: [100, 599]
+ description: THe expected HTTP status code for the REST request
+ org.onap.datatypes.policy.clamp.controlloop.httpControlLoopElement.ConfigurationEntity:
+ version: 1.0.0
+ derived_from: tosca.datatypes.Root
+ properties:
+ configurationEntityId:
+ type: onap.datatypes.ToscaConceptIdentifier
+ typeVersion: 1.0.0
+ required: true
+ description: The name and version of a Configuration Entity to be handled by the HTTP Control Loop Element
+ restSequence:
+ type: list
+ entry_schema:
+ type: org.onap.datatypes.policy.clamp.controlloop.httpControlLoopElement.RestRequest
+ typeVersion: 1.0.0
+ description: A sequence of REST commands to send to the REST endpoint
+
+
+node_types:
+ org.onap.policy.clamp.controlloop.Participant:
+ version: 1.0.1
+ derived_from: tosca.nodetypes.Root
+ properties:
+ provider:
+ type: string
+ requred: false
+ org.onap.policy.clamp.controlloop.ControlLoopElement:
+ version: 1.0.1
+ derived_from: tosca.nodetypes.Root
+ properties:
+ provider:
+ type: string
+ requred: false
+ participant_id:
+ type: onap.datatypes.ToscaConceptIdentifier
+ requred: true
+ org.onap.policy.clamp.controlloop.ControlLoop:
+ version: 1.0.1
+ derived_from: tosca.nodetypes.Root
+ properties:
+ provider:
+ type: string
+ requred: false
+ elements:
+ type: list
+ required: true
+ entry_schema:
+ type: onap.datatypes.ToscaConceptIdentifier
+ org.onap.policy.clamp.controlloop.HttpControlLoopElement:
+ version: 1.0.1
+ derived_from: org.onap.policy.clamp.controlloop.ControlLoopElement
+ properties:
+ baseUrl:
+ type: string
+ required: true
+ description: The base URL to be prepended to each path, identifies the host for the REST endpoints.
+ httpHeaders:
+ type: map
+ required: false
+ entry_schema:
+ type: string
+ description: HTTP headers to send on REST requests
+ configurationEntities:
+ type: map
+ required: true
+ entry_schema:
+ type: org.onap.datatypes.policy.clamp.controlloop.httpControlLoopElement.ConfigurationEntity
+ typeVersion: 1.0.0
+ description: The connfiguration entities the Control Loop Element is managing and their associated REST requests
+topology_template:
+ node_templates:
+ org.onap.k8s.controlloop.HttpControlLoopParticipant:
+ version: 2.3.4
+ type: org.onap.policy.clamp.controlloop.Participant
+ type_version: 1.0.1
+ description: Participant for Http requests
+ properties:
+ provider: ONAP
+
+ org.onap.domain.database.Http_PMSHMicroserviceControlLoopElement:
+ # Http config for PMSH.
+ version: 1.2.3
+ type: org.onap.policy.clamp.controlloop.HttpControlLoopElement
+ type_version: 1.0.1
+ description: Control loop element for the http requests of PMSH microservice
+ properties:
+ provider: ONAP
+ participant_id:
+ name: org.onap.controlloop.HttpControlLoopParticipant
+ version: 2.3.4
+ uninitializedToPassiveTimeout: 180
+ baseUrl: https://httpbin.org
+ httpHeaders:
+ Content-Type: application/json
+ configurationEntities:
+ - configurationEntityId:
+ name: entity1
+ version: 1.0.1
+ restSequence:
+ - restRequestId:
+ name: request1
+ version: 1.0.1
+ httpMethod: POST
+ path: post
+ body: '{"name":"ob1","port_type"}'
+ expectedResponse: 200
+
+ - restRequestId:
+ name: request1
+ version: 1.0.1
+ httpMethod: GET
+ path: get
+ expectedResponse: 200
+
+ # Rest path with path params and query params
+ - configurationEntityId:
+ name: entity2
+ version: 1.0.1
+ restSequence:
+ - restRequestId:
+ name: request1
+ version: 1.0.1
+ httpMethod: POST
+ path: post/{id}/{name}
+ pathParams:
+ id: 123
+ name: dummyName
+ body: this is a test body
+ expectedResponse: 200
+
+ - restRequestId:
+ name: request1
+ version: 1.0.1
+ httpMethod: GET
+ path: get
+ queryParams:
+ id: 123
+ name: dummyName
+ expectedResponse: 200
+
+
+ org.onap.domain.sample.GenericK8s_ControlLoopDefinition:
+ version: 1.2.3
+ type: org.onap.policy.clamp.controlloop.ControlLoop
+ type_version: 1.0.0
+ description: Control loop for HTTP request
+ properties:
+ provider: ONAP
+ elements:
+ - name: org.onap.domain.database.Http_PMSHMicroserviceControlLoopElement
+ version: 1.2.3
diff --git a/participant/participant-impl/pom.xml b/participant/participant-impl/pom.xml
index f1f4f0e..439bdea 100644
--- a/participant/participant-impl/pom.xml
+++ b/participant/participant-impl/pom.xml
@@ -40,6 +40,7 @@
<module>participant-impl-policy</module>
<module>participant-impl-cds</module>
<module>participant-impl-kubernetes</module>
+ <module>participant-impl-http</module>
</modules>
<dependencies>
diff --git a/pom.xml b/pom.xml
index fdaeb13..61af7c4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -201,5 +201,9 @@
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-webflux</artifactId>
+ </dependency>
</dependencies>
</project>