Implementation for HTTP/HTTPS and endpoints 13/43513/6
authorwasala <przemyslaw.wasala@nokia.com>
Wed, 18 Apr 2018 13:21:56 +0000 (15:21 +0200)
committerwasala <przemyslaw.wasala@nokia.com>
Fri, 20 Apr 2018 09:26:33 +0000 (11:26 +0200)
*Added HTTP/HTTPS in spring configuration
*Fixing issues with license
*Fixing HTTP/HTTPS and logging configuration
*Add Webflux in implementation

Change-Id: I0a7add391cde010d56dbf352de365b1eba90a9cd
Issue-ID: DCAEGEN2-453
Signed-off-by: wasala <przemyslaw.wasala@nokia.com>
15 files changed:
pom.xml
prh-app-server/config/application.yaml
prh-app-server/config/keystore [new file with mode: 0644]
prh-app-server/pom.xml
prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/MainApp.java
prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfig.java
prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/TomcatHttpConfig.java [new file with mode: 0644]
prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/HeartbeatController.java [new file with mode: 0644]
prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/ScheduleController.java
prh-app-server/src/main/resources/application.properties [new file with mode: 0644]
prh-app-server/src/main/resources/keystore.jks [new file with mode: 0644]
prh-app-server/src/main/resources/keystore.jks.old [new file with mode: 0644]
prh-app-server/src/main/resources/logback-spring.xml [moved from prh-app-server/src/main/resources/logback.xml with 100% similarity]
prh-app-server/src/main/resources/scheduled-context.xml
prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/IT/ScheduledXmlContextITest.java

diff --git a/pom.xml b/pom.xml
index 8c652d4..f4514bf 100644 (file)
--- a/pom.xml
+++ b/pom.xml
         <artifactId>gson</artifactId>
         <version>${immutable.version}</version>
       </dependency>
+      <dependency>
+        <groupId>io.projectreactor</groupId>
+        <artifactId>reactor-bom</artifactId>
+        <version>Bismuth-RELEASE</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
       <dependency>
         <groupId>com.spotify</groupId>
         <artifactId>docker-maven-plugin</artifactId>
index 0baa1f9..306c94f 100644 (file)
@@ -2,7 +2,13 @@ spring:
   profiles:
     active: prod
 server:
-  port: 8100
+  port: 8433
+  ssl:
+    key-store-type: PKCS12
+    key-store-password: nokiapnf
+    key-store: classpath:keystore.jks
+    key-password: nokiapnf
+    keyAlias: tomcat-localhost
 logging:
   level:
     ROOT: ERROR
diff --git a/prh-app-server/config/keystore b/prh-app-server/config/keystore
new file mode 100644 (file)
index 0000000..26a16f7
Binary files /dev/null and b/prh-app-server/config/keystore differ
index f178d34..e804c3e 100644 (file)
@@ -79,6 +79,7 @@
           </resources>
           <exposes>
             <expose>8100</expose>
+            <expose>8433</expose>
           </exposes>
           <imageTags>
             <imageTag>${project.version}-SNAPSHOT-${maven.build.timestamp}Z</imageTag>
         </exclusion>
       </exclusions>
     </dependency>
+    <dependency>
+      <groupId>io.projectreactor</groupId>
+      <artifactId>reactor-core</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.bouncycastle</groupId>
       <artifactId>bcprov-jdk15on</artifactId>
     </dependency>
 
     <!--TESTS DEPENDENCIES -->
+    <dependency>
+      <groupId>io.projectreactor</groupId>
+      <artifactId>reactor-test</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter-engine</artifactId>
index fd86448..5d60208 100644 (file)
@@ -27,7 +27,6 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.scheduling.TaskScheduler;
-import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
 
 /**
@@ -36,7 +35,6 @@ import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
 @SpringBootApplication
 @Configuration
 @ComponentScan
-@EnableScheduling
 @EnableAutoConfiguration(exclude = {JacksonAutoConfiguration.class})
 public class MainApp {
 
index 6f077a3..1bd90ee 100644 (file)
@@ -19,9 +19,6 @@
  */
 package org.onap.dcaegen2.services.prh.configuration;
 
