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