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-jbang-examples.git


The following commit(s) were added to refs/heads/main by this push:
     new eee2b45  CAMEL-24808: rung 6 of the ladder: connect to one service via 
camel infra (#83)
eee2b45 is described below

commit eee2b4568eb6eabf45a10c047a3eff02a802c651
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Sep 18 19:24:46 2026 +0200

    CAMEL-24808: rung 6 of the ladder: connect to one service via camel infra 
(#83)
    
    Six examples under connect-service/, each against a service the Camel CLI 
starts with camel infra run, no compose files: sql (customers table in 
Postgres, insert with ON CONFLICT counting orders, periodic report), mqtt 
(cold-room sensors publishing on Mosquitto, alert above 8 degrees), 
kafka-orders (the route-topology example rewritten around the shop: shared 
validation, stop for a pending order, key per order, fulfilment and 
notification consumers), artemis (orders queue, intake and  [...]
    
    Co-Authored-By: Claude Fable 5.1 <[email protected]>
    Claude-Session: https://claude.ai/code/session_01Bp3538HRBPMQkb5ta9xRaj
---
 .github/workflows/build.yml                        |  16 +-
 beginner/camel-1-tribute/application.properties    |  17 -
 camel-jbang-example-catalog.json                   | 469 ++++++++++++---------
 connect-service/artemis/README.md                  |  83 ++++
 connect-service/artemis/application.properties     |   6 +
 connect-service/artemis/artemis.camel.yaml         |  38 ++
 connect-service/artemis/metadata.json              |  35 ++
 connect-service/artemis/orders/order-1001.json     |   2 +
 connect-service/artemis/orders/order-1002.json     |   2 +
 connect-service/artemis/orders/order-1003.json     |   2 +
 .../artemis/test/artemis.citrus.it.yaml            |  30 ++
 .../camel-1-tribute/README.md                      |  25 +-
 .../camel-1-tribute/application.properties         |   6 +
 .../camel-1-tribute/jms-to-file.camel.yaml         |   5 +-
 .../camel-1-tribute/metadata.json                  |  19 +-
 .../test/camel-1-tribute.citrus.it.yaml            |  26 ++
 connect-service/ftp/README.md                      |  82 ++++
 connect-service/ftp/application.properties         |   6 +
 connect-service/ftp/ftp.camel.yaml                 |  43 ++
 connect-service/ftp/metadata.json                  |  33 ++
 connect-service/ftp/orders/order-1001.json         |   2 +
 connect-service/ftp/orders/order-1002.json         |   2 +
 connect-service/ftp/orders/order-1003.json         |   2 +
 connect-service/ftp/test/ftp.citrus.it.yaml        |  35 ++
 connect-service/kafka-orders/README.md             |  95 +++++
 .../kafka-orders/application.properties            |   1 +
 .../kafka-orders/kafka-orders.camel.yaml           | 104 +++++
 connect-service/kafka-orders/metadata.json         |  38 ++
 .../kafka-orders/orders/order-1001.json            |   2 +
 .../kafka-orders/orders/order-1002.json            |   2 +
 .../kafka-orders/orders/order-1003.json            |   2 +
 .../kafka-orders/test/kafka-orders.citrus.it.yaml  |  35 ++
 connect-service/mqtt/README.md                     |  84 ++++
 connect-service/mqtt/application.properties        |   1 +
 connect-service/mqtt/metadata.json                 |  33 ++
 connect-service/mqtt/mqtt.camel.yaml               |  45 ++
 connect-service/mqtt/test/mqtt.citrus.it.yaml      |  33 ++
 connect-service/sql/README.md                      |  86 ++++
 .../sql/application.properties                     |   0
 connect-service/sql/metadata.json                  |  34 ++
 connect-service/sql/orders/order-1001.json         |   2 +
 connect-service/sql/orders/order-1002.json         |   2 +
 connect-service/sql/orders/order-1003.json         |   2 +
 connect-service/sql/sql.camel.yaml                 |  62 +++
 connect-service/sql/test/sql.citrus.it.yaml        |  35 ++
 database/sql/README.md                             |  71 ----
 database/sql/compose.yaml                          |  10 -
 database/sql/metadata.json                         |  24 --
 database/sql/sql.camel.yaml                        |  40 --
 messaging/artemis/README.md                        |  81 ----
 messaging/artemis/application.properties           |  19 -
 messaging/artemis/consumer.camel.yaml              |   9 -
 messaging/artemis/metadata.json                    |  24 --
 messaging/artemis/producer.camel.yaml              |  16 -
 messaging/ftp/README.md                            | 104 -----
 messaging/ftp/application.properties               |  24 --
 messaging/ftp/compose.yaml                         |  23 -
 messaging/ftp/ftp-kaoto.png                        | Bin 76547 -> 0 bytes
 messaging/ftp/ftp.camel.yaml                       |  17 -
 messaging/ftp/jbang.properties                     |   2 -
 messaging/ftp/metadata.json                        |  25 --
 messaging/ftp/test/citrus-application.properties   |   2 -
 messaging/ftp/test/ftp.citrus.it.yaml              |  40 --
 messaging/ftp/test/payload.xml                     |   3 -
 messaging/mqtt/README.md                           | 106 -----
 messaging/mqtt/application.properties              |  19 -
 messaging/mqtt/compose.yaml                        |   9 -
 messaging/mqtt/infra/mosquitto.conf                |   4 -
 messaging/mqtt/metadata.json                       |  28 --
 messaging/mqtt/mqtt-kaoto.png                      | Bin 81783 -> 0 bytes
 messaging/mqtt/mqtt-karavan.png                    | Bin 492600 -> 0 bytes
 messaging/mqtt/mqtt.camel.yaml                     |  25 --
 messaging/mqtt/start.sh                            |   5 -
 messaging/mqtt/test/citrus-application.properties  |   2 -
 messaging/mqtt/test/mqtt.citrus.it.yaml            |  46 --
 messaging/mqtt/test/payload-low.json               |   3 -
 messaging/mqtt/test/payload.json                   |   3 -
 observability/route-topology/README.md             |  61 ---
 .../route-topology/application.properties          |   6 -
 observability/route-topology/metadata.json         |  30 --
 .../route-topology/route-topology.camel.yaml       | 104 -----
 81 files changed, 1433 insertions(+), 1236 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 16c00ec..321f06e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -28,10 +28,18 @@ jobs:
     strategy:
       matrix:
         include:
-          - name: FTP messaging
-            path: messaging/ftp
-          - name: MQTT messaging
-            path: messaging/mqtt
+          - name: SQL database
+            path: connect-service/sql
+          - name: MQTT sensors
+            path: connect-service/mqtt
+          - name: Kafka orders
+            path: connect-service/kafka-orders
+          - name: Artemis queue
+            path: connect-service/artemis
+          - name: FTP courier
+            path: connect-service/ftp
+          - name: Camel 1.0 tribute
+            path: connect-service/camel-1-tribute
           - name: Order generator
             path: run/order-generator
           - name: Nightly report
diff --git a/beginner/camel-1-tribute/application.properties 
b/beginner/camel-1-tribute/application.properties
deleted file mode 100644
index 79bbe78..0000000
--- a/beginner/camel-1-tribute/application.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-# artemis connection factory
-camel.beans.artemisCF = 
#class:org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
-# URL for broker
-camel.beans.artemisCF.brokerURL = tcp://localhost:61616
-
-# if broker requires specific login
-camel.beans.artemisCF.user = artemis
-camel.beans.artemisCF.password = artemis
-
-# pooled connection factory
-camel.beans.poolCF = 
#class:org.messaginghub.pooled.jms.JmsPoolConnectionFactory
-camel.beans.poolCF.connectionFactory = #bean:artemisCF
-camel.beans.poolCF.maxSessionsPerConnection = 500
-camel.beans.poolCF.connectionIdleTimeout = 20000
-
-# setup JMS component to use connection factory
-camel.component.jms.connection-factory = #bean:poolCF
diff --git a/camel-jbang-example-catalog.json b/camel-jbang-example-catalog.json
index 2d873e1..c0f7bd8 100644
--- a/camel-jbang-example-catalog.json
+++ b/camel-jbang-example-catalog.json
@@ -161,41 +161,6 @@
             "ui-console/rest-api.camel.yaml"
         ]
     },
-    {
-        "name": "beginner/camel-1-tribute",
-        "title": "Camel 1.0 Tribute",
-        "description": "The very first Camel example of 2007, JMS to file: a 
timer sends a message to a queue on a running Artemis broker and the consumer 
writes each message to a file; the log shows both sides.",
-        "level": "connect-service",
-        "teaches": {
-            "components": [
-                "timer",
-                "jms",
-                "file",
-                "log"
-            ],
-            "languages": [
-                "simple"
-            ]
-        },
-        "tags": [
-            "beginner",
-            "jms",
-            "file",
-            "artemis",
-            "tribute"
-        ],
-        "bundled": true,
-        "requiresDocker": true,
-        "hasCitrusTests": false,
-        "files": [
-            "README.md",
-            "application.properties",
-            "jms-to-file.camel.yaml"
-        ],
-        "infraServices": [
-            "artemis"
-        ]
-    },
     {
         "name": "beginner/rest-api",
         "title": "REST API",
@@ -341,6 +306,263 @@
             "http-to-aws-sqs.camel.yaml"
         ]
     },
+    {
+        "name": "connect-service/artemis",
+        "title": "Artemis queue",
+        "description": "The three orders are put on the orders queue of an 
ActiveMQ Artemis broker started with camel infra, and a consumer route takes 
them off and logs the customer and line count; the connection factory is 
declared in application.properties.",
+        "level": "connect-service",
+        "teaches": {
+            "components": [
+                "jms",
+                "file",
+                "log"
+            ],
+            "eips": [
+                "setHeader",
+                "unmarshal"
+            ],
+            "languages": [
+                "simple",
+                "jsonpath"
+            ],
+            "dataformats": [
+                "json"
+            ]
+        },
+        "tags": [
+            "shop",
+            "jms",
+            "artemis",
+            "queue",
+            "messaging"
+        ],
+        "bundled": false,
+        "requiresDocker": true,
+        "hasCitrusTests": true,
+        "files": [
+            "README.md",
+            "application.properties",
+            "artemis.camel.yaml",
+            "orders/order-1001.json",
+            "orders/order-1002.json",
+            "orders/order-1003.json"
+        ],
+        "infraServices": [
+            "artemis"
+        ]
+    },
+    {
+        "name": "connect-service/camel-1-tribute",
+        "title": "Camel 1.0 tribute",
+        "description": "The very first Camel example of 2007, JMS to file: a 
timer sends ten messages to a queue on an Artemis broker started with camel 
infra, and the consumer writes each message to a file in outbox; the log shows 
both sides.",
+        "level": "connect-service",
+        "teaches": {
+            "components": [
+                "jms",
+                "file",
+                "timer",
+                "log"
+            ],
+            "eips": [
+                "setBody"
+            ],
+            "languages": [
+                "simple"
+            ]
+        },
+        "tags": [
+            "history",
+            "jms",
+            "artemis",
+            "file"
+        ],
+        "bundled": false,
+        "requiresDocker": true,
+        "hasCitrusTests": true,
+        "files": [
+            "README.md",
+            "application.properties",
+            "jms-to-file.camel.yaml"
+        ],
+        "infraServices": [
+            "artemis"
+        ]
+    },
+    {
+        "name": "connect-service/ftp",
+        "title": "FTP courier",
+        "description": "Each order on the shipments queue of an Artemis broker 
becomes a file on the courier's FTP server, both started with camel infra; the 
log shows each shipment uploaded and camel infra get ftp shows where the files 
landed.",
+        "level": "connect-service",
+        "teaches": {
+            "components": [
+                "ftp",
+                "jms",
+                "file",
+                "log"
+            ],
+            "eips": [
+                "setHeader"
+            ],
+            "languages": [
+                "simple",
+                "jsonpath"
+            ]
+        },
+        "tags": [
+            "shop",
+            "ftp",
+            "jms",
+            "artemis",
+            "courier"
+        ],
+        "bundled": false,
+        "requiresDocker": true,
+        "hasCitrusTests": true,
+        "files": [
+            "README.md",
+            "application.properties",
+            "ftp.camel.yaml",
+            "orders/order-1001.json",
+            "orders/order-1002.json",
+            "orders/order-1003.json"
+        ],
+        "infraServices": [
+            "artemis",
+            "ftp"
+        ]
+    },
+    {
+        "name": "connect-service/kafka-orders",
+        "title": "Kafka orders",
+        "description": "The three orders go through a shared validation route 
to a Kafka topic on a broker started with camel infra; the pending one is 
stopped, the paid ones are dispatched to the fulfilment and notifications 
topics, whose consumers log the picking and the email; camel cmd route-topology 
draws the flow.",
+        "level": "connect-service",
+        "teaches": {
+            "components": [
+                "kafka",
+                "file",
+                "direct",
+                "log"
+            ],
+            "eips": [
+                "multicast",
+                "choice",
+                "stop",
+                "setHeader",
+                "unmarshal"
+            ],
+            "languages": [
+                "simple",
+                "jsonpath"
+            ],
+            "dataformats": [
+                "json"
+            ]
+        },
+        "tags": [
+            "shop",
+            "kafka",
+            "topology",
+            "messaging"
+        ],
+        "bundled": false,
+        "requiresDocker": true,
+        "hasCitrusTests": true,
+        "files": [
+            "README.md",
+            "application.properties",
+            "kafka-orders.camel.yaml",
+            "orders/order-1001.json",
+            "orders/order-1002.json",
+            "orders/order-1003.json"
+        ],
+        "infraServices": [
+            "kafka"
+        ]
+    },
+    {
+        "name": "connect-service/mqtt",
+        "title": "MQTT sensors",
+        "description": "Temperature sensors in the warehouse's cold rooms 
publish JSON readings on an MQTT topic of a Mosquitto broker started with camel 
infra; a consumer logs each reading and raises a warning when a room is above 8 
degrees.",
+        "level": "connect-service",
+        "teaches": {
+            "components": [
+                "paho-mqtt5",
+                "timer",
+                "log"
+            ],
+            "eips": [
+                "choice",
+                "unmarshal"
+            ],
+            "languages": [
+                "simple"
+            ],
+            "dataformats": [
+                "json"
+            ]
+        },
+        "tags": [
+            "shop",
+            "mqtt",
+            "mosquitto",
+            "iot"
+        ],
+        "bundled": false,
+        "requiresDocker": true,
+        "hasCitrusTests": true,
+        "files": [
+            "README.md",
+            "application.properties",
+            "mqtt.camel.yaml"
+        ],
+        "infraServices": [
+            "mosquitto"
+        ]
+    },
+    {
+        "name": "connect-service/sql",
+        "title": "SQL database",
+        "description": "Against a Postgres started with camel infra, a 
customers table is created, the three orders register their customers with an 
insert that counts orders on conflict, and every ten seconds a select lists the 
customers; run it twice and the order counts go up.",
+        "level": "connect-service",
+        "teaches": {
+            "components": [
+                "sql",
+                "file",
+                "timer",
+                "log"
+            ],
+            "eips": [
+                "split",
+                "unmarshal"
+            ],
+            "languages": [
+                "simple"
+            ],
+            "dataformats": [
+                "json"
+            ]
+        },
+        "tags": [
+            "shop",
+            "sql",
+            "postgres",
+            "database"
+        ],
+        "bundled": false,
+        "requiresDocker": true,
+        "hasCitrusTests": true,
+        "files": [
+            "README.md",
+            "application.properties",
+            "orders/order-1001.json",
+            "orders/order-1002.json",
+            "orders/order-1003.json",
+            "sql.camel.yaml"
+        ],
+        "infraServices": [
+            "postgres"
+        ]
+    },
     {
         "name": "connect/file-processing",
         "title": "File processing",
@@ -467,7 +689,7 @@
         ],
         "bundled": false,
         "requiresDocker": false,