-import static org.apache.tomcat.util.file.ConfigFileLoader.getInputStream;
-
-import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/TomcatHttpConfig.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/TomcatHttpConfig.java
new file mode 100644 (file)
index 0000000..0e9d7fe
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * 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.prh.configuration;
+
+import org.apache.catalina.connector.Connector;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/18/18
+ */
+@Configuration
+public class TomcatHttpConfig {
+
+    @Bean
+    public ServletWebServerFactory servletContainer() {
+        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
+        tomcat.addAdditionalTomcatConnectors(getHttpConnector());
+        return tomcat;
+    }
+
+    private Connector getHttpConnector() {
+        Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
+        connector.setScheme("http");
+        connector.setPort(8100);
+        connector.setSecure(false);
+        return connector;
+    }
+
+}
diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/HeartbeatController.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/HeartbeatController.java
new file mode 100644 (file)
index 0000000..95b360e
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * 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.prh.controllers;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import org.onap.dcaegen2.services.prh.configuration.PrhAppConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Mono;
+
+/**
+ * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/19/18
+ */
+@RestController
+public class HeartbeatController {
+
+    private static final Logger logger = LoggerFactory.getLogger(PrhAppConfig.class);
+    private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
+
+    @RequestMapping(value = "heartbeat", method = RequestMethod.GET)
+    public Mono<ResponseEntity<String>> heartbeat() {
+        logger.debug("Receiving request on on thread={} , time={} ", Thread.currentThread().getName(),
+            dateTimeFormatter.format(
+                LocalDateTime.now()));
+
+        return Mono.defer(() -> {
+            logger.debug("Sending response on thread={} , time={} ", Thread.currentThread().getName(),
+                dateTimeFormatter.format(
+                    LocalDateTime.now()));
+            return Mono.just(new ResponseEntity<>("I'm living", HttpStatus.OK));
+        });
+    }
+}
index 99516c4..6f08dd8 100644 (file)
  */
 package org.onap.dcaegen2.services.prh.controllers;
 
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.ScheduledFuture;
+import org.onap.dcaegen2.services.prh.configuration.PrhAppConfig;
 import org.onap.dcaegen2.services.prh.tasks.ScheduledTasks;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.scheduling.TaskScheduler;
 import org.springframework.stereotype.Component;
-import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Mono;
 
 /**
  * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/5/18
  */
