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 c3701da596f6 CAMEL-25592: camel-jbang-plugin-kubernetes - read the 
endpoints of the route sources from the route model instead of starting a 
stubbed CamelContext (#27736)
c3701da596f6 is described below

commit c3701da596f6171183b70c4c42e5186b6255b84b
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Oct 12 19:19:09 2026 +0200

    CAMEL-25592: camel-jbang-plugin-kubernetes - read the endpoints of the 
route sources from the route model instead of starting a stubbed CamelContext 
(#27736)
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
---
 .../core/commands/kubernetes/MetadataHelper.java   | 169 ++++++++++-----------
 .../commands/kubernetes/support/Capability.java    |  52 -------
 .../kubernetes/support/SourceMetadata.java         |  24 +--
 .../commands/kubernetes/KubernetesExportTest.java  |  20 +++
 .../commands/kubernetes/MetadataHelperTest.java    |  61 +++++++-
 5 files changed, 154 insertions(+), 172 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/MetadataHelper.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/MetadataHelper.java
index aa79a754a320..81550e06a6a8 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/MetadataHelper.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/MetadataHelper.java
@@ -17,14 +17,11 @@
 
 package org.apache.camel.dsl.jbang.core.commands.kubernetes;
 
-import java.util.Collection;
-import java.util.HashMap;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.TreeSet;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
@@ -33,8 +30,8 @@ import org.apache.camel.Endpoint;
 import org.apache.camel.ExtendedCamelContext;
 import org.apache.camel.Route;
 import org.apache.camel.catalog.CamelCatalog;
-import org.apache.camel.component.kamelet.KameletEndpoint;
-import org.apache.camel.dsl.jbang.core.commands.kubernetes.support.Capability;
+import org.apache.camel.dsl.jbang.core.commands.ai.RouteModel;
+import org.apache.camel.dsl.jbang.core.commands.ai.RouteNodes;
 import 
org.apache.camel.dsl.jbang.core.commands.kubernetes.support.SourceMetadata;
 import 
org.apache.camel.dsl.jbang.core.commands.kubernetes.support.StubComponentResolver;
 import 
org.apache.camel.dsl.jbang.core.commands.kubernetes.support.StubDataFormatResolver;
@@ -46,6 +43,7 @@ import org.apache.camel.dsl.jbang.core.common.Source;
 import org.apache.camel.dsl.jbang.core.common.VersionHelper;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.impl.DefaultModelReifierFactory;
+import org.apache.camel.java.in.LwJavaParser;
 import org.apache.camel.main.download.CamelCustomClassLoader;
 import org.apache.camel.main.download.DependencyDownloaderClassLoader;
 import org.apache.camel.main.download.DependencyDownloaderClassResolver;
@@ -56,7 +54,6 @@ import 
org.apache.camel.main.download.MavenDependencyDownloader;
 import org.apache.camel.model.CircuitBreakerDefinition;
 import org.apache.camel.model.FromDefinition;
 import org.apache.camel.model.Model;
-import org.apache.camel.model.ProcessorDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.reifier.DisabledReifier;
 import org.apache.camel.reifier.ProcessorReifier;
@@ -73,26 +70,36 @@ import org.apache.camel.spi.TransformerResolver;
 import org.apache.camel.support.PluginHelper;
 import org.apache.camel.support.ResourceHelper;
 import org.apache.camel.tooling.maven.MavenDownloaderImpl;
-import org.apache.camel.tooling.model.ComponentModel;
-import org.apache.camel.tooling.model.DataFormatModel;
-import org.apache.camel.tooling.model.LanguageModel;
 import org.apache.camel.util.URISupport;
 
+/**
+ * Reads what the traits need to know of a route source: the endpoints its 
routes consume from and send to. The service
+ * trait creates a Kubernetes Service when a route consumes from an http 
component or knative, and the knative trait
+ * configures the knative: channels, endpoints and events.
+ * <p/>
+ * Java and XML routes are read into the route model without starting anything 
(CAMEL-25592): Java with the Java DSL
+ * parser of camel-java-io, which neither compiles nor runs the source. YAML 
routes, Pipes and Kamelets are loaded in a
+ * stubbed CamelContext, as the YAML DSL builds the uri of an endpoint written 
with parameters with the component.
+ */
 public class MetadataHelper {
 
     public static final String STUB_PATTERN = "*";
 
-    private static final Map<String, BiConsumer<CamelCatalog, SourceMetadata>> 
COMPONENT_CUSTOMIZERS;
+    /**
+     * The steps that send to a fixed endpoint, which the routes create when 
they start. enrich, pollEnrich, poll and
+     * toD resolve their endpoint for each exchange, so a started route has 
not created it, and they are left out as the
+     * stubbed CamelContext did.
+     */
+    private static final Set<String> PRODUCERS = Set.of("to", "wireTap");
+
+    /** The Quarkus platform version of the stubbed context, looked up once. */
+    private static volatile String quarkusVersion;
 
     static {
         // the core CircuitBreaker reifier fails as it depends on a specific 
implementation provided by
         // a dedicated component/module, but as we are only inspecting the 
route to determine its capabilities,
         // we can safely disable the EIP with a disabled/stub reifier.
         ProcessorReifier.registerReifier(CircuitBreakerDefinition.class, 
DisabledReifier::new);
-
-        COMPONENT_CUSTOMIZERS = new HashMap<>();
-        COMPONENT_CUSTOMIZERS.put(Capability.PlatformHttp.getValue(),
-                (catalog, meta) -> 
meta.capabilities.add(Capability.PlatformHttp));
     }
 
     private MetadataHelper() {
@@ -104,6 +111,39 @@ public class MetadataHelper {
     }
 
     public static SourceMetadata readFromSource(CamelCatalog catalog, String 
location, String source) throws Exception {
+        String lower = location.toLowerCase(Locale.ROOT);
+        if (lower.endsWith(".java") || lower.endsWith(".xml")) {
+            RouteModel model = RouteModel.read(location, source, catalog, 
Map.of());
+            // a Java or XML file that is not a route source has no endpoints
+            return model != null ? fromModel(model, catalog) : new 
SourceMetadata();
+        }
+        return fromContext(location, source);
+    }
+
+    /**
+     * The endpoints of the routes read into the model: the route inputs, and 
the fixed endpoints the routes send to. A
+     * value only known at runtime is left out.
+     */
+    private static SourceMetadata fromModel(RouteModel model, CamelCatalog 
catalog) {
+        SourceMetadata meta = new SourceMetadata();
+        Set<String> to = new TreeSet<>();
+        for (RouteNodes.Node n : RouteNodes.of(model, catalog)) {
+            String uri = n.uri();
+            if (n.kind() != RouteNodes.Kind.ENDPOINT || uri == null || 
uri.contains(LwJavaParser.UNRESOLVED_PREFIX)) {
+                continue;
+            }
+            if ("from".equals(n.eip()) && n.parents().isEmpty()) {
+                meta.endpoints.from.add(uri);
+            } else if (PRODUCERS.contains(n.eip()) && !uri.contains("${")) {
+                to.add(uri);
+            }
+        }
+        to.removeAll(meta.endpoints.from);
+        meta.endpoints.to.addAll(to);
+        return meta;
+    }
+
+    private static SourceMetadata fromContext(String location, String source) 
throws Exception {
         try (CamelContext context = createCamelContext()) {
             Resource resource = ResourceHelper.fromString(location, source);
 
@@ -129,71 +169,13 @@ public class MetadataHelper {
                     .filter(Predicate.not(fromEndpoints::contains))
                     .collect(Collectors.toSet());
 
-            final Set<String> kamelets = context.getEndpoints().stream()
-                    .filter(KameletEndpoint.class::isInstance)
-                    .map(KameletEndpoint.class::cast)
-                    .map(KameletEndpoint::getTemplateId)
-                    .collect(Collectors.toSet());
-
             SourceMetadata meta = new SourceMetadata();
-            meta.resources.components.addAll(context.getComponentNames());
-            meta.resources.languages.addAll(context.getLanguageNames());
-            meta.resources.dataformats.addAll(context.getDataFormatNames());
-            meta.resources.kamelets.addAll(kamelets);
             meta.endpoints.from.addAll(fromEndpoints);
             meta.endpoints.to.addAll(toEndpoints);
-
-            // determine capabilities based on components
-            for (String component : meta.resources.components) {
-                // TODO: add this information to the model so we can retrieve 
them automatically
-                BiConsumer<CamelCatalog, SourceMetadata> consumer = 
COMPONENT_CUSTOMIZERS.get(component);
-                if (consumer != null) {
-                    consumer.accept(catalog, meta);
-                }
-            }
-
-            // determine capabilities based on EIP
-            for (RouteDefinition definition : model.getRouteDefinitions()) {
-                navigateRoute(
-                        definition,
-                        d -> {
-                            if (d instanceof CircuitBreakerDefinition) {
-                                
meta.capabilities.add(Capability.CircuitBreaker);
-                            }
-                        });
-            }
-
-            meta.dependencies.addAll(deps(context, catalog));
-
             return meta;
         }
     }
 
-    private static Collection<String> deps(CamelContext context, CamelCatalog 
catalog) {
-        final Set<String> answer = new TreeSet<>();
-
-        for (String name : context.getComponentNames()) {
-            ComponentModel model = catalog.componentModel(name);
-            if (model != null) {
-                answer.add(String.format("mvn:%s/%s/%s", model.getGroupId(), 
model.getArtifactId(), model.getVersion()));
-            }
-        }
-        for (String name : context.getLanguageNames()) {
-            LanguageModel model = catalog.languageModel(name);
-            if (model != null) {
-                answer.add(String.format("mvn:%s/%s/%s", model.getGroupId(), 
model.getArtifactId(), model.getVersion()));
-            }
-        }
-        for (String name : context.getDataFormatNames()) {
-            DataFormatModel model = catalog.dataFormatModel(name);
-            if (model != null) {
-                answer.add(String.format("mvn:%s/%s/%s", model.getGroupId(), 
model.getArtifactId(), model.getVersion()));
-            }
-        }
-
-        return answer;
-    }
-
     private static CamelContext createCamelContext() throws Exception {
         final StubComponentResolver componentResolver = new 
StubComponentResolver(STUB_PATTERN, true);
         final StubDataFormatResolver dataFormatResolver = new 
StubDataFormatResolver(STUB_PATTERN, true);
@@ -246,20 +228,8 @@ public class MetadataHelper {
         PluginHelper.getPackageScanClassResolver(context).addClassLoader(cl);
         
PluginHelper.getPackageScanResourceResolver(context).addClassLoader(cl);
 
-        String quarkusVersion = null;
-        try (MavenDownloaderImpl d = new MavenDownloaderImpl()) {
-            d.build();
-            quarkusVersion = QuarkusHelper
-                    .findQuarkusPlatformBom(
-                            RuntimeType.main.version(),
-                            d::resolveArtifact,
-                            true,
-                            RuntimeType.QUARKUS_EXTENSION_REGISTRY_BASE_URL,
-                            false)
-                    .version();
-        }
         ClassResolver classResolver = new DependencyDownloaderClassResolver(
-                context, new KnownDependenciesResolver(context, 
RuntimeType.SPRING_BOOT_VERSION, quarkusVersion),
+                context, new KnownDependenciesResolver(context, 
RuntimeType.SPRING_BOOT_VERSION, quarkusVersion()),
                 true);
         context.setClassResolver(classResolver);
         // re-create factory finder with download class-resolver
@@ -287,12 +257,29 @@ public class MetadataHelper {
         return context;
     }
 
-    private static void navigateRoute(ProcessorDefinition<?> root, 
Consumer<ProcessorDefinition<?>> consumer) {
-        consumer.accept(root);
-
-        for (ProcessorDefinition<?> def : root.getOutputs()) {
-            navigateRoute(def, consumer);
+    /** The Quarkus platform version for the known dependencies of the stubbed 
context: a lookup, done once. */
+    private static String quarkusVersion() throws Exception {
+        String answer = quarkusVersion;
+        if (answer == null) {
+            synchronized (MetadataHelper.class) {
+                answer = quarkusVersion;
+                if (answer == null) {
+                    try (MavenDownloaderImpl d = new MavenDownloaderImpl()) {
+                        d.build();
+                        answer = QuarkusHelper
+                                .findQuarkusPlatformBom(
+                                        RuntimeType.main.version(),
+                                        d::resolveArtifact,
+                                        true,
+                                        
RuntimeType.QUARKUS_EXTENSION_REGISTRY_BASE_URL,
+                                        false)
+                                .version();
+                    }
+                    quarkusVersion = answer;
+                }
+            }
         }
+        return answer;
     }
 
     public static boolean exposesHttpServices(CamelCatalog catalog, 
SourceMetadata sourceMetadata) {
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/support/Capability.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/support/Capability.java
deleted file mode 100644
index 4a70f2d4233e..000000000000
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/support/Capability.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.dsl.jbang.core.commands.kubernetes.support;
-
-import java.util.Objects;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonValue;
-
-public enum Capability {
-    PlatformHttp("platform-http"),
-    CircuitBreaker("circuit-breaker"),
-    Health("health"),
-    Tracing("tracing");
-
-    private final String name;
-
-    Capability(String name) {
-        this.name = name;
-    }
-
-    @JsonValue
-    public String getValue() {
-        return this.name;
-    }
-
-    @JsonCreator
-    public static Capability fromValue(String value) {
-        for (Capability c : values()) {
-            if (Objects.equals(c.name, value)) {
-                return c;
-            }
-        }
-
-        throw new IllegalArgumentException("Unsupported value: " + value);
-    }
-}
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/support/SourceMetadata.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/support/SourceMetadata.java
index 6e7c1b16e46a..c958fa34bed3 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/support/SourceMetadata.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/support/SourceMetadata.java
@@ -17,37 +17,19 @@
 
 package org.apache.camel.dsl.jbang.core.commands.kubernetes.support;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 
+/**
+ * What the traits need to know of a route source: the endpoints its routes 
consume from and send to.
+ */
 @JsonPropertyOrder(alphabetic = true)
 public class SourceMetadata {
-
-    @JsonProperty
-    public final Reources resources = new Reources();
     @JsonProperty
     public final Endpoints endpoints = new Endpoints();
-    @JsonProperty
-    public final List<Capability> capabilities = new ArrayList<>();
-    @JsonProperty
-    public final Set<String> dependencies = new TreeSet<>();
-
-    @JsonPropertyOrder(alphabetic = true)
-    public static class Reources {
-        @JsonProperty
-        public final Set<String> components = new TreeSet<>();
-        @JsonProperty
-        public final Set<String> languages = new TreeSet<>();
-        @JsonProperty
-        public final Set<String> dataformats = new TreeSet<>();
-        @JsonProperty
-        public final Set<String> kamelets = new TreeSet<>();
-    }
 
     @JsonPropertyOrder(alphabetic = true)
     public static class Endpoints {
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java
index 8ff1cc443918..b71fa46154bd 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java
@@ -17,6 +17,9 @@
 package org.apache.camel.dsl.jbang.core.commands.kubernetes;
 
 import java.io.FileInputStream;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.List;
 import java.util.Properties;
 import java.util.stream.Stream;
@@ -404,6 +407,23 @@ class KubernetesExportTest extends 
KubernetesExportBaseTestSupport {
         Assertions.assertEquals("http", 
ports.get(0).getTargetPort().getStrVal());
     }
 
+    @ParameterizedTest
+    @MethodSource("runtimeProvider")
+    public void shouldAddServiceForJavaRoute(RuntimeType rt) throws Exception {
+        // the route consumes from platform-http: read from the Java source 
without compiling it (CAMEL-25592)
+        Path source = 
Files.createTempDirectory("camel-k8s-java").resolve("PlatformHttpServer.java");
+        try (InputStream is = 
getClass().getClassLoader().getResourceAsStream("PlatformHttpServer.java")) {
+            Files.copy(is, source);
+        }
+        KubernetesExport command = createCommand(new String[] { 
source.toString() },
+                "--runtime=" + rt.runtime());
+        var exit = command.doCall();
+        Assertions.assertEquals(0, exit);
+
+        Assertions.assertTrue(hasService(rt));
+        Assertions.assertFalse(hasKnativeService(rt));
+    }
+
     @ParameterizedTest
     @MethodSource("runtimeProvider")
     public void shouldAddIngressSpec(RuntimeType rt) throws Exception {
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/MetadataHelperTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/MetadataHelperTest.java
index 06928a9c24ac..89052abbbd9e 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/MetadataHelperTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/MetadataHelperTest.java
@@ -17,10 +17,10 @@
 
 package org.apache.camel.dsl.jbang.core.commands.kubernetes;
 
-import java.util.Arrays;
+import java.util.Set;
 
 import org.apache.camel.catalog.CamelCatalog;
-import org.apache.camel.dsl.jbang.core.commands.kubernetes.support.Capability;
+import org.apache.camel.catalog.DefaultCamelCatalog;
 import 
org.apache.camel.dsl.jbang.core.commands.kubernetes.support.SourceMetadata;
 import org.apache.camel.dsl.jbang.core.common.CatalogLoader;
 import org.apache.camel.dsl.jbang.core.common.Source;
@@ -48,27 +48,72 @@ public class MetadataHelperTest {
             d.build();
             CamelCatalog catalog = 
CatalogLoader.loadQuarkusCatalog(camelQuarkusBom, d::resolveArtifact);
 
+            // a Java route is read with the Java DSL parser: the uris as the 
route has them
             Source source = 
SourceHelper.resolveSource("classpath:PlatformHttpServer.java");
             SourceMetadata metadata = MetadataHelper.readFromSource(catalog, 
source);
 
             Assertions.assertTrue(MetadataHelper.exposesHttpServices(catalog, 
metadata));
-            
Assertions.assertTrue(metadata.capabilities.contains(Capability.PlatformHttp));
-            Assertions.assertEquals(1, metadata.resources.components.size());
-            
Assertions.assertTrue(metadata.resources.components.contains("platform-http"));
             Assertions.assertEquals(1, metadata.endpoints.from.size());
-            
Assertions.assertTrue(metadata.endpoints.from.contains("platform-http:///hello?httpMethodRestrict=GET";));
+            
Assertions.assertTrue(metadata.endpoints.from.contains("platform-http:/hello?httpMethodRestrict=GET"));
             Assertions.assertEquals(0, metadata.endpoints.to.size());
 
+            // a YAML route is loaded in a stubbed CamelContext: the uris as 
the endpoints normalize them
             source = SourceHelper.resolveSource("classpath:route.yaml");
             metadata = MetadataHelper.readFromSource(catalog, source);
 
             Assertions.assertFalse(MetadataHelper.exposesHttpServices(catalog, 
metadata));
-            Assertions.assertEquals(2, metadata.resources.components.size());
-            
Assertions.assertTrue(metadata.resources.components.containsAll(Arrays.asList("timer",
 "log")));
             Assertions.assertEquals(1, metadata.endpoints.from.size());
             
Assertions.assertTrue(metadata.endpoints.from.contains("timer://tick"));
             Assertions.assertEquals(1, metadata.endpoints.to.size());
             
Assertions.assertTrue(metadata.endpoints.to.contains("log://info"));
         }
     }
+
+    @Test
+    public void testJavaRouteIsNotCompiled() throws Exception {
+        CamelCatalog catalog = new DefaultCamelCatalog();
+        // NoSuchProcessor does not exist: the source does not compile, and is 
read all the same
+        SourceMetadata metadata = MetadataHelper.readFromSource(catalog, 
"Orders.java", """
+                import org.apache.camel.builder.RouteBuilder;
+
+                public class Orders extends RouteBuilder {
+                    @Override
+                    public void configure() {
+                        from("knative:channel/orders")
+                            .process(new NoSuchProcessor())
+                            .wireTap("knative:event/order-received")
+                            .toD("knative:endpoint/${header.target}")
+                            .to("knative:endpoint/billing");
+                    }
+                }
+                """);
+
+        Assertions.assertTrue(MetadataHelper.exposesHttpServices(catalog, 
metadata));
+        Assertions.assertEquals(Set.of("knative:channel/orders"), 
metadata.endpoints.from);
+        // the toD is only known at runtime
+        Assertions.assertEquals(Set.of("knative:event/order-received", 
"knative:endpoint/billing"),
+                metadata.endpoints.to);
+    }
+
+    @Test
+    public void testXmlRoute() throws Exception {
+        CamelCatalog catalog = new DefaultCamelCatalog();
+        SourceMetadata metadata = MetadataHelper.readFromSource(catalog, 
"routes.xml", """
+                <routes xmlns="http://camel.apache.org/schema/xml-io";>
+                    <route>
+                        <from uri="platform-http:/orders"/>
+                        <to uri="kafka:orders"/>
+                    </route>
+                </routes>
+                """);
+
+        Assertions.assertTrue(MetadataHelper.exposesHttpServices(catalog, 
metadata));
+        Assertions.assertEquals(Set.of("platform-http:/orders"), 
metadata.endpoints.from);
+        Assertions.assertEquals(Set.of("kafka:orders"), metadata.endpoints.to);
+
+        // a Java or XML file that is not a route source has no endpoints
+        metadata = MetadataHelper.readFromSource(catalog, "Util.java", "public 
class Util {}");
+        Assertions.assertTrue(metadata.endpoints.from.isEmpty());
+        Assertions.assertTrue(metadata.endpoints.to.isEmpty());
+    }
 }

Reply via email to