-        "hasCitrusTests": false,
+        "hasCitrusTests": true,
         "files": [
             "README.md",
             "application.properties",
@@ -475,38 +697,6 @@
             "stock.json"
         ]
     },
-    {
-        "name": "database/sql",
-        "title": "SQL Database",
-        "description": "Against a running Postgres, a table is created and a 
row inserted on startup, and every five seconds a select logs the rows; the 
datasource comes from application.properties.",
-        "level": "connect-service",
-        "teaches": {
-            "components": [
-                "timer",
-                "sql",
-                "log"
-            ],
-            "languages": [
-                "simple"
-            ]
-        },
-        "tags": [
-            "database",
-            "sql",
-            "postgres"
-        ],
-        "bundled": true,
-        "requiresDocker": true,
-        "hasCitrusTests": false,
-        "files": [
-            "README.md",
-            "application.properties",
-            "sql.camel.yaml"
-        ],
-        "infraServices": [
-            "postgres"
-        ]
-    },
     {
         "name": "eip/splitter",
         "title": "Splitter",
@@ -620,111 +810,6 @@
             "parked/order-1003.json"
         ]
     },
-    {
-        "name": "messaging/artemis",
-        "title": "Apache ActiveMQ Artemis",
-        "description": "A producer route sends a JSON order to the queue 
numbers on a running Artemis broker every second and a consumer route logs each 
one; the connection factory is declared in application.properties.",
-        "level": "connect-service",
-        "teaches": {
-            "components": [
-                "timer",
-                "jms",
-                "log"
-            ],
-            "languages": [
-                "simple"
-            ]
-        },
-        "tags": [
-            "messaging",
-            "jms",
-            "artemis"
-        ],
-        "bundled": false,
-        "requiresDocker": true,
-        "hasCitrusTests": false,
-        "files": [
-            "README.md",
-            "application.properties",
-            "consumer.camel.yaml",
-            "producer.camel.yaml"
-        ],
-        "infraServices": [
-            "artemis"
-        ]
-    },
-    {
-        "name": "messaging/ftp",
-        "title": "ActiveMQ to FTP",
-        "description": "Each message arriving on the JMS queue cheese of a 
running Artemis broker is logged and uploaded as a file to a running FTP 
server.",
-        "level": "connect-service",
-        "teaches": {
-            "components": [
-                "jms",
-                "ftp",
-                "log"
-            ],
-            "languages": [
-                "simple"
-            ]
-        },
-        "tags": [
-            "messaging",
-            "ftp",
-            "activemq"
-        ],
-        "bundled": false,
-        "requiresDocker": true,
-        "hasCitrusTests": true,
-        "files": [
-            "README.md",
-            "application.properties",
-            "ftp.camel.yaml",
-            "jbang.properties"
-        ],
-        "infraServices": [
-            "artemis",
-            "ftp"
-        ]
-    },
-    {
-        "name": "messaging/mqtt",
-        "title": "MQTT",
-        "description": "Temperature readings published as JSON on the MQTT 
topic temperature of a running broker are received, the value is extracted with 
jq, and each is logged as warm or cold.",
-        "level": "connect-service",
-        "teaches": {
-            "components": [
-                "kamelet",
-                "log"
-            ],
-            "eips": [
-                "transform",
-                "choice"
-            ],
-            "languages": [
-                "jq",
-                "simple"
-            ]
-        },
-        "tags": [
-            "messaging",
-            "mqtt",
-            "iot"
-        ],
-        "bundled": false,
-        "requiresDocker": true,
-        "hasCitrusTests": true,
-        "files": [
-            "README.md",
-            "application.properties",
-            "infra/mosquitto.conf",
-            "mqtt.camel.yaml",
-            "start.sh"
-        ],
-        "infraServices": [
-            "mosquitto"
-        ]
-    },
     {
         "name": "observability/memory-leak",
         "title": "Memory Leak",
@@ -784,44 +869,6 @@
             "orders.camel.yaml"
         ]
     },
-    {
-        "name": "observability/route-topology",
-        "title": "Route Topology",
-        "description": "A timer generates an order every five seconds and an 
HTTP endpoint accepts orders too; both flow through a shared validation route 
to Kafka, where consumers dispatch, fulfil and notify, each logging the order. 
camel cmd route-topology draws how the routes connect.",
-        "level": "connect-service",
-        "teaches": {
-            "components": [
-                "timer",
-                "platform-http",
-                "direct",
-                "kafka",
-                "log"
-            ],
-            "eips": [
-                "multicast"
-            ],
-            "languages": [
-                "simple"
-            ]
-        },
-        "tags": [
-            "topology",
-            "direct",
-            "kafka",
-            "timer"
-        ],
-        "bundled": true,
-        "requiresDocker": true,
-        "hasCitrusTests": false,
-        "files": [
-            "README.md",
-            "application.properties",
-            "route-topology.camel.yaml"
-        ],
-        "infraServices": [
-            "kafka"
-        ]
-    },
     {
         "name": "rest/openapi-client",
         "title": "OpenAPI Client",
diff --git a/connect-service/artemis/README.md 
b/connect-service/artemis/README.md
new file mode 100644
index 0000000..cad43b8
--- /dev/null
+++ b/connect-service/artemis/README.md
@@ -0,0 +1,83 @@
+# Artemis queue
+
+Orders go on a queue on an ActiveMQ Artemis broker and a consumer takes them 
off. The queue keeps the two sides
+apart: the intake keeps working when processing is down, and the broker holds 
the orders until it is back.
+
+## What you will see
+
+```text
+INFO ... artemis.camel.yaml:23 : Order ORD-1001 put on the queue
+INFO ... artemis.camel.yaml:37 : Took ORD-1001 off the queue: 2 line(s) for 
customer C-482 in DK
+INFO ... artemis.camel.yaml:23 : Order ORD-1002 put on the queue
+INFO ... artemis.camel.yaml:37 : Took ORD-1002 off the queue: 1 line(s) for 
customer C-207 in DE
+...
+```
+
+## Install Camel CLI
+
+<!-- see installation instructions in ../../install.adoc -->
+
+## Run it
+
+The example needs a running artemis, which the Camel CLI starts for you in a 
container
+(Docker or Podman must be running). In one terminal:
+
+```shell
+camel infra run artemis
+```
+
+It prints the connection details as JSON; they match `application.properties`. 
In another terminal:
+
+```shell
+camel run *
+```
+
+The broker's web console is at http://localhost:8161 (user `artemis`, password 
`artemis`), where the `orders`
+queue shows its message counts.
+
+Stop the example with `ctrl` + `c` and the service with `camel infra stop 
artemis`.
+
+## How it works
+
+- `application.properties` declares the connection factory as a bean, 
`#class:...ActiveMQConnectionFactory`,
+  with the broker URL, user and password `camel infra run artemis` prints, and 
wires it into the `jms` component.
+  The CLI downloads the Artemis client from the class name.
+- `order-intake` reads each order file and sends the text to the `orders` 
queue; `order-processing` consumes the
+  queue. JMS delivers each message to one consumer, which is what makes a 
queue a work list.
+- The order id is put in a header before sending: JMS headers travel with the 
message.
+
+## Build it step by step
+
+1. A file route on `orders` sending to `jms:queue:orders`; start the broker 
and see the messages arrive in the
+   console.
+2. Add the consumer route with a log of `${body}`.
+3. Parse the JSON and log the customer and line count; add the header.
+
+## Try changing
+
+- Stop the consumer route with `camel cmd stop-route order-processing`, drop a 
new order file in, and see it
+  wait on the queue in the console until you `start-route` again.
+- Use a topic instead of a queue, `destinationType: topic`, and add a second 
consumer route: both get every order.
+- Add `camel.beans.artemisCF.retryInterval` and other factory properties and 
see them applied.
+
+## Integration testing
+
+The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
+`test/artemis.citrus.it.yaml`, which the Camel CLI runs. The test starts the 
service itself
+with the same `camel infra` mechanism, so nothing must be running beforehand:
+
+```shell
+camel test run test/artemis.citrus.it.yaml
+```
+
+The test starts Artemis, runs the routes and verifies both sides of the queue.
+
+## Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+[let us know](https://camel.apache.org/community/support/).
+
+We also love contributors, so
+[get involved](https://camel.apache.org/community/contributing/) :-)
+
+The Camel riders!
diff --git a/connect-service/artemis/application.properties 
b/connect-service/artemis/application.properties
new file mode 100644
index 0000000..008ce7f
--- /dev/null
+++ b/connect-service/artemis/application.properties
@@ -0,0 +1,6 @@
+# The broker started by: camel infra run artemis
+camel.beans.artemisCF = 
#class:org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
+camel.beans.artemisCF.brokerURL = tcp://localhost:61616
+camel.beans.artemisCF.user = artemis
+camel.beans.artemisCF.password = artemis
+camel.component.jms.connection-factory = #bean:artemisCF
diff --git a/connect-service/artemis/artemis.camel.yaml 
b/connect-service/artemis/artemis.camel.yaml
new file mode 100644
index 0000000..8151457
--- /dev/null
+++ b/connect-service/artemis/artemis.camel.yaml
@@ -0,0 +1,38 @@
+# Orders go on a queue on an ActiveMQ Artemis broker and a consumer takes
+# them off; the queue keeps the two sides apart. Start the broker with:
+# camel infra run artemis
+- route:
+    id: order-intake
+    from:
+      uri: file
+      parameters:
+        directoryName: orders
+        noop: true
+        sortBy: "file:name"
+      steps:
+        - setHeader:
+            name: orderId
+            expression:
+              jsonpath:
+                expression: "$.orderId"
+        - to:
+            uri: jms
+            parameters:
+              destinationType: queue
+              destinationName: orders
+        - log:
+            message: "Order ${header.orderId} put on the queue"
+
+- route:
+    id: order-processing
+    from:
+      uri: jms
+      parameters:
+        destinationType: queue
+        destinationName: orders
+      steps:
+        - unmarshal:
+            json:
+              library: Jackson
+        - log:
+            message: "Took ${body[orderId]} off the queue: 
${body[lines].size()} line(s) for customer ${body[customer]} in 
${body[country]}"
diff --git a/connect-service/artemis/metadata.json 
b/connect-service/artemis/metadata.json
new file mode 100644
index 0000000..061b6a1
--- /dev/null
+++ b/connect-service/artemis/metadata.json
@@ -0,0 +1,35 @@
+{
+    "title": "Artemis queue",
+    "description": "The three orders are put on the orders queue of an 
ActiveMQ Artemis broker started with camel infra, and a consumer route takes 
them off and logs the customer and line count; the connection factory is 
declared in application.properties.",
+    "level": "connect-service",
+    "teaches": {
+        "components": [
+            "jms",
+            "file",
+            "log"
+        ],
+        "eips": [
+            "setHeader",
+            "unmarshal"
+        ],
+        "languages": [
+            "simple",
+            "jsonpath"
+        ],
+        "dataformats": [
+            "json"
+        ]
+    },
+    "tags": [
+        "shop",
+        "jms",
+        "artemis",
+        "queue",
+        "messaging"
+    ],
+    "infraServices": [
+        "artemis"
+    ],
+    "requiresDocker": true,
+    "bundled": false
+}
diff --git a/connect-service/artemis/orders/order-1001.json 
b/connect-service/artemis/orders/order-1001.json
new file mode 100644
index 0000000..3eb5f03
--- /dev/null
+++ b/connect-service/artemis/orders/order-1001.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1001", "customer": "C-482", "country": "DK", "status": "paid",
+ "lines": [{"sku": "CAMEL-TSHIRT", "qty": 2, "price": 19.95}, {"sku": 
"CAMEL-MUG", "qty": 1, "price": 9.50}]}
diff --git a/connect-service/artemis/orders/order-1002.json 
b/connect-service/artemis/orders/order-1002.json
new file mode 100644
index 0000000..bb7aa0e
--- /dev/null
+++ b/connect-service/artemis/orders/order-1002.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1002", "customer": "C-207", "country": "DE", "status": "paid",
+ "lines": [{"sku": "CAMEL-MUG", "qty": 3, "price": 9.50}]}
diff --git a/connect-service/artemis/orders/order-1003.json 
b/connect-service/artemis/orders/order-1003.json
new file mode 100644
index 0000000..9edab76
--- /dev/null
+++ b/connect-service/artemis/orders/order-1003.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1003", "customer": "C-134", "country": "US", "status": 
"pending",
+ "lines": [{"sku": "CAMEL-TSHIRT", "qty": 1, "price": 19.95}, {"sku": 
"CAMEL-CAP", "qty": 1, "price": 14.00}, {"sku": "CAMEL-MUG", "qty": 2, "price": 
9.50}]}
diff --git a/connect-service/artemis/test/artemis.citrus.it.yaml 
b/connect-service/artemis/test/artemis.citrus.it.yaml
new file mode 100644
index 0000000..1d3abaa
--- /dev/null
+++ b/connect-service/artemis/test/artemis.citrus.it.yaml
@@ -0,0 +1,30 @@
+name: artemis-test
+description: The artemis example logs what its README promises
+actions:
+  - camel:
+      infra:
+        run:
+          service: artemis
+          fixedPort: true
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "artemis"
+            file: "../artemis.camel.yaml"
+            systemProperties:
+              file: "../application.properties"
+          resources:
+            - "orders/order-1001.json"
+            - "orders/order-1002.json"
+            - "orders/order-1003.json"
+  - camel:
+      jbang:
+        verify:
+          integration: "artemis"
+          logMessage: "Order ORD-1001 put on the queue"
+  - camel:
+      jbang:
+        verify:
+          integration: "artemis"
+          logMessage: "Took ORD-1003 off the queue: 3 line(s) for customer 
C-134 in US"
diff --git a/beginner/camel-1-tribute/README.md 
b/connect-service/camel-1-tribute/README.md
similarity index 75%
rename from beginner/camel-1-tribute/README.md
rename to connect-service/camel-1-tribute/README.md
index f1c50b9..7ba2c5a 100644
--- a/beginner/camel-1-tribute/README.md
+++ b/connect-service/camel-1-tribute/README.md
@@ -41,26 +41,23 @@ Today, the same example is a single YAML file and one 
command.
 
 ### Running the example
 
