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-spring-boot-examples.git


The following commit(s) were added to refs/heads/main by this push:
     new f1fcd42  CAMEL-21118: Adds rest-cxf-opentelemetry (#142)
f1fcd42 is described below

commit f1fcd42dcd160fece20ed8086087223c1644bb06
Author: Marco Carletti <[email protected]>
AuthorDate: Wed Aug 28 15:29:10 2024 +0200

    CAMEL-21118: Adds rest-cxf-opentelemetry (#142)
---
 README.adoc                                        |   4 +-
 pom.xml                                            |   1 +
 rest-cxf-opentelemetry/README.adoc                 | 145 ++++++++++++++++++
 .../containers/docker-compose.yml                  |  35 +++++
 rest-cxf-opentelemetry/containers/env.sh           |   8 +
 .../containers/otel-collector.yml                  |  25 ++++
 rest-cxf-opentelemetry/docs/jaeger.png             | Bin 0 -> 35152 bytes
 rest-cxf-opentelemetry/docs/overview.png           | Bin 0 -> 10026 bytes
 rest-cxf-opentelemetry/pom.xml                     | 163 +++++++++++++++++++++
 .../rest-cxf-otel-common/pom.xml                   |  78 ++++++++++
 .../cxf/otel/InputStreamConverterLoader.java       |  54 +++++++
 .../cxf/otel/IntegerConverterLoader.java           |  54 +++++++
 .../services/org/apache/camel/TypeConverterLoader  |   3 +
 .../example/springboot/cxf/otel/Constants.java     |  30 ++++
 .../example/springboot/cxf/otel/CxfConfig.java     |  39 +++++
 .../springboot/cxf/otel/InputStreamConverter.java  |  34 +++++
 .../springboot/cxf/otel/IntegerConverter.java      |  29 ++++
 .../example/springboot/cxf/otel/RandomNumber.java  |  73 +++++++++
 rest-cxf-opentelemetry/rest-cxf-otel-even/pom.xml  |  63 ++++++++
 .../example/springboot/cxf/otel/Application.java   |  37 +++++
 .../example/springboot/cxf/otel/CamelRouter.java   |  63 ++++++++
 .../example/springboot/cxf/otel/EvenService.java   |  43 ++++++
 .../springboot/cxf/otel/EvenServiceImpl.java       |  42 ++++++
 .../src/main/resources/application.properties      |  22 +++
 rest-cxf-opentelemetry/rest-cxf-otel-odd/pom.xml   |  63 ++++++++
 .../example/springboot/cxf/otel/Application.java   |  37 +++++
 .../example/springboot/cxf/otel/CamelRouter.java   |  63 ++++++++
 .../example/springboot/cxf/otel/OddService.java    |  43 ++++++
 .../springboot/cxf/otel/OddServiceImpl.java        |  42 ++++++
 .../src/main/resources/application.properties      |  22 +++
 .../rest-cxf-otel-random/pom.xml                   |  67 +++++++++
 .../example/springboot/cxf/otel/Application.java   |  37 +++++
 .../example/springboot/cxf/otel/CamelRouter.java   | 131 +++++++++++++++++
 .../example/springboot/cxf/otel/RandomService.java |  71 +++++++++
 .../springboot/cxf/otel/RandomServiceImpl.java     |  59 ++++++++
 .../camel/example/springboot/cxf/otel/Results.java |  62 ++++++++
 .../src/main/resources/application.properties      |  28 ++++
 37 files changed, 1769 insertions(+), 1 deletion(-)

diff --git a/README.adoc b/README.adoc
index f5517ec..110e73f 100644
--- a/README.adoc
+++ b/README.adoc
@@ -27,7 +27,7 @@ readme's instructions.
 === Examples
 
 // examples: START
-Number of Examples: 58 (0 deprecated)
+Number of Examples: 59 (0 deprecated)
 
 [width="100%",cols="4,2,4",options="header"]
 |===
@@ -77,6 +77,8 @@ Number of Examples: 58 (0 deprecated)
 
 | link:master/readme.adoc[Master] (master) | Clustering | An example showing 
how to work with Camel's Master component and Spring Boot
 
+| link:rest-cxf-opentelemetry/README.adoc[Rest Cxf Opentelemetry] 
(rest-cxf-opentelemetry) | CXF | An example showing Camel REST using CXF and 
OpenTelemetry with Spring Boot
+
 | link:soap-cxf/README.adoc[Soap Cxf] (soap-cxf) | CXF | An example showing 
the Camel SOAP CXF
 
 | link:arangodb/README.adoc[Arangodb] (arangodb) | Database | An example 
showing the Camel ArangoDb component with Spring Boot
diff --git a/pom.xml b/pom.xml
index 318d1c9..fb165cf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,7 @@
                <module>reactive-streams</module>
                <module>resilience4j</module>
                <module>rest-cxf</module>
+               <module>rest-cxf-opentelemetry</module>
                <module>rest-openapi</module>
                <module>rest-openapi-simple</module>
                <module>rest-openapi-springdoc</module>
diff --git a/rest-cxf-opentelemetry/README.adoc 
b/rest-cxf-opentelemetry/README.adoc
new file mode 100644
index 0000000..5d09ff6
--- /dev/null
+++ b/rest-cxf-opentelemetry/README.adoc
@@ -0,0 +1,145 @@
+== Spring Boot Example with Camel exposing REST services using Apache CXF, 
collecting distributed tracing using OpenTelemetry
+
+=== Introduction
+
+This example illustrates how to use 
https://projects.spring.io/spring-boot/[Spring Boot] with 
http://camel.apache.org[Camel] and https://cxf.apache.org/[Apache CXF] 
implementing REST services using bottom-up approach.
+
+If you are using REST services directly from Camel and you want to use 
https://opentelemetry.io/[OpenTelemetry] please refer to 
link:../opentelemetry/README.adoc[the dedicated example]
+
+There are 3 services which communicate each other, starting from the `random` 
service:
+
+- random: the main service, exposes the entry point REST service and store the 
results
+- even: the service that verifies the even numbers
+- odd: the service that verifies the odd numbers
+
+moreover there is a common module containing common classes
+
+image::docs/overview.png[]
+
+=== Build
+
+You can build this example using the following command; it will also download 
the OpenTelemetry agent used to instrument the applications:
+
+    $ mvn package -Potel-agent
+
+=== Run
+
+Run docker-compose to start all the needed services:
+
+    $ docker-compose -f containers/docker-compose.yml up -d
+
+the command runs:
+
+- https://github.com/minio/minio[minio] as application storage
+- 
https://github.com/open-telemetry/opentelemetry-collector[opentelemetry-collector]
 to receive the generated Trace/Span
+- https://github.com/jaegertracing/jaeger[Jaeger] to visualize the traces
+
+Run each services on separated terminals:
+
+    $ source containers/env.sh \
+        && java -javaagent:target/opentelemetry-javaagent.jar \
+        -Dotel.service.name=random \
+        -jar rest-cxf-otel-random/target/*.jar
+
+    $ source containers/env.sh \
+        && java -javaagent:target/opentelemetry-javaagent.jar \
+        -Dotel.service.name=even \
+        -Dserver.port=8081 \
+        -jar rest-cxf-otel-even/target/*.jar
+
+    $ source containers/env.sh \
+        && java -javaagent:target/opentelemetry-javaagent.jar \
+        -Dotel.service.name=odd \
+        -Dserver.port=8082 \
+        -jar rest-cxf-otel-odd/target/*.jar
+
+After the Spring Boot applications have been started, you can open the 
following URL in your web browser http://localhost:8080/services/ to access the 
list of services,  including WADL definition
+
+You can also access the REST endpoint from the command line:
+
+i.e. to generate 5 random numbers run:
+
+    $ curl -X POST http://localhost:8080/services/api/play/5 -s | jq .
+
+The command will produce an output like:
+
+[source,json]
+----
+{
+  "result": {
+    "ODD": [
+      {
+        "number": 229,
+        "type": "ODD"
+      },
+      {
+        "number": 585,
+        "type": "ODD"
+      }
+    ],
+    "EVEN": [
+      {
+        "number": 648,
+        "type": "EVEN"
+      },
+      {
+        "number": 670,
+        "type": "EVEN"
+      },
+      {
+        "number": 846,
+        "type": "EVEN"
+      }
+    ]
+  },
+  "evenCount": 3,
+  "oddCount": 2
+}
+----
+
+Now in the Jaeger UI http://localhost:16686 the traces will be available, both 
from Camel and from CXF instrumentation
+
+image::docs/jaeger.png[]
+
+The services can be stopped pressing `[CTRL] + [C]` in the shell, and the 
containers can be stopped with
+
+    $ docker-compose -f containers/docker-compose.yml down
+
+=== Explain the code
+
+The dependency `org.apache.cxf:cxf-integration-tracing-opentelemetry` provides 
`org.apache.cxf.tracing.opentelemetry.jaxrs.OpenTelemetryFeature` that 
instruments the OpenTelemetry API implemented in the java agent.
+
+The feature is injected in the Spring context
+
+[source,java]
+----
+include::rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/CxfConfig.java[lines=35..38]
+----
+
+and then it is configured in the Camel route as provider in the `cxfrs` 
endpoint
+
+[source,java]
+----
+include::rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/CamelRouter.java[lines=51]
+----
+
+When the feature is enabled it is possible to add custom tags or logs using 
`TracerContext` from CXF
+[source,java]
+----
+include::rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/RandomService.java[lines=56..58]
+----
+
+[source,java]
+----
+include::rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/RandomServiceImpl.java[lines=43..45]
+----
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/community/support/[let us know].
+
+We also love contributors, so
+https://camel.apache.org/community/contributing/[get involved] :-)
+
+The Camel riders!
diff --git a/rest-cxf-opentelemetry/containers/docker-compose.yml 
b/rest-cxf-opentelemetry/containers/docker-compose.yml
new file mode 100644
index 0000000..25b7e9d
--- /dev/null
+++ b/rest-cxf-opentelemetry/containers/docker-compose.yml
@@ -0,0 +1,35 @@
+version: "3.9"
+
+services:
+
+  minio:
+    image: "quay.io/minio/minio:latest"
+    environment:
+      - MINIO_ROOT_USER=admin
+      - MINIO_ROOT_PASSWORD=admin123
+    ports:
+      - "9000:9000"
+      - "9001:9001"
+    command:
+      - server
+      - /data
+      - --console-address
+      - :9001
+
+  otel-collector:
+    image: otel/opentelemetry-collector:latest
+    command:
+      - --config=/etc/otelcol-cont/otel-collector.yml
+    volumes:
+      - ./otel-collector.yml:/etc/otelcol-cont/otel-collector.yml
+    ports:
+      - "4318:4318" # OTLP http receiver
+      - "4317:4317" # OTLP grpc receiver
+    depends_on:
+      - jaeger-all-in-one
+
+  jaeger-all-in-one:
+    image: quay.io/jaegertracing/all-in-one:latest
+    restart: always
+    ports:
+      - "16686:16686"
diff --git a/rest-cxf-opentelemetry/containers/env.sh 
b/rest-cxf-opentelemetry/containers/env.sh
new file mode 100644
index 0000000..549fb23
--- /dev/null
+++ b/rest-cxf-opentelemetry/containers/env.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/bash
+
+export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
+export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4318/v1/traces
+export OTEL_TRACES_EXPORTER=otlp
+export OTEL_METRICS_EXPORTER=none
+export OTEL_LOGS_EXPORTER=none
+#export OTEL_JAVAAGENT_DEBUG=true
diff --git a/rest-cxf-opentelemetry/containers/otel-collector.yml 
b/rest-cxf-opentelemetry/containers/otel-collector.yml
new file mode 100644
index 0000000..db8a4be
--- /dev/null
+++ b/rest-cxf-opentelemetry/containers/otel-collector.yml
@@ -0,0 +1,25 @@
+receivers:
+  otlp:
+    protocols:
+      grpc:
+        endpoint: 0.0.0.0:4317
+      http:
+        endpoint: 0.0.0.0:4318
+
+processors:
+  batch:
+
+exporters:
+  debug:
+    verbosity: detailed
+  otlp/jaeger:
+    endpoint: jaeger-all-in-one:4317
+    tls:
+      insecure: true
+
+service:
+  pipelines:
+    traces:
+      receivers: [otlp]
+      processors: [batch]
+      exporters: [debug,otlp/jaeger]
diff --git a/rest-cxf-opentelemetry/docs/jaeger.png 
b/rest-cxf-opentelemetry/docs/jaeger.png
new file mode 100644
index 0000000..e89e987
Binary files /dev/null and b/rest-cxf-opentelemetry/docs/jaeger.png differ
diff --git a/rest-cxf-opentelemetry/docs/overview.png 
b/rest-cxf-opentelemetry/docs/overview.png
new file mode 100644
index 0000000..15550cd
Binary files /dev/null and b/rest-cxf-opentelemetry/docs/overview.png differ
diff --git a/rest-cxf-opentelemetry/pom.xml b/rest-cxf-opentelemetry/pom.xml
new file mode 100644
index 0000000..7d6adcd
--- /dev/null
+++ b/rest-cxf-opentelemetry/pom.xml
@@ -0,0 +1,163 @@
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel.springboot.example</groupId>
+        <artifactId>examples</artifactId>
+        <version>4.8.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-example-spring-boot-rest-cxf-opentelemetry</artifactId>
+    <name>Camel SB Examples :: REST using CXF and OpenTelemetry</name>
+    <description>An example showing Camel REST using CXF and OpenTelemetry 
with Spring Boot</description>
+    <packaging>pom</packaging>
+
+    <properties>
+        <category>CXF</category>
+        
<opentelemetry-javaagent.version>2.7.0</opentelemetry-javaagent.version>
+    </properties>
+    
+    <modules>
+           <module>rest-cxf-otel-common</module>
+        <module>rest-cxf-otel-random</module>
+        <module>rest-cxf-otel-even</module>
+        <module>rest-cxf-otel-odd</module>
+    </modules>
+
+    <!-- Spring-Boot and Camel BOM -->
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.apache.camel.springboot</groupId>
+                <artifactId>camel-spring-boot-bom</artifactId>
+                <version>${project.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot-version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+       <!-- Spring Boot -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <!-- Camel -->
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-direct-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-log-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-bean-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-bean-validator-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-cxf-rest-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-jackson-starter</artifactId>
+        </dependency>
+
+        <!-- camel opentelemetry -->
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-opentelemetry-starter</artifactId>
+        </dependency>
+
+        <!-- jax-rs json provider from jackson -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.jakarta.rs</groupId>
+            <artifactId>jackson-jakarta-rs-json-provider</artifactId>
+        </dependency>
+
+        <!-- CXF opentelemetry -->
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-integration-tracing-opentelemetry</artifactId>
+            <version>${cxf-version}</version>
+        </dependency>
+
+        <!-- CXF WADL definition-->
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-rs-service-description</artifactId>
+            <version>${cxf-version}</version>
+        </dependency>
+
+    </dependencies>
+
+    <profiles>
+        <profile>
+            <id>otel-agent</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-dependency-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>copy</goal>
+                                </goals>
+                                <phase>process-resources</phase>
+                                <configuration>
+                                    <stripVersion>true</stripVersion>
+                                    <artifactItems>
+                                        <artifactItem>
+                                            
<groupId>io.opentelemetry.javaagent</groupId>
+                                            
<artifactId>opentelemetry-javaagent</artifactId>
+                                            
<version>${opentelemetry-javaagent.version}</version>
+                                            <type>jar</type>
+                                            
<outputDirectory>${project.build.directory}</outputDirectory>
+                                        </artifactItem>
+                                    </artifactItems>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/rest-cxf-opentelemetry/rest-cxf-otel-common/pom.xml 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/pom.xml
new file mode 100644
index 0000000..e5995f4
--- /dev/null
+++ b/rest-cxf-opentelemetry/rest-cxf-otel-common/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.apache.camel.springboot.example</groupId>
+               
<artifactId>camel-example-spring-boot-rest-cxf-opentelemetry</artifactId>
+               <version>4.8.0-SNAPSHOT</version>
+       </parent>
+
+       <artifactId>camel-example-spring-boot-rest-cxf-otel-common</artifactId>
+       <name>Camel SB Examples :: REST using CXF and OpenTelemetry :: 
Common</name>
+
+       <properties>
+               <category>CXF</category>
+       </properties>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.camel</groupId>
+                               
<artifactId>camel-component-maven-plugin</artifactId>
+                               <version>${camel-version}</version>
+                               <executions>
+                                       <execution>
+                                               <id>generate</id>
+                                               <goals>
+                                                       <goal>generate</goal>
+                                               </goals>
+                                               <phase>process-classes</phase>
+                                       </execution>
+                               </executions>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.codehaus.mojo</groupId>
+                               
<artifactId>build-helper-maven-plugin</artifactId>
+                               <executions>
+                                       <execution>
+                                               <phase>initialize</phase>
+                                               <goals>
+                                                       <goal>add-source</goal>
+                                                       
<goal>add-resource</goal>
+                                               </goals>
+                                               <configuration>
+                                                       <sources>
+                                                               
<source>src/generated/java</source>
+                                                       </sources>
+                                                       <resources>
+                                                               <resource>
+                                                                       
<directory>src/generated/resources</directory>
+                                                               </resource>
+                                                       </resources>
+                                               </configuration>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+</project>
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-common/src/generated/java/org/apache/camel/example/springboot/cxf/otel/InputStreamConverterLoader.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/generated/java/org/apache/camel/example/springboot/cxf/otel/InputStreamConverterLoader.java
new file mode 100644
index 0000000..daab67b
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/generated/java/org/apache/camel/example/springboot/cxf/otel/InputStreamConverterLoader.java
@@ -0,0 +1,54 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import javax.annotation.processing.Generated;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.DeferredContextBinding;
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConversionException;
+import org.apache.camel.TypeConverterLoaderException;
+import org.apache.camel.spi.TypeConverterLoader;
+import org.apache.camel.spi.TypeConverterRegistry;
+import org.apache.camel.support.SimpleTypeConverter;
+import org.apache.camel.support.TypeConverterSupport;
+import org.apache.camel.util.DoubleMap;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.TypeConverterLoaderGeneratorMojo")
+@SuppressWarnings("unchecked")
+@DeferredContextBinding
+public final class InputStreamConverterLoader implements TypeConverterLoader, 
CamelContextAware {
+
+    private CamelContext camelContext;
+
+    public InputStreamConverterLoader() {
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void load(TypeConverterRegistry registry) throws 
TypeConverterLoaderException {
+        registerConverters(registry);
+    }
+
+    private void registerConverters(TypeConverterRegistry registry) {
+        addTypeConverter(registry, 
org.apache.camel.example.springboot.cxf.otel.RandomNumber.class, 
java.io.InputStream.class, false,
+            (type, exchange, value) -> 
org.apache.camel.example.springboot.cxf.otel.InputStreamConverter.toRandomNumber((java.io.InputStream)
 value));
+    }
+
+    private static void addTypeConverter(TypeConverterRegistry registry, 
Class<?> toType, Class<?> fromType, boolean allowNull, 
SimpleTypeConverter.ConversionMethod method) {
+        registry.addTypeConverter(toType, fromType, new 
SimpleTypeConverter(allowNull, method));
+    }
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-common/src/generated/java/org/apache/camel/example/springboot/cxf/otel/IntegerConverterLoader.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/generated/java/org/apache/camel/example/springboot/cxf/otel/IntegerConverterLoader.java
new file mode 100644
index 0000000..fe86ec1
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/generated/java/org/apache/camel/example/springboot/cxf/otel/IntegerConverterLoader.java
@@ -0,0 +1,54 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import javax.annotation.processing.Generated;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.DeferredContextBinding;
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConversionException;
+import org.apache.camel.TypeConverterLoaderException;
+import org.apache.camel.spi.TypeConverterLoader;
+import org.apache.camel.spi.TypeConverterRegistry;
+import org.apache.camel.support.SimpleTypeConverter;
+import org.apache.camel.support.TypeConverterSupport;
+import org.apache.camel.util.DoubleMap;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.TypeConverterLoaderGeneratorMojo")
+@SuppressWarnings("unchecked")
+@DeferredContextBinding
+public final class IntegerConverterLoader implements TypeConverterLoader, 
CamelContextAware {
+
+    private CamelContext camelContext;
+
+    public IntegerConverterLoader() {
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void load(TypeConverterRegistry registry) throws 
TypeConverterLoaderException {
+        registerConverters(registry);
+    }
+
+    private void registerConverters(TypeConverterRegistry registry) {
+        addTypeConverter(registry, 
org.apache.camel.example.springboot.cxf.otel.RandomNumber.class, 
java.lang.Integer.class, false,
+            (type, exchange, value) -> 
org.apache.camel.example.springboot.cxf.otel.IntegerConverter.toRandomNumber((java.lang.Integer)
 value));
+    }
+
+    private static void addTypeConverter(TypeConverterRegistry registry, 
Class<?> toType, Class<?> fromType, boolean allowNull, 
SimpleTypeConverter.ConversionMethod method) {
+        registry.addTypeConverter(toType, fromType, new 
SimpleTypeConverter(allowNull, method));
+    }
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-common/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
new file mode 100644
index 0000000..b01c01e
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/generated/resources/META-INF/services/org/apache/camel/TypeConverterLoader
@@ -0,0 +1,3 @@
+# Generated by camel build tools - do NOT edit this file!
+org.apache.camel.example.springboot.cxf.otel.InputStreamConverterLoader
+org.apache.camel.example.springboot.cxf.otel.IntegerConverterLoader
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/Constants.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/Constants.java
new file mode 100644
index 0000000..0040108
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/Constants.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+public final class Constants {
+
+       private Constants() {
+       }
+
+       public static final String SERVICE_HEADER_NAME = "service-name";
+
+       public enum NUM_TYPE {
+               EVEN,
+               ODD
+       }
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/CxfConfig.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/CxfConfig.java
new file mode 100644
index 0000000..d1a1751
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/CxfConfig.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import org.apache.cxf.tracing.opentelemetry.jaxrs.OpenTelemetryFeature;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.jakarta.rs.json.JacksonJsonProvider;
+
+@Configuration
+public class CxfConfig {
+
+       @Bean
+       public JacksonJsonProvider jaxrsProvider() {
+               return new 
JacksonJsonProvider().configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, 
false);
+       }
+
+       @Bean
+       public OpenTelemetryFeature openTelemetryProvider() {
+               return new OpenTelemetryFeature();
+       }
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/InputStreamConverter.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/InputStreamConverter.java
new file mode 100644
index 0000000..d5137d6
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/InputStreamConverter.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import org.apache.camel.Converter;
+import org.apache.camel.TypeConverters;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+@Converter(generateLoader = true)
+public class InputStreamConverter implements TypeConverters {
+
+       @Converter
+       public static RandomNumber toRandomNumber(InputStream inputStream) 
throws IOException {
+               return new ObjectMapper().readValue(inputStream, 
RandomNumber.class);
+       }
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/IntegerConverter.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/IntegerConverter.java
new file mode 100644
index 0000000..ac5e361
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/IntegerConverter.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import org.apache.camel.Converter;
+import org.apache.camel.TypeConverters;
+
+@Converter(generateLoader = true)
+public class IntegerConverter implements TypeConverters {
+
+       @Converter
+       public static RandomNumber toRandomNumber(Integer num) {
+               return new RandomNumber(num);
+       }
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/RandomNumber.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/RandomNumber.java
new file mode 100644
index 0000000..c258f2f
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-common/src/main/java/org/apache/camel/example/springboot/cxf/otel/RandomNumber.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import java.util.Objects;
+import java.util.Optional;
+
+import jakarta.validation.constraints.NotNull;
+
+public class RandomNumber {
+
+       @NotNull
+       Integer number;
+
+       Constants.NUM_TYPE type;
+
+       public RandomNumber() {
+       }
+
+       public RandomNumber(final Integer number) {
+               this.number = number;
+       }
+
+       public Integer getNumber() {
+               return number;
+       }
+
+       public RandomNumber setNumber(final Integer number) {
+               this.number = number;
+               return this;
+       }
+
+       public Constants.NUM_TYPE getType() {
+               return type;
+       }
+
+       public RandomNumber setType(final Constants.NUM_TYPE type) {
+               this.type = type;
+               return this;
+       }
+
+       @Override
+       public String toString() {
+               return 
Optional.ofNullable(number).map(Objects::toString).orElse("");
+       }
+
+       @Override
+       public boolean equals(final Object o) {
+               if (this == o) return true;
+               if (o == null || getClass() != o.getClass()) return false;
+               final RandomNumber that = (RandomNumber) o;
+               return Objects.equals(getNumber(), that.getNumber());
+       }
+
+       @Override
+       public int hashCode() {
+               return Objects.hash(getNumber());
+       }
+}
diff --git a/rest-cxf-opentelemetry/rest-cxf-otel-even/pom.xml 
b/rest-cxf-opentelemetry/rest-cxf-otel-even/pom.xml
new file mode 100644
index 0000000..f80eac9
--- /dev/null
+++ b/rest-cxf-opentelemetry/rest-cxf-otel-even/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.apache.camel.springboot.example</groupId>
+               
<artifactId>camel-example-spring-boot-rest-cxf-opentelemetry</artifactId>
+               <version>4.8.0-SNAPSHOT</version>
+       </parent>
+
+       <artifactId>camel-example-spring-boot-rest-cxf-otel-even</artifactId>
+       <name>Camel SB Examples :: REST using CXF and OpenTelemetry :: 
Even</name>
+
+       <properties>
+               <category>CXF</category>
+       </properties>
+
+       <dependencies>
+               <dependency>
+                       <groupId>org.apache.camel.springboot.example</groupId>
+                       
<artifactId>camel-example-spring-boot-rest-cxf-otel-common</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+       </dependencies>
+
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.springframework.boot</groupId>
+                               
<artifactId>spring-boot-maven-plugin</artifactId>
+                               <version>${spring-boot-version}</version>
+                               <executions>
+                                       <execution>
+                                               <goals>
+                                                       <goal>repackage</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+</project>
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/Application.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/Application.java
new file mode 100644
index 0000000..15b7d45
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/Application.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import org.apache.camel.opentelemetry.starter.CamelOpenTelemetry;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+// CHECKSTYLE:OFF
+@SpringBootApplication
+@CamelOpenTelemetry
+public class Application {
+
+    /**
+     * Main method to start the application.
+     */
+    public static void main(String[] args) {
+        SpringApplication.run(Application.class, args);
+    }
+
+}
+// CHECKSTYLE:ON
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/CamelRouter.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/CamelRouter.java
new file mode 100644
index 0000000..c2aa567
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/CamelRouter.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import static 
org.apache.camel.example.springboot.cxf.otel.Constants.SERVICE_HEADER_NAME;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.bean.validator.BeanValidationException;
+import org.apache.camel.component.cxf.common.message.CxfConstants;
+import org.apache.camel.model.dataformat.JsonLibrary;
+
+import org.springframework.stereotype.Component;
+
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+@Component
+public class CamelRouter extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        //very raw way, just to handle the validation responses
+        onException(BeanValidationException.class)
+                .handled(true)
+                .setHeader(Exchange.HTTP_RESPONSE_CODE, 
constant(Response.Status.BAD_REQUEST.getStatusCode()))
+                
.setBody(simple("${exchangeProperty.CamelExceptionCaught.getMessage()}"));
+
+        // @formatter:off
+        from("cxfrs:/api?" +
+                    
"resourceClasses=org.apache.camel.example.springboot.cxf.otel.EvenService" +
+                    "&bindingStyle=SimpleConsumer" +
+                    "&providers=jaxrsProvider,openTelemetryProvider" +
+                    "&loggingFeatureEnabled=true")
+                .to("log:camel-cxf-log?showAll=true")
+                .setHeader(Exchange.BEAN_METHOD_NAME, 
simple("${header.operationName}"))
+                .bean(EvenServiceImpl.class);
+
+
+        from("direct:register").routeId("even-register")
+                .marshal().json(JsonLibrary.Jackson)
+                .setHeader(CxfConstants.HTTP_METHOD, constant("PUT"))
+                .setHeader(CxfConstants.CONTENT_TYPE, 
constant(MediaType.APPLICATION_JSON))
+                .setHeader(SERVICE_HEADER_NAME, constant("even"))
+                .toD("cxfrs:{{service.random.url}}/services/api/register");
+        // @formatter:on
+    }
+
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/EvenService.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/EvenService.java
new file mode 100644
index 0000000..bf0a62d
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/EvenService.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import jakarta.validation.Valid;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+/**
+ * Service interface for managing users.
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+public interface EvenService {
+
+    /**
+     * Check if the number is even, and eventually, register it
+     *
+     * @param number
+     *            the number to verify
+     */
+    @POST
+    @Path("/check")
+    RandomNumber check(@Valid RandomNumber number);
+
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/EvenServiceImpl.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/EvenServiceImpl.java
new file mode 100644
index 0000000..446bf59
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/java/org/apache/camel/example/springboot/cxf/otel/EvenServiceImpl.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import org.apache.camel.ProducerTemplate;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class EvenServiceImpl implements EvenService {
+
+       private static final Logger LOGGER = 
LoggerFactory.getLogger(EvenServiceImpl.class);
+
+       @Autowired
+       ProducerTemplate producerTemplate;
+
+       @Override
+       public RandomNumber check(RandomNumber number) {
+               if (number.getNumber() % 2 == 0) {
+                       //register
+                       producerTemplate.sendBody("direct:register", new 
RandomNumber().setNumber(number.getNumber()).setType(Constants.NUM_TYPE.EVEN));
+               } else {
+                       LOGGER.info("skip {}, it is odd", number);
+               }
+               return number;
+       }
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/resources/application.properties
 
b/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/resources/application.properties
new file mode 100644
index 0000000..4e64700
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-even/src/main/resources/application.properties
@@ -0,0 +1,22 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# the name of Camel
+camel.springboot.name = cxf-otel-even
+camel.springboot.main-run-controller=true
+service.random.url = http://localhost:8080
+#logging.level.org.apache.cxf = TRACE
diff --git a/rest-cxf-opentelemetry/rest-cxf-otel-odd/pom.xml 
b/rest-cxf-opentelemetry/rest-cxf-otel-odd/pom.xml
new file mode 100644
index 0000000..83fb364
--- /dev/null
+++ b/rest-cxf-opentelemetry/rest-cxf-otel-odd/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.apache.camel.springboot.example</groupId>
+               
<artifactId>camel-example-spring-boot-rest-cxf-opentelemetry</artifactId>
+               <version>4.8.0-SNAPSHOT</version>
+       </parent>
+
+       <artifactId>camel-example-spring-boot-rest-cxf-otel-odd</artifactId>
+       <name>Camel SB Examples :: REST using CXF and OpenTelemetry :: 
Odd</name>
+
+       <properties>
+               <category>CXF</category>
+       </properties>
+
+       <dependencies>
+               <dependency>
+                       <groupId>org.apache.camel.springboot.example</groupId>
+                       
<artifactId>camel-example-spring-boot-rest-cxf-otel-common</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+       </dependencies>
+
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.springframework.boot</groupId>
+                               
<artifactId>spring-boot-maven-plugin</artifactId>
+                               <version>${spring-boot-version}</version>
+                               <executions>
+                                       <execution>
+                                               <goals>
+                                                       <goal>repackage</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+</project>
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/Application.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/Application.java
new file mode 100644
index 0000000..15b7d45
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/Application.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import org.apache.camel.opentelemetry.starter.CamelOpenTelemetry;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+// CHECKSTYLE:OFF
+@SpringBootApplication
+@CamelOpenTelemetry
+public class Application {
+
+    /**
+     * Main method to start the application.
+     */
+    public static void main(String[] args) {
+        SpringApplication.run(Application.class, args);
+    }
+
+}
+// CHECKSTYLE:ON
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/CamelRouter.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/CamelRouter.java
new file mode 100644
index 0000000..d355dc0
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/CamelRouter.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import static 
org.apache.camel.example.springboot.cxf.otel.Constants.SERVICE_HEADER_NAME;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.bean.validator.BeanValidationException;
+import org.apache.camel.component.cxf.common.message.CxfConstants;
+import org.apache.camel.model.dataformat.JsonLibrary;
+
+import org.springframework.stereotype.Component;
+
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+@Component
+public class CamelRouter extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        //very raw way, just to handle the validation responses
+        onException(BeanValidationException.class)
+                .handled(true)
+                .setHeader(Exchange.HTTP_RESPONSE_CODE, 
constant(Response.Status.BAD_REQUEST.getStatusCode()))
+                
.setBody(simple("${exchangeProperty.CamelExceptionCaught.getMessage()}"));
+
+        // @formatter:off
+        from("cxfrs:/api?" +
+                    
"resourceClasses=org.apache.camel.example.springboot.cxf.otel.OddService" +
+                    "&bindingStyle=SimpleConsumer" +
+                    "&providers=jaxrsProvider,openTelemetryProvider" +
+                    "&loggingFeatureEnabled=true")
+                .to("log:camel-cxf-log?showAll=true")
+                .setHeader(Exchange.BEAN_METHOD_NAME, 
simple("${header.operationName}"))
+                .bean(OddServiceImpl.class);
+
+
+        from("direct:register").routeId("odd-register")
+                .marshal().json(JsonLibrary.Jackson)
+                .setHeader(CxfConstants.HTTP_METHOD, constant("PUT"))
+                .setHeader(CxfConstants.CONTENT_TYPE, 
constant(MediaType.APPLICATION_JSON))
+                .setHeader(SERVICE_HEADER_NAME, constant("odd"))
+                .toD("cxfrs:{{service.random.url}}/services/api/register");
+        // @formatter:on
+    }
+
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/OddService.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/OddService.java
new file mode 100644
index 0000000..4ecdce5
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/OddService.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import jakarta.validation.Valid;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+/**
+ * Service interface for managing users.
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+public interface OddService {
+
+    /**
+     * Check if the number is odd, and eventually, register it
+     *
+     * @param number
+     *            the number to verify
+     */
+    @POST
+    @Path("/check")
+    RandomNumber check(@Valid RandomNumber number);
+
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/OddServiceImpl.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/OddServiceImpl.java
new file mode 100644
index 0000000..bab2b46
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/java/org/apache/camel/example/springboot/cxf/otel/OddServiceImpl.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import org.apache.camel.ProducerTemplate;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class OddServiceImpl implements OddService {
+
+       private static final Logger LOGGER = 
LoggerFactory.getLogger(OddServiceImpl.class);
+
+       @Autowired
+       ProducerTemplate producerTemplate;
+
+       @Override
+       public RandomNumber check(RandomNumber number) {
+               if (number.getNumber() % 2 == 1) {
+                       //register
+                       producerTemplate.sendBody("direct:register", new 
RandomNumber().setNumber(number.getNumber()).setType(Constants.NUM_TYPE.ODD));
+               } else {
+                       LOGGER.info("skip {}, it is even", number);
+               }
+               return number;
+       }
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/resources/application.properties
 
b/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/resources/application.properties
new file mode 100644
index 0000000..0a6755a
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-odd/src/main/resources/application.properties
@@ -0,0 +1,22 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# the name of Camel
+camel.springboot.name = cxf-otel-odd
+camel.springboot.main-run-controller=true
+service.random.url = http://localhost:8080
+#logging.level.org.apache.cxf = TRACE
diff --git a/rest-cxf-opentelemetry/rest-cxf-otel-random/pom.xml 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/pom.xml
new file mode 100644
index 0000000..ed984b9
--- /dev/null
+++ b/rest-cxf-opentelemetry/rest-cxf-otel-random/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+       <modelVersion>4.0.0</modelVersion>
+
+       <parent>
+               <groupId>org.apache.camel.springboot.example</groupId>
+               
<artifactId>camel-example-spring-boot-rest-cxf-opentelemetry</artifactId>
+               <version>4.8.0-SNAPSHOT</version>
+       </parent>
+
+       <artifactId>camel-example-spring-boot-rest-cxf-otel-random</artifactId>
+       <name>Camel SB Examples :: REST using CXF and OpenTelemetry :: 
Random</name>
+
+       <properties>
+               <category>CXF</category>
+       </properties>
+
+       <dependencies>
+               <dependency>
+                       <groupId>org.apache.camel.springboot.example</groupId>
+                       
<artifactId>camel-example-spring-boot-rest-cxf-otel-common</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.apache.camel.springboot</groupId>
+                       <artifactId>camel-minio-starter</artifactId>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.springframework.boot</groupId>
+                               
<artifactId>spring-boot-maven-plugin</artifactId>
+                               <version>${spring-boot-version}</version>
+                               <executions>
+                                       <execution>
+                                               <goals>
+                                                       <goal>repackage</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+
+</project>
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/Application.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/Application.java
new file mode 100644
index 0000000..15b7d45
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/Application.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import org.apache.camel.opentelemetry.starter.CamelOpenTelemetry;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+// CHECKSTYLE:OFF
+@SpringBootApplication
+@CamelOpenTelemetry
+public class Application {
+
+    /**
+     * Main method to start the application.
+     */
+    public static void main(String[] args) {
+        SpringApplication.run(Application.class, args);
+    }
+
+}
+// CHECKSTYLE:ON
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/CamelRouter.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/CamelRouter.java
new file mode 100644
index 0000000..9d7e9c4
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/CamelRouter.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.bean.validator.BeanValidationException;
+import org.apache.camel.component.cxf.common.message.CxfConstants;
+import org.apache.camel.component.minio.MinioConstants;
+import org.apache.camel.model.dataformat.JsonLibrary;
+
+import org.springframework.stereotype.Component;
+
+import java.security.SecureRandom;
+
+import io.minio.Result;
+import io.minio.messages.Contents;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+@Component
+public class CamelRouter extends RouteBuilder {
+
+
+    @Override
+    public void configure() throws Exception {
+        //very raw way, just to handle the validation responses
+        onException(BeanValidationException.class)
+                .handled(true)
+                .setHeader(Exchange.HTTP_RESPONSE_CODE, 
constant(Response.Status.BAD_REQUEST.getStatusCode()))
+                
.setBody(simple("${exchangeProperty.CamelExceptionCaught.getMessage()}"));
+
+        // @formatter:off
+        from("cxfrs:/api?" +
+                    
"resourceClasses=org.apache.camel.example.springboot.cxf.otel.RandomService" +
+                    "&bindingStyle=SimpleConsumer" +
+                    "&providers=jaxrsProvider,openTelemetryProvider" +
+                    "&loggingFeatureEnabled=true")
+                .to("log:camel-cxf-log?showAll=true")
+                .setHeader(Exchange.BEAN_METHOD_NAME, 
simple("${header.operationName}"))
+                .bean(RandomServiceImpl.class);
+
+
+        from("direct:play").routeId("play")
+                .loop(header("attempts"))
+                    .process(exchange -> exchange.getIn().getHeaders().clear())
+                    .setHeader(CxfConstants.HTTP_METHOD, constant("GET"))
+                    .toD("cxfrs:{{service.random.url}}/services/api/generate")
+                    .process(exchange -> exchange.getIn().getHeaders().clear())
+                    .setHeader(CxfConstants.HTTP_METHOD, constant("POST"))
+                    .setHeader(CxfConstants.CONTENT_TYPE, 
constant(MediaType.APPLICATION_JSON))
+                    .toD("cxfrs:{{service.even.url}}/services/api/check")
+                    .process(exchange -> exchange.getIn().getHeaders().clear())
+                    .setHeader(CxfConstants.HTTP_METHOD, constant("POST"))
+                    .setHeader(CxfConstants.CONTENT_TYPE, 
constant(MediaType.APPLICATION_JSON))
+                    .toD("cxfrs:{{service.odd.url}}/services/api/check")
+                .end()
+                .setBody(constant(null));
+
+        from("direct:random").routeId("generate-random")
+                .loadBalance().random()
+                    .to("direct:generate-even")
+                    .to("direct:generate-odd")
+                .end()
+                .convertBodyTo(RandomNumber.class);
+
+        from("direct:generate-even")
+                .routeId("generate-even")
+                .process(exchange -> {
+                    int num = random();
+                    while (num % 2 != 0) {
+                        num = random();
+                    }
+                    exchange.getIn().setBody(num);
+                });
+
+        from("direct:generate-odd").routeId("generate-odd")
+                .process(exchange -> {
+                    int num = random();
+                    while (num % 2 == 0) {
+                        num = random();
+                    }
+                    exchange.getIn().setBody(num);
+                });
+
+        from("direct:save-obj").routeId("save-obj")
+                .setHeader(MinioConstants.OBJECT_NAME, header("objectName"))
+                .marshal().json(JsonLibrary.Jackson)
+                .toD("minio://{{bucket.name}}");
+
+        from("direct:load-results").routeId("load-results")
+                .setVariable("results", () -> new Results())
+                .toD("minio://{{bucket.name}}?operation=listObjects")
+                .split(body())
+                    .process(exchange -> {
+                                               try {
+                            
exchange.getIn().setHeader(MinioConstants.OBJECT_NAME
+                                    , ((Contents) 
exchange.getIn().getBody(Result.class).get()).objectName());
+                                               } catch (Exception e) {
+                                                       throw new 
RuntimeException(e);
+                                               }
+                                       })
+                    .toD("minio://{{bucket.name}}?operation=getObject")
+                    .unmarshal().json(JsonLibrary.Jackson, RandomNumber.class)
+                    .process(exchange -> exchange.getVariable("results", 
Results.class)
+                                                       
.addNumber(exchange.getIn().getBody(RandomNumber.class)))
+                .end()
+                .setBody(variable("results"));
+        // @formatter:on
+
+    }
+
+    private static int random() {
+        return new SecureRandom().nextInt(100, 1000);
+    }
+
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/RandomService.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/RandomService.java
new file mode 100644
index 0000000..fd2e23b
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/RandomService.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import org.apache.camel.Exchange;
+import org.apache.cxf.tracing.TracerContext;
+
+import jakarta.validation.Valid;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+
+/**
+ * Service interface for managing users.
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+public interface RandomService {
+
+    /**
+     * Find a user by the given ID
+     *
+     * @param attempts
+     *            the number of attempts, how many random numbers will be 
generated
+     * @return Results, the results
+     */
+    @POST
+    @Path("/play/{attempts}")
+    Results play(@PathParam("attempts") Integer attempts);
+
+    /**
+     * Generate random number between 100 and 1000
+     *
+     * @return RandomNumber, the number
+     */
+    @GET
+    @Path("/generate")
+    RandomNumber generate(@Context TracerContext tracer);
+
+    /**
+     * Register result
+     *
+     * @param number
+     *            the number to register
+     *
+     */
+    @PUT
+    @Path("/register")
+    void register(@Valid RandomNumber number, Exchange exchange);
+
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/RandomServiceImpl.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/RandomServiceImpl.java
new file mode 100644
index 0000000..1941b0a
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/RandomServiceImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import static 
org.apache.camel.example.springboot.cxf.otel.Constants.SERVICE_HEADER_NAME;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.cxf.tracing.TracerContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class RandomServiceImpl implements RandomService {
+
+       private static final Logger LOGGER = 
LoggerFactory.getLogger(RandomServiceImpl.class);
+
+       @Autowired
+       ProducerTemplate producerTemplate;
+
+       @Override
+       public Results play(Integer attempts) {
+               producerTemplate.requestBodyAndHeader("direct:play", null, 
"attempts", attempts, Void.class);
+               return producerTemplate.requestBody("direct:load-results", 
null, Results.class);
+       }
+
+       @Override
+       public RandomNumber generate(final TracerContext tracer) {
+               tracer.timeline("generate number");
+               tracer.annotate("custom-op", "generate");
+               return producerTemplate.requestBody("direct:random", null, 
RandomNumber.class);
+       }
+
+       @Override
+       public void register(RandomNumber number, Exchange exchange) {
+               final String serviceName = (String) 
exchange.getIn().getHeader(SERVICE_HEADER_NAME);
+               assert serviceName != null;
+               assert number != null;
+               assert number.getType() != null;
+               LOGGER.info("register {}", number);
+               final String objName = String.format("%s-%s", serviceName, 
number.getNumber());
+               producerTemplate.sendBodyAndHeader("direct:save-obj", number, 
"objectName", objName);
+       }
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/Results.java
 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/Results.java
new file mode 100644
index 0000000..ba0d7e5
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/java/org/apache/camel/example/springboot/cxf/otel/Results.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.springboot.cxf.otel;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+import jakarta.validation.constraints.NotNull;
+
+public class Results {
+       @NotNull
+       Map<Constants.NUM_TYPE, List<RandomNumber>> result;
+
+       public Results() {
+               result = new ConcurrentHashMap<>(2);
+       }
+
+       public Map<Constants.NUM_TYPE, List<RandomNumber>> getResult() {
+               return result;
+       }
+
+       public int getEvenCount() {
+               return count(Constants.NUM_TYPE.EVEN);
+       }
+
+       public int getOddCount() {
+               return count(Constants.NUM_TYPE.ODD);
+       }
+
+       public Results addNumber(RandomNumber num) {
+               addNumber(num.getType(), num);
+               return this;
+       }
+
+       private void addNumber(Constants.NUM_TYPE evenOddKey, RandomNumber 
number) {
+               final List<RandomNumber> values = 
Optional.ofNullable(result.get(evenOddKey)).orElseGet(() -> new ArrayList<>());
+               values.add(number);
+               result.put(evenOddKey, values);
+       }
+
+       private Integer count(Constants.NUM_TYPE key) {
+               return 
Optional.ofNullable(result.get(key)).map(List::size).orElse(0);
+       }
+
+}
diff --git 
a/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/resources/application.properties
 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/resources/application.properties
new file mode 100644
index 0000000..dd013fa
--- /dev/null
+++ 
b/rest-cxf-opentelemetry/rest-cxf-otel-random/src/main/resources/application.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# the name of Camel
+camel.springboot.name = cxf-otel-random
+camel.springboot.main-run-controller=true
+service.random.url = http://localhost:8080
+service.even.url = http://localhost:8081
+service.odd.url = http://localhost:8082
+bucket.name = evenodd
+camel.component.minio.access-key = admin
+camel.component.minio.secret-key = admin123
+camel.component.minio.endpoint = http://localhost:9000
+#logging.level.org.apache.cxf = TRACE

Reply via email to