You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2024/03/13 16:29:03 UTC

(camel) 01/06: CAMEL-18090: camel-main - Loading properties with profiles for prod/dev/test

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

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

commit 5a14e5ab3d6b47c34a9aa4e47bcc9fd055e47e51
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 13 15:38:23 2024 +0100

    CAMEL-18090: camel-main - Loading properties with profiles for prod/dev/test
---
 .../properties/ClasspathPropertiesSource.java      |  9 ++-
 .../component/properties/FilePropertiesSource.java |  9 ++-
 .../component/properties/PropertiesComponent.java  | 14 ++--
 .../component/properties/RefPropertiesSource.java  | 15 +++-
 .../org/apache/camel/main/BaseMainSupport.java     | 13 +++-
 .../apache/camel/main/MainCommandLineSupport.java  |  7 ++
 .../java/org/apache/camel/main/MainConstants.java  |  5 ++
 .../org/apache/camel/main/ProfileConfigurer.java   |  6 +-
 .../camel/dsl/jbang/core/commands/Export.java      | 63 ++++++++--------
 .../dsl/jbang/core/commands/ExportBaseCommand.java |  4 +
 .../dsl/jbang/core/commands/ExportCamelMain.java   | 34 +++++++++
 .../apache/camel/dsl/jbang/core/commands/Run.java  | 86 +++++++++++++++-------
 12 files changed, 199 insertions(+), 66 deletions(-)