-Start an Apache ActiveMQ Artemis broker:
+The example needs a running ActiveMQ Artemis broker, which the Camel CLI 
starts for you in a container
+(Docker or Podman must be running). In one terminal:
 
 ```sh
 $ camel infra run artemis
 ```
 
-Or with Docker manually:
-
-```sh
-$ docker run --detach --name mycontainer -p 61616:61616 -p 8161:8161 --rm 
apache/activemq-artemis:latest-alpine
-```
-
-Then run the example:
+It prints the broker URL, user and password; they match 
`application.properties`. In another terminal:
 
 ```sh
 $ camel run *
 ```
 
 Camel will send 10 test messages to the `test.queue` JMS queue (just like the 
original)
-and consume them back, saving each message as a file in the `test` directory.
+and consume them back, saving each message as a file in the `outbox` directory
+(the original wrote to a directory named `test`; here that name holds the 
integration test).
+Stop the broker with `camel infra stop artemis`.
 
 ### What changed in 19 years
 
@@ -85,3 +82,13 @@ We also love contributors, so
 [get involved](https://camel.apache.org/community/contributing/) :-)
 
 The Camel riders!
+
+### Integration testing
+
+The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
+`test/camel-1-tribute.citrus.it.yaml`, which the Camel CLI runs. The test 
starts the broker itself
+with `camel infra`, so nothing must be running beforehand:
+
+```sh
+$ camel test run test/camel-1-tribute.citrus.it.yaml
+```
diff --git a/connect-service/camel-1-tribute/application.properties 
b/connect-service/camel-1-tribute/application.properties
new file mode 100644
index 0000000..008ce7f
--- /dev/null
+++ b/connect-service/camel-1-tribute/application.properties
@@ -0,0 +1,6 @@
+# The broker started by: camel infra run artemis
+camel.beans.artemisCF = 
#class:org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
+camel.beans.artemisCF.brokerURL = tcp://localhost:61616
+camel.beans.artemisCF.user = artemis
+camel.beans.artemisCF.password = artemis
+camel.component.jms.connection-factory = #bean:artemisCF
diff --git a/beginner/camel-1-tribute/jms-to-file.camel.yaml 
b/connect-service/camel-1-tribute/jms-to-file.camel.yaml
similarity index 85%
rename from beginner/camel-1-tribute/jms-to-file.camel.yaml
rename to connect-service/camel-1-tribute/jms-to-file.camel.yaml
index 582d025..b40067b 100644
--- a/beginner/camel-1-tribute/jms-to-file.camel.yaml
+++ b/connect-service/camel-1-tribute/jms-to-file.camel.yaml
@@ -11,7 +11,7 @@
         - to:
             uri: file
             parameters:
-              directoryName: test
+              directoryName: outbox
 
 - route:
     id: send-test-messages
@@ -21,12 +21,13 @@
       parameters:
         timerName: sender
         repeatCount: 10
+        includeMetadata: true
         period: 1000
       steps:
         - setBody:
             expression:
               simple:
-                expression: "Test Message: 
${exchangeProperty.CamelTimerCounter}"
+                expression: "Test Message: ${header.CamelTimerCounter}"
         - log:
             message: "Sending: ${body}"
         - to:
diff --git a/beginner/camel-1-tribute/metadata.json 
b/connect-service/camel-1-tribute/metadata.json
similarity index 52%
rename from beginner/camel-1-tribute/metadata.json
rename to connect-service/camel-1-tribute/metadata.json
index be94533..a183f1a 100644
--- a/beginner/camel-1-tribute/metadata.json
+++ b/connect-service/camel-1-tribute/metadata.json
@@ -1,27 +1,30 @@
 {
-    "title": "Camel 1.0 Tribute",
-    "description": "The very first Camel example of 2007, JMS to file: a timer 
sends a message to a queue on a running Artemis broker and the consumer writes 
each message to a file; the log shows both sides.",
+    "title": "Camel 1.0 tribute",
+    "description": "The very first Camel example of 2007, JMS to file: a timer 
sends ten messages to a queue on an Artemis broker started with camel infra, 
and the consumer writes each message to a file in outbox; the log shows both 
sides.",
     "level": "connect-service",
     "teaches": {
         "components": [
-            "timer",
             "jms",
             "file",
+            "timer",
             "log"
         ],
+        "eips": [
+            "setBody"
+        ],
         "languages": [
             "simple"
         ]
     },
     "tags": [
-        "beginner",
+        "history",
         "jms",
-        "file",
         "artemis",
-        "tribute"
+        "file"
     ],
-    "bundled": true,
     "infraServices": [
         "artemis"
-    ]
+    ],
+    "requiresDocker": true,
+    "bundled": false
 }
