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 de6f726cb3c9 Fix camel validate normalize command (#23390)
de6f726cb3c9 is described below

commit de6f726cb3c9207c21ab2b05d28b92cd6ee408e1
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu May 21 07:26:06 2026 +0200

    Fix camel validate normalize command (#23390)
    
    * chore: fix camel validate normalize command
    
    The normalize command had two bugs making it non-functional:
    
    1. Files with .camel.yaml extension were silently skipped because
       matchFile() used FileUtil.onlyExt(name) which returns "camel.yaml"
       for double extensions. Fixed by using onlyExt(name, true) for
       single-extension mode, consistent with other JBang commands.
       Same fix applied to YamlValidateCommand.
    
    2. Route reification failed for complex EIPs (CircuitBreaker, etc.)
       because the lightweight CamelContext lacked required implementations.
       Rewrote to delegate to the Run command with dumpRoutes=yaml, the
       same proven pattern used by TransformRoute.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    
    * chore: normalize command should output URIs with expanded parameters
    
    The canonical YAML DSL format should use expanded parameters as key/value
    pairs rather than inlining them as query strings in the URI.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    
    ---------
    
    Co-authored-by: Claude Opus 4.6 <[email protected]>
---
 .../camel-jbang-plugin-validate/pom.xml            |   4 -
 .../commands/validate/YamlNormalizeCommand.java    | 173 +++++++++------------
 .../commands/validate/YamlValidateCommand.java     |   2 +-
 3 files changed, 72 insertions(+), 107 deletions(-)

diff --git a/dsl/camel-jbang/camel-jbang-plugin-validate/pom.xml 
b/dsl/camel-jbang/camel-jbang-plugin-validate/pom.xml
index bc2ce1064d71..e2ab30a97939 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-validate/pom.xml
+++ b/dsl/camel-jbang/camel-jbang-plugin-validate/pom.xml
@@ -49,9 +49,5 @@
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-yaml-dsl-validator</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.apache.camel</groupId>
-            <artifactId>camel-yaml-io</artifactId>
-        </dependency>
     </dependencies>
 </project>
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlNormalizeCommand.java
 
b/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlNormalizeCommand.java
index fa2332138a25..9281ccfafd59 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlNormalizeCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlNormalizeCommand.java
@@ -16,7 +16,7 @@
  */
 package org.apache.camel.dsl.jbang.core.commands.validate;
 
-import java.io.File;
+import java.io.InputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
@@ -24,32 +24,15 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Stack;
 
-import org.apache.camel.CamelContext;
-import org.apache.camel.TypeConverterExists;
-import org.apache.camel.component.properties.PropertiesComponent;
-import org.apache.camel.component.stub.StubComponent;
 import org.apache.camel.dsl.jbang.core.commands.CamelCommand;
 import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
-import org.apache.camel.dsl.yaml.YamlRoutesBuilderLoader;
-import org.apache.camel.dsl.yaml.validator.DummyPropertiesParser;
-import org.apache.camel.dsl.yaml.validator.DummyTypeConverter;
-import org.apache.camel.impl.DefaultCamelContext;
-import org.apache.camel.main.stub.StubBeanRepository;
-import org.apache.camel.main.stub.StubDataFormat;
-import org.apache.camel.main.stub.StubEipReifier;
-import org.apache.camel.main.stub.StubLanguage;
-import org.apache.camel.main.stub.StubTransformer;
-import org.apache.camel.model.Model;
-import org.apache.camel.model.RouteDefinition;
-import org.apache.camel.model.RoutesDefinition;
-import org.apache.camel.spi.ComponentResolver;
-import org.apache.camel.spi.DataFormatResolver;
-import org.apache.camel.spi.LanguageResolver;
-import org.apache.camel.spi.TransformerResolver;
-import org.apache.camel.support.DefaultRegistry;
-import org.apache.camel.support.PluginHelper;
-import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.dsl.jbang.core.commands.Run;
+import org.apache.camel.dsl.jbang.core.common.CamelJBangConstants;
+import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
+import org.apache.camel.main.KameletMain;
 import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.StopWatch;
 import picocli.CommandLine;
 
 @CommandLine.Command(name = "normalize",
@@ -75,101 +58,87 @@ public class YamlNormalizeCommand extends CamelCommand {
 
     @Override
     public Integer doCall() throws Exception {
-        int count = 0;
-        int errors = 0;
+        List<String> matched = new ArrayList<>();
         for (String n : files) {
-            if (!matchFile(n)) {
-                continue;
-            }
-            String normalized = normalize(new File(n));
-            if (normalized == null) {
-                printer().printErr("Error normalizing: " + n);
-                errors++;
-                continue;
-            }
-            if (output != null) {
-                Path outPath = Path.of(output);
-                if (Files.isDirectory(outPath)) {
-                    outPath = outPath.resolve(Path.of(n).getFileName());
-                }
-                Files.writeString(outPath, normalized);
-                count++;
-            } else {
-                printer().println(normalized);
+            if (matchFile(n)) {
+                matched.add(n);
             }
         }
-        if (output != null) {
-            printer().println("Normalized " + count + " file(s) to " + output);
+        if (matched.isEmpty()) {
+            return 0;
         }
-        return errors > 0 ? 1 : 0;
-    }
 
-    private String normalize(File file) throws Exception {
-        DefaultRegistry registry = new DefaultRegistry();
-        registry.addBeanRepository(new StubBeanRepository("*"));
-
-        try (CamelContext camelContext = new DefaultCamelContext(registry)) {
-            camelContext.setAutoStartup(false);
-            
camelContext.getCamelContextExtension().addContextPlugin(ComponentResolver.class,
-                    (name, context) -> new StubComponent());
-            
camelContext.getCamelContextExtension().addContextPlugin(DataFormatResolver.class,
-                    (name, context) -> new StubDataFormat());
-            
camelContext.getCamelContextExtension().addContextPlugin(LanguageResolver.class,
-                    (name, context) -> new StubLanguage());
-            
camelContext.getCamelContextExtension().addContextPlugin(TransformerResolver.class,
-                    (name, context) -> new StubTransformer());
-
-            PropertiesComponent pc = (PropertiesComponent) 
camelContext.getPropertiesComponent();
-            
pc.addInitialProperty("camel.component.properties.ignoreMissingProperty", 
"true");
-            
pc.addInitialProperty("camel.component.properties.ignoreMissingLocation", 
"true");
-            pc.setPropertiesParser(new DummyPropertiesParser(camelContext));
-
-            DummyTypeConverter ec = new DummyTypeConverter();
-            var tcr = camelContext.getTypeConverterRegistry();
-            tcr.setTypeConverterExists(TypeConverterExists.Override);
-            tcr.addTypeConverter(Integer.class, String.class, ec);
-            tcr.addTypeConverter(Long.class, String.class, ec);
-            tcr.addTypeConverter(Double.class, String.class, ec);
-            tcr.addTypeConverter(Float.class, String.class, ec);
-            tcr.addTypeConverter(Byte.class, String.class, ec);
-            tcr.addTypeConverter(Boolean.class, String.class, ec);
-            tcr.addFallbackTypeConverter(ec, false);
-
-            StubEipReifier.registerStubEipReifiers(camelContext);
-
-            camelContext.start();
-
-            // load YAML routes
-            try (YamlRoutesBuilderLoader loader = new 
YamlRoutesBuilderLoader()) {
-                loader.setCamelContext(camelContext);
-                loader.start();
-                var rb = loader.doLoadRouteBuilder(
-                        ResourceHelper.fromString(file.getName(), 
Files.readString(file.toPath())));
-                camelContext.addRoutes(rb);
+        String dump = CommandLineHelper.CAMEL_JBANG_WORK_DIR + 
"/normalize-output.yaml";
+        final String target = dump;
+
+        Run run = new Run(getMain()) {
+            @Override
+            protected void doAddInitialProperty(KameletMain main) {
+                main.addInitialProperty("camel.main.dumpRoutes", "yaml");
+                main.addInitialProperty("camel.main.dumpRoutesInclude", 
"routes,rests,routeConfigurations,beans,dataFormats");
+                main.addInitialProperty("camel.main.dumpRoutesLog", "false");
+                
main.addInitialProperty("camel.main.dumpRoutesResolvePlaceholders", "false");
+                
main.addInitialProperty("camel.main.dumpRoutesUriAsParameters", "true");
+                main.addInitialProperty("camel.main.dumpRoutesOutput", target);
+                main.addInitialProperty("camel.debug.enabled", "false");
+                main.addInitialProperty(CamelJBangConstants.TRANSFORM, "true");
+                
main.addInitialProperty("camel.component.properties.ignoreMissingProperty", 
"true");
+                main.addInitialProperty("camel.language.bean.validate", 
"false");
             }
+        };
+        run.files = matched;
+        run.executionLimitOptions.maxSeconds = 1;
+        Integer exit = run.runTransform(true);
+        if (exit != null && exit != 0) {
+            return exit;
+        }
 
-            // get loaded route definitions
-            Model model = 
camelContext.getCamelContextExtension().getContextPlugin(Model.class);
-            List<RouteDefinition> routes = model.getRouteDefinitions();
+        String normalized = waitForDumpFile(Path.of(target));
+        if (normalized == null) {
+            printer().printErr("Error normalizing files");
+            return 1;
+        }
 
-            if (routes.isEmpty()) {
-                return "";
+        if (output != null) {
+            Path outPath = Path.of(output);
+            if (Files.isDirectory(outPath)) {
+                outPath = outPath.resolve("normalized.yaml");
             }
+            Files.writeString(outPath, normalized);
+            printer().println("Normalized " + matched.size() + " file(s) to " 
+ output);
+        } else {
+            printer().println(normalized);
+        }
+
+        return 0;
+    }
 
-            // dump as YAML in canonical form
-            var dumper = PluginHelper.getModelToYAMLDumper(camelContext);
-            RoutesDefinition rd = new RoutesDefinition();
-            rd.setRoutes(routes);
-            return dumper.dumpModelAsYaml(camelContext, rd, false, false, 
false, false);
+    private String waitForDumpFile(Path dumpFile) {
+        StopWatch watch = new StopWatch();
+        while (watch.taken() < 5000) {
+            try {
+                Thread.sleep(100);
+
+                if (Files.exists(dumpFile)) {
+                    try (InputStream is = Files.newInputStream(dumpFile)) {
+                        return IOHelper.loadText(is);
+                    }
+                }
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+            } catch (Exception e) {
+                // ignore
+            }
         }
+        return null;
     }
 
     private static boolean matchFile(String name) {
-        String no = FileUtil.onlyName(name).toLowerCase(Locale.ROOT);
+        String no = FileUtil.onlyName(name, true).toLowerCase(Locale.ROOT);
         if (IGNORE_FILE.equals(no)) {
             return false;
         }
-        String ext = FileUtil.onlyExt(name);
+        String ext = FileUtil.onlyExt(name, true);
         if (ext == null) {
             return false;
         }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlValidateCommand.java
 
b/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlValidateCommand.java
index 203f1cc49644..342f11dbb320 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlValidateCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlValidateCommand.java
@@ -96,7 +96,7 @@ public class YamlValidateCommand extends CamelCommand {
         if (IGNORE_FILE.equals(no)) {
             return false;
         }
-        String ext = FileUtil.onlyExt(name);
+        String ext = FileUtil.onlyExt(name, true);
         if (ext == null) {
             return false;
         }

Reply via email to