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.
-
-
-
-## 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.
-
-
-
-## 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