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 c0f92eb7910f CAMEL-25719: camel-jbang - camel_catalog_doc and 
camel_catalog_find know the beans entry of the YAML DSL, and five more entries 
have samples (#28002)
c0f92eb7910f is described below

commit c0f92eb7910ff14f904ea872950f6c5fbba473bf
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Oct 17 20:29:44 2026 +0200

    CAMEL-25719: camel-jbang - camel_catalog_doc and camel_catalog_find know 
the beans entry of the YAML DSL, and five more entries have samples (#28002)
    
    A model that had to declare a Java class as a bean looked up beans four 
times in one step and was told "EIP not
    found", while camel_catalog_sample had the example. The items of beans are 
bean factories: camel_catalog_doc now
    answers for beans with the options of the beanFactory model, where the 
entry goes, how a route uses a bean, and an
    example; camel_catalog_find lists it for beans and for bean.
    
    templatedRoute, restConfiguration, transformers, validators and 
sslContextParameters had no sample, as their
    examples are on the page of what they belong to: the sample generator reads 
those pages for them now.
    
    Claude-Session: https://claude.ai/code/session_01STT6whBgK1AqsSsUKrnE8m
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
---
 dsl/camel-jbang/camel-jbang-core/pom.xml           |  6 ++
 .../dsl/jbang/core/commands/ai/eip-samples.json    | 78 ++++++++++++++++++++++
 .../dsl/jbang/core/commands/ai/CatalogDocs.java    | 48 +++++++++++++
 .../jbang/core/commands/ai/CatalogDocsTest.java    | 26 ++++++++
 .../jbang/core/commands/ai/CatalogSamplesTest.java | 14 ++++
 5 files changed, 172 insertions(+)

diff --git a/dsl/camel-jbang/camel-jbang-core/pom.xml 
b/dsl/camel-jbang/camel-jbang-core/pom.xml
index dc0753e88fa5..e8a13ffd7a55 100644
--- a/dsl/camel-jbang/camel-jbang-core/pom.xml
+++ b/dsl/camel-jbang/camel-jbang-core/pom.xml
@@ -298,6 +298,12 @@
                                 
<entryPage>../../camel-yaml-dsl/camel-yaml-dsl/src/main/docs/yaml-dsl.adoc=beans</entryPage>
                                 <!-- the contract-first rest, next to the 
path-based examples of rest-dsl -->
                                 
<entryPage>../../../docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc=rest</entryPage>
+                                <!-- the top-level entries whose examples are 
on a page about something else (CAMEL-25719) -->
+                                
<entryPage>../../../docs/user-manual/modules/ROOT/pages/route-template.adoc=templatedRoute</entryPage>
+                                
<entryPage>../../../docs/user-manual/modules/ROOT/pages/rest-dsl.adoc=restConfiguration</entryPage>
+                                
<entryPage>../../../docs/user-manual/modules/ROOT/pages/transformer.adoc=transformers</entryPage>
+                                
<entryPage>../../../docs/user-manual/modules/ROOT/pages/validator.adoc=validators</entryPage>
+                                
<entryPage>../../../docs/user-manual/modules/ROOT/pages/camel-configuration-utilities.adoc=sslContextParameters</entryPage>
                             </entryPages>
                             <!-- user manual pages that show old syntax or 
YAML that is not a Camel file -->
                             <excludes>
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/org/apache/camel/dsl/jbang/core/commands/ai/eip-samples.json
 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/org/apache/camel/dsl/jbang/core/commands/ai/eip-samples.json
index 8275e7969d73..5548570fb542 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/org/apache/camel/dsl/jbang/core/commands/ai/eip-samples.json
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/org/apache/camel/dsl/jbang/core/commands/ai/eip-samples.json
@@ -1033,6 +1033,16 @@
       "yaml": "- rest:\n    get:\n      - path: \"\/customers\/{id}\"\n        
to: \"direct:customerDetails\"\n      - path: \"\/customers\/{id}\/orders\"\n   
     to: \"direct:customerOrders\"\n        disabled: \"{{ordersEnabled}}\"\n   
 post:\n      - path: \"\/customers\/neworder\"\n        to: 
\"direct:customerNewOrder\"\n        disabled: \"true\"\n"
     }
   ],
