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