diff --git 
a/connect-service/camel-1-tribute/test/camel-1-tribute.citrus.it.yaml 
b/connect-service/camel-1-tribute/test/camel-1-tribute.citrus.it.yaml
new file mode 100644
index 0000000..bb1d9e4
--- /dev/null
+++ b/connect-service/camel-1-tribute/test/camel-1-tribute.citrus.it.yaml
@@ -0,0 +1,26 @@
+name: camel-1-tribute-test
+description: The camel-1-tribute example logs what its README promises
+actions:
+  - camel:
+      infra:
+        run:
+          service: artemis
+          fixedPort: true
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "camel-1-tribute"
+            file: "../jms-to-file.camel.yaml"
+            systemProperties:
+              file: "../application.properties"
+  - camel:
+      jbang:
+        verify:
+          integration: "camel-1-tribute"
+          logMessage: "Sending: Test Message: 10"
+  - camel:
+      jbang:
+        verify:
+          integration: "camel-1-tribute"
+          logMessage: "Received: Test Message: 10"
diff --git a/connect-service/ftp/README.md b/connect-service/ftp/README.md
new file mode 100644
index 0000000..0bdc1d8
--- /dev/null
+++ b/connect-service/ftp/README.md
@@ -0,0 +1,82 @@
+# FTP courier
+
+Shipments are handed to the courier as files on its FTP server: an order on 
the `shipments` queue becomes one
+file per order in the courier's directory. Two services, both started by the 
CLI.
+
+## What you will see
+
+```text
+INFO ... ftp.camel.yaml:42 : Shipment ORD-1001 uploaded to the courier as 
courier/shipment-ORD-1001.json
+INFO ... ftp.camel.yaml:42 : Shipment ORD-1002 uploaded to the courier as 
courier/shipment-ORD-1002.json
+INFO ... ftp.camel.yaml:42 : Shipment ORD-1003 uploaded to the courier as 
courier/shipment-ORD-1003.json
+```
+
+## Install Camel CLI
+
+<!-- see installation instructions in ../../install.adoc -->
+
+## Run it
+
+The example needs running artemis and ftp, which the Camel CLI starts for you 
in a container
+(Docker or Podman must be running). In one terminal:
+
+```shell
+camel infra run artemis ftp
+```
+
+It prints the connection details as JSON; they match `application.properties`. 
In another terminal:
+
+```shell
+camel run *
+```
+
+The embedded FTP server keeps its files under the directory `camel infra` was 
started in;
+`camel infra get ftp` prints the exact path as `getFtpRootDir`, and the three 
files are in its `courier/`
+subdirectory.
+
+Stop the example with `ctrl` + `c` and the services with `camel infra stop 
artemis ftp`.
+
+## How it works
+
+- `ready-to-ship` reads the orders and puts each on the `shipments` queue with 
the order id in a header, the
+  same way `artemis` does.
+- `courier-upload` consumes the queue and writes each message with the `ftp` 
producer: host and port from
+  `camel infra run ftp`, user and password `admin`, `directoryName` the 
courier's folder, and `fileName` built
+  from the header. `passiveMode` is what most servers behind a firewall need.
+- `CamelFileNameProduced` is set by the producer with the name it used.
+- The FTP server here runs embedded in the `camel infra` process, no container 
needed.
+
+## Build it step by step
+
+1. A timer route that writes one fixed file with the `ftp` producer; start 
`camel infra run ftp` and find the
+   file with `camel infra get ftp`.
+2. Read the orders and write one file per order with `fileName` from a header.
+3. Put the queue in between and split the work in two routes.
+
+## Try changing
+
+- Use `sftp` instead: `camel infra run sftp` and the `sftp` component with the 
same options.
+- Add `tempPrefix: .uploading-` so the courier never picks up a half-written 
file.
+- Consume from the FTP server with `ftp://...&delete=true` in a third route 
and log what the courier gets.
+
+## Integration testing
+
+The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
+`test/ftp.citrus.it.yaml`, which the Camel CLI runs. The test starts the 
services itself
+with the same `camel infra` mechanism, so nothing must be running beforehand:
+
+```shell
+camel test run test/ftp.citrus.it.yaml
+```
+
+The test starts Artemis and the FTP server, runs the routes and verifies the 
three uploads.
+
+## Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+[let us know](https://camel.apache.org/community/support/).
+
+We also love contributors, so
+[get involved](https://camel.apache.org/community/contributing/) :-)
+
+The Camel riders!
diff --git a/connect-service/ftp/application.properties 
b/connect-service/ftp/application.properties
new file mode 100644
index 0000000..008ce7f
--- /dev/null
+++ b/connect-service/ftp/application.properties
@@ -0,0 +1,6 @@
+# The broker started by: camel infra run artemis
+camel.beans.artemisCF = 
#class:org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
+camel.beans.artemisCF.brokerURL = tcp://localhost:61616
+camel.beans.artemisCF.user = artemis
+camel.beans.artemisCF.password = artemis
+camel.component.jms.connection-factory = #bean:artemisCF
diff --git a/connect-service/ftp/ftp.camel.yaml 
b/connect-service/ftp/ftp.camel.yaml
new file mode 100644
index 0000000..f1a8fff
--- /dev/null
+++ b/connect-service/ftp/ftp.camel.yaml
@@ -0,0 +1,43 @@
+# Shipments are handed to the courier as files on its FTP server. An order on
+# the shipments queue becomes one file per order. Start both services with:
+# camel infra run artemis ftp
+- route:
+    id: ready-to-ship
+    from:
+      uri: file
+      parameters:
+        directoryName: orders
+        noop: true
+        sortBy: "file:name"
+      steps:
+        - setHeader:
+            name: orderId
+            expression:
+              jsonpath:
+                expression: "$.orderId"
+        - to:
+            uri: jms
+            parameters:
+              destinationType: queue
+              destinationName: shipments
+
+- route:
+    id: courier-upload
+    from:
+      uri: jms
+      parameters:
+        destinationType: queue
+        destinationName: shipments
+      steps:
+        - to:
+            uri: ftp
+            parameters:
+              host: localhost
+              port: 2121
+              directoryName: courier
+              username: admin
+              password: admin
+              fileName: "shipment-${header.orderId}.json"
+              passiveMode: true
+        - log:
+            message: "Shipment ${header.orderId} uploaded to the courier as 
${header.CamelFileNameProduced}"
diff --git a/connect-service/ftp/metadata.json 
b/connect-service/ftp/metadata.json
new file mode 100644
index 0000000..124592f
--- /dev/null
+++ b/connect-service/ftp/metadata.json
@@ -0,0 +1,33 @@
+{
+    "title": "FTP courier",
+    "description": "Each order on the shipments queue of an Artemis broker 
becomes a file on the courier's FTP server, both started with camel infra; the 
log shows each shipment uploaded and camel infra get ftp shows where the files 
landed.",
+    "level": "connect-service",
+    "teaches": {
+        "components": [
+            "ftp",
+            "jms",
+            "file",
+            "log"
+        ],
+        "eips": [
+            "setHeader"
+        ],
+        "languages": [
+            "simple",
+            "jsonpath"
+        ]
+    },
+    "tags": [
+        "shop",
+        "ftp",
+        "jms",
+        "artemis",
+        "courier"
+    ],
+    "infraServices": [
+        "artemis",
+        "ftp"
+    ],
+    "requiresDocker": true,
+    "bundled": false
+}
diff --git a/connect-service/ftp/orders/order-1001.json 
b/connect-service/ftp/orders/order-1001.json
new file mode 100644
index 0000000..3eb5f03
--- /dev/null
+++ b/connect-service/ftp/orders/order-1001.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1001", "customer": "C-482", "country": "DK", "status": "paid",
+ "lines": [{"sku": "CAMEL-TSHIRT", "qty": 2, "price": 19.95}, {"sku": 
"CAMEL-MUG", "qty": 1, "price": 9.50}]}
diff --git a/connect-service/ftp/orders/order-1002.json 
b/connect-service/ftp/orders/order-1002.json
new file mode 100644
index 0000000..bb7aa0e
--- /dev/null
+++ b/connect-service/ftp/orders/order-1002.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1002", "customer": "C-207", "country": "DE", "status": "paid",
+ "lines": [{"sku": "CAMEL-MUG", "qty": 3, "price": 9.50}]}
diff --git a/connect-service/ftp/orders/order-1003.json 
b/connect-service/ftp/orders/order-1003.json
new file mode 100644
index 0000000..9edab76
--- /dev/null
+++ b/connect-service/ftp/orders/order-1003.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1003", "customer": "C-134", "country": "US", "status": 
"pending",
+ "lines": [{"sku": "CAMEL-TSHIRT", "qty": 1, "price": 19.95}, {"sku": 
"CAMEL-CAP", "qty": 1, "price": 14.00}, {"sku": "CAMEL-MUG", "qty": 2, "price": 
9.50}]}
diff --git a/connect-service/ftp/test/ftp.citrus.it.yaml 
b/connect-service/ftp/test/ftp.citrus.it.yaml
new file mode 100644
index 0000000..2a6e8df
--- /dev/null
+++ b/connect-service/ftp/test/ftp.citrus.it.yaml
@@ -0,0 +1,35 @@
+name: ftp-test
+description: The ftp example logs what its README promises
+actions:
+  - camel:
+      infra:
+        run:
+          service: artemis
+          fixedPort: true
+  - camel:
+      infra:
+        run:
+          service: ftp
+          fixedPort: true
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "ftp"
+            file: "../ftp.camel.yaml"
+            systemProperties:
+              file: "../application.properties"
+          resources:
+            - "orders/order-1001.json"
+            - "orders/order-1002.json"
+            - "orders/order-1003.json"
+  - camel:
+      jbang:
+        verify:
+          integration: "ftp"
+          logMessage: "Shipment ORD-1001 uploaded to the courier as 
courier/shipment-ORD-1001.json"
+  - camel:
+      jbang:
+        verify:
+          integration: "ftp"
+          logMessage: "Shipment ORD-1003 uploaded to the courier"
diff --git a/connect-service/kafka-orders/README.md 
b/connect-service/kafka-orders/README.md
new file mode 100644
index 0000000..ab954ab
--- /dev/null
+++ b/connect-service/kafka-orders/README.md
@@ -0,0 +1,95 @@
+# Kafka orders
+
+Orders flow through validation to a Kafka topic, where two departments pick 
them up independently: fulfilment
+picks the goods, notification emails the customer. Each department is its own 
consumer, so one can be down
+while the other keeps working, and the topic keeps the orders until they catch 
up.
+
+## What you will see
+
+```text
+INFO ... kafka-orders.camel.yaml:56 : Order ORD-1001 validated
+INFO ... kafka-orders.camel.yaml:34 : Published ORD-1001 to the orders topic
+INFO ... kafka-orders.camel.yaml:56 : Order ORD-1002 validated
+INFO ... kafka-orders.camel.yaml:34 : Published ORD-1002 to the orders topic
+INFO ... kafka-orders.camel.yaml:51 : Order ORD-1003 is pending, not published
+INFO ... kafka-orders.camel.yaml:67 : Dispatching ORD-1001 from partition 0 
offset 0
+INFO ... kafka-orders.camel.yaml:90 : Fulfilment: 2 line(s) of ORD-1001 to the 
warehouse
+INFO ... kafka-orders.camel.yaml:103 : Notification: email to customer C-482 
about ORD-1001
+...
+```
+
+## Install Camel CLI
+
+<!-- see installation instructions in ../../install.adoc -->
+
+## Run it
+
+The example needs a running kafka, which the Camel CLI starts for you in a 
container
+(Docker or Podman must be running). In one terminal:
+
+```shell
+camel infra run kafka
+```
+
+It prints the connection details as JSON; they match `application.properties`. 
In another terminal:
+
+```shell
+camel run *
+```
+
+See how the routes connect, with the topics between them, while it runs:
+
+```shell
+camel cmd route-topology kafka-orders
+```
+
+Run it again and the offsets continue where they were: the topic remembers.
+
+Stop the example with `ctrl` + `c` and the service with `camel infra stop 
kafka`.
+
+## How it works
+
+- `camel.component.kafka.brokers` in `application.properties` points every 
`kafka` endpoint at the broker.
+- `incoming-orders` reads the order files, keeps the order id and status in 
headers with `jsonpath`, and calls
+  the shared `validate-order` route, which logs and `stop`s a pending order; 
`stop` ends the whole exchange,
+  so the caller does not publish it.
+- The paid order is published with `CamelKafkaKey` set to the order id, so all 
events of one order land on the
+  same partition and stay in order.
+- `dispatch` consumes `orders` and `multicast`s to two topics; `fulfilment` 
and `notification` consume those.
+  `CamelKafkaPartition` and `CamelKafkaOffset` are set by the consumer on 
every message.
+- Topics are created on first use by this broker; a production cluster usually 
has that switched off.
+
+## Build it step by step
+
+1. A file route on `orders` that publishes each file to `kafka:orders`, and a 
consumer route that logs it.
+2. Pull the validation into a `direct` route with the `choice` and `stop`.
+3. Add the `multicast` to two more topics and a consumer for each.
+4. Set the key and log partition and offset in `dispatch`.
+
+## Try changing
+
+- Kill the example while it is running and start it again: the consumers 
resume from their committed offsets.
+- Give `fulfilment` a `groupId` and start the example twice: the two instances 
share the partitions.
+- Replace the file consumer with a `platform-http` route that accepts orders 
with `POST /orders`.
+
+## Integration testing
+
+The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
+`test/kafka-orders.citrus.it.yaml`, which the Camel CLI runs. The test starts 
the service itself
+with the same `camel infra` mechanism, so nothing must be running beforehand:
+
+```shell
+camel test run test/kafka-orders.citrus.it.yaml
+```
+
+The test starts Kafka, runs the routes and verifies validation, the stopped 
order and both departments.
+
+## Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+[let us know](https://camel.apache.org/community/support/).
+
+We also love contributors, so
+[get involved](https://camel.apache.org/community/contributing/) :-)
+
+The Camel riders!
diff --git a/connect-service/kafka-orders/application.properties 
b/connect-service/kafka-orders/application.properties
new file mode 100644
index 0000000..af89cbd
--- /dev/null
+++ b/connect-service/kafka-orders/application.properties
@@ -0,0 +1 @@
+camel.component.kafka.brokers=localhost:9092
diff --git a/connect-service/kafka-orders/kafka-orders.camel.yaml 
b/connect-service/kafka-orders/kafka-orders.camel.yaml
new file mode 100644
index 0000000..92feebf
--- /dev/null
+++ b/connect-service/kafka-orders/kafka-orders.camel.yaml
@@ -0,0 +1,104 @@
+# Orders flow through validation to a Kafka topic, where fulfilment and
+# notification each pick them up. Start Kafka with: camel infra run kafka
+# See how the routes connect with: camel cmd route-topology <pid>
+- route:
+    id: incoming-orders
+    from:
+      uri: file
+      parameters:
+        directoryName: orders
+        noop: true
+        sortBy: "file:name"
+      steps:
+        - setHeader:
+            name: orderId
+            expression:
+              jsonpath:
+                expression: "$.orderId"
+        - setHeader:
+            name: status
+            expression:
+              jsonpath:
+                expression: "$.status"
+        - to:
+            uri: direct:validate-order
+        - setHeader:
+            name: CamelKafkaKey
+            expression:
+              simple:
+                expression: "${header.orderId}"
+        - to:
+            uri: kafka
+            parameters:
+              topic: orders
+        - log:
+            message: "Published ${header.orderId} to the orders topic"
+
+# Shared by every way an order can come in
+- route:
+    id: validate-order
+    from:
+      uri: direct
+      parameters:
+        name: validate-order
+      steps:
+        - choice:
+            when:
+              - expression:
+                  simple:
+                    expression: "${header.status} != 'paid'"
+                steps:
+                  - log:
+                      message: "Order ${header.orderId} is ${header.status}, 
not published"
+                  - stop: {}
+            otherwise:
+              steps:
+                - log:
+                    message: "Order ${header.orderId} validated"
+
+# Picks up orders and fans out to the two departments
+- route:
+    id: dispatch
+    from:
+      uri: kafka
+      parameters:
+        topic: orders
+      steps:
+        - log:
+            message: "Dispatching ${header.orderId} from partition 
${header.CamelKafkaPartition} offset ${header.CamelKafkaOffset}"
+        - multicast:
+            steps:
+              - to:
+                  uri: kafka
+                  parameters:
+                    topic: fulfilment
+              - to:
+                  uri: kafka
+                  parameters:
+                    topic: notifications
+
+- route:
+    id: fulfilment
+    from:
+      uri: kafka
+      parameters:
+        topic: fulfilment
+      steps:
+        - unmarshal:
+            json:
+              library: Jackson
+        - log:
+            message: "Fulfilment: ${body[lines].size()} line(s) of 
${body[orderId]} to the warehouse"
+
+- route:
+    id: notification
+    from:
+      uri: kafka
+      parameters:
+        topic: notifications
+      steps:
+        - unmarshal:
+            json:
+              library: Jackson
+        - log:
+            message: "Notification: email to customer ${body[customer]} about 
${body[orderId]}"
diff --git a/connect-service/kafka-orders/metadata.json 
b/connect-service/kafka-orders/metadata.json
new file mode 100644
index 0000000..18bd9a3
--- /dev/null
+++ b/connect-service/kafka-orders/metadata.json
@@ -0,0 +1,38 @@
+{
+    "title": "Kafka orders",
+    "description": "The three orders go through a shared validation route to a 
Kafka topic on a broker started with camel infra; the pending one is stopped, 
the paid ones are dispatched to the fulfilment and notifications topics, whose 
consumers log the picking and the email; camel cmd route-topology draws the 
flow.",
+    "level": "connect-service",
+    "teaches": {
+        "components": [
+            "kafka",
+            "file",
+            "direct",
+            "log"
+        ],
+        "eips": [
+            "multicast",
+            "choice",
+            "stop",
+            "setHeader",
+            "unmarshal"
+        ],
+        "languages": [
+            "simple",
+            "jsonpath"
+        ],
+        "dataformats": [
+            "json"
+        ]
+    },
+    "tags": [
+        "shop",
+        "kafka",
+        "topology",
+        "messaging"
+    ],
+    "infraServices": [
+        "kafka"
+    ],
+    "requiresDocker": true,
+    "bundled": false
+}
diff --git a/connect-service/kafka-orders/orders/order-1001.json 
b/connect-service/kafka-orders/orders/order-1001.json
new file mode 100644
index 0000000..3eb5f03
--- /dev/null
+++ b/connect-service/kafka-orders/orders/order-1001.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1001", "customer": "C-482", "country": "DK", "status": "paid",
+ "lines": [{"sku": "CAMEL-TSHIRT", "qty": 2, "price": 19.95}, {"sku": 
"CAMEL-MUG", "qty": 1, "price": 9.50}]}
diff --git a/connect-service/kafka-orders/orders/order-1002.json 
b/connect-service/kafka-orders/orders/order-1002.json
new file mode 100644
index 0000000..bb7aa0e
--- /dev/null
+++ b/connect-service/kafka-orders/orders/order-1002.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1002", "customer": "C-207", "country": "DE", "status": "paid",
+ "lines": [{"sku": "CAMEL-MUG", "qty": 3, "price": 9.50}]}
diff --git a/connect-service/kafka-orders/orders/order-1003.json 
b/connect-service/kafka-orders/orders/order-1003.json
new file mode 100644
index 0000000..9edab76
--- /dev/null
+++ b/connect-service/kafka-orders/orders/order-1003.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1003", "customer": "C-134", "country": "US", "status": 
"pending",
+ "lines": [{"sku": "CAMEL-TSHIRT", "qty": 1, "price": 19.95}, {"sku": 
"CAMEL-CAP", "qty": 1, "price": 14.00}, {"sku": "CAMEL-MUG", "qty": 2, "price": 
9.50}]}
diff --git a/connect-service/kafka-orders/test/kafka-orders.citrus.it.yaml 
b/connect-service/kafka-orders/test/kafka-orders.citrus.it.yaml
new file mode 100644
index 0000000..19e920b
--- /dev/null
+++ b/connect-service/kafka-orders/test/kafka-orders.citrus.it.yaml
@@ -0,0 +1,35 @@
+name: kafka-orders-test
+description: The kafka-orders example logs what its README promises
+actions:
+  - camel:
+      infra:
+        run:
+          service: kafka
+          fixedPort: true
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "kafka-orders"
+            file: "../kafka-orders.camel.yaml"
+            systemProperties:
+              file: "../application.properties"
+          resources:
+            - "orders/order-1001.json"
+            - "orders/order-1002.json"
+            - "orders/order-1003.json"
+  - camel:
+      jbang:
+        verify:
+          integration: "kafka-orders"
+          logMessage: "Order ORD-1003 is pending, not published"
+  - camel:
+      jbang:
+        verify:
+          integration: "kafka-orders"
+          logMessage: "Fulfilment: 2 line(s) of ORD-1001 to the warehouse"
+  - camel:
+      jbang:
+        verify:
+          integration: "kafka-orders"
+          logMessage: "Notification: email to customer C-207 about ORD-1002"
diff --git a/connect-service/mqtt/README.md b/connect-service/mqtt/README.md
new file mode 100644
index 0000000..5aef730
--- /dev/null
+++ b/connect-service/mqtt/README.md
@@ -0,0 +1,84 @@
+# MQTT sensors
+
+Temperature sensors in the warehouse's cold rooms publish readings over MQTT 
every two seconds. The shop
+watches the topic and raises an alert when a room gets too warm. The first 
route plays the sensors.
+
+## What you will see
+
+```text
+INFO ... mqtt.camel.yaml:44 : cold-room-2: 6 °C, ok
+WARN ... mqtt.camel.yaml:39 : cold-room-3: 10 °C, too warm, alert the warehouse
+INFO ... mqtt.camel.yaml:44 : cold-room-1: 3 °C, ok
+WARN ... mqtt.camel.yaml:39 : cold-room-1: 9 °C, too warm, alert the warehouse
+```
+
+## Install Camel CLI
+
+<!-- see installation instructions in ../../install.adoc -->
+
+## Run it
+
+The example needs a running mosquitto, which the Camel CLI starts for you in a 
container
+(Docker or Podman must be running). In one terminal:
+
+```shell
+camel infra run mosquitto
+```
+
+It prints the connection details as JSON; they match `application.properties`. 
In another terminal:
+
+```shell
+camel run *
+```
+
+Publish a reading yourself from a third terminal, and see the consumer react:
+
+```shell
+camel cmd send 
--endpoint="paho-mqtt5:warehouse/temperature?brokerUrl=tcp://localhost:1883" 
--body='{"sensor": "cold-room-9", "value": 14}'
+```
+
+Stop the example with `ctrl` + `c` and the service with `camel infra stop 
mosquitto`.
+
+## How it works
+
+- `paho-mqtt5` is the MQTT 5 client component; the topic is the endpoint path 
and the broker URL a parameter,
+  read from `application.properties` with `{{mqtt.broker.url}}`.
+- The `sensors` route publishes a JSON reading with a random room and value; a 
real warehouse has the sensors
+  publishing and only the second route would be Camel.
+- The `cold-rooms` route subscribes to the same topic, parses the JSON and 
logs at WARN above 8 degrees. MQTT
+  delivers each message to every subscriber, so several consumers can watch 
the topic.
+
+## Build it step by step
+
+1. A timer route that publishes a fixed reading to 
`paho-mqtt5:warehouse/temperature`; start the broker and
+   watch it connect.
+2. Add the consumer route with a log of `${body}` and see the readings come 
back.
+3. Randomise the reading, parse it and add the `choice` on the value.
+
+## Try changing
+
+- Subscribe with a wildcard, `warehouse/#`, and publish on 
`warehouse/humidity` as well.
+- Set `qos: 1` on both endpoints and `retained: true` on the producer, then 
start a second consumer late.
+- Point `mqtt.broker.url` at a real broker and delete the `sensors` route.
+
+## Integration testing
+
+The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
+`test/mqtt.citrus.it.yaml`, which the Camel CLI runs. The test starts the 
service itself
+with the same `camel infra` mechanism, so nothing must be running beforehand:
+
+```shell
+camel test run test/mqtt.citrus.it.yaml
+```
+
+The test starts Mosquitto, publishes a warm reading itself and verifies the 
alert.
+
+## Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+[let us know](https://camel.apache.org/community/support/).
+
+We also love contributors, so
+[get involved](https://camel.apache.org/community/contributing/) :-)
+
+The Camel riders!
diff --git a/connect-service/mqtt/application.properties 
b/connect-service/mqtt/application.properties
new file mode 100644
index 0000000..ab561c5
--- /dev/null
+++ b/connect-service/mqtt/application.properties
@@ -0,0 +1 @@
+mqtt.broker.url=tcp://localhost:1883
diff --git a/connect-service/mqtt/metadata.json 
b/connect-service/mqtt/metadata.json
new file mode 100644
index 0000000..72ec5ad
--- /dev/null
+++ b/connect-service/mqtt/metadata.json
@@ -0,0 +1,33 @@
+{
+    "title": "MQTT sensors",
+    "description": "Temperature sensors in the warehouse's cold rooms publish 
JSON readings on an MQTT topic of a Mosquitto broker started with camel infra; 
a consumer logs each reading and raises a warning when a room is above 8 
degrees.",
+    "level": "connect-service",
+    "teaches": {
+        "components": [
+            "paho-mqtt5",
+            "timer",
+            "log"
+        ],
+        "eips": [
+            "choice",
+            "unmarshal"
+        ],
+        "languages": [
+            "simple"
+        ],
+        "dataformats": [
+            "json"
+        ]
+    },
+    "tags": [
+        "shop",
+        "mqtt",
+        "mosquitto",
+        "iot"
+    ],
+    "infraServices": [
+        "mosquitto"
+    ],
+    "requiresDocker": true,
+    "bundled": false
+}
diff --git a/connect-service/mqtt/mqtt.camel.yaml 
b/connect-service/mqtt/mqtt.camel.yaml
new file mode 100644
index 0000000..abb2242
--- /dev/null
+++ b/connect-service/mqtt/mqtt.camel.yaml
@@ -0,0 +1,45 @@
+# Temperature sensors in the warehouse's cold rooms publish readings over
+# MQTT; the shop watches the topic and raises an alert when a room gets too
+# warm. Start the broker with: camel infra run mosquitto
+- route:
+    id: sensors
+    from:
+      uri: timer
+      parameters:
+        timerName: sensors
+        period: 2000
+      steps:
+        - setBody:
+            expression:
+              simple:
+                expression: '{"sensor": "cold-room-${random(1,4)}", "value": 
${random(2,12)}}'
+        - to:
+            uri: paho-mqtt5
+            parameters:
+              topic: warehouse/temperature
+              brokerUrl: "{{mqtt.broker.url}}"
+
+- route:
+    id: cold-rooms
+    from:
+      uri: paho-mqtt5
+      parameters:
+        topic: warehouse/temperature
+        brokerUrl: "{{mqtt.broker.url}}"
+      steps:
+        - unmarshal:
+            json:
+              library: Jackson
+        - choice:
+            when:
+              - expression:
+                  simple:
+                    expression: "${body[value]} > 8"
+                steps:
+                  - log:
+                      loggingLevel: WARN
+                      message: "${body[sensor]}: ${body[value]} °C, too warm, 
alert the warehouse"
+            otherwise:
+              steps:
+                - log:
+                    message: "${body[sensor]}: ${body[value]} °C, ok"
diff --git a/connect-service/mqtt/test/mqtt.citrus.it.yaml 
b/connect-service/mqtt/test/mqtt.citrus.it.yaml
new file mode 100644
index 0000000..e5b6f31
--- /dev/null
+++ b/connect-service/mqtt/test/mqtt.citrus.it.yaml
@@ -0,0 +1,33 @@
+name: mqtt-test
+description: The mqtt example raises an alert for a warm reading
+actions:
+  - camel:
+      infra:
+        run:
+          service: mosquitto
+          fixedPort: true
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "mqtt"
+            file: "../mqtt.camel.yaml"
+            systemProperties:
+              file: "../application.properties"
+  - camel:
+      jbang:
+        verify:
+          integration: "mqtt"
+          logMessage: "°C, ok"
+  - camel:
+      startContext: {}
+  - send:
+      endpoint: 
"camel:paho-mqtt5:warehouse/temperature?brokerUrl=tcp://localhost:1883&clientId=citrus-sensor"
+      message:
+        body:
+          data: '{"sensor": "cold-room-9", "value": 14}'
+  - camel:
+      jbang:
+        verify:
+          integration: "mqtt"
+          logMessage: "cold-room-9: 14 °C, too warm, alert the warehouse"
diff --git a/connect-service/sql/README.md b/connect-service/sql/README.md
new file mode 100644
index 0000000..bc6ee2c
--- /dev/null
+++ b/connect-service/sql/README.md
@@ -0,0 +1,86 @@
+# SQL database
+
+The shop's customers in a Postgres table: one row per customer, with the 
number of orders they placed.
+The three orders register their customers; a report lists the table.
+
+## What you will see
+
+```text
+INFO ... sql.camel.yaml:16 : Table customers is ready
+INFO ... sql.camel.yaml:38 : Customer C-482 from DK registered with order 
ORD-1001
+INFO ... sql.camel.yaml:38 : Customer C-207 from DE registered with order 
ORD-1002
+INFO ... sql.camel.yaml:38 : Customer C-134 from US registered with order 
ORD-1003
+INFO ... sql.camel.yaml:54 : 3 customer(s) in the table
+INFO ... sql.camel.yaml:61 :   C-134 (US): 1 order(s)
+INFO ... sql.camel.yaml:61 :   C-207 (DE): 1 order(s)
+INFO ... sql.camel.yaml:61 :   C-482 (DK): 1 order(s)
+```
+
+## Install Camel CLI
+
+<!-- see installation instructions in ../../install.adoc -->
+
+## Run it
+
+The example needs a running postgres, which the Camel CLI starts for you in a 
container
+(Docker or Podman must be running). In one terminal:
+
+```shell
+camel infra run postgres
+```
+
+It prints the connection details as JSON; they match `application.properties`. 
In another terminal:
+
+```shell
+camel run *
+```
+
+Run it a second time while the database is still up: the customers are already 
there, so the insert's
+`ON CONFLICT` branch counts a second order for each.
+
+Stop the example with `ctrl` + `c` and the service with `camel infra stop 
postgres`.
+
+## How it works
+
+- `application.properties` declares the datasource with the 
`spring.datasource.*` keys the CLI understands:
+  URL, user and password as `camel infra run postgres` prints them, plus the 
driver class, from which the CLI
+  works out the JDBC driver to download.
+- The `sql` component runs the query in the endpoint URI. The first route 
creates the table once.
+- The insert uses named parameters, `:#${body[customer]}`: the value comes 
from the message, so there is no
+  string concatenation and no SQL injection. `noop: true` keeps the order as 
the body instead of the update count.
+- A select returns a list of maps, one per row; the report logs the size and 
splits it to log each row.
+
+## Build it step by step
+
+1. A timer route with `sql:CREATE TABLE ...` and a log; run it, then `camel 
infra run postgres` in the other
+   terminal and watch the retry succeed.
+2. Add the file route on `orders` with the insert; run twice and see the 
conflict error, then add `ON CONFLICT`.
+3. Add the report timer with the select and log `${body}` to see the list of 
maps, then split it.
+
+## Try changing
+
+- Add a `WHERE country = :#${header.country}` select behind a `direct` route 
and call it from `camel cmd send`.
+- Switch to `camel infra run mysql` and adapt the URL, driver and the `ON 
CONFLICT` clause.
+- Replace `noop: true` by a log of `${header.CamelSqlUpdateCount}` after the 
insert.
+
+## Integration testing
+
+The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
+`test/sql.citrus.it.yaml`, which the Camel CLI runs. The test starts the 
service itself
+with the same `camel infra` mechanism, so nothing must be running beforehand:
+
+```shell
+camel test run test/sql.citrus.it.yaml
+```
+
+The test starts Postgres, runs the routes and verifies the registered 
customers and the report.
+
+## Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+[let us know](https://camel.apache.org/community/support/).
+
+We also love contributors, so
+[get involved](https://camel.apache.org/community/contributing/) :-)
+
+The Camel riders!
diff --git a/database/sql/application.properties 
b/connect-service/sql/application.properties
similarity index 100%
rename from database/sql/application.properties
rename to connect-service/sql/application.properties
diff --git a/connect-service/sql/metadata.json 
b/connect-service/sql/metadata.json
new file mode 100644
index 0000000..b4c29cf
--- /dev/null
+++ b/connect-service/sql/metadata.json
@@ -0,0 +1,34 @@
+{
+    "title": "SQL database",
+    "description": "Against a Postgres started with camel infra, a customers 
table is created, the three orders register their customers with an insert that 
counts orders on conflict, and every ten seconds a select lists the customers; 
run it twice and the order counts go up.",
+    "level": "connect-service",
+    "teaches": {
+        "components": [
+            "sql",
+            "file",
+            "timer",
+            "log"
+        ],
+        "eips": [
+            "split",
+            "unmarshal"
+        ],
+        "languages": [
+            "simple"
+        ],
+        "dataformats": [
+            "json"
+        ]
+    },
+    "tags": [
+        "shop",
+        "sql",
+        "postgres",
+        "database"
+    ],
+    "infraServices": [
+        "postgres"
+    ],
+    "requiresDocker": true,
+    "bundled": false
+}
diff --git a/connect-service/sql/orders/order-1001.json 
b/connect-service/sql/orders/order-1001.json
new file mode 100644
index 0000000..3eb5f03
--- /dev/null
+++ b/connect-service/sql/orders/order-1001.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1001", "customer": "C-482", "country": "DK", "status": "paid",
+ "lines": [{"sku": "CAMEL-TSHIRT", "qty": 2, "price": 19.95}, {"sku": 
"CAMEL-MUG", "qty": 1, "price": 9.50}]}
diff --git a/connect-service/sql/orders/order-1002.json 
b/connect-service/sql/orders/order-1002.json
new file mode 100644
index 0000000..bb7aa0e
--- /dev/null
+++ b/connect-service/sql/orders/order-1002.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1002", "customer": "C-207", "country": "DE", "status": "paid",
+ "lines": [{"sku": "CAMEL-MUG", "qty": 3, "price": 9.50}]}
diff --git a/connect-service/sql/orders/order-1003.json 
b/connect-service/sql/orders/order-1003.json
new file mode 100644
index 0000000..9edab76
--- /dev/null
+++ b/connect-service/sql/orders/order-1003.json
@@ -0,0 +1,2 @@
+{"orderId": "ORD-1003", "customer": "C-134", "country": "US", "status": 
"pending",
+ "lines": [{"sku": "CAMEL-TSHIRT", "qty": 1, "price": 19.95}, {"sku": 
"CAMEL-CAP", "qty": 1, "price": 14.00}, {"sku": "CAMEL-MUG", "qty": 2, "price": 
9.50}]}
diff --git a/connect-service/sql/sql.camel.yaml 
b/connect-service/sql/sql.camel.yaml
new file mode 100644
index 0000000..ae92127
--- /dev/null
+++ b/connect-service/sql/sql.camel.yaml
@@ -0,0 +1,62 @@
+# The shop's customers in a Postgres table: one row per customer with the
+# number of orders they placed. Start the database with: camel infra run 
postgres
+- route:
+    id: create-table
+    from:
+      uri: timer
+      parameters:
+        timerName: setup
+        repeatCount: 1
+        delay: 0
+      steps:
+        - to:
+            uri: sql
+            parameters:
+              query: "CREATE TABLE IF NOT EXISTS customers (id varchar(10) 
PRIMARY KEY, country varchar(2), orders integer)"
+        - log:
+            message: "Table customers is ready"
+
+- route:
+    id: register-customers
+    from:
+      uri: file
+      parameters:
+        directoryName: orders
+        noop: true
+        sortBy: "file:name"
+        initialDelay: 2000
+      steps:
+        - unmarshal:
+            json:
+              library: Jackson
+        # named parameters come from the message with :#, noop keeps the body
+        - to:
+            uri: sql
+            parameters:
+              query: "INSERT INTO customers (id, country, orders) VALUES 
(:#${body[customer]}, :#${body[country]}, 1) ON CONFLICT (id) DO UPDATE SET 
orders = customers.orders + 1"
+              noop: true
+        - log:
+            message: "Customer ${body[customer]} from ${body[country]} 
registered with order ${body[orderId]}"
+
+- route:
+    id: customer-report
+    from:
+      uri: timer
+      parameters:
+        timerName: report
+        delay: 5000
+        period: 10000
+      steps:
+        - to:
+            uri: sql
+            parameters:
+              query: "SELECT id, country, orders FROM customers ORDER BY id"
+        - log:
+            message: "${body.size()} customer(s) in the table"
+        - split:
+            expression:
+              simple:
+                expression: "${body}"
+            steps:
+              - log:
+                  message: "  ${body[id]} (${body[country]}): ${body[orders]} 
order(s)"
diff --git a/connect-service/sql/test/sql.citrus.it.yaml 
b/connect-service/sql/test/sql.citrus.it.yaml
new file mode 100644
index 0000000..2c94491
--- /dev/null
+++ b/connect-service/sql/test/sql.citrus.it.yaml
@@ -0,0 +1,35 @@
+name: sql-test
+description: The sql example logs what its README promises
+actions:
+  - camel:
+      infra:
+        run:
+          service: postgres
+          fixedPort: true
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "sql"
+            file: "../sql.camel.yaml"
+            systemProperties:
+              file: "../application.properties"
+          resources:
+            - "orders/order-1001.json"
+            - "orders/order-1002.json"
+            - "orders/order-1003.json"
+  - camel:
+      jbang:
+        verify:
+          integration: "sql"
+          logMessage: "Customer C-482 from DK registered with order ORD-1001"
+  - camel:
+      jbang:
+        verify:
+          integration: "sql"
+          logMessage: "3 customer(s) in the table"
+  - camel:
+      jbang:
+        verify:
+          integration: "sql"
+          logMessage: "C-207 (DE): 1 order(s)"
diff --git a/database/sql/README.md b/database/sql/README.md
deleted file mode 100644
index 25d3afc..0000000
--- a/database/sql/README.md
+++ /dev/null
@@ -1,71 +0,0 @@
-## SQL
-
-This example shows how to use a SQL database with Camel.
-
-The example comes with a `docker compose` file for running a local Postgres 
database.
-There is also a `application.properties` configuration file that setup
-a JDBC `DataSource` for connecting to the database.
-
-### Install JBang
-
-First install JBang according to https://www.jbang.dev
-
-When JBang is installed then you should be able to run from a shell:
-
-```sh
-$ jbang --version
-```
-
-This will output the version of JBang.
-
-To run this example you can either install Camel on JBang via:
-
-```sh
-$ jbang app install camel@apache/camel
-```
-
-Which allows to run Camel CLI with `camel` as shown below.
-
-### How to run
-
-You can run PostgreSQL using
-
-```sh
-$ camel infra run postgres
-```
-
-Alternatively, you can run it with Docker Compose:
-
-```sh
-$ docker compose up
-```
-
-or manually with just Docker
-
-```sh
-$ docker run \
---env POSTGRES_DB=test \
---env POSTGRES_USER=postgres \
---env POSTGRES_PASSWORD=postgres \
---publish 5432:5432 \
-postgres
-```
-
-After Docker starts and pulls down the Postgres image, you can run this 
example using:
-
-```sh
-$ camel run *
-```
-
-This runs several routes. The first one sets up a new table called _users_, 
the second one fills
-it with data and the third one runs a query on that table and logs the results.
-
-### Help and contributions
-
-If you hit any problem using Camel or have some feedback, then please
-[let us know](https://camel.apache.org/community/support/).
-
-We also love contributors, so
-[get involved](https://camel.apache.org/community/contributing/) :-)
-
-The Camel riders!
diff --git a/database/sql/compose.yaml b/database/sql/compose.yaml
deleted file mode 100644
index 6e2bd82..0000000
--- a/database/sql/compose.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-services:
-  db:
-    image: postgres
-    restart: always
-    environment:
-      - POSTGRES_DB=test
-      - POSTGRES_USER=postgres
-      - POSTGRES_PASSWORD=postgres
-    ports:
-      - '5432:5432'
diff --git a/database/sql/metadata.json b/database/sql/metadata.json
deleted file mode 100644
index 5679d51..0000000
--- a/database/sql/metadata.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-    "title": "SQL Database",
-    "description": "Against a running Postgres, a table is created and a row 
inserted on startup, and every five seconds a select logs the rows; the 
datasource comes from application.properties.",
-    "level": "connect-service",
-    "teaches": {
-        "components": [
-            "timer",
-            "sql",
-            "log"
-        ],
-        "languages": [
-            "simple"
-        ]
-    },
-    "tags": [
-        "database",
-        "sql",
-        "postgres"
-    ],
-    "bundled": true,
-    "infraServices": [
-        "postgres"
-    ]
-}
diff --git a/database/sql/sql.camel.yaml b/database/sql/sql.camel.yaml
deleted file mode 100644
index 34d02a5..0000000
--- a/database/sql/sql.camel.yaml
+++ /dev/null
@@ -1,40 +0,0 @@
-- route:
-    from:
-      uri: timer
-      parameters:
-        timerName: create
-        repeatCount: 1
-        delay: 500
-      steps:
-        - to:
-            uri: sql
-            parameters:
-              query: "CREATE TABLE IF NOT EXISTS users(id integer PRIMARY KEY, 
name\
-                \ varchar(20), byear integer);"
-- route:
-    from:
-      uri: timer
-      parameters:
-        timerName: insert
-        repeatCount: 1
-        delay: 1000
-      steps:
-        - to:
-            uri: sql
-            parameters:
-              query: "INSERT INTO users(id, name, byear) VALUES(1, 'Camel', 
2025)\
-                \ ON CONFLICT DO NOTHING;"
-- route:
-    from:
-      uri: timer
-      parameters:
-        timerName: select
-        period: 5000
-      steps:
-        - to:
-            uri: sql
-            parameters:
-              query: SELECT * FROM users
-        - log:
-            message: "${body}"
-
diff --git a/messaging/artemis/README.md b/messaging/artemis/README.md
deleted file mode 100644
index 0cc62ee..0000000
--- a/messaging/artemis/README.md
+++ /dev/null
@@ -1,81 +0,0 @@
-## Apache ActiveMQ Artemis
-
-This example shows how to setup connection factory to a remote Apache ActiveMQ 
Artemis
-messaging broker.
-
-### Apache ActiveMQ Artemis
-
-You first need to have an ActiveMQ Artemis broker up and running.
-See more at: https://activemq.apache.org/components/artemis/
-
-You can run Artemis using
-
-```sh
-$ camel infra run artemis
-```
-
-Alternatively, you can run it with Docker manually
-
-```sh
-$ docker run --detach --name mycontainer -p 61616:61616 -p 8161:8161 --rm 
apache/activemq-artemis:latest-alpine
-```
-
-Either command will run the broker locally. To login you need to use `artemis` 
as username and password,
-in the `application.properties` file.
-
-
-### Install JBang
-
-First install JBang according to https://www.jbang.dev
-
-When JBang is installed then you should be able to run from a shell:
-
-```sh
-$ jbang --version
-```
-
-This will output the version of JBang.
-
-To run this example you can either install Camel on JBang via:
-
-```sh
-$ jbang app install camel@apache/camel
-```
-
-Which allows to run Camel CLI with `camel` as shown below.
-
-### How to run
-
-You can run this example using:
-
-```sh
-$ camel run *
-```
-
-Camel will start sending random numbers to Artemis and logging them. See 
`producer.camel.yaml` for route that sends the numbers
-and `consumer.camel.yaml` for route that logs them.
-
-### Artemis configuration
-
-See the `application.properties` for how to configure to the ActiveMQ Artemis 
broker.
-
-### Developer Web Console
-
-You can enable the developer console via `--console` flag as show:
-
-```sh
-$ camel run * --console
-```
-
-Then you can browse: http://localhost:8080/q/dev to introspect the running 
Camel Application.
-
-
-### Help and contributions
-
-If you hit any problem using Camel or have some feedback, then please
-[let us know](https://camel.apache.org/community/support/).
-
-We also love contributors, so
-[get involved](https://camel.apache.org/community/contributing/) :-)
-
-The Camel riders!
diff --git a/messaging/artemis/application.properties 
b/messaging/artemis/application.properties
deleted file mode 100644
index 73cdd56..0000000
--- a/messaging/artemis/application.properties
+++ /dev/null
@@ -1,19 +0,0 @@
-# artemis connection factory
-camel.beans.artemisCF = 
#class:org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
-# URL for broker
-camel.beans.artemisCF.brokerURL = tcp://localhost:61616
-
-# if broker requires specific login
-camel.beans.artemisCF.user = artemis
-camel.beans.artemisCF.password = artemis
-
-# pooled connection factory
-camel.beans.poolCF = 
#class:org.messaginghub.pooled.jms.JmsPoolConnectionFactory
-camel.beans.poolCF.connectionFactory = #bean:artemisCF
-camel.beans.poolCF.maxSessionsPerConnection = 500
-camel.beans.poolCF.connectionIdleTimeout = 20000
-# more options can be configured
-# 
https://github.com/messaginghub/pooled-jms/blob/main/pooled-jms-docs/Configuration.md
-
-# setup JMS component to use connection factory
-camel.component.jms.connection-factory = #bean:poolCF
diff --git a/messaging/artemis/consumer.camel.yaml 
b/messaging/artemis/consumer.camel.yaml
deleted file mode 100644
index 55dc3c8..0000000
--- a/messaging/artemis/consumer.camel.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-- route:
-    from:
-      uri: jms
-      parameters:
-        destinationName: numbers
-      steps:
-        - log:
-            message: "${body}"
-
diff --git a/messaging/artemis/metadata.json b/messaging/artemis/metadata.json
deleted file mode 100644
index e84e418..0000000
--- a/messaging/artemis/metadata.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-    "title": "Apache ActiveMQ Artemis",
-    "description": "A producer route sends a JSON order to the queue numbers 
on a running Artemis broker every second and a consumer route logs each one; 
the connection factory is declared in application.properties.",
-    "level": "connect-service",
-    "teaches": {
-        "components": [
-            "timer",
-            "jms",
-            "log"
-        ],
-        "languages": [
-            "simple"
-        ]
-    },
-    "tags": [
-        "messaging",
-        "jms",
-        "artemis"
-    ],
-    "bundled": false,
-    "infraServices": [
-        "artemis"
-    ]
-}
diff --git a/messaging/artemis/producer.camel.yaml 
b/messaging/artemis/producer.camel.yaml
deleted file mode 100644
index 3d8741a..0000000
--- a/messaging/artemis/producer.camel.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-- route:
-    from:
-      uri: timer
-      parameters:
-        timerName: start
-      steps:
-        - setBody:
-            expression:
-              simple:
-                expression: '{"orderId": ${random(1000)}, "item": "widget", 
"quantity":
-                  ${random(10)}}'
-        - to:
-            uri: jms
-            parameters:
-              destinationName: numbers
-
diff --git a/messaging/ftp/README.md b/messaging/ftp/README.md
deleted file mode 100644
index 3289235..0000000
--- a/messaging/ftp/README.md
+++ /dev/null
@@ -1,104 +0,0 @@
-# ActiveMQ to FTP
-
-This example shows how to integrate ActiveMQ with FTP server.
-
-![](ftp-kaoto.png)
-
-## Install Camel CLI
-
-include::../install.adoc[see installation]
-
-## Running ActiveMQ and FTP server
-
-You need both an ActiveMQ Artemis broker, and FTP server up and running.
-
-### Using Camel Infra
-
-You can run both services using Camel Infra
-
-```shell
-camel infra run artemis
-```
-
-```shell
-camel infra run ftp
-```
-
-### Using Docker Compose
-
-You can run both services via Docker Compose (or Podman)
-
-```shell
-docker compose up --detach
-```
-
-## How to run
-
-Then you can run this example using:
-
-```shell
-camel run *
-```
-
-## Sending Messages to ActiveMQ
-
-When the example is running, you need to trigger Camel, by sending messages to 
the ActiveMQ broker.
-You can either do this via the broker web console http://localhost:8161 (login 
with `artemis/artemis`
-or by using Camel CLI (by sending the message into the existing running Camel 
named ftp):
-
-```shell
-camel cmd send ftp --body=file:test/payload.xml
-```
-
-## Browsing FTP server
-
-When you have sent some messages to ActiveMQ Camel will route these to the FTP 
server.
-To see which files have been uploaded, you can start a remote shell into the 
Docker container or use Camel CLI:
-
-```shell
-camel cmd browse
-```
-
-Which shows a status page of pending messages in the systems.
-
-To see the content of these messages, you can tell Camel to dump via
-
-```shell
-camel cmd browse --dump
-```
-
-> **Tip:** To see more options use `camel cmd browse --help`.
-
-## Developer Web Console
-
-You can enable the developer console via `--console` flag as show:
-
-```shell
-camel run * --console
-```
-
-Then you can browse: http://localhost:8080/q/dev to introspect the running 
Camel Application.
-
-## Integration testing
-
-The example provides an automated integration test (`ftp.citrus.it.yaml`) in 
the [Citrus](https://citrusframework.org/) YAML DSL, which the Camel CLI runs 
(the test plugin installs on first use).
-
-You may run the test with:
-
-```shell
-camel test run test/ftp.citrus.it.yaml
-```
-
-## More Information
-
-This example was also covered in the following YouTube video: 
https://youtu.be/V0sBmE8rcVg
-
-## Help and contributions
-
-If you hit any problem using Camel or have some feedback, then please
-[let us know](https://camel.apache.org/community/support/).
-
-We also love contributors, so
-[get involved](https://camel.apache.org/community/contributing/) :-)
-
-The Camel riders!
diff --git a/messaging/ftp/application.properties 
b/messaging/ftp/application.properties
deleted file mode 100644
index 128c508..0000000
--- a/messaging/ftp/application.properties
+++ /dev/null
@@ -1,24 +0,0 @@
-# artemis connection factory
-camel.beans.artemisCF = 
#class:org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
-# URL for broker
-camel.beans.artemisCF.brokerURL = tcp://localhost:61616
-
-# if broker requires specific login
-camel.beans.artemisCF.user = artemis
-camel.beans.artemisCF.password = artemis
-
-# pooled connection factory
-camel.beans.poolCF = 
#class:org.messaginghub.pooled.jms.JmsPoolConnectionFactory
-camel.beans.poolCF.connectionFactory = #bean:artemisCF
-camel.beans.poolCF.maxSessionsPerConnection = 500
-camel.beans.poolCF.connectionIdleTimeout = 20000
-# more options can be configured
-# 
https://github.com/messaginghub/pooled-jms/blob/main/pooled-jms-docs/Configuration.md
-
-# setup JMS component to use connection factory
-camel.component.jms.connection-factory = #bean:poolCF
-
-camel.jbang.classpathFiles=application.properties
-
-# Additional dependencies required at runtime (comma separated)
-camel.jbang.dependencies=jakarta.inject:jakarta.inject-api:2.0.1,jakarta.enterprise:jakarta.enterprise.cdi-api:4.1.0
diff --git a/messaging/ftp/compose.yaml b/messaging/ftp/compose.yaml
deleted file mode 100644
index 507ee52..0000000
--- a/messaging/ftp/compose.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
-services:
-
-  artemis:
-    image: mirror.gcr.io/apache/artemis:2.52.0
-    ports:
-      - "8161:8161"
-      - "61616:61616"
-      - "5672:5672"
-    environment:
-      ARTEMIS_USER: artemis
-      ARTEMIS_PASSWORD: artemis
-      ANONYMOUS_LOGIN: false
-
-  ftp-server:
-    environment:
-      - FTP_PASS=admin
-      - FTP_USER=admin
-    image: mirror.gcr.io/garethflowers/ftp-server
-    ports:
-      - '2221:21/tcp'
-      - '40000-40009:40000-40009/tcp' # Only needed for passive mode
-#    volumes:
-#      - '/data:/home/user'
diff --git a/messaging/ftp/ftp-kaoto.png b/messaging/ftp/ftp-kaoto.png
deleted file mode 100644
index 1a59048..0000000
Binary files a/messaging/ftp/ftp-kaoto.png and /dev/null differ
diff --git a/messaging/ftp/ftp.camel.yaml b/messaging/ftp/ftp.camel.yaml
deleted file mode 100644
index f0f7a5e..0000000
--- a/messaging/ftp/ftp.camel.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-- route:
-    from:
-      uri: jms
-      parameters:
-        destinationName: cheese
-      steps:
-        - log:
-            message: "Incoming: ${body}"
-        - to:
-            uri: ftp
-            parameters:
-              host: localhost
-              passiveMode: true
-              password: admin
-              port: 2221
-              username: admin
-
diff --git a/messaging/ftp/jbang.properties b/messaging/ftp/jbang.properties
deleted file mode 100644
index 06e387f..0000000
--- a/messaging/ftp/jbang.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-# Additional runtime dependencies are declared via camel.jbang.dependencies
-# in application.properties (Camel JBang natively supports comma separated 
lists).
diff --git a/messaging/ftp/metadata.json b/messaging/ftp/metadata.json
deleted file mode 100644
index 32ce614..0000000
--- a/messaging/ftp/metadata.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    "title": "ActiveMQ to FTP",
-    "description": "Each message arriving on the JMS queue cheese of a running 
Artemis broker is logged and uploaded as a file to a running FTP server.",
-    "level": "connect-service",
-    "teaches": {
-        "components": [
-            "jms",
-            "ftp",
-            "log"
-        ],
-        "languages": [
-            "simple"
-        ]
-    },
-    "tags": [
-        "messaging",
-        "ftp",
-        "activemq"
-    ],
-    "bundled": false,
-    "infraServices": [
-        "artemis",
-        "ftp"
-    ]
-}
diff --git a/messaging/ftp/test/citrus-application.properties 
b/messaging/ftp/test/citrus-application.properties
deleted file mode 100644
index 67a108f..0000000
--- a/messaging/ftp/test/citrus-application.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-# Enable dump of Camel JBang integration output
-citrus.camel.jbang.dump.integration.output=true
diff --git a/messaging/ftp/test/ftp.citrus.it.yaml 
b/messaging/ftp/test/ftp.citrus.it.yaml
deleted file mode 100644
index 1f44edc..0000000
--- a/messaging/ftp/test/ftp.citrus.it.yaml
+++ /dev/null
@@ -1,40 +0,0 @@
-# deps: org.apache.activemq:artemis-jakarta-client:2.52.0
-name: ftp-camel-test
-description: Test verifying the ActiveMQ to Ftp Camel route
-variables:
-  - name: jms.queue
-    value: cheese
-actions:
-  - groovy:
-      beans:
-        script: |
-          beans {
-            
connectionFactory(org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.class)
 {
-              brokerURL = "tcp://localhost:61616"
-              user = "artemis"
-              password = "artemis"
-            }
-          }
-  - testcontainers:
-      compose:
-        up:
-          file: "../compose.yaml"
-  - camel:
-      jbang:
-        run:
-          integration:
-            name: "ftp-camel"
-            file: "../ftp.camel.yaml"
-            systemProperties:
-              file: "../application.properties"
-  - send:
-      endpoint: jms:${jms.queue}
-      message:
-        body:
-          resource:
-            file: "payload.xml"
-  - camel:
-      jbang:
-        verify:
-          integration: "ftp-camel"
-          logMessage: "Camel in Action"
diff --git a/messaging/ftp/test/payload.xml b/messaging/ftp/test/payload.xml
deleted file mode 100644
index a087424..0000000
--- a/messaging/ftp/test/payload.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<order id="123">
-    <item id="444">Camel in Action</item>
-</order>
\ No newline at end of file
diff --git a/messaging/mqtt/README.md b/messaging/mqtt/README.md
deleted file mode 100644
index 3075ec7..0000000
--- a/messaging/mqtt/README.md
+++ /dev/null
@@ -1,106 +0,0 @@
-# MQTT
-
-This example is using Camel to receive MQTT events from an external MQTT 
broker,
-as illustrated below.
-
-![](mqtt-kaoto.png)
-
-## Install Camel CLI
-
-<!-- see installation instructions in ../install.adoc -->
-
-## Running MQTT Broker
-
-You need to run a MQTT broker such as via Docker, Camel Infra, or download and 
run Apache ActiveMQ Artemis.
-
-### Using Camel Infra
-
-The MQTT broker can be run using Camel Infra command:
-
-```shell
-camel infra run mqtt
-```
-
-### Using Docker compose
-
-To use docker (docker compose), you can run the following command:
-
-```shell
-start.sh
-```
-
-Or use
-
-```shell
-docker compose up --detach
-```
-
-## How to run
-
-Then you can run the Camel integration using:
-
-```shell
-camel run mqtt.camel.yaml application.properties
-```
-
-And then from another terminal (or run the integration with `--background` 
option),
-then send a message to the MQTT broker. This can be done with the help from 
camel-jbang
-where you can send a message as follows:
-
-```shell
-camel cmd send mqtt --body=file:test/payload.json
-```
-
-This will send a message where the payload (body) is read from the local file 
named payload.json.
-The message is sent to an existing running Camel integration (named mqtt). 
Then Camel will
-send the message to the MQTT broker. So in other words we use Camel as a proxy 
to send the
-message to the actual MQTT broker.
-
-The Camel integration will then consume the payload and output in the console.
-
-```text
-2023-04-14 08:58:58.676  INFO 62348 --- [calCliConnector] mqtt.camel.yaml:27   
               : Warm temperature at 21
-```
-
-Now send another sample file `payload-low.json` and see what is the output now.
-
-```shell
-camel cmd send mqtt --body=file:test/payload-low.json
-```
-
-## Stopping
-
-To stop Docker, you can run
-
-```shell
-docker compose down
-```
-
-And you can stop Camel with
-
-```shell
-camel stop mqtt
-```
-
-## Integration testing
-
-The example provides an automated integration test (`mqtt.citrus.it.yaml`) in 
the [Citrus](https://citrusframework.org/) YAML DSL, which the Camel CLI runs 
(the test plugin installs on first use).
-
-You can run the test with:
-
-```shell
-camel test run test/mqtt.citrus.it.yaml
-```
-
-The test prepares the complete infrastructure (e.g. via Docker compose) and 
starts the Camel route automatically.
-The test sends some test data to the MQTT broker and verifies that the Camel 
route successfully processes the messages.
-
-## Help and contributions
-
-If you hit any problem using Camel or have some feedback, then please
-[let us know](https://camel.apache.org/community/support/).
-
-We also love contributors, so
-[get involved](https://camel.apache.org/community/contributing/) :-)
-
-The Camel riders!
diff --git a/messaging/mqtt/application.properties 
b/messaging/mqtt/application.properties
deleted file mode 100644
index 00c7c08..0000000
--- a/messaging/mqtt/application.properties
+++ /dev/null
@@ -1,19 +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.
-
-mqtt.topic=temperature
-mqtt.broker.url=tcp://localhost:1883
diff --git a/messaging/mqtt/compose.yaml b/messaging/mqtt/compose.yaml
deleted file mode 100644
index 2678bfc..0000000
--- a/messaging/mqtt/compose.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-services:
-  mosquitto:
-    image: mirror.gcr.io/eclipse-mosquitto
-    ports:
-      - '1883:1883'
-    volumes:
-      - ./infra:/mosquitto/config
-      - ./data:/mosquitto/data
-      - ./log:/mosquitto/log
diff --git a/messaging/mqtt/infra/mosquitto.conf 
b/messaging/mqtt/infra/mosquitto.conf
deleted file mode 100644
index 05c4845..0000000
--- a/messaging/mqtt/infra/mosquitto.conf
+++ /dev/null
@@ -1,4 +0,0 @@
-listener 1883
-protocol mqtt
-allow_anonymous true
-socket_domain ipv4
\ No newline at end of file
diff --git a/messaging/mqtt/metadata.json b/messaging/mqtt/metadata.json
deleted file mode 100644
index e3222ab..0000000
--- a/messaging/mqtt/metadata.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-    "title": "MQTT",
-    "description": "Temperature readings published as JSON on the MQTT topic 
temperature of a running broker are received, the value is extracted with jq, 
and each is logged as warm or cold.",
-    "level": "connect-service",
-    "teaches": {
-        "components": [
-            "kamelet",
-            "log"
-        ],
-        "eips": [
-            "transform",
-            "choice"
-        ],
-        "languages": [
-            "jq",
-            "simple"
-        ]
-    },
-    "tags": [
-        "messaging",
-        "mqtt",
-        "iot"
-    ],
-    "bundled": false,
-    "infraServices": [
-        "mosquitto"
-    ]
-}
diff --git a/messaging/mqtt/mqtt-kaoto.png b/messaging/mqtt/mqtt-kaoto.png
deleted file mode 100644
index f2f65f1..0000000
Binary files a/messaging/mqtt/mqtt-kaoto.png and /dev/null differ
diff --git a/messaging/mqtt/mqtt-karavan.png b/messaging/mqtt/mqtt-karavan.png
deleted file mode 100644
index d9de25e..0000000
Binary files a/messaging/mqtt/mqtt-karavan.png and /dev/null differ
diff --git a/messaging/mqtt/mqtt.camel.yaml b/messaging/mqtt/mqtt.camel.yaml
deleted file mode 100644
index 78598d6..0000000
--- a/messaging/mqtt/mqtt.camel.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
-- route:
-    from:
-      uri: kamelet
-      parameters:
-        templateId: mqtt5-source
-        brokerUrl: "{{mqtt.broker.url}}"
-        topic: "{{mqtt.topic}}"
-      steps:
-        - transform:
-            expression:
-              jq:
-                expression: .value
-        - choice:
-            when:
-              - expression:
-                  simple:
-                    expression: "${body} > 20"
-                steps:
-                  - log:
-                      message: "Warm temperature at ${body}"
-            otherwise:
-              steps:
-                - log:
-                    message: "Cold temperature at ${body}"
-
diff --git a/messaging/mqtt/start.sh b/messaging/mqtt/start.sh
deleted file mode 100755
index ae169a3..0000000
--- a/messaging/mqtt/start.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-docker compose down
-docker compose up -d
-docker compose logs -f%
diff --git a/messaging/mqtt/test/citrus-application.properties 
b/messaging/mqtt/test/citrus-application.properties
deleted file mode 100644
index 67a108f..0000000
--- a/messaging/mqtt/test/citrus-application.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-# Enable dump of Camel JBang integration output
-citrus.camel.jbang.dump.integration.output=true
diff --git a/messaging/mqtt/test/mqtt.citrus.it.yaml 
b/messaging/mqtt/test/mqtt.citrus.it.yaml
deleted file mode 100644
index 50478e5..0000000
--- a/messaging/mqtt/test/mqtt.citrus.it.yaml
+++ /dev/null
@@ -1,46 +0,0 @@
-name: mqtt-camel-test
-description: Sample test in YAML
-variables:
-  - name: mqtt.topic
-    value: temperature
-  - name: mqtt.client.id
-    value: mqtt-citrus-client
-actions:
-  - testcontainers:
-      compose:
-        up:
-          file: "../compose.yaml"
-  - camel:
-      jbang:
-        run:
-          integration:
-            name: "mqtt-camel"
-            file: "../mqtt.camel.yaml"
-            systemProperties:
-              file: "../application.properties"
-  - camel:
-      startContext: {}
-  - send:
-      endpoint: |
-        
camel:paho-mqtt5:${mqtt.topic}?brokerUrl=tcp://localhost:1883&clientId=${mqtt.client.id}
-      message:
-        body:
-          resource:
-            file: "payload.json"
-  - camel:
-      jbang:
-        verify:
-          integration: "mqtt-camel"
-          logMessage: "Warm temperature"
-  - send:
-      endpoint: |
-        
camel:paho-mqtt5:${mqtt.topic}?brokerUrl=tcp://localhost:1883&clientId=${mqtt.client.id}
-      message:
-        body:
-          resource:
-            file: "payload-low.json"
-  - camel:
-      jbang:
-        verify:
-          integration: "mqtt-camel"
-          logMessage: "Cold temperature"
diff --git a/messaging/mqtt/test/payload-low.json 
b/messaging/mqtt/test/payload-low.json
deleted file mode 100644
index 63b9a39..0000000
--- a/messaging/mqtt/test/payload-low.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "value": 7
-}
\ No newline at end of file
diff --git a/messaging/mqtt/test/payload.json b/messaging/mqtt/test/payload.json
deleted file mode 100644
index f650d2f..0000000
--- a/messaging/mqtt/test/payload.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "value": 21
-}
\ No newline at end of file
diff --git a/observability/route-topology/README.md 
b/observability/route-topology/README.md
deleted file mode 100644
index 194f09d..0000000
--- a/observability/route-topology/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-## Route Topology
-
-This example demonstrates inter-route topology in an order processing system.
-It showcases how multiple routes connect through shared endpoints — both 
internal (direct)
-and external (kafka) — making it a good example for the `route-topology` 
command.
-
-### How to run
-
-    camel run route-topology.camel.yaml
-
-You can use `--stub` to run without a Kafka broker installed.
-This replaces Kafka with an internal in-memory queue, so the routes still 
connect and messages flow end-to-end:
-
-    camel run route-topology.camel.yaml --stub=kafka
-
-### View the route topology
-
-    camel cmd route-topology
-
-View as a Unicode diagram with live metrics and route descriptions:
-
-    camel cmd route-topology --theme=unicode --metric --description
-
-Sample output:
-
-```
-    ┌──────────────────────┐    ┌──────────────────────┐
-    │   Generate Orders    │    │    Order REST API    │
-    │          54          │    └──────────────────────┘
-    └──────────────────────┘
-                │                           │
-                │             ┬─────────────┘
-                └─────────────│
-                              ▼
-                  ┌──────────────────────┐
-                  │    Process Order     │
-                  │          54          │
-                  └──────────────────────┘
-                              │
-                ┬─────────────┴─────────────┬
-                ▼                           ▼
-    ┌──────────────────────┐    ┌──────────────────────┐
-    │    Dispatch Order    │    │    Validate Order    │
-    │          54          │    │          54          │
-    └──────────────────────┘    └──────────────────────┘
-                │
-                └───────────────────────────┬
-                ▼                           ▼
-    ┌──────────────────────┐    ┌──────────────────────┐
-    │    Fulfill Order     │    │  Send Notification   │
-    │          54          │    │          54          │
-    └──────────────────────┘    └──────────────────────┘
-```
-
-Save as PNG image:
-
-    camel cmd route-topology --theme=dark --output=topology.png
-
-### View as JSON
-
-    camel cmd route-topology --json
diff --git a/observability/route-topology/application.properties 
b/observability/route-topology/application.properties
deleted file mode 100644
index 997aa60..0000000
--- a/observability/route-topology/application.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-# enable breadcrumb to correlate messages across broker boundaries
-camel.main.useBreadcrumb=true
-
-# Kafka defaults to localhost:9092
-# To use a different broker, uncomment and adjust:
-camel.component.kafka.brokers=localhost:9092
diff --git a/observability/route-topology/metadata.json 
b/observability/route-topology/metadata.json
deleted file mode 100644
index 22742b8..0000000
--- a/observability/route-topology/metadata.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-    "title": "Route Topology",
-    "description": "A timer generates an order every five seconds and an HTTP 
endpoint accepts orders too; both flow through a shared validation route to 
Kafka, where consumers dispatch, fulfil and notify, each logging the order. 
camel cmd route-topology draws how the routes connect.",
-    "level": "connect-service",
-    "teaches": {
-        "components": [
-            "timer",
-            "platform-http",
-            "direct",
-            "kafka",
-            "log"
-        ],
-        "eips": [
-            "multicast"
-        ],
-        "languages": [
-            "simple"
-        ]
-    },
-    "tags": [
-        "topology",
-        "direct",
-        "kafka",
-        "timer"
-    ],
-    "bundled": true,
-    "infraServices": [
-        "kafka"
-    ]
-}
diff --git a/observability/route-topology/route-topology.camel.yaml 
b/observability/route-topology/route-topology.camel.yaml
deleted file mode 100644
index bbe81fb..0000000
--- a/observability/route-topology/route-topology.camel.yaml
+++ /dev/null
@@ -1,104 +0,0 @@
-# Order Processing System
-# This example demonstrates inter-route topology with triggers, shared routes, 
and external systems.
-# Use "camel cmd route-topology" to visualize how the routes connect to each 
other.
-
-# Trigger: generates a new order every 5 seconds
-- route:
-    id: order-generator
-    description: Generates a new order every 5 seconds
-    from:
-      uri: timer
-      parameters:
-        timerName: orders
-        period: 5000
-      steps:
-        - setBody:
-            expression:
-              simple:
-                expression: '{"orderId": "${exchangeId}", "item": "Camel 
T-Shirt", "quantity": 1}'
-        - to:
-            uri: direct:process-order
-
-# HTTP entry point: receives orders from external clients
-- route:
-    id: order-api
-    description: Receives orders from external clients via HTTP
-    from:
-      uri: platform-http
-      parameters:
-        path: /api/orders
-        httpMethodRestrict: POST
-      steps:
-        - to:
-            uri: direct:process-order
-
-# Shared route: validates and publishes orders (used by both order-generator 
and order-api)
-- route:
-    id: process-order
-    description: Validates and publishes orders to Kafka
-    from:
-      uri: direct:process-order
-      steps:
-        - to:
-            uri: direct:validate-order
-        - log:
-            message: "Processing order: ${body}"
-        - to:
-            id: to-kafka-orders
-            uri: kafka:orders
-
-# Validation: checks order contents
-- route:
-    id: validate-order
-    description: Checks order contents before processing
-    from:
-      uri: direct:validate-order
-      steps:
-        - log:
-            message: "Validating order: ${body}"
-
-# Kafka consumer: picks up orders and fans out to fulfillment and notifications
-- route:
-    id: order-dispatcher
-    description: Fans out orders to fulfillment and notifications
-    from:
-      uri: kafka:orders
-      steps:
-        - log:
-            message: "Dispatching order: ${body}"
-        - multicast:
-            steps:
-              - to:
-                  id: to-kafka-fulfillment
-                  uri: kafka:fulfillment
-              - to:
-                  id: to-kafka-notifications
-                  uri: kafka:notifications
-
-# Kafka consumer: handles fulfillment and reports to warehouse
-- route:
-    id: fulfillment
-    description: Handles order fulfillment and ships to warehouse
-    from:
-      uri: kafka:fulfillment
-      steps:
-        - log:
-            message: "Fulfilling order: ${body}"
-        - to:
-            id: to-kafka-warehouse-shipments
-            uri: kafka:warehouse-shipments
-            description: Ship to Warehouse
-
-# Kafka consumer: sends notifications via external email service
-- route:
-    id: notification
-    description: Sends order notifications via email
-    from:
-      uri: kafka:notifications
-      steps:
-        - log:
-            message: "Sending notification for: ${body}"
-        - to:
-            id: to-kafka-email-outbox
-            uri: kafka:email-outbox
-            description: Send Email

Reply via email to