+  "restConfiguration": [
+    {
+      "source": "rest-dsl.adoc",
+      "yaml": "- restConfiguration:\n    inlineRoutes: true\n- rest:\n    
get:\n      - path: \"\/customers\/{id}\"\n        to: 
\"direct:customerDetails\"\n      - path: \"\/customers\/{id}\/orders\"\n       
 to: \"direct:customerOrders\"\n    post:\n      - path: 
\"\/customers\/neworder\"\n        to: \"direct:customerNewOrder\"\n"
+    },
+    {
+      "source": "rest-dsl.adoc",
+      "yaml": "- restConfiguration:\n    inlineRoutes: true\n- rest:\n    
path: \"\/customers\/\"\n    get:\n      - path: \"\/{id}\"\n        to: 
\"direct:customerDetails\"\n      - path: \"\/{id}\/orders\"\n        to: 
\"direct:customerOrders\"\n    post:\n      - path: \"\/neworder\"\n        to: 
\"direct:customerNewOrder\"\n- route:\n    from:\n      uri: 
direct:customerNewOrder\n      steps:\n        - to:\n            uri: 
direct:commonCustomerNewOrder\n- route:\n    from:\n      u [...]
+    }
+  ],
   "returnAddress": [
     {
       "source": "return-address.adoc",
@@ -1419,6 +1429,12 @@
       "yaml": "- route:\n    from:\n      uri: direct:start\n      steps:\n    
    - to:\n            uri: mock:a\n        - split:\n            
shareUnitOfWork: \"true\"\n            expression:\n              tokenize:\n   
             token: \",\"\n            steps:\n              - to:\n            
      uri: mock:b\n              - to:\n                  uri: direct:line\n    
    - to:\n            uri: mock:result\n\n- route:\n    from:\n      uri: 
direct:line\n      steps:\n      [...]
     }
   ],
+  "sslContextParameters": [
+    {
+      "source": "camel-configuration-utilities.adoc",
+      "yaml": "- sslContextParameters:\n    id: mySSL\n    keyStore: 
server.p12\n    keystorePassword: changeit\n    trustStore: truststore.p12\n    
trustStorePassword: changeit\n- route:\n    from:\n      uri: direct:ssl\n      
steps:\n        - to:\n            uri: mock:ssl\n"
+    }
+  ],
   "step": [
     {
       "source": "step-eip.adoc",
@@ -1451,6 +1467,24 @@
       "yaml": "- semantic:\n    evaluation:\n      department:\n        
expert: decisions\n        type: choice\n        instructions: Which department 
should handle this message?\n        criteria:\n          billing: Invoices, 
payments and refunds\n          technical: Bugs, outages and technical 
problems\n          other: Any other request\n- route:\n    from:\n      uri: 
direct:classify\n      steps:\n        - switch:\n            selector:\n       
       language:\n                 [...]
     }
   ],
