From 7c4b350ca2ac207e6d67a990f9b196d4078b7a2c Mon Sep 17 00:00:00 2001 From: James Netherton Date: Wed, 25 Mar 2026 16:45:03 +0000 Subject: [PATCH 01/12] Next is 3.35.0 --- amqp/pom.xml | 12 ++++++------ artemis-elasticsearch/pom.xml | 12 ++++++------ aws-lambda/pom.xml | 12 ++++++------ aws2-s3/pom.xml | 12 ++++++------ cluster-leader-election/pom.xml | 12 ++++++------ cxf-soap/pom.xml | 12 ++++++------ data-extract-langchain4j/pom.xml | 12 ++++++------ fhir/pom.xml | 12 ++++++------ fhir/src/main/kubernetes/kubernetes.yml | 10 +++++----- fhir/src/main/kubernetes/openshift.yml | 10 +++++----- file-bindy-ftp/pom.xml | 12 ++++++------ file-bindy-ftp/src/main/kubernetes/kubernetes.yml | 12 ++++++------ file-bindy-ftp/src/main/kubernetes/openshift.yml | 12 ++++++------ file-split-log-xml/pom.xml | 12 ++++++------ health/pom.xml | 12 ++++++------ http-log/pom.xml | 12 ++++++------ jdbc-datasource/pom.xml | 12 ++++++------ jms-jpa/pom.xml | 12 ++++++------ jpa-idempotent-repository/pom.xml | 12 ++++++------ .../src/main/kubernetes/kubernetes.yml | 12 ++++++------ .../src/main/kubernetes/openshift.yml | 14 +++++++------- jta-jpa/pom.xml | 12 ++++++------ kafka/pom.xml | 12 ++++++------ kamelet-chucknorris/pom.xml | 12 ++++++------ message-bridge/pom.xml | 12 ++++++------ netty-custom-correlation/pom.xml | 12 ++++++------ observability/pom.xml | 12 ++++++------ openapi-contract-first/pom.xml | 12 ++++++------ platform-http-security-keycloak/pom.xml | 12 ++++++------ quarkus-rest-json/pom.xml | 12 ++++++------ rest-json/pom.xml | 12 ++++++------ saga/pom.xml | 12 ++++++------ saga/saga-app/pom.xml | 2 +- saga/saga-flight-service/pom.xml | 2 +- saga/saga-payment-service/pom.xml | 2 +- saga/saga-train-service/pom.xml | 2 +- spring-redis/pom.xml | 12 ++++++------ timer-log-main/pom.xml | 12 ++++++------ timer-log/pom.xml | 12 ++++++------ variables/pom.xml | 12 ++++++------ vertx-websocket-chat/pom.xml | 12 ++++++------ 41 files changed, 225 insertions(+), 225 deletions(-) diff --git a/amqp/pom.xml b/amqp/pom.xml index 9769aee3..9a3221b2 100644 --- a/amqp/pom.xml +++ b/amqp/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-amqp org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: AMQP Camel Quarkus Example :: AMQP - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/artemis-elasticsearch/pom.xml b/artemis-elasticsearch/pom.xml index a91ef20f..395ad47d 100644 --- a/artemis-elasticsearch/pom.xml +++ b/artemis-elasticsearch/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-artemis-elasticsearch org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Artemis ElasticSearch Camel Quarkus Example :: Artemis ElasticSearch - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/aws-lambda/pom.xml b/aws-lambda/pom.xml index 7476412f..63ba319a 100644 --- a/aws-lambda/pom.xml +++ b/aws-lambda/pom.xml @@ -21,19 +21,19 @@ 4.0.0 org.apache.camel.quarkus.examples camel-quarkus-examples-aws-lambda - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: AWS Lambda Camel Quarkus Example :: Deploying a Camel Route in AWS Lambda - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/aws2-s3/pom.xml b/aws2-s3/pom.xml index 87ac5f7c..e074be6b 100644 --- a/aws2-s3/pom.xml +++ b/aws2-s3/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-aws2-s3 org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: aws2-s3 Camel Quarkus Example :: Upload a file to an AWS S3 bucket - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/cluster-leader-election/pom.xml b/cluster-leader-election/pom.xml index de80f105..8bfd8ebf 100644 --- a/cluster-leader-election/pom.xml +++ b/cluster-leader-election/pom.xml @@ -23,19 +23,19 @@ camel-quarkus-examples-cluster-leader-election org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Cluster leader election Camel Quarkus Example :: Cluster leader election - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/cxf-soap/pom.xml b/cxf-soap/pom.xml index 2ef6599f..926f026f 100644 --- a/cxf-soap/pom.xml +++ b/cxf-soap/pom.xml @@ -23,19 +23,19 @@ camel-quarkus-examples-cxf-soap org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: CXF SOAP Camel Quarkus Example :: CXF SOAP - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/data-extract-langchain4j/pom.xml b/data-extract-langchain4j/pom.xml index ad4c4276..7eb36d22 100644 --- a/data-extract-langchain4j/pom.xml +++ b/data-extract-langchain4j/pom.xml @@ -24,20 +24,20 @@ camel-quarkus-examples-data-extract-langchain4j org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Data Extract LangChain4j Repository Camel Quarkus Example :: Data Extract LangChain4j Repository - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/fhir/pom.xml b/fhir/pom.xml index e4f7b8d3..80f2b470 100644 --- a/fhir/pom.xml +++ b/fhir/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-fhir org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: FHIR Camel Quarkus Example :: FHIR - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/fhir/src/main/kubernetes/kubernetes.yml b/fhir/src/main/kubernetes/kubernetes.yml index 8e1fcf7e..a19c63b6 100644 --- a/fhir/src/main/kubernetes/kubernetes.yml +++ b/fhir/src/main/kubernetes/kubernetes.yml @@ -21,18 +21,18 @@ metadata: name: fhir-server-deployment labels: app.kubernetes.io/name: camel-quarkus-examples-fhir - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: camel-quarkus-examples-fhir - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT template: metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-fhir - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: # Work around container permissions issues for /app/target # https://github.com/hapifhir/hapi-fhir-jpaserver-starter/issues/519 @@ -99,7 +99,7 @@ kind: Service metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-fhir - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT name: fhir-server spec: ports: @@ -108,5 +108,5 @@ spec: targetPort: 8080 selector: app.kubernetes.io/name: camel-quarkus-examples-fhir - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT type: ClusterIP diff --git a/fhir/src/main/kubernetes/openshift.yml b/fhir/src/main/kubernetes/openshift.yml index 13bb5c72..ecbdafb6 100644 --- a/fhir/src/main/kubernetes/openshift.yml +++ b/fhir/src/main/kubernetes/openshift.yml @@ -21,18 +21,18 @@ metadata: name: fhir-server labels: app.kubernetes.io/name: camel-quarkus-examples-fhir - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: camel-quarkus-examples-fhir - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT template: metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-fhir - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: # Work around container permissions issues for /app/target # https://github.com/hapifhir/hapi-fhir-jpaserver-starter/issues/519 @@ -99,7 +99,7 @@ kind: Service metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-fhir - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT name: fhir-server spec: ports: @@ -108,5 +108,5 @@ spec: targetPort: 8080 selector: app.kubernetes.io/name: camel-quarkus-examples-fhir - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT type: ClusterIP diff --git a/file-bindy-ftp/pom.xml b/file-bindy-ftp/pom.xml index 51edb846..e087e974 100644 --- a/file-bindy-ftp/pom.xml +++ b/file-bindy-ftp/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-file-bindy-ftp org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: File Bindy FTP Camel Quarkus Example :: File Bindy FTP - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/file-bindy-ftp/src/main/kubernetes/kubernetes.yml b/file-bindy-ftp/src/main/kubernetes/kubernetes.yml index 32a05fba..f3083c96 100644 --- a/file-bindy-ftp/src/main/kubernetes/kubernetes.yml +++ b/file-bindy-ftp/src/main/kubernetes/kubernetes.yml @@ -21,18 +21,18 @@ metadata: name: ssh-server-deployment labels: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT template: metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: containers: - name: openssh-server @@ -57,7 +57,7 @@ kind: Service metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT name: ftp-server spec: ports: @@ -66,7 +66,7 @@ spec: targetPort: 2222 selector: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT type: ClusterIP --- apiVersion: v1 @@ -77,7 +77,7 @@ kind: Secret metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT name: ftp-credentials type: Opaque --- diff --git a/file-bindy-ftp/src/main/kubernetes/openshift.yml b/file-bindy-ftp/src/main/kubernetes/openshift.yml index 32a05fba..f3083c96 100644 --- a/file-bindy-ftp/src/main/kubernetes/openshift.yml +++ b/file-bindy-ftp/src/main/kubernetes/openshift.yml @@ -21,18 +21,18 @@ metadata: name: ssh-server-deployment labels: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT template: metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: containers: - name: openssh-server @@ -57,7 +57,7 @@ kind: Service metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT name: ftp-server spec: ports: @@ -66,7 +66,7 @@ spec: targetPort: 2222 selector: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT type: ClusterIP --- apiVersion: v1 @@ -77,7 +77,7 @@ kind: Secret metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-file-bindy-ftp - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT name: ftp-credentials type: Opaque --- diff --git a/file-split-log-xml/pom.xml b/file-split-log-xml/pom.xml index a4a78c38..4b758cf1 100644 --- a/file-split-log-xml/pom.xml +++ b/file-split-log-xml/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-file-log-xml org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: File To Log XML DSL Camel Quarkus Example :: File To Log XML DSL - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/health/pom.xml b/health/pom.xml index 8e8fdb2e..4852270b 100644 --- a/health/pom.xml +++ b/health/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-health org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Health Camel Quarkus Example :: Health Check - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/http-log/pom.xml b/http-log/pom.xml index e320c3c4..5ccc7db4 100644 --- a/http-log/pom.xml +++ b/http-log/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-http-log org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: HTTP Log Camel Quarkus Example :: HTTP to Log - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/jdbc-datasource/pom.xml b/jdbc-datasource/pom.xml index d0ac3883..d255491b 100644 --- a/jdbc-datasource/pom.xml +++ b/jdbc-datasource/pom.xml @@ -21,17 +21,17 @@ 4.0.0 org.apache.camel.quarkus.examples camel-quarkus-examples-jdbc-datasource - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Jdbc - DatataSource - Log Camel Quarkus Example :: Connect to Database using Datasource - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom 2.29.0 1.13.0 diff --git a/jms-jpa/pom.xml b/jms-jpa/pom.xml index 13ba2d2c..9fcc2e84 100644 --- a/jms-jpa/pom.xml +++ b/jms-jpa/pom.xml @@ -21,18 +21,18 @@ 4.0.0 org.apache.camel.quarkus.examples camel-quarkus-examples-jms-jpa - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: JMS JPA Camel Quarkus Example :: JMS JPA - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT 3.13.0 - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom 2.29.0 1.13.0 diff --git a/jpa-idempotent-repository/pom.xml b/jpa-idempotent-repository/pom.xml index 0b64eaa7..49bcba2f 100644 --- a/jpa-idempotent-repository/pom.xml +++ b/jpa-idempotent-repository/pom.xml @@ -24,19 +24,19 @@ camel-quarkus-examples-jpa-idempotent-repository org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: JPA Idempotent Repository Camel Quarkus Example :: JPA Idempotent Repository - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/jpa-idempotent-repository/src/main/kubernetes/kubernetes.yml b/jpa-idempotent-repository/src/main/kubernetes/kubernetes.yml index b55a25f4..7ed6662a 100644 --- a/jpa-idempotent-repository/src/main/kubernetes/kubernetes.yml +++ b/jpa-idempotent-repository/src/main/kubernetes/kubernetes.yml @@ -21,18 +21,18 @@ metadata: name: camel-quarkus-examples-mariadb-database-deployment labels: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT template: metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: containers: - name: mariadb-database @@ -68,7 +68,7 @@ kind: Service metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT name: mariadb-database spec: ports: @@ -77,7 +77,7 @@ spec: targetPort: 3306 selector: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT type: ClusterIP --- apiVersion: v1 @@ -85,7 +85,7 @@ kind: Secret metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT name: mariadb-secret type: Opaque data: diff --git a/jpa-idempotent-repository/src/main/kubernetes/openshift.yml b/jpa-idempotent-repository/src/main/kubernetes/openshift.yml index 3f64e258..56527d18 100644 --- a/jpa-idempotent-repository/src/main/kubernetes/openshift.yml +++ b/jpa-idempotent-repository/src/main/kubernetes/openshift.yml @@ -21,18 +21,18 @@ metadata: name: camel-quarkus-examples-mariadb-database-deployment labels: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT template: metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: containers: - name: mariadb-database @@ -68,7 +68,7 @@ kind: Service metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT name: mariadb-database spec: ports: @@ -77,7 +77,7 @@ spec: targetPort: 3306 selector: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT type: ClusterIP --- apiVersion: v1 @@ -85,7 +85,7 @@ kind: Secret metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-mariadb-database - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT name: mariadb-secret type: Opaque data: @@ -104,7 +104,7 @@ spec: metadata: labels: app.kubernetes.io/name: camel-quarkus-examples-jpa-idempotent-repository-flyway-init - app.kubernetes.io/version: 3.33.0 + app.kubernetes.io/version: 3.35.0-SNAPSHOT spec: containers: - env: diff --git a/jta-jpa/pom.xml b/jta-jpa/pom.xml index 5d4e0b7f..be69b05a 100644 --- a/jta-jpa/pom.xml +++ b/jta-jpa/pom.xml @@ -21,17 +21,17 @@ 4.0.0 org.apache.camel.quarkus.examples camel-quarkus-examples-jta-jpa - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: JTA JPA Camel Quarkus Example :: JTA JPA - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom 2.29.0 1.13.0 diff --git a/kafka/pom.xml b/kafka/pom.xml index 2702d6ce..18a8b717 100644 --- a/kafka/pom.xml +++ b/kafka/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-kafka org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Kafka Camel Quarkus Example :: Kafka - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/kamelet-chucknorris/pom.xml b/kamelet-chucknorris/pom.xml index 2d9ba227..22bbe99e 100644 --- a/kamelet-chucknorris/pom.xml +++ b/kamelet-chucknorris/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-kamelet-chucknorris org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Kamelet Chuck Norris Camel Quarkus Example :: Kamelet Chuck Norris - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/message-bridge/pom.xml b/message-bridge/pom.xml index d9ab2247..8733424d 100644 --- a/message-bridge/pom.xml +++ b/message-bridge/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-message-bridge org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Message Bridge Camel Quarkus Example :: Configure XA Transactions and connection pooling - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/netty-custom-correlation/pom.xml b/netty-custom-correlation/pom.xml index 782cddea..fe2e5ffe 100644 --- a/netty-custom-correlation/pom.xml +++ b/netty-custom-correlation/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-netty-custom-correlation org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Communication with Netty over TCP Camel Quarkus Example :: Communication with Netty over TCP - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/observability/pom.xml b/observability/pom.xml index c43e1354..6a6a2440 100644 --- a/observability/pom.xml +++ b/observability/pom.xml @@ -22,20 +22,20 @@ camel-quarkus-examples-observability org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Observability Camel Quarkus Example :: Observability - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/openapi-contract-first/pom.xml b/openapi-contract-first/pom.xml index 60309f66..a591de9e 100644 --- a/openapi-contract-first/pom.xml +++ b/openapi-contract-first/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-examples-openapi-contract-first org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: openapi-contract-first Camel Quarkus Example :: openapi-contract-first - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/platform-http-security-keycloak/pom.xml b/platform-http-security-keycloak/pom.xml index 1d164e49..04fbe8da 100644 --- a/platform-http-security-keycloak/pom.xml +++ b/platform-http-security-keycloak/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-platform-http-security-keycloak org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Platform HTTP Security Keycloak Camel Quarkus Example :: Platform HTTP Security Keycloak - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/quarkus-rest-json/pom.xml b/quarkus-rest-json/pom.xml index 53d5ec54..76d6d7de 100644 --- a/quarkus-rest-json/pom.xml +++ b/quarkus-rest-json/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-rest-json org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Quarkus Rest Json Camel Quarkus Example :: Quarkus Rest Json - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/rest-json/pom.xml b/rest-json/pom.xml index d43ad0ef..2cc81a15 100644 --- a/rest-json/pom.xml +++ b/rest-json/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-rest-json org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Rest Json Camel Quarkus Example :: Rest Json - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/saga/pom.xml b/saga/pom.xml index 1525cb01..932b4961 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -22,21 +22,21 @@ camel-quarkus-examples-saga org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Saga Camel Quarkus Example :: Saga pom - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT 3.13.0 - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/saga/saga-app/pom.xml b/saga/saga-app/pom.xml index 3a7704b9..b7fd20c3 100644 --- a/saga/saga-app/pom.xml +++ b/saga/saga-app/pom.xml @@ -24,7 +24,7 @@ camel-quarkus-examples-saga org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT camel-quarkus-example-saga-app diff --git a/saga/saga-flight-service/pom.xml b/saga/saga-flight-service/pom.xml index 0cdd7267..40cf31d0 100644 --- a/saga/saga-flight-service/pom.xml +++ b/saga/saga-flight-service/pom.xml @@ -24,7 +24,7 @@ camel-quarkus-examples-saga org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT camel-quarkus-example-saga-flight diff --git a/saga/saga-payment-service/pom.xml b/saga/saga-payment-service/pom.xml index 324cbb10..83d7b951 100644 --- a/saga/saga-payment-service/pom.xml +++ b/saga/saga-payment-service/pom.xml @@ -24,7 +24,7 @@ camel-quarkus-examples-saga org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT camel-quarkus-example-saga-payment diff --git a/saga/saga-train-service/pom.xml b/saga/saga-train-service/pom.xml index bdec208e..5af427e8 100644 --- a/saga/saga-train-service/pom.xml +++ b/saga/saga-train-service/pom.xml @@ -24,7 +24,7 @@ camel-quarkus-examples-saga org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT camel-quarkus-example-saga-train diff --git a/spring-redis/pom.xml b/spring-redis/pom.xml index 6636cf47..7832acc7 100644 --- a/spring-redis/pom.xml +++ b/spring-redis/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-spring-redis org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: spring-redis Camel Quarkus Example :: Send and receive messages from Redis - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/timer-log-main/pom.xml b/timer-log-main/pom.xml index e0196862..ffffb1e5 100644 --- a/timer-log-main/pom.xml +++ b/timer-log-main/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-timer-log-main org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Timer Log Main Camel Quarkus Example :: Timer to Log Main - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/timer-log/pom.xml b/timer-log/pom.xml index 8df517f2..f911a845 100644 --- a/timer-log/pom.xml +++ b/timer-log/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-timer-log org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Timer Log Camel Quarkus Example :: Timer to Log - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/variables/pom.xml b/variables/pom.xml index 44395b4a..60a2137d 100644 --- a/variables/pom.xml +++ b/variables/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-variables org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Variables Camel Quarkus Example :: Variables - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 diff --git a/vertx-websocket-chat/pom.xml b/vertx-websocket-chat/pom.xml index 09cc1d74..76c1a530 100644 --- a/vertx-websocket-chat/pom.xml +++ b/vertx-websocket-chat/pom.xml @@ -22,19 +22,19 @@ camel-quarkus-examples-vertx-websocket-chat org.apache.camel.quarkus.examples - 3.33.0 + 3.35.0-SNAPSHOT Camel Quarkus :: Examples :: Vertx-Websocket chat Camel Quarkus Example :: Implementing Websocket - 3.33.1 - ${quarkus.platform.version} + 3.34.1 + 3.35.0-SNAPSHOT - io.quarkus.platform + io.quarkus quarkus-bom - ${quarkus.platform.group-id} - quarkus-camel-bom + org.apache.camel.quarkus + camel-quarkus-bom UTF-8 UTF-8 From 430cfb25b82d8fbee9ee9a70500a9af9ed3a93e0 Mon Sep 17 00:00:00 2001 From: James Netherton Date: Sun, 29 Mar 2026 09:35:47 +0100 Subject: [PATCH 02/12] Run only test phase for non-native CI workflow jobs --- .github/workflows/ci-build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-build.yaml b/.github/workflows/ci-build.yaml index 85a6c9cb..2e420720 100644 --- a/.github/workflows/ci-build.yaml +++ b/.github/workflows/ci-build.yaml @@ -191,7 +191,7 @@ jobs: - name: Integration Tests shell: bash run: | - ./mvnw-for-each.sh ${MAVEN_ARGS} clean verify + ./mvnw-for-each.sh ${MAVEN_ARGS} clean test - name: Fail if there are uncommitted changes shell: bash run: | @@ -225,7 +225,7 @@ jobs: - name: Integration Tests shell: bash run: | - ./mvnw-for-each.sh ${MAVEN_ARGS} -Dskip-testcontainers-tests clean verify + ./mvnw-for-each.sh ${MAVEN_ARGS} -Dskip-testcontainers-tests clean test - name: Fail if there are uncommitted changes shell: bash run: | From 9d4649a731d5bc17144bb7ed90fda5b7977e658a Mon Sep 17 00:00:00 2001 From: jomin mathew <> Date: Tue, 24 Mar 2026 12:10:55 +0000 Subject: [PATCH 03/12] Fixes #6195: Add integration tests for Saga example --- saga/README.adoc | 25 ++- saga/pom.xml | 19 ++- saga/saga-app/pom.xml | 17 ++ .../apache/camel/example/saga/SagaRoute.java | 9 +- saga/saga-flight-service/pom.xml | 17 ++ .../camel/example/saga/FlightRoute.java | 10 +- saga/saga-integration-tests/README.md | 126 +++++++++++++++ saga/saga-integration-tests/pom.xml | 148 ++++++++++++++++++ .../camel/example/saga/SagaBasicIT.java | 28 ++++ .../camel/example/saga/SagaBasicTest.java | 106 +++++++++++++ .../camel/example/saga/SagaTestResource.java | 115 ++++++++++++++ .../src/test/resources/application.yml | 48 ++++++ saga/saga-payment-service/pom.xml | 17 ++ .../camel/example/saga/PaymentRoute.java | 4 +- saga/saga-train-service/pom.xml | 17 ++ .../apache/camel/example/saga/TrainRoute.java | 10 +- 16 files changed, 697 insertions(+), 19 deletions(-) create mode 100644 saga/saga-integration-tests/README.md create mode 100644 saga/saga-integration-tests/pom.xml create mode 100644 saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaBasicIT.java create mode 100644 saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaBasicTest.java create mode 100644 saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaTestResource.java create mode 100644 saga/saga-integration-tests/src/test/resources/application.yml diff --git a/saga/README.adoc b/saga/README.adoc index d6dabf57..8a7ade08 100644 --- a/saga/README.adoc +++ b/saga/README.adoc @@ -8,12 +8,16 @@ and other general information. === How it works -There are 4 services as participants of the Saga: +There are 5 modules in this example: -- payment-service: it emulates a real payment transaction, and it will be used by both flight-service and train-service +**Service Modules:** +- app: is the starting point, and it emulates a user that starts the transaction to buy both flight and train tickets - flight-service: it emulates the booking of a flight ticket, and it uses the payment-service to execute a payment transaction - train-service: it emulates the reservation of a train seat, and it uses the payment-service to execute a payment transaction -- app: is the starting point, and it emulates a user that starts the transaction to buy both flight and train tickets +- payment-service: it emulates a real payment transaction, and it will be used by both flight-service and train-service + +**Test Module:** +- integration-tests: contains automated integration tests using Testcontainers for Docker-based testing The starting point is a REST endpoint that creates a request for a new reservation and there is 15% probability that the payment service fails. @@ -101,6 +105,21 @@ Transaction http://localhost:8080/lra-coordinator/0_ffff7f000001_8aad_62d16f11_7 ---- +=== Running Tests + +The integration tests use Testcontainers to automatically start Artemis and LRA Coordinator in Docker. + +[source,shell] +---- +# Ensure Docker is running +docker ps + +# Run integration tests +mvn clean test -pl saga-integration-tests +---- + +See link:saga-integration-tests/README.md[saga-integration-tests/README.md] for more details. + === Package and run the application Once you are done with developing you may want to package and run the application. diff --git a/saga/pom.xml b/saga/pom.xml index 932b4961..75d70b56 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -44,6 +44,7 @@ 2.29.0 1.13.0 + 3.0.1 5.0.0 3.15.0 3.5.0 @@ -56,6 +57,7 @@ saga-flight-service saga-payment-service saga-train-service + saga-integration-tests @@ -87,6 +89,10 @@ org.apache.camel.quarkus camel-quarkus-core + + org.apache.camel.quarkus + camel-quarkus-bean + org.apache.camel.quarkus camel-quarkus-direct @@ -104,13 +110,6 @@ quarkus-artemis-jms ${quarkiverse-artemis.version} - - - - io.quarkus - quarkus-junit - test - @@ -182,6 +181,12 @@ ${maven-jar-plugin.version} + + io.smallrye + jandex-maven-plugin + ${jandex-maven-plugin.version} + + com.mycila license-maven-plugin diff --git a/saga/saga-app/pom.xml b/saga/saga-app/pom.xml index b7fd20c3..ad10c7b7 100644 --- a/saga/saga-app/pom.xml +++ b/saga/saga-app/pom.xml @@ -31,4 +31,21 @@ Camel Quarkus :: Examples :: Saga :: App Main application starting SAGA + + + + io.smallrye + jandex-maven-plugin + + + make-index + + jandex + + + + + + + diff --git a/saga/saga-app/src/main/java/org/apache/camel/example/saga/SagaRoute.java b/saga/saga-app/src/main/java/org/apache/camel/example/saga/SagaRoute.java index d1985326..6f31b1df 100644 --- a/saga/saga-app/src/main/java/org/apache/camel/example/saga/SagaRoute.java +++ b/saga/saga-app/src/main/java/org/apache/camel/example/saga/SagaRoute.java @@ -16,9 +16,11 @@ */ package org.apache.camel.example.saga; +import jakarta.enterprise.context.ApplicationScoped; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.model.rest.RestParamType; +@ApplicationScoped public class SagaRoute extends RouteBuilder { @Override @@ -33,12 +35,15 @@ public void configure() throws Exception { .compensation("direct:cancelOrder") .log("Executing saga #${header.id} with LRA ${header.Long-Running-Action}") .setHeader("payFor", constant("train")) + // Request timeout prevents indefinite waits during service failures or slow responses .to("jms:queue:{{example.services.train}}?exchangePattern=InOut" + - "&replyTo={{example.services.train}}.reply") + "&replyTo={{example.services.train}}.reply" + + "&requestTimeout=30000") .log("train seat reserved for saga #${header.id} with payment transaction: ${body}") .setHeader("payFor", constant("flight")) .to("jms:queue:{{example.services.flight}}?exchangePattern=InOut" + - "&replyTo={{example.services.flight}}.reply") + "&replyTo={{example.services.flight}}.reply" + + "&requestTimeout=30000") .log("flight booked for saga #${header.id} with payment transaction: ${body}") .setBody(header("Long-Running-Action")) .end(); diff --git a/saga/saga-flight-service/pom.xml b/saga/saga-flight-service/pom.xml index 40cf31d0..62c36c58 100644 --- a/saga/saga-flight-service/pom.xml +++ b/saga/saga-flight-service/pom.xml @@ -31,4 +31,21 @@ Camel Quarkus :: Examples :: Saga :: Flight Service Flight Service + + + + io.smallrye + jandex-maven-plugin + + + make-index + + jandex + + + + + + + diff --git a/saga/saga-flight-service/src/main/java/org/apache/camel/example/saga/FlightRoute.java b/saga/saga-flight-service/src/main/java/org/apache/camel/example/saga/FlightRoute.java index 8e0bd7e0..04694f18 100644 --- a/saga/saga-flight-service/src/main/java/org/apache/camel/example/saga/FlightRoute.java +++ b/saga/saga-flight-service/src/main/java/org/apache/camel/example/saga/FlightRoute.java @@ -16,9 +16,11 @@ */ package org.apache.camel.example.saga; +import jakarta.enterprise.context.ApplicationScoped; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.model.SagaPropagation; +@ApplicationScoped public class FlightRoute extends RouteBuilder { @Override @@ -27,14 +29,16 @@ public void configure() throws Exception { .saga() .propagation(SagaPropagation.MANDATORY) .option("id", header("id")) - .compensation("direct:cancelPurchase") + .compensation("direct:cancelFlightPurchase") .log("Buying flight #${header.id}") + // Request timeout prevents indefinite waits during payment service failures .to("jms:queue:{{example.services.payment}}?exchangePattern=InOut" + - "&replyTo={{example.services.payment}}.flight.reply") + "&replyTo={{example.services.payment}}.flight.reply" + + "&requestTimeout=30000") .log("Payment for flight #${header.id} done with transaction ${body}") .end(); - from("direct:cancelPurchase") + from("direct:cancelFlightPurchase") .log("Flight purchase #${header.id} has been cancelled due to payment failure"); } diff --git a/saga/saga-integration-tests/README.md b/saga/saga-integration-tests/README.md new file mode 100644 index 00000000..86a3f139 --- /dev/null +++ b/saga/saga-integration-tests/README.md @@ -0,0 +1,126 @@ +# Saga Integration Tests + +Integration tests for the Camel Quarkus Saga example demonstrating distributed transaction coordination using the LRA (Long Running Action) pattern with JMS messaging. + +## Overview + +This module tests the Saga example by running all services (train, flight, payment) in a single JVM with Testcontainers managing external dependencies (LRA Coordinator and Artemis broker). + +## Test Coverage + +The test suite verifies: + +- **LRA Integration:** Saga coordination with LRA coordinator +- **JMS Messaging:** Request-reply pattern over Artemis queues +- **Service Participation:** Train, flight, and payment service coordination +- **Compensation Flow:** Rollback when failures occur (15% random failure rate) +- **End-to-End Flow:** Complete saga orchestration + +### Test Case + +`testSagaWithLRAAndRandomOutcomes()` - Comprehensive end-to-end test that verifies the complete saga flow including LRA coordination, all service participation (train, flight, payment), and validates both success and compensation scenarios. Since the payment service has a 15% random failure rate, the test accepts either outcome as valid. + +## Running Tests + +### Prerequisites + +- Java 17+ +- Maven 3.9+ +- Docker (for Testcontainers) + +### Execute Tests + +```bash +# Run all tests +mvn clean test -pl saga-integration-tests + +# Run specific test +mvn test -pl saga-integration-tests -Dtest=SagaBasicTest#testCompleteSagaFlow + +# Native mode +mvn clean verify -Pnative -pl saga-integration-tests +``` + +## Infrastructure + +**Testcontainers manages:** + +- **LRA Coordinator** (`quay.io/jbosstm/lra-coordinator:latest`) - Distributed saga coordination +- **Artemis Broker** (`quay.io/artemiscloud/activemq-artemis-broker:latest`) - JMS messaging + +Both containers run on a shared Docker network with proper wait strategies. + +## Configuration + +### Test Settings (`src/test/resources/application.yml`) + +Key configuration settings: + +```yaml +quarkus: + http: + port: 8084 + log: + file: + enable: true + path: target/quarkus.log + category: + "org.apache.camel": DEBUG + "org.apache.camel.saga": DEBUG + "org.apache.camel.component.lra": DEBUG + +camel: + lra: + enabled: true + # coordinator-url and local-participant-url are set by SagaTestResource + component: + jms: + test-connection-on-startup: true + concurrent-consumers: 5 +``` + +Dynamic configuration (Artemis URL, LRA coordinator URL) is injected by `SagaTestResource` at test runtime. + +## Saga Flow + +``` +POST /api/saga?id=1 + → SagaRoute creates LRA transaction + → Sends to jms:queue:saga-train-service + → TrainRoute processes and sends to jms:queue:saga-payment-service + → PaymentRoute completes payment + → Sends to jms:queue:saga-flight-service + → FlightRoute processes and sends to jms:queue:saga-payment-service + → PaymentRoute completes payment + → LRA Coordinator commits saga + → Returns LRA ID +``` + +## Troubleshooting + +### Tests Fail with "Connection Refused" + +Docker not running. Start Docker and verify: +```bash +docker ps +``` + +### Tests Timeout + +Increase timeout in tests: +```java +await().atMost(30, TimeUnit.SECONDS) // Instead of 10-15 +``` + +### View Container Logs + +```bash +docker ps # Find container ID +docker logs +``` + +## Related Links + +- [Camel Saga EIP](https://camel.apache.org/components/latest/eips/saga-eip.html) +- [Camel LRA Component](https://camel.apache.org/components/latest/lra-component.html) +- [Issue #6195](https://github.com/apache/camel-quarkus/issues/6195) diff --git a/saga/saga-integration-tests/pom.xml b/saga/saga-integration-tests/pom.xml new file mode 100644 index 00000000..e74983de --- /dev/null +++ b/saga/saga-integration-tests/pom.xml @@ -0,0 +1,148 @@ + + + + + 4.0.0 + + + camel-quarkus-examples-saga + org.apache.camel.quarkus.examples + 3.35.0-SNAPSHOT + + + camel-quarkus-example-saga-integration-tests + Camel Quarkus :: Examples :: Saga :: Integration Tests + Integration tests for Saga example + + + + + org.apache.camel.quarkus.examples + camel-quarkus-example-saga-app + ${project.version} + + + org.apache.camel.quarkus.examples + camel-quarkus-example-saga-flight + ${project.version} + + + org.apache.camel.quarkus.examples + camel-quarkus-example-saga-train + ${project.version} + + + org.apache.camel.quarkus.examples + camel-quarkus-example-saga-payment + ${project.version} + + + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + org.awaitility + awaitility + test + + + org.testcontainers + testcontainers + test + + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + + + build + + build + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + org.jboss.logmanager.LogManager + + + + + + + + + native + + + native + + + + true + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + + + + + + skip-testcontainers-tests + + + skip-testcontainers-tests + + + + true + + + + + diff --git a/saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaBasicIT.java b/saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaBasicIT.java new file mode 100644 index 00000000..c27b6790 --- /dev/null +++ b/saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaBasicIT.java @@ -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. + */ +package org.apache.camel.example.saga; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +/** + * Integration test for native mode compilation. + * Extends SagaBasicTest to run the same tests against native executable. + */ +@QuarkusIntegrationTest +public class SagaBasicIT extends SagaBasicTest { + // Runs all tests from SagaBasicTest in native mode +} diff --git a/saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaBasicTest.java b/saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaBasicTest.java new file mode 100644 index 00000000..64700c51 --- /dev/null +++ b/saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaBasicTest.java @@ -0,0 +1,106 @@ +/* + * 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.saga; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.Duration; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import org.awaitility.Awaitility; +import org.jboss.logmanager.Logger; +import org.junit.jupiter.api.Test; + +import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Basic integration tests for Saga example. + * Tests verify saga orchestration, service participation, routing, and compensation. + * Note: Payment service has 15% random failure rate to test compensation scenarios. + */ +@QuarkusTest +@QuarkusTestResource(SagaTestResource.class) +public class SagaBasicTest { + private static final String LOG_FILE = "target/quarkus.log"; + private static final Logger LOG = Logger.getLogger(SagaBasicTest.class.getName()); + + /** + * Test saga orchestration with LRA - accepts both success and compensation outcomes. + * Payment service has 15% random failure rate, so either scenario is valid. + */ + @Test + public void testSagaWithLRAAndRandomOutcomes() throws Exception { + // Trigger saga asynchronously (may timeout on payment failure, which is expected) + CompletableFuture.runAsync(() -> { + try { + RestAssured.given() + .queryParam("id", 1) + .post("/api/saga"); + } catch (Exception e) { + // Expected - request may timeout on payment failure + } + }); + + // Wait for saga to start and process fully + // In native mode, we need to wait longer for all messages to be logged + await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> { + String log = Files.readString(Paths.get(LOG_FILE)); + assertTrue(log.contains("Executing saga #1"), "Saga should start with LRA"); + + // Wait until we see evidence of completion (success or failure) + boolean completed = log.contains("done for order #1") + || log.contains("fails!") + || log.contains("cancelled"); + assertTrue(completed, "Saga should complete with either success or compensation"); + }); + + Awaitility.await() + .pollDelay(Duration.ofSeconds(1)) + .pollInterval(Duration.ofMillis(250)) + .atMost(Duration.ofMinutes(1)) + .untilAsserted(() -> { + String log = Files.readString(Paths.get(LOG_FILE)); + + // Verify LRA coordinator is used + assertTrue(log.contains("lra-coordinator"), "Should use LRA coordinator"); + + // Verify services participated + assertTrue(log.contains("Buying train") || log.contains("Buying flight"), + "Services should participate"); + + // Check outcome - either success or compensation is valid + boolean hasSuccess = log.contains("done for order #1"); + boolean hasFailure = log.contains("fails!"); + boolean hasCompensation = log.contains("cancelled"); + + if (hasFailure || hasCompensation) { + LOG.info("Saga #1: Compensation scenario tested (payment failed, saga rolled back)"); + } else if (hasSuccess) { + LOG.info("Saga #1: Success scenario tested (all payments completed)"); + } + + // Either outcome is valid because the trigger for saga compensation is triggered at random + assertTrue(hasSuccess || hasFailure, + "Saga should complete with either success or compensation"); + }); + } +} diff --git a/saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaTestResource.java b/saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaTestResource.java new file mode 100644 index 00000000..b2fa0000 --- /dev/null +++ b/saga/saga-integration-tests/src/test/java/org/apache/camel/example/saga/SagaTestResource.java @@ -0,0 +1,115 @@ +/* + * 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.saga; + +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; +import org.apache.commons.lang3.SystemUtils; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.Network; +import org.testcontainers.containers.wait.strategy.Wait; + +/** + * Testcontainers resource for Saga integration tests. + * Manages the lifecycle of LRA Coordinator and Artemis broker. + */ +public class SagaTestResource implements QuarkusTestResourceLifecycleManager { + + private static final String LRA_IMAGE = "quay.io/jbosstm/lra-coordinator:7.0.1.Final-3.8.3"; + private static final String ARTEMIS_IMAGE = "quay.io/arkmq-org/activemq-artemis-broker:artemis.2.51.0"; + private static final int LRA_PORT = 8080; + private static final int ARTEMIS_PORT = 61616; + + private GenericContainer lraContainer; + private GenericContainer artemisContainer; + private Network network; + + @Override + public Map start() { + network = Network.newNetwork(); + + // Start Artemis broker + artemisContainer = new GenericContainer<>(ARTEMIS_IMAGE) + .withNetwork(network) + .withNetworkAliases("artemis") + .withEnv("AMQ_USER", "admin") + .withEnv("AMQ_PASSWORD", "admin") + .withExposedPorts(ARTEMIS_PORT) + .waitingFor(Wait.forListeningPort() + .withStartupTimeout(Duration.ofSeconds(60))); + + artemisContainer.start(); + + // Start LRA Coordinator + lraContainer = new GenericContainer<>(LRA_IMAGE) + .withNetwork(network) + .withNetworkAliases("lra-coordinator") + .withEnv("QUARKUS_HTTP_PORT", String.valueOf(LRA_PORT)) + .withExposedPorts(LRA_PORT) + .withExtraHost("host.testcontainers.internal", "host-gateway") + .waitingFor(Wait.forHttp("/lra-coordinator") + .forPort(LRA_PORT) + .forStatusCode(200) + .withStartupTimeout(Duration.ofSeconds(90))); + + if (!SystemUtils.IS_OS_LINUX) { + lraContainer.withNetworkMode("bridge"); + } + + lraContainer.start(); + + Map config = new HashMap<>(); + + // Artemis configuration + String artemisUrl = String.format("tcp://%s:%d", + artemisContainer.getHost(), + artemisContainer.getMappedPort(ARTEMIS_PORT)); + config.put("quarkus.artemis.url", artemisUrl); + config.put("quarkus.artemis.username", "admin"); + config.put("quarkus.artemis.password", "admin"); + + // LRA configuration + String lraCoordinatorUrl = String.format("http://%s:%d", + lraContainer.getHost(), + lraContainer.getMappedPort(LRA_PORT)); + config.put("camel.lra.coordinator-url", lraCoordinatorUrl); + + // Set local participant URL - use host.testcontainers.internal for coordinator callbacks + config.put("camel.lra.local-participant-url", "http://host.testcontainers.internal:8084/api"); + + // Allow external connections + config.put("quarkus.http.host", "0.0.0.0"); + + return config; + } + + @Override + public void stop() { + if (artemisContainer != null) { + artemisContainer.stop(); + } + if (lraContainer != null) { + lraContainer.stop(); + } + if (network != null) { + network.close(); + } + } +} diff --git a/saga/saga-integration-tests/src/test/resources/application.yml b/saga/saga-integration-tests/src/test/resources/application.yml new file mode 100644 index 00000000..da44b5a2 --- /dev/null +++ b/saga/saga-integration-tests/src/test/resources/application.yml @@ -0,0 +1,48 @@ +# +# 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. +# + +# Test configuration +# External dependencies (Artemis, LRA) are managed by SagaTestResource + +quarkus: + http: + port: 8084 + log: + console: + format: "%d{HH:mm:ss} %-5p [%c{2.}] %s%e%n" + level: INFO + min-level: DEBUG + file: + enable: true + path: target/quarkus.log + +camel: + rest: + context-path: /api + component: + jms: + test-connection-on-startup: true + concurrent-consumers: 5 + lra: + enabled: true + # coordinator-url and local-participant-url are set by SagaTestResource + +example: + services: + train: saga-train-service + flight: saga-flight-service + payment: saga-payment-service diff --git a/saga/saga-payment-service/pom.xml b/saga/saga-payment-service/pom.xml index 83d7b951..0661d46d 100644 --- a/saga/saga-payment-service/pom.xml +++ b/saga/saga-payment-service/pom.xml @@ -31,4 +31,21 @@ Camel Quarkus :: Examples :: Saga :: Payment Service Payment Service + + + + io.smallrye + jandex-maven-plugin + + + make-index + + jandex + + + + + + + diff --git a/saga/saga-payment-service/src/main/java/org/apache/camel/example/saga/PaymentRoute.java b/saga/saga-payment-service/src/main/java/org/apache/camel/example/saga/PaymentRoute.java index 342a3d87..3b2fd20b 100644 --- a/saga/saga-payment-service/src/main/java/org/apache/camel/example/saga/PaymentRoute.java +++ b/saga/saga-payment-service/src/main/java/org/apache/camel/example/saga/PaymentRoute.java @@ -16,9 +16,11 @@ */ package org.apache.camel.example.saga; +import jakarta.enterprise.context.ApplicationScoped; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.model.SagaPropagation; +@ApplicationScoped public class PaymentRoute extends RouteBuilder { @Override @@ -33,7 +35,7 @@ public void configure() throws Exception { .log("Paying ${header.payFor} for order #${header.id}") .setBody(header("JMSCorrelationID")) .choice() - .when(x -> Math.random() >= 0.85) + .when(simple("${random(0,100)} >= 85")) .log("Payment ${header.payFor} for saga #${header.id} fails!") .throwException(new RuntimeException("Random failure during payment")) .endChoice() diff --git a/saga/saga-train-service/pom.xml b/saga/saga-train-service/pom.xml index 5af427e8..ef7da71b 100644 --- a/saga/saga-train-service/pom.xml +++ b/saga/saga-train-service/pom.xml @@ -31,4 +31,21 @@ Camel Quarkus :: Examples :: Saga :: Train Service Train Service + + + + io.smallrye + jandex-maven-plugin + + + make-index + + jandex + + + + + + + diff --git a/saga/saga-train-service/src/main/java/org/apache/camel/example/saga/TrainRoute.java b/saga/saga-train-service/src/main/java/org/apache/camel/example/saga/TrainRoute.java index bf5b05a6..ef339ef4 100644 --- a/saga/saga-train-service/src/main/java/org/apache/camel/example/saga/TrainRoute.java +++ b/saga/saga-train-service/src/main/java/org/apache/camel/example/saga/TrainRoute.java @@ -16,9 +16,11 @@ */ package org.apache.camel.example.saga; +import jakarta.enterprise.context.ApplicationScoped; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.model.SagaPropagation; +@ApplicationScoped public class TrainRoute extends RouteBuilder { @Override @@ -27,14 +29,16 @@ public void configure() throws Exception { .saga() .propagation(SagaPropagation.MANDATORY) .option("id", header("id")) - .compensation("direct:cancelPurchase") + .compensation("direct:cancelTrainPurchase") .log("Buying train #${header.id}") + // Request timeout prevents indefinite waits during payment service failures .to("jms:queue:{{example.services.payment}}?exchangePattern=InOut" + - "&replyTo={{example.services.payment}}.train.reply") + "&replyTo={{example.services.payment}}.train.reply" + + "&requestTimeout=30000") .log("Payment for train #${header.id} done with transaction ${body}") .end(); - from("direct:cancelPurchase") + from("direct:cancelTrainPurchase") .log("Train purchase #${header.id} has been cancelled due to payment failure"); } From 5b40edecb198c077f862d4cad3e0b17f72229419 Mon Sep 17 00:00:00 2001 From: James Netherton Date: Wed, 25 Mar 2026 11:15:14 +0000 Subject: [PATCH 04/12] Avoid needlessly building native apps for saga sub-modules on CI builds --- saga/pom.xml | 28 ++++++++++++++++++++++++++++ saga/saga-integration-tests/pom.xml | 25 +++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/saga/pom.xml b/saga/pom.xml index 75d70b56..5163944c 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -277,6 +277,34 @@ + + ci + + + env.CI + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + + + build + + true + + + + + + + + false + + + native diff --git a/saga/saga-integration-tests/pom.xml b/saga/saga-integration-tests/pom.xml index e74983de..9c39d1c1 100644 --- a/saga/saga-integration-tests/pom.xml +++ b/saga/saga-integration-tests/pom.xml @@ -105,6 +105,31 @@ + + ci + + + env.CI + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + + + build + + false + + + + + + + + native From dd9825961b26697008d0efde2a7b20cce42615f8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 08:16:02 +0100 Subject: [PATCH 05/12] Bump the maven group across 7 directories with 1 update Bumps the maven group with 1 update in the /jms-jpa directory: io.quarkiverse.artemis:quarkus-artemis-jms. Bumps the maven group with 1 update in the /message-bridge directory: io.quarkiverse.artemis:quarkus-artemis-jms. Bumps the maven group with 1 update in the /saga directory: io.quarkiverse.artemis:quarkus-artemis-jms. Bumps the maven group with 1 update in the /saga/saga-app directory: io.quarkiverse.artemis:quarkus-artemis-jms. Bumps the maven group with 1 update in the /saga/saga-flight-service directory: io.quarkiverse.artemis:quarkus-artemis-jms. Bumps the maven group with 1 update in the /saga/saga-payment-service directory: io.quarkiverse.artemis:quarkus-artemis-jms. Bumps the maven group with 1 update in the /saga/saga-train-service directory: io.quarkiverse.artemis:quarkus-artemis-jms. Updates `io.quarkiverse.artemis:quarkus-artemis-jms` from 3.13.0 to 3.14.1 Updates `io.quarkiverse.artemis:quarkus-artemis-jms` from 3.13.0 to 3.14.1 Updates `io.quarkiverse.artemis:quarkus-artemis-jms` from 3.13.0 to 3.14.1 Updates `io.quarkiverse.artemis:quarkus-artemis-jms` from 3.13.0 to 3.14.1 Updates `io.quarkiverse.artemis:quarkus-artemis-jms` from 3.13.0 to 3.14.1 Updates `io.quarkiverse.artemis:quarkus-artemis-jms` from 3.13.0 to 3.14.1 Updates `io.quarkiverse.artemis:quarkus-artemis-jms` from 3.13.0 to 3.14.1 --- updated-dependencies: - dependency-name: io.quarkiverse.artemis:quarkus-artemis-jms dependency-version: 3.14.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven - dependency-name: io.quarkiverse.artemis:quarkus-artemis-jms dependency-version: 3.14.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven - dependency-name: io.quarkiverse.artemis:quarkus-artemis-jms dependency-version: 3.14.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven - dependency-name: io.quarkiverse.artemis:quarkus-artemis-jms dependency-version: 3.14.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven - dependency-name: io.quarkiverse.artemis:quarkus-artemis-jms dependency-version: 3.14.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven - dependency-name: io.quarkiverse.artemis:quarkus-artemis-jms dependency-version: 3.14.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven - dependency-name: io.quarkiverse.artemis:quarkus-artemis-jms dependency-version: 3.14.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- jms-jpa/pom.xml | 2 +- message-bridge/pom.xml | 2 +- saga/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/jms-jpa/pom.xml b/jms-jpa/pom.xml index 9fcc2e84..9bd867c4 100644 --- a/jms-jpa/pom.xml +++ b/jms-jpa/pom.xml @@ -27,7 +27,7 @@ 3.34.1 3.35.0-SNAPSHOT - 3.13.0 + 3.14.1 io.quarkus quarkus-bom diff --git a/message-bridge/pom.xml b/message-bridge/pom.xml index 8733424d..9ad71195 100644 --- a/message-bridge/pom.xml +++ b/message-bridge/pom.xml @@ -48,7 +48,7 @@ 3.3.1 3.5.5 - 3.13.0 + 3.14.1 3.27.7 diff --git a/saga/pom.xml b/saga/pom.xml index 5163944c..fb52ed74 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -31,7 +31,7 @@ 3.34.1 3.35.0-SNAPSHOT - 3.13.0 + 3.14.1 io.quarkus quarkus-bom From 224024b3af681f941e89bdb726921f884d8b180c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 07:16:03 +0100 Subject: [PATCH 06/12] Bump the maven group across 6 directories with 1 update Bumps the maven group with 1 update in the /saga directory: [io.smallrye:jandex-maven-plugin](https://github.com/smallrye/jandex). Bumps the maven group with 1 update in the /saga/saga-app directory: [io.smallrye:jandex-maven-plugin](https://github.com/smallrye/jandex). Bumps the maven group with 1 update in the /saga/saga-flight-service directory: [io.smallrye:jandex-maven-plugin](https://github.com/smallrye/jandex). Bumps the maven group with 1 update in the /saga/saga-integration-tests directory: [io.smallrye:jandex-maven-plugin](https://github.com/smallrye/jandex). Bumps the maven group with 1 update in the /saga/saga-payment-service directory: [io.smallrye:jandex-maven-plugin](https://github.com/smallrye/jandex). Bumps the maven group with 1 update in the /saga/saga-train-service directory: [io.smallrye:jandex-maven-plugin](https://github.com/smallrye/jandex). Updates `io.smallrye:jandex-maven-plugin` from 3.0.1 to 3.5.3 - [Release notes](https://github.com/smallrye/jandex/releases) - [Changelog](https://github.com/smallrye/jandex/blob/main/RELEASE_PROCEDURE.md) - [Commits](https://github.com/smallrye/jandex/compare/3.0.1...3.5.3) Updates `io.smallrye:jandex-maven-plugin` from 3.0.1 to 3.5.3 - [Release notes](https://github.com/smallrye/jandex/releases) - [Changelog](https://github.com/smallrye/jandex/blob/main/RELEASE_PROCEDURE.md) - [Commits](https://github.com/smallrye/jandex/compare/3.0.1...3.5.3) Updates `io.smallrye:jandex-maven-plugin` from 3.0.1 to 3.5.3 - [Release notes](https://github.com/smallrye/jandex/releases) - [Changelog](https://github.com/smallrye/jandex/blob/main/RELEASE_PROCEDURE.md) - [Commits](https://github.com/smallrye/jandex/compare/3.0.1...3.5.3) Updates `io.smallrye:jandex-maven-plugin` from 3.0.1 to 3.5.3 - [Release notes](https://github.com/smallrye/jandex/releases) - [Changelog](https://github.com/smallrye/jandex/blob/main/RELEASE_PROCEDURE.md) - [Commits](https://github.com/smallrye/jandex/compare/3.0.1...3.5.3) Updates `io.smallrye:jandex-maven-plugin` from 3.0.1 to 3.5.3 - [Release notes](https://github.com/smallrye/jandex/releases) - [Changelog](https://github.com/smallrye/jandex/blob/main/RELEASE_PROCEDURE.md) - [Commits](https://github.com/smallrye/jandex/compare/3.0.1...3.5.3) Updates `io.smallrye:jandex-maven-plugin` from 3.0.1 to 3.5.3 - [Release notes](https://github.com/smallrye/jandex/releases) - [Changelog](https://github.com/smallrye/jandex/blob/main/RELEASE_PROCEDURE.md) - [Commits](https://github.com/smallrye/jandex/compare/3.0.1...3.5.3) --- updated-dependencies: - dependency-name: io.smallrye:jandex-maven-plugin dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven - dependency-name: io.smallrye:jandex-maven-plugin dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven - dependency-name: io.smallrye:jandex-maven-plugin dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven - dependency-name: io.smallrye:jandex-maven-plugin dependency-version: 3.5.3 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: maven - dependency-name: io.smallrye:jandex-maven-plugin dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven - dependency-name: io.smallrye:jandex-maven-plugin dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: maven ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- saga/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/saga/pom.xml b/saga/pom.xml index fb52ed74..e7d199b5 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -44,7 +44,7 @@ 2.29.0 1.13.0 - 3.0.1 + 3.5.3 5.0.0 3.15.0 3.5.0 From 27a422db66d3868b7ccd767b8664c35bb86d2c06 Mon Sep 17 00:00:00 2001 From: aldettinger Date: Thu, 2 Apr 2026 10:08:38 +0200 Subject: [PATCH 07/12] data-extract: upgrade ollama to version 0.19.0 --- data-extract-langchain4j/README.adoc | 2 +- ...=> api_chat-352961ad-e58d-4aa3-bd02-98f1da9b5b2d.json} | 8 ++++---- ...=> api_chat-911e18f4-d2c2-4697-b795-8f4a5bf0f9b7.json} | 8 ++++---- ...=> api_chat-ca667f9d-7d74-40e9-b55f-39ed24737b42.json} | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) rename data-extract-langchain4j/src/test/resources/mappings/{api_chat-18cda03a-bbe5-48d0-a35b-262b36c541a7.json => api_chat-352961ad-e58d-4aa3-bd02-98f1da9b5b2d.json} (87%) rename data-extract-langchain4j/src/test/resources/mappings/{api_chat-ae3edfa4-a510-4121-9eb2-6051c3072e69.json => api_chat-911e18f4-d2c2-4697-b795-8f4a5bf0f9b7.json} (81%) rename data-extract-langchain4j/src/test/resources/mappings/{api_chat-d0af43a7-81b5-49cd-8624-a4c222c5eb4b.json => api_chat-ca667f9d-7d74-40e9-b55f-39ed24737b42.json} (79%) diff --git a/data-extract-langchain4j/README.adoc b/data-extract-langchain4j/README.adoc index c882190a..ca4bef1c 100644 --- a/data-extract-langchain4j/README.adoc +++ b/data-extract-langchain4j/README.adoc @@ -24,7 +24,7 @@ Let's start a container to serve the LLM with Ollama, in a first shell type: [source,shell] ---- -docker run --rm -it -v cqex-data-extract-ollama:/root/.ollama -p 11434:11434 --name cqex-data-extract-ollama ollama/ollama:0.17.7 +docker run --rm -it -v cqex-data-extract-ollama:/root/.ollama -p 11434:11434 --name cqex-data-extract-ollama ollama/ollama:0.19.0 ---- After a moment, a log like below should be output: diff --git a/data-extract-langchain4j/src/test/resources/mappings/api_chat-18cda03a-bbe5-48d0-a35b-262b36c541a7.json b/data-extract-langchain4j/src/test/resources/mappings/api_chat-352961ad-e58d-4aa3-bd02-98f1da9b5b2d.json similarity index 87% rename from data-extract-langchain4j/src/test/resources/mappings/api_chat-18cda03a-bbe5-48d0-a35b-262b36c541a7.json rename to data-extract-langchain4j/src/test/resources/mappings/api_chat-352961ad-e58d-4aa3-bd02-98f1da9b5b2d.json index 2e325121..bed9253d 100644 --- a/data-extract-langchain4j/src/test/resources/mappings/api_chat-18cda03a-bbe5-48d0-a35b-262b36c541a7.json +++ b/data-extract-langchain4j/src/test/resources/mappings/api_chat-352961ad-e58d-4aa3-bd02-98f1da9b5b2d.json @@ -1,5 +1,5 @@ { - "id" : "18cda03a-bbe5-48d0-a35b-262b36c541a7", + "id" : "352961ad-e58d-4aa3-bd02-98f1da9b5b2d", "name" : "api_chat", "request" : { "url" : "/api/chat", @@ -12,13 +12,13 @@ }, "response" : { "status" : 200, - "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-01-20T14:46:58.833215508Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": true,\\n \\\"customerName\\\": \\\"Sarah London\\\",\\n \\\"customerBirthday\\\": {\\n \\\"year\\\": 1986,\\n \\\"month\\\": 7,\\n \\\"day\\\": 10\\n },\\n \\\"summary\\\": \\\"The customer, Sarah London, needed to declare an accident on her main vehicle and was informed that all expenses linked to the accident would be reimbursed.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":11185974927,\"load_duration\":1196566631,\"prompt_eval_count\":211,\"prompt_eval_duration\":4245459177,\"eval_count\":87,\"eval_duration\":4712126872}", + "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-04-02T07:49:56.668088405Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": true,\\n \\\"customerName\\\": \\\"Sarah London\\\",\\n \\\"customerBirthday\\\": {\\n \\\"year\\\": 1986,\\n \\\"month\\\": 7,\\n \\\"day\\\": 10\\n },\\n \\\"summary\\\": \\\"The customer, Sarah London, needed to declare an accident on her main vehicle and was informed that all expenses linked to the accident would be reimbursed.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":11115104439,\"load_duration\":1207380770,\"prompt_eval_count\":211,\"prompt_eval_duration\":4150700272,\"eval_count\":87,\"eval_duration\":4727844125}", "headers" : { - "Date" : "Tue, 20 Jan 2026 14:46:58 GMT", + "Date" : "Thu, 02 Apr 2026 07:49:56 GMT", "Content-Type" : "application/json; charset=utf-8" } }, - "uuid" : "18cda03a-bbe5-48d0-a35b-262b36c541a7", + "uuid" : "352961ad-e58d-4aa3-bd02-98f1da9b5b2d", "persistent" : true, "insertionIndex" : 6 } \ No newline at end of file diff --git a/data-extract-langchain4j/src/test/resources/mappings/api_chat-ae3edfa4-a510-4121-9eb2-6051c3072e69.json b/data-extract-langchain4j/src/test/resources/mappings/api_chat-911e18f4-d2c2-4697-b795-8f4a5bf0f9b7.json similarity index 81% rename from data-extract-langchain4j/src/test/resources/mappings/api_chat-ae3edfa4-a510-4121-9eb2-6051c3072e69.json rename to data-extract-langchain4j/src/test/resources/mappings/api_chat-911e18f4-d2c2-4697-b795-8f4a5bf0f9b7.json index 4a9422da..c81e97dd 100644 --- a/data-extract-langchain4j/src/test/resources/mappings/api_chat-ae3edfa4-a510-4121-9eb2-6051c3072e69.json +++ b/data-extract-langchain4j/src/test/resources/mappings/api_chat-911e18f4-d2c2-4697-b795-8f4a5bf0f9b7.json @@ -1,5 +1,5 @@ { - "id" : "ae3edfa4-a510-4121-9eb2-6051c3072e69", + "id" : "911e18f4-d2c2-4697-b795-8f4a5bf0f9b7", "name" : "api_chat", "request" : { "url" : "/api/chat", @@ -12,13 +12,13 @@ }, "response" : { "status" : 200, - "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-01-20T14:47:27.992920518Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": true,\\n \\\"customerName\\\": \\\"Kate Boss\\\",\\n \\\"customerBirthday\\\": {\\n \\\"year\\\": 1999,\\n \\\"month\\\": 8,\\n \\\"day\\\": 13\\n },\\n \\\"summary\\\": \\\"The customer, Kate Boss, had an accident and needed proof of insurance from the police station. The operator helped by verifying her identity and confirming that her contract was found in their records.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":14254749993,\"load_duration\":43034352,\"prompt_eval_count\":361,\"prompt_eval_duration\":7954943708,\"eval_count\":94,\"eval_duration\":5143927847}", + "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-04-02T07:50:24.668969617Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": true,\\n \\\"customerName\\\": \\\"Kate Boss\\\",\\n \\\"customerBirthday\\\": {\\n \\\"year\\\": 1999,\\n \\\"month\\\": 8,\\n \\\"day\\\": 13\\n },\\n \\\"summary\\\": \\\"Kate Boss contacted the operator to provide proof of insurance for an accident she was involved in at a police station. The operator helped locate her insurance contract and informed her that her husband could retrieve the proof directly from the office.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":14261328773,\"load_duration\":42998735,\"prompt_eval_count\":361,\"prompt_eval_duration\":7673926216,\"eval_count\":101,\"eval_duration\":5423317392}", "headers" : { - "Date" : "Tue, 20 Jan 2026 14:47:27 GMT", + "Date" : "Thu, 02 Apr 2026 07:50:24 GMT", "Content-Type" : "application/json; charset=utf-8" } }, - "uuid" : "ae3edfa4-a510-4121-9eb2-6051c3072e69", + "uuid" : "911e18f4-d2c2-4697-b795-8f4a5bf0f9b7", "persistent" : true, "insertionIndex" : 4 } \ No newline at end of file diff --git a/data-extract-langchain4j/src/test/resources/mappings/api_chat-d0af43a7-81b5-49cd-8624-a4c222c5eb4b.json b/data-extract-langchain4j/src/test/resources/mappings/api_chat-ca667f9d-7d74-40e9-b55f-39ed24737b42.json similarity index 79% rename from data-extract-langchain4j/src/test/resources/mappings/api_chat-d0af43a7-81b5-49cd-8624-a4c222c5eb4b.json rename to data-extract-langchain4j/src/test/resources/mappings/api_chat-ca667f9d-7d74-40e9-b55f-39ed24737b42.json index fdb405c8..10d90a27 100644 --- a/data-extract-langchain4j/src/test/resources/mappings/api_chat-d0af43a7-81b5-49cd-8624-a4c222c5eb4b.json +++ b/data-extract-langchain4j/src/test/resources/mappings/api_chat-ca667f9d-7d74-40e9-b55f-39ed24737b42.json @@ -1,5 +1,5 @@ { - "id" : "d0af43a7-81b5-49cd-8624-a4c222c5eb4b", + "id" : "ca667f9d-7d74-40e9-b55f-39ed24737b42", "name" : "api_chat", "request" : { "url" : "/api/chat", @@ -12,13 +12,13 @@ }, "response" : { "status" : 200, - "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-01-20T14:47:13.730091697Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": false,\\n \\\"customerName\\\": \\\"John Doe\\\",\\n \\\"customerBirthday\\\": {\\n \\\"year\\\": 2001,\\n \\\"month\\\": 11,\\n \\\"day\\\": 1\\n },\\n \\\"summary\\\": \\\"The customer, John Doe, is dissatisfied as his insurance company did not notify him about the cancellation of full reimbursement option after one year. He requested for a notification and was informed that the best they could do was to inform their manager.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":14851122117,\"load_duration\":56442194,\"prompt_eval_count\":363,\"prompt_eval_duration\":7657362565,\"eval_count\":106,\"eval_duration\":5876308381}", + "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-04-02T07:50:10.398278523Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": false,\\n \\\"customerName\\\": \\\"John Doe\\\",\\n \\\"customerBirthday\\\": {\\\"year\\\": 2001, \\\"month\\\": 11, \\\"day\\\": 1},\\n \\\"summary\\\": \\\"John Doe, the customer, is dissatisfied with the insurance company as the full reimbursement option was cancelled automatically by their system and he was not notified. He requested to inform the manager about this issue.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":13689200730,\"load_duration\":53779449,\"prompt_eval_count\":363,\"prompt_eval_duration\":7556841000,\"eval_count\":93,\"eval_duration\":5018724852}", "headers" : { - "Date" : "Tue, 20 Jan 2026 14:47:13 GMT", + "Date" : "Thu, 02 Apr 2026 07:50:10 GMT", "Content-Type" : "application/json; charset=utf-8" } }, - "uuid" : "d0af43a7-81b5-49cd-8624-a4c222c5eb4b", + "uuid" : "ca667f9d-7d74-40e9-b55f-39ed24737b42", "persistent" : true, "insertionIndex" : 5 } \ No newline at end of file From 4db337f967b1f495efda88a25b6d4c847af8d187 Mon Sep 17 00:00:00 2001 From: aldettinger Date: Thu, 2 Apr 2026 10:19:07 +0200 Subject: [PATCH 08/12] data-extract: upgrade to langchain 1.12.2 --- data-extract-langchain4j/pom.xml | 2 +- ...=> api_chat-173e3a1f-b194-46f7-a510-c1d497f98986.json} | 8 ++++---- ...=> api_chat-4400676b-1fdd-4664-bfbd-80be34aae24b.json} | 8 ++++---- ...=> api_chat-f1bd1a9f-c9c9-465d-9328-84d80ca0d4d1.json} | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) rename data-extract-langchain4j/src/test/resources/mappings/{api_chat-352961ad-e58d-4aa3-bd02-98f1da9b5b2d.json => api_chat-173e3a1f-b194-46f7-a510-c1d497f98986.json} (87%) rename data-extract-langchain4j/src/test/resources/mappings/{api_chat-ca667f9d-7d74-40e9-b55f-39ed24737b42.json => api_chat-4400676b-1fdd-4664-bfbd-80be34aae24b.json} (89%) rename data-extract-langchain4j/src/test/resources/mappings/{api_chat-911e18f4-d2c2-4697-b795-8f4a5bf0f9b7.json => api_chat-f1bd1a9f-c9c9-465d-9328-84d80ca0d4d1.json} (89%) diff --git a/data-extract-langchain4j/pom.xml b/data-extract-langchain4j/pom.xml index 7eb36d22..fa20b595 100644 --- a/data-extract-langchain4j/pom.xml +++ b/data-extract-langchain4j/pom.xml @@ -52,7 +52,7 @@ 3.3.1 3.5.5 - 1.11.0 + 1.12.2 3.13.2 diff --git a/data-extract-langchain4j/src/test/resources/mappings/api_chat-352961ad-e58d-4aa3-bd02-98f1da9b5b2d.json b/data-extract-langchain4j/src/test/resources/mappings/api_chat-173e3a1f-b194-46f7-a510-c1d497f98986.json similarity index 87% rename from data-extract-langchain4j/src/test/resources/mappings/api_chat-352961ad-e58d-4aa3-bd02-98f1da9b5b2d.json rename to data-extract-langchain4j/src/test/resources/mappings/api_chat-173e3a1f-b194-46f7-a510-c1d497f98986.json index bed9253d..27596a5b 100644 --- a/data-extract-langchain4j/src/test/resources/mappings/api_chat-352961ad-e58d-4aa3-bd02-98f1da9b5b2d.json +++ b/data-extract-langchain4j/src/test/resources/mappings/api_chat-173e3a1f-b194-46f7-a510-c1d497f98986.json @@ -1,5 +1,5 @@ { - "id" : "352961ad-e58d-4aa3-bd02-98f1da9b5b2d", + "id" : "173e3a1f-b194-46f7-a510-c1d497f98986", "name" : "api_chat", "request" : { "url" : "/api/chat", @@ -12,13 +12,13 @@ }, "response" : { "status" : 200, - "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-04-02T07:49:56.668088405Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": true,\\n \\\"customerName\\\": \\\"Sarah London\\\",\\n \\\"customerBirthday\\\": {\\n \\\"year\\\": 1986,\\n \\\"month\\\": 7,\\n \\\"day\\\": 10\\n },\\n \\\"summary\\\": \\\"The customer, Sarah London, needed to declare an accident on her main vehicle and was informed that all expenses linked to the accident would be reimbursed.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":11115104439,\"load_duration\":1207380770,\"prompt_eval_count\":211,\"prompt_eval_duration\":4150700272,\"eval_count\":87,\"eval_duration\":4727844125}", + "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-04-02T08:15:17.527674637Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": true,\\n \\\"customerName\\\": \\\"Sarah London\\\",\\n \\\"customerBirthday\\\": {\\n \\\"year\\\": 1986,\\n \\\"month\\\": 7,\\n \\\"day\\\": 10\\n },\\n \\\"summary\\\": \\\"The customer, Sarah London, needed to declare an accident on her main vehicle and was informed that all expenses linked to the accident would be reimbursed.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":11199370161,\"load_duration\":1209262913,\"prompt_eval_count\":211,\"prompt_eval_duration\":4245491703,\"eval_count\":87,\"eval_duration\":4676863156}", "headers" : { - "Date" : "Thu, 02 Apr 2026 07:49:56 GMT", + "Date" : "Thu, 02 Apr 2026 08:15:17 GMT", "Content-Type" : "application/json; charset=utf-8" } }, - "uuid" : "352961ad-e58d-4aa3-bd02-98f1da9b5b2d", + "uuid" : "173e3a1f-b194-46f7-a510-c1d497f98986", "persistent" : true, "insertionIndex" : 6 } \ No newline at end of file diff --git a/data-extract-langchain4j/src/test/resources/mappings/api_chat-ca667f9d-7d74-40e9-b55f-39ed24737b42.json b/data-extract-langchain4j/src/test/resources/mappings/api_chat-4400676b-1fdd-4664-bfbd-80be34aae24b.json similarity index 89% rename from data-extract-langchain4j/src/test/resources/mappings/api_chat-ca667f9d-7d74-40e9-b55f-39ed24737b42.json rename to data-extract-langchain4j/src/test/resources/mappings/api_chat-4400676b-1fdd-4664-bfbd-80be34aae24b.json index 10d90a27..705ff402 100644 --- a/data-extract-langchain4j/src/test/resources/mappings/api_chat-ca667f9d-7d74-40e9-b55f-39ed24737b42.json +++ b/data-extract-langchain4j/src/test/resources/mappings/api_chat-4400676b-1fdd-4664-bfbd-80be34aae24b.json @@ -1,5 +1,5 @@ { - "id" : "ca667f9d-7d74-40e9-b55f-39ed24737b42", + "id" : "4400676b-1fdd-4664-bfbd-80be34aae24b", "name" : "api_chat", "request" : { "url" : "/api/chat", @@ -12,13 +12,13 @@ }, "response" : { "status" : 200, - "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-04-02T07:50:10.398278523Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": false,\\n \\\"customerName\\\": \\\"John Doe\\\",\\n \\\"customerBirthday\\\": {\\\"year\\\": 2001, \\\"month\\\": 11, \\\"day\\\": 1},\\n \\\"summary\\\": \\\"John Doe, the customer, is dissatisfied with the insurance company as the full reimbursement option was cancelled automatically by their system and he was not notified. He requested to inform the manager about this issue.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":13689200730,\"load_duration\":53779449,\"prompt_eval_count\":363,\"prompt_eval_duration\":7556841000,\"eval_count\":93,\"eval_duration\":5018724852}", + "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-04-02T08:15:31.297936294Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": false,\\n \\\"customerName\\\": \\\"John Doe\\\",\\n \\\"customerBirthday\\\": {\\\"year\\\": 2001, \\\"month\\\": 11, \\\"day\\\": 1},\\n \\\"summary\\\": \\\"John Doe, the customer, is dissatisfied with the insurance company as the full reimbursement option was cancelled automatically by their system and he was not notified. He requested to inform the manager about this issue.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":13730120429,\"load_duration\":46627949,\"prompt_eval_count\":363,\"prompt_eval_duration\":7507657361,\"eval_count\":93,\"eval_duration\":5022486287}", "headers" : { - "Date" : "Thu, 02 Apr 2026 07:50:10 GMT", + "Date" : "Thu, 02 Apr 2026 08:15:31 GMT", "Content-Type" : "application/json; charset=utf-8" } }, - "uuid" : "ca667f9d-7d74-40e9-b55f-39ed24737b42", + "uuid" : "4400676b-1fdd-4664-bfbd-80be34aae24b", "persistent" : true, "insertionIndex" : 5 } \ No newline at end of file diff --git a/data-extract-langchain4j/src/test/resources/mappings/api_chat-911e18f4-d2c2-4697-b795-8f4a5bf0f9b7.json b/data-extract-langchain4j/src/test/resources/mappings/api_chat-f1bd1a9f-c9c9-465d-9328-84d80ca0d4d1.json similarity index 89% rename from data-extract-langchain4j/src/test/resources/mappings/api_chat-911e18f4-d2c2-4697-b795-8f4a5bf0f9b7.json rename to data-extract-langchain4j/src/test/resources/mappings/api_chat-f1bd1a9f-c9c9-465d-9328-84d80ca0d4d1.json index c81e97dd..a2906d27 100644 --- a/data-extract-langchain4j/src/test/resources/mappings/api_chat-911e18f4-d2c2-4697-b795-8f4a5bf0f9b7.json +++ b/data-extract-langchain4j/src/test/resources/mappings/api_chat-f1bd1a9f-c9c9-465d-9328-84d80ca0d4d1.json @@ -1,5 +1,5 @@ { - "id" : "911e18f4-d2c2-4697-b795-8f4a5bf0f9b7", + "id" : "f1bd1a9f-c9c9-465d-9328-84d80ca0d4d1", "name" : "api_chat", "request" : { "url" : "/api/chat", @@ -12,13 +12,13 @@ }, "response" : { "status" : 200, - "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-04-02T07:50:24.668969617Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": true,\\n \\\"customerName\\\": \\\"Kate Boss\\\",\\n \\\"customerBirthday\\\": {\\n \\\"year\\\": 1999,\\n \\\"month\\\": 8,\\n \\\"day\\\": 13\\n },\\n \\\"summary\\\": \\\"Kate Boss contacted the operator to provide proof of insurance for an accident she was involved in at a police station. The operator helped locate her insurance contract and informed her that her husband could retrieve the proof directly from the office.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":14261328773,\"load_duration\":42998735,\"prompt_eval_count\":361,\"prompt_eval_duration\":7673926216,\"eval_count\":101,\"eval_duration\":5423317392}", + "body" : "{\"model\":\"granite4:3b-h\",\"created_at\":\"2026-04-02T08:15:45.751056354Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"customerSatisfied\\\": true,\\n \\\"customerName\\\": \\\"Kate Boss\\\",\\n \\\"customerBirthday\\\": {\\n \\\"year\\\": 1999,\\n \\\"month\\\": 8,\\n \\\"day\\\": 13\\n },\\n \\\"summary\\\": \\\"Kate Boss contacted the operator to provide proof of insurance for an accident she was involved in at a police station. The operator helped locate her insurance contract and informed her that her husband could retrieve the proof directly from the office.\\\"\\n}\"},\"done\":true,\"done_reason\":\"stop\",\"total_duration\":14446012640,\"load_duration\":42576483,\"prompt_eval_count\":361,\"prompt_eval_duration\":7632214511,\"eval_count\":101,\"eval_duration\":5491927793}", "headers" : { - "Date" : "Thu, 02 Apr 2026 07:50:24 GMT", + "Date" : "Thu, 02 Apr 2026 08:15:45 GMT", "Content-Type" : "application/json; charset=utf-8" } }, - "uuid" : "911e18f4-d2c2-4697-b795-8f4a5bf0f9b7", + "uuid" : "f1bd1a9f-c9c9-465d-9328-84d80ca0d4d1", "persistent" : true, "insertionIndex" : 4 } \ No newline at end of file From 790805e2e80ed130d491da34a00343ad8e2a0745 Mon Sep 17 00:00:00 2001 From: James Netherton Date: Thu, 9 Apr 2026 13:38:13 +0100 Subject: [PATCH 09/12] Add a README link to create new example project guide --- README.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/README.adoc b/README.adoc index baa1b320..719ca06b 100644 --- a/README.adoc +++ b/README.adoc @@ -2,6 +2,7 @@ Useful links: +* https://camel.apache.org/camel-quarkus/latest/contributor-guide/create-new-example.html[How to create a new Camel Quarkus example project] * https://camel.apache.org/camel-quarkus/latest/user-guide/examples.html[List of Camel Quarkus examples] with short descriptions * https://camel.apache.org/camel-quarkus/latest/user-guide/index.html[Camel Quarkus User guide] * https://camel.apache.org/camel-quarkus/latest/contributor-guide/index.html[Camel Quarkus Contributor guide] From 81120c09af7b8aa6432d2fa4a878c7ec26ae2ad3 Mon Sep 17 00:00:00 2001 From: JiriOndrusek Date: Fri, 10 Apr 2026 19:05:55 +0200 Subject: [PATCH 10/12] Add HTTP PQC Example for Java 17 --- docs/modules/ROOT/attachments/examples.json | 5 + http-pqc-j17/PQC-EXPLANATION.adoc | 476 ++++++++++++++++++ http-pqc-j17/README.adoc | 189 +++++++ http-pqc-j17/eclipse-formatter-config.xml | 276 ++++++++++ http-pqc-j17/pom.xml | 303 +++++++++++ .../java/org/acme/http/pqc/PqcCamelRoute.java | 42 ++ .../HybridCertificateGenerator.java | 247 +++++++++ .../certificates/SecurityConfiguration.java | 54 ++ .../util/CertificateValidationException.java | 33 ++ .../certificates/util/CertificatesUtil.java | 200 ++++++++ .../org/acme/http/pqc/crypto/ChimeraOids.java | 167 ++++++ .../HybridPqcTrustManagerCustomizer.java | 58 +++ .../HybridPqcX509TrustManager.java | 77 +++ .../src/main/resources/application.properties | 49 ++ .../java/org/acme/http/pqc/HttpPqcIT.java | 23 + .../java/org/acme/http/pqc/HttpPqcTest.java | 115 +++++ 16 files changed, 2314 insertions(+) create mode 100644 http-pqc-j17/PQC-EXPLANATION.adoc create mode 100644 http-pqc-j17/README.adoc create mode 100644 http-pqc-j17/eclipse-formatter-config.xml create mode 100644 http-pqc-j17/pom.xml create mode 100644 http-pqc-j17/src/main/java/org/acme/http/pqc/PqcCamelRoute.java create mode 100644 http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/HybridCertificateGenerator.java create mode 100644 http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/SecurityConfiguration.java create mode 100644 http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/util/CertificateValidationException.java create mode 100644 http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/util/CertificatesUtil.java create mode 100644 http-pqc-j17/src/main/java/org/acme/http/pqc/crypto/ChimeraOids.java create mode 100644 http-pqc-j17/src/main/java/org/acme/http/pqc/trustmanager/HybridPqcTrustManagerCustomizer.java create mode 100644 http-pqc-j17/src/main/java/org/acme/http/pqc/trustmanager/HybridPqcX509TrustManager.java create mode 100644 http-pqc-j17/src/main/resources/application.properties create mode 100644 http-pqc-j17/src/test/java/org/acme/http/pqc/HttpPqcIT.java create mode 100644 http-pqc-j17/src/test/java/org/acme/http/pqc/HttpPqcTest.java diff --git a/docs/modules/ROOT/attachments/examples.json b/docs/modules/ROOT/attachments/examples.json index c755be4c..c69639f1 100644 --- a/docs/modules/ROOT/attachments/examples.json +++ b/docs/modules/ROOT/attachments/examples.json @@ -44,6 +44,11 @@ "description": "Shows how to consume CSV files, marshal \u0026 unmarshal the data and send it onwards via FTP", "link": "https://github.com/apache/camel-quarkus-examples/tree/main/file-bindy-ftp" }, + { + "title": "HTTP with Post-Quantum Cryptography (PQC) (Java 17)", + "description": "Shows how to implement quantum-resistant authentication using hybrid certificates that combine RSA with post-quantum ML-DSA-65 signatures on Java 17 using application-level validation", + "link": "https://github.com/apache/camel-quarkus-examples/tree/main/http-pqc-j17" + }, { "title": "HTTP with vanilla JAX-RS or with Camel `platform-http` component", "description": "Shows how to create HTTP endpoints using either the RESTEasy", diff --git a/http-pqc-j17/PQC-EXPLANATION.adoc b/http-pqc-j17/PQC-EXPLANATION.adoc new file mode 100644 index 00000000..f29ef7e1 --- /dev/null +++ b/http-pqc-j17/PQC-EXPLANATION.adoc @@ -0,0 +1,476 @@ += Post-Quantum Cryptography: Visual Explanation + +== The Quantum Computer Threat + +=== Traditional Encryption (RSA/ECC) + +[source,text] +---- +┌─────────────────────────────────────────────────────────────┐ +│ Current World (Safe) Future with Quantum Computer │ +│ │ +│ RSA-2048 encryption Quantum Computer │ +│ ┌──────────────┐ ┌──────────────┐ │ +│ │ Lock (RSA) │ ──────> │ Shor's Algo │ │ +│ │ Takes 1000s │ │ Breaks in │ │ +│ │ of years to │ │ MINUTES! ⚠️ │ │ +│ │ break │ └──────────────┘ │ +│ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +---- + +=== Post-Quantum Cryptography (PQC) + +[source,text] +---- +┌─────────────────────────────────────────────────────────────┐ +│ PQC Solution Even with Quantum Computer │ +│ │ +│ ML-DSA (FIPS 204) Quantum Computer │ +│ ┌──────────────┐ ┌──────────────┐ │ +│ │ Lattice Lock │ ──────> │ Shor's Algo │ │ +│ │ Based on │ │ Doesn't work!│ │ +│ │ hard math │ │ Still takes │ │ +│ │ problems │ │ 1000s years ✓│ │ +│ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +---- + +''' + +== Three Approaches in Our Implementation + +=== 1. CURRENT HTTPS (What Most Systems Use Today) + +[source,text] +---- +┌──────────────┐ ┌──────────────┐ +│ Browser │ │ Server │ +│ (Client) │ │ │ +└──────┬───────┘ └──────┬───────┘ + │ │ + │ 1. "Hello, I want HTTPS connection" │ + ├──────────────────────────────────────────────>│ + │ │ + │ 2. "Here's my certificate" │ + │ ┌─────────────────────────┐ │ + │ │ Certificate: │ │ + │ │ - Public Key: RSA-2048 │ │ + │ │ - Signature: SHA256+RSA │ │ + │<────│ - Subject: localhost │───────────────│ + │ │ ⚠️ QUANTUM VULNERABLE │ │ + │ └─────────────────────────┘ │ + │ │ + │ 3. Verify RSA signature ✓ │ + │ (Works today, broken by quantum later) │ + │ │ + │ 4. Encrypted communication using RSA │ + │<─────────────────────────────────────────────>│ + │ ⚠️ Future quantum computer can break this │ + │ │ +---- + +**Problem:** When quantum computers arrive, they can: + +* Break the RSA encryption +* Forge RSA signatures +* Read all your "encrypted" data + +''' + +=== 2. ALTERNATIVE APPROACH: Application-Layer PQC (NOT this example) + +This is a **workaround approach** when you can't modify TLS behavior - demonstrate PQC **inside** the application: + +[source,text] +---- +┌──────────────┐ ┌──────────────┐ +│ Browser │ │ Server │ +│ (curl) │ │ (Quarkus) │ +└──────┬───────┘ └──────┬───────┘ + │ │ + │ LAYER 1: HTTPS (Still uses RSA) │ + │ ════════════════════════════════════════ │ + │ 1. TLS Handshake with RSA certificate │ + ├──────────────────────────────────────────────>│ + │ ┌─────────────────────────┐ │ + │ │ TLS Certificate: │ │ + │ │ - RSA-2048 (classical) │ │ + │<────│ ⚠️ Quantum vulnerable │───────────────│ + │ └─────────────────────────┘ │ + │ │ + │ 2. Encrypted tunnel established │ + │<═════════════════════════════════════════════>│ + │ ⚠️ TLS handshake is quantum-vulnerable │ + │ │ + │ LAYER 2: PQC at Application Level │ + │ ════════════════════════════════════════ │ + │ 3. GET /pqc/sign │ + ├──────────────────────────────────────────────>│ + │ │ + │ ┌──────────┴───────────┐ + │ │ PqcSignatureService │ + │ │ - Generate ML-DSA-65 │ + │ │ keypair │ + │ │ - Sign message │ + │ │ - Verify signature │ + │ │ ✓ Algorithm is safe │ + │ └──────────┬───────────┘ + │ 4. Returns PQC signature demo │ + │<──────────────────────────────────────────────│ +---- + +**Why we DON'T use this approach:** + +* ⚠️ **TLS handshake is still quantum-vulnerable** - attacker can intercept the initial connection +* ℹ️ **Only demonstrates PQC algorithms** - doesn't actually protect the authentication +* ✅ **Good for learning/demos** - shows how PQC algorithms work +* ❌ **Not good for real security** - TLS layer remains vulnerable + +**This example uses Approach #3 instead** ⬇️ + +''' + +=== 3. OUR IMPLEMENTATION: Chimera Hybrid Certificates at TLS Layer + +**This example implements this approach!** It validates hybrid PQC certificates during the TLS handshake: + +[source,text] +---- +┌──────────────┐ ┌──────────────┐ +│ Browser │ │ Server │ +│ (Client) │ │ │ +└──────┬───────┘ └──────┬───────┘ + │ │ + │ 1. "Hello, I want HTTPS connection" │ + ├──────────────────────────────────────────────>│ + │ │ + │ 2. "Here's my HYBRID certificate" │ + │ ┌─────────────────────────────────────┐ │ + │ │ Chimera Hybrid Certificate: │ │ + │ │ ──────────────────────────────── │ │ + │ │ PRIMARY (Classical): │ │ + │ │ - Public Key: RSA-2048 │ │ + │ │ - Signature: SHA256withRSA │ │ + │ │ ✓ Works with old systems │ │ + │ │ │ │ + │ │ ALTERNATIVE (PQC) - Extensions: │ │ + │<────│ - altPublicKey: ML-DSA-65 │───│ + │ │ - altSignature: ML-DSA-65 │ │ + │ │ ✓ QUANTUM SAFE │ │ + │ │ │ │ + │ │ BOTH signatures present! │ │ + │ └─────────────────────────────────────┘ │ + │ │ + │ 3. Verify RSA signature ✓ │ + │ (Works with old browsers) │ + │ │ + │ 4. Verify ML-DSA-65 signature ✓ │ + │ (PQC-aware clients check this too) │ + │ │ + │ 5. Encrypted communication │ + │<─────────────────────────────────────────────>│ + │ ✓ Protected by BOTH classical & PQC │ + │ │ +---- + +==== How Chimera Works + +[source,text] +---- +┌─────────────────────────────────────────────────────────────┐ +│ CHIMERA HYBRID CERTIFICATE │ +│ │ +│ ┌────────────────────┐ ┌────────────────────┐ │ +│ │ PRIMARY LAYER │ │ ALTERNATIVE LAYER │ │ +│ │ (Classical RSA) │ │ (PQC ML-DSA) │ │ +│ └─────────┬──────────┘ └─────────┬──────────┘ │ +│ │ │ │ +│ │ Subject: CN=localhost │ │ +│ │ Issuer: CN=PQC Hybrid CA │ │ +│ │ Serial: 1234567890 │ │ +│ │ │ │ +│ ┌─────────▼──────────┐ ┌─────────▼──────────┐ │ +│ │ RSA-2048 │ │ Extension OID │ │ +│ │ Public Key │ │ 2.5.29.72: │ │ +│ │ (Standard field) │ │ ML-DSA-65 Public │ │ +│ └────────────────────┘ │ Key │ │ +│ └────────────────────┘ │ +│ ┌────────────────────┐ ┌────────────────────┐ │ +│ │ SHA256withRSA │ │ Extension OID │ │ +│ │ Signature │ │ 2.5.29.74: │ │ +│ │ [RSA signature │ │ ML-DSA-65 │ │ +│ │ bytes] │ │ Signature bytes │ │ +│ └────────────────────┘ └────────────────────┘ │ +│ │ +│ Verification: BOTH signatures must be valid! │ +│ - Old systems: Check RSA only ✓ │ +│ - PQC systems: Check RSA ✓ AND ML-DSA ✓ │ +└─────────────────────────────────────────────────────────────┘ +---- + +''' + +== Certificate Comparison + +=== Traditional Certificate (RSA only) + +[source,text] +---- +┌─────────────────────────────────┐ +│ X.509 Certificate │ +├─────────────────────────────────┤ +│ Version: 3 │ +│ Serial: 0x123456 │ +│ Issuer: CN=My CA │ +│ Subject: CN=localhost │ +│ ┌─────────────────────────────┐ │ +│ │ Public Key: │ │ +│ │ Algorithm: RSA │ │ +│ │ Size: 2048 bits │ │ +│ │ Key: [MIIBIjANBg...] │ │ +│ └─────────────────────────────┘ │ +│ ┌─────────────────────────────┐ │ +│ │ Signature: │ │ +│ │ Algorithm: SHA256withRSA │ │ +│ │ Value: [3045022100...] │ │ +│ └─────────────────────────────┘ │ +│ │ +│ ⚠️ QUANTUM VULNERABLE │ +└─────────────────────────────────┘ +---- + +=== Chimera Hybrid Certificate (RSA + ML-DSA-65) + +[source,text] +---- +┌─────────────────────────────────────────────────────┐ +│ X.509 Certificate (Chimera Format) │ +├─────────────────────────────────────────────────────┤ +│ Version: 3 │ +│ Serial: 0x123456 │ +│ Issuer: CN=PQC Hybrid CA │ +│ Subject: CN=localhost │ +│ ┌─────────────────────────────┐ │ +│ │ Public Key (PRIMARY): │ │ +│ │ Algorithm: RSA │ ✓ Classical │ +│ │ Size: 2048 bits │ │ +│ │ Key: [MIIBIjANBg...] │ │ +│ └─────────────────────────────┘ │ +│ ┌─────────────────────────────┐ │ +│ │ Extensions: │ │ +│ │ ┌─────────────────────────┐ │ │ +│ │ │ OID 2.5.29.72: │ │ │ +│ │ │ altSubjectPublicKeyInfo │ │ │ +│ │ │ Algorithm: ML-DSA-65 │ │ ✓ Post-Quantum │ +│ │ │ Key: [3082071E...] │ │ │ +│ │ │ Size: 1976 bytes │ │ │ +│ │ └─────────────────────────┘ │ │ +│ │ ┌─────────────────────────┐ │ │ +│ │ │ OID 2.5.29.73: │ │ │ +│ │ │ altSignatureAlgorithm │ │ │ +│ │ │ Algorithm: ML-DSA-65 │ │ │ +│ │ └─────────────────────────┘ │ │ +│ │ ┌─────────────────────────┐ │ │ +│ │ │ OID 2.5.29.74: │ │ │ +│ │ │ altSignatureValue │ │ │ +│ │ │ Signature: [D1L1...] │ │ ✓ Post-Quantum │ +│ │ │ Size: 3309 bytes │ │ │ +│ │ └─────────────────────────┘ │ │ +│ └─────────────────────────────┘ │ +│ ┌─────────────────────────────┐ │ +│ │ Signature (PRIMARY): │ │ +│ │ Algorithm: SHA256withRSA │ ✓ Classical │ +│ │ Value: [3045022100...] │ │ +│ └─────────────────────────────┘ │ +│ │ +│ ✓ HYBRID: Protected against classical AND quantum! │ +└─────────────────────────────────────────────────────┘ +---- + +''' + +== Our Implementation: TLS-Layer Hybrid Certificate Validation + +[source,text] +---- +┌────────────────────────────────────────────────────────────────┐ +│ HTTP PQC Example - TLS-Layer Validation │ +└────────────────────────────────────────────────────────────────┘ + +HYBRID CERTIFICATE VALIDATION (Chimera at TLS Layer) +──────────────────────────────────────────────────── +Endpoint: https://localhost:8443/pqc/secure + +┌─────────────┐ ┌─────────────────────────┐ +│ Client │─────>│ TLS Handshake │ +│ Request │ │ (with client cert) │ +└─────────────┘ └─────────┬───────────────┘ + │ + ┌─────────▼───────────┐ + │ Client sends hybrid │ + │ PQC certificate │ + └─────────┬───────────┘ + │ + ┌──────────────┴──────────────┐ + │ HybridPqcX509TrustManager │ + └──────────────┬──────────────┘ + │ + ┌─────────▼─────────┐ + │ Extract signatures│ + │ from certificate │ + └─────────┬─────────┘ + │ + ┌──────────────┴──────────────┐ + ▼ ▼ + ┌───────────────┐ ┌────────────────┐ + │ Validate RSA │ │ Validate │ + │ Signature ✓ │ │ ML-DSA-65 ✓ │ + └───────┬───────┘ └────────┬───────┘ + │ │ + └──────────────┬──────────────┘ + │ + ┌─────────▼─────────┐ + │ BOTH valid? │ + │ YES → Allow │ + │ NO → Reject TLS │ + └─────────┬─────────┘ + │ + ▼ + ┌──────────────────┐ + │ /pqc/secure │ + │ route executes │ + └──────┬───────────┘ + │ + ▼ + Result: ✓ Validated! + "✓ Hybrid PQC certificate + validated at TLS layer!" + + (Dual protection - works + now + quantum-safe!) +---- + +''' + +== Why We Use Approach #3 (Chimera) Instead of Approach #2 + +[cols="1,2,2",options="header"] +|=== +|Aspect +|Approach #2: App-Layer PQC +|Approach #3: Chimera at TLS Layer ✅ + +|**TLS Handshake** +|⚠️ Quantum-vulnerable (RSA only) +|✅ Validates both RSA + ML-DSA-65 + +|**Authentication** +|❌ No PQC authentication +|✅ Rejects invalid certificates + +|**Protection Level** +|⚠️ Demo only, TLS is vulnerable +|✅ Real security at TLS layer + +|**When to use** +|Learning, experimenting +|Production-ready hybrid solution + +|**Code complexity** +|Simple (app endpoints) +|Moderate (custom TrustManager) +|=== + +**Key Difference:** + +* **Approach #2** is like having a regular lock on your door (RSA TLS) but demonstrating fancy new locks inside your house (PQC demos) +* **Approach #3** is like installing a dual-lock system ON YOUR DOOR (Chimera certificates validated at TLS handshake) + +Approach #3 provides actual security because: + +. Invalid certificates are **rejected during TLS handshake** before any data is exchanged +. Both RSA and ML-DSA-65 signatures must be valid to establish the connection +. Works with the existing TLS infrastructure (backward compatible) + +''' + +== Why Chimera is the Best Migration Path + +[source,text] +---- +┌─────────────────────────────────────────────────────────────┐ +│ MIGRATION TIMELINE │ +└─────────────────────────────────────────────────────────────┘ + +TODAY (2026) FUTURE (Quantum Computers) +════════════ ══════════════════════════ + +Old Browser: PQC-Aware Browser: +┌────────────┐ ┌────────────┐ +│ Only knows │ │ Checks RSA │ +│ RSA │ │ AND │ +└──────┬─────┘ │ ML-DSA │ + │ └──────┬─────┘ + │ Chimera │ + │ Certificate │ + ▼ ▼ +┌──────────────┐ ┌──────────────┐ +│ Verifies RSA │ │ Verifies RSA │ +│ signature ✓ │ │ signature ✓ │ +│ │ │ │ +│ Ignores │ │ ALSO checks │ +│ ML-DSA │ │ ML-DSA ✓ │ +│ (unknown │ │ │ +│ extension) │ │ Double │ +│ │ │ protected! │ +│ ✓ Works! │ │ ✓ Quantum │ +│ │ │ safe! │ +└──────────────┘ └──────────────┘ + +ADVANTAGE: One certificate works for everyone! +---- + +''' + +== Summary: What We've Built + +[cols="2,3,1",options="header"] +|=== +|Component +|What It Does +|Quantum Safe? + +|**HTTPS Transport** +|Encrypts connection (Java 17 limitation) +|⚠️ No (classical crypto) + +|**HybridCertificateGenerator** +|Generates Chimera dual certificates (RSA + ML-DSA-65) +|✅ Yes + +|**HybridPqcX509TrustManager** +|Validates both RSA and ML-DSA-65 signatures at TLS layer +|✅ Yes + +|**SecurityConfiguration** +|Configures custom TrustManager and client authentication +|✅ Yes + +|**/pqc/secure endpoint** +|Accessible only with valid hybrid PQC certificates +|✅ Yes +|=== + +**Think of it like this:** + +* The **transport tunnel** (HTTPS/TLS) still uses classical encryption (Java 17 limitation) +* But the **authentication** (certificate validation) is quantum-safe with dual signatures +* The **Chimera certificate** is like a dual-lock ID card: RSA works today, ML-DSA-65 protects against future quantum attacks +* Only clients with valid hybrid certificates can access the secure endpoint + +**When Java 21+ becomes standard:** + +* The transport itself can be upgraded to full PQC (e.g., Kyber for key exchange) +* Chimera certificates will work perfectly with full PQC TLS +* Zero code changes needed - we're already PQC-ready! diff --git a/http-pqc-j17/README.adoc b/http-pqc-j17/README.adoc new file mode 100644 index 00000000..f448aa98 --- /dev/null +++ b/http-pqc-j17/README.adoc @@ -0,0 +1,189 @@ += HTTP with Post-Quantum Cryptography (PQC): A Camel Quarkus example (Java 17) +:cq-example-description: An example that shows how to implement quantum-resistant authentication using hybrid certificates that combine RSA with post-quantum ML-DSA-65 signatures on Java 17 using application-level validation + +{cq-description} + +This example shows how to implement quantum-resistant TLS authentication on **Java 17** by combining classical RSA with post-quantum ML-DSA-65 signatures in X.509 certificates. Both signatures must be valid for authentication to succeed. + +IMPORTANT: This example uses **application-level PQC validation** because Java 17 doesn't support PQC in TLS natively. For full PQC TLS support with hybrid cipher suites, use Java 21+ with BouncyCastle JSSE provider. + +TIP: Check the https://camel.apache.org/camel-quarkus/latest/first-steps.html[Camel Quarkus User guide] for prerequisites and other general information. + +== What is Post-Quantum Cryptography? + +Post-Quantum Cryptography (PQC) protects against "harvest now, decrypt later" attacks where adversaries capture encrypted data today to decrypt when quantum computers become available. + +=== Java 17 Approach + +Since **Java 17 doesn't support PQC algorithms natively in TLS**, this example demonstrates a workaround using: + +* **Chimera hybrid certificates**: Combines RSA-2048 + ML-DSA-65 (NIST FIPS 204) +* **X.509 extensions**: Standard extension OIDs (2.5.29.72-74) for alternative signatures +* **Application-level validation**: Custom X509TrustManager validates both RSA and ML-DSA-65 signatures during TLS handshake +* **BouncyCastle 1.83**: Provides ML-DSA-65 post-quantum signature algorithm (JCA provider only) + +This approach validates PQC signatures at the application level rather than relying on Java's TLS stack. For native PQC TLS support (hybrid cipher suites like X25519Kyber768), use Java 21+ with BouncyCastle JSSE provider. + +NOTE: For detailed diagrams and architecture explanation, see link:PQC-EXPLANATION.adoc[PQC Visual Guide]. + +== Certificate Generation + +Hybrid certificates are automatically generated on every application startup. No manual steps required. + +Generated files in `target/certs/`: + +* `server-hybrid-keystore.p12` - Server certificate with RSA + ML-DSA-65 +* `server-hybrid-truststore.p12` - Truststore for validating clients +* `client-hybrid-keystore.p12` - Client certificate with PQC (for success test) +* `client-hybrid-keystore-cert.pem` - Client certificate in PEM format (for curl testing) +* `client-hybrid-keystore-key.pem` - Client private key in PEM format (for curl testing) +* `client-rsa-only-keystore.p12` - Client certificate without PQC (for failure test) + +== Prerequisites + +* **Java 17** (this example demonstrates Java 17-specific workarounds for PQC; for Java 21+, use native PQC TLS support instead) +* Maven 3.9.9 or later +* GraalVM (for native mode only) + +== Start in Development Mode + +[source,shell] +---- +$ mvn clean compile quarkus:dev +---- + +The above command compiles the project, starts the application and lets the Quarkus tooling watch for changes in your workspace. Any modifications in your project will automatically take effect in the running application. + +TIP: Please refer to the Development mode section of https://camel.apache.org/camel-quarkus/latest/first-steps.html#_development_mode[Camel Quarkus User guide] for more details. + +The application starts on HTTPS port 8443 with mutual TLS (mTLS) enabled. All endpoints require a valid hybrid client certificate with RSA + ML-DSA-65. + +Main endpoint: + +* `/pqc/secure` - Requires hybrid client certificate validated at TLS layer + +NOTE: With `client-auth=required`, the TLS handshake rejects connections without valid hybrid PQC certificates before any application code executes. + +=== Manual Testing with Client Certificates + +PEM files are automatically generated during application startup in `target/certs/`: + +* `client-hybrid-keystore-cert.pem` - Hybrid certificate (RSA + ML-DSA-65) +* `client-hybrid-keystore-key.pem` - Private key for hybrid certificate + +Test with hybrid certificate (should succeed): + +[source,shell] +---- +$ curl --cert target/certs/client-hybrid-keystore-cert.pem \ + --key target/certs/client-hybrid-keystore-key.pem \ + -k \ + https://localhost:8443/pqc/secure + +✓ Hybrid PQC certificate validated at TLS layer! +Your connection is quantum-safe. +Both RSA and ML-DSA-65 signatures were validated during TLS handshake. +---- + +== Package and Run the Application + +Once you are done with developing you may want to package and run the application. + +TIP: Find more details about the JVM mode and Native mode in the Package and run section of https://camel.apache.org/camel-quarkus/latest/first-steps.html#_package_and_run_the_application[Camel Quarkus User guide] + +=== JVM Mode + +[source,shell] +---- +$ mvn clean package +$ java -jar target/quarkus-app/quarkus-run.jar +... +[io.quarkus] (main) camel-quarkus-examples-http-pqc started in 1.5s. Listening on: https://0.0.0.0:8443 +---- + +=== Native Mode + +IMPORTANT: Native mode requires having GraalVM and other tools installed. Please check the Prerequisites section of https://camel.apache.org/camel-quarkus/latest/first-steps.html#_prerequisites[Camel Quarkus User guide]. + +To prepare a native executable using GraalVM, run the following command: + +[source,shell] +---- +$ mvn clean package -Dnative +$ ./target/*-runner +... +[io.quarkus] (main) camel-quarkus-examples-http-pqc started in 0.015s. Listening on: https://0.0.0.0:8443 +... +---- + +== Testing + +Run the tests to verify hybrid certificate functionality: + +[source,shell] +---- +$ mvn clean test +---- + +The test suite validates: + +* Hybrid keystores are generated automatically +* `/pqc/secure` rejects requests without client certificates +* `/pqc/secure` accepts hybrid certificates (RSA + ML-DSA-65) +* `/pqc/secure` rejects RSA-only certificates missing PQC extensions + +For native mode testing: + +[source,shell] +---- +$ mvn clean verify -Dnative +---- + +== How It Works (Java 17 Application-Level Validation) + +This example works around Java 17's lack of native PQC support by implementing custom certificate validation at the application level, integrated into the TLS handshake via a custom `X509TrustManager`. + +=== Certificate Structure + +Traditional X.509 certificates are extended with three additional fields (Chimera format): + +* **OID 2.5.29.72** - Alternative public key (ML-DSA-65) +* **OID 2.5.29.73** - Alternative signature algorithm identifier +* **OID 2.5.29.74** - Alternative signature value (ML-DSA-65 signature) + +Both RSA and ML-DSA-65 signatures must validate for authentication to succeed. + +=== Validation Flow (Application-Level, Not TLS-Native) + +1. Client connects with TLS client certificate +2. Java's TLS stack invokes our custom `HybridPqcX509TrustManager` during handshake +3. `CertificatesUtil.validateHybridCertificate()` performs application-level checks: + - RSA signature (standard X.509 validation via Java crypto) + - ML-DSA-65 algorithm OID (2.5.29.73) - manual extraction + - ML-DSA-65 public key (2.5.29.72) - manual extraction + - ML-DSA-65 signature (2.5.29.74) - manual verification via BouncyCastle +4. If all checks pass, TLS handshake continues +5. If any check fails, TLS handshake is rejected + +NOTE: This validation happens at the application level, not within Java's TLS implementation. Java 17's TLS stack only handles the standard RSA certificate; our custom code validates the PQC extensions. + +== Important Notes + +* **Java 17 Only**: This example is specifically designed for Java 17, which lacks native PQC support in its TLS stack. It demonstrates application-level validation as a workaround. Do not use this approach if you can upgrade to Java 21+. + +* **Development Only**: Certificates are regenerated on every startup. For production, use persistent certificates from a trusted CA. + +* **BouncyCastle 1.83**: Uses standardized ML-DSA-65 naming per NIST FIPS 204 (effective August 2024). This example uses JCA provider only, not JSSE. Note that ML-DSA (standardized) and Dilithium (pre-standard) are NOT interoperable. + +== Additional Resources + +* link:PQC-EXPLANATION.adoc[Visual Guide] - Detailed diagrams and architecture +* https://csrc.nist.gov/pubs/fips/204/final[NIST FIPS 204 - ML-DSA Standard] +* https://datatracker.ietf.org/doc/html/draft-ounsworth-pq-composite-sigs[IETF Composite Signatures - Chimera format specification] +* https://www.bouncycastle.org/[BouncyCastle - PQC provider documentation] +* https://www.rfc-editor.org/rfc/rfc9881.html[RFC 9881 - Algorithm Identifiers for ML-DSA in X.509] +* https://www.rfc-editor.org/rfc/rfc9882.html[RFC 9882 - Use of ML-DSA in CMS] + +== Feedback and Contributions + +For issues or contributions, please submit to the https://github.com/apache/camel-quarkus-examples[Camel Quarkus Examples] repository. diff --git a/http-pqc-j17/eclipse-formatter-config.xml b/http-pqc-j17/eclipse-formatter-config.xml new file mode 100644 index 00000000..2248b2b8 --- /dev/null +++ b/http-pqc-j17/eclipse-formatter-config.xml @@ -0,0 +1,276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/http-pqc-j17/pom.xml b/http-pqc-j17/pom.xml new file mode 100644 index 00000000..e74b8651 --- /dev/null +++ b/http-pqc-j17/pom.xml @@ -0,0 +1,303 @@ + + + + 4.0.0 + + camel-quarkus-examples-http-pqc-j17 + org.apache.camel.quarkus.examples + 3.35.0-SNAPSHOT + + Camel Quarkus :: Examples :: HTTP PQC + Camel Quarkus Example :: HTTP with Post-Quantum Cryptography + + + 3.34.1 + 3.35.0-SNAPSHOT + + io.quarkus + quarkus-bom + org.apache.camel.quarkus + camel-quarkus-bom + + UTF-8 + UTF-8 + 17 + + 2.29.0 + 1.13.0 + 5.0.0 + 3.15.0 + 3.5.0 + 3.3.1 + 3.5.5 + + + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + ${camel-quarkus.platform.group-id} + ${camel-quarkus.platform.artifact-id} + ${camel-quarkus.platform.version} + pom + import + + + + + + + org.apache.camel.quarkus + camel-quarkus-log + + + org.apache.camel.quarkus + camel-quarkus-platform-http + + + org.apache.camel.quarkus + camel-quarkus-support-bouncycastle + + + org.apache.camel.quarkus + camel-quarkus-microprofile-health + + + + + io.quarkus + quarkus-junit + test + + + io.rest-assured + rest-assured + test + + + org.awaitility + awaitility + test + + + + + + + + + net.revelc.code.formatter + formatter-maven-plugin + ${formatter-maven-plugin.version} + + ${maven.multiModuleProjectDirectory}/eclipse-formatter-config.xml + LF + + + + + net.revelc.code + impsort-maven-plugin + ${impsort-maven-plugin.version} + + java.,javax.,org.w3c.,org.xml.,junit. + true + true + java.,javax.,org.w3c.,org.xml.,junit. + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + true + true + + -Xlint:unchecked + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + false + + org.jboss.logmanager.LogManager + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${maven-surefire-plugin.version} + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + + com.mycila + license-maven-plugin + ${license-maven-plugin.version} + + true +
${maven.multiModuleProjectDirectory}/header.txt
+ + **/*.adoc + **/*.txt + **/LICENSE.txt + **/LICENSE + **/NOTICE.txt + **/NOTICE + **/README + **/pom.xml.versionsBackup + **/quarkus.log* + **/*.p12 + + + SLASHSTAR_STYLE + CAMEL_PROPERTIES_STYLE + SLASHSTAR_STYLE + + + ${maven.multiModuleProjectDirectory}/license-properties-headerdefinition.xml + +
+
+
+
+ + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + + + build + + build + + + + + + + net.revelc.code.formatter + formatter-maven-plugin + + + format + + format + + process-sources + + + + + + net.revelc.code + impsort-maven-plugin + + + sort-imports + + sort + + process-sources + + + + + + com.mycila + license-maven-plugin + + + license-format + + format + + process-sources + + + + +
+ + + + native + + + native + + + + true + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + ${quarkus.native.enabled} + + + + + + + + + + +
diff --git a/http-pqc-j17/src/main/java/org/acme/http/pqc/PqcCamelRoute.java b/http-pqc-j17/src/main/java/org/acme/http/pqc/PqcCamelRoute.java new file mode 100644 index 00000000..2d8f95ac --- /dev/null +++ b/http-pqc-j17/src/main/java/org/acme/http/pqc/PqcCamelRoute.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.acme.http.pqc; + +import jakarta.enterprise.context.ApplicationScoped; +import org.apache.camel.builder.endpoint.EndpointRouteBuilder; + +@ApplicationScoped +public class PqcCamelRoute extends EndpointRouteBuilder { + + @Override + public void configure() throws Exception { + // Secure endpoint with TLS-layer hybrid PQC certificate validation + // Note: Certificate validation happens during TLS handshake via custom TrustManager + // Invalid certificates are rejected before this route executes + // With client-auth=required, only valid hybrid PQC certificates can reach this endpoint + from(platformHttp("/pqc/secure")) + .routeId("pqc-secure-route") + .log("Processing request with validated hybrid PQC certificate") + .setBody(constant( + "✓ Hybrid PQC certificate validated at TLS layer!\n\n" + + "Your connection is quantum-safe.\n" + + "Both RSA and ML-DSA-65 signatures were validated during TLS handshake.\n\n" + + "This demonstrates TLS-layer validation using a custom X509TrustManager.\n" + + "Invalid or RSA-only certificates are rejected during the TLS handshake.\n")) + .to(log("pqc-secure").showExchangePattern(false).showBodyType(false)); + } +} diff --git a/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/HybridCertificateGenerator.java b/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/HybridCertificateGenerator.java new file mode 100644 index 00000000..e5f7d8db --- /dev/null +++ b/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/HybridCertificateGenerator.java @@ -0,0 +1,247 @@ +/* + * 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.acme.http.pqc.certificates; + +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.math.BigInteger; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.cert.X509Certificate; +import java.util.Date; + +import org.acme.http.pqc.crypto.ChimeraOids; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.openssl.jcajce.JcaPEMWriter; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility class for generating and persisting Chimera hybrid certificates. + * These certificates combine classical RSA with post-quantum ML-DSA-65 signatures + * using X.509 extensions as specified in the BouncyCastle PQC Almanac. + * + *

+ * Certificates are automatically generated at application startup by + * {@link SecurityConfiguration} if they don't already exist. + */ +public class HybridCertificateGenerator { + + private static final Logger LOG = LoggerFactory.getLogger(HybridCertificateGenerator.class); + + // Demo keystore password - DO NOT use in production + private static final String KEYSTORE_PASSWORD = "changeit"; + private static final String KEYSTORES_DIR = "target/certs"; + + /** + * Certificate data holder for keypairs and certificates. + */ + public static class CertificateData { + public final KeyPair rsaKeyPair; + public final KeyPair mlDsaKeyPair; + public final X509Certificate certificate; + + public CertificateData(KeyPair rsaKeyPair, KeyPair mlDsaKeyPair, X509Certificate certificate) { + this.rsaKeyPair = rsaKeyPair; + this.mlDsaKeyPair = mlDsaKeyPair; + this.certificate = certificate; + } + } + + /** + * Generates a Chimera hybrid certificate combining RSA and ML-DSA-65. + * + * @param commonName The CN for the certificate subject + * @param includeAltSignature Whether to include the ML-DSA-65 alternative signature + * @return CertificateData containing keypairs and certificate + */ + public static CertificateData generateChimeraCertificate(String commonName, boolean includeAltSignature) + throws Exception { + LOG.debug("Generating Chimera hybrid certificate for CN={}, includeAltSignature={}", + commonName, includeAltSignature); + + // Generate RSA keypair (classical algorithm) + KeyPairGenerator rsaKpg = KeyPairGenerator.getInstance("RSA"); + rsaKpg.initialize(2048, new SecureRandom()); + KeyPair rsaKeyPair = rsaKpg.generateKeyPair(); + + // Generate ML-DSA-65 keypair (PQC algorithm - NIST FIPS 204) + KeyPairGenerator mlDsaKpg = KeyPairGenerator.getInstance("ML-DSA-65", "BC"); + KeyPair mlDsaKeyPair = mlDsaKpg.generateKeyPair(); + + // Build certificate + X500Name issuer = new X500Name("CN=PQC Hybrid CA,O=Apache Camel Quarkus,C=US"); + X500Name subject = new X500Name("CN=" + commonName + ",O=Apache Camel Quarkus,C=US"); + BigInteger serial = BigInteger.valueOf(System.currentTimeMillis()); + Date notBefore = new Date(); + Date notAfter = new Date(System.currentTimeMillis() + 365L * 24 * 60 * 60 * 1000); // 1 year + + X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( + issuer, + serial, + notBefore, + notAfter, + subject, + rsaKeyPair.getPublic()); + + if (includeAltSignature) { + // Add ML-DSA-65 alternative public key (Chimera extension) + SubjectPublicKeyInfo mlDsaPubKeyInfo = SubjectPublicKeyInfo + .getInstance(mlDsaKeyPair.getPublic().getEncoded()); + certBuilder.addExtension(ChimeraOids.SUBJECT_ALT_PUBLIC_KEY_INFO, false, mlDsaPubKeyInfo); + + // Add alternative signature algorithm (Chimera extension) + AlgorithmIdentifier mlDsaSigAlg = new AlgorithmIdentifier(ChimeraOids.ML_DSA_65); + certBuilder.addExtension(ChimeraOids.ALT_SIGNATURE_ALGORITHM, false, mlDsaSigAlg); + + // Generate ML-DSA-65 alternative signature (Chimera extension) + Signature mlDsaSig = Signature.getInstance("ML-DSA-65", "BC"); + mlDsaSig.initSign(mlDsaKeyPair.getPrivate()); + mlDsaSig.update(subject.getEncoded()); // Sign subject DN as per Chimera spec + byte[] mlDsaSignature = mlDsaSig.sign(); + certBuilder.addExtension(ChimeraOids.ALT_SIGNATURE_VALUE, false, new DERBitString(mlDsaSignature)); + + LOG.debug("ML-DSA-65 extensions added to certificate"); + } + + // Sign with RSA (primary signature) + ContentSigner rsaSigner = new JcaContentSignerBuilder("SHA256withRSA").build(rsaKeyPair.getPrivate()); + X509CertificateHolder certHolder = certBuilder.build(rsaSigner); + + // Convert to X509Certificate + X509Certificate certificate = new JcaX509CertificateConverter() + .setProvider("BC") + .getCertificate(certHolder); + + LOG.debug("Chimera certificate generated successfully for CN={}", commonName); + + return new CertificateData(rsaKeyPair, mlDsaKeyPair, certificate); + } + + /** + * Generates a keystore with the specified certificate type. + * + * @param commonName The CN for the certificate + * @param includeAltSignature Whether to include ML-DSA-65 extensions + * @param keystorePath Path where keystore will be saved + * @param alias Keystore entry alias + * @param includeTruststore Whether to also create a truststore + * @param savePemFiles Whether to also save certificate and key as PEM files + */ + private static void generateKeystore( + String commonName, + boolean includeAltSignature, + String keystorePath, + String alias, + boolean includeTruststore, + boolean savePemFiles) throws Exception { + + CertificateData certData = generateChimeraCertificate(commonName, includeAltSignature); + + KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC"); + keyStore.load(null, null); + keyStore.setKeyEntry(alias, + certData.rsaKeyPair.getPrivate(), + KEYSTORE_PASSWORD.toCharArray(), + new X509Certificate[] { certData.certificate }); + + saveKeyStore(keyStore, keystorePath, KEYSTORE_PASSWORD); + LOG.info("Keystore created: {}", keystorePath); + + if (includeTruststore) { + String trustPath = keystorePath.replace("-keystore.p12", "-truststore.p12"); + KeyStore trustStore = KeyStore.getInstance("PKCS12", "BC"); + trustStore.load(null, null); + trustStore.setCertificateEntry(alias + "-ca", certData.certificate); + saveKeyStore(trustStore, trustPath, KEYSTORE_PASSWORD); + LOG.info("Truststore created: {}", trustPath); + } + + if (savePemFiles) { + // Save certificate as PEM + String certPemPath = keystorePath.replace(".p12", "-cert.pem"); + try (FileWriter certWriter = new FileWriter(certPemPath); + JcaPEMWriter pemWriter = new JcaPEMWriter(certWriter)) { + pemWriter.writeObject(certData.certificate); + } + LOG.info("Certificate PEM file created: {}", certPemPath); + + // Save private key as PEM + String keyPemPath = keystorePath.replace(".p12", "-key.pem"); + try (FileWriter keyWriter = new FileWriter(keyPemPath); + JcaPEMWriter pemWriter = new JcaPEMWriter(keyWriter)) { + pemWriter.writeObject(certData.rsaKeyPair.getPrivate()); + } + LOG.info("Private key PEM file created: {}", keyPemPath); + } + } + + /** + * Generates server hybrid keystore with RSA + ML-DSA-65 certificate. + */ + public static void generateServerKeystore() throws Exception { + generateKeystore("localhost", true, KEYSTORES_DIR + "/server-hybrid-keystore.p12", + "server", true, false); + } + + /** + * Generates client hybrid keystore with RSA + ML-DSA-65 certificate. + * Also saves PEM files for manual curl testing. + */ + public static void generateClientHybridKeystore() throws Exception { + generateKeystore("client-hybrid", true, KEYSTORES_DIR + "/client-hybrid-keystore.p12", + "client", false, true); + } + + /** + * Generates client RSA-only keystore (no PQC extensions - for failure test). + */ + public static void generateClientRsaOnlyKeystore() throws Exception { + generateKeystore("client-rsa-only", false, KEYSTORES_DIR + "/client-rsa-only-keystore.p12", + "client", false, false); + } + + /** + * Saves a KeyStore to disk, overwriting any existing file. + */ + public static void saveKeyStore(KeyStore keyStore, String path, String password) throws Exception { + Path dirPath = Paths.get(path).getParent(); + if (!Files.exists(dirPath)) { + Files.createDirectories(dirPath); + LOG.info("Created directory: {}", dirPath); + } + + try (FileOutputStream fos = new FileOutputStream(path)) { + keyStore.store(fos, password.toCharArray()); + } + } +} diff --git a/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/SecurityConfiguration.java b/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/SecurityConfiguration.java new file mode 100644 index 00000000..44309e07 --- /dev/null +++ b/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/SecurityConfiguration.java @@ -0,0 +1,54 @@ +/* + * 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.acme.http.pqc.certificates; + +import java.security.Security; + +import io.quarkus.runtime.StartupEvent; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ApplicationScoped +public class SecurityConfiguration { + + private static final Logger LOG = LoggerFactory.getLogger(SecurityConfiguration.class); + + void onStart(@Observes StartupEvent ev) { + // Register BouncyCastle as the first provider to ensure PQC algorithms are available + Security.insertProviderAt(new BouncyCastleProvider(), 1); + LOG.info("BouncyCastle provider registered at position 1 for PQC support"); + + // Generate fresh hybrid PQC keystores on every startup + generateKeystores(); + } + + private void generateKeystores() { + try { + LOG.info("Generating fresh hybrid PQC keystores..."); + HybridCertificateGenerator.generateServerKeystore(); + HybridCertificateGenerator.generateClientHybridKeystore(); + HybridCertificateGenerator.generateClientRsaOnlyKeystore(); + LOG.info("Hybrid PQC keystores generated successfully"); + } catch (Exception e) { + LOG.error("Failed to generate hybrid PQC keystores", e); + throw new RuntimeException("Keystore generation failed", e); + } + } +} diff --git a/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/util/CertificateValidationException.java b/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/util/CertificateValidationException.java new file mode 100644 index 00000000..c2015438 --- /dev/null +++ b/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/util/CertificateValidationException.java @@ -0,0 +1,33 @@ +/* + * 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.acme.http.pqc.certificates.util; + +import java.security.cert.CertificateException; + +/** + * Exception thrown when hybrid PQC certificate validation fails. + */ +public class CertificateValidationException extends CertificateException { + + public CertificateValidationException(String message) { + super(message); + } + + public CertificateValidationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/util/CertificatesUtil.java b/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/util/CertificatesUtil.java new file mode 100644 index 00000000..84c4d8c3 --- /dev/null +++ b/http-pqc-j17/src/main/java/org/acme/http/pqc/certificates/util/CertificatesUtil.java @@ -0,0 +1,200 @@ +/* + * 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.acme.http.pqc.certificates.util; + +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; + +import org.acme.http.pqc.crypto.ChimeraOids; +import org.bouncycastle.asn1.ASN1BitString; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility class for validating Chimera hybrid certificates. + * Validates both RSA and ML-DSA-65 signatures using static methods. + */ +public final class CertificatesUtil { + + private static final Logger LOG = LoggerFactory.getLogger(CertificatesUtil.class); + + private CertificatesUtil() { + throw new AssertionError("Utility class cannot be instantiated"); + } + + /** + * Validates a hybrid certificate by checking both RSA and ML-DSA-65 signatures. + * + * @param cert The certificate to validate + * @throws CertificateValidationException if validation fails + */ + public static void validateHybridCertificate(X509Certificate cert) throws CertificateValidationException { + LOG.debug("Validating hybrid certificate for subject: {}", cert.getSubjectX500Principal()); + + try { + // Verify RSA signature (standard X.509 verification) + if (!verifyRsaSignature(cert)) { + throw new CertificateValidationException("RSA signature validation failed"); + } + + LOG.debug("RSA signature verified"); + + // Verify alternative signature algorithm extension exists + byte[] altSigAlgExt = cert.getExtensionValue(ChimeraOids.ALT_SIGNATURE_ALGORITHM.getId()); + if (altSigAlgExt == null) { + throw new CertificateValidationException( + "PQC signature algorithm extension missing (OID 2.5.29.73)"); + } + + // Validate it's ML-DSA-65 + ASN1Primitive primitive = ASN1Primitive.fromByteArray(altSigAlgExt); + byte[] octets = ((ASN1OctetString) primitive).getOctets(); + AlgorithmIdentifier algId = AlgorithmIdentifier.getInstance(octets); + + if (!ChimeraOids.ML_DSA_65.equals(algId.getAlgorithm())) { + throw new CertificateValidationException( + "Expected ML-DSA-65 algorithm OID, found: " + algId.getAlgorithm()); + } + + LOG.debug("ML-DSA-65 algorithm OID validated"); + + // Extract and verify ML-DSA-65 signature + PublicKey mlDsaPublicKey = extractMlDsaPublicKey(cert); + if (mlDsaPublicKey == null) { + throw new CertificateValidationException( + "PQC public key extension missing (OID 2.5.29.72)"); + } + + byte[] mlDsaSignature = extractMlDsaSignature(cert); + if (mlDsaSignature == null) { + throw new CertificateValidationException( + "PQC signature extension missing (OID 2.5.29.74)"); + } + + if (!verifyMlDsaSignature(cert, mlDsaPublicKey, mlDsaSignature)) { + throw new CertificateValidationException("ML-DSA-65 signature validation failed"); + } + + LOG.debug("ML-DSA-65 signature verified - hybrid certificate valid"); + + } catch (IOException e) { + throw new CertificateValidationException("Failed to parse PQC extensions", e); + } catch (CertificateValidationException e) { + LOG.warn("Certificate validation failed: {}", e.getMessage()); + throw e; + } catch (Exception e) { + String message = "Unexpected error during certificate validation: " + e.getMessage(); + LOG.error(message, e); + throw new CertificateValidationException(message, e); + } + } + + /** + * Verifies the RSA signature using standard X.509 verification. + */ + private static boolean verifyRsaSignature(X509Certificate cert) { + try { + // Self-signed certificate - verify with its own public key + cert.verify(cert.getPublicKey()); + return true; + } catch (CertificateException | NoSuchAlgorithmException | InvalidKeyException | SignatureException + | NoSuchProviderException e) { + LOG.error("RSA signature verification failed", e); + return false; + } + } + + /** + * Extracts the ML-DSA-65 public key from the altSubjectPublicKeyInfo extension. + */ + private static PublicKey extractMlDsaPublicKey(X509Certificate cert) { + try { + byte[] extensionValue = cert.getExtensionValue(ChimeraOids.SUBJECT_ALT_PUBLIC_KEY_INFO.getId()); + if (extensionValue == null) { + return null; + } + + // Extension value is wrapped in OCTET STRING + ASN1Primitive primitive = ASN1Primitive.fromByteArray(extensionValue); + byte[] octets = ((ASN1OctetString) primitive).getOctets(); + + // Parse SubjectPublicKeyInfo + SubjectPublicKeyInfo spki = SubjectPublicKeyInfo.getInstance(octets); + + // Convert to PublicKey using X509EncodedKeySpec + KeyFactory keyFactory = KeyFactory.getInstance("ML-DSA-65", "BC"); + return keyFactory.generatePublic(new X509EncodedKeySpec(spki.getEncoded())); + + } catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException | NoSuchProviderException e) { + LOG.error("Failed to extract ML-DSA-65 public key", e); + return null; + } + } + + /** + * Extracts the ML-DSA-65 signature from the altSignatureValue extension. + */ + private static byte[] extractMlDsaSignature(X509Certificate cert) { + try { + byte[] extensionValue = cert.getExtensionValue(ChimeraOids.ALT_SIGNATURE_VALUE.getId()); + if (extensionValue == null) { + return null; + } + + // Extension value is wrapped in OCTET STRING + ASN1Primitive primitive = ASN1Primitive.fromByteArray(extensionValue); + byte[] octets = ((ASN1OctetString) primitive).getOctets(); + + // Parse as BIT STRING + ASN1BitString bitString = ASN1BitString.getInstance(octets); + return bitString.getBytes(); + + } catch (IOException e) { + LOG.error("Failed to extract ML-DSA-65 signature", e); + return null; + } + } + + /** + * Verifies the ML-DSA-65 signature. + */ + private static boolean verifyMlDsaSignature(X509Certificate cert, PublicKey pqcKey, byte[] signature) { + try { + Signature mlDsaVerify = Signature.getInstance("ML-DSA-65", "BC"); + mlDsaVerify.initVerify(pqcKey); + mlDsaVerify.update(cert.getSubjectX500Principal().getEncoded()); + return mlDsaVerify.verify(signature); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | NoSuchProviderException e) { + LOG.error("ML-DSA-65 signature verification failed", e); + return false; + } + } +} diff --git a/http-pqc-j17/src/main/java/org/acme/http/pqc/crypto/ChimeraOids.java b/http-pqc-j17/src/main/java/org/acme/http/pqc/crypto/ChimeraOids.java new file mode 100644 index 00000000..d5fc254c --- /dev/null +++ b/http-pqc-j17/src/main/java/org/acme/http/pqc/crypto/ChimeraOids.java @@ -0,0 +1,167 @@ +/* + * 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.acme.http.pqc.crypto; + +import org.bouncycastle.asn1.ASN1ObjectIdentifier; + +/** + * X.509 extension OIDs (Object Identifiers) for Chimera hybrid certificate format. + * + *

+ * OIDs are globally unique identifiers used in X.509 certificates to label specific + * data fields and extensions. These OIDs enable standard X.509 certificates to carry + * both classical (RSA) and post-quantum (ML-DSA-65) cryptographic signatures. + * + *

Chimera Hybrid Certificate Structure:

+ * + *
+ * Standard X.509 Certificate:
+ *   Subject: CN=localhost
+ *   Public Key: RSA-2048                    ← Classical (readable by all TLS stacks)
+ *   Signature: SHA256withRSA                ← Classical signature
+ *
+ *   Extensions:
+ *     [2.5.29.72] altSubjectPublicKeyInfo:  ← ML-DSA-65 public key
+ *     [2.5.29.73] altSignatureAlgorithm:    ← Identifies ML-DSA-65 (2.16.840.1.101.3.4.3.18)
+ *     [2.5.29.74] altSignatureValue:        ← ML-DSA-65 signature
+ * 
+ * + *

+ * Why this matters: Both signatures must be valid for authentication. + * This provides quantum resistance (via ML-DSA-65) while maintaining backward + * compatibility with standard TLS (via RSA). + * + *

OID Hierarchy Explained:

+ *
    + *
  • 2.5.29.x - X.509 certificate extensions (standardized by ITU-T) + *
      + *
    • 2.5.29.15 - keyUsage (common)
    • + *
    • 2.5.29.17 - subjectAltName (common)
    • + *
    • 2.5.29.72-74 - Chimera hybrid extensions (new for PQC)
    • + *
    + *
  • + *
  • 2.16.840.1.101.3.4.3.18 - ML-DSA-65 algorithm (NIST FIPS 204) + *
      + *
    • 2.16.840.1.101.3 - NIST algorithms
    • + *
    • 4.3 - Signature algorithms
    • + *
    • 18 - ML-DSA-65 (Level 3 security)
    • + *
    + *
  • + *
+ * + * @see RFC 5280 - X.509 Certificate Standard + * @see FIPS 204 - ML-DSA Standard + */ +public final class ChimeraOids { + + /** + * OID 2.5.29.72 - Alternative Subject Public Key Info extension. + * Contains the ML-DSA-65 public key in addition to the standard RSA public key. + * + *

+ * This allows a single certificate to carry two public keys: + *

    + *
  • Primary: RSA-2048 (in standard subjectPublicKeyInfo field)
  • + *
  • Alternative: ML-DSA-65 (in this extension)
  • + *
+ * + *

+ * Official References: + *

+ */ + public static final ASN1ObjectIdentifier SUBJECT_ALT_PUBLIC_KEY_INFO = new ASN1ObjectIdentifier("2.5.29.72"); + + /** + * OID 2.5.29.73 - Alternative Signature Algorithm extension. + * Identifies which algorithm was used for the alternative signature (ML-DSA-65). + * + *

+ * Contains the OID {@link #ML_DSA_65} to specify the PQC algorithm used. + * + *

+ * Official References: + *

+ */ + public static final ASN1ObjectIdentifier ALT_SIGNATURE_ALGORITHM = new ASN1ObjectIdentifier("2.5.29.73"); + + /** + * OID 2.5.29.74 - Alternative Signature Value extension. + * Contains the actual ML-DSA-65 digital signature bytes. + * + *

+ * This is the post-quantum signature that proves the certificate is authentic + * and hasn't been tampered with, computed using the ML-DSA-65 private key. + * + *

+ * Official References: + *

+ */ + public static final ASN1ObjectIdentifier ALT_SIGNATURE_VALUE = new ASN1ObjectIdentifier("2.5.29.74"); + + /** + * OID 2.16.840.1.101.3.4.3.18 - ML-DSA-65 algorithm identifier (NIST FIPS 204). + * + *

+ * ML-DSA-65 (Module-Lattice-Based Digital Signature Algorithm, parameter set 65) + * is a NIST Level 3 post-quantum signature algorithm resistant to attacks from + * quantum computers. ML-DSA was standardized from CRYSTALS-Dilithium. + * + *

+ * Security level: NIST Level 3, equivalent to AES-192 (192-bit security) + *
+ * Signature size: ~3,309 bytes (much larger than RSA-2048's ~256 bytes) + *
+ * Public key size: ~1,952 bytes + * + *

+ * NOTE: ML-DSA (standardized) and Dilithium (pre-standard) are NOT interoperable. + * This OID represents the final NIST FIPS 204 standardized version. + * + *

+ * Official References: + *

+ */ + public static final ASN1ObjectIdentifier ML_DSA_65 = new ASN1ObjectIdentifier("2.16.840.1.101.3.4.3.18"); + + private ChimeraOids() { + throw new AssertionError("Constants class cannot be instantiated"); + } +} diff --git a/http-pqc-j17/src/main/java/org/acme/http/pqc/trustmanager/HybridPqcTrustManagerCustomizer.java b/http-pqc-j17/src/main/java/org/acme/http/pqc/trustmanager/HybridPqcTrustManagerCustomizer.java new file mode 100644 index 00000000..c4c48dbf --- /dev/null +++ b/http-pqc-j17/src/main/java/org/acme/http/pqc/trustmanager/HybridPqcTrustManagerCustomizer.java @@ -0,0 +1,58 @@ +/* + * 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.acme.http.pqc.trustmanager; + +import javax.net.ssl.X509TrustManager; + +import io.quarkus.vertx.http.HttpServerOptionsCustomizer; +import io.vertx.core.http.HttpServerOptions; +import io.vertx.core.net.TrustOptions; +import jakarta.enterprise.context.ApplicationScoped; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Quarkus CDI bean that customizes the Vert.x HTTP server to use a custom TrustManager. + * + * This customizer registers {@link HybridPqcX509TrustManager} with the HTTP server, + * enabling TLS-layer validation of hybrid PQC certificates (RSA + ML-DSA-65) during + * the TLS handshake. + * + * Uses Quarkus {@link HttpServerOptionsCustomizer} interface to integrate with Vert.x. + */ +@ApplicationScoped +public class HybridPqcTrustManagerCustomizer implements HttpServerOptionsCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(HybridPqcTrustManagerCustomizer.class); + + @Override + public void customizeHttpsServer(HttpServerOptions options) { + LOG.info("Registering custom hybrid PQC TrustManager for TLS-layer validation..."); + + // Create custom TrustManager + X509TrustManager customTrustManager = new HybridPqcX509TrustManager(); + + // Wrap the X509TrustManager into Vert.x TrustOptions + TrustOptions trustOptions = TrustOptions.wrap(customTrustManager); + + // Register with Vert.x HTTP server using setTrustOptions + options.setTrustOptions(trustOptions); + + LOG.info("Custom hybrid PQC TrustManager registered successfully"); + LOG.info(" Client certificates will be validated at TLS layer (RSA + ML-DSA-65)"); + } +} diff --git a/http-pqc-j17/src/main/java/org/acme/http/pqc/trustmanager/HybridPqcX509TrustManager.java b/http-pqc-j17/src/main/java/org/acme/http/pqc/trustmanager/HybridPqcX509TrustManager.java new file mode 100644 index 00000000..7d85ec9e --- /dev/null +++ b/http-pqc-j17/src/main/java/org/acme/http/pqc/trustmanager/HybridPqcX509TrustManager.java @@ -0,0 +1,77 @@ +/* + * 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.acme.http.pqc.trustmanager; + +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.X509TrustManager; + +import org.acme.http.pqc.certificates.util.CertificateValidationException; +import org.acme.http.pqc.certificates.util.CertificatesUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Custom X509TrustManager that validates hybrid PQC certificates at the TLS layer. + * + * This TrustManager validates both RSA and ML-DSA-65 signatures during the TLS handshake, + * rejecting connections with invalid or RSA-only certificates before the application layer + * sees the request. + */ +public class HybridPqcX509TrustManager implements X509TrustManager { + + private static final Logger LOG = LoggerFactory.getLogger(HybridPqcX509TrustManager.class); + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + if (chain == null || chain.length == 0) { + throw new CertificateException("Client certificate chain is empty"); + } + + X509Certificate clientCert = chain[0]; + LOG.debug("Validating client certificate at TLS layer: {}", clientCert.getSubjectX500Principal()); + + try { + // Validate hybrid certificate - throws CertificateValidationException on failure + CertificatesUtil.validateHybridCertificate(clientCert); + LOG.debug("Client certificate validated successfully at TLS layer (RSA + ML-DSA-65)"); + } catch (CertificateValidationException e) { + LOG.error("Hybrid PQC certificate validation failed: {}", e.getMessage()); + throw new CertificateException("Validation failed: " + e.getMessage(), e); + } + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + // Not implemented - this example only validates client certificates + // (server-to-client authentication, not client-to-server) + // + // In mutual TLS where client validates server's hybrid certificate, + // this method would implement similar validation logic. + LOG.debug("Server certificate validation not implemented (client-auth only)"); + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + // Return empty array for self-signed certificates in this demo. + // + // In production with a CA hierarchy, this would return the + // list of trusted CA certificates that can issue client certificates. + return new X509Certificate[0]; + } +} diff --git a/http-pqc-j17/src/main/resources/application.properties b/http-pqc-j17/src/main/resources/application.properties new file mode 100644 index 00000000..90b2e0cd --- /dev/null +++ b/http-pqc-j17/src/main/resources/application.properties @@ -0,0 +1,49 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +# +# Quarkus +# +quarkus.banner.enabled = false +quarkus.log.file.enabled = true + +# HTTPS Configuration with Hybrid PQC Certificates +quarkus.http.ssl-port = 8443 +quarkus.http.insecure-requests = disabled + +# Server uses hybrid certificate (RSA + ML-DSA-65) +quarkus.http.ssl.certificate.key-store-file = target/certs/server-hybrid-keystore.p12 +quarkus.http.ssl.certificate.key-store-password = changeit +quarkus.http.ssl.certificate.key-store-file-type = PKCS12 + +# Require client certificates (validated by custom TrustManager) +# Certificates must be valid hybrid PQC certificates (RSA + ML-DSA-65) +quarkus.http.ssl.client-auth = required + +# Truststore for client certificate validation (standard TLS layer) +quarkus.http.ssl.certificate.trust-store-file = target/certs/server-hybrid-truststore.p12 +quarkus.http.ssl.certificate.trust-store-password = changeit +quarkus.http.ssl.certificate.trust-store-file-type = PKCS12 + +# +# Quarkus - Camel +# +quarkus.camel.health.enabled = true + +# +# Camel +# +camel.context.name = quarkus-camel-example-http-pqc diff --git a/http-pqc-j17/src/test/java/org/acme/http/pqc/HttpPqcIT.java b/http-pqc-j17/src/test/java/org/acme/http/pqc/HttpPqcIT.java new file mode 100644 index 00000000..232ace0a --- /dev/null +++ b/http-pqc-j17/src/test/java/org/acme/http/pqc/HttpPqcIT.java @@ -0,0 +1,23 @@ +/* + * 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.acme.http.pqc; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +public class HttpPqcIT extends HttpPqcTest { +} diff --git a/http-pqc-j17/src/test/java/org/acme/http/pqc/HttpPqcTest.java b/http-pqc-j17/src/test/java/org/acme/http/pqc/HttpPqcTest.java new file mode 100644 index 00000000..39387ef6 --- /dev/null +++ b/http-pqc-j17/src/test/java/org/acme/http/pqc/HttpPqcTest.java @@ -0,0 +1,115 @@ +/* + * 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.acme.http.pqc; + +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import io.restassured.config.RestAssuredConfig; +import io.restassured.config.SSLConfig; +import org.eclipse.microprofile.config.ConfigProvider; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.fail; + +@QuarkusTest +public class HttpPqcTest { + + private static final Logger log = LoggerFactory.getLogger(HttpPqcTest.class); + + @BeforeAll + public static void setUpClass() { + // Use relaxed HTTPS validation for self-signed certificates in tests + RestAssured.useRelaxedHTTPSValidation(); + } + + @BeforeEach + public void setUp() { + // Configure base URI and port for each test + // Read the port dynamically from config - works in both JVM and native tests + int sslPort = ConfigProvider.getConfig() + .getValue("quarkus.http.test-ssl-port", Integer.class); + RestAssured.baseURI = "https://localhost"; + RestAssured.port = sslPort; + } + + @Test + public void testPqcSecureEndpointWithoutClientCert() { + // With client-auth=required, TLS handshake fails before reaching the route + try { + RestAssured.given() + .when() + .get("/pqc/secure") + .then() + .statusCode(200); + + fail("Expected SSL exception but connection succeeded"); + } catch (Exception e) { + // Expected: SSL handshake failure (certificate_required) + log.info("✓ Expected SSL exception without client cert: {}", e.getMessage()); + } + } + + @Test + public void testPqcSecureEndpointWithValidClientCert() { + // Test /pqc/secure WITH valid hybrid client certificate + // TLS handshake should succeed, and custom TrustManager validates both RSA + ML-DSA-65 + // Configure RestAssured with client certificate keystore and server truststore + + RestAssured.given() + .config(RestAssuredConfig.config().sslConfig( + SSLConfig.sslConfig() + .keyStore("target/certs/client-hybrid-keystore.p12", "changeit") + .trustStore("target/certs/server-hybrid-truststore.p12", "changeit") + .allowAllHostnames() // Accept localhost with self-signed cert + )) + .when() + .get("/pqc/secure") + .then() + .statusCode(200) + .body(containsString("Hybrid PQC certificate validated")) + .body(containsString("quantum-safe")) + .body(containsString("TLS layer")); + } + + @Test + public void testPqcSecureEndpointWithRsaOnlyCertificate() { + // Test /pqc/secure WITH RSA-only client certificate (no PQC extensions) + // TLS handshake should FAIL because custom TrustManager requires hybrid cert + try { + RestAssured.given() + .config(RestAssuredConfig.config().sslConfig( + SSLConfig.sslConfig() + .keyStore("target/certs/client-rsa-only-keystore.p12", "changeit") + .trustStore("target/certs/server-hybrid-truststore.p12", "changeit") + .allowAllHostnames())) + .when() + .get("/pqc/secure") + .then() + .statusCode(200); // Should NOT reach here + + fail("Expected SSL exception for RSA-only certificate, but connection succeeded"); + } catch (Exception e) { + // Expected: TLS handshake failure due to missing PQC extensions + log.info("✓ Expected SSL exception for RSA-only cert: {}", e.getMessage()); + } + } +} From 75fe47e5072c2ca744fe8af7c6440a7248617fa5 Mon Sep 17 00:00:00 2001 From: James Netherton Date: Mon, 13 Apr 2026 08:25:42 +0100 Subject: [PATCH 11/12] Move Kafka example k8s devservice disablement config to Maven properties --- kafka/pom.xml | 6 ++++++ kafka/src/main/resources/application.properties | 3 --- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/kafka/pom.xml b/kafka/pom.xml index 18a8b717..ff7f5747 100644 --- a/kafka/pom.xml +++ b/kafka/pom.xml @@ -329,6 +329,9 @@ kubernetes
+ + false + io.quarkus @@ -347,6 +350,9 @@ openshift
+ + false + io.quarkus diff --git a/kafka/src/main/resources/application.properties b/kafka/src/main/resources/application.properties index c82c0f42..80dbb9f3 100644 --- a/kafka/src/main/resources/application.properties +++ b/kafka/src/main/resources/application.properties @@ -15,9 +15,6 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -# No need for k8s dev services in this project -quarkus.kubernetes-client.devservices.enabled = false - # Use Strimzi as it's power architecture compatible quarkus.kafka.devservices.provider = strimzi quarkus.kafka.devservices.image-name = quay.io/strimzi-test-container/test-container:0.114.0-kafka-4.1.0 From 38718c94b35c7623cc366188fe3e75cd57625c3e Mon Sep 17 00:00:00 2001 From: James Netherton Date: Fri, 1 May 2026 08:23:15 +0100 Subject: [PATCH 12/12] Upgrade to Quarkus Platform 3.35.1 --- amqp/pom.xml | 10 +++++----- artemis-elasticsearch/pom.xml | 10 +++++----- aws-lambda/pom.xml | 10 +++++----- aws2-s3/pom.xml | 10 +++++----- cluster-leader-election/pom.xml | 10 +++++----- cxf-soap/pom.xml | 10 +++++----- data-extract-langchain4j/pom.xml | 10 +++++----- fhir/pom.xml | 10 +++++----- file-bindy-ftp/pom.xml | 10 +++++----- file-split-log-xml/pom.xml | 10 +++++----- health/pom.xml | 10 +++++----- http-log/pom.xml | 10 +++++----- http-pqc-j17/pom.xml | 10 +++++----- jdbc-datasource/pom.xml | 10 +++++----- jms-jpa/pom.xml | 10 +++++----- jpa-idempotent-repository/pom.xml | 10 +++++----- jta-jpa/pom.xml | 10 +++++----- kafka/pom.xml | 10 +++++----- kamelet-chucknorris/pom.xml | 10 +++++----- message-bridge/pom.xml | 10 +++++----- netty-custom-correlation/pom.xml | 10 +++++----- observability/pom.xml | 10 +++++----- openapi-contract-first/pom.xml | 10 +++++----- platform-http-security-keycloak/pom.xml | 10 +++++----- quarkus-rest-json/pom.xml | 10 +++++----- rest-json/pom.xml | 10 +++++----- saga/pom.xml | 10 +++++----- spring-redis/pom.xml | 10 +++++----- timer-log-main/pom.xml | 10 +++++----- timer-log/pom.xml | 10 +++++----- variables/pom.xml | 10 +++++----- vertx-websocket-chat/pom.xml | 10 +++++----- 32 files changed, 160 insertions(+), 160 deletions(-) diff --git a/amqp/pom.xml b/amqp/pom.xml index 9a3221b2..e6d6dbfb 100644 --- a/amqp/pom.xml +++ b/amqp/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: AMQP - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/artemis-elasticsearch/pom.xml b/artemis-elasticsearch/pom.xml index 395ad47d..0363e7dc 100644 --- a/artemis-elasticsearch/pom.xml +++ b/artemis-elasticsearch/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Artemis ElasticSearch - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/aws-lambda/pom.xml b/aws-lambda/pom.xml index 63ba319a..e018afd0 100644 --- a/aws-lambda/pom.xml +++ b/aws-lambda/pom.xml @@ -27,13 +27,13 @@ Camel Quarkus Example :: Deploying a Camel Route in AWS Lambda - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/aws2-s3/pom.xml b/aws2-s3/pom.xml index e074be6b..7b71c483 100644 --- a/aws2-s3/pom.xml +++ b/aws2-s3/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Upload a file to an AWS S3 bucket - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/cluster-leader-election/pom.xml b/cluster-leader-election/pom.xml index 8bfd8ebf..9a1cc360 100644 --- a/cluster-leader-election/pom.xml +++ b/cluster-leader-election/pom.xml @@ -29,13 +29,13 @@ Camel Quarkus Example :: Cluster leader election - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/cxf-soap/pom.xml b/cxf-soap/pom.xml index 926f026f..4d6d613a 100644 --- a/cxf-soap/pom.xml +++ b/cxf-soap/pom.xml @@ -29,13 +29,13 @@ Camel Quarkus Example :: CXF SOAP - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/data-extract-langchain4j/pom.xml b/data-extract-langchain4j/pom.xml index fa20b595..e741d68f 100644 --- a/data-extract-langchain4j/pom.xml +++ b/data-extract-langchain4j/pom.xml @@ -31,13 +31,13 @@ - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/fhir/pom.xml b/fhir/pom.xml index 80f2b470..e26cd493 100644 --- a/fhir/pom.xml +++ b/fhir/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: FHIR - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/file-bindy-ftp/pom.xml b/file-bindy-ftp/pom.xml index e087e974..5c3d542e 100644 --- a/file-bindy-ftp/pom.xml +++ b/file-bindy-ftp/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: File Bindy FTP - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/file-split-log-xml/pom.xml b/file-split-log-xml/pom.xml index 4b758cf1..4f439fe7 100644 --- a/file-split-log-xml/pom.xml +++ b/file-split-log-xml/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: File To Log XML DSL - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/health/pom.xml b/health/pom.xml index 4852270b..be66bcbf 100644 --- a/health/pom.xml +++ b/health/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Health Check - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/http-log/pom.xml b/http-log/pom.xml index 5ccc7db4..cb468bee 100644 --- a/http-log/pom.xml +++ b/http-log/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: HTTP to Log - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/http-pqc-j17/pom.xml b/http-pqc-j17/pom.xml index e74b8651..37859bc1 100644 --- a/http-pqc-j17/pom.xml +++ b/http-pqc-j17/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: HTTP with Post-Quantum Cryptography - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/jdbc-datasource/pom.xml b/jdbc-datasource/pom.xml index d255491b..28734fc1 100644 --- a/jdbc-datasource/pom.xml +++ b/jdbc-datasource/pom.xml @@ -25,13 +25,13 @@ Camel Quarkus :: Examples :: Jdbc - DatataSource - Log Camel Quarkus Example :: Connect to Database using Datasource - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom 2.29.0 1.13.0 diff --git a/jms-jpa/pom.xml b/jms-jpa/pom.xml index 9bd867c4..fa47c892 100644 --- a/jms-jpa/pom.xml +++ b/jms-jpa/pom.xml @@ -25,14 +25,14 @@ Camel Quarkus :: Examples :: JMS JPA Camel Quarkus Example :: JMS JPA - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} 3.14.1 - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom 2.29.0 1.13.0 diff --git a/jpa-idempotent-repository/pom.xml b/jpa-idempotent-repository/pom.xml index 49bcba2f..a01f7382 100644 --- a/jpa-idempotent-repository/pom.xml +++ b/jpa-idempotent-repository/pom.xml @@ -30,13 +30,13 @@ Camel Quarkus Example :: JPA Idempotent Repository - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/jta-jpa/pom.xml b/jta-jpa/pom.xml index be69b05a..16e9a0c4 100644 --- a/jta-jpa/pom.xml +++ b/jta-jpa/pom.xml @@ -25,13 +25,13 @@ Camel Quarkus :: Examples :: JTA JPA Camel Quarkus Example :: JTA JPA - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom 2.29.0 1.13.0 diff --git a/kafka/pom.xml b/kafka/pom.xml index ff7f5747..b4a94bd7 100644 --- a/kafka/pom.xml +++ b/kafka/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Kafka - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/kamelet-chucknorris/pom.xml b/kamelet-chucknorris/pom.xml index 22bbe99e..091d5f61 100644 --- a/kamelet-chucknorris/pom.xml +++ b/kamelet-chucknorris/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Kamelet Chuck Norris - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/message-bridge/pom.xml b/message-bridge/pom.xml index 9ad71195..49c67f47 100644 --- a/message-bridge/pom.xml +++ b/message-bridge/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Configure XA Transactions and connection pooling - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/netty-custom-correlation/pom.xml b/netty-custom-correlation/pom.xml index fe2e5ffe..6f53116f 100644 --- a/netty-custom-correlation/pom.xml +++ b/netty-custom-correlation/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Communication with Netty over TCP - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/observability/pom.xml b/observability/pom.xml index 6a6a2440..5a7fb8f4 100644 --- a/observability/pom.xml +++ b/observability/pom.xml @@ -29,13 +29,13 @@ - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/openapi-contract-first/pom.xml b/openapi-contract-first/pom.xml index a591de9e..04ef48f7 100644 --- a/openapi-contract-first/pom.xml +++ b/openapi-contract-first/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: openapi-contract-first - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/platform-http-security-keycloak/pom.xml b/platform-http-security-keycloak/pom.xml index 04fbe8da..c3d5f0a9 100644 --- a/platform-http-security-keycloak/pom.xml +++ b/platform-http-security-keycloak/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Platform HTTP Security Keycloak - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/quarkus-rest-json/pom.xml b/quarkus-rest-json/pom.xml index 76d6d7de..c93764b5 100644 --- a/quarkus-rest-json/pom.xml +++ b/quarkus-rest-json/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Quarkus Rest Json - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/rest-json/pom.xml b/rest-json/pom.xml index 2cc81a15..7000755d 100644 --- a/rest-json/pom.xml +++ b/rest-json/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Rest Json - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/saga/pom.xml b/saga/pom.xml index e7d199b5..3b94239f 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -29,14 +29,14 @@ pom - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} 3.14.1 - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/spring-redis/pom.xml b/spring-redis/pom.xml index 7832acc7..966cb273 100644 --- a/spring-redis/pom.xml +++ b/spring-redis/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Send and receive messages from Redis - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/timer-log-main/pom.xml b/timer-log-main/pom.xml index ffffb1e5..64ae9192 100644 --- a/timer-log-main/pom.xml +++ b/timer-log-main/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Timer to Log Main - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/timer-log/pom.xml b/timer-log/pom.xml index f911a845..36b1374c 100644 --- a/timer-log/pom.xml +++ b/timer-log/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Timer to Log - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/variables/pom.xml b/variables/pom.xml index 60a2137d..8c144768 100644 --- a/variables/pom.xml +++ b/variables/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Variables - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8 diff --git a/vertx-websocket-chat/pom.xml b/vertx-websocket-chat/pom.xml index 76c1a530..3719e2b9 100644 --- a/vertx-websocket-chat/pom.xml +++ b/vertx-websocket-chat/pom.xml @@ -28,13 +28,13 @@ Camel Quarkus Example :: Implementing Websocket - 3.34.1 - 3.35.0-SNAPSHOT + 3.35.1 + ${quarkus.platform.version} - io.quarkus + io.quarkus.platform quarkus-bom - org.apache.camel.quarkus - camel-quarkus-bom + ${quarkus.platform.group-id} + quarkus-camel-bom UTF-8 UTF-8