This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 1e65cbf8278 CAMEL-20970: camel-main - Allow to configure MainListener 
via applica… (#14790)
1e65cbf8278 is described below

commit 1e65cbf8278df1d82dd963baaaaf66411aa14f1e
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Thu Jul 11 14:56:16 2024 +0200

    CAMEL-20970: camel-main - Allow to configure MainListener via applica… 
(#14790)
    
    * CAMEL-20970: camel-main - Allow to configure MainListener via 
application.properties
---
 .../main/camel-main-configuration-metadata.json    |   2 +
 .../MainConfigurationPropertiesConfigurer.java     |  14 +++
 .../camel-main-configuration-metadata.json         |   2 +
 core/camel-main/src/main/docs/main.adoc            |   4 +-
 .../org/apache/camel/main/BaseMainSupport.java     |  17 ++++
 .../camel/main/MainConfigurationProperties.java    | 101 +++++++++++++++++++++
 .../org/apache/camel/main/MainListenerTest.java    |  17 ++++
 .../java/org/apache/camel/main/MyMainListener.java |  29 ++++++
 8 files changed, 185 insertions(+), 1 deletion(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
index 73d756eee1e..48e0cb42495 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
@@ -79,6 +79,8 @@
     { "name": "camel.main.logDebugMaxChars", "description": "Is used to limit 
the maximum length of the logging Camel message bodies. If the message body is 
longer than the limit, the log message is clipped. Use -1 to have unlimited 
length. Use for example 1000 to log at most 1000 characters.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", 
"javaType": "int" },
     { "name": "camel.main.logExhaustedMessageBody", "description": "Sets 
whether to log exhausted message body with message history. Default is false.", 
"sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": 
"boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.logMask", "description": "Sets whether log mask is 
enabled or not. Default is false.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.main.mainListenerClasses", "description": "Sets classes 
names that will be used for MainListener that makes it possible to do custom 
logic during starting and stopping camel-main.", "sourceType": 
"org.apache.camel.main.MainConfigurationProperties", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.main.mainListeners", "description": "Sets main listener 
objects that will be used for MainListener that makes it possible to do custom 
logic during starting and stopping camel-main.", "sourceType": 
"org.apache.camel.main.MainConfigurationProperties", "type": "object", 
"javaType": "java.util.List" },
     { "name": "camel.main.mdcLoggingKeysPattern", "description": "Sets the 
pattern used for determine which custom MDC keys to propagate during message 
routing when the routing engine continues routing asynchronously for the given 
message. Setting this pattern to will propagate all custom keys. Or setting the 
pattern to foo,bar will propagate any keys starting with either foo or bar. 
Notice that a set of standard Camel MDC keys are always propagated which starts 
with camel. as key name.  [...]
     { "name": "camel.main.messageHistory", "description": "Sets whether 
message history is enabled or not. Default is false.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.modeline", "description": "Whether camel-k style 
modeline is also enabled when not using camel-k. Enabling this allows to use a 
camel-k like experience by being able to configure various settings using 
modeline directly in your route source code.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
diff --git 
a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
 
b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
index 6e598b2a464..28b63284bca 100644
--- 
a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
+++ 
b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
@@ -140,6 +140,10 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "logExhaustedMessageBody": 
target.setLogExhaustedMessageBody(property(camelContext, boolean.class, 
value)); return true;
         case "logmask":
         case "logMask": target.setLogMask(property(camelContext, 
boolean.class, value)); return true;
+        case "mainlistenerclasses":
+        case "mainListenerClasses": 
target.setMainListenerClasses(property(camelContext, java.lang.String.class, 
value)); return true;
+        case "mainlisteners":
+        case "mainListeners": target.setMainListeners(property(camelContext, 
java.util.List.class, value)); return true;
         case "mdcloggingkeyspattern":
         case "mdcLoggingKeysPattern": 
target.setMdcLoggingKeysPattern(property(camelContext, java.lang.String.class, 
value)); return true;
         case "messagehistory":
@@ -374,6 +378,10 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "logExhaustedMessageBody": return boolean.class;
         case "logmask":
         case "logMask": return boolean.class;
+        case "mainlistenerclasses":
+        case "mainListenerClasses": return java.lang.String.class;
+        case "mainlisteners":
+        case "mainListeners": return java.util.List.class;
         case "mdcloggingkeyspattern":
         case "mdcLoggingKeysPattern": return java.lang.String.class;
         case "messagehistory":
@@ -609,6 +617,10 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "logExhaustedMessageBody": return 
target.isLogExhaustedMessageBody();
         case "logmask":
         case "logMask": return target.isLogMask();
+        case "mainlistenerclasses":
+        case "mainListenerClasses": return target.getMainListenerClasses();
+        case "mainlisteners":
+        case "mainListeners": return target.getMainListeners();
         case "mdcloggingkeyspattern":
         case "mdcLoggingKeysPattern": return target.getMdcLoggingKeysPattern();
         case "messagehistory":
@@ -729,6 +741,8 @@ public class MainConfigurationPropertiesConfigurer extends 
org.apache.camel.supp
         case "configurations": return 
org.apache.camel.CamelConfiguration.class;
         case "globaloptions":
         case "globalOptions": return java.lang.String.class;
+        case "mainlisteners":
+        case "mainListeners": return org.apache.camel.main.MainListener.class;
         case "routesbuilders":
         case "routesBuilders": return org.apache.camel.RoutesBuilder.class;
         default: return null;
diff --git 
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
 
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index 73d756eee1e..48e0cb42495 100644
--- 
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++ 
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -79,6 +79,8 @@
     { "name": "camel.main.logDebugMaxChars", "description": "Is used to limit 
the maximum length of the logging Camel message bodies. If the message body is 
longer than the limit, the log message is clipped. Use -1 to have unlimited 
length. Use for example 1000 to log at most 1000 characters.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", 
"javaType": "int" },
     { "name": "camel.main.logExhaustedMessageBody", "description": "Sets 
whether to log exhausted message body with message history. Default is false.", 
"sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": 
"boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.logMask", "description": "Sets whether log mask is 
enabled or not. Default is false.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.main.mainListenerClasses", "description": "Sets classes 
names that will be used for MainListener that makes it possible to do custom 
logic during starting and stopping camel-main.", "sourceType": 
"org.apache.camel.main.MainConfigurationProperties", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.main.mainListeners", "description": "Sets main listener 
objects that will be used for MainListener that makes it possible to do custom 
logic during starting and stopping camel-main.", "sourceType": 
"org.apache.camel.main.MainConfigurationProperties", "type": "object", 
"javaType": "java.util.List" },
     { "name": "camel.main.mdcLoggingKeysPattern", "description": "Sets the 
pattern used for determine which custom MDC keys to propagate during message 
routing when the routing engine continues routing asynchronously for the given 
message. Setting this pattern to will propagate all custom keys. Or setting the 
pattern to foo,bar will propagate any keys starting with either foo or bar. 
Notice that a set of standard Camel MDC keys are always propagated which starts 
with camel. as key name.  [...]
     { "name": "camel.main.messageHistory", "description": "Sets whether 
message history is enabled or not. Default is false.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.modeline", "description": "Whether camel-k style 
modeline is also enabled when not using camel-k. Enabling this allows to use a 
camel-k like experience by being able to configure various settings using 
modeline directly in your route source code.", "sourceType": 
"org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
diff --git a/core/camel-main/src/main/docs/main.adoc 
b/core/camel-main/src/main/docs/main.adoc
index 47828c66429..fa04d822266 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -19,7 +19,7 @@ The following tables lists all the options:
 
 // main options: START
 === Camel Main configurations
-The camel.main supports 117 options, which are listed below.
+The camel.main supports 119 options, which are listed below.
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
@@ -84,6 +84,8 @@ The camel.main supports 117 options, which are listed below.
 | *camel.main.logDebugMaxChars* | Is used to limit the maximum length of the 
logging Camel message bodies. If the message body is longer than the limit, the 
log message is clipped. Use -1 to have unlimited length. Use for example 1000 
to log at most 1000 characters. |  | int
 | *camel.main.logExhaustedMessage{zwsp}Body* | Sets whether to log exhausted 
message body with message history. Default is false. | false | boolean
 | *camel.main.logMask* | Sets whether log mask is enabled or not. Default is 
false. | false | boolean
+| *camel.main.mainListenerClasses* | Sets classes names that will be used for 
MainListener that makes it possible to do custom logic during starting and 
stopping camel-main. |  | String
+| *camel.main.mainListeners* | Sets main listener objects that will be used 
for MainListener that makes it possible to do custom logic during starting and 
stopping camel-main. |  | List
 | *camel.main.mdcLoggingKeys{zwsp}Pattern* | Sets the pattern used for 
determine which custom MDC keys to propagate during message routing when the 
routing engine continues routing asynchronously for the given message. Setting 
this pattern to will propagate all custom keys. Or setting the pattern to 
foo,bar will propagate any keys starting with either foo or bar. Notice that a 
set of standard Camel MDC keys are always propagated which starts with camel. 
as key name. The match rules are a [...]
 | *camel.main.messageHistory* | Sets whether message history is enabled or 
not. Default is false. | false | boolean
 | *camel.main.modeline* | Whether camel-k style modeline is also enabled when 
not using camel-k. Enabling this allows to use a camel-k like experience by 
being able to configure various settings using modeline directly in your route 
source code. | false | boolean
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java 
b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index 8ef5d715da3..fb8c24bfeaf 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -586,6 +586,21 @@ public abstract class BaseMainSupport extends BaseService {
         }
     }
 
+    protected void configureMainListener(CamelContext camelContext) throws 
Exception {
+        // any custom listener in registry
+        
camelContext.getRegistry().findByType(MainListener.class).forEach(this::addMainListener);
+        // listener from configuration
+        
mainConfigurationProperties.getMainListeners().forEach(this::addMainListener);
+        if (mainConfigurationProperties.getMainListenerClasses() != null) {
+            for (String fqn : 
mainConfigurationProperties.getMainListenerClasses().split(",")) {
+                fqn = fqn.trim();
+                Class<? extends MainListener> clazz
+                        = 
camelContext.getClassResolver().resolveMandatoryClass(fqn, MainListener.class);
+                addMainListener(camelContext.getInjector().newInstance(clazz));
+            }
+        }
+    }
+
     protected void configureRoutesLoader(CamelContext camelContext) {
         // use main based routes loader
         ExtendedCamelContext ecc = camelContext.getCamelContextExtension();
@@ -668,6 +683,8 @@ public abstract class BaseMainSupport extends BaseService {
         configurePackageScan(camelContext);
         // configure to use our main routes loader
         configureRoutesLoader(camelContext);
+        // configure custom main listeners
+        configureMainListener(camelContext);
 
         // ensure camel context is build
         camelContext.build();
diff --git 
a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
 
b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
index bd66aff9e1b..e3cf452be1d 100644
--- 
a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
+++ 
b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
@@ -47,11 +47,13 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
     private String basePackageScan;
     private boolean basePackageScanEnabled = true;
 
+    private String mainListenerClasses;
     private String routesBuilderClasses;
     private String configurationClasses;
 
     private List<RoutesBuilder> routesBuilders = new ArrayList<>();
     private List<CamelConfiguration> configurations = new ArrayList<>();
+    private List<MainListener> mainListeners = new ArrayList<>();
 
     // extended configuration
     private HealthConfigurationProperties healthConfigurationProperties;
@@ -135,6 +137,10 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
             configurations.clear();
             configurations = null;
         }
+        if (mainListeners != null) {
+            mainListeners.clear();
+            mainListeners = null;
+        }
     }
 
     // extended
@@ -536,6 +542,64 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
         this.extraShutdownTimeout = extraShutdownTimeout;
     }
 
+    // getter and setters - main listener
+    // --------------------------------------------------------------
+
+    public String getMainListenerClasses() {
+        return mainListenerClasses;
+    }
+
+    /**
+     * Sets classes names that will be used for {@link MainListener} that 
makes it possible to do custom logic during
+     * starting and stopping camel-main.
+     */
+    public void setMainListenerClasses(String mainListenerClasses) {
+        this.mainListenerClasses = mainListenerClasses;
+    }
+
+    /**
+     * Adds {@link MainListener} object to the known list of main listener 
classes.
+     */
+    @SuppressWarnings("unchecked")
+    private void addMainListenerClass(Class<? extends MainListener>... 
listener) {
+        StringJoiner existing = new StringJoiner(",");
+        if (mainListenerClasses != null && !mainListenerClasses.isEmpty()) {
+            existing.add(mainListenerClasses);
+        }
+        if (listener != null) {
+            for (Class<? extends MainListener> clazz : listener) {
+                existing.add(clazz.getName());
+            }
+        }
+        setMainListenerClasses(existing.toString());
+    }
+
+    /**
+     * Adds main listener object to the known list of listener objects.
+     */
+    public void addMainListener(MainListener listener) {
+        mainListeners.add(listener);
+    }
+
+    /**
+     * Adds main listener class to the known list of listener objects.
+     */
+    public void addMainListener(Class<? extends MainListener> listener) {
+        addMainListenerClass(listener);
+    }
+
+    public List<MainListener> getMainListeners() {
+        return mainListeners;
+    }
+
+    /**
+     * Sets main listener objects that will be used for {@link MainListener} 
that makes it possible to do custom logic
+     * during starting and stopping camel-main.
+     */
+    public void setMainListeners(List<MainListener> mainListeners) {
+        this.mainListeners = mainListeners;
+    }
+
     // getter and setters - configurations
     // --------------------------------------------------------------
 
@@ -779,6 +843,43 @@ public class MainConfigurationProperties extends 
DefaultConfigurationProperties<
         return this;
     }
 
+    // fluent builders - main listener
+    // --------------------------------------------------------------
+
+    /**
+     * Sets classes names that will be used for {@link MainListener} that 
makes it possible to do custom logic during
+     * starting and stopping camel-main.
+     */
+    public MainConfigurationProperties withMainListeners(String listeners) {
+        if (this.mainListenerClasses == null) {
+            this.mainListenerClasses = "";
+        }
+        if (this.mainListenerClasses.isEmpty()) {
+            this.mainListenerClasses = listeners;
+        } else {
+            this.mainListenerClasses = "," + listeners;
+        }
+        return this;
+    }
+
+    /**
+     * Adds main listener object to the known list of listener objects.
+     */
+    @SuppressWarnings("unchecked")
+    public MainConfigurationProperties withMainListeners(
+            Class<? extends MainListener>... listeners) {
+        addMainListenerClass(listeners);
+        return this;
+    }
+
+    /**
+     * Adds main listener object to the known list of listener objects.
+     */
+    public MainConfigurationProperties withMainListeners(List<MainListener> 
listeners) {
+        setMainListeners(listeners);
+        return this;
+    }
+
     // fluent builders - configurations
     // --------------------------------------------------------------
 
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MainListenerTest.java 
b/core/camel-main/src/test/java/org/apache/camel/main/MainListenerTest.java
index 36b6e2142b7..15e903d7abd 100644
--- a/core/camel-main/src/test/java/org/apache/camel/main/MainListenerTest.java
+++ b/core/camel-main/src/test/java/org/apache/camel/main/MainListenerTest.java
@@ -76,4 +76,21 @@ public class MainListenerTest {
             main.stop();
         }
     }
+
+    @Test
+    public void testCustomListener() {
+        Main main = new Main();
+        try {
+            
main.configure().withMainListeners("org.apache.camel.main.MyMainListener");
+            main.setDefaultPropertyPlaceholderLocation("false");
+            main.setInitialProperties(propertiesOf(
+                    "camel.context.name", "my-ctx"));
+            main.start();
+
+            assertEquals("my-special-override", 
main.getCamelContext().getName());
+        } finally {
+            main.stop();
+        }
+    }
+
 }
diff --git 
a/core/camel-main/src/test/java/org/apache/camel/main/MyMainListener.java 
b/core/camel-main/src/test/java/org/apache/camel/main/MyMainListener.java
new file mode 100644
index 00000000000..c405f7b37ce
--- /dev/null
+++ b/core/camel-main/src/test/java/org/apache/camel/main/MyMainListener.java
@@ -0,0 +1,29 @@
+/*
+ * 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.main;
+
+import static org.apache.camel.util.CollectionHelper.propertiesOf;
+
+public class MyMainListener extends MainListenerSupport {
+
+    @Override
+    public void beforeConfigure(BaseMainSupport main) {
+        
main.getCamelContext().getPropertiesComponent().setOverrideProperties(propertiesOf(
+                "camel.context.name", "my-special-override"));
+    }
+
+}

Reply via email to