+  "templatedRoute": [
+    {
+      "source": "route-template.adoc",
+      "yaml": "- templatedRoute:\n    routeTemplateRef: \"myTemplate\"\n    
parameters:\n      - name: \"name\"\n        value: \"one\"\n      - name: 
\"greeting\"\n        value: \"Hello\"\n\n- templatedRoute:\n    
routeTemplateRef: \"myTemplate\"\n    parameters:\n      - name: \"name\"\n     
   value: \"two\"\n      - name: \"greeting\"\n        value: \"Bonjour\"\n     
 - name: \"myPeriod\"\n        value: \"5s\"\n"
+    },
+    {
+      "source": "route-template.adoc",
+      "yaml": "- templatedRoute:\n    routeTemplateRef: \"myTemplate\"\n    
routeId: \"myCoolRoute\"\n    parameters:\n      - name: \"name\"\n        
value: \"one\"\n      - name: \"greeting\"\n        value: \"hello\"\n      - 
name: \"myPeriod\"\n        value: \"5s\"\n"
+    },
+    {
+      "source": "route-template.adoc",
+      "yaml": "- templatedRoute:\n    routeTemplateRef: \"orderTemplate\"\n    
routeId: \"webOrder\"\n    prefixId: \"web\"\n    parameters:\n      - name: 
\"queue\"\n        value: \"web\"\n"
+    },
+    {
+      "source": "route-template.adoc",
+      "yaml": "- templatedRoute:\n    routeTemplateRef: \"orderTemplate\"\n    
routeId: \"ftpOrder\"\n    prefixId: \"ftp\"\n    parameters:\n      - name: 
\"queue\"\n        value: \"order.ftp\"\n"
+    }
+  ],
   "threads": [
     {
       "source": "threads-eip.adoc",
@@ -1585,6 +1619,32 @@
       "yaml": "- route:\n    from:\n      uri: direct:cheese\n      steps:\n   
     - transformDataType:\n            toType: myDataType\n        - to:\n      
      uri: log:hello\n"
     }
   ],
+  "transformers": [
+    {
+      "source": "transformer.adoc",
+      "yaml": "- transformers:\n    dataFormatTransformer:\n      fromType: 
java:com.example.Order\n      toType: \"csv:CSVOrder\"\n      bindy:\n        
type: \"Csv\"\n        classType: \"com.example.Order\"\n"
+    },
+    {
+      "source": "transformer.adoc",
+      "yaml": "- transformers:\n    endpointTransformer:\n      uri: 
component:componentPathOptions?mappingFile=myMapping.xml\n      fromType: xml\n 
     toType: json\n"
+    },
+    {
+      "source": "transformer.adoc",
+      "yaml": "- transformers:\n    customTransformer:\n      className: 
com.example.MyCustomTransformer\n      fromType: xml\n      toType: json\n"
+    },
+    {
+      "source": "transformer.adoc",
+      "yaml": "- transformers:\n    loadTransformer:\n      defaults: true\n"
+    },
+    {
+      "source": "transformer.adoc",
+      "yaml": "- transformers:\n    loadTransformer:\n      packageScan: 
\"org.apache.camel.transformer.standard\"\n"
+    },
+    {
+      "source": "transformer.adoc",
+      "yaml": "- transformers:\n    endpointTransformer:\n      uri: 
xslt:transform.xsl\n      fromType: xml:ABCOrder\n      toType: xml:XYZOrder\n"
+    }
+  ],
   "unmarshal": [
     {
       "source": "unmarshal-eip.adoc",
@@ -1605,6 +1665,24 @@
       "yaml": "- route:\n    from:\n      uri: file:inbox\n      steps:\n      
  - validate:\n            expression:\n              simple:\n                
expression: \"${header.bar} > 100\"\n        - to:\n            uri: 
bean:myServiceBean.processLine\n"
     }
   ],
