From b937b203b9e3276041428c7090c41a58583bc3f6 Mon Sep 17 00:00:00 2001 From: Bogumil Zebek Date: Thu, 5 Nov 2020 15:14:02 +0100 Subject: CBS configuration fetching - Fix deadlock problem which occurs during starting application Change-Id: I9103f0efd7caa105727f4814532934881335190f Issue-ID: DCAEGEN2-2495 Signed-off-by: Zebek Bogumil (cherry picked from commit 266777f52144bc1e6110c18d34de612538b78b26) --- .../java/org/onap/dcae/ApplicationSettings.java | 5 ++- src/main/java/org/onap/dcae/VesApplication.java | 51 +++++++++++++++------- .../common/publishing/DMaaPEventPublisher.java | 10 ++++- .../onap/dcae/configuration/ConfigFilesFacade.java | 35 ++++++++++----- .../org/onap/dcae/configuration/ConfigUpdater.java | 11 +++++ 5 files changed, 83 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/onap/dcae/ApplicationSettings.java b/src/main/java/org/onap/dcae/ApplicationSettings.java index 9462a380..7bdef655 100644 --- a/src/main/java/org/onap/dcae/ApplicationSettings.java +++ b/src/main/java/org/onap/dcae/ApplicationSettings.java @@ -80,7 +80,10 @@ public class ApplicationSettings { eventTransformations = loadEventTransformations(); } - public void reloadProperties() { + /** + * Reload application settings. + */ + public void reload() { try { properties.load(configurationFileLocation); properties.refresh(); diff --git a/src/main/java/org/onap/dcae/VesApplication.java b/src/main/java/org/onap/dcae/VesApplication.java index ec04157f..f8cd74ad 100644 --- a/src/main/java/org/onap/dcae/VesApplication.java +++ b/src/main/java/org/onap/dcae/VesApplication.java @@ -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 getDmaapConfig() { diff --git a/src/main/java/org/onap/dcae/common/publishing/DMaaPEventPublisher.java b/src/main/java/org/onap/dcae/common/publishing/DMaaPEventPublisher.java index 876c391b..2b4cfc15 100644 --- a/src/main/java/org/onap/dcae/common/publishing/DMaaPEventPublisher.java +++ b/src/main/java/org/onap/dcae/common/publishing/DMaaPEventPublisher.java @@ -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 dmaapConfiguration){ + this.publishersCache = new DMaaPPublishersCache(dmaapConfiguration); + } + public void sendEvent(VesEvent vesEvent, String dmaapId){ clearVesUniqueIdFromEvent(vesEvent); publishersCache.getPublisher(dmaapId) diff --git a/src/main/java/org/onap/dcae/configuration/ConfigFilesFacade.java b/src/main/java/org/onap/dcae/configuration/ConfigFilesFacade.java index c0280c75..c94e6c30 100644 --- a/src/main/java/org/onap/dcae/configuration/ConfigFilesFacade.java +++ b/src/main/java/org/onap/dcae/configuration/ConfigFilesFacade.java @@ -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> readCollectorProperties() { @@ -62,19 +75,19 @@ class ConfigFilesFacade { } Try 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 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 +} diff --git a/src/main/java/org/onap/dcae/configuration/ConfigUpdater.java b/src/main/java/org/onap/dcae/configuration/ConfigUpdater.java index eb1a1a5f..930ec2c5 100644 --- a/src/main/java/org/onap/dcae/configuration/ConfigUpdater.java +++ b/src/main/java/org/onap/dcae/configuration/ConfigUpdater.java @@ -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 appConfig) { appConfig.peek(this::handleUpdate).onEmpty(logSkipMessage()); } -- cgit 1.2.3-korg