-@Controller
+@RestController
 @Component
 public class ScheduleController {
 
+    private static final Logger logger = LoggerFactory.getLogger(PrhAppConfig.class);
+    private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
     private static final int SCHEDULING_DELAY = 20000;
+    private static volatile List<ScheduledFuture> scheduledFutureList = new ArrayList<>();
 
     private final TaskScheduler taskScheduler;
     private final ScheduledTasks scheduledTask;
 
-    private ScheduledFuture<?> scheduledFuture;
 
     @Autowired
     public ScheduleController(TaskScheduler taskScheduler, ScheduledTasks scheduledTask) {
@@ -50,18 +60,54 @@ public class ScheduleController {
         this.scheduledTask = scheduledTask;
     }
 
+    @RequestMapping(value = "start", method = RequestMethod.GET)
+    public Mono<ResponseEntity<String>> startTasks() {
+        logDebug("Starting scheduling worker request on on thread={} , time={} ");
+        return Mono.fromSupplier(this::tryToStartTask).map(this::createStartTaskResponse);
+    }
+
+    @RequestMapping(value = "stopPrh", method = RequestMethod.GET)
+    public Mono<ResponseEntity<String>> stopTask() {
+        logDebug("Stopping scheduling worker request on on thread={} , time={} ");
+        return getResponseFromCancellationOfTasks();
+    }
 
-    @RequestMapping(value = "preferences", method = RequestMethod.PUT)
-    public ResponseEntity<Void> startTask() {
-        scheduledFuture = taskScheduler
-            .scheduleWithFixedDelay(scheduledTask::scheduleMainPrhEventTask, SCHEDULING_DELAY);
-        return new ResponseEntity<>(HttpStatus.OK);
+    private synchronized Mono<ResponseEntity<String>> getResponseFromCancellationOfTasks() {
+        scheduledFutureList.forEach(x -> x.cancel(false));
+        scheduledFutureList.clear();
+        return Mono.defer(() -> {
+            logDebug("Sending success response on stopping task execution thread={} , time={} ");
+            return Mono.just(new ResponseEntity<>("PRH Service has already been stopped!", HttpStatus.CREATED));
+        });
     }
 
-    @RequestMapping("stopPrh")
-    public ResponseEntity<Void> stopTask() {
-        scheduledFuture.cancel(false);
-        return new ResponseEntity<>(HttpStatus.OK);
+    private synchronized boolean tryToStartTask() {
+        if (scheduledFutureList.isEmpty()) {
+            scheduledFutureList.add(taskScheduler
+                .scheduleWithFixedDelay(scheduledTask::scheduleMainPrhEventTask, SCHEDULING_DELAY));
+            return true;
+        } else {
+            return false;
+        }
+
     }
 
+    private ResponseEntity<String> createStartTaskResponse(boolean wasScheduled) {
+        if (wasScheduled) {
+            logDebug("Sending success response on starting task execution thread={} , time={} ");
+            return new ResponseEntity<>("PRH Service has been started!", HttpStatus.CREATED);
+        } else {
+            logDebug("Sending error response on starting task execution thread={} , time={} ");
+            return new ResponseEntity<>("PRH Service is still running!", HttpStatus.NOT_ACCEPTABLE);
+        }
+    }
+
+    private static void logDebug(String message) {
+        if (logger.isDebugEnabled()) {
+            logger.debug(message,
+                Thread.currentThread().getName(),
+                dateTimeFormatter.format(
+                    LocalDateTime.now()));
+        }
+    }
 }
diff --git a/prh-app-server/src/main/resources/application.properties b/prh-app-server/src/main/resources/application.properties
new file mode 100644 (file)
index 0000000..53fa9cd
--- /dev/null
@@ -0,0 +1,13 @@
+spring.profiles.active=prod
+server.port=8433
+server.ssl.key-store-type=PKCS12
+server.ssl.key-store-password=nokiapnf
+server.ssl.key-store=classpath:keystore.jks
+server.ssl.key-password=nokiapnf
+server.ssl.key-alias=tomcat-localhost
+logging.level.root=ERROR
+logging.level.org.springframework=ERROR
+logging.level.org.springframework.data=ERROR
+logging.level.org.onap.dcaegen2.services.prh=INFO
+logging.file=logs/log/application.log
+app.filepath=config/prh_endpoints.json
diff --git a/prh-app-server/src/main/resources/keystore.jks b/prh-app-server/src/main/resources/keystore.jks
new file mode 100644 (file)
index 0000000..cd27cc0
Binary files /dev/null and b/prh-app-server/src/main/resources/keystore.jks differ
diff --git a/prh-app-server/src/main/resources/keystore.jks.old b/prh-app-server/src/main/resources/keystore.jks.old
new file mode 100644 (file)
index 0000000..8a2b4f9
Binary files /dev/null and b/prh-app-server/src/main/resources/keystore.jks.old differ
index d1c80ca..91919aa 100644 (file)
@@ -10,7 +10,7 @@
   <context:component-scan
     base-package="org.onap.dcaegen2.services.prh"/>
   <task:scheduled-tasks>
-    <task:scheduled ref="scheduleController" method="startTask"
+    <task:scheduled ref="scheduleController" method="startTasks"
       fixed-rate="1000"/>
   </task:scheduled-tasks>
 </beans>
index c8ed88d..faecec4 100644 (file)
@@ -23,13 +23,18 @@ import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.onap.dcaegen2.services.prh.IT.junit5.mockito.MockitoExtension;
 import org.onap.dcaegen2.services.prh.configuration.PrhAppConfig;
+import org.onap.dcaegen2.services.prh.exceptions.PrhTaskException;
 import org.onap.dcaegen2.services.prh.tasks.ScheduledTasks;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;