+  "validators": [
+    {
+      "source": "validator.adoc",
+      "yaml": "- validators:\n    predicateValidator:\n      type: 
csv:CSVOrder\n      expression:\n        simple:\n          expression: 
\"${body} contains '{name:XOrder}'\"\n"
+    },
+    {
+      "source": "validator.adoc",
+      "yaml": "- validators:\n    endpointValidator:\n      type: xml\n      
uri: validator:xsd\/schema.xsd\n"
+    },
+    {
+      "source": "validator.adoc",
+      "yaml": "- validators:\n    customValidator:\n      type: json\n      
className: com.example.MyCustomValidator\n"
+    },
+    {
+      "source": "validator.adoc",
+      "yaml": "- validators:\n    endpointValidator:\n      type: 
xml:ABCOrder\n      uri: \"validator:xsd\/schema.xsd\"\n"
+    }
+  ],
   "weightedLoadBalancer": [
     {
       "source": "weightedLoadBalancer-eip.adoc",
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java
index 2561cabac4fb..a8584ad191b4 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java
@@ -383,6 +383,12 @@ public final class CatalogDocs {
             if (em != null) {
                 return eipDoc(catalog, em, lowerFilter, scope, includeDoc, 
null);
             }
+            if (BEANS_ENTRY.equalsIgnoreCase(name)) {
+                JsonObject beans = beansDoc(catalog, lowerFilter, scope, 
includeDoc);
+                if (beans != null) {
+                    return beans;
+                }
+            }
             if (kind != null) {
                 // an alias (fan-out, dedup, rate-limit) or the whole title 
names the EIP as well
                 JsonObject byTerm = eipByTerm(catalog, name, lowerFilter, 
scope, includeDoc);
@@ -624,6 +630,42 @@ public final class CatalogDocs {
         return result;
     }
 
+    /** The top-level entry of the YAML DSL that declares beans: a list of 
bean factories, with no model of its own. */
+    static final String BEANS_ENTRY = "beans";
+
+    private static final String BEANS_DESCRIPTION
+            = "The top-level entry of the YAML DSL that declares beans: a list 
of beans, each with a name and how to create"
+              + " it (type, properties, constructors, a factory method or a 
script)";
+
+    /**
+     * The beans entry of the YAML DSL (CAMEL-25719). Each item of its list is 
a bean factory, so the options are those
+     * of the beanFactory model, and the answer says where the entry goes and 
how a route uses a bean, with an example.
+     * A model that looked up beans before was told "EIP not found" four times 
in one step, while camel_catalog_sample
+     * had the example all along. Null when the catalog has no beanFactory 
model.
+     */
+    private static JsonObject beansDoc(CamelCatalog catalog, String filter, 
OptionScope scope, boolean includeDoc) {
+        EipModel factory = catalog.eipModel("beanFactory");
+        if (factory == null) {
+            return null;
+        }
+        JsonObject result = eipDoc(catalog, factory, filter, scope, 
includeDoc, null);
+        result.put("name", BEANS_ENTRY);
+        result.put("title", "Beans");
+        result.put("description", BEANS_DESCRIPTION + ". The options are those 
of one bean; name is required. A route uses"
+                                  + " a bean as #bean:name in an option, 
${bean:name.method} in Simple, or with the bean EIP"
+                                  + " (ref: name). The entry goes in the file 
of the routes, or in a file of its own such as"
+                                  + " beans.yaml next to them.");
+        result.put("placement", CatalogSamples.placement(BEANS_ENTRY));
+        // the example itself, short as it is, rather than a hint to fetch it 
with another call
+        JsonArray samples = (JsonArray) CatalogSamples.sample(catalog, 
BEANS_ENTRY, 1).get("samples");
+        // the hint of eipDoc names beanFactory, which is not the name to ask 
for
+        result.remove("sampleHint");
+        if (samples != null && !samples.isEmpty()) {
+            result.put("sample", ((JsonObject) 
samples.get(0)).getString("yaml"));
+        }
+        return result;
+    }
+
     /**
      * The options of the elements of an EIP that match the filter, when none 
of its own do: logStackTrace is an option
      * of the redeliveryPolicy of onException, and a filter on onException 
found nothing (CAMEL-25370).
@@ -940,6 +982,12 @@ public final class CatalogDocs {
                     matches.add(o);
                 }
             }
+            // the beans entry of the YAML DSL has no model to suggest: a 
model that wants to declare a bean asks for
+            // beans, or for bean (CAMEL-25719)
+            String key = normalizeName(term);
+            if (BEANS_ENTRY.equals(key) || "bean".equals(key)) {
+                matches.add(summary("eip", BEANS_ENTRY, "Beans", 
BEANS_DESCRIPTION, "configuration"));
+            }
         }
         if (kind == null || "bean".equals(kind)) {
             // the built-in beans: an interface name (AggregationStrategy) 
lists its implementations
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java
index 7834f9ca0935..bc790f834679 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java
@@ -277,6 +277,32 @@ class CatalogDocsTest {
                 .anyMatch(b -> b.startsWith("GroupedBodyAggregationStrategy 
(")));
     }
 
+    @Test
+    void theBeansEntryOfTheYamlDslIsKnown() throws Exception {
+        // CAMEL-25719: a model that had to declare a bean looked up beans 
four times in one step and was told "EIP not
+        // found", while camel_catalog_sample had the example; the items of 
beans are bean factories
+        for (Map<String, Object> args : List.<Map<String, Object>> 
of(Map.of("name", "beans"),
+                Map.of("name", "beans", "kind", "eip"))) {
+            JsonObject doc = catalogDoc(args);
+            assertEquals("beans", doc.getString("name"), String.valueOf(doc));
+            assertTrue(doc.getString("placement").startsWith("top-level 
entry"), doc.getString("placement"));
+            
assertTrue(doc.getString("description").contains("${bean:name.method}"), 
doc.getString("description"));
+            
assertTrue(String.valueOf(doc.get("options")).contains("properties"), 
String.valueOf(doc.get("options")));
+            assertTrue(doc.getString("sample").contains("- beans:"), 
doc.getString("sample"));
+            assertNull(doc.get("sampleHint"), "the example is in the answer");
+        }
+
+        CamelCatalog catalog = new DefaultCamelCatalog();
+        for (String term : List.of("beans", "bean")) {
+            JsonArray matches = (JsonArray) CatalogDocs.find(catalog, term, 
null, 10).get("matches");
+            assertTrue(matches.stream().anyMatch(m -> 
"beans".equals(((JsonObject) m).getString("name"))),
+                    term + ": " + matches);
+        }
+        // the bean EIP comes first for bean, which is also the name of an EIP
+        JsonArray eips = (JsonArray) CatalogDocs.find(catalog, "bean", "eip", 
10).get("matches");
+        assertEquals("bean", ((JsonObject) eips.get(0)).getString("name"));
+    }
+
     @Test
     void anEipAliasFindsTheEip() throws Exception {
         // the aliases of the EIP models (fan-out, dedup, rate-limit) are what 
a model asks with; the former
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogSamplesTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogSamplesTest.java
index 6436fcaf36f8..4c227b3beed8 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogSamplesTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogSamplesTest.java
@@ -40,6 +40,20 @@ public class CatalogSamplesTest {
         assertThat(((JsonObject) 
samples.get(0)).getString("yaml")).startsWith("- onException:");
     }
 
+    @Test
+    void theTopLevelEntriesDocumentedOnAnotherPageHaveSamples() {
+        // CAMEL-25719: their examples are on the page of what they belong to 
(route templates, the REST DSL,
+        // transformers, validators, the configuration utilities), which the 
samples did not read
+        for (String entry : List.of("templatedRoute", "restConfiguration", 
"transformers", "validators",
+                "sslContextParameters")) {
+            JsonObject o = CatalogSamples.sample(entry, 1);
+            
assertThat(o.getString("placement")).as(entry).contains("top-level");
+            JsonArray samples = (JsonArray) o.get("samples");
+            assertThat(samples).as(entry).isNotEmpty();
+            assertThat(((JsonObject) 
samples.get(0)).getString("yaml")).as(entry).startsWith("- " + entry + ":");
+        }
+    }
+
     @Test
     void kebabCaseAndPartsResolveToTheEip() {
         JsonObject o = CatalogSamples.sample("circuit-breaker", 1);

Reply via email to