diff --git a/023-quarkus-kamelet/README.md b/023-quarkus-kamelet/README.md
new file mode 100644
index 00000000..36497079
--- /dev/null
+++ b/023-quarkus-kamelet/README.md
@@ -0,0 +1,24 @@
+# Quarkus - Kamelet
+
+Quarkus-kamelet provide you support to interacting with Camel routes templates.
+The aim of this module is to cover the following Kamelet scenarios:
+* Camel producers, those scenarios where your service produces events and are consumed by a camel route
+* Camel consumers, those scenarios where your service consumes a camel route
+* Chain routes multiples routes
+* Load application properties as routes bodies
+* Validate Kamelet resources as ocp/k8s kamelet yamls(routes-temapltes, routes-bindings...)
+
+Project folder structure
+
+* `/resources/kamelets` contains kamelets resources as templates or KameletBindings. Also, there are groovy scripts
+in order to instantiate these templates by your self (as an example).
+
+* `io.quarkus.qe.kamelet.KameletRoutes` contains templates that could be invoked (tested) directly by code. So is not
+need it to be deployed into ocp or some other platform.
+
+### Recommended Readings
+[Kamelet introduction](https://camel.apache.org/camel-k/latest/kamelets/kamelets-user.html)
+
+[Kamelets developer guide](https://camel.apache.org/camel-k/latest/kamelets/kamelets-dev.html)
+
+[Camel-Quarkus first steps](https://camel.apache.org/camel-quarkus/latest/user-guide/first-steps.html)
diff --git a/023-quarkus-kamelet/pom.xml b/023-quarkus-kamelet/pom.xml
new file mode 100644
index 00000000..3412ec69
--- /dev/null
+++ b/023-quarkus-kamelet/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+
+ io.quarkus.qe
+ beefy-scenarios
+ 1.0.0-SNAPSHOT
+
+ 023-quarkus-kamelet
+
+
+ org.apache.camel.quarkus
+ camel-quarkus-kamelet
+
+
+ org.apache.camel.quarkus
+ camel-quarkus-timer
+
+
+ org.apache.camel.quarkus
+ camel-quarkus-direct
+
+
+ io.quarkus
+ quarkus-resteasy
+
+
+ io.quarkus
+ quarkus-resteasy-jsonb
+
+
+
diff --git a/023-quarkus-kamelet/src/main/java/io/quarkus/qe/kamelet/KameletResource.java b/023-quarkus-kamelet/src/main/java/io/quarkus/qe/kamelet/KameletResource.java
new file mode 100644
index 00000000..5c2e3699
--- /dev/null
+++ b/023-quarkus-kamelet/src/main/java/io/quarkus/qe/kamelet/KameletResource.java
@@ -0,0 +1,51 @@
+package io.quarkus.qe.kamelet;
+
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.camel.ConsumerTemplate;
+import org.apache.camel.FluentProducerTemplate;
+
+@Path("/kamelet")
+public class KameletResource {
+
+ @Inject
+ FluentProducerTemplate fluentProducerTemplate;
+
+ @Inject
+ ConsumerTemplate consumerTemplate;
+
+ @Path("/produce")
+ @POST
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Produces(MediaType.TEXT_PLAIN)
+ public String produceToKamelet(String message) {
+ return fluentProducerTemplate.toF("kamelet:setBody/test?bodyValue=%s", message).request(String.class);
+ }
+
+ @Path("/timer")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public Integer consumeFromKamelet() {
+ return consumerTemplate.receiveBody("kamelet:tick", 10000, Integer.class);
+ }
+
+ @Path("/property")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String bodyFromApplicationProperty() {
+ return fluentProducerTemplate.to("kamelet:setBodyFromProperties").request(String.class);
+ }
+
+ @Path("/chain")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ public String kameletChain(String message) {
+ return fluentProducerTemplate.to("direct:chain").withBody(message).request(String.class);
+ }
+}
diff --git a/023-quarkus-kamelet/src/main/java/io/quarkus/qe/kamelet/KameletRoutes.java b/023-quarkus-kamelet/src/main/java/io/quarkus/qe/kamelet/KameletRoutes.java
new file mode 100644
index 00000000..b43fed06
--- /dev/null
+++ b/023-quarkus-kamelet/src/main/java/io/quarkus/qe/kamelet/KameletRoutes.java
@@ -0,0 +1,35 @@
+package io.quarkus.qe.kamelet;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+
+public class KameletRoutes extends RouteBuilder {
+
+ @Override
+ public void configure() throws Exception {
+ routeTemplate("setBody")
+ .templateParameter("bodyValue")
+ .from("kamelet:source")
+ .setBody().constant("Hello {{bodyValue}}");
+
+ routeTemplate("tick")
+ .from("timer:{{routeId}}?repeatCount=1&delay=-1")
+ .setBody().exchangeProperty(Exchange.TIMER_COUNTER)
+ .to("kamelet:sink");
+
+ routeTemplate("setBodyFromProperties")
+ .templateParameter("bodyValueFromProperty")
+ .from("kamelet:source")
+ .setBody().constant("Hello {{bodyValueFromProperty}}");
+
+ routeTemplate("echo")
+ .templateParameter("prefix")
+ .templateParameter("suffix")
+ .from("kamelet:source")
+ .setBody().simple("{{prefix}} ${body} {{suffix}}");
+
+ from("direct:chain")
+ .to("kamelet:echo/1?prefix=Camel Quarkus&suffix=Chained")
+ .to("kamelet:echo/2?prefix=Hello&suffix=Route");
+ }
+}
diff --git a/023-quarkus-kamelet/src/main/resources/application.properties b/023-quarkus-kamelet/src/main/resources/application.properties
new file mode 100644
index 00000000..ff0fe0d8
--- /dev/null
+++ b/023-quarkus-kamelet/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+# kamelet.names, must match with kamelets prefix name, ex: {prefix}.kamelet.yaml
+quarkus.camel.kamelet.names = logger, fresh-beer
+
+camel.kamelet.setBodyFromProperties.bodyValueFromProperty=World from property
diff --git a/023-quarkus-kamelet/src/main/resources/kamelets/fresh-beer-integration-example.groovy b/023-quarkus-kamelet/src/main/resources/kamelets/fresh-beer-integration-example.groovy
new file mode 100644
index 00000000..cfd332e6
--- /dev/null
+++ b/023-quarkus-kamelet/src/main/resources/kamelets/fresh-beer-integration-example.groovy
@@ -0,0 +1,3 @@
+package kamelets
+
+from('kamelet:beer-source').log('${body}')
diff --git a/023-quarkus-kamelet/src/main/resources/kamelets/fresh-beer.Kamelet.yaml b/023-quarkus-kamelet/src/main/resources/kamelets/fresh-beer.Kamelet.yaml
new file mode 100644
index 00000000..1a1e90e3
--- /dev/null
+++ b/023-quarkus-kamelet/src/main/resources/kamelets/fresh-beer.Kamelet.yaml
@@ -0,0 +1,27 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: Kamelet
+metadata:
+ name: beer-source
+ labels:
+ camel.apache.org/kamelet.type: "source"
+spec:
+ definition:
+ title: "Beer Source"
+ description: "Retrieve a random beer from catalog"
+ properties:
+ period:
+ title: Period
+ description: The interval between two events
+ type: integer
+ default: 1000
+ types:
+ out:
+ mediaType: application/json
+ flow:
+ from:
+ uri: timer:tick
+ parameters:
+ period: "#property:period"
+ steps:
+ - to: "https://random-data-api.com/api/beer/random_beer"
+ - to: "kamelet:sink"
\ No newline at end of file
diff --git a/023-quarkus-kamelet/src/main/resources/kamelets/logger.kamelet.yaml b/023-quarkus-kamelet/src/main/resources/kamelets/logger.kamelet.yaml
new file mode 100644
index 00000000..bc06b7c6
--- /dev/null
+++ b/023-quarkus-kamelet/src/main/resources/kamelets/logger.kamelet.yaml
@@ -0,0 +1,39 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: Kamelet
+metadata:
+ labels:
+ camel.apache.org/kamelet.type: "sink"
+ camel.apache.org/kamelet.name: "log"
+ camel.apache.org/kamelet.version: "v1alpha1"
+spec:
+ definition:
+ title: "Logger"
+ description: "Logger"
+ properties:
+ loggerName:
+ title: Name of the logging category
+ description: Name of the logging category
+ type: string
+ default: "logger"
+ showAll:
+ title: Show All
+ description: Show All
+ type: boolean
+ default: false
+ multiLine:
+ title: Multi Line
+ description: Multi Line
+ type: boolean
+ default: false
+ dependencies:
+ - "camel:log"
+ flow:
+ from:
+ uri: "kamelet:source"
+ steps:
+ - to:
+ uri: "log"
+ properties:
+ loggerName: "{{loggerName}}"
+ showAll: "{{showAll}}"
+ multiline: "{{multiLine}}"
diff --git a/023-quarkus-kamelet/src/test/java/io/quarkus/qe/kamelet/KameletIT.java b/023-quarkus-kamelet/src/test/java/io/quarkus/qe/kamelet/KameletIT.java
new file mode 100644
index 00000000..7e090a1d
--- /dev/null
+++ b/023-quarkus-kamelet/src/test/java/io/quarkus/qe/kamelet/KameletIT.java
@@ -0,0 +1,8 @@
+package io.quarkus.qe.kamelet;
+
+import io.quarkus.test.junit.NativeImageTest;
+
+@NativeImageTest
+class KameletIT extends KameletTest {
+
+}
diff --git a/023-quarkus-kamelet/src/test/java/io/quarkus/qe/kamelet/KameletTest.java b/023-quarkus-kamelet/src/test/java/io/quarkus/qe/kamelet/KameletTest.java
new file mode 100644
index 00000000..3b944125
--- /dev/null
+++ b/023-quarkus-kamelet/src/test/java/io/quarkus/qe/kamelet/KameletTest.java
@@ -0,0 +1,52 @@
+package io.quarkus.qe.kamelet;
+
+import static org.hamcrest.Matchers.is;
+
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+
+@QuarkusTest
+class KameletTest {
+ @Test
+ public void testKameletProducerHelloWorld() {
+ String message = "World";
+
+ RestAssured.given()
+ .contentType(ContentType.TEXT)
+ .body(message)
+ .post("/kamelet/produce")
+ .then()
+ .statusCode(200)
+ .body(is("Hello " + message));
+ }
+
+ @Test
+ public void testKameletTimerConsumer() {
+ RestAssured.get("/kamelet/timer")
+ .then()
+ .statusCode(200)
+ .body(is("1"));
+ }
+
+ @Test
+ public void testKameletWithProperties() {
+ RestAssured.get("/kamelet/property")
+ .then()
+ .statusCode(200)
+ .body(is("Hello World from property"));
+ }
+
+ @Test
+ public void testKameletChain() {
+ RestAssured.given()
+ .contentType(ContentType.TEXT)
+ .body("Kamelet")
+ .post("/kamelet/chain")
+ .then()
+ .statusCode(200)
+ .body(is("Hello Camel Quarkus Kamelet Chained Route"));
+ }
+}
diff --git a/pom.xml b/pom.xml
index 99f8356c..b61a9d4a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,6 +24,7 @@
020-quarkus-http-non-application-endpoints
021-quarkus-panache-multiple-pus
022-quarkus-properties-config-all
+ 023-quarkus-kamelet
101-javaee-like-getting-started
201-large-static-content
300-quarkus-vertx-webClient
@@ -49,6 +50,7 @@
1.3.2.Final
6.0.0
0.0.2
+ 1.8.1
2.15.0
1.6.0
3.1.2
@@ -105,6 +107,21 @@
quarkiverse-apicurio-registry-client
${version.quarkiverse.apicurio.registry.client}
+
+ org.apache.camel.quarkus
+ camel-quarkus-kamelet
+ ${version.quarkus.camel}
+
+
+ org.apache.camel.quarkus
+ camel-quarkus-timer
+ ${version.quarkus.camel}
+
+
+ org.apache.camel.quarkus
+ camel-quarkus-direct
+ ${version.quarkus.camel}
+