You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2018/10/01 09:02:20 UTC
[camel-k] 01/03: support component configuration from properties
This is an automated email from the ASF dual-hosted git repository.
nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 29e058a4681e261ae1581db05428b5087f1f1388
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Sun Sep 30 01:50:00 2018 +0200
support component configuration from properties
---
runtime/jvm/pom.xml | 5 +
.../java/org/apache/camel/k/jvm/Application.java | 119 ++++++++++++---------
.../java/org/apache/camel/k/jvm/Constants.java | 1 +
.../jvm/{Application.java => RuntimeSupport.java} | 94 ++++++++--------
.../org/apache/camel/k/jvm/PropertiesTest.java | 97 +++++++++++++++++
runtime/jvm/src/test/resources/log4j2-test.xml | 19 ++++
6 files changed, 233 insertions(+), 102 deletions(-)
diff --git a/runtime/jvm/pom.xml b/runtime/jvm/pom.xml
index 9dc3918..6251e75 100644
--- a/runtime/jvm/pom.xml
+++ b/runtime/jvm/pom.xml
@@ -34,6 +34,11 @@
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ <version>${log4j2.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
<scope>runtime</scope>
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java
index acb25f3..6ec328b 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java
@@ -16,28 +16,46 @@
*/
package org.apache.camel.k.jvm;
-import java.io.IOException;
-import java.nio.file.FileVisitResult;
-import java.nio.file.FileVisitor;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
+import java.util.Properties;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.main.Main;
+import org.apache.camel.main.MainListenerSupport;
+import org.apache.camel.support.LifecycleStrategySupport;
+import org.apache.camel.util.IntrospectionSupport;
import org.apache.camel.util.ObjectHelper;
-import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Application {
private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
+ static {
+ //
+ // Load properties as system properties so they are accessible through
+ // camel's properties component as well as for runtime configuration.
+ //
+ RuntimeSupport.configureSystemProperties();
+
+ //
+ // Configure the logging subsystem log4j2 using a subset of spring boot
+ // conventions:
+ //
+ // logging.level.${nane} = OFF|FATAL|ERROR|WARN|INFO|DEBUG|TRACE|ALL
+ //
+ // We now support setting the logging level only
+ //
+ RuntimeSupport.configureLogging();
+ }
+
+ // *******************************
+ //
+ // Main
+ //
+ // *******************************
+
public static void main(String[] args) throws Exception {
final String resource = System.getenv(Constants.ENV_CAMEL_K_ROUTES_URI);
final String language = System.getenv(Constants.ENV_CAMEL_K_ROUTES_LANGUAGE);
@@ -46,7 +64,6 @@ public class Application {
throw new IllegalStateException("No valid resource found in " + Constants.ENV_CAMEL_K_ROUTES_URI + " environment variable");
}
- String locations = computePropertyPlaceholderLocations();
RoutesLoader loader = RoutesLoaders.loaderFor(resource, language);
RouteBuilder routes = loader.load(resource);
@@ -56,59 +73,55 @@ public class Application {
LOGGER.info("Routes: {}", resource);
LOGGER.info("Language: {}", language);
- LOGGER.info("Locations: {}", locations);
Main main = new Main();
-
- if (ObjectHelper.isNotEmpty(locations)) {
- main.setPropertyPlaceholderLocations(locations);
- }
-
+ main.addMainListener(new ComponentPropertiesBinder());
main.addRouteBuilder(routes);
main.run();
}
// *******************************
//
- // helpers
+ // Listeners
//
// *******************************
- private static String computePropertyPlaceholderLocations() throws IOException {
- final String conf = System.getenv(Constants.ENV_CAMEL_K_CONF);
- final String confd = System.getenv(Constants.ENV_CAMEL_K_CONF_D);
- final List<String> locations = new ArrayList<>();
-
- // Main location
- if (ObjectHelper.isNotEmpty(conf)) {
- locations.add("file:" + conf);
- }
-
- // Additional locations
- if (ObjectHelper.isNotEmpty(confd)) {
- Path root = Paths.get(confd);
- FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {
+ static class ComponentPropertiesBinder extends MainListenerSupport {
+ @Override
+ public void configure(CamelContext context) {
+ context.addLifecycleStrategy(new LifecycleStrategySupport() {
+ @SuppressWarnings("unchecked")
@Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
- Objects.requireNonNull(file);
- Objects.requireNonNull(attrs);
-
- String path = file.toFile().getAbsolutePath();
- String ext = FilenameUtils.getExtension(path);
-
- if (Objects.equals("properties", ext)) {
- locations.add("file:" + path);
- }
-
- return FileVisitResult.CONTINUE;
+ public void onComponentAdd(String name, Component component) {
+ // Integration properties are defined as system properties
+ final Properties properties = System.getProperties();
+
+ // Set the prefix used by setProperties to filter
+ // and apply properties to match the one used by
+ // camel spring boot:
+ //
+ // camel.component.${scheme}.${value}
+ //
+ final String prefix = "camel.component." + name + ".";
+
+ properties.entrySet().stream()
+ .filter(entry -> entry.getKey() instanceof String)
+ .filter(entry -> entry.getValue() != null)
+ .filter(entry -> ((String)entry.getKey()).startsWith(prefix))
+ .forEach(entry -> {
+ final String key = ((String)entry.getKey()).substring(prefix.length());
+ final Object val = entry.getValue();
+
+ try {
+ IntrospectionSupport.setProperty(component, key, val, false);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ );
}
- };
-
- if (Files.exists(root)) {
- Files.walkFileTree(root, visitor);
- }
+ });
}
-
- return String.join(",", locations);
}
+
}
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Constants.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Constants.java
index 0e9bcae..d123d7a 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Constants.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Constants.java
@@ -23,6 +23,7 @@ public final class Constants {
public static final String ENV_CAMEL_K_CONF_D = "CAMEL_K_CONF_D";
public static final String SCHEME_CLASSPATH = "classpath:";
public static final String SCHEME_FILE = "file:";
+ public static final String LOGGING_LEVEL_PREFIX = "logging.level.";
private Constants() {
}
diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeSupport.java
similarity index 53%
copy from runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java
copy to runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeSupport.java
index acb25f3..6210b54 100644
--- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java
+++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/RuntimeSupport.java
@@ -17,6 +17,7 @@
package org.apache.camel.k.jvm;
import java.io.IOException;
+import java.io.Reader;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
@@ -24,64 +25,32 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Objects;
+import java.util.Properties;
-import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.main.Main;
import org.apache.camel.util.ObjectHelper;
import org.apache.commons.io.FilenameUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.LoggerConfig;
-public class Application {
- private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
-
- public static void main(String[] args) throws Exception {
- final String resource = System.getenv(Constants.ENV_CAMEL_K_ROUTES_URI);
- final String language = System.getenv(Constants.ENV_CAMEL_K_ROUTES_LANGUAGE);
-
- if (ObjectHelper.isEmpty(resource)) {
- throw new IllegalStateException("No valid resource found in " + Constants.ENV_CAMEL_K_ROUTES_URI + " environment variable");
- }
-
- String locations = computePropertyPlaceholderLocations();
- RoutesLoader loader = RoutesLoaders.loaderFor(resource, language);
- RouteBuilder routes = loader.load(resource);
-
- if (routes == null) {
- throw new IllegalStateException("Unable to load route from: " + resource);
- }
-
- LOGGER.info("Routes: {}", resource);
- LOGGER.info("Language: {}", language);
- LOGGER.info("Locations: {}", locations);
-
- Main main = new Main();
-
- if (ObjectHelper.isNotEmpty(locations)) {
- main.setPropertyPlaceholderLocations(locations);
- }
-
- main.addRouteBuilder(routes);
- main.run();
+public final class RuntimeSupport {
+ private RuntimeSupport() {
}
- // *******************************
- //
- // helpers
- //
- // *******************************
-
- private static String computePropertyPlaceholderLocations() throws IOException {
+ public static void configureSystemProperties() {
final String conf = System.getenv(Constants.ENV_CAMEL_K_CONF);
final String confd = System.getenv(Constants.ENV_CAMEL_K_CONF_D);
- final List<String> locations = new ArrayList<>();
+ final Properties properties = new Properties();
// Main location
if (ObjectHelper.isNotEmpty(conf)) {
- locations.add("file:" + conf);
+ try (Reader reader = Files.newBufferedReader(Paths.get(conf))) {
+ properties.load(reader);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
// Additional locations
@@ -97,7 +66,9 @@ public class Application {
String ext = FilenameUtils.getExtension(path);
if (Objects.equals("properties", ext)) {
- locations.add("file:" + path);
+ try (Reader reader = Files.newBufferedReader(Paths.get(path))) {
+ properties.load(reader);
+ }
}
return FileVisitResult.CONTINUE;
@@ -105,10 +76,35 @@ public class Application {
};
if (Files.exists(root)) {
- Files.walkFileTree(root, visitor);
+ try {
+ Files.walkFileTree(root, visitor);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
}
- return String.join(",", locations);
+ System.getProperties().putAll(properties);
+ }
+
+ public static void configureLogging() {
+ final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+ final Properties properties = System.getProperties();
+
+ properties.entrySet().stream()
+ .filter(entry -> entry.getKey() instanceof String)
+ .filter(entry -> entry.getValue() instanceof String)
+ .filter(entry -> ((String)entry.getKey()).startsWith(Constants.LOGGING_LEVEL_PREFIX))
+ .forEach(entry -> {
+ String key = ((String)entry.getKey());
+ String val = ((String)entry.getValue());
+
+ String logger = key.substring(Constants.LOGGING_LEVEL_PREFIX.length());
+ Level level = Level.getLevel(val);
+ LoggerConfig config = new LoggerConfig(logger, level, true);
+
+ ctx.getConfiguration().addLogger(logger, config);
+ }
+ );
}
}
diff --git a/runtime/jvm/src/test/java/org/apache/camel/k/jvm/PropertiesTest.java b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/PropertiesTest.java
new file mode 100644
index 0000000..2bfba13
--- /dev/null
+++ b/runtime/jvm/src/test/java/org/apache/camel/k/jvm/PropertiesTest.java
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.camel.k.jvm;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.seda.SedaComponent;
+import org.apache.camel.main.Main;
+import org.apache.camel.main.MainListenerSupport;
+import org.apache.camel.main.MainSupport;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PropertiesTest {
+
+ @Test
+ public void testSystemProperties() throws Exception {
+ System.setProperty("my.property", "my.value");
+
+ try {
+ Main main = new Main();
+ main.setDuration(5);
+ main.addMainListener(new Application.ComponentPropertiesBinder());
+ main.addMainListener(new MainListenerSupport() {
+ @Override
+ public void afterStart(MainSupport main) {
+ try {
+ CamelContext context = main.getCamelContexts().get(0);
+ String value = context.resolvePropertyPlaceholders("{{my.property}}");
+
+ assertThat(value).isEqualTo("my.value");
+
+ main.stop();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+
+ main.run();
+ } finally {
+ System.getProperties().remove("my.property");
+ }
+ }
+
+
+ @Test
+ public void testComponentConfiguration() throws Exception {
+ int queueSize1 = ThreadLocalRandom.current().nextInt(10, 100);
+ int queueSize2 = ThreadLocalRandom.current().nextInt(10, 100);
+
+ System.setProperty("camel.component.seda.queueSize", Integer.toString(queueSize1));
+ System.setProperty("camel.component.my-seda.queueSize", Integer.toString(queueSize2));
+
+ try {
+ Main main = new Main();
+ main.setDuration(5);
+ main.bind("my-seda", new SedaComponent());
+ main.addMainListener(new Application.ComponentPropertiesBinder());
+ main.addMainListener(new MainListenerSupport() {
+ @Override
+ public void afterStart(MainSupport main) {
+ try {
+ CamelContext context = main.getCamelContexts().get(0);
+
+ assertThat(context.getComponent("seda", true)).hasFieldOrPropertyWithValue("queueSize", queueSize1);
+ assertThat(context.getComponent("my-seda", true)).hasFieldOrPropertyWithValue("queueSize", queueSize2);
+
+ main.stop();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+
+ main.run();
+ } finally {
+ System.getProperties().remove("camel.component.seda.queueSize");
+ }
+ }
+}
diff --git a/runtime/jvm/src/test/resources/log4j2-test.xml b/runtime/jvm/src/test/resources/log4j2-test.xml
new file mode 100644
index 0000000..619c63a
--- /dev/null
+++ b/runtime/jvm/src/test/resources/log4j2-test.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="INFO">
+ <Appenders>
+ <Console name="STDOUT" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%t|%c{1} - %msg%n"/>
+ </Console>
+ <File name="FILE" fileName="target/camel-k-runtime-jmv-test.log">
+ <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%t|%c{1} - %msg%n"/>
+ </File>
+ </Appenders>
+
+ <Loggers>
+ <Root level="INFO">
+ <!--<AppenderRef ref="STDOUT"/>-->
+ <AppenderRef ref="FILE"/>
+ </Root>
+ </Loggers>
+
+</Configuration>
\ No newline at end of file