From commits-return-65561-archive-asf-public=cust-asf.ponee.io@camel.apache.org Mon Oct 1 11:02:24 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id 1AEBE18077A for ; Mon, 1 Oct 2018 11:02:22 +0200 (CEST) Received: (qmail 44668 invoked by uid 500); 1 Oct 2018 09:02:22 -0000 Mailing-List: contact commits-help@camel.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@camel.apache.org Delivered-To: mailing list commits@camel.apache.org Received: (qmail 44555 invoked by uid 99); 1 Oct 2018 09:02:22 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 01 Oct 2018 09:02:22 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 7F04A82C3C; Mon, 1 Oct 2018 09:02:21 +0000 (UTC) Date: Mon, 01 Oct 2018 09:02:20 +0000 To: "commits@camel.apache.org" Subject: [camel-k] 01/03: support component configuration from properties MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit From: nferraro@apache.org In-Reply-To: <153838453955.28968.13171773255974963358@gitbox.apache.org> References: <153838453955.28968.13171773255974963358@gitbox.apache.org> X-Git-Host: gitbox.apache.org X-Git-Repo: camel-k X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Rev: 29e058a4681e261ae1581db05428b5087f1f1388 X-Git-NotificationType: diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated Message-Id: <20181001090221.7F04A82C3C@gitbox.apache.org> 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 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 @@ org.apache.logging.log4j + log4j-core + ${log4j2.version} + + + org.apache.logging.log4j log4j-slf4j-impl ${log4j2.version} runtime 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 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 visitor = new SimpleFileVisitor() { + 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 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 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file