aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/org
diff options
context:
space:
mode:
authorZlatko Murgoski <zlatko.murgoski@nokia.com>2019-02-04 09:27:00 +0100
committerZlatko Murgoski <zlatko.murgoski@nokia.com>2019-03-01 07:50:28 +0100
commite7360f7e7e77672b885087af68a3d96ebbc8c313 (patch)
tree8316d86334ec400b48f5a7a6a862fe7ffd9b9867 /src/main/java/org
parent8971ae1e6ccc99811663652819206231065b1755 (diff)
Restart Issue
Restart Issue Issue-ID: DCAEGEN2-1104 Change-Id: Iac1ee2f79be00084f5c0cd963503d54d7d6e6cb9 Signed-off-by: Zlatko Murgoski <zlatko.murgoski@nokia.com>
Diffstat (limited to 'src/main/java/org')
-rw-r--r--src/main/java/org/onap/dcae/ApplicationException.java6
-rw-r--r--src/main/java/org/onap/dcae/ApplicationSettings.java34
-rw-r--r--src/main/java/org/onap/dcae/VesApplication.java90
-rw-r--r--src/main/java/org/onap/dcae/common/SSLContextCreator.java4
-rw-r--r--src/main/java/org/onap/dcae/controller/ConfigLoader.java41
-rw-r--r--src/main/java/org/onap/dcae/controller/PreAppStartupConfigUpdater.java49
-rw-r--r--src/main/java/org/onap/dcae/restapi/ServletConfig.java55
7 files changed, 157 insertions, 122 deletions
diff --git a/src/main/java/org/onap/dcae/ApplicationException.java b/src/main/java/org/onap/dcae/ApplicationException.java
index 2079d867..1252423d 100644
--- a/src/main/java/org/onap/dcae/ApplicationException.java
+++ b/src/main/java/org/onap/dcae/ApplicationException.java
@@ -34,7 +34,11 @@ public class ApplicationException extends RuntimeException {
super(message,ex);
}
- public ApplicationException(IOException ex) {
+ public ApplicationException(Exception ex) {
super(ex);
}
+
+ public ApplicationException(String message) {
+ super(message);
+ }
}
diff --git a/src/main/java/org/onap/dcae/ApplicationSettings.java b/src/main/java/org/onap/dcae/ApplicationSettings.java
index 7d52c5e8..7a2bff97 100644
--- a/src/main/java/org/onap/dcae/ApplicationSettings.java
+++ b/src/main/java/org/onap/dcae/ApplicationSettings.java
@@ -69,11 +69,21 @@ public class ApplicationSettings {
Map<String, String> parsedArgs = argsParser.apply(args);
configurationFileLocation = findOutConfigurationFileLocation(parsedArgs);
loadPropertiesFromFile();
- parsedArgs.filterKeys(k -> !"c".equals(k)).forEach(this::updateProperty);
+ parsedArgs.filterKeys(k -> !"c".equals(k)).forEach(this::addOrUpdate);
loadedJsonSchemas = loadJsonSchemas();
}
- private void loadPropertiesFromFile() {
+
+ public void reloadProperties() {
+ try {
+ properties.load(configurationFileLocation);
+ properties.refresh();
+ } catch (ConfigurationException ex) {
+ log.error("Cannot load properties cause:", ex);
+ throw new ApplicationException(ex);
+ }
+ }
+ public void loadPropertiesFromFile() {
try {
properties.load(configurationFileLocation);
} catch (ConfigurationException ex) {
@@ -169,10 +179,6 @@ public class ApplicationSettings {
return httpsEnabled() && properties.getInt("collector.service.secure.clientauth", 0) > 0;
}
- public String keystoreAlias() {
- return properties.getString("collector.keystore.alias", "tomcat");
- }
-
public String truststorePasswordFileLocation() {
return prependWithUserDirOnRelative(properties.getString("collector.truststore.passwordfile", "etc/trustpasswordfile"));
}
@@ -198,6 +204,14 @@ public class ApplicationSettings {
}
}
+ public void addOrUpdate(String key, String value) {
+ if (properties.containsKey(key)) {
+ properties.setProperty(key, value);
+ } else {
+ properties.addProperty(key, value);
+ }
+ }
+
private JSONObject jsonSchema() {
return new JSONObject(properties.getString("collector.schema.file",
format("{\"%s\":\"etc/CommonEventFormat_28.4.1.json\"}", FALLBACK_VES_VERSION)));
@@ -214,14 +228,6 @@ public class ApplicationSettings {
return HashMap.ofAll(domainToStreamIdsMapping);
}
- private void updateProperty(String key, String value) {
- if (properties.containsKey(key)) {
- properties.setProperty(key, value);
- } else {
- properties.addProperty(key, value);
- }
- }
-
private String prependWithUserDirOnRelative(String filePath) {
if (!Paths.get(filePath).isAbsolute()) {
filePath = Paths.get(appInvocationDir, filePath).toString();
diff --git a/src/main/java/org/onap/dcae/VesApplication.java b/src/main/java/org/onap/dcae/VesApplication.java
index 2dcd8fa8..d658b4aa 100644
--- a/src/main/java/org/onap/dcae/VesApplication.java
+++ b/src/main/java/org/onap/dcae/VesApplication.java
@@ -25,6 +25,7 @@ import java.nio.file.Paths;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.json.JSONObject;
@@ -41,6 +42,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
@@ -54,47 +56,77 @@ public class VesApplication {
private static final int MAX_THREADS = 20;
public static LinkedBlockingQueue<JSONObject> fProcessingInputQueue;
private static ApplicationSettings properties;
+ private static ConfigurableApplicationContext context;
+ private static ConfigLoader configLoader;
+ private static EventProcessor eventProcessor;
+ private static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
+ private static SpringApplication app;
+ private static EventPublisher eventPublisher;
+ private static ScheduledFuture<?> scheduleFeatures;
+ private static ExecutorService executor;
public static void main(String[] args) {
- SpringApplication app = new SpringApplication(VesApplication.class);
+ app = new SpringApplication(VesApplication.class);
+ properties = new ApplicationSettings(args, CLIUtils::processCmdLine);
+ scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
+ init();
+ app.setAddCommandLineProperties(true);
+ context = app.run();
+ configLoader.updateConfig();
- properties = new ApplicationSettings(args, CLIUtils::processCmdLine);
+ }
+
+ public static void restartApplication() {
+ Thread thread = new Thread(() -> {
+ context.close();
+ properties.reloadProperties();
+ scheduleFeatures.cancel(true);
+ init();
+ context = SpringApplication.run(VesApplication.class);
+ });
+ thread.setDaemon(false);
+ thread.start();
+ }
+
+ private static void init() {
+ fProcessingInputQueue = new LinkedBlockingQueue<>(properties.maximumAllowedQueuedEvents());
+ createConfigLoader();
+ createSchedulePoolExecutor();
+ createExecutors();
+ }
- fProcessingInputQueue = new LinkedBlockingQueue<>(properties.maximumAllowedQueuedEvents());
+ private static void createExecutors() {
+ eventPublisher = EventPublisher.createPublisher(oplog, getDmapConfig());
+ eventProcessor = new EventProcessor(new EventSender(eventPublisher, properties));
- EventPublisher publisher = EventPublisher.createPublisher(oplog,
- DMaaPConfigurationParser
- .parseToDomainMapping(Paths.get(properties.dMaaPConfigurationFileLocation()))
- .get());
- spawnDynamicConfigUpdateThread(publisher, properties);
- EventProcessor ep = new EventProcessor(
- new EventSender(EventPublisher.createPublisher(oplog, getDmapConfig()), properties));
+ executor = Executors.newFixedThreadPool(MAX_THREADS);
+ for (int i = 0; i < MAX_THREADS; ++i) {
+ executor.execute(eventProcessor);
+ }
+ }
- ExecutorService executor = Executors.newFixedThreadPool(MAX_THREADS);
- for (int i = 0; i < MAX_THREADS; ++i) {
- executor.execute(ep);
- }
+ private static void createSchedulePoolExecutor() {
+ scheduleFeatures = scheduledThreadPoolExecutor.scheduleAtFixedRate(configLoader::updateConfig,
+ properties.configurationUpdateFrequency(),
+ properties.configurationUpdateFrequency(),
+ TimeUnit.MINUTES);
+ }
- app.setAddCommandLineProperties(true);
- app.run();
+ private static void createConfigLoader() {
+ configLoader = ConfigLoader.create(getEventPublisher()::reconfigure,
+ Paths.get(properties.dMaaPConfigurationFileLocation()),
+ properties.configurationFileLocation());
}
- private static void spawnDynamicConfigUpdateThread(EventPublisher eventPublisher, ApplicationSettings properties) {
- ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
- ConfigLoader configLoader = ConfigLoader
- .create(eventPublisher::reconfigure,
- Paths.get(properties.dMaaPConfigurationFileLocation()),
- properties.configurationFileLocation());
- scheduledThreadPoolExecutor
- .scheduleAtFixedRate(configLoader::updateConfig,
- properties.configurationUpdateFrequency(),
- properties.configurationUpdateFrequency(),
- TimeUnit.MINUTES);
+
+ private static EventPublisher getEventPublisher() {
+ return EventPublisher.createPublisher(oplog, DMaaPConfigurationParser
+ .parseToDomainMapping(Paths.get(properties.dMaaPConfigurationFileLocation())).get());
}
private static Map<String, PublisherConfig> getDmapConfig() {
- return DMaaPConfigurationParser.
- parseToDomainMapping(Paths.get(properties.dMaaPConfigurationFileLocation())).get();
+ return DMaaPConfigurationParser
+ .parseToDomainMapping(Paths.get(properties.dMaaPConfigurationFileLocation())).get();
}
@Bean
diff --git a/src/main/java/org/onap/dcae/common/SSLContextCreator.java b/src/main/java/org/onap/dcae/common/SSLContextCreator.java
index a76c7cbe..e636f4c0 100644
--- a/src/main/java/org/onap/dcae/common/SSLContextCreator.java
+++ b/src/main/java/org/onap/dcae/common/SSLContextCreator.java
@@ -20,9 +20,8 @@
package org.onap.dcae.common;
-import org.springframework.boot.web.server.Ssl;
-
import java.nio.file.Path;
+import org.springframework.boot.web.server.Ssl;
public class SSLContextCreator {
private final String keyStorePassword;
@@ -53,7 +52,6 @@ public class SSLContextCreator {
private void configureKeyStore(final Ssl ssl) {
final String keyStore = keyStoreFile.toAbsolutePath().toString();
-
ssl.setKeyStore(keyStore);
ssl.setKeyPassword(keyStorePassword);
ssl.setKeyAlias(certAlias);
diff --git a/src/main/java/org/onap/dcae/controller/ConfigLoader.java b/src/main/java/org/onap/dcae/controller/ConfigLoader.java
index e11c2b8a..dbf52823 100644
--- a/src/main/java/org/onap/dcae/controller/ConfigLoader.java
+++ b/src/main/java/org/onap/dcae/controller/ConfigLoader.java
@@ -33,6 +33,7 @@ import io.vavr.control.Try;
import java.nio.file.Path;
import java.util.function.Consumer;
import org.json.JSONObject;
+import org.onap.dcae.VesApplication;
import org.onap.dcae.common.publishing.PublisherConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,19 +46,21 @@ public class ConfigLoader {
private final ConfigFilesFacade configFilesFacade;
private final Function1<EnvProps, Try<JSONObject>> configurationSource;
private final Function0<Map<String, String>> envVariablesSupplier;
+ private boolean toRestart = false;
ConfigLoader(Consumer<Map<String, PublisherConfig>> eventPublisherReconfigurer,
- ConfigFilesFacade configFilesFacade,
- Function1<EnvProps, Try<JSONObject>> configurationSource,
- Function0<Map<String, String>> envVariablesSupplier) {
+ ConfigFilesFacade configFilesFacade,
+ Function1<EnvProps, Try<JSONObject>> configurationSource,
+ Function0<Map<String, String>> envVariablesSupplier) {
this.eventPublisherReconfigurer = eventPublisherReconfigurer;
this.configFilesFacade = configFilesFacade;
this.configurationSource = configurationSource;
this.envVariablesSupplier = envVariablesSupplier;
}
- public static ConfigLoader create(Consumer<Map<String, PublisherConfig>> eventPublisherReconfigurer,
- Path dMaaPConfigFile, Path propertiesConfigFile) {
+ public static ConfigLoader create(
+ Consumer<Map<String, PublisherConfig>> eventPublisherReconfigurer,
+ Path dMaaPConfigFile, Path propertiesConfigFile) {
return new ConfigLoader(eventPublisherReconfigurer,
new ConfigFilesFacade(dMaaPConfigFile, propertiesConfigFile),
ConfigSource::getAppConfig,
@@ -67,20 +70,27 @@ public class ConfigLoader {
public void updateConfig() {
log.info("Trying to dynamically update config from Config Binding Service");
readEnvProps(envVariablesSupplier.get())
- .onEmpty(() -> log.warn(SKIP_MSG))
- .forEach(this::updateConfig);
+ .onEmpty(() -> log.warn(SKIP_MSG)).forEach(this::updateConfig);
}
private void updateConfig(EnvProps props) {
configurationSource.apply(props)
.onFailure(logSkip())
.onSuccess(newConf -> {
- updateConfigurationProperties(newConf);
- updateDMaaPProperties(newConf);
+ updateConfigurationProperties(newConf);
+ updateDMaaPProperties(newConf);
+ reloadApplication();
}
);
}
+ private void reloadApplication() {
+ if(toRestart){
+ log.info("New app config - Application will be restarted");
+ VesApplication.restartApplication();
+ }
+ }
+
private void updateDMaaPProperties(JSONObject newConf) {
configFilesFacade.readDMaaPConfiguration()
.onFailure(logSkip())
@@ -98,9 +108,13 @@ public class ConfigLoader {
private void compareAndOverwritePropertiesConfig(JSONObject newConf, Map<String, String> oldProps) {
Map<String, String> newProperties = getProperties(newConf);
- if (!oldProps.equals(newProperties)) {
+ Map<String, String> result = oldProps.filterKeys((s) -> newProperties.keySet().contains(s));
+ if (!result.equals(newProperties)) {
configFilesFacade.writeProperties(newProperties)
- .onSuccess(__ -> log.info("New properties configuration written to file"))
+ .onSuccess(__ -> {
+ toRestart= true;
+ log.info("New properties configuration written to file");
+ })
.onFailure(logSkip());
} else {
log.info("Collector properties from CBS are the same as currently used ones. " + SKIP_MSG);
@@ -115,7 +129,10 @@ public class ConfigLoader {
.onSuccess(parsedConfig ->
configFilesFacade.writeDMaaPConfiguration(newDMaaPConf)
.onFailure(logSkip())
- .onSuccess(__ -> log.info("New dMaaP configuration written to file")));
+ .onSuccess(__ -> {
+ toRestart= true;
+ log.info("New dMaaP configuration written to file");
+ }));
} else {
log.info("DMaaP config from CBS is the same as currently used one. " + SKIP_MSG);
}
diff --git a/src/main/java/org/onap/dcae/controller/PreAppStartupConfigUpdater.java b/src/main/java/org/onap/dcae/controller/PreAppStartupConfigUpdater.java
deleted file mode 100644
index be569119..00000000
--- a/src/main/java/org/onap/dcae/controller/PreAppStartupConfigUpdater.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * org.onap.dcaegen2.collectors.ves
- * ================================================================================
- * Copyright (C) 2018 Nokia. 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.dcae.controller;
-
-import io.vavr.collection.Map;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.function.Consumer;
-import org.onap.dcae.common.publishing.PublisherConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * On the first application launch, the configuration update thread that application spawns, has no chance to run yet
- * and prepare initial application configuration. In this case, it needs to be fetched from outside of the application,
- * so this is run from the .sh script.
- * Later on, once application is already started it will take care of the configuration update itself
- * @author Pawel Szalapski (pawel.szalapski@nokia.com)
- */
-public class PreAppStartupConfigUpdater {
- private final static Logger log = LoggerFactory.getLogger(PreAppStartupConfigUpdater.class);
-
- private static final Path DEFAULT_CONFIGURATION_FILE_PATH = Paths.get("etc/collector.properties");
- private static final Path DEFAULT_DMAAP_FILE_PATH = Paths.get("etc/DmaapConfig.json");
- private static final Consumer<Map<String, PublisherConfig>> NO_OP_CONSUMER = c -> { };
-
- public static void main(String[] args) {
- log.info("Running initial configuration update, before the application gets started.");
- ConfigLoader.create(NO_OP_CONSUMER, DEFAULT_DMAAP_FILE_PATH, DEFAULT_CONFIGURATION_FILE_PATH)
- .updateConfig();
- }
-}
diff --git a/src/main/java/org/onap/dcae/restapi/ServletConfig.java b/src/main/java/org/onap/dcae/restapi/ServletConfig.java
index 35616ac1..e66f3f1f 100644
--- a/src/main/java/org/onap/dcae/restapi/ServletConfig.java
+++ b/src/main/java/org/onap/dcae/restapi/ServletConfig.java
@@ -21,6 +21,16 @@
package org.onap.dcae.restapi;
+import static java.nio.file.Files.readAllBytes;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
import org.onap.dcae.ApplicationException;
import org.onap.dcae.ApplicationSettings;
import org.onap.dcae.common.SSLContextCreator;
@@ -32,12 +42,6 @@ import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import static java.nio.file.Files.readAllBytes;
-
@Component
public class ServletConfig implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@@ -49,28 +53,51 @@ public class ServletConfig implements WebServerFactoryCustomizer<ConfigurableSer
@Override
public void customize(ConfigurableServletWebServerFactory container) {
final boolean hasClientTlsAuthentication = properties.clientTlsAuthenticationEnabled();
-
if (hasClientTlsAuthentication || properties.authorizationEnabled()) {
- container.setSsl(hasClientTlsAuthentication ? httpsContextWithTlsAuthentication() : simpleHttpsContext());
- container.setPort(properties.httpsPort());
+ container.setSsl(hasClientTlsAuthentication ? httpsContextWithTlsAuthentication() : simpleHttpsContext());
+ int port = properties.httpsPort();
+ container.setPort(port);
+ log.info("Application https port: " + port);
} else {
- container.setPort(properties.httpPort());
+ int port = properties.httpPort();
+ container.setPort(port);
+ log.info("Application http port: " + port);
}
+
}
private SSLContextCreator simpleHttpsContextBuilder() {
log.info("Enabling SSL");
- final Path keyStore = toAbsolutePath(properties.keystoreFileLocation());
- log.info("Using keyStore path: " + keyStore);
+ final Path keyStorePath = toAbsolutePath(properties.keystoreFileLocation());
+ log.info("Using keyStore path: " + keyStorePath);
final Path keyStorePasswordLocation = toAbsolutePath(properties.keystorePasswordFileLocation());
final String keyStorePassword = getKeyStorePassword(keyStorePasswordLocation);
log.info("Using keyStore password from: " + keyStorePasswordLocation);
+ return SSLContextCreator.create(keyStorePath, getKeyStoreAlias(keyStorePath, keyStorePassword), keyStorePassword);
+ }
- final String alias = properties.keystoreAlias();
+ private String getKeyStoreAlias(Path keyStorePath, String keyStorePassword) {
+ KeyStore keyStore = getKeyStore();
+ try(InputStream keyStoreData = new FileInputStream(keyStorePath.toString())){
+ keyStore.load(keyStoreData, keyStorePassword.toCharArray());
+ String alias = keyStore.aliases().nextElement();
+ log.info("Actual key store alias is: " + alias);
+ return alias;
+ } catch (IOException | GeneralSecurityException ex) {
+ log.error("Cannot load Key Store alias cause: " + ex);
+ throw new ApplicationException(ex);
+ }
+ }
- return SSLContextCreator.create(keyStore, alias, keyStorePassword);
+ private KeyStore getKeyStore() {
+ try {
+ return KeyStore.getInstance(KeyStore.getDefaultType());
+ } catch (KeyStoreException ex) {
+ log.error("Cannot create Key Store instance cause: " + ex);
+ throw new ApplicationException(ex);
+ }
}
private Ssl simpleHttpsContext() {