CBS configuration fetching 31/114631/3
authorBogumil Zebek <bogumil.zebek@nokia.com>
Thu, 5 Nov 2020 14:14:02 +0000 (15:14 +0100)
committerZebek Bogumil <bogumil.zebek@nokia.com>
Fri, 6 Nov 2020 10:41:01 +0000 (11:41 +0100)
- Fix deadlock problem which occurs during starting application

Change-Id: I9103f0efd7caa105727f4814532934881335190f
Issue-ID: DCAEGEN2-2495
Signed-off-by: Zebek Bogumil <bogumil.zebek@nokia.com>
src/main/java/org/onap/dcae/ApplicationSettings.java
src/main/java/org/onap/dcae/VesApplication.java
src/main/java/org/onap/dcae/common/publishing/DMaaPEventPublisher.java
src/main/java/org/onap/dcae/configuration/ConfigFilesFacade.java
src/main/java/org/onap/dcae/configuration/ConfigUpdater.java

index 9462a38..7bdef65 100644 (file)
@@ -80,7 +80,10 @@ public class ApplicationSettings {
         eventTransformations = loadEventTransformations();
     }
 
-    public void reloadProperties() {
+    /**
+     * Reload application settings.
+     */
+    public void reload() {
         try {
             properties.load(configurationFileLocation);
             properties.refresh();
index ec04157..f8cd74a 100644 (file)
@@ -46,6 +46,7 @@ import org.springframework.context.annotation.Lazy;
 import java.nio.file.Paths;
 import java.time.Duration;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.locks.ReentrantLock;
 
 @SpringBootApplication(exclude = {GsonAutoConfiguration.class, SecurityAutoConfiguration.class})
 public class VesApplication {
@@ -59,45 +60,63 @@ public class VesApplication {
     private static ConfigUpdater configUpdater;
     private static DMaaPEventPublisher eventPublisher;
     private static ApplicationConfigurationListener applicationConfigurationListener;
+    private static ReentrantLock applicationLock = new ReentrantLock();
 
     public static void main(String[] args) {
+        applicationLock.lock();
+        try {
+            startApplication(args);
+            startListeningForApplicationConfigurationStoredInConsul();
+        } finally {
+            applicationLock.unlock();
+        }
+    }
+
+    private static void startApplication(String[] args) {
         SpringApplication app = new SpringApplication(VesApplication.class);
         applicationSettings = new ApplicationSettings(args, CLIUtils::processCmdLine);
-        init();
-
-        applicationConfigurationListener = startListeningForApplicationConfigurationStoredInConsul();
-
+        configUpdater = ConfigUpdaterFactory.create(
+                applicationSettings.configurationFileLocation(),
+                Paths.get(applicationSettings.dMaaPConfigurationFileLocation()));
+        eventPublisher = new DMaaPEventPublisher(getDmaapConfig());
         app.setAddCommandLineProperties(true);
         context = app.run();
     }
 
     public static void restartApplication() {
         Thread thread = new Thread(() -> {
-            context.close();
-            applicationSettings.reloadProperties();
-            applicationConfigurationListener.reload(Duration.ofMinutes(applicationSettings.configurationUpdateFrequency()));
-            init();
-            context = SpringApplication.run(VesApplication.class);
+            try {
+                applicationLock.lock();
+                reloadApplicationResources();
+                reloadSpringContext();
+            } finally {
+                applicationLock.unlock();
+            }
         });
         thread.setDaemon(false);
         thread.start();
     }
 
-    private static void init() {
-        configUpdater = ConfigUpdaterFactory.create(
-                applicationSettings.configurationFileLocation(),
+    private static void reloadApplicationResources() {
+        applicationSettings.reload();
+        eventPublisher.reload(getDmaapConfig());
+        configUpdater.setPaths(applicationSettings.configurationFileLocation(),
                 Paths.get(applicationSettings.dMaaPConfigurationFileLocation()));
-        eventPublisher = new DMaaPEventPublisher(getDmaapConfig());
+        applicationConfigurationListener.reload(Duration.ofMinutes(applicationSettings.configurationUpdateFrequency()));
     }
 
-    private static ApplicationConfigurationListener startListeningForApplicationConfigurationStoredInConsul() {
+    private static void reloadSpringContext() {
+        context.close();
+        context = SpringApplication.run(VesApplication.class);
+    }
+
+    private static void startListeningForApplicationConfigurationStoredInConsul() {
         ConfigurationHandler cbsHandler = new ConfigurationHandler(new CbsClientConfigurationProvider(), configUpdater);
         ApplicationConfigurationListener applicationConfigProvider = new ApplicationConfigurationListener(Duration.ofMinutes(DEFAULT_CONFIGURATION_FETCH_PERIOD), cbsHandler);
 
         ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
         scheduledThreadPoolExecutor.execute(applicationConfigProvider);
-
-        return applicationConfigProvider;
+        applicationConfigurationListener = applicationConfigProvider;
     }
 
     private static Map<String, PublisherConfig> getDmaapConfig() {
index 876c391..2b4cfc1 100644 (file)
@@ -42,7 +42,7 @@ import static org.onap.dcae.common.publishing.VavrUtils.f;
 public class DMaaPEventPublisher {
     private static final int PENDING_MESSAGE_LOG_THRESHOLD = 100;
     private static final Logger log = LoggerFactory.getLogger(DMaaPEventPublisher.class);
-    private final DMaaPPublishersCache publishersCache;
+    private DMaaPPublishersCache publishersCache;
     private final Logger outputLogger = LoggerFactory.getLogger("org.onap.dcae.common.output");
 
     DMaaPEventPublisher(DMaaPPublishersCache publishersCache) {
@@ -53,6 +53,14 @@ public class DMaaPEventPublisher {
         this(new DMaaPPublishersCache(dMaaPConfig));
     }
 
+    /**
+     * Reload Dmaap configuration
+     * @param dmaapConfiguration Dmaap configuration
+     */
+    public void reload(Map<String, PublisherConfig> dmaapConfiguration){
+        this.publishersCache = new DMaaPPublishersCache(dmaapConfiguration);
+    }
+
     public void sendEvent(VesEvent vesEvent, String dmaapId){
         clearVesUniqueIdFromEvent(vesEvent);
         publishersCache.getPublisher(dmaapId)
index c0280c7..c94e6c3 100644 (file)
@@ -40,16 +40,29 @@ import org.json.JSONObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-class ConfigFilesFacade {
+/**
+ * ConfigFilesFacade is used for reading and writing application properties and dmaap configuration.
+ */
+public class ConfigFilesFacade {
 
     private static final Logger log = LoggerFactory.getLogger(ConfigFilesFacade.class);
 
-    private final Path dMaaPConfigPath;
-    private final Path propertiesPath;
+    private Path dmaapConfigPath;
+    private Path propertiesPath;
 
     ConfigFilesFacade(Path propertiesPath, Path dMaaPConfigPath) {
         this.propertiesPath = propertiesPath;
-        this.dMaaPConfigPath = dMaaPConfigPath;
+        this.dmaapConfigPath = dMaaPConfigPath;
+    }
+
+    /**
+     * Set new paths
+     * @param propertiesFile application property file
+     * @param dmaapConfigFile dmaap configuration file
+     */
+    public void setPaths(Path propertiesFile, Path dmaapConfigFile) {
+        this.propertiesPath = propertiesFile;
+        this.dmaapConfigPath = dmaapConfigFile;
     }
 
     Try<Map<String, String>> readCollectorProperties() {
@@ -62,19 +75,19 @@ class ConfigFilesFacade {
     }
 
     Try<JSONObject> readDMaaPConfiguration() {
-        log.info(f("Reading DMaaP configuration from file: '%s'", dMaaPConfigPath));
-        return readFile(dMaaPConfigPath)
+        log.info(f("Reading DMaaP configuration from file: '%s'", dmaapConfigPath));
+        return readFile(dmaapConfigPath)
             .recover(FileNotFoundException.class, __ -> "{}")
-            .mapFailure(enhanceError("Unable to read DMaaP configuration from file '%s'", dMaaPConfigPath))
+            .mapFailure(enhanceError("Unable to read DMaaP configuration from file '%s'", dmaapConfigPath))
             .flatMap(Conversions::toJson)
             .onFailure(logError(log))
             .peek(props -> log.info(f("Read following DMaaP properties: '%s'", props)));
     }
 
     Try<Void> writeDMaaPConfiguration(JSONObject dMaaPConfiguration) {
-        log.info(f("Writing DMaaP configuration '%s' into file '%s'", dMaaPConfiguration, dMaaPConfigPath));
-        return writeFile(dMaaPConfigPath, indentConfiguration(dMaaPConfiguration.toString()))
-            .mapFailure(enhanceError("Could not save new DMaaP configuration to path '%s'", dMaaPConfigPath))
+        log.info(f("Writing DMaaP configuration '%s' into file '%s'", dMaaPConfiguration, dmaapConfigPath));
+        return writeFile(dmaapConfigPath, indentConfiguration(dMaaPConfiguration.toString()))
+            .mapFailure(enhanceError("Could not save new DMaaP configuration to path '%s'", dmaapConfigPath))
             .onFailure(logError(log))
             .peek(__ -> log.info("Written successfully"));
     }
@@ -127,4 +140,4 @@ class ConfigFilesFacade {
     private String indentConfiguration(String configuration) {
         return new JSONObject(configuration).toString(4);
     }
-}
\ No newline at end of file
+}
index eb1a1a5..930ec2c 100644 (file)
@@ -25,6 +25,8 @@ import org.json.JSONObject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.nio.file.Path;
+
 public class ConfigUpdater {
 
     private static final Logger log = LoggerFactory.getLogger(ConfigUpdater.class);
@@ -38,6 +40,15 @@ public class ConfigUpdater {
         this.isApplicationRestartNeeded = false;
     }
 
+    /**
+     * Set new paths
+     * @param propertiesFile application property file
+     * @param dmaapConfigFile dmaap configuration file
+     */
+    public void setPaths(Path propertiesFile, Path dmaapConfigFile){
+        this.configFilesFacade.setPaths(propertiesFile, dmaapConfigFile);
+
+    }
     public synchronized void updateConfig(Option<JSONObject> appConfig) {
         appConfig.peek(this::handleUpdate).onEmpty(logSkipMessage());
     }