AAI client & common module added

* added module containing common code for other sdk modules
* added reactive rest client for AAI data base with unit tests
* improved poms
* license text corrected accoriding to SDK

Change-Id: I23ea5fbf0e45170b2a1d70ad300bd72121d16ec1
Issue-ID: DCAEGEN2-986
Signed-off-by: pwielebs <piotr.wielebski@nokia.com>
diff --git a/pom.xml b/pom.xml
index dee0b2d..dd20f23 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,6 +32,7 @@
     <immutables.version>2.7.3</immutables.version>
     <spring.version>5.1.2.RELEASE</spring.version>
     <slf4j.version>1.7.25</slf4j.version>
+    <mockito.version>2.16.0</mockito.version>
   </properties>
 
   <modules>
@@ -162,10 +163,20 @@
       </dependency>
       <dependency>
         <groupId>org.springframework</groupId>
+        <artifactId>spring-web</artifactId>
+        <version>${spring.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.springframework</groupId>
         <artifactId>spring-context</artifactId>
         <version>${spring.version}</version>
       </dependency>
       <dependency>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring-core</artifactId>
+        <version>${spring.version}</version>
+      </dependency>
+      <dependency>
         <groupId>org.immutables</groupId>
         <artifactId>value</artifactId>
         <version>${immutables.version}</version>
@@ -195,7 +206,7 @@
       <dependency>
         <groupId>org.mockito</groupId>
         <artifactId>mockito-core</artifactId>
-        <version>2.23.0</version>
+        <version>${mockito.version}</version>
         <scope>test</scope>
       </dependency>
       <dependency>
@@ -229,6 +240,11 @@
         <type>pom</type>
         <scope>import</scope>
       </dependency>
+      <dependency>
+        <groupId>io.projectreactor.netty</groupId>
+        <artifactId>reactor-netty</artifactId>
+        <version>0.8.1.RELEASE</version>
+      </dependency>
     </dependencies>
   </dependencyManagement>
 </project>
diff --git a/rest-services/aai-client/pom.xml b/rest-services/aai-client/pom.xml
index 5bf4833..84b7082 100644
--- a/rest-services/aai-client/pom.xml
+++ b/rest-services/aai-client/pom.xml
@@ -21,16 +21,39 @@
 
   <dependencies>
     <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-core</artifactId>
-      <scope>test</scope>
+      <groupId>org.immutables</groupId>
+      <artifactId>value</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.junit.platform</groupId>
-      <artifactId>junit-platform-launcher</artifactId>
-      <scope>test</scope>
+      <groupId>io.projectreactor.netty</groupId>
+      <artifactId>reactor-netty</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-webflux</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jul-to-slf4j</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>log4j-over-slf4j</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter-api</artifactId>
       <scope>test</scope>
@@ -45,5 +68,22 @@
       <artifactId>junit-vintage-engine</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>io.projectreactor</groupId>
+      <artifactId>reactor-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+      <artifactId>common-dependency</artifactId>
+      <version>1.0.0-SNAPSHOT</version>
+      <scope>compile</scope>
+    </dependency>
+
   </dependencies>
 </project>
\ No newline at end of file
diff --git a/rest-services/aai-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/config/AaiClientConfiguration.java b/rest-services/aai-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/config/AaiClientConfiguration.java
new file mode 100644
index 0000000..fc4b0f4
--- /dev/null
+++ b/rest-services/aai-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/config/AaiClientConfiguration.java
@@ -0,0 +1,82 @@
+/*
+ * ============LICENSE_START=======================================================
+ * DCAEGEN2-SERVICES-SDK
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.sdk.rest.services.aai.client.config;
+
+import org.immutables.gson.Gson;
+import org.immutables.value.Value;
+import org.springframework.stereotype.Component;
+
+
+import java.io.Serializable;
+import java.util.Map;
+
+
+@Component
+@Value.Immutable(prehash = true)
+@Value.Style(builder = "new")
+@Gson.TypeAdapters
+public abstract class AaiClientConfiguration implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @Value.Parameter
+    public abstract String aaiHost();
+
+    @Value.Parameter
+    public abstract Integer aaiPort();
+
+    @Value.Parameter
+    public abstract String aaiProtocol();
+
+    @Value.Parameter
+    public abstract String aaiUserName();
+
+    @Value.Parameter
+    public abstract String aaiUserPassword();
+
+    @Value.Parameter
+    public abstract Boolean aaiIgnoreSslCertificateErrors();
+
+    @Value.Parameter
+    public abstract String aaiBasePath();
+
+    @Value.Parameter
+    public abstract String aaiPnfPath();
+
+    @Value.Parameter
+    public abstract Map<String, String> aaiHeaders();
+
+    @Value.Parameter
+    public abstract String trustStorePath();
+
+    @Value.Parameter
+    public abstract  String trustStorePasswordPath();
+
+    @Value.Parameter
+    public abstract String keyStorePath();
+
+    @Value.Parameter
+    public abstract String keyStorePasswordPath();
+
+    @Value.Parameter
+    public abstract Boolean enableAaiCertAuth();
+
+}
diff --git a/rest-services/aai-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/AaiReactiveWebClientFactory.java b/rest-services/aai-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/AaiReactiveWebClientFactory.java
new file mode 100644
index 0000000..1b9e57f
--- /dev/null
+++ b/rest-services/aai-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/AaiReactiveWebClientFactory.java
@@ -0,0 +1,131 @@
+/*
+ * ============LICENSE_START=======================================================
+ * DCAEGEN2-SERVICES-SDK
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.sdk.rest.services.aai.client.service;
+
+import io.netty.handler.ssl.SslContext;
+import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration;
+
+import org.onap.dcaegen2.services.sdk.rest.services.ssl.SslFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.springframework.http.client.reactive.ClientHttpConnector;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+import reactor.netty.http.client.HttpClient;
+
+import javax.net.ssl.SSLException;
+import java.util.Map;
+
+import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.RESPONSE_CODE;
+import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.SERVICE_NAME;
+import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
+
+
+public class AaiReactiveWebClientFactory {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(AaiReactiveWebClientFactory.class);
+
+    private final String aaiUserName;
+    private final String aaiUserPassword;
+    private final Map<String, String> aaiHeaders;
+    private final Boolean enableAaiCertAuth;
+    private final String trustStorePath;
+    private final String trustStorePasswordPath;
+    private final String keyStorePath;
+    private final String keyStorePasswordPath;
+    private final SslFactory sslFactory;
+
+    /**
+     * Creating AaiReactiveWebClientFactory.
+     *
+     * @param configuration - configuration object
+     * @param sslFactory - factory for ssl setup
+     */
+    public AaiReactiveWebClientFactory(SslFactory sslFactory, AaiClientConfiguration configuration) {
+        this.aaiUserName = configuration.aaiUserName();
+        this.aaiUserPassword = configuration.aaiUserPassword();
+        this.aaiHeaders = configuration.aaiHeaders();
+        this.trustStorePath = configuration.trustStorePath();
+        this.trustStorePasswordPath = configuration.trustStorePasswordPath();
+        this.keyStorePath = configuration.keyStorePath();
+        this.keyStorePasswordPath = configuration.keyStorePasswordPath();
+        this.enableAaiCertAuth = configuration.enableAaiCertAuth();
+        this.sslFactory = sslFactory;
+    }
+
+    /**
+     * Construct Reactive WebClient with appropriate settings.
+     *
+     * @return WebClient
+     */
+    public WebClient build() throws SSLException {
+        LOGGER.debug("Setting ssl context");
+        
+        SslContext sslContext = createSslContext();
+
+        
+        ClientHttpConnector reactorClientHttpConnector = new ReactorClientHttpConnector(
+            HttpClient.create().secure(sslContextSpec -> sslContextSpec.sslContext(sslContext)));
+
+        return WebClient.builder()
+            .clientConnector(reactorClientHttpConnector)
+            .defaultHeaders(httpHeaders -> httpHeaders.setAll(aaiHeaders))
+            .filter(basicAuthentication(aaiUserName, aaiUserPassword))
+            .filter(logRequest())
+            .filter(logResponse())
+            .build();
+    }
+
+    private SslContext createSslContext() throws SSLException {
+        if (enableAaiCertAuth) {
+            return sslFactory.createSecureContext(
+                keyStorePath,
+                keyStorePasswordPath,
+                trustStorePath,
+                trustStorePasswordPath
+            );
+        }
+        return sslFactory.createInsecureContext();
+    }
+    
+    private ExchangeFilterFunction logRequest() {
+        return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
+            MDC.put(SERVICE_NAME, String.valueOf(clientRequest.url()));
+            LOGGER.info("Request: {} {}", clientRequest.method(), clientRequest.url());
+            clientRequest.headers()
+                .forEach((name, values) -> values.forEach(value -> LOGGER.info("{}={}", name, value)));
+            MDC.remove(SERVICE_NAME);
+            return Mono.just(clientRequest);
+        });
+    }
+
+    private ExchangeFilterFunction logResponse() {
+        return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
+            MDC.put(RESPONSE_CODE, String.valueOf(clientResponse.statusCode()));
+            LOGGER.info("Response Status {}", clientResponse.statusCode());
+            MDC.remove(RESPONSE_CODE);
+            return Mono.just(clientResponse);
+        });
+    }
+}
diff --git a/rest-services/aai-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/http/patch/AaiReactiveHttpPatchClient.java b/rest-services/aai-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/http/patch/AaiReactiveHttpPatchClient.java
new file mode 100644
index 0000000..8b231a4
--- /dev/null
+++ b/rest-services/aai-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/http/patch/AaiReactiveHttpPatchClient.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * DCAEGEN2-SERVICES-SDK
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.patch;
+
+
+import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.model.ConsumerDmaapModel;
+import org.slf4j.MDC;
+import org.springframework.web.reactive.function.client.ClientResponse;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+import reactor.core.publisher.Mono;
+
+import java.net.URI;
+import java.util.UUID;
+
+
+import static org.onap.dcaegen2.services.sdk.rest.services.model.CommonFunctions.createJsonBody;
+import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.REQUEST_ID;
+import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.X_INVOCATION_ID;
+import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.X_ONAP_REQUEST_ID;
+
+
+public class AaiReactiveHttpPatchClient {
+
+    private WebClient webClient;
+    private final String aaiHost;
+    private final String aaiProtocol;
+    private final Integer aaiHostPortNumber;
+    private final String aaiBasePath;
+    private final String aaiPnfPath;
+
+    /**
+     * Constructor of AaiProducerReactiveHttpClient.
+     *
+     * @param configuration - AAI producer configuration object
+     */
+    public AaiReactiveHttpPatchClient(AaiClientConfiguration configuration) {
+        this.aaiHost = configuration.aaiHost();
+        this.aaiProtocol = configuration.aaiProtocol();
+        this.aaiHostPortNumber = configuration.aaiPort();
+        this.aaiBasePath = configuration.aaiBasePath();
+        this.aaiPnfPath = configuration.aaiPnfPath();
+    }
+
+    /**
+     * Function for calling AAI Http producer - patch request to AAI database.
+     *
+     * @param consumerDmaapModelMono - object which will be sent to AAI database
+     * @return status code of operation
+     */
+    public Mono<ClientResponse> getAaiProducerResponse(ConsumerDmaapModel consumerDmaapModelMono) {
+        return patchAaiRequest(consumerDmaapModelMono);
+    }
+
+    public AaiReactiveHttpPatchClient createAaiWebClient(WebClient webClient) {
+        this.webClient = webClient;
+        return this;
+    }
+
+    private Mono<ClientResponse> patchAaiRequest(ConsumerDmaapModel dmaapModel) {
+        return
+            webClient.patch()
+                .uri(getUri(dmaapModel.getCorrelationId()))
+                .header(X_ONAP_REQUEST_ID, MDC.get(REQUEST_ID))
+                .header(X_INVOCATION_ID, UUID.randomUUID().toString())
+                .body(Mono.just(createJsonBody(dmaapModel)), String.class)
+                .exchange();
+    }
+
+    URI getUri(String pnfName) {
+        return new DefaultUriBuilderFactory().builder().scheme(aaiProtocol).host(aaiHost).port(aaiHostPortNumber)
+            .path(aaiBasePath + aaiPnfPath + "/" + pnfName).build();
+    }
+}
\ No newline at end of file
diff --git a/rest-services/aai-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/AaiReactiveWebClientFactoryTest.java b/rest-services/aai-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/AaiReactiveWebClientFactoryTest.java
new file mode 100644
index 0000000..c732316
--- /dev/null
+++ b/rest-services/aai-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/AaiReactiveWebClientFactoryTest.java
@@ -0,0 +1,73 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * DCAEGEN2-SERVICES-SDK
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+
+package org.onap.dcaegen2.services.sdk.rest.services.aai.client.service;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.ssl.SslFactory;
+
+import javax.net.ssl.SSLException;
+
+
+
+class AaiReactiveWebClientFactoryTest {
+
+    private static final String TRUST_STORE_PATH = "trust_store_path";
+    private static final String TRUST_STORE_PASS_PATH = "trust_store_pass_path";
+    private static final String KEY_STORE_PATH = "key_store_path";
+    private static final String KEY_STORE_PASS_PATH = "key_store_pass_path";
+    private SslFactory sslFactory = mock(SslFactory.class);
+    private AaiClientConfiguration aaiClientConfiguration = mock(AaiClientConfiguration.class);
+    private AaiReactiveWebClientFactory aaiReactiveWebClientFactory;
+
+    @Test
+    void shouldCreateWebClientWithSecureSslContext() throws SSLException {
+        givenEnabledAaiCertAuthConfiguration();
+        aaiReactiveWebClientFactory = new AaiReactiveWebClientFactory(sslFactory, aaiClientConfiguration);
+
+        Assertions.assertNotNull(aaiReactiveWebClientFactory.build());
+        verify(sslFactory).createSecureContext(KEY_STORE_PATH, KEY_STORE_PASS_PATH,
+                TRUST_STORE_PATH, TRUST_STORE_PASS_PATH);
+    }
+
+    @Test
+    void shouldCreateWebClientWithInsecureSslContext() throws SSLException {
+        when(aaiClientConfiguration.enableAaiCertAuth()).thenReturn(false);
+        aaiReactiveWebClientFactory = new AaiReactiveWebClientFactory(sslFactory, aaiClientConfiguration);
+
+        Assertions.assertNotNull(aaiReactiveWebClientFactory.build());
+        verify(sslFactory).createInsecureContext();
+    }
+
+    private void givenEnabledAaiCertAuthConfiguration() {
+        when(aaiClientConfiguration.enableAaiCertAuth()).thenReturn(true);
+        when(aaiClientConfiguration.trustStorePath()).thenReturn(TRUST_STORE_PATH);
+        when(aaiClientConfiguration.trustStorePasswordPath()).thenReturn(TRUST_STORE_PASS_PATH);
+        when(aaiClientConfiguration.keyStorePath()).thenReturn(KEY_STORE_PATH);
+        when(aaiClientConfiguration.keyStorePasswordPath()).thenReturn(KEY_STORE_PASS_PATH);
+    }
+}
diff --git a/rest-services/aai-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/http/patch/AaiReactiveHttpPatchClientTest.java b/rest-services/aai-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/http/patch/AaiReactiveHttpPatchClientTest.java
new file mode 100644
index 0000000..f3b4c5f
--- /dev/null
+++ b/rest-services/aai-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/aai/client/service/http/patch/AaiReactiveHttpPatchClientTest.java
@@ -0,0 +1,136 @@
+/*
+ * ============LICENSE_START=======================================================
+ * DCAEGEN2-SERVICES-SDK
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.patch;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.model.ConsumerDmaapModel;
+import org.onap.dcaegen2.services.sdk.rest.services.model.ImmutableConsumerDmaapModel;
+import org.springframework.web.reactive.function.client.ClientResponse;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
+
+
+class AaiReactiveHttpPatchClientTest {
+    private static final Integer SUCCESS_RESPONSE = 200;
+    private static AaiClientConfiguration aaiConfigurationMock = mock(AaiClientConfiguration.class);
+
+
+    private AaiReactiveHttpPatchClient httpClient;
+    private WebClient webClient;
+    private ConsumerDmaapModel dmaapModel;
+    private WebClient.RequestBodyUriSpec requestBodyUriSpec;
+    private WebClient.ResponseSpec responseSpec;
+
+    private Map<String, String> aaiHeaders;
+    private ClientResponse clientResponse;
+    private Mono<ClientResponse> clientResponseMono;
+
+    @BeforeEach
+    void setUp() {
+        setupHeaders();
+        clientResponse = mock(ClientResponse.class);
+        clientResponseMono = Mono.just(clientResponse);
+
+        dmaapModel = ImmutableConsumerDmaapModel.builder()
+                .correlationId("NOKnhfsadhff")
+                .ipv4("256.22.33.155")
+                .ipv6("200J:0db8:85a3:0000:0000:8a2e:0370:7334")
+                .build();
+
+        when(aaiConfigurationMock.aaiHost()).thenReturn("54.45.33.2");
+        when(aaiConfigurationMock.aaiProtocol()).thenReturn("https");
+        when(aaiConfigurationMock.aaiPort()).thenReturn(1234);
+        when(aaiConfigurationMock.aaiUserName()).thenReturn("PRH");
+        when(aaiConfigurationMock.aaiUserPassword()).thenReturn("PRH");
+        when(aaiConfigurationMock.aaiBasePath()).thenReturn("/aai/v11");
+        when(aaiConfigurationMock.aaiPnfPath()).thenReturn("/network/pnfs/pnf");
+        when(aaiConfigurationMock.aaiHeaders()).thenReturn(aaiHeaders);
+
+        httpClient = new AaiReactiveHttpPatchClient(aaiConfigurationMock);
+
+        webClient = spy(WebClient.builder()
+                .defaultHeaders(httpHeaders -> httpHeaders.setAll(aaiHeaders))
+                .filter(basicAuthentication(aaiConfigurationMock.aaiUserName(), aaiConfigurationMock.aaiUserPassword()))
+                .build());
+
+        requestBodyUriSpec = mock(WebClient.RequestBodyUriSpec.class);
+        responseSpec = mock(WebClient.ResponseSpec.class);
+    }
+
+    @Test
+    void getAaiProducerResponse_shouldReturn200() {
+        //given
+        Mono<Integer> expectedResult = Mono.just(SUCCESS_RESPONSE);
+
+        //when
+        mockWebClientDependantObject();
+        doReturn(expectedResult).when(responseSpec).bodyToMono(Integer.class);
+        httpClient.createAaiWebClient(webClient);
+
+        //then
+        StepVerifier.create(httpClient.getAaiProducerResponse(dmaapModel)).expectSubscription()
+                .expectNextMatches(results -> {
+                    Assertions.assertEquals(results, clientResponse);
+                    return true;
+                }).verifyComplete();
+    }
+
+
+    @Test
+    void getAppropriateUri_whenPassingCorrectedPathForPnf() {
+        Assertions.assertEquals(httpClient.getUri("NOKnhfsadhff"),
+                URI.create("https://54.45.33.2:1234/aai/v11/network/pnfs/pnf/NOKnhfsadhff"));
+    }
+
+
+    private void setupHeaders() {
+        aaiHeaders = new HashMap<>();
+        aaiHeaders.put("X-FromAppId", "PRH");
+        aaiHeaders.put("X-TransactionId", "vv-temp");
+        aaiHeaders.put("Accept", "application/json");
+        aaiHeaders.put("Real-Time", "true");
+        aaiHeaders.put("Content-Type", "application/merge-patch+json");
+    }
+
+    private void mockWebClientDependantObject() {
+        WebClient.RequestHeadersSpec requestHeadersSpec = mock(WebClient.RequestHeadersSpec.class);
+        when(webClient.patch()).thenReturn(requestBodyUriSpec);
+        when(requestBodyUriSpec.uri((URI) any())).thenReturn(requestBodyUriSpec);
+        when(requestBodyUriSpec.header(any(), any())).thenReturn(requestBodyUriSpec);
+        when(requestBodyUriSpec.body(any(), (Class<Object>) any())).thenReturn(requestHeadersSpec);
+        when(requestHeadersSpec.exchange()).thenReturn(clientResponseMono);
+    }
+}
diff --git a/rest-services/cbs-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/providers/ReactiveCloudConfigurationProvider.java b/rest-services/cbs-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/providers/ReactiveCloudConfigurationProvider.java
index 8807298..fdc966b 100644
--- a/rest-services/cbs-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/providers/ReactiveCloudConfigurationProvider.java
+++ b/rest-services/cbs-client/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/providers/ReactiveCloudConfigurationProvider.java
@@ -52,7 +52,7 @@
     @Override
     public Mono<JsonObject> callForServiceConfigurationReactive(EnvProperties envProperties) {
         return callConsulForConfigBindingServiceEndpoint(envProperties)
-            .flatMap(this::callConfigBindingServiceForPrhConfiguration);
+            .flatMap(this::callConfigBindingServiceForConfiguration);
     }
 
     @Override
@@ -82,8 +82,8 @@
             envProperties.cbsName());
     }
 
-    private Mono<JsonObject> callConfigBindingServiceForPrhConfiguration(String configBindingServiceUri) {
-        LOGGER.info("Retrieving PRH configuration");
+    private Mono<JsonObject> callConfigBindingServiceForConfiguration(String configBindingServiceUri) {
+        LOGGER.info("Retrieving configuration");
         return cloudHttpClient.callHttpGet(configBindingServiceUri, JsonObject.class);
     }
 
diff --git a/rest-services/cbs-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/providers/ReactiveCloudConfigurationProviderTest.java b/rest-services/cbs-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/providers/ReactiveCloudConfigurationProviderTest.java
index afc5a25..5d6ef6b 100644
--- a/rest-services/cbs-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/providers/ReactiveCloudConfigurationProviderTest.java
+++ b/rest-services/cbs-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/providers/ReactiveCloudConfigurationProviderTest.java
@@ -52,8 +52,8 @@
         + "\"CreateIndex\":803,\"ModifyIndex\":803}]";
     private static final JsonArray configBindingServiceJson = gson.fromJson(configBindingService, JsonArray.class);
     private static final JsonArray emptyConfigBindingServiceJson = gson.fromJson("[]", JsonArray.class);
-    private static final String prhMockConfiguration = "{\"test\":1}";
-    private static final JsonObject prhMockConfigurationJson = gson.fromJson(prhMockConfiguration, JsonObject.class);
+    private static final String configurationMock = "{\"test\":1}";
+    private static final JsonObject configurationJsonMock = gson.fromJson(configurationMock, JsonObject.class);
 
     private EnvProperties envProperties = ImmutableEnvProperties.builder()
         .appName("dcae-prh")
@@ -70,13 +70,13 @@
             webClient.callHttpGet("http://consul:8500/v1/catalog/service/config-binding-service", JsonArray.class))
             .thenReturn(Mono.just(configBindingServiceJson));
         when(webClient.callHttpGet("http://config-binding-service:10000/service_component/dcae-prh", JsonObject.class))
-            .thenReturn(Mono.just(prhMockConfigurationJson));
+            .thenReturn(Mono.just(configurationJsonMock));
 
         ReactiveCloudConfigurationProvider provider = new ReactiveCloudConfigurationProvider(webClient);
 
         //when/then
         StepVerifier.create(provider.callForServiceConfigurationReactive(envProperties)).expectSubscription()
-            .expectNext(prhMockConfigurationJson).verifyComplete();
+            .expectNext(configurationJsonMock).verifyComplete();
     }
 
     @Test
diff --git a/rest-services/common-dependency/pom.xml b/rest-services/common-dependency/pom.xml
new file mode 100644
index 0000000..7289514
--- /dev/null
+++ b/rest-services/common-dependency/pom.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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.dcaegen2.services.sdk</groupId>
+        <artifactId>dcaegen2-services-sdk-rest-services</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId>
+    <artifactId>common-dependency</artifactId>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <name>dcaegen2-services-sdk-rest-services-common-dependency</name>
+    <description>Common functionality in the project</description>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.projectreactor.netty</groupId>
+            <artifactId>reactor-netty</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.immutables</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.immutables</groupId>
+            <artifactId>value</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jul-to-slf4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>log4j-over-slf4j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+        </dependency>
+
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/model/CommonFunctions.java b/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/model/CommonFunctions.java
new file mode 100644
index 0000000..55b12e0
--- /dev/null
+++ b/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/model/CommonFunctions.java
@@ -0,0 +1,46 @@
+/*
+ * ============LICENSE_START=======================================================
+ * DCAEGEN2-SERVICES-SDK
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.sdk.rest.services.model;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.TypeAdapterFactory;
+
+import java.util.ServiceLoader;
+
+
+public class CommonFunctions {
+
+    private CommonFunctions() {
+    }
+
+    /**
+     * Method for serialization object by GSON.
+     *
+     * @param consumerDmaapModel - object which will be serialized
+     * @return string from serialization
+     */
+    public static String createJsonBody(ConsumerDmaapModel consumerDmaapModel) {
+        GsonBuilder gsonBuilder = new GsonBuilder();
+        ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory);
+        return gsonBuilder.create().toJson(ImmutableConsumerDmaapModel.builder().ipv4(consumerDmaapModel.getIpv4())
+            .ipv6(consumerDmaapModel.getIpv6()).correlationId(consumerDmaapModel.getCorrelationId()).build());
+    }
+}
\ No newline at end of file
diff --git a/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/model/ConsumerDmaapModel.java b/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/model/ConsumerDmaapModel.java
new file mode 100644
index 0000000..1bf9ff6
--- /dev/null
+++ b/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/model/ConsumerDmaapModel.java
@@ -0,0 +1,43 @@
+/*
+ * ============LICENSE_START=======================================================
+ * DCAEGEN2-SERVICES-SDK
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.sdk.rest.services.model;
+
+import com.google.gson.annotations.SerializedName;
+import org.immutables.gson.Gson;
+import org.immutables.value.Value;
+
+/**
+ * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/8/18
+ */
+
+@Value.Immutable
+@Gson.TypeAdapters(fieldNamingStrategy = true)
+public interface ConsumerDmaapModel {
+
+    @SerializedName(value = "correlationId", alternate = "correlationId")
+    String getCorrelationId();
+
+    @SerializedName(value = "ipaddress-v4-oam", alternate = "ipaddress-v4-oam")
+    String getIpv4();
+
+    @SerializedName(value = "ipaddress-v6-oam", alternate = "ipaddress-v6-oam")
+    String getIpv6();
+}
diff --git a/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/model/logging/MdcVariables.java b/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/model/logging/MdcVariables.java
new file mode 100644
index 0000000..22090e9
--- /dev/null
+++ b/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/model/logging/MdcVariables.java
@@ -0,0 +1,45 @@
+/*
+ * ============LICENSE_START=======================================================
+ * DCAEGEN2-SERVICES-SDK
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.sdk.rest.services.model.logging;
+
+import org.slf4j.MDC;
+
+import java.util.Map;
+
+public final class MdcVariables {
+
+    public static final String X_ONAP_REQUEST_ID = "X-ONAP-RequestID";
+    public static final String X_INVOCATION_ID = "X-InvocationID";
+    public static final String REQUEST_ID = "RequestID";
+    public static final String INVOCATION_ID = "InvocationID";
+    public static final String INSTANCE_UUID = "InstanceUUID";
+    public static final String RESPONSE_CODE = "ResponseCode";
+    public static final String SERVICE_NAME = "ServiceName";
+
+    private MdcVariables() {
+    }
+
+    public static void setMdcContextMap(Map<String, String> mdcContextMap) {
+        if (mdcContextMap != null) {
+            MDC.setContextMap(mdcContextMap);
+        }
+    }
+}
diff --git a/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/ssl/SslFactory.java b/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/ssl/SslFactory.java
new file mode 100644
index 0000000..cce811c
--- /dev/null
+++ b/rest-services/common-dependency/src/main/java/org/onap/dcaegen2/services/sdk/rest/services/ssl/SslFactory.java
@@ -0,0 +1,112 @@
+/*
+ * ============LICENSE_START=======================================================
+ * DCAEGEN2-SERVICES-SDK
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.sdk.rest.services.ssl;
+
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+
+public class SslFactory {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SslFactory.class);
+
+    /**
+     * Function for creating secure ssl context.
+     *
+     * @param keyStorePath - path to file with keystore
+     * @param keyStorePasswordPath - path to file with keystore password
+     * @param trustStorePath - path to file with truststore
+     * @param trustStorePasswordPath - path to file with truststore password
+     * @return configured ssl context
+     */
+    public SslContext createSecureContext(String keyStorePath,
+        String keyStorePasswordPath,
+        String trustStorePath,
+        String trustStorePasswordPath) throws SSLException {
+        LOGGER.info("Creating secure ssl context for: {} {}", keyStorePath, trustStorePath);
+        try {
+            return SslContextBuilder
+                .forClient()
+                .keyManager(keyManagerFactory(keyStorePath, loadPasswordFromFile(keyStorePasswordPath)))
+                .trustManager(trustManagerFactory(trustStorePath, loadPasswordFromFile(trustStorePasswordPath)))
+                .build();
+        } catch (GeneralSecurityException | IOException ex) {
+            throw new SSLException(ex);
+        }
+    }
+
+    /**
+     * Function for creating insecure ssl context.
+     *
+     * @return configured insecure ssl context
+     */
+    public SslContext createInsecureContext() throws SSLException {
+        LOGGER.info("Creating insecure ssl context");
+        return SslContextBuilder
+            .forClient()
+            .trustManager(InsecureTrustManagerFactory.INSTANCE)
+            .build();
+    }
+
+    private KeyManagerFactory keyManagerFactory(String path, String password)
+            throws GeneralSecurityException, IOException {
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+        kmf.init(loadKeyStoreFromFile(path, password),
+            password.toCharArray());
+        return kmf;
+    }
+
+    private TrustManagerFactory trustManagerFactory(String path, String password)
+            throws GeneralSecurityException, IOException {
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        tmf.init(loadKeyStoreFromFile(path, password));
+        return tmf;
+    }
+
+    private KeyStore loadKeyStoreFromFile(String path, String keyStorePassword)
+            throws GeneralSecurityException, IOException {
+        KeyStore ks = KeyStore.getInstance("jks");
+        ks.load(getResource(path), keyStorePassword.toCharArray());
+        return ks;
+    }
+
+    private InputStream getResource(String path) throws FileNotFoundException {
+        return new FileInputStream(path);
+    }
+
+    private String loadPasswordFromFile(String path) throws IOException {
+        return new String(Files.readAllBytes(Paths.get(path)));
+    }
+}
diff --git a/rest-services/pom.xml b/rest-services/pom.xml
index 4f42d0a..a363dc8 100644
--- a/rest-services/pom.xml
+++ b/rest-services/pom.xml
@@ -20,8 +20,10 @@
   <packaging>pom</packaging>
 
   <modules>
+    <module>common-dependency</module>
     <module>aai-client</module>
     <module>cbs-client</module>
     <module>dmaap-client</module>
+
   </modules>
 </project>