diff --git a/core/camel-base/src/main/java/org/apache/camel/component/properties/ClasspathPropertiesSource.java b/core/camel-base/src/main/java/org/apache/camel/component/properties/ClasspathPropertiesSource.java
index 264628995c3..d897f61135d 100644
--- a/core/camel-base/src/main/java/org/apache/camel/component/properties/ClasspathPropertiesSource.java
+++ b/core/camel-base/src/main/java/org/apache/camel/component/properties/ClasspathPropertiesSource.java
@@ -31,8 +31,15 @@ import org.apache.camel.util.OrderedProperties;
 
 public class ClasspathPropertiesSource extends AbstractLocationPropertiesSource implements Ordered {
 
+    private final int order;
+
     public ClasspathPropertiesSource(PropertiesComponent propertiesComponent, PropertiesLocation location) {
+        this(propertiesComponent, location, 400);
+    }
+
+    public ClasspathPropertiesSource(PropertiesComponent propertiesComponent, PropertiesLocation location, int order) {
         super(propertiesComponent, location);
+        this.order = order;
     }
 
     @Override
@@ -71,6 +78,6 @@ public class ClasspathPropertiesSource extends AbstractLocationPropertiesSource
 
     @Override
     public int getOrder() {
-        return 300;
+        return order;
     }
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/component/properties/FilePropertiesSource.java b/core/camel-base/src/main/java/org/apache/camel/component/properties/FilePropertiesSource.java
index 88cc980c2d9..3fb197cfb2a 100644
--- a/core/camel-base/src/main/java/org/apache/camel/component/properties/FilePropertiesSource.java
+++ b/core/camel-base/src/main/java/org/apache/camel/component/properties/FilePropertiesSource.java
@@ -32,8 +32,15 @@ import org.apache.camel.util.OrderedProperties;
 
 public class FilePropertiesSource extends AbstractLocationPropertiesSource implements Ordered {
 
+    private final int order;
+
     protected FilePropertiesSource(PropertiesComponent propertiesComponent, PropertiesLocation location) {
+        this(propertiesComponent, location, 300);
+    }
+
+    protected FilePropertiesSource(PropertiesComponent propertiesComponent, PropertiesLocation location, int order) {
         super(propertiesComponent, location);
+        this.order = order;
     }
 
     @Override
@@ -69,6 +76,6 @@ public class FilePropertiesSource extends AbstractLocationPropertiesSource imple
 
     @Override
     public int getOrder() {
-        return 100;
+        return order;
     }
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java b/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
index 4a13c4e0e4a..d7acf6218b9 100644
--- a/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
+++ b/core/camel-base/src/main/java/org/apache/camel/component/properties/PropertiesComponent.java
@@ -353,8 +353,10 @@ public class PropertiesComponent extends ServiceSupport
 
         // we need to re-create the property sources which may have already been created from locations
         this.sources.removeIf(s -> s instanceof LocationPropertiesSource);
+        // ensure order we want as given in the locations
+        int order = 100;
         for (PropertiesLocation loc : locations) {
-            addPropertiesLocationsAsPropertiesSource(loc);
+            addPropertiesLocationsAsPropertiesSource(loc, order++);
         }
     }
 
@@ -386,6 +388,8 @@ public class PropertiesComponent extends ServiceSupport
     public void addLocation(String location) {
         if (location != null) {
             List<PropertiesLocation> newLocations = new ArrayList<>();
+            // add in reverse order as
+
             for (String loc : location.split(",")) {
                 newLocations.add(new PropertiesLocation(loc));
             }
@@ -793,13 +797,13 @@ public class PropertiesComponent extends ServiceSupport
         ServiceHelper.stopAndShutdownServices(sources, propertiesFunctionResolver);
     }
 
-    private void addPropertiesLocationsAsPropertiesSource(PropertiesLocation location) {
+    private void addPropertiesLocationsAsPropertiesSource(PropertiesLocation location, int order) {
         if ("ref".equals(location.getResolver())) {
-            addPropertiesSource(new RefPropertiesSource(this, location));
+            addPropertiesSource(new RefPropertiesSource(this, location, order));
         } else if ("file".equals(location.getResolver())) {
-            addPropertiesSource(new FilePropertiesSource(this, location));
+            addPropertiesSource(new FilePropertiesSource(this, location, order));
         } else if ("classpath".equals(location.getResolver())) {
-            addPropertiesSource(new ClasspathPropertiesSource(this, location));
+            addPropertiesSource(new ClasspathPropertiesSource(this, location, order));
         }
     }
 
diff --git a/core/camel-base/src/main/java/org/apache/camel/component/properties/RefPropertiesSource.java b/core/camel-base/src/main/java/org/apache/camel/component/properties/RefPropertiesSource.java
index 7b199e5cdc2..4eb90dcc5da 100644
--- a/core/camel-base/src/main/java/org/apache/camel/component/properties/RefPropertiesSource.java
+++ b/core/camel-base/src/main/java/org/apache/camel/component/properties/RefPropertiesSource.java
@@ -20,17 +20,24 @@ import java.io.FileNotFoundException;
 import java.util.Map;
 import java.util.Properties;
 
+import org.apache.camel.Ordered;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.util.OrderedProperties;
 
-public class RefPropertiesSource implements LocationPropertiesSource {
+public class RefPropertiesSource implements LocationPropertiesSource, Ordered {
 
+    private final int order;
     private final PropertiesComponent propertiesComponent;
     private final PropertiesLocation location;
 
     public RefPropertiesSource(PropertiesComponent propertiesComponent, PropertiesLocation location) {
+        this(propertiesComponent, location, 200);
+    }
+
+    public RefPropertiesSource(PropertiesComponent propertiesComponent, PropertiesLocation location, int order) {
         this.propertiesComponent = propertiesComponent;
         this.location = location;
+        this.order = order;
     }
 
     @Override
@@ -71,4 +78,10 @@ public class RefPropertiesSource implements LocationPropertiesSource {
 
         return answer;
     }
+
+    @Override
+    public int getOrder() {
+        return order;
+    }
+
 }
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 84c41283ba9..52065f24cde 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
@@ -102,6 +102,7 @@ import org.apache.camel.vault.VaultConfiguration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.camel.main.MainConstants.profilePropertyPlaceholderLocation;
 import static org.apache.camel.main.MainHelper.computeProperties;
 import static org.apache.camel.main.MainHelper.optionKey;
 import static org.apache.camel.main.MainHelper.setPropertiesOnTarget;
@@ -362,6 +363,12 @@ public abstract class BaseMainSupport extends BaseService {
         if (pc.getLocations().isEmpty()) {
             String locations = propertyPlaceholderLocations;
             if (locations == null) {
+                String profile = MainHelper.lookupPropertyFromSysOrEnv(MainConstants.PROFILE)
+                        .orElse(mainConfigurationProperties.getProfile());
+                if (profile != null) {
+                    String loc = profilePropertyPlaceholderLocation(profile);
+                    defaultPropertyPlaceholderLocation = loc + "," + defaultPropertyPlaceholderLocation;
+                }
                 locations
                         = MainHelper.lookupPropertyFromSysOrEnv(MainConstants.PROPERTY_PLACEHOLDER_LOCATION)
                                 .orElse(defaultPropertyPlaceholderLocation);
@@ -371,11 +378,11 @@ public abstract class BaseMainSupport extends BaseService {
             }
             if (!Objects.equals(locations, "false")) {
                 pc.addLocation(locations);
-                if (MainConstants.DEFAULT_PROPERTY_PLACEHOLDER_LOCATION.equals(locations)) {
-                    LOG.debug("Using properties from: {}", locations);
+                if (defaultPropertyPlaceholderLocation.equals(locations)) {
+                    LOG.debug("Properties location: {}", locations);
                 } else {
                     // if not default location then log at INFO
-                    LOG.info("Using properties from: {}", locations);
+                    LOG.info("Properties location: {}", locations);
                 }
             }
         }
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java
index caa145f5a89..7e1322d7dc0 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainCommandLineSupport.java
@@ -233,6 +233,13 @@ public abstract class MainCommandLineSupport extends MainSupport {
 
     @Override
     protected void configurePropertiesService(CamelContext camelContext) throws Exception {
+        if (mainConfigurationProperties.getProfile() != null) {
+            // setup property placeholder location to include the profile based properties file also
+            defaultPropertyPlaceholderLocation
+                    = String.format("classpath:application-%s.properties;optional=true," + defaultPropertyPlaceholderLocation,
+                            mainConfigurationProperties.getProfile());
+        }
+
         super.configurePropertiesService(camelContext);
 
         PropertiesComponent pc = camelContext.getPropertiesComponent();
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainConstants.java b/core/camel-main/src/main/java/org/apache/camel/main/MainConstants.java
index 808722a3aa4..2a0302161e5 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainConstants.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainConstants.java
@@ -23,8 +23,13 @@ public final class MainConstants {
     public static final String OVERRIDE_PROPERTIES_LOCATION = "camel.main.override-properties-location";
     public static final String PROPERTY_PLACEHOLDER_LOCATION = "camel.main.property-placeholder-location";
     public static final String PLATFORM_HTTP_SERVER = "platform-http-server";
+    public static final String PROFILE = "camel.main.profile";
 
     private MainConstants() {
     }
 
+    static String profilePropertyPlaceholderLocation(String profile) {
+        return "classpath:application-" + profile + ".properties;optional=true";
+    }
+
 }
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/ProfileConfigurer.java b/core/camel-main/src/main/java/org/apache/camel/main/ProfileConfigurer.java
index 83ce2603e0f..8af6a99701e 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/ProfileConfigurer.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/ProfileConfigurer.java
@@ -32,7 +32,11 @@ public class ProfileConfigurer {
 
     public static void configure(CamelContext camelContext, String profile, MainConfigurationProperties config)
             throws Exception {
-        if (profile == null || "prod".equals(profile)) {
+        if (profile == null) {
+            // no profile is active
+            return;
+        }
+        if ("prod".equals(profile)) {
             LOG.info("The application is starting with profile: production");
             return; // no need to do special configuration
         }
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
index ae6ef2ff17b..650de02b114 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
@@ -35,17 +35,41 @@ public class Export extends ExportBaseCommand {
 
     @Override
     protected Integer export() throws Exception {
-        File profile = new File("application.properties");
-        if (profile.exists()) {
+        // application.properties
+        doLoadAndInitProfileProperties(new File("application.properties"));
+        if (profile != null) {
+            // override from profile specific configuration
+            doLoadAndInitProfileProperties(new File("application-" + profile + ".properties"));
+        }
+
+        if (runtime == null) {
+            System.err.println("The runtime option must be specified");
+            return 1;
+        }
+        if (gav == null) {
+            System.err.println("The gav option must be specified");
+            return 1;
+        }
+
+        if ("spring-boot".equals(runtime) || "camel-spring-boot".equals(runtime)) {
+            return export(new ExportSpringBoot(getMain()));
+        } else if ("quarkus".equals(runtime) || "camel-quarkus".equals(runtime)) {
+            return export(new ExportQuarkus(getMain()));
+        } else if ("main".equals(runtime) || "camel-main".equals(runtime)) {
+            return export(new ExportCamelMain(getMain()));
+        } else {
+            System.err.println("Unknown runtime: " + runtime);
+            return 1;
+        }
+    }
+
+    private void doLoadAndInitProfileProperties(File file) throws Exception {
+        if (file.exists()) {
             Properties prop = new CamelCaseOrderedProperties();
-            RuntimeUtil.loadProperties(prop, profile);
+            RuntimeUtil.loadProperties(prop, file);
             // read runtime and gav from profile if not configured
-            if (this.runtime == null) {
-                this.runtime = prop.getProperty("camel.jbang.runtime");
-            }
-            if (this.gav == null) {
-                this.gav = prop.getProperty("camel.jbang.gav");
-            }
+            this.runtime = prop.getProperty("camel.jbang.runtime", this.runtime);
+            this.gav = prop.getProperty("camel.jbang.gav", this.gav);
             // allow configuring versions from profile
             this.javaVersion = prop.getProperty("camel.jbang.javaVersion", this.javaVersion);
             this.camelVersion = prop.getProperty("camel.jbang.camelVersion", this.camelVersion);
@@ -72,26 +96,6 @@ public class Export extends ExportBaseCommand {
                     mavenApacheSnapshotEnabled ? "true" : "false"));
             this.exclude = prop.getProperty("camel.jbang.exclude", this.exclude);
         }
-
-        if (runtime == null) {
-            System.err.println("The runtime option must be specified");
-            return 1;
-        }
-        if (gav == null) {
-            System.err.println("The gav option must be specified");
-            return 1;
-        }
-
-        if ("spring-boot".equals(runtime) || "camel-spring-boot".equals(runtime)) {
-            return export(new ExportSpringBoot(getMain()));
-        } else if ("quarkus".equals(runtime) || "camel-quarkus".equals(runtime)) {
-            return export(new ExportQuarkus(getMain()));
-        } else if ("main".equals(runtime) || "camel-main".equals(runtime)) {
-            return export(new ExportCamelMain(getMain()));
-        } else {
-            System.err.println("Unknown runtime: " + runtime);
-            return 1;
-        }
     }
 
     protected Integer export(ExportBaseCommand cmd) throws Exception {
@@ -111,6 +115,7 @@ public class Export extends ExportBaseCommand {
         cmd.javaVersion = this.javaVersion;
         cmd.camelVersion = this.camelVersion;
         cmd.kameletsVersion = this.kameletsVersion;
+        cmd.profile = this.profile;
         cmd.localKameletDir = this.localKameletDir;
         cmd.logging = this.logging;
         cmd.loggingLevel = this.loggingLevel;
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
index de639ddf831..c6c97e189d3 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
@@ -139,6 +139,10 @@ abstract class ExportBaseCommand extends CamelCommand {
             "--kamelets-version" }, description = "Apache Camel Kamelets version")
     protected String kameletsVersion;
 
+    @CommandLine.Option(names = { "--profile" }, scope = CommandLine.ScopeType.INHERIT,
+                        description = "Profile to export (dev, test, or prod).")
+    String profile;
+
     @CommandLine.Option(names = { "--local-kamelet-dir" },
                         description = "Local directory for loading Kamelets (takes precedence)")
     protected String localKameletDir;
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
index 1c6753fde44..d632644ef34 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportCamelMain.java
@@ -17,6 +17,7 @@
 package org.apache.camel.dsl.jbang.core.commands;
 
 import java.io.File;
+import java.io.FileFilter;
 import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.util.ArrayList;
@@ -99,6 +100,9 @@ class ExportCamelMain extends Export {
         srcCamelResourcesDir.mkdirs();
         File srcKameletsResourcesDir = new File(BUILD_DIR, "src/main/resources/kamelets");
         srcKameletsResourcesDir.mkdirs();
+        // copy application properties files
+        // TODO: spring boot
+        copyApplicationPropertiesFiles(srcResourcesDir);
         // copy source files
         copySourceFiles(settings, profile, srcJavaDirRoot, srcJavaDir, srcResourcesDir, srcCamelResourcesDir,
                 srcKameletsResourcesDir, srcPackageName);
@@ -151,6 +155,35 @@ class ExportCamelMain extends Export {
         return 0;
     }
 
+    protected void copyApplicationPropertiesFiles(File srcResourcesDir) throws Exception {
+        File[] files = new File(".").listFiles(f -> {
+            if (!f.isFile()) {
+                return false;
+            }
+            String ext = FileUtil.onlyExt(f.getName());
+            String name = FileUtil.onlyName(f.getName());
+            if (!"properties".equals(ext)) {
+                return false;
+            }
+            if (name.equals("application")) {
+                // skip generic as its handled specially
+                return false;
+            }
+            if (profile == null) {
+                // accept all kind of configuration files
+                return name.startsWith("application");
+            } else {
+                // only accept the configuration file that matches the profile
+                return name.equals("application-" + profile);
+            }
+        });
+        if (files != null) {
+            for (File f : files) {
+                safeCopy(f, new File(srcResourcesDir, f.getName()), true);
+            }
+        }
+    }
+
     private void createMavenPom(File settings, File profile, File pom, Set<String> deps, String packageName) throws Exception {
         String[] ids = gav.split(":");
 
@@ -330,6 +363,7 @@ class ExportCamelMain extends Export {
         IOHelper.writeText(context, new FileOutputStream(srcJavaDir + "/" + mainClassname + ".java", false));
     }
 
+
     @Override
     protected void copySourceFiles(
             File settings, File profile, File srcJavaDirRoot, File srcJavaDir, File srcResourcesDir, File srcCamelResourcesDir,
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index f380ede69ad..a6b42b06273 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -503,9 +503,6 @@ public class Run extends CamelCommand {
         writeSetting(main, profileProperties, "camel.jbang.metrics", metrics ? "true" : "false");
         writeSetting(main, profileProperties, "camel.jbang.console", console ? "true" : "false");
         writeSetting(main, profileProperties, "camel.jbang.verbose", verbose ? "true" : "false");
-        if ("dev".equals(profile)) {
-            writeSetting(main, profileProperties, "camel.jbang.backlogTracing", "true");
-        }
         // the runtime version of Camel is what is loaded via the catalog
         writeSetting(main, profileProperties, "camel.jbang.camel-version", new DefaultCamelCatalog().getCatalogVersion());
 
@@ -612,17 +609,19 @@ public class Run extends CamelCommand {
 
             // check for properties files
             if (file.endsWith(".properties")) {
-                if (!ResourceHelper.hasScheme(file) && !file.startsWith("github:")) {
-                    file = "file:" + file;
-                }
-                if (ObjectHelper.isEmpty(propertiesFiles)) {
-                    propertiesFiles = file;
-                } else {
-                    propertiesFiles = propertiesFiles + "," + file;
-                }
-                if (dev && file.startsWith("file:")) {
-                    // we can only reload if file based
-                    sjReload.add(file.substring(5));
+                if (acceptPropertiesFile(file)) {
+                    if (!ResourceHelper.hasScheme(file) && !file.startsWith("github:")) {
+                        file = "file:" + file;
+                    }
+                    if (ObjectHelper.isEmpty(propertiesFiles)) {
+                        propertiesFiles = file;
+                    } else {
+                        propertiesFiles = propertiesFiles + "," + file;
+                    }
+                    if (dev && file.startsWith("file:")) {
+                        // we can only reload if file based
+                        sjReload.add(file.substring(5));
+                    }
                 }
                 continue;
             }
@@ -725,15 +724,26 @@ public class Run extends CamelCommand {
 
         if (propertiesFiles != null) {
             String[] filesLocation = propertiesFiles.split(",");
+            // sort so general application.properties comes first (we should load profile first)
+            List<String> names = new ArrayList<>(List.of(filesLocation));
+            names.sort((o1, o2) -> {
+                // make sure application.properties is last
+                if (o1.endsWith("application.properties")) {
+                    return 1;
+                } else if (o2.endsWith("application.properties")) {
+                    return -1;
+                }
+                return 0;
+            });
             StringBuilder locations = new StringBuilder();
-            for (String file : filesLocation) {
+            for (String file : names) {
                 if (!file.startsWith("file:")) {
                     if (!file.startsWith("/")) {
                         file = FileSystems.getDefault().getPath("").toAbsolutePath() + File.separator + file;
                     }
                     file = "file://" + file;
                 }
-                if (locations.length() > 0) {
+                if (!locations.isEmpty()) {
                     locations.append(",");
                 }
                 locations.append(file);
@@ -745,9 +755,9 @@ public class Run extends CamelCommand {
             } else {
                 loc = locations.toString();
             }
-            // TODO: remove duplicates in loc
             main.addInitialProperty("camel.component.properties.location", loc);
             writeSettings("camel.component.properties.location", loc);
+            main.setPropertyPlaceholderLocations(loc);
         }
 
         // merge existing dependencies with --deps
@@ -803,6 +813,15 @@ public class Run extends CamelCommand {
         }
     }
 
+    private boolean acceptPropertiesFile(String file) {
+        String name = FileUtil.onlyName(file);
+        if (profile != null && name.startsWith("application-")) {
+            // only accept the file that matches the correct profile
+            return ("application-" + profile).equals(name);
+        }
+        return true;
+    }
+
     protected void doAddInitialProperty(KameletMain main) {
         // noop
     }
@@ -844,12 +863,37 @@ public class Run extends CamelCommand {
             return answer;
         }
 
+        // application.properties
         File profilePropertiesFile;
         if (sourceDir != null) {
             profilePropertiesFile = new File(sourceDir, "application.properties");
         } else {
             profilePropertiesFile = new File("application.properties");
         }
+        // based application-profile.properties
+        answer = doLoadAndInitProfileProperties(profilePropertiesFile);
+
+        if (profile != null) {
+            if (sourceDir != null) {
+                profilePropertiesFile = new File(sourceDir, "application-" + profile + ".properties");
+            } else {
+                profilePropertiesFile = new File("application-" + profile + ".properties");
+            }
+            // application-profile.properties should override standard application.properties
+            Properties override = doLoadAndInitProfileProperties(profilePropertiesFile);
+            if (override != null) {
+                answer.putAll(override);
+            }
+        }
+
+        if (kameletsVersion == null) {
+            kameletsVersion = VersionHelper.extractKameletsVersion();
+        }
+        return answer;
+    }
+
+    private Properties doLoadAndInitProfileProperties(File profilePropertiesFile) throws Exception {
+        Properties answer = null;
         if (profilePropertiesFile.exists()) {
             answer = loadProfileProperties(profilePropertiesFile);
             // logging level/color may be configured in the properties file
@@ -858,11 +902,6 @@ public class Run extends CamelCommand {
                     = "true".equals(answer.getProperty("loggingColor", loggingColor ? "true" : "false"));
             loggingJson
                     = "true".equals(answer.getProperty("loggingJson", loggingJson ? "true" : "false"));
-            if (propertiesFiles == null) {
-                propertiesFiles = "file:" + profilePropertiesFile.getPath();
-            } else {
-                propertiesFiles = propertiesFiles + ",file:" + profilePropertiesFile.getPath();
-            }
             repos = answer.getProperty("camel.jbang.repos", repos);
             mavenSettings = answer.getProperty("camel.jbang.maven-settings", mavenSettings);
             mavenSettingsSecurity = answer.getProperty("camel.jbang.maven-settings-security", mavenSettingsSecurity);
@@ -881,9 +920,6 @@ public class Run extends CamelCommand {
             exclude = answer.getProperty("camel.jbang.exclude", exclude);
         }
 
-        if (kameletsVersion == null) {
-            kameletsVersion = VersionHelper.extractKameletsVersion();
-        }
         return answer;
     }