From 4aabd06e5200154cf726dcc69f7516904d5dd00f Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 18:15:08 +0200 Subject: [PATCH 01/87] CAMEL-23789: Make AWS S3 component docs multi-DSL friendly (Wave 1) Convert processor-based examples to declarative setHeader/setBody DSL, add XML and YAML tabs for all route examples, resolve AWS2S3Constants to string header values, add Java-only markers for programmatic config, and convert streaming upload timestamp grouping examples to multi-DSL. Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/aws2-s3-component.adoc | 1426 +++++++++++++---- 1 file changed, 1076 insertions(+), 350 deletions(-) diff --git a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc index 0e02327ecb69e..6b2a2c3ab60c1 100644 --- a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc +++ b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc @@ -185,13 +185,54 @@ YAML:: To use AWS KMS to encrypt/decrypt data by using AWS infrastructure, you can use the options introduced in 2.21.x like in the following example +[tabs] +==== +Java:: ++ [source,java] ---- from("file:tmp/test?fileName=test.txt") - .setHeader(AWS2S3Constants.KEY, constant("testFile")) - .to("aws2-s3://mybucket?amazonS3Client=#client&useAwsKMS=true&awsKMSKeyId=3f0637ad-296a-3dfe-a796-e60654fb128c"); + .setHeader("CamelAwsS3Key", constant("testFile")) + .to("aws2-s3://mybucket?amazonS3Client=#client&useAwsKMS=true&awsKMSKeyId=3f0637ad-296a-3dfe-a796-e60654fb128c"); ---- +XML:: ++ +[source,xml] +---- + + + + testFile + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:tmp/test + parameters: + fileName: test.txt + steps: + - setHeader: + name: CamelAwsS3Key + constant: testFile + - to: + uri: aws2-s3://mybucket + parameters: + amazonS3Client: "#client" + useAwsKMS: true + awsKMSKeyId: "3f0637ad-296a-3dfe-a796-e60654fb128c" +---- +==== + +TIP: The Java example uses the string value `"CamelAwsS3Key"` directly. You can also use the Java constant `AWS2S3Constants.KEY`. + In this way, you'll ask S3 to use the KMS key 3f0637ad-296a-3dfe-a796-e60654fb128c, to encrypt the file test.txt. When you ask to download this file, the decryption will be done directly before the download. @@ -218,74 +259,213 @@ For more information about this you can look at https://docs.aws.amazon.com/sdk- - Single Upload: This operation will upload a file to S3 based on the body content +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camel.txt")) + .setBody(constant("Camel rocks!")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camel.txt"); - exchange.getIn().setBody("Camel rocks!"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camel.txt + Camel rocks! + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camel.txt" + - setBody: + constant: "Camel rocks!" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + - to: + uri: mock:result +---- +==== + This operation will upload the file camel.txt with the content "Camel rocks!" in the _mycamelbucket_ bucket - Multipart Upload: This operation will perform a multipart upload of a file to S3 based on the body content +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("empty.txt")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&multiPartUpload=true&autoCreateBucket=true&partSize=1048576") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "empty.txt"); - exchange.getIn().setBody(new File("src/empty.txt")); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&multiPartUpload=true&autoCreateBucket=true&partSize=1048576") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + empty.txt + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "empty.txt" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + multiPartUpload: true + autoCreateBucket: true + partSize: 1048576 + - to: + uri: mock:result +---- +==== + This operation will perform a multipart upload of the file empty.txt with based on the content the file src/empty.txt in the _mycamelbucket_ bucket - CopyObject: this operation copies an object from one bucket to a different one +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3BucketDestinationName", constant("camelDestinationBucket")) + .setHeader("CamelAwsS3Key", constant("camelKey")) + .setHeader("CamelAwsS3DestinationKey", constant("camelDestinationKey")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=copyObject") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.BUCKET_DESTINATION_NAME, "camelDestinationBucket"); - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - exchange.getIn().setHeader(AWS2S3Constants.DESTINATION_KEY, "camelDestinationKey"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=copyObject") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camelDestinationBucket + camelKey + camelDestinationKey + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3BucketDestinationName + constant: "camelDestinationBucket" + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - setHeader: + name: CamelAwsS3DestinationKey + constant: "camelDestinationKey" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: copyObject + - to: + uri: mock:result +---- +==== + This operation will copy the object with the name expressed in the header camelDestinationKey to the camelDestinationBucket bucket, from the bucket _mycamelbucket_. - DeleteObject: this operation deletes an object from a bucket +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camelKey")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=deleteObject") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=deleteObject") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camelKey + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: deleteObject + - to: + uri: mock:result +---- +==== + This operation will delete the object camelKey from the bucket _mycamelbucket_. - ListBuckets: this operation lists the buckets for this account in this region @@ -422,55 +602,161 @@ This operation will list the objects in the _mycamelbucket_ bucket - GetObject: this operation gets a single object in a specific bucket +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camelKey")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=getObject") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=getObject") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camelKey + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: getObject + - to: + uri: mock:result +---- +==== + This operation will return an S3Object instance related to the camelKey object in _mycamelbucket_ bucket. - GetObjectRange: this operation gets a single object range in a specific bucket +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camelKey")) + .setHeader("CamelAwsS3RangeStart", constant("0")) + .setHeader("CamelAwsS3RangeEnd", constant("9")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=getObjectRange") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - exchange.getIn().setHeader(AWS2S3Constants.RANGE_START, "0"); - exchange.getIn().setHeader(AWS2S3Constants.RANGE_END, "9"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=getObjectRange") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camelKey + 0 + 9 + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - setHeader: + name: CamelAwsS3RangeStart + constant: "0" + - setHeader: + name: CamelAwsS3RangeEnd + constant: "9" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: getObjectRange + - to: + uri: mock:result +---- +==== + This operation will return an S3Object instance related to the camelKey object in _mycamelbucket_ bucket, containing the bytes from 0 to 9. - CreateDownloadLink: this operation will return a download link through S3 Presigner +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camelKey")) + .to("aws2-s3://mycamelbucket?accessKey=xxx&secretKey=yyy®ion=region&operation=createDownloadLink") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - } - }) - .to("aws2-s3://mycamelbucket?accessKey=xxx&secretKey=yyy®ion=region&operation=createDownloadLink") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camelKey + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - to: + uri: aws2-s3://mycamelbucket + parameters: + accessKey: xxx + secretKey: yyy + region: region + operation: createDownloadLink + - to: + uri: mock:result +---- +==== + This operation will return a download link url for the file camel-key in the bucket _mycamelbucket_ and region _region_. Parameters (`accessKey`, `secretKey` and `region`) are mandatory for this operation, if S3 client is autowired from the registry. @@ -522,291 +808,468 @@ This operation will check if the bucket _mycamelbucket_ exists and is accessible - HeadObject: this operation retrieves metadata from an object without returning the object itself +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camelKey")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=headObject") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=headObject") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camelKey + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: headObject + - to: + uri: mock:result +---- +==== + This operation will return metadata about the object camelKey in the bucket _mycamelbucket_. - DeleteObjects: this operation deletes multiple objects from a bucket in a single request +NOTE: The `CamelAwsS3KeysToDelete` header requires a `List` value, which must be set from a bean or processor. + +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .process(exchange -> { + List keys = List.of("key1", "key2", "key3"); + exchange.getIn().setHeader("CamelAwsS3KeysToDelete", keys); + }) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=deleteObjects") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - List keys = Arrays.asList("key1", "key2", "key3"); - exchange.getIn().setHeader(AWS2S3Constants.KEYS_TO_DELETE, keys); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=deleteObjects") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + + + + ---- +YAML:: ++ [source,yaml] ---- -- from: - uri: direct:start - steps: - - process: - ref: myProcessor - - to: - uri: aws2-s3://mycamelbucket - parameters: - amazonS3Client: "#amazonS3Client" - operation: deleteObjects +- route: + from: + uri: direct:start + steps: + - process: + ref: deleteKeysProcessor + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: deleteObjects + - to: + uri: mock:result ---- +==== This operation will delete the objects with keys key1, key2, and key3 from the bucket _mycamelbucket_. - CreateUploadLink: this operation will return an upload link through S3 Presigner +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camelKey")) + .to("aws2-s3://mycamelbucket?accessKey=xxx&secretKey=yyy®ion=region&operation=createUploadLink") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - } - }) - .to("aws2-s3://mycamelbucket?accessKey=xxx&secretKey=yyy®ion=region&operation=createUploadLink") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camelKey + + + ---- +YAML:: ++ [source,yaml] ---- -- from: - uri: direct:start - steps: - - setHeader: - name: CamelAwsS3Key - constant: camelKey - - to: - uri: aws2-s3://mycamelbucket - parameters: - accessKey: xxx - secretKey: yyy - region: region - operation: createUploadLink +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - to: + uri: aws2-s3://mycamelbucket + parameters: + accessKey: xxx + secretKey: yyy + region: region + operation: createUploadLink + - to: + uri: mock:result ---- +==== This operation will return an upload link url for uploading to the bucket _mycamelbucket_. - RestoreObject: this operation restores an archived object from Glacier storage +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camelKey")) + .setHeader("CamelAwsS3RestoreDays", constant(1)) + .setHeader("CamelAwsS3RestoreTier", constant("Expedited")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=restoreObject") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - exchange.getIn().setHeader(AWS2S3Constants.RESTORE_DAYS, 1); - exchange.getIn().setHeader(AWS2S3Constants.RESTORE_TIER, "Expedited"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=restoreObject") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camelKey + 1 + Expedited + + + ---- +YAML:: ++ [source,yaml] ---- -- from: - uri: direct:start - steps: - - setHeader: - name: CamelAwsS3Key - constant: camelKey - - setHeader: - name: CamelAwsS3RestoreDays - constant: 1 - - setHeader: - name: CamelAwsS3RestoreTier - constant: Expedited - - to: - uri: aws2-s3://mycamelbucket - parameters: - amazonS3Client: "#amazonS3Client" - operation: restoreObject +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - setHeader: + name: CamelAwsS3RestoreDays + constant: 1 + - setHeader: + name: CamelAwsS3RestoreTier + constant: "Expedited" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: restoreObject + - to: + uri: mock:result ---- +==== This operation will restore the archived object camelKey from Glacier for 1 day using expedited retrieval. - GetObjectTagging: this operation retrieves the tags associated with an object +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camelKey")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=getObjectTagging") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=getObjectTagging") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camelKey + + + ---- +YAML:: ++ [source,yaml] ---- -- from: - uri: direct:start - steps: - - setHeader: - name: CamelAwsS3Key - constant: camelKey - - to: - uri: aws2-s3://mycamelbucket - parameters: - amazonS3Client: "#amazonS3Client" - operation: getObjectTagging +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: getObjectTagging + - to: + uri: mock:result ---- +==== This operation will return the tags for object camelKey in the bucket _mycamelbucket_. - PutObjectTagging: this operation sets tags on an object +NOTE: The `CamelAwsS3ObjectTags` header requires a `Map` value, which must be set from a bean or processor. + +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - Map tags = new HashMap<>(); - tags.put("Environment", "Production"); - tags.put("Owner", "TeamA"); - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - exchange.getIn().setHeader(AWS2S3Constants.OBJECT_TAGS, tags); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=putObjectTagging") - .to("mock:result"); +from("direct:start") + .process(exchange -> { + Map tags = Map.of("Environment", "Production", "Owner", "TeamA"); + exchange.getIn().setHeader("CamelAwsS3Key", "camelKey"); + exchange.getIn().setHeader("CamelAwsS3ObjectTags", tags); + }) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=putObjectTagging") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + ---- +YAML:: ++ [source,yaml] ---- -- from: - uri: direct:start - steps: - - process: - ref: myProcessor - - to: - uri: aws2-s3://mycamelbucket - parameters: - amazonS3Client: "#amazonS3Client" - operation: putObjectTagging +- route: + from: + uri: direct:start + steps: + - process: + ref: objectTagsProcessor + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: putObjectTagging + - to: + uri: mock:result ---- +==== This operation will set tags on the object camelKey in the bucket _mycamelbucket_. - DeleteObjectTagging: this operation deletes all tags from an object +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camelKey")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=deleteObjectTagging") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=deleteObjectTagging") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camelKey + + + ---- +YAML:: ++ [source,yaml] ---- -- from: - uri: direct:start - steps: - - setHeader: - name: CamelAwsS3Key - constant: camelKey - - to: - uri: aws2-s3://mycamelbucket - parameters: - amazonS3Client: "#amazonS3Client" - operation: deleteObjectTagging +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: deleteObjectTagging + - to: + uri: mock:result ---- +==== This operation will delete all tags from the object camelKey in the bucket _mycamelbucket_. - GetObjectAcl: this operation retrieves the access control list (ACL) for an object +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camelKey")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=getObjectAcl") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=getObjectAcl") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + camelKey + + + ---- +YAML:: ++ [source,yaml] ---- -- from: - uri: direct:start - steps: - - setHeader: - name: CamelAwsS3Key - constant: camelKey - - to: - uri: aws2-s3://mycamelbucket - parameters: - amazonS3Client: "#amazonS3Client" - operation: getObjectAcl +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: getObjectAcl + - to: + uri: mock:result ---- +==== This operation will return the ACL for object camelKey in the bucket _mycamelbucket_. - PutObjectAcl: this operation sets the access control list (ACL) for an object +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.KEY, "camelKey"); - exchange.getIn().setHeader(AWS2S3Constants.CANNED_ACL, "PublicRead"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=putObjectAcl") - .to("mock:result"); +from("direct:start") + .setHeader("CamelAwsS3Key", constant("camelKey")) + .setHeader("CamelAwsS3CannedAcl", constant("PublicRead")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=putObjectAcl") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + camelKey + PublicRead + + + ---- +YAML:: ++ [source,yaml] ---- -- from: - uri: direct:start - steps: - - setHeader: - name: CamelAwsS3Key - constant: camelKey - - setHeader: - name: CamelAwsS3CannedAcl - constant: PublicRead - - to: - uri: aws2-s3://mycamelbucket - parameters: - amazonS3Client: "#amazonS3Client" - operation: putObjectAcl +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3Key + constant: "camelKey" + - setHeader: + name: CamelAwsS3CannedAcl + constant: "PublicRead" + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: putObjectAcl + - to: + uri: mock:result ---- +==== This operation will set the ACL to public-read for object camelKey in the bucket _mycamelbucket_. @@ -900,35 +1363,54 @@ This operation will return the tags for the bucket _mycamelbucket_. - PutBucketTagging: this operation sets tags on a bucket +NOTE: The `CamelAwsS3BucketTags` header requires a `Map` value, which must be set from a bean or processor. + +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - Map tags = new HashMap<>(); - tags.put("Project", "CamelIntegration"); - tags.put("CostCenter", "Engineering"); - exchange.getIn().setHeader(AWS2S3Constants.BUCKET_TAGS, tags); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=putBucketTagging") - .to("mock:result"); +from("direct:start") + .process(exchange -> { + Map tags = Map.of("Project", "CamelIntegration", "CostCenter", "Engineering"); + exchange.getIn().setHeader("CamelAwsS3BucketTags", tags); + }) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=putBucketTagging") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + ---- +YAML:: ++ [source,yaml] ---- -- from: - uri: direct:start - steps: - - process: - ref: myProcessor - - to: - uri: aws2-s3://mycamelbucket - parameters: - amazonS3Client: "#amazonS3Client" - operation: putBucketTagging +- route: + from: + uri: direct:start + steps: + - process: + ref: bucketTagsProcessor + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: putBucketTagging + - to: + uri: mock:result ---- +==== This operation will set tags on the bucket _mycamelbucket_. @@ -1022,33 +1504,52 @@ This operation will return the versioning configuration for the bucket _mycamelb - PutBucketVersioning: this operation sets the versioning configuration of a bucket +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { +from("direct:start") + .setHeader("CamelAwsS3VersioningStatus", constant("Enabled")) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=putBucketVersioning") + .to("mock:result"); +---- - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(AWS2S3Constants.VERSIONING_STATUS, "Enabled"); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=putBucketVersioning") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + + Enabled + + + + ---- +YAML:: ++ [source,yaml] ---- -- from: - uri: direct:start - steps: - - setHeader: - name: CamelAwsS3VersioningStatus - constant: Enabled - - to: - uri: aws2-s3://mycamelbucket - parameters: - amazonS3Client: "#amazonS3Client" - operation: putBucketVersioning +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsS3VersioningStatus + constant: Enabled + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: putBucketVersioning + - to: + uri: mock:result ---- +==== This operation will enable versioning on the bucket _mycamelbucket_. @@ -1098,40 +1599,57 @@ This operation will return the bucket policy for _mycamelbucket_ as a JSON strin - PutBucketPolicy: this operation sets the policy on a bucket +NOTE: The `CamelAwsS3BucketPolicy` header requires a JSON policy string, which must be set from a bean or processor. + +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - String policy = "{" - + "\"Version\": \"2012-10-17\"," - + "\"Statement\": [{" - + "\"Effect\": \"Allow\"," - + "\"Principal\": \"*\"," - + "\"Action\": \"s3:GetObject\"," - + "\"Resource\": \"arn:aws:s3:::mycamelbucket/*\"" - + "}]}"; - exchange.getIn().setHeader(AWS2S3Constants.BUCKET_POLICY, policy); - } - }) - .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=putBucketPolicy") - .to("mock:result"); +from("direct:start") + .process(exchange -> { + String policy = """ + {"Version": "2012-10-17", "Statement": [{"Effect": "Allow", \ + "Principal": "*", "Action": "s3:GetObject", \ + "Resource": "arn:aws:s3:::mycamelbucket/*"}]}"""; + exchange.getIn().setHeader("CamelAwsS3BucketPolicy", policy); + }) + .to("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&operation=putBucketPolicy") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + ---- +YAML:: ++ [source,yaml] ---- -- from: - uri: direct:start - steps: - - process: - ref: myProcessor - - to: - uri: aws2-s3://mycamelbucket - parameters: - amazonS3Client: "#amazonS3Client" - operation: putBucketPolicy +- route: + from: + uri: direct:start + steps: + - process: + ref: bucketPolicyProcessor + - to: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + operation: putBucketPolicy + - to: + uri: mock:result ---- +==== This operation will set a bucket policy on _mycamelbucket_. @@ -1269,15 +1787,21 @@ Additionally, streaming upload mode supports timestamp-based file grouping, whic As an example: +._Java-only: Endpoint DSL builder style_ + [source,java] ---- from(kafka("topic1").brokers("localhost:9092")) .log("Kafka Message is: ${body}") - .to(aws2S3("camel-bucket").streamingUploadMode(true).batchMessageNumber(25).namingStrategy(AWS2S3EndpointBuilderFactory.AWSS3NamingStrategyEnum.progressive).keyName("{{kafkaTopic1}}/{{kafkaTopic1}}.txt")); + .to(aws2S3("camel-bucket").streamingUploadMode(true).batchMessageNumber(25) + .namingStrategy(AWS2S3EndpointBuilderFactory.AWSS3NamingStrategyEnum.progressive) + .keyName("{{kafkaTopic1}}/{{kafkaTopic1}}.txt")); from(kafka("topic2").brokers("localhost:9092")) .log("Kafka Message is: ${body}") - .to(aws2S3("camel-bucket").streamingUploadMode(true).batchMessageNumber(25).namingStrategy(AWS2S3EndpointBuilderFactory.AWSS3NamingStrategyEnum.random).keyName("{{kafkaTopic2}}/{{kafkaTopic2}}.txt")); + .to(aws2S3("camel-bucket").streamingUploadMode(true).batchMessageNumber(25) + .namingStrategy(AWS2S3EndpointBuilderFactory.AWSS3NamingStrategyEnum.random) + .keyName("{{kafkaTopic2}}/{{kafkaTopic2}}.txt")); ---- The default size for a batch is 1 Mb, but you can adjust it according to your requirements. @@ -1315,11 +1839,16 @@ In this way, the upload completion will be passed on three tiers: the timeout, t As an example: +._Java-only: Endpoint DSL builder style_ + [source,java] ---- from(kafka("topic1").brokers("localhost:9092")) .log("Kafka Message is: ${body}") - .to(aws2S3("camel-bucket").streamingUploadMode(true).batchMessageNumber(25).streamingUploadTimeout(10000).namingStrategy(AWS2S3EndpointBuilderFactory.AWSS3NamingStrategyEnum.progressive).keyName("{{kafkaTopic1}}/{{kafkaTopic1}}.txt")); + .to(aws2S3("camel-bucket").streamingUploadMode(true).batchMessageNumber(25) + .streamingUploadTimeout(10000) + .namingStrategy(AWS2S3EndpointBuilderFactory.AWSS3NamingStrategyEnum.progressive) + .keyName("{{kafkaTopic1}}/{{kafkaTopic1}}.txt")); ---- In this case, the upload will be completed after 10 seconds. @@ -1346,45 +1875,167 @@ Files are automatically named using a timestamp-based pattern that includes the Basic timestamp grouping with 5-minute windows: +[tabs] +==== +Java:: ++ [source,java] ---- from("timer:messages?period=10000") .setHeader(Exchange.MESSAGE_TIMESTAMP, simple("${date:now:timestamp}")) .setBody(constant("Message with timestamp")) - .to("aws2-s3://my-bucket?streamingUploadMode=true" - + "×tampGroupingEnabled=true" - + "×tampWindowSizeMillis=300000" - + "&keyName=grouped-messages.txt"); + .to("aws2-s3://my-bucket?streamingUploadMode=true×tampGroupingEnabled=true×tampWindowSizeMillis=300000&keyName=grouped-messages.txt"); +---- + +XML:: ++ +[source,xml] +---- + + + + ${date:now:timestamp} + + + Message with timestamp + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: timer:messages + parameters: + period: 10000 + steps: + - setHeader: + name: CamelMessageTimestamp + simple: "${date:now:timestamp}" + - setBody: + constant: Message with timestamp + - to: + uri: aws2-s3://my-bucket + parameters: + streamingUploadMode: true + timestampGroupingEnabled: true + timestampWindowSizeMillis: 300000 + keyName: grouped-messages.txt ---- +==== Custom window size (1 minute) with custom header name: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:timestamped") .setHeader("MyTimestamp", simple("${date:now:timestamp}")) - .setBody("Custom timestamped message") - .to("aws2-s3://my-bucket?streamingUploadMode=true" - + "×tampGroupingEnabled=true" - + "×tampWindowSizeMillis=60000" - + "×tampHeaderName=MyTimestamp" - + "&keyName=custom-grouped.txt"); + .setBody(constant("Custom timestamped message")) + .to("aws2-s3://my-bucket?streamingUploadMode=true×tampGroupingEnabled=true×tampWindowSizeMillis=60000×tampHeaderName=MyTimestamp&keyName=custom-grouped.txt"); +---- + +XML:: ++ +[source,xml] +---- + + + + ${date:now:timestamp} + + + Custom timestamped message + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:timestamped + steps: + - setHeader: + name: MyTimestamp + simple: "${date:now:timestamp}" + - setBody: + constant: Custom timestamped message + - to: + uri: aws2-s3://my-bucket + parameters: + streamingUploadMode: true + timestampGroupingEnabled: true + timestampWindowSizeMillis: 60000 + timestampHeaderName: MyTimestamp + keyName: custom-grouped.txt ---- +==== Large files with multipart and timestamp grouping: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:large-timestamped") .setHeader(Exchange.MESSAGE_TIMESTAMP, simple("${date:now:timestamp}")) - .setBody("Large message content...") - .to("aws2-s3://my-bucket?streamingUploadMode=true" - + "×tampGroupingEnabled=true" - + "×tampWindowSizeMillis=1800000" // 30 minutes - + "&multiPartUpload=true" - + "&partSize=5242880" // 5MB parts - + "&keyName=large-grouped.txt"); + .setBody(constant("Large message content...")) + .to("aws2-s3://my-bucket?streamingUploadMode=true×tampGroupingEnabled=true×tampWindowSizeMillis=1800000&multiPartUpload=true&partSize=5242880&keyName=large-grouped.txt"); +---- + +XML:: ++ +[source,xml] +---- + + + + ${date:now:timestamp} + + + Large message content... + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:large-timestamped + steps: + - setHeader: + name: CamelMessageTimestamp + simple: "${date:now:timestamp}" + - setBody: + constant: "Large message content..." + - to: + uri: aws2-s3://my-bucket + parameters: + streamingUploadMode: true + timestampGroupingEnabled: true + timestampWindowSizeMillis: 1800000 + multiPartUpload: true + partSize: 5242880 + keyName: large-grouped.txt ---- +==== ===== File Naming @@ -1485,26 +2136,87 @@ The options are `destinationBucketPrefix` and `destinationBucketSuffix`. Both options support the xref:languages:simple-language.adoc[Simple] expression language. Wrap an expression in `RAW()` to prevent the Camel URI parser from interpreting special characters: +[tabs] +==== +Java:: ++ [source,java] ---- - from("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&moveAfterRead=true" - + "&destinationBucket=myothercamelbucket" - + "&destinationBucketPrefix=RAW(pre-)&destinationBucketSuffix=RAW(-suff)") - .to("mock:result"); +from("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&moveAfterRead=true&destinationBucket=myothercamelbucket&destinationBucketPrefix=RAW(pre-)&destinationBucketSuffix=RAW(-suff)") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + moveAfterRead: true + destinationBucket: myothercamelbucket + destinationBucketPrefix: "RAW(pre-)" + destinationBucketSuffix: "RAW(-suff)" + steps: + - to: + uri: mock:result ---- +==== In this case, an object named `test` is moved to `myothercamelbucket` with the key `pre-test-suff`. Using a Simple expression, you can build dynamic paths at runtime. The following example organises moved objects by date: +[tabs] +==== +Java:: ++ [source,java] ---- - from("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&moveAfterRead=true" - + "&destinationBucket=myothercamelbucket" - + "&destinationBucketPrefix=RAW(${date:now:yyyy/MM/dd}/)") - .to("mock:result"); +from("aws2-s3://mycamelbucket?amazonS3Client=#amazonS3Client&moveAfterRead=true&destinationBucket=myothercamelbucket&destinationBucketPrefix=RAW(${date:now:yyyy/MM/dd}/)") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: aws2-s3://mycamelbucket + parameters: + amazonS3Client: "#amazonS3Client" + moveAfterRead: true + destinationBucket: myothercamelbucket + destinationBucketPrefix: "RAW(${date:now:yyyy/MM/dd}/)" + steps: + - to: + uri: mock:result ---- +==== An object named `report.csv` consumed on 2026-05-19 is moved with the key `2026/05/19/report.csv`. Expressions are evaluated once per exchange, so each message can produce a different destination key. @@ -1687,6 +2399,8 @@ This consumer will only process files when a corresponding .done file exists in We introduced also the customer key support (an alternative of using KMS). The following code shows an example. +._Java-only: programmatic customer key encryption setup_ + [source,java] ---- String key = UUID.randomUUID().toString(); @@ -1697,7 +2411,7 @@ String b64KeyMd5 = Md5Utils.md5AsBase64(secretKey); String awsEndpoint = "aws2-s3://mycamel?autoCreateBucket=false&useCustomerKey=true&customerKeyId=RAW(" + b64Key + ")&customerKeyMD5=RAW(" + b64KeyMd5 + ")&customerAlgorithm=" + AES256.name(); from("direct:putObject") - .setHeader(AWS2S3Constants.KEY, constant("test.txt")) + .setHeader("CamelAwsS3Key", constant("test.txt")) .setBody(constant("Test")) .to(awsEndpoint); ---- @@ -1705,14 +2419,16 @@ from("direct:putObject") === Using a POJO as body Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as the body. -In AWS S3 there are multiple operations you can submit, as an example for List brokers request, you can do something like: +In AWS S3 there are multiple operations you can submit, as an example for List objects request, you can do something like: + +._Java-only: POJO request requires building AWS SDK request objects_ [source,java] --------------------------- +---- from("direct:aws2-s3") -.setBody(ListObjectsV2Request.builder().bucket(bucketName).build()) - .to("aws2-s3://test?amazonS3Client=#amazonS3Client&operation=listObjects&pojoRequest=true") --------------------------- + .setBody(ListObjectsV2Request.builder().bucket(bucketName).build()) + .to("aws2-s3://test?amazonS3Client=#amazonS3Client&operation=listObjects&pojoRequest=true"); +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -1721,13 +2437,17 @@ In this way, you'll pass the request directly without the need of passing header Sometimes you would want to perform some advanced configuration using AWS2S3Configuration, which also allows to set the S3 client. You can create and set the S3 client in the component configuration as shown in the following example +._Java-only: programmatic S3 client creation_ + [source,java] ---- String awsBucketAccessKey = "your_access_key"; String awsBucketSecretKey = "your_secret_key"; -S3Client s3Client = S3Client.builder().credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(awsBucketAccessKey, awsBucketSecretKey))) - .region(Region.US_EAST_1).build(); +S3Client s3Client = S3Client.builder() + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create(awsBucketAccessKey, awsBucketSecretKey))) + .region(Region.US_EAST_1).build(); AWS2S3Configuration configuration = new AWS2S3Configuration(); configuration.setAmazonS3Client(s3Client); @@ -1739,6 +2459,8 @@ configuration.setRegion("us-east-1"); Now you can configure the S3 component (using the configuration object created above) and add it to the registry in the configure method before initialization of routes. +._Java-only: programmatic component registration_ + [source,java] ---- AWS2S3Component s3Component = new AWS2S3Component(getContext()); @@ -1751,15 +2473,19 @@ Now your component will be used for all the operations implemented in camel rout === Note about using this component for storing and retrieving objects from/to Dell ECS (Elastic Cloud Solutions) -For storing and retrieving objects from/to Dell ECS, both of the `forcePathStyle` and `overrideEndpoint` options need to be set to `true` and using the `uriEndpointOverride` you need to provide your own ECS endpoint. +For storing and retrieving objects from/to Dell ECS, both of the `forcePathStyle` and `overrideEndpoint` options need to be set to `true` and using the `uriEndpointOverride` you need to provide your own ECS endpoint. + +._Java-only: programmatic Dell ECS configuration_ [source,java] ---- String awsBucketAccessKey = "your_access_key"; String awsBucketSecretKey = "your_secret_key"; -S3Client s3Client = S3Client.builder().credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(awsBucketAccessKey, awsBucketSecretKey))) - .region(Region.US_EAST_1).build(); +S3Client s3Client = S3Client.builder() + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create(awsBucketAccessKey, awsBucketSecretKey))) + .region(Region.US_EAST_1).build(); AWS2S3Configuration configuration = new AWS2S3Configuration(); configuration.setForcePathStyle(true); From a86b60cca0d2259a390ce7e7b52870e14285ba61 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 18:25:37 +0200 Subject: [PATCH 02/87] CAMEL-23789: Make Azure Storage Blob docs multi-DSL friendly (Wave 1) Convert processor-based examples to declarative setHeader/setBody DSL, add XML and YAML tabs for all route examples, resolve all BlobConstants to string header values, add Java-only markers for programmatic config, and fix string concatenation in URIs. Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../docs/azure-storage-blob-component.adoc | 1582 +++++++++++++---- 1 file changed, 1205 insertions(+), 377 deletions(-) diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc b/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc index 3024456ed44f4..ce27bca299518 100644 --- a/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc +++ b/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc @@ -370,24 +370,32 @@ Java:: + [source,java] ---- -// Delete blob after successful processing from("azure-storage-blob://camelazure/container1?deleteAfterRead=true&accessKey=RAW(yourAccessKey)") .log("Processing blob: ${header.CamelAzureStorageBlobBlobName}") .to("direct:processBlob"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + YAML:: + [source,yaml] ---- - route: - id: azure-blob-delete-after-read from: uri: azure-storage-blob://camelazure/container1 parameters: deleteAfterRead: true - credentialType: SHARED_ACCOUNT_KEY - accessKey: "RAW({{azure.accessKey}})" + accessKey: "RAW(yourAccessKey)" steps: - log: message: "Processing blob: ${header.CamelAzureStorageBlobBlobName}" @@ -410,25 +418,33 @@ Java:: + [source,java] ---- -// Move blob to archive container after processing from("azure-storage-blob://camelazure/incoming?moveAfterRead=true&destinationContainer=archive&accessKey=RAW(yourAccessKey)") .log("Processing blob: ${header.CamelAzureStorageBlobBlobName}") .to("direct:processBlob"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + YAML:: + [source,yaml] ---- - route: - id: azure-blob-move-after-read from: uri: azure-storage-blob://camelazure/incoming parameters: moveAfterRead: true destinationContainer: archive - credentialType: SHARED_ACCOUNT_KEY - accessKey: "RAW({{azure.accessKey}})" + accessKey: "RAW(yourAccessKey)" steps: - log: message: "Processing blob: ${header.CamelAzureStorageBlobBlobName}" @@ -445,26 +461,27 @@ Java:: + [source,java] ---- -// Move blob with prefix and suffix transformation -// Source: incoming/data.csv -> Destination: processed/data.csv.done -from("azure-storage-blob://camelazure/source" - + "?moveAfterRead=true" - + "&destinationContainer=archive" - + "&prefix=incoming/" - + "&removePrefixOnMove=true" - + "&destinationBlobPrefix=processed/" - + "&destinationBlobSuffix=.done" - + "&accessKey=RAW(yourAccessKey)") +from("azure-storage-blob://camelazure/source?moveAfterRead=true&destinationContainer=archive&prefix=incoming/&removePrefixOnMove=true&destinationBlobPrefix=processed/&destinationBlobSuffix=.done&accessKey=RAW(yourAccessKey)") .log("Processing: ${header.CamelAzureStorageBlobBlobName}") .to("direct:processBlob"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + YAML:: + [source,yaml] ---- - route: - id: azure-blob-move-with-transform from: uri: azure-storage-blob://camelazure/source parameters: @@ -474,8 +491,7 @@ YAML:: removePrefixOnMove: true destinationBlobPrefix: "processed/" destinationBlobSuffix: ".done" - credentialType: SHARED_ACCOUNT_KEY - accessKey: "RAW({{azure.accessKey}})" + accessKey: "RAW(yourAccessKey)" steps: - log: message: "Processing: ${header.CamelAzureStorageBlobBlobName}" @@ -505,190 +521,174 @@ The following options control the move behavior: === Producer Operations Examples - `listBlobContainers`: -[source,java] ----- -from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(BlobConstants.LIST_BLOB_CONTAINERS_OPTIONS, new ListBlobContainersOptions().setMaxResultsPerPage(10)); - }) - .to("azure-storage-blob://camelazure?operation=listBlobContainers&client&serviceClient=#client") - .to("mock:result"); ----- +NOTE: The `CamelAzureStorageBlobListBlobContainersOptions` header requires a `ListBlobContainersOptions` object, which must be set from a bean or processor. -- `createBlobContainer`: +._Java-only: programmatic ListBlobContainersOptions_ [source,java] ---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(BlobConstants.BLOB_CONTAINER_NAME, "newContainerName"); - }) - .to("azure-storage-blob://camelazure/container1?operation=createBlobContainer&serviceClient=#client") - .to("mock:result"); + .process(exchange -> { + exchange.getIn().setHeader("CamelAzureStorageBlobListBlobContainersOptions", + new ListBlobContainersOptions().setMaxResultsPerPage(10)); + }) + .to("azure-storage-blob://camelazure?operation=listBlobContainers&serviceClient=#client") + .to("mock:result"); ---- -- `deleteBlobContainer`: +- `createBlobContainer`: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(BlobConstants.BLOB_CONTAINER_NAME, "overridenName"); - }) - .to("azure-storage-blob://camelazure/container1?operation=deleteBlobContainer&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobBlobContainerName", constant("newContainerName")) + .to("azure-storage-blob://camelazure/container1?operation=createBlobContainer&serviceClient=#client") + .to("mock:result"); ---- -- `listBlobs`: - -[source,java] +XML:: ++ +[source,xml] ---- -from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(BlobConstants.BLOB_CONTAINER_NAME, "overridenName"); - }) - .to("azure-storage-blob://camelazure/container1?operation=listBlobs&serviceClient=#client") - .to("mock:result"); + + + + newContainerName + + + + ---- - -- `listBlobVersions`: - -Returns every version of every blob in the container. Versioning must be enabled on the storage -account. Each `BlobItem` in the result carries its own `versionId` and `isCurrentVersion` flag. -The `prefix` and `regex` options can be used to narrow the result down to a single blob name. - -[source,java] +YAML:: ++ +[source,yaml] ---- -from("direct:start") - .setHeader(BlobConstants.PREFIX, constant("invoice.pdf")) - .to("azure-storage-blob://camelazure/container1?operation=listBlobVersions&serviceClient=#client") - .process(exchange -> { - @SuppressWarnings("unchecked") - List versions = exchange.getMessage().getBody(List.class); - for (BlobItem v : versions) { - System.out.printf("%s versionId=%s isCurrent=%s%n", - v.getName(), v.getVersionId(), v.isCurrentVersion()); - } - }) - .to("mock:result"); +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageBlobBlobContainerName + constant: newContainerName + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + operation: createBlobContainer + serviceClient: "#client" + - to: + uri: mock:result ---- +==== +- `deleteBlobContainer`: -- `getBlob`: - -We can either set an `outputStream` in the exchange body and write the data to it. E.g.: +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(BlobConstants.BLOB_CONTAINER_NAME, "overridenName"); - - // set our body - exchange.getIn().setBody(outputStream); - }) - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=getBlob&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobBlobContainerName", constant("overridenName")) + .to("azure-storage-blob://camelazure/container1?operation=deleteBlobContainer&serviceClient=#client") + .to("mock:result"); ---- -If we don't set a body, then this operation will give us an `InputStream` instance which can proceeded further downstream: - -[source,java] +XML:: ++ +[source,xml] ---- - -from("direct:start") - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=getBlob&serviceClient=#client") - .process(exchange -> { - InputStream inputStream = exchange.getMessage().getBody(InputStream.class); - // We use Apache common IO for simplicity, but you are free to do whatever dealing - // with inputStream - System.out.println(IOUtils.toString(inputStream, StandardCharsets.UTF_8.name())); - }) - .to("mock:result"); + + + + overridenName + + + + ---- -- `deleteBlob`: - -[source,java] +YAML:: ++ +[source,yaml] ---- - -from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(BlobConstants.BLOB_NAME, "overridenName"); - }) - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=deleteBlob&serviceClient=#client") - .to("mock:result"); +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageBlobBlobContainerName + constant: overridenName + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + operation: deleteBlobContainer + serviceClient: "#client" + - to: + uri: mock:result ---- +==== -- `downloadBlobToFile`: +- `listBlobs`: +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(BlobConstants.BLOB_NAME, "overridenName"); - }) - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=downloadBlobToFile&fileDir=/var/mydir&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobBlobContainerName", constant("overridenName")) + .to("azure-storage-blob://camelazure/container1?operation=listBlobs&serviceClient=#client") + .to("mock:result"); ---- -- `downloadLink` - -[source,java] +XML:: ++ +[source,xml] ---- - -from("direct:start") - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=downloadLink&serviceClient=#client") - .process(exchange -> { - String link = exchange.getMessage().getHeader(BlobConstants.DOWNLOAD_LINK, String.class); - System.out.println("My link " + link); - }) - .to("mock:result"); + + + + overridenName + + + + ---- -- `uploadBlockBlob` - -[source,java] +YAML:: ++ +[source,yaml] ---- - -from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(BlobConstants.BLOB_NAME, "overridenName"); - exchange.getIn().setBody("Block Blob"); - }) - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=uploadBlockBlob&serviceClient=#client") - .to("mock:result"); +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageBlobBlobContainerName + constant: overridenName + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + operation: listBlobs + serviceClient: "#client" + - to: + uri: mock:result ---- +==== -- `uploadBlockBlobChunked` -This operation is recommended for uploading large files (larger than 256MB) as it uses chunked parallel uploads for memory efficiency. +- `listBlobVersions`: + +Returns every version of every blob in the container. Versioning must be enabled on the storage +account. Each `BlobItem` in the result carries its own `versionId` and `isCurrentVersion` flag. +The `prefix` and `regex` options can be used to narrow the result down to a single blob name. [tabs] ==== @@ -696,16 +696,26 @@ Java:: + [source,java] ---- -// Upload large files from the file component -from("file://data?noop=true") - .log("Uploading file: ${header.CamelFileName}") - .to("azure-storage-blob://camelazure/container1" + - "?blobName=${header.CamelFileName}" + - "&operation=uploadBlockBlobChunked" + - "&blockSize=52428800" + // 50MB blocks - "&maxConcurrency=4" + // 4 parallel uploads - "&serviceClient=#client") - .log("Upload completed: ${header.CamelFileName}"); +from("direct:start") + .setHeader("CamelAzureStorageBlobPrefix", constant("invoice.pdf")) + .to("azure-storage-blob://camelazure/container1?operation=listBlobVersions&serviceClient=#client") + .log("${body}") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + invoice.pdf + + + + + ---- YAML:: @@ -713,213 +723,749 @@ YAML:: [source,yaml] ---- - route: - id: azure-blob-upload from: - uri: file://data - parameters: - noop: true + uri: direct:start steps: - - log: - message: "Uploading file: ${header.CamelFileName}" - - toD: - uri: "azure-storage-blob://{{azure.account}}/{{azure.container}}" + - setHeader: + name: CamelAzureStorageBlobPrefix + constant: invoice.pdf + - to: + uri: azure-storage-blob://camelazure/container1 parameters: - blobName: "${header.CamelFileName}" - operation: uploadBlockBlobChunked - blockSize: 52428800 # 50MB blocks - maxConcurrency: 4 # 4 parallel uploads - credentialType: SHARED_ACCOUNT_KEY - accessKey: "RAW({{azure.accessKey}})" + operation: listBlobVersions + serviceClient: "#client" - log: - message: "Upload completed: ${header.CamelFileName}" + message: "${body}" + - to: + uri: mock:result ---- ==== -The `blockSize` and `maxConcurrency` options control memory usage and upload speed: -* `blockSize`: Size of each chunk (default: 4MB, max: 4000MB). Larger blocks = fewer requests but more memory. -* `maxConcurrency`: Number of parallel uploads (default: auto-detected based on CPU cores). Higher = faster but more memory. -* Memory usage is approximately `blockSize × maxConcurrency`. +- `getBlob`: -- `stageBlockBlobList` +We can either set an `outputStream` in the exchange body and write the data to it: + +._Java-only: programmatic OutputStream handling_ [source,java] ---- - from("direct:start") - .process(exchange -> { - final List blocks = new LinkedList<>(); - blocks.add(BlobBlock.createBlobBlock(new ByteArrayInputStream("Hello".getBytes()))); - blocks.add(BlobBlock.createBlobBlock(new ByteArrayInputStream("From".getBytes()))); - blocks.add(BlobBlock.createBlobBlock(new ByteArrayInputStream("Camel".getBytes()))); - - exchange.getIn().setBody(blocks); - }) - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=stageBlockBlobList&serviceClient=#client") - .to("mock:result"); + .process(exchange -> { + exchange.getIn().setHeader("CamelAzureStorageBlobBlobContainerName", "overridenName"); + exchange.getIn().setBody(outputStream); + }) + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=getBlob&serviceClient=#client") + .to("mock:result"); ---- -- `commitBlockBlobList` +If we don't set a body, then this operation will give us an `InputStream` instance which can be processed further downstream: +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start") - .process(exchange -> { - // We assume here you have the knowledge of these blocks you want to commit - final List blockIds = new LinkedList<>(); - blockIds.add(new Block().setName("id-1")); - blockIds.add(new Block().setName("id-2")); - blockIds.add(new Block().setName("id-3")); - - exchange.getIn().setBody(blockIds); - }) - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=commitBlockBlobList&serviceClient=#client") - .to("mock:result"); + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=getBlob&serviceClient=#client") + .log("${body}") + .to("mock:result"); ---- -- `getBlobBlockList` - -[source,java] +XML:: ++ +[source,xml] ---- - -from("direct:start") - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=getBlobBlockList&serviceClient=#client") - .log("${body}") - .to("mock:result"); + + + + + + ---- - -- `createAppendBlob` - -[source,java] +YAML:: ++ +[source,yaml] ---- - -from("direct:start") - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=createAppendBlob&serviceClient=#client") - .to("mock:result"); +- route: + from: + uri: direct:start + steps: + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: blob + operation: getBlob + serviceClient: "#client" + - log: + message: "${body}" + - to: + uri: mock:result ---- +==== -- `commitAppendBlob` +- `deleteBlob`: +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start") - .process(exchange -> { - final String data = "Hello world from my awesome tests!"; - final InputStream dataStream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)); - - exchange.getIn().setBody(dataStream); - - // of course, you can set whatever headers you like, refer to the headers section to learn more - }) - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=commitAppendBlob&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobBlobName", constant("overridenName")) + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=deleteBlob&serviceClient=#client") + .to("mock:result"); ---- -- `createPageBlob` - -[source,java] +XML:: ++ +[source,xml] ---- - -from("direct:start") - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=createPageBlob&serviceClient=#client") - .to("mock:result"); + + + + overridenName + + + + ---- -- `uploadPageBlob` - -[source,java] +YAML:: ++ +[source,yaml] ---- - -from("direct:start") - .process(exchange -> { - byte[] dataBytes = new byte[512]; // we set range for the page from 0-511 - new Random().nextBytes(dataBytes); - final InputStream dataStream = new ByteArrayInputStream(dataBytes); - final PageRange pageRange = new PageRange().setStart(0).setEnd(511); - - exchange.getIn().setHeader(BlobConstants.PAGE_BLOB_RANGE, pageRange); - exchange.getIn().setBody(dataStream); - }) - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=uploadPageBlob&serviceClient=#client") - .to("mock:result"); +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageBlobBlobName + constant: overridenName + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: blob + operation: deleteBlob + serviceClient: "#client" + - to: + uri: mock:result ---- +==== -- `resizePageBlob` +- `downloadBlobToFile`: +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start") - .process(exchange -> { - final PageRange pageRange = new PageRange().setStart(0).setEnd(511); - - exchange.getIn().setHeader(BlobConstants.PAGE_BLOB_RANGE, pageRange); - }) - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=resizePageBlob&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobBlobName", constant("overridenName")) + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=downloadBlobToFile&fileDir=/var/mydir&serviceClient=#client") + .to("mock:result"); ---- -- `clearPageBlob` - +XML:: ++ +[source,xml] +---- + + + + overridenName + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageBlobBlobName + constant: overridenName + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: blob + operation: downloadBlobToFile + fileDir: /var/mydir + serviceClient: "#client" + - to: + uri: mock:result +---- +==== + +- `downloadLink` + +[tabs] +==== +Java:: ++ [source,java] ---- +from("direct:start") + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=downloadLink&serviceClient=#client") + .log("My link ${header.CamelAzureStorageBlobDownloadLink}") + .to("mock:result"); +---- +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: blob + operation: downloadLink + serviceClient: "#client" + - log: + message: "My link ${header.CamelAzureStorageBlobDownloadLink}" + - to: + uri: mock:result +---- +==== + +- `uploadBlockBlob` + +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:start") - .process(exchange -> { - final PageRange pageRange = new PageRange().setStart(0).setEnd(511); + .setHeader("CamelAzureStorageBlobBlobName", constant("overridenName")) + .setBody(constant("Block Blob")) + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=uploadBlockBlob&serviceClient=#client") + .to("mock:result"); +---- - exchange.getIn().setHeader(BlobConstants.PAGE_BLOB_RANGE, pageRange); - }) - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=clearPageBlob&serviceClient=#client") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + + overridenName + + + Block Blob + + + + ---- -- `getPageBlobRanges` +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageBlobBlobName + constant: overridenName + - setBody: + constant: Block Blob + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: blob + operation: uploadBlockBlob + serviceClient: "#client" + - to: + uri: mock:result +---- +==== + +- `uploadBlockBlobChunked` +This operation is recommended for uploading large files (larger than 256MB) as it uses chunked parallel uploads for memory efficiency. + +[tabs] +==== +Java:: ++ [source,java] ---- +from("file://data?noop=true") + .log("Uploading file: ${header.CamelFileName}") + .toD("azure-storage-blob://camelazure/container1?blobName=${header.CamelFileName}&operation=uploadBlockBlobChunked&blockSize=52428800&maxConcurrency=4&serviceClient=#client") + .log("Upload completed: ${header.CamelFileName}"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://data + parameters: + noop: true + steps: + - log: + message: "Uploading file: ${header.CamelFileName}" + - toD: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: "${header.CamelFileName}" + operation: uploadBlockBlobChunked + blockSize: 52428800 + maxConcurrency: 4 + serviceClient: "#client" + - log: + message: "Upload completed: ${header.CamelFileName}" +---- +==== +The `blockSize` and `maxConcurrency` options control memory usage and upload speed: + +* `blockSize`: Size of each chunk (default: 4MB, max: 4000MB). Larger blocks = fewer requests but more memory. +* `maxConcurrency`: Number of parallel uploads (default: auto-detected based on CPU cores). Higher = faster but more memory. +* Memory usage is approximately `blockSize × maxConcurrency`. + +- `stageBlockBlobList` + +._Java-only: requires BlobBlock objects in the body_ + +[source,java] +---- from("direct:start") - .process(exchange -> { - final PageRange pageRange = new PageRange().setStart(0).setEnd(511); + .process(exchange -> { + final List blocks = new LinkedList<>(); + blocks.add(BlobBlock.createBlobBlock(new ByteArrayInputStream("Hello".getBytes()))); + blocks.add(BlobBlock.createBlobBlock(new ByteArrayInputStream("From".getBytes()))); + blocks.add(BlobBlock.createBlobBlock(new ByteArrayInputStream("Camel".getBytes()))); + exchange.getIn().setBody(blocks); + }) + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=stageBlockBlobList&serviceClient=#client") + .to("mock:result"); +---- + +- `commitBlockBlobList` + +._Java-only: requires Block objects in the body_ - exchange.getIn().setHeader(BlobConstants.PAGE_BLOB_RANGE, pageRange); - }) - .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=getPageBlobRanges&serviceClient=#client") - .log("${body}") - .to("mock:result"); +[source,java] +---- +from("direct:start") + .process(exchange -> { + final List blockIds = new LinkedList<>(); + blockIds.add(new Block().setName("id-1")); + blockIds.add(new Block().setName("id-2")); + blockIds.add(new Block().setName("id-3")); + exchange.getIn().setBody(blockIds); + }) + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=commitBlockBlobList&serviceClient=#client") + .to("mock:result"); +---- + +- `getBlobBlockList` + +[tabs] +==== +Java:: ++ +[source,java] +---- +from("direct:start") + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=getBlobBlockList&serviceClient=#client") + .log("${body}") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: blob + operation: getBlobBlockList + serviceClient: "#client" + - log: + message: "${body}" + - to: + uri: mock:result +---- +==== + + +- `createAppendBlob` + +[tabs] +==== +Java:: ++ +[source,java] +---- +from("direct:start") + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=createAppendBlob&serviceClient=#client") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: blob + operation: createAppendBlob + serviceClient: "#client" + - to: + uri: mock:result +---- +==== + +- `commitAppendBlob` + +[tabs] +==== +Java:: ++ +[source,java] +---- +from("direct:start") + .setBody(constant("Hello world from my awesome tests!")) + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=commitAppendBlob&serviceClient=#client") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + Hello world from my awesome tests! + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: "Hello world from my awesome tests!" + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: blob + operation: commitAppendBlob + serviceClient: "#client" + - to: + uri: mock:result +---- +==== + +- `createPageBlob` + +[tabs] +==== +Java:: ++ +[source,java] +---- +from("direct:start") + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=createPageBlob&serviceClient=#client") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: blob + operation: createPageBlob + serviceClient: "#client" + - to: + uri: mock:result +---- +==== + +- `uploadPageBlob` + +NOTE: The `CamelAzureStorageBlobPageBlobRange` header requires a `PageRange` object, which must be set from a bean or processor. + +._Java-only: requires PageRange object_ + +[source,java] +---- +from("direct:start") + .process(exchange -> { + byte[] dataBytes = new byte[512]; + new Random().nextBytes(dataBytes); + final InputStream dataStream = new ByteArrayInputStream(dataBytes); + final PageRange pageRange = new PageRange().setStart(0).setEnd(511); + exchange.getIn().setHeader("CamelAzureStorageBlobPageBlobRange", pageRange); + exchange.getIn().setBody(dataStream); + }) + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=uploadPageBlob&serviceClient=#client") + .to("mock:result"); +---- + +- `resizePageBlob` + +._Java-only: requires PageRange object_ + +[source,java] +---- +from("direct:start") + .process(exchange -> { + exchange.getIn().setHeader("CamelAzureStorageBlobPageBlobRange", + new PageRange().setStart(0).setEnd(511)); + }) + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=resizePageBlob&serviceClient=#client") + .to("mock:result"); +---- + +- `clearPageBlob` + +._Java-only: requires PageRange object_ + +[source,java] +---- +from("direct:start") + .process(exchange -> { + exchange.getIn().setHeader("CamelAzureStorageBlobPageBlobRange", + new PageRange().setStart(0).setEnd(511)); + }) + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=clearPageBlob&serviceClient=#client") + .to("mock:result"); +---- + +- `getPageBlobRanges` + +._Java-only: requires PageRange object_ + +[source,java] +---- +from("direct:start") + .process(exchange -> { + exchange.getIn().setHeader("CamelAzureStorageBlobPageBlobRange", + new PageRange().setStart(0).setEnd(511)); + }) + .to("azure-storage-blob://camelazure/container1?blobName=blob&operation=getPageBlobRanges&serviceClient=#client") + .log("${body}") + .to("mock:result"); +---- + +- `copyBlob` + +[tabs] +==== +Java:: ++ +[source,java] +---- +from("direct:copyBlob") + .setHeader("CamelAzureStorageBlobBlobName", constant("file.txt")) + .setHeader("CamelAzureStorageBlobSourceBlobContainerName", constant("containerblob1")) + .setHeader("CamelAzureStorageBlobSourceBlobAccountName", constant("account")) + .to("azure-storage-blob://account/containerblob2?operation=copyBlob&sourceBlobAccessKey=RAW(accessKey)") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + file.txt + + + containerblob1 + + + account + + + + ---- -- `copyBlob` - -[source,java] +YAML:: ++ +[source,yaml] ---- - -from("direct:copyBlob") - .process(exchange -> { - exchange.getIn().setHeader(BlobConstants.BLOB_NAME, "file.txt"); - exchange.getMessage().setHeader(BlobConstants.SOURCE_BLOB_CONTAINER_NAME, "containerblob1"); - exchange.getMessage().setHeader(BlobConstants.SOURCE_BLOB_ACCOUNT_NAME, "account"); - }) - .to("azure-storage-blob://account/containerblob2?operation=copyBlob&sourceBlobAccessKey=RAW(accessKey)") - .to("mock:result"); +- route: + from: + uri: direct:copyBlob + steps: + - setHeader: + name: CamelAzureStorageBlobBlobName + constant: file.txt + - setHeader: + name: CamelAzureStorageBlobSourceBlobContainerName + constant: containerblob1 + - setHeader: + name: CamelAzureStorageBlobSourceBlobAccountName + constant: account + - to: + uri: azure-storage-blob://account/containerblob2 + parameters: + operation: copyBlob + sourceBlobAccessKey: "RAW(accessKey)" + - to: + uri: mock:result ---- +==== In this way the `file.txt` in the container `containerblob1` of the account `account`, will be copied to the container `containerblob2` of the same account. - `createBlobSnapshot` +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:createBlobSnapshot") - .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=createBlobSnapshot&serviceClient=#client") - .log("Snapshot ID: ${header.CamelAzureStorageBlobSnapshotId}") - .to("mock:result"); + .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=createBlobSnapshot&serviceClient=#client") + .log("Snapshot ID: ${header.CamelAzureStorageBlobSnapshotId}") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:createBlobSnapshot + steps: + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: hello.txt + operation: createBlobSnapshot + serviceClient: "#client" + - log: + message: "Snapshot ID: ${header.CamelAzureStorageBlobSnapshotId}" + - to: + uri: mock:result ---- +==== === Reading a specific blob snapshot @@ -927,14 +1473,53 @@ The `getBlob`, `downloadBlobToFile` and `downloadLink` operations can target a s `snapshotId` URI parameter or the `CamelAzureStorageBlobSnapshotId` exchange header. When set, the read is scoped to the snapshot version of the blob instead of the live one. The header takes precedence over the URI parameter. +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:readSnapshot") - .process(exchange -> exchange.getIn().setHeader(BlobConstants.BLOB_SNAPSHOT_ID, "2026-04-15T10:00:00.0000000Z")) - .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=getBlob&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobSnapshotId", constant("2026-04-15T10:00:00.0000000Z")) + .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=getBlob&serviceClient=#client") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + 2026-04-15T10:00:00.0000000Z + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:readSnapshot + steps: + - setHeader: + name: CamelAzureStorageBlobSnapshotId + constant: "2026-04-15T10:00:00.0000000Z" + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: hello.txt + operation: getBlob + serviceClient: "#client" + - to: + uri: mock:result ---- +==== === Reading a specific blob version @@ -943,108 +1528,324 @@ operations can target a specific version by setting the `versionId` URI paramete `CamelAzureStorageBlobVersionId` exchange header. When set, the read is scoped to the version of the blob instead of the live one. The header takes precedence over the URI parameter. +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:readVersion") - .setHeader(BlobConstants.BLOB_VERSION_ID, constant("2026-04-15T10:00:00.0000000Z")) - .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=getBlob&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobVersionId", constant("2026-04-15T10:00:00.0000000Z")) + .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=getBlob&serviceClient=#client") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + 2026-04-15T10:00:00.0000000Z + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:readVersion + steps: + - setHeader: + name: CamelAzureStorageBlobVersionId + constant: "2026-04-15T10:00:00.0000000Z" + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: hello.txt + operation: getBlob + serviceClient: "#client" + - to: + uri: mock:result ---- +==== - `setBlobTags` +NOTE: The `CamelAzureStorageBlobTags` header requires a `Map` value, which must be set from a bean or processor in XML/YAML. + +._Java-only: Map.of() for blob tags_ + [source,java] ---- - from("direct:setBlobTags") - .setHeader(BlobConstants.BLOB_TAGS, constant(Map.of("status", "quarantine", "category", "document"))) - .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=setBlobTags&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobTags", constant(Map.of("status", "quarantine", "category", "document"))) + .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=setBlobTags&serviceClient=#client") + .to("mock:result"); ---- - `getBlobTags` +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:getBlobTags") - .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=getBlobTags&serviceClient=#client") - .log("Tags: ${body}") - .to("mock:result"); + .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=getBlobTags&serviceClient=#client") + .log("Tags: ${body}") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:getBlobTags + steps: + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: hello.txt + operation: getBlobTags + serviceClient: "#client" + - log: + message: "Tags: ${body}" + - to: + uri: mock:result ---- +==== - `findBlobsByTags` +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:findBlobsByTags") - .setHeader(BlobConstants.BLOB_TAG_FILTER, constant("\"Environment\" = 'Production' AND \"Status\" = 'Active'")) - .to("azure-storage-blob://camelazure?operation=findBlobsByTags&serviceClient=#client") - .log("Matching blobs: ${body}") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobTagFilter", constant("\"Environment\" = 'Production' AND \"Status\" = 'Active'")) + .to("azure-storage-blob://camelazure?operation=findBlobsByTags&serviceClient=#client") + .log("Matching blobs: ${body}") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + "Environment" = 'Production' AND "Status" = 'Active' + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:findBlobsByTags + steps: + - setHeader: + name: CamelAzureStorageBlobTagFilter + constant: "\"Environment\" = 'Production' AND \"Status\" = 'Active'" + - to: + uri: azure-storage-blob://camelazure + parameters: + operation: findBlobsByTags + serviceClient: "#client" + - log: + message: "Matching blobs: ${body}" + - to: + uri: mock:result ---- +==== - `setBlobLegalHold` +[tabs] +==== +Java:: ++ [source,java] ---- - -// place a legal hold on the blob (e.g. for compliance / quarantine workflows) +// place a legal hold on the blob from("direct:setLegalHold") - .setHeader(BlobConstants.BLOB_LEGAL_HOLD, constant(true)) - .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=setBlobLegalHold&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobLegalHold", constant(true)) + .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=setBlobLegalHold&serviceClient=#client") + .to("mock:result"); -// clear the legal hold once the workflow is complete +// clear the legal hold from("direct:clearLegalHold") - .setHeader(BlobConstants.BLOB_LEGAL_HOLD, constant(false)) - .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=setBlobLegalHold&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobLegalHold", constant(false)) + .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=setBlobLegalHold&serviceClient=#client") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + true + + + + + + + + + false + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:setLegalHold + steps: + - setHeader: + name: CamelAzureStorageBlobLegalHold + constant: true + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: hello.txt + operation: setBlobLegalHold + serviceClient: "#client" + - to: + uri: mock:result + +- route: + from: + uri: direct:clearLegalHold + steps: + - setHeader: + name: CamelAzureStorageBlobLegalHold + constant: false + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: hello.txt + operation: setBlobLegalHold + serviceClient: "#client" + - to: + uri: mock:result ---- +==== - `setBlobImmutabilityPolicy` +._Java-only: requires OffsetDateTime and BlobImmutabilityPolicyMode objects_ + [source,java] ---- - -// apply a 7-day unlocked time-based retention policy (can be modified or deleted) from("direct:setImmutabilityPolicy") - .setHeader(BlobConstants.BLOB_IMMUTABILITY_POLICY_EXPIRY_TIME, constant(OffsetDateTime.now().plusDays(7))) - .setHeader(BlobConstants.BLOB_IMMUTABILITY_POLICY_MODE, constant(BlobImmutabilityPolicyMode.UNLOCKED)) - .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=setBlobImmutabilityPolicy&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobImmutabilityPolicyExpiryTime", constant(OffsetDateTime.now().plusDays(7))) + .setHeader("CamelAzureStorageBlobImmutabilityPolicyMode", constant(BlobImmutabilityPolicyMode.UNLOCKED)) + .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=setBlobImmutabilityPolicy&serviceClient=#client") + .to("mock:result"); ---- - `undeleteBlob` +[tabs] +==== +Java:: ++ [source,java] ---- - -// restore a soft-deleted blob (requires soft delete to be enabled on the storage account) from("direct:undeleteBlob") - .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=undeleteBlob&serviceClient=#client") - .to("mock:result"); + .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=undeleteBlob&serviceClient=#client") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:undeleteBlob + steps: + - to: + uri: azure-storage-blob://camelazure/container1 + parameters: + blobName: hello.txt + operation: undeleteBlob + serviceClient: "#client" + - to: + uri: mock:result ---- +==== - `setBlobTier` +._Java-only: requires AccessTier and RehydratePriority enum objects_ + [source,java] ---- - // move a blob to the COOL tier for less frequent access from("direct:moveToCool") - .setHeader(BlobConstants.ACCESS_TIER, constant(AccessTier.COOL)) - .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=setBlobTier&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobAccessTier", constant(AccessTier.COOL)) + .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=setBlobTier&serviceClient=#client") + .to("mock:result"); // rehydrate a blob from ARCHIVE to HOT with high priority from("direct:rehydrate") - .setHeader(BlobConstants.ACCESS_TIER, constant(AccessTier.HOT)) - .setHeader(BlobConstants.REHYDRATE_PRIORITY, constant(RehydratePriority.HIGH)) - .to("azure-storage-blob://camelazure/container1?blobName=archived.txt&operation=setBlobTier&serviceClient=#client") - .to("mock:result"); + .setHeader("CamelAzureStorageBlobAccessTier", constant(AccessTier.HOT)) + .setHeader("CamelAzureStorageBlobRehydratePriority", constant(RehydratePriority.HIGH)) + .to("azure-storage-blob://camelazure/container1?blobName=archived.txt&operation=setBlobTier&serviceClient=#client") + .to("mock:result"); ---- === Blob modification during download (ConditionNotMet) @@ -1065,48 +1866,75 @@ Workarounds: === SAS Token generation example -SAS Blob Container tokens can be generated programmatically or via Azure UI. To generate the token with java code, the following can be done: +SAS Blob Container tokens can be generated programmatically or via Azure UI. To generate the token with Java code, the following can be done: + +._Java-only: programmatic SAS token generation_ [source,java] ---- - BlobContainerClient blobClient = new BlobContainerClientBuilder() - .endpoint(String.format("https://%s.blob.core.windows.net/%s", accountName, accessKey)) - .containerName(containerName) - .credential(new StorageSharedKeyCredential(accountName, accessKey)) - .buildClient(); + .endpoint(String.format("https://%s.blob.core.windows.net/%s", accountName, accessKey)) + .containerName(containerName) + .credential(new StorageSharedKeyCredential(accountName, accessKey)) + .buildClient(); - // Create a SAS token that's valid for 1 day, as an example - OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(1); +OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(1); - // Assign permissions to the SAS token - BlobContainerSasPermission blobContainerSasPermission = new BlobContainerSasPermission() - .setWritePermission(true) - .setListPermission(true) - .setCreatePermission(true) - .setDeletePermission(true) - .setAddPermission(true) - .setReadPermission(true); +BlobContainerSasPermission blobContainerSasPermission = new BlobContainerSasPermission() + .setWritePermission(true) + .setListPermission(true) + .setCreatePermission(true) + .setDeletePermission(true) + .setAddPermission(true) + .setReadPermission(true); - BlobServiceSasSignatureValues sasSignatureValues = new BlobServiceSasSignatureValues(expiryTime, blobContainerSasPermission); +BlobServiceSasSignatureValues sasSignatureValues = new BlobServiceSasSignatureValues(expiryTime, blobContainerSasPermission); - return blobClient.generateSas(sasSignatureValues); +return blobClient.generateSas(sasSignatureValues); ---- -The generated SAS token can be then stored to an application.properties file so that it can be loaded by the camel route, for example: +The generated SAS token can be then stored to an application.properties file so that it can be loaded by the Camel route, for example: [source,properties] ---- - camel.component.azure-storage-blob.sas-token=MY_TOKEN_HERE ---- +[tabs] +==== +Java:: ++ [source,java] ---- +from("direct:uploadBlob") + .to("azure-storage-blob://account/containerblob2?operation=uploadBlockBlob&credentialType=AZURE_SAS"); +---- -from("direct:copyBlob") - .to("azure-storage-blob://account/containerblob2?operation=uploadBlockBlob&credentialType=AZURE_SAS") +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:uploadBlob + steps: + - to: + uri: azure-storage-blob://account/containerblob2 + parameters: + operation: uploadBlockBlob + credentialType: AZURE_SAS ---- +==== == Important Development Notes From b932d8c8a38b727309539e5a2e90146d85e0c9d6 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 18:28:58 +0200 Subject: [PATCH 03/87] CAMEL-23789: Make MongoDB component docs multi-DSL friendly (Wave 1) Resolve all MongoDbConstants to string header values, add Java-only markers for Bson/ProducerTemplate examples, add tabs for count route, fix prose references to use string header names, and remove duplicate projection example. Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/mongodb-component.adoc | 236 +++++++++++------- 1 file changed, 146 insertions(+), 90 deletions(-) diff --git a/components/camel-mongodb/src/main/docs/mongodb-component.adoc b/components/camel-mongodb/src/main/docs/mongodb-component.adoc index 93715a0a4a11d..a2455b13f4d74 100644 --- a/components/camel-mongodb/src/main/docs/mongodb-component.adoc +++ b/components/camel-mongodb/src/main/docs/mongodb-component.adoc @@ -229,13 +229,15 @@ YAML:: ====== Example with a query selector (returns the first matching document in a collection): +._Java-only: requires Bson Filters object_ + [source,java] ------------------------------------------------------------------------------------- +---- from("direct:findOneByQuery") - .setHeader(MongoDbConstants.CRITERIA, constant(Filters.eq("name", "Raul Kripalani"))) + .setHeader("CamelMongoDbCriteria", constant(Filters.eq("name", "Raul Kripalani"))) .to("mongodb:myDb?database=flights&collection=tickets&operation=findOneByQuery") .to("mock:resultFindOneByQuery"); ------------------------------------------------------------------------------------- +---- [TIP] ==== @@ -300,24 +302,28 @@ YAML:: ====== Example with a query selector (returns all matching documents in a collection) +._Java-only: requires Bson Filters object_ + [source,java] ------------------------------------------------------------------------------ +---- from("direct:findAll") - .setHeader(MongoDbConstants.CRITERIA, Filters.eq("name", "Raul Kripalani")) + .setHeader("CamelMongoDbCriteria", constant(Filters.eq("name", "Raul Kripalani"))) .to("mongodb:myDb?database=flights&collection=tickets&operation=findAll") .to("mock:resultFindAll"); ------------------------------------------------------------------------------ +---- ====== Example with option _outputType=MongoIterable_ and batch size +._Java-only: requires Bson Filters object_ + [source,java] ------------------------------------------------------------------------------ +---- from("direct:findAll") - .setHeader(MongoDbConstants.BATCH_SIZE).constant(10) - .setHeader(MongoDbConstants.CRITERIA, constant(Filters.eq("name", "Raul Kripalani"))) + .setHeader("CamelMongoDbBatchSize", constant(10)) + .setHeader("CamelMongoDbCriteria", constant(Filters.eq("name", "Raul Kripalani"))) .to("mongodb:myDb?database=flights&collection=tickets&operation=findAll&outputType=MongoIterable") .to("mock:resultFindAll"); ------------------------------------------------------------------------------ +---- [TIP] ==== @@ -337,27 +343,69 @@ and as a result, the operation will not run against the "notableScientists" collection, but against the "dynamicCollectionName" collection. +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------------------------------------------------------- +---- from("direct:count") - .to("mongodb:myDb?database=tickets&collection=flights&operation=count&dynamicity=true"); + .to("mongodb:myDb?database=tickets&collection=flights&operation=count&dynamicity=true"); +---- -Long result = template.requestBodyAndHeader("direct:count", "irrelevantBody", MongoDbConstants.COLLECTION, "dynamicCollectionName"); -assertTrue("Result is not of type Long", result instanceof Long); ------------------------------------------------------------------------------------------------------------------------------------- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:count + steps: + - to: + uri: mongodb:myDb + parameters: + database: tickets + collection: flights + operation: count + dynamicity: true +---- +==== + +To dynamically target a different collection, set the `CamelMongoDbCollection` header: + +._Java-only: Java test API (ProducerTemplate)_ + +[source,java] +---- +Long result = template.requestBodyAndHeader("direct:count", "irrelevantBody", + "CamelMongoDbCollection", "dynamicCollectionName"); +---- You can provide a query *The query object is extracted `CamelMongoDbCriteria` header*. -if the CamelMongoDbCriteria header is null the query object is extracted +if the CamelMongoDbCriteria header is null the query object is extracted message body, i.e., it should be of type `Bson` or convertible to `Bson`., and operation will return the number of documents matching the criteria. +._Java-only: Java test API (ProducerTemplate)_ + [source,java] ------------------------------------------------------------------------------------------------------------------------- +---- Document query = ... -Long count = template.requestBodyAndHeader("direct:count", query, MongoDbConstants.COLLECTION, "dynamicCollectionName"); ------------------------------------------------------------------------------------------------------------------------- +Long count = template.requestBodyAndHeader("direct:count", query, + "CamelMongoDbCollection", "dynamicCollectionName"); +---- ===== Specifying a `fields` filter (projection) @@ -366,30 +414,21 @@ entirety (with all their fields). If your documents are large, and you only require retrieving a subset of their fields, you can specify a field filter in all query operations, simply by setting the relevant `Bson` (or type convertible to `Bson`, such as a JSON String, -Map, etc.) on the `CamelMongoDbFieldsProjection` header, constant shortcut: -`MongoDbConstants.FIELDS_PROJECTION`. +Map, etc.) on the `CamelMongoDbFieldsProjection` header. Here is an example that uses MongoDB's `Projections` to simplify the creation of Bson. It retrieves all fields except `_id` and `boringField`: -[source,java] ----------------------------------------------------------------------------------------------------------------------------- -// route: from("direct:findAll").to("mongodb:myDb?database=flights&collection=tickets&operation=findAll") -Bson fieldProjection = Projection.exclude("_id", "boringField"); -Object result = template.requestBodyAndHeader("direct:findAll", ObjectUtils.NULL, MongoDbConstants.FIELDS_PROJECTION, fieldProjection); ----------------------------------------------------------------------------------------------------------------------------- - -Here is an example that uses MongoDB's `Projections` to simplify -the creation of Bson. It retrieves all fields except `_id` and -`boringField`: +._Java-only: Java test API with Bson Projection_ [source,java] ----------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:findAll").to("mongodb:myDb?database=flights&collection=tickets&operation=findAll") Bson fieldProjection = Projection.exclude("_id", "boringField"); -Object result = template.requestBodyAndHeader("direct:findAll", ObjectUtils.NULL, MongoDbConstants.FIELDS_PROJECTION, fieldProjection); ----------------------------------------------------------------------------------------------------------------------------- +Object result = template.requestBodyAndHeader("direct:findAll", ObjectUtils.NULL, + "CamelMongoDbFieldsProjection", fieldProjection); +---- ===== Specifying a sort clause @@ -399,12 +438,15 @@ that uses MongoDB's `Sorts` to simplify the creation of Bson. It retrieves all fields except `_id` and `boringField`: +._Java-only: Java test API with Bson Sorts_ + [source,java] ----------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:findAll").to("mongodb:myDb?database=flights&collection=tickets&operation=findAll") Bson sorts = Sorts.descending("_id"); -Object result = template.requestBodyAndHeader("direct:findAll", ObjectUtils.NULL, MongoDbConstants.SORT_BY, sorts); ----------------------------------------------------------------------------------------------------------------------------- +Object result = template.requestBodyAndHeader("direct:findAll", ObjectUtils.NULL, + "CamelMongoDbSortBy", sorts); +---- In a Camel route, the SORT_BY header can be used with the findOneByQuery operation to achieve the same result. If the FIELDS_PROJECTION header is also @@ -414,15 +456,17 @@ parameterized MyBatis SELECT query). This example demonstrates fetching the temporally newest document from a collection and reducing the result to a single field, based on the `documentTimestamp` field: +._Java-only: requires Bson Sorts and Projection objects_ + [source,java] ----------------------------------------------------------------------------------------------------------------------------- -.from("direct:someTriggeringEvent") -.setHeader(MongoDbConstants.SORT_BY).constant(Sorts.descending("documentTimestamp")) -.setHeader(MongoDbConstants.FIELDS_PROJECTION).constant(Projection.include("documentTimestamp")) -.setBody().constant("{}") -.to("mongodb:myDb?database=local&collection=myDemoCollection&operation=findOneByQuery") -.to("direct:aMyBatisParameterizedSelect"); ----------------------------------------------------------------------------------------------------------------------------- +---- +from("direct:someTriggeringEvent") + .setHeader("CamelMongoDbSortBy", constant(Sorts.descending("documentTimestamp"))) + .setHeader("CamelMongoDbFieldsProjection", constant(Projection.include("documentTimestamp"))) + .setBody(constant("{}")) + .to("mongodb:myDb?database=local&collection=myDemoCollection&operation=findOneByQuery") + .to("direct:aMyBatisParameterizedSelect"); +---- ==== Create/update operations @@ -496,8 +540,7 @@ expected to ensure at the application level that is unique (and this is a good practice too). OID(s) of the inserted record(s) are stored in the -message header under `CamelMongoOid` key (`MongoDbConstants.OID` -constant). The value stored is `org.bson.types.ObjectId` for single +message header under `CamelMongoOid` key. The value stored is `org.bson.types.ObjectId` for single insert or `java.util.List` if multiple records have been inserted. @@ -567,30 +610,32 @@ YAML:: ---- ==== +._Java-only: Java test API (ProducerTemplate)_ + [source,java] ------------------------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:insert").to("mongodb:myDb?database=flights&collection=tickets&operation=save"); -org.bson.Document docForSave = new org.bson.Document(); +Document docForSave = new Document(); docForSave.put("key", "value"); Object result = template.requestBody("direct:insert", docForSave); ------------------------------------------------------------------------------------------------------------------------------------------- +---- ===== update Update one or multiple records in the collection. Requires a filter query and a update rules. -You can define the filter using `MongoDBConstants.CRITERIA` header as `Bson` +You can define the filter using `CamelMongoDbCriteria` header as `Bson` and define the update rules as `Bson` in Body. [NOTE] ==== *Update after enrich* -While defining the filter by using `MongoDBConstants.CRITERIA` header as `Bson` +While defining the filter by using `CamelMongoDbCriteria` header as `Bson` to query mongodb before you do update, you should notice you need to remove it from the resulting Camel exchange during aggregation if you use the enrich pattern with an aggregation strategy and then apply mongodb update. -If you don't remove this header during aggregation and/or redefine `MongoDBConstants.CRITERIA` header before sending +If you don't remove this header during aggregation and/or redefine `CamelMongoDbCriteria` header before sending Camel exchange to mongodb producer endpoint, you may end up with invalid Camel exchange payload while updating mongodb. ==== @@ -614,41 +659,45 @@ records, set the `CamelMongoDbMultiUpdate` IN message header to `true`. ==== -A header with key `CamelMongoDbRecordsAffected` will be returned -(`MongoDbConstants.RECORDS_AFFECTED` constant) with the number of +A header with key `CamelMongoDbRecordsAffected` will be returned with the number of records updated (copied from `WriteResult.getN()`). For example, the following will update *all* records whose filterField field equals true by setting the value of the "scientist" field to "Darwin": +._Java-only: Java test API with Bson filter and update_ + [source,java] ------------------------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:update").to("mongodb:myDb?database=science&collection=notableScientists&operation=update"); List body = new ArrayList<>(); Bson filterField = Filters.eq("filterField", true); body.add(filterField); BsonDocument updateObj = new BsonDocument().append("$set", new BsonDocument("scientist", new BsonString("Darwin"))); body.add(updateObj); -Object result = template.requestBodyAndHeader("direct:update", body, MongoDbConstants.MULTIUPDATE, true); ------------------------------------------------------------------------------------------------------------------------------------------- +Object result = template.requestBodyAndHeader("direct:update", body, "CamelMongoDbMultiUpdate", true); +---- + +._Java-only: Java test API with criteria header_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:update").to("mongodb:myDb?database=science&collection=notableScientists&operation=update"); -Maps headers = new HashMap<>(2); -headers.add(MongoDbConstants.MULTIUPDATE, true); -headers.add(MongoDbConstants.FIELDS_FILTER, Filters.eq("filterField", true)); -String updateObj = Updates.set("scientist", "Darwin");; +Map headers = new HashMap<>(2); +headers.put("CamelMongoDbMultiUpdate", true); +headers.put("CamelMongoDbCriteria", Filters.eq("filterField", true)); +Bson updateObj = Updates.set("scientist", "Darwin"); Object result = template.requestBodyAndHeaders("direct:update", updateObj, headers); +---- ------------------------------------------------------------------------------------------------------------------------------------------- +._Java-only: Java test API with JSON string_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:update").to("mongodb:myDb?database=science&collection=notableScientists&operation=update"); String updateObj = "[{\"filterField\": true}, {\"$set\", {\"scientist\", \"Darwin\"}}]"; -Object result = template.requestBodyAndHeader("direct:update", updateObj, MongoDbConstants.MULTIUPDATE, true); +Object result = template.requestBodyAndHeader("direct:update", updateObj, "CamelMongoDbMultiUpdate", true); ------------------------------------------------------------------------------------------------------------------------------------------ @@ -663,15 +712,16 @@ act as the removal filter query, and is expected to be of type 'conditionField' equals true, in the science database, notableScientists collection: +._Java-only: Java test API with Bson filter_ + [source,java] ------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:remove").to("mongodb:myDb?database=science&collection=notableScientists&operation=remove"); Bson conditionField = Filters.eq("conditionField", true); Object result = template.requestBody("direct:remove", conditionField); ------------------------------------------------------------------------------------------------------------------- +---- -A header with key `CamelMongoDbRecordsAffected` is returned -(`MongoDbConstants.RECORDS_AFFECTED` constant) with type `int`, +A header with key `CamelMongoDbRecordsAffected` is returned with type `int`, containing the number of records deleted (copied from `WriteResult.getN()`). @@ -685,17 +735,19 @@ Requires a `List>` as the IN message body containing comman The following example will insert a new scientist "Pierre Curie", update record with id "5" by setting the value of the "scientist" field to "Marie Curie" and delete record with id "3" : +._Java-only: Java test API with WriteModel objects_ + [source,java] ------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:bulkWrite").to("mongodb:myDb?database=science&collection=notableScientists&operation=bulkWrite"); List> bulkOperations = Arrays.asList( - new InsertOneModel<>(new Document("scientist", "Pierre Curie")), - new UpdateOneModel<>(new Document("_id", "5"), - new Document("$set", new Document("scientist", "Marie Curie"))), - new DeleteOneModel<>(new Document("_id", "3"))); + new InsertOneModel<>(new Document("scientist", "Pierre Curie")), + new UpdateOneModel<>(new Document("_id", "5"), + new Document("$set", new Document("scientist", "Marie Curie"))), + new DeleteOneModel<>(new Document("_id", "3"))); BulkWriteResult result = template.requestBody("direct:bulkWrite", bulkOperations, BulkWriteResult.class); ------------------------------------------------------------------------------------------------------------------- +---- By default, operations are executed in order and interrupted on the first write error without processing any remaining write operations in the list. To instruct MongoDB to continue to process remaining write operations in the list, set the `CamelMongoDbBulkOrdered` IN message header to `false`. @@ -710,16 +762,18 @@ Perform an aggregation with the given pipeline contained in the body. *Aggregations could be long and heavy operations. Use with care.* +._Java-only: requires Bson aggregation pipeline_ + [source,java] ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- // route: from("direct:aggregate").to("mongodb:myDb?database=science&collection=notableScientists&operation=aggregate"); -List aggregate = Arrays.asList(match(or(eq("scientist", "Darwin"), eq("scientist", +List aggregate = Arrays.asList(match(or(eq("scientist", "Darwin"), eq("scientist", "Einstein"))), group("$scientist", sum("count", 1))); from("direct:aggregate") - .setBody().constant(aggregate) + .setBody(constant(aggregate)) .to("mongodb:myDb?database=science&collection=notableScientists&operation=aggregate") .to("mock:resultAggregate"); ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- By default, a List of all results is returned. This can be heavy on memory depending on the size of the results. A safer alternative is to set your outputType=MongoIterable. The next Processor will see an iterable in the message body allowing it to step through the results one by one. @@ -727,13 +781,15 @@ Thus, setting a batch size and returning an iterable allows for efficient retrie An example would look like: +._Java-only: requires Bson aggregation pipeline_ + [source,java] ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- -List aggregate = Arrays.asList(match(or(eq("scientist", "Darwin"), eq("scientist", +---- +List aggregate = Arrays.asList(match(or(eq("scientist", "Darwin"), eq("scientist", "Einstein"))), group("$scientist", sum("count", 1))); from("direct:aggregate") - .setHeader(MongoDbConstants.BATCH_SIZE).constant(10) - .setBody().constant(aggregate) + .setHeader("CamelMongoDbBatchSize", constant(10)) + .setBody(constant(aggregate)) .to("mongodb:myDb?database=science&collection=notableScientists&operation=aggregate&outputType=MongoIterable") .split(body()) .streaming() @@ -836,20 +892,20 @@ Object result = template.requestBody("direct:command", commandBody); ==== Dynamic operations An Exchange can override the endpoint's fixed operation by setting the -`CamelMongoDbOperation` header, defined by the -`MongoDbConstants.OPERATION_HEADER` constant. + - The values supported are determined by the MongoDbOperation enumeration +`CamelMongoDbOperation` header. The values supported are determined by the MongoDbOperation enumeration and match the accepted values for the `operation` parameter on the endpoint URI. For example: +._Java-only: Java test API (ProducerTemplate)_ + [source,java] ------------------------------------------------------------------------------------------------------------------------------ +---- // from("direct:insert").to("mongodb:myDb?database=flights&collection=tickets&operation=insert"); -Object result = template.requestBodyAndHeader("direct:insert", "irrelevantBody", MongoDbConstants.OPERATION_HEADER, "count"); +Object result = template.requestBodyAndHeader("direct:insert", "irrelevantBody", "CamelMongoDbOperation", "count"); assertTrue("Result is not of type Long", result instanceof Long); ------------------------------------------------------------------------------------------------------------------------------ +---- === Consumers There are several types of consumers: From 5fd904bc5c99cef306e65f01075fe8bb2abbd789 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 19:02:26 +0200 Subject: [PATCH 04/87] CAMEL-23789: Make JMS component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/jms-component.adoc | 272 +++++++++++++++--- 1 file changed, 237 insertions(+), 35 deletions(-) diff --git a/components/camel-jms/src/main/docs/jms-component.adoc b/components/camel-jms/src/main/docs/jms-component.adoc index 1dc15de302b45..9fb1cc18c6fae 100644 --- a/components/camel-jms/src/main/docs/jms-component.adoc +++ b/components/camel-jms/src/main/docs/jms-component.adoc @@ -367,6 +367,7 @@ consume from the Dead Letter Queue and retrieve the caused exception from the Exchange property with the key `Exchange.EXCEPTION_CAUGHT`. The demo below illustrates this: +._Java-only: `errorHandler` configuration is Java DSL specific_ [source,java] ------------------------------------------------------------------------ // setup error handler to use JMS as queue and store the entire Exchange @@ -375,11 +376,43 @@ errorHandler(deadLetterChannel("jms:queue:dead?transferExchange=true")); Then you can consume from the JMS queue and analyze the problem: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------ +---- from("jms:queue:dead").to("bean:myErrorAnalyzer"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- -// and in our bean +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: jms:queue:dead + steps: + - to: + uri: bean:myErrorAnalyzer +---- +==== + +And in the `myErrorAnalyzer` bean: + +._Java-only: programmatic access to exchange properties and exception_ +[source,java] +----------------------------------------------------------------------------------- String body = exchange.getIn().getBody(); Exception cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class); // the cause message is @@ -394,6 +427,7 @@ Message Translator EIP to do a transformation on the failed exchange before it is moved to the xref:jms-component.adoc[JMS] dead letter queue: +._Java-only: `errorHandler` and `exceptionMessage()` are Java DSL specific_ [source,java] -------------------------------------------------------------------------------------------------- // we sent it to a seda dead queue first @@ -554,6 +588,7 @@ YAML:: You can also specify the message type to use for each message by setting the header with the key `CamelJmsMessageType`. For example: +._Java-only: uses the `JmsMessageType` enum which requires Java code_ [source,java] --------------------------------------------------------------------------------------------------------- from("file://inbox/order").setHeader("CamelJmsMessageType", JmsMessageType.Text).to("jms:queue:order"); @@ -712,13 +747,46 @@ you can specify the exchange pattern to use, see more at Request Reply. + This is useful if you want to send an `InOnly` message to a JMS topic: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------- +---- from("activemq:queue:in") .to("bean:validateOrder") .to(ExchangePattern.InOnly, "activemq:topic:order") .to("bean:handleOrder"); ------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: activemq:queue:in + steps: + - to: + uri: bean:validateOrder + - inOnly: + uri: activemq:topic:order + - to: + uri: bean:handleOrder +---- +==== === Reuse endpoint and send to different destinations computed at runtime @@ -784,11 +852,12 @@ part of the JMS endpoint URL, but it will be ignored in this example. In the `computeDestination` bean, specify the real destination by setting the `CamelJmsDestinationName` header as follows: +._Java-only: bean method that sets the destination header programmatically_ [source,java] ------------------------------------------------------------------------- public void setJmsHeader(Exchange exchange) { String id = .... - exchange.getIn().setHeader("CamelJmsDestinationName", "order:" + id"); + exchange.getIn().setHeader("CamelJmsDestinationName", "order:" + id); } ------------------------------------------------------------------------- @@ -853,11 +922,40 @@ multiple threads to make an application more responsive. You can set the `concurrentConsumers` option to specify the number of threads servicing the JMS endpoint, as follows: +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------- -from("jms:SomeQueue?concurrentConsumers=20"). - bean(MyClass.class); ---------------------------------------------- +---- +from("jms:SomeQueue?concurrentConsumers=20") + .bean(MyClass.class); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: jms:SomeQueue + parameters: + concurrentConsumers: 20 + steps: + - to: + uri: bean:MyClass +---- +==== You can configure this option in one of the following ways: @@ -876,11 +974,41 @@ Asynchronous Routing Engine). See more details in the table on top of the page about the `asyncConsumer` option. +[tabs] +==== +Java:: ++ [source,java] ----------------------------------------------------------------- -from("jms:SomeQueue?concurrentConsumers=20&asyncConsumer=true"). - bean(MyClass.class); ----------------------------------------------------------------- +---- +from("jms:SomeQueue?concurrentConsumers=20&asyncConsumer=true") + .bean(MyClass.class); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: jms:SomeQueue + parameters: + concurrentConsumers: 20 + asyncConsumer: true + steps: + - to: + uri: bean:MyClass +---- +==== === Request-reply over JMS @@ -960,6 +1088,7 @@ concurrent threads using the `concurrentConsumers` and `maxConcurrentConsumers` options. This allows you to easier configure this in Camel as shown below: +._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] ------------------------------------------------------- from(xxx) @@ -977,6 +1106,7 @@ If you use a fixed reply queue when doing Request Reply over JMS as shown in the example below, then pay attention. +._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] --------------------------------------------- from(xxx) @@ -994,6 +1124,7 @@ using the `receiveTimeout` option. By default, its 1000 milliseconds. So to make it faster, you can set it to 250 millis to pull 4 times per second as shown: +._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] ---------------------------------------------------------------- from(xxx) @@ -1021,6 +1152,7 @@ the `ReplyToType` option which you can configure to `Exclusive` + to tell Camel that the reply queue is exclusive as shown in the example below: +._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] ------------------------------------------------------------------- from(xxx) @@ -1032,6 +1164,7 @@ Mind that the queue must be exclusive to each and every endpoint. So if you have two routes, then they each need a unique reply queue as shown in the next example: +._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] ----------------------------------------------------------------------------- from(xxx) @@ -1140,22 +1273,62 @@ which would then fail due the exception, and Camel's error handler reacts. If you want to use a per message timeout value, you can set the header -with key -`org.apache.camel.component.jms.JmsConstants#JMS_REQUEST_TIMEOUT` which -has constant value `"CamelJmsRequestTimeout"` with a timeout value as -a long type. +`CamelJmsRequestTimeout` with a timeout value as a long type. + +TIP: In Java code, you can use the constant `JmsConstants.JMS_REQUEST_TIMEOUT` for the header name. For example, we can use a bean to compute the timeout value per individual message, such as calling the `"whatIsTheTimeout"` method on the service bean as shown below: +[tabs] +==== +Java:: ++ [source,java] ----------------------------------------------------------------------------------------- +---- from("direct:someWhere") .setHeader("CamelJmsRequestTimeout", method(ServiceBean.class, "whatIsTheTimeout")) .to("jms:queue:foo?replyTo=bar&requestTimeout=30s") .to("bean:processReply"); ----------------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:someWhere + steps: + - setHeader: + name: CamelJmsRequestTimeout + method: + ref: serviceBean + method: whatIsTheTimeout + - to: + uri: jms:queue:foo + parameters: + replyTo: bar + requestTimeout: 30s + - to: + uri: bean:processReply +---- +==== When you do fire and forget (InOut) over xref:jms-component.adoc[JMS] with Camel, then Camel by default does *not* set any time to live value on the @@ -1217,13 +1390,15 @@ When using Camel as a JMS listener, it sets an Exchange property with the value of the ReplyTo `javax.jms.Destination` object, having the key `ReplyTo`. You can obtain this `Destination` as follows: +._Java-only: uses JMS `Destination` object and Camel Java API_ [source,java] ----------------------------------------------------------------------------------------------------------------- -Destination replyDestination = exchange.getIn().getHeader(JmsConstants.JMS_REPLY_DESTINATION, Destination.class); +Destination replyDestination = exchange.getIn().getHeader("JMSReplyTo", Destination.class); ----------------------------------------------------------------------------------------------------------------- And then later use it to send a reply using regular JMS or Camel. +._Java-only: uses `JmsEndpoint` and `ProducerTemplate` Java API_ [source,java] ---------------------------------------------------------------------------------------- // we need to pass in the JMS component, and in this sample we use ActiveMQ @@ -1238,16 +1413,15 @@ Camel will then pick up this property and use it for the real destination. The endpoint URI must include a dummy destination, however. For example: +._Java-only: uses `ProducerTemplate` and `Processor` to set the JMS destination object programmatically_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------------- // we pretend to send it to some non-existing dummy queue -template.send("activemq:queue:dummy, new Processor() { - public void process(Exchange exchange) throws Exception { +template.send("activemq:queue:dummy", exchange -> { // and here we override the destination with the ReplyTo destination object so the message is sent to there instead of dummy - exchange.getIn().setHeader(JmsConstants.JMS_DESTINATION, replyDestination); + exchange.getIn().setHeader("CamelJmsDestination", replyDestination); exchange.getIn().setBody("Here is the late reply."); - } -} +}); ---------------------------------------------------------------------------------------------------------------------------------------- === Using a request timeout @@ -1269,13 +1443,12 @@ keep it, otherwise the `JMSReplyTo` header will be dropped. For example, to send an `InOnly` message to the foo queue, but with a `JMSReplyTo` with bar queue you can do as follows: +._Java-only: uses `ProducerTemplate` test API to send with custom JMS headers_ [source,java] ------------------------------------------------------------------------------------- -template.send("activemq:queue:foo?preserveMessageQos=true", new Processor() { - public void process(Exchange exchange) throws Exception { +template.send("activemq:queue:foo?preserveMessageQos=true", exchange -> { exchange.getIn().setBody("World"); exchange.getIn().setHeader("JMSReplyTo", "bar"); - } }); ------------------------------------------------------------------------------------- @@ -1290,12 +1463,42 @@ the JMS destination. For example, you may need to specify the a Camel URI option, you need to set that on the JMS destination name like so: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------ +---- // ... .setHeader("CamelJmsDestinationName", constant("queue:///MY_QUEUE?targetClient=1")) .to("wmq:queue:MY_QUEUE?useMessageIDAsCorrelationID=true"); ------------------------------------------------------------------------------------ +---- + +XML:: ++ +[source,xml] +---- + + + queue:///MY_QUEUE?targetClient=1 + + +---- + +YAML:: ++ +[source,yaml] +---- +# ... +- setHeader: + name: CamelJmsDestinationName + constant: "queue:///MY_QUEUE?targetClient=1" +- to: + uri: wmq:queue:MY_QUEUE + parameters: + useMessageIDAsCorrelationID: true +---- +==== Some versions of WMQ won't accept this option on the destination name, and you will get an exception like: @@ -1308,15 +1511,14 @@ value 'MY_QUEUE?targetClient=1' is not allowed for A workaround is to use a custom DestinationResolver: +._Java-only: programmatic JMS component configuration with custom `DestinationResolver`_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------- JmsComponent wmq = new JmsComponent(connectionFactory); -wmq.setDestinationResolver(new DestinationResolver() { - public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) throws JMSException { - MQQueueSession wmqSession = (MQQueueSession) session; - return wmqSession.createQueue("queue:///" + destinationName + "?targetClient=1"); - } +wmq.setDestinationResolver((session, destinationName, pubSubDomain) -> { + MQQueueSession wmqSession = (MQQueueSession) session; + return wmqSession.createQueue("queue:///" + destinationName + "?targetClient=1"); }); ---------------------------------------------------------------------------------------------------------------------------------- From 0671e248f1a44c57af1fcd61bf44a6077a36615e Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 19:03:44 +0200 Subject: [PATCH 05/87] CAMEL-23789: Make AWS SQS component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/aws2-sqs-component.adoc | 87 ++++++++++++++----- 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/components/camel-aws/camel-aws2-sqs/src/main/docs/aws2-sqs-component.adoc b/components/camel-aws/camel-aws2-sqs/src/main/docs/aws2-sqs-component.adoc index 231962e8676c5..c9002977271f0 100644 --- a/components/camel-aws/camel-aws2-sqs/src/main/docs/aws2-sqs-component.adoc +++ b/components/camel-aws/camel-aws2-sqs/src/main/docs/aws2-sqs-component.adoc @@ -89,16 +89,17 @@ create your own instance, and configure Camel to use your instance by the bean i In the example below, we use _myClient_ as the bean id: +._Java-only: programmatic `SqsClient` creation and registry binding_ [source,java] --------------------------------------------------------------------------------- -// crate my own instance of SqsClient +// create my own instance of SqsClient SqsClient sqs = ... // register the client into Camel registry camelContext.getRegistry().bind("myClient", sqs); // refer to the custom client via myClient as the bean id -from("aws2-sqs://MyQueue?amazonSQSClient=#m4yClient&delay=5000&maxMessagesPerPoll=5") +from("aws2-sqs://MyQueue?amazonSQSClient=#myClient&delay=5000&maxMessagesPerPoll=5") .to("mock:result"); --------------------------------------------------------------------------------- @@ -131,20 +132,66 @@ route, unless the route ended in failure. To achieve appropriate filtering and not send the DeleteMessage even on successful completion of the route, use a Filter: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("aws2-sqs://MyQueue?amazonSQSClient=#client&defaultVisibilityTimeout=5000&deleteIfFiltered=false&deleteAfterRead=false") .filter("${header.login} == true") - .setProperty(Sqs2Constants.SQS_DELETE_FILTERED, constant(true)) + .setProperty("CamelAwsSqsDeleteFiltered", constant(true)) .to("mock:filter"); ------------------------------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + ${header.login} == true + + true + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: aws2-sqs://MyQueue + parameters: + amazonSQSClient: "#client" + defaultVisibilityTimeout: 5000 + deleteIfFiltered: false + deleteAfterRead: false + steps: + - filter: + simple: "${header.login} == true" + steps: + - setProperty: + name: CamelAwsSqsDeleteFiltered + constant: true + - to: + uri: mock:filter +---- +==== + +TIP: In Java code, you can use the constant `Sqs2Constants.SQS_DELETE_FILTERED` for the property name. In the above code, if an exchange doesn't have an appropriate header, it will not make it through the filter AND also not be deleted from the SQS queue. After 5000 milliseconds, the message will become visible to other consumers. -Note we must set the property `Sqs2Constants.SQS_DELETE_FILTERED` to `true` to +Note we must set the property `CamelAwsSqsDeleteFiltered` to `true` to instruct Camel to send the DeleteMessage, if being filtered. === Available Producer Operations @@ -203,20 +250,18 @@ YAML:: You can set a `SendMessageBatchRequest` or an `Iterable` +._Java-only: requires constructing a `List` body programmatically for batch messages_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") - .setHeader(SqsConstants.SQS_OPERATION, constant("sendBatchMessage")) - .process(new Processor() { - @Override - public void process(Exchange exchange) throws Exception { - List c = new ArrayList(); - c.add("team1"); - c.add("team2"); - c.add("team3"); - c.add("team4"); - exchange.getIn().setBody(c); - } + .setHeader("CamelAwsSqsOperation", constant("sendBatchMessage")) + .process(exchange -> { + List c = new ArrayList<>(); + c.add("team1"); + c.add("team2"); + c.add("team3"); + c.add("team4"); + exchange.getIn().setBody(c); }) .to("aws2-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)®ion=eu-west-1"); ------------------------------------------------------------------------------------------------------ @@ -235,8 +280,8 @@ Java:: [source,java] ---- from("direct:start") - .setHeader(SqsConstants.SQS_OPERATION, constant("deleteMessage")) - .setHeader(SqsConstants.RECEIPT_HANDLE, constant("123456")) + .setHeader("CamelAwsSqsOperation", constant("deleteMessage")) + .setHeader("CamelAwsSqsReceiptHandle", constant("123456")) .to("aws2-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)®ion=eu-west-1"); ---- @@ -292,7 +337,7 @@ Java:: [source,java] ---- from("direct:start") - .setHeader(SqsConstants.SQS_OPERATION, constant("listQueues")) + .setHeader("CamelAwsSqsOperation", constant("listQueues")) .to("aws2-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)®ion=eu-west-1"); ---- @@ -342,7 +387,7 @@ Java:: [source,java] ---- from("direct:start") - .setHeader(SqsConstants.SQS_OPERATION, constant("purgeQueue")) + .setHeader("CamelAwsSqsOperation", constant("purgeQueue")) .to("aws2-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)®ion=eu-west-1"); ---- From 198e19de4e4f418adad0eca7ad3764e43f58f44a Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 19:04:17 +0200 Subject: [PATCH 06/87] CAMEL-23789: Make AWS SNS component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/aws2-sns-component.adoc | 67 ++++++++++++------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc b/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc index 50afc122106e0..22519f1503055 100644 --- a/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc +++ b/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc @@ -164,11 +164,42 @@ you'll be able to subscribe your SQS Queue to your SNS Topic. At this point, you can consume messages coming from SNS Topic through your SQS Queue +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------- +---- from("aws2-sqs://test-camel?amazonSQSClient=#amazonSQSClient&delay=50&maxMessagesPerPoll=5") - .to(...); -------------------------------------------------- + .to("..."); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: aws2-sqs://test-camel + parameters: + amazonSQSClient: "#amazonSQSClient" + delay: 50 + maxMessagesPerPoll: 5 + steps: + - to: + uri: "..." +---- +==== === Topic Auto-creation @@ -275,33 +306,17 @@ YAML:: Sending batch to a topic +._Java-only: requires constructing `PublishBatchRequestEntry` objects programmatically_ [source,java] -------------------------------------------------------------------------------- from("direct:start") - .process(new Processor() { - @Override - public void process(Exchange exchange) throws Exception { - PublishBatchRequestEntry publishBatchRequestEntry1 = PublishBatchRequestEntry.builder() - .id("message1") - .message("This is message 1") - .build(); - - PublishBatchRequestEntry publishBatchRequestEntry2 = PublishBatchRequestEntry.builder() - .id("message2") - .message("This is message 2") - .build(); - - PublishBatchRequestEntry publishBatchRequestEntry3 = PublishBatchRequestEntry.builder() - .id("message3") - .message("This is message 3") - .build(); - - List pubList = new ArrayList<>(); - pubList.add(publishBatchRequestEntry1); - pubList.add(publishBatchRequestEntry2); - pubList.add(publishBatchRequestEntry3); + .process(exchange -> { + List pubList = List.of( + PublishBatchRequestEntry.builder().id("message1").message("This is message 1").build(), + PublishBatchRequestEntry.builder().id("message2").message("This is message 2").build(), + PublishBatchRequestEntry.builder().id("message3").message("This is message 3").build() + ); exchange.getIn().setBody(pubList); - } }) .to("aws2-sns://camel-topic?subject=The+subject+message&autoCreateTopic=true&batchEnabled=true"); -------------------------------------------------------------------------------- From efd747172e424f2258173d7ba4f1a4a3f8e8f979 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 19:09:57 +0200 Subject: [PATCH 07/87] CAMEL-23789: Make File component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/file-component.adoc | 138 +++++++++++++++++- 1 file changed, 130 insertions(+), 8 deletions(-) diff --git a/components/camel-file/src/main/docs/file-component.adoc b/components/camel-file/src/main/docs/file-component.adoc index 4c8f3cdb74337..767c8ac054b3e 100644 --- a/components/camel-file/src/main/docs/file-component.adoc +++ b/components/camel-file/src/main/docs/file-component.adoc @@ -465,6 +465,10 @@ files, by setting a property on the exchange with the key `Exchange.CHARSET_NAME`. For example, in the route below, we set the property with a value from a message header. +[tabs] +==== +Java:: ++ [source,java] ---- from("file:inbox") @@ -474,6 +478,42 @@ from("file:inbox") .to("file:outbox"); ---- +XML:: ++ +[source,xml] +---- + + + + + +
someCharsetHeader
+
+ +
+---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:inbox + steps: + - convertBodyTo: + type: "byte[]" + charset: iso-8859-1 + - to: + uri: bean:myBean + - setProperty: + name: CamelCharsetName + header: someCharsetHeader + - to: + uri: file:outbox +---- +==== + We suggest keeping things simpler, so if you pick up files with the same encoding, and want to write the files in a specific encoding, then favor to use the `charset` option on the endpoints. @@ -576,14 +616,7 @@ YAML:: ---- ==== -To use `report.txt` as the filename you have to do: - -[source,java] ----- -from("direct:report").setHeader(Exchange.FILE_NAME, constant("report.txt")).to( "file:target/reports"); ----- - -... the same as above, but with `CamelFileName`: +To use `report.txt` as the filename you have to do (using the `CamelFileName` header): [tabs] ==== @@ -692,11 +725,33 @@ See also section <> below. If you want only to consume files when a _done file_ exists, then you can use the `doneFileName` option on the endpoint. +[tabs] +==== +Java:: ++ [source,java] ---- from("file:bar?doneFileName=done"); ---- +XML:: ++ +[source,xml] +---- + +---- + +YAML:: ++ +[source,yaml] +---- +- from: + uri: file:bar + parameters: + doneFileName: done +---- +==== + It will only consume files from the _bar_ folder if a _done file_ exists in the same directory as the target files. Camel will automatically delete the _done file_ when it's done consuming the files. @@ -754,11 +809,33 @@ After you have written a file, you may want to write an additional _done file_ a to indicate to others that the file is finished and has been written. To do that, you can use the `doneFileName` option on the file producer endpoint. +[tabs] +==== +Java:: ++ [source,java] ---- .to("file:bar?doneFileName=done"); ---- +XML:: ++ +[source,xml] +---- + +---- + +YAML:: ++ +[source,yaml] +---- +- to: + uri: file:bar + parameters: + doneFileName: done +---- +==== + This will create a file named `done` in the same directory as the target file. @@ -935,11 +1012,33 @@ Camel supports Idempotent Consumer directly within the component, so it will skip already processed files. This feature can be enabled by setting the `idempotent=true` option. +[tabs] +==== +Java:: ++ [source,java] ---- from("file://inbox?idempotent=true").to("..."); ---- +XML:: ++ +[source,xml] +---- + +---- + +YAML:: ++ +[source,yaml] +---- +- from: + uri: file://inbox + parameters: + idempotent: true +---- +==== + Camel uses the absolute file name as the idempotent key, to detect duplicate files. You can customize this key by using an expression in the idempotentKey option. For example, to use both @@ -1113,11 +1212,33 @@ See the URI options above for more information. The sample below demonstrates how to use it: +[tabs] +==== +Java:: ++ [source,java] ---- from("file://inbox?antInclude=**/*.txt").to("..."); ---- +XML:: ++ +[source,xml] +---- + +---- + +YAML:: ++ +[source,yaml] +---- +- from: + uri: file://inbox + parameters: + antInclude: "**/*.txt" +---- +==== + === Sorting Strategies Camel supports pluggable sorting strategies. They are described below. @@ -1262,6 +1383,7 @@ If you want to use the Camel Error Handler to deal with any exception occurring in the file consumer, then you can enable the `bridgeErrorHandler` option as shown below: +._Java-only: `onException` error handler configuration is Java DSL specific_ [source,java] ---- // to handle any IOException being thrown From d58fef5f08dd71b86c232e9904b8bb434092e48c Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 19:26:00 +0200 Subject: [PATCH 08/87] CAMEL-23789: Make HTTP component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/http-component.adoc | 275 +++++++++++++++--- 1 file changed, 229 insertions(+), 46 deletions(-) diff --git a/components/camel-http/src/main/docs/http-component.adoc b/components/camel-http/src/main/docs/http-component.adoc index d466543344fd8..26fa4c6229550 100644 --- a/components/camel-http/src/main/docs/http-component.adoc +++ b/components/camel-http/src/main/docs/http-component.adoc @@ -105,6 +105,7 @@ the HTTP component will appear to hang for that duration. To avoid this, you can disable automatic retries on the component: +._Java-only: programmatic `HttpComponent` configuration_ [source,java] ---- HttpComponent httpComponent = context.getComponent("https", HttpComponent.class); @@ -184,12 +185,45 @@ YAML:: You can override the HTTP endpoint URI by adding a header with the key `Exchange.HTTP_URI` on the message. +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------ +---- from("direct:start") - .setHeader(Exchange.HTTP_URI, constant("http://newhost")) + .setHeader("CamelHttpUri", constant("http://newhost")) .to("http://oldhost"); ------------------------------------------------------------ +---- + +XML:: ++ +[source,xml] +---- + + + + http://newhost + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelHttpUri + constant: "http://newhost" + - to: + uri: http://oldhost +---- +==== In the sample above, Camel will call the http://newhost despite the endpoint is configured with http://oldhost. + @@ -240,37 +274,67 @@ YAML:: Or options provided in a header: +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------------------------------- +---- from("direct:start") - .setHeader(Exchange.HTTP_QUERY, constant("order=123&detail=short")) + .setHeader("CamelHttpQuery", constant("order=123&detail=short")) .to("http://oldhost"); ---------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + order=123&detail=short + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelHttpQuery + constant: "order=123&detail=short" + - to: + uri: http://oldhost +---- +==== === How to set the http method (GET/PATCH/POST/PUT/DELETE/HEAD/OPTIONS/TRACE) to the HTTP producer The HTTP component provides a way to set the HTTP request method by setting the message header. Here is an example: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------------------ +---- from("direct:start") - .setHeader(Exchange.HTTP_METHOD, constant(org.apache.camel.component.http.HttpMethods.POST)) + .setHeader("CamelHttpMethod", constant("POST")) .to("http://www.google.com") .to("mock:results"); ------------------------------------------------------------------------------------------------ - -The method can be written a bit shorter using the string constants: - -[source,java] ------------------------------------------------ -.setHeader("CamelHttpMethod", constant("POST")) ------------------------------------------------ - -And the equivalent XML DSL: +---- +XML:: ++ [source,xml] ---------------------------------------------------------------------- +---- @@ -279,7 +343,25 @@ And the equivalent XML DSL: ---------------------------------------------------------------------- +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelHttpMethod + constant: POST + - to: + uri: http://www.google.com + - to: + uri: mock:results +---- +==== === Using client timeout - SO_TIMEOUT @@ -338,6 +420,7 @@ To avoid System properties conflicts, you can set proxy configuration only from the CamelContext or URI. + Java DSL : +._Java-only: programmatic `CamelContext` global options configuration (deprecated)_ [source,java] --------------------------------------------------------------- context.getGlobalOptions().put("http.proxyHost", "172.168.18.9"); @@ -370,6 +453,7 @@ IMPORTANT: Using GlobalOptions (as shown above) is deprecated. Instead, configur If you are using `POST` to send data you can configure the `charset` using the `Exchange` property: +._Java-only: setting exchange property programmatically_ [source,java] ---------------------------------------------------------- exchange.setProperty(Exchange.CHARSET_NAME, "ISO-8859-1"); @@ -380,13 +464,53 @@ exchange.setProperty(Exchange.CHARSET_NAME, "ISO-8859-1"); This sample polls the Google homepage every 10 seconds and write the page to the file `message.html`: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------- +---- from("timer://foo?fixedRate=true&delay=0&period=10000") .to("http://www.google.com") - .setHeader(FileComponent.HEADER_FILE_NAME, "message.html") + .setHeader("CamelFileName", constant("message.html")) .to("file:target/google"); ------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + message.html + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: timer://foo + parameters: + fixedRate: true + delay: 0 + period: 10000 + steps: + - to: + uri: http://www.google.com + - setHeader: + name: CamelFileName + constant: message.html + - to: + uri: file:target/google +---- +==== ==== URI Parameters from the endpoint URI @@ -395,6 +519,7 @@ would have typed in a web browser. Multiple URI parameters can of course be set using the `&` character as separator, just as you would in the web browser. Camel does no tricks here. +._Java-only: uses `ProducerTemplate` test API_ [source,java] ----------------------------------------------------------------- // we query for Camel at the Google page @@ -403,6 +528,7 @@ template.sendBody("http://www.google.com/search?q=Camel", null); ==== URI Parameters from the Message +._Java-only: uses `ProducerTemplate` test API with headers_ [source,java] ------------------------------------------------------------------ Map headers = new HashMap(); @@ -420,15 +546,14 @@ You can get the HTTP response code from the HTTP component by getting the value from the Out message header with `Exchange.HTTP_RESPONSE_CODE`. +._Java-only: uses `ProducerTemplate` and `Processor` to inspect response code_ [source,java] ------------------------------------------------------------------------------------ -Exchange exchange = template.send("http://www.google.com/search", new Processor() { - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(Exchange.HTTP_QUERY, constant("hl=en&q=activemq")); - } +Exchange exchange = template.send("http://www.google.com/search", e -> { + e.getIn().setHeader("CamelHttpQuery", "hl=en&q=activemq"); }); -Message out = exchange.getOut(); -int responseCode = out.getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class); +Message out = exchange.getMessage(); +int responseCode = out.getHeader("CamelHttpResponseCode", Integer.class); ------------------------------------------------------------------------------------ === Defining specific properties of Apache HTTP client via Camel parameters @@ -467,30 +592,84 @@ To get an access token from an Authorization Server and fill that in Authorizati In below example camel will do an underlying request to `https://localhost:8080/realms/master/protocol/openid-connect/token` using provided credentials (client id and client secret), then will get `access_token` from response and lastly will fill it at `Authorization` header of request which will be done to `https://localhost:9090`. +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------- -String clientId = "my-client-id"; -String clientSecret = "my-client-secret"; -String tokenEndpoint = "https://localhost:8080/realms/master/protocol/openid-connect/token"; -String scope = "my-scope"; // optional scope - +---- from("direct:start") - .to("https://localhost:9090/?oauth2ClientId=" + clientId + "&oauth2ClientSecret=" + clientSecret + "&oauth2TokenEndpoint=" + tokenEndpoint + "&oauth2Scope=" + scope); ------------------------------------------------------------------------------------- + .to("https://localhost:9090/?oauth2ClientId=my-client-id&oauth2ClientSecret=my-client-secret&oauth2TokenEndpoint=https://localhost:8080/realms/master/protocol/openid-connect/token&oauth2Scope=my-scope"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: "https://localhost:9090/" + parameters: + oauth2ClientId: my-client-id + oauth2ClientSecret: my-client-secret + oauth2TokenEndpoint: "https://localhost:8080/realms/master/protocol/openid-connect/token" + oauth2Scope: my-scope +---- +==== Additional support for OAuth2 is for RFC 8707 where a _Resource Indicator_ must be provided in the body: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------- -String clientId = "my-client-id"; -String clientSecret = "my-client-secret"; -String tokenEndpoint = "https://localhost:8080/realms/master/protocol/openid-connect/token"; -String scope = "my-scope"; // optional scope -String resourceIndicator = "https://localhost:9090"; // optional, for RFC 8707 - +---- from("direct:start") - .to("https://localhost:9090/?oauth2ClientId=" + clientId + "&oauth2ClientSecret=" + clientSecret + "&oauth2TokenEndpoint=" + tokenEndpoint + "&oauth2Scope=" + scope + "&oauth2ResourceIndicator=" + resourceIndicator); ------------------------------------------------------------------------------------- + .to("https://localhost:9090/?oauth2ClientId=my-client-id&oauth2ClientSecret=my-client-secret&oauth2TokenEndpoint=https://localhost:8080/realms/master/protocol/openid-connect/token&oauth2Scope=my-scope&oauth2ResourceIndicator=https://localhost:9090"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: "https://localhost:9090/" + parameters: + oauth2ClientId: my-client-id + oauth2ClientSecret: my-client-secret + oauth2TokenEndpoint: "https://localhost:8080/realms/master/protocol/openid-connect/token" + oauth2Scope: my-scope + oauth2ResourceIndicator: "https://localhost:9090" +---- +==== NOTE: Resource Indicator is the URL to the actual endpoint as defined in the component URI. @@ -521,6 +700,7 @@ to use the utility with the HTTP component. [[HTTP-Programmaticconfigurationofthecomponent]] Programmatic configuration of the component +._Java-only: programmatic `SSLContextParameters` setup_ [source,java] --------------------------------------------------------------------------------------- KeyStoreParameters ksp = new KeyStoreParameters(); @@ -574,6 +754,7 @@ configuration on the http client if you need full control of it. However, if you _just_ want to specify the keystore and truststore, you can do this with Apache HTTP `HttpClientConfigurer`, for example: +._Java-only: programmatic `KeyStore` and `SchemeRegistry` setup_ [source,java] ------------------------------------------------------------------------------------------------------ KeyStore keystore = ...; @@ -588,6 +769,7 @@ And then you need to create a class that implements keystore or truststore per the example above. Then, from your camel route builder class, you can hook it up like so: +._Java-only: programmatic `HttpClientConfigurer` setup_ [source,java] -------------------------------------------------------------------------------------- HttpComponent httpComponent = getContext().getComponent("http", HttpComponent.class); @@ -618,6 +800,7 @@ The problem was eventually resolved by providing a custom configured * 1. Create a (Spring) factory for HttpContexts: +._Java-only: custom `HttpContext` factory for preemptive basic authentication_ [source,java] ------------------------------------------------------------------ public class HttpContextFactory { From c1b3e01a64cad7368b6360833aa9d39276cc9df8 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 19:26:03 +0200 Subject: [PATCH 09/87] CAMEL-23789: Make SQL component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/sql-component.adoc | 53 ++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/components/camel-sql/src/main/docs/sql-component.adoc b/components/camel-sql/src/main/docs/sql-component.adoc index 24b10f99095b0..d0ca70c5298db 100644 --- a/components/camel-sql/src/main/docs/sql-component.adoc +++ b/components/camel-sql/src/main/docs/sql-component.adoc @@ -145,7 +145,7 @@ the size of the outer iterator determines the batch size. You can use the option `useMessageBodyForSql` that allows to use the message body as the SQL statement, and then the SQL parameters must be provided in a header with the -key `SqlConstants.SQL_PARAMETERS`. This allows the SQL component to work +key `CamelSqlParameters`. This allows the SQL component to work more dynamically as the SQL query is from the message body. Use templating (such as xref:components::velocity-component.adoc[Velocity], xref:components::freemarker-component.adoc[Freemarker]) for conditional processing, e.g., to include or exclude `where` clauses @@ -211,6 +211,10 @@ The producer supports `outputType=StreamList` that uses an iterator to stream th This allows processing the data in a streaming fashion which, for example, can be used by the Splitter EIP to process each row one at a time, and load data from the database as needed. +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:withSplitModel") @@ -222,6 +226,49 @@ from("direct:withSplitModel") .end(); ---- +XML:: ++ +[source,xml] +---- + + + + + + ${body} + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:withSplitModel + steps: + - to: + uri: "sql:select * from projects order by id" + parameters: + outputType: StreamList + outputClass: org.apache.camel.component.sql.ProjectModel + - to: + uri: log:stream + - split: + expression: + simple: "${body}" + streaming: true + steps: + - to: + uri: log:row + - to: + uri: mock:result +---- +==== + === Generated keys If you insert data using SQL INSERT, then the RDBMS may support auto @@ -519,6 +566,7 @@ YAML:: Then the IN query can use a header with the key names with the dynamic values such as: +._Java-only: uses `ProducerTemplate` test API_ [source,java] ---- // use an array @@ -600,12 +648,13 @@ the custom data source. For example in the code snippet below, we set the header `CamelSqlDataSource` with a custom `javax.sql.DataSource` instance. +._Java-only: requires setting a `DataSource` object reference programmatically_ [source,java] ---- DataSource custom = ... from("direct:query") - .setHeader("CamelSqlDataSource", custom) + .setHeader("CamelSqlDataSource", constant(custom)) .to("sql:query.sql") .to("bean:processData"); ---- From b75abc5ca011bdce881be878776cdc26ad8829b6 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:07:31 +0200 Subject: [PATCH 10/87] CAMEL-23789: Make gRPC component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/grpc-component.adoc | 403 +++++++++++++++--- 1 file changed, 343 insertions(+), 60 deletions(-) diff --git a/components/camel-grpc/src/main/docs/grpc-component.adoc b/components/camel-grpc/src/main/docs/grpc-component.adoc index 559dbe3c0fb29..6c363e9c0c50f 100644 --- a/components/camel-grpc/src/main/docs/grpc-component.adoc +++ b/components/camel-grpc/src/main/docs/grpc-component.adoc @@ -103,17 +103,41 @@ It is not possible to create a universal proxy-route for all methods, so you nee For unary requests, it is enough to write the following code: +[tabs] +==== +Java:: ++ [source,java] ---- -from("grpc://localhost:1101" + - "/org.apache.camel.component.grpc.PingPong" -) - .toD("grpc://remotehost:1101" + - "/org.apache.camel.component.grpc.PingPong" + - "?method=${header.CamelGrpcMethodName}" - ) +from("grpc://localhost:1101/org.apache.camel.component.grpc.PingPong") + .toD("grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong?method=${header.CamelGrpcMethodName}"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: grpc://localhost:1101/org.apache.camel.component.grpc.PingPong + steps: + - toD: + uri: grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong + parameters: + method: "${header.CamelGrpcMethodName}" +---- +==== + === Server streaming Server streaming may be done by the same approach as unary, but in that configuration Camel route will wait stream for completion and will aggregate all responses to a list before sending that data as response stream. @@ -127,24 +151,61 @@ If this behavior is unacceptable, you need to apply a number of options: Example: +[tabs] +==== +Java:: ++ [source,java] ---- -from("grpc://localhost:1101" + - "/org.apache.camel.component.grpc.PingPong" + - "?routeControlledStreamObserver=true" -) - .toD("grpc://remotehost:1101" + - "/org.apache.camel.component.grpc.PingPong" + - "?method=${header.CamelGrpcMethodName}" + - "&streamRepliesTo=direct:next" + - "&forwardOnError=true" + - "&forwardOnCompleted=true" + - "&inheritExchangePropertiesForReplies=true" - ); +from("grpc://localhost:1101/org.apache.camel.component.grpc.PingPong?routeControlledStreamObserver=true") + .toD("grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong?method=${header.CamelGrpcMethodName}&streamRepliesTo=direct:next&forwardOnError=true&forwardOnCompleted=true&inheritExchangePropertiesForReplies=true"); from("direct:next") - .to("grpc://dummy:0/?toRouteControlledStreamObserver=true"); + .to("grpc://dummy:0/?toRouteControlledStreamObserver=true"); +---- + +XML:: ++ +[source,xml] ---- + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: grpc://localhost:1101/org.apache.camel.component.grpc.PingPong + parameters: + routeControlledStreamObserver: true + steps: + - toD: + uri: grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong + parameters: + method: "${header.CamelGrpcMethodName}" + streamRepliesTo: direct:next + forwardOnError: true + forwardOnCompleted: true + inheritExchangePropertiesForReplies: true +- route: + from: + uri: direct:next + steps: + - to: + uri: grpc://dummy:0/ + parameters: + toRouteControlledStreamObserver: true +---- +==== === Client streaming and bidirectional streaming @@ -159,89 +220,311 @@ But there is another thing: requests also come in streaming mode. So you need th Example: +[tabs] +==== +Java:: ++ [source,java] ---- -from("grpc://localhost:1101" + - "/org.apache.camel.component.grpc.PingPong" + - "?routeControlledStreamObserver=true" + - "&consumerStrategy=DELEGATION" + - "&forwardOnError=true" + - "&forwardOnCompleted=true" -) - .toD("grpc://remotehost:1101" + - "/org.apache.camel.component.grpc.PingPong" + - "?method=${header.CamelGrpcMethodName}" + - "&producerStrategy=STREAMING" + - "&streamRepliesTo=direct:next" + - "&forwardOnError=true" + - "&forwardOnCompleted=true" + - "&inheritExchangePropertiesForReplies=true" - ); +from("grpc://localhost:1101/org.apache.camel.component.grpc.PingPong?routeControlledStreamObserver=true&consumerStrategy=DELEGATION&forwardOnError=true&forwardOnCompleted=true") + .toD("grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong?method=${header.CamelGrpcMethodName}&producerStrategy=STREAMING&streamRepliesTo=direct:next&forwardOnError=true&forwardOnCompleted=true&inheritExchangePropertiesForReplies=true"); from("direct:next") - .to("grpc://dummy:0/?toRouteControlledStreamObserver=true"); + .to("grpc://dummy:0/?toRouteControlledStreamObserver=true"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + + + +---- + +YAML:: ++ +[source,yaml] ---- +- route: + from: + uri: grpc://localhost:1101/org.apache.camel.component.grpc.PingPong + parameters: + routeControlledStreamObserver: true + consumerStrategy: DELEGATION + forwardOnError: true + forwardOnCompleted: true + steps: + - toD: + uri: grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong + parameters: + method: "${header.CamelGrpcMethodName}" + producerStrategy: STREAMING + streamRepliesTo: direct:next + forwardOnError: true + forwardOnCompleted: true + inheritExchangePropertiesForReplies: true +- route: + from: + uri: direct:next + steps: + - to: + uri: grpc://dummy:0/ + parameters: + toRouteControlledStreamObserver: true +---- +==== == Examples Below is a simple synchronous method invoke with host and port parameters +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------- +---- from("direct:grpc-sync") -.to("grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong?method=sendPing&synchronous=true"); -------------------------------------------------------------------------------- + .to("grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong?method=sendPing&synchronous=true"); +---- +XML:: ++ [source,xml] ---------------------------------------------------------------------------------------- +---- - - + + ---------------------------------------------------------------------------------------- +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:grpc-sync + steps: + - to: + uri: grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong + parameters: + method: sendPing + synchronous: true +---- +==== An asynchronous method invoke +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------- +---- from("direct:grpc-async") -.to("grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong?method=pingAsyncResponse"); -------------------------------------------------------------------------------- + .to("grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong?method=pingAsyncResponse"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:grpc-async + steps: + - to: + uri: grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong + parameters: + method: pingAsyncResponse +---- +==== gRPC service consumer with propagation consumer strategy +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------- +---- from("grpc://localhost:1101/org.apache.camel.component.grpc.PingPong?consumerStrategy=PROPAGATION") -.to("direct:grpc-service"); -------------------------------------------------------------------------------- + .to("direct:grpc-service"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: grpc://localhost:1101/org.apache.camel.component.grpc.PingPong + parameters: + consumerStrategy: PROPAGATION + steps: + - to: + uri: direct:grpc-service +---- +==== gRPC service producer with streaming producer strategy (requires a service that uses "stream" mode as input and output) +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------- +---- from("direct:grpc-request-stream") -.to("grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong?method=PingAsyncAsync&producerStrategy=STREAMING&streamRepliesTo=direct:grpc-response-stream"); + .to("grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong?method=PingAsyncAsync&producerStrategy=STREAMING&streamRepliesTo=direct:grpc-response-stream"); from("direct:grpc-response-stream") -.log("Response received: ${body}"); -------------------------------------------------------------------------------- + .log("Response received: ${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:grpc-request-stream + steps: + - to: + uri: grpc://remotehost:1101/org.apache.camel.component.grpc.PingPong + parameters: + method: PingAsyncAsync + producerStrategy: STREAMING + streamRepliesTo: direct:grpc-response-stream +- route: + from: + uri: direct:grpc-response-stream + steps: + - log: "Response received: ${body}" +---- +==== gRPC service consumer TLS/SSL security negotiation enabled +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------- +---- from("grpc://localhost:1101/org.apache.camel.component.grpc.PingPong?consumerStrategy=PROPAGATION&negotiationType=TLS&keyCertChainResource=file:src/test/resources/certs/server.pem&keyResource=file:src/test/resources/certs/server.key&trustCertCollectionResource=file:src/test/resources/certs/ca.pem") -.to("direct:tls-enable") -------------------------------------------------------------------------------- + .to("direct:tls-enable"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: grpc://localhost:1101/org.apache.camel.component.grpc.PingPong + parameters: + consumerStrategy: PROPAGATION + negotiationType: TLS + keyCertChainResource: "file:src/test/resources/certs/server.pem" + keyResource: "file:src/test/resources/certs/server.key" + trustCertCollectionResource: "file:src/test/resources/certs/ca.pem" + steps: + - to: + uri: direct:tls-enable +---- +==== gRPC service producer with custom JSON Web Token (JWT) implementation authentication +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------- +---- from("direct:grpc-jwt") -.to("grpc://localhost:1101/org.apache.camel.component.grpc.PingPong?method=pingSyncSync&synchronous=true&authenticationType=JWT&jwtSecret=supersecuredsecret"); -------------------------------------------------------------------------------- + .to("grpc://localhost:1101/org.apache.camel.component.grpc.PingPong?method=pingSyncSync&synchronous=true&authenticationType=JWT&jwtSecret=supersecuredsecret"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:grpc-jwt + steps: + - to: + uri: grpc://localhost:1101/org.apache.camel.component.grpc.PingPong + parameters: + method: pingSyncSync + synchronous: true + authenticationType: JWT + jwtSecret: supersecuredsecret +---- +==== == Configuration From 617f15ce4a87e4eac8d283f764be77f705e83cce Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:07:32 +0200 Subject: [PATCH 11/87] CAMEL-23789: Make AWS Bedrock component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/aws-bedrock-component.adoc | 754 +++++++++++++++--- 1 file changed, 642 insertions(+), 112 deletions(-) diff --git a/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc b/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc index 591da05643eec..345947b52ba02 100644 --- a/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc +++ b/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc @@ -872,15 +872,46 @@ Guardrails work with all models that support the Converse API: - invokeTextModel: this operation will invoke a model from Bedrock. This is an example for both Titan Express and Titan Lite. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:invoke") - .to("aws-bedrock://test?bedrockRuntimeClient=#amazonBedrockRuntimeClient&operation=invokeTextModel&modelId=" - + BedrockModels.TITAN_TEXT_EXPRESS_V1.model)) --------------------------------------------------------------------------------- + .to("aws-bedrock://test?bedrockRuntimeClient=#amazonBedrockRuntimeClient&operation=invokeTextModel&modelId=amazon.titan-text-express-v1"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:invoke + steps: + - to: + uri: aws-bedrock://test + parameters: + bedrockRuntimeClient: "#amazonBedrockRuntimeClient" + operation: invokeTextModel + modelId: amazon.titan-text-express-v1 +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with complex JSON construction_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:invoke", exchange -> { @@ -898,27 +929,29 @@ and you can then send to the direct endpoint something like rootNode.put("textGenerationConfig", childNode); exchange.getMessage().setBody(mapper.writer().writeValueAsString(rootNode)); - exchange.getMessage().setHeader(BedrockConstants.MODEL_CONTENT_TYPE, "application/json"); - exchange.getMessage().setHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE, "application/json"); + exchange.getMessage().setHeader("CamelAwsBedrockContentType", "application/json"); + exchange.getMessage().setHeader("CamelAwsBedrockAcceptContentType", "application/json"); }); -------------------------------------------------------------------------------- where template is a ProducerTemplate. -- invokeImageModel: this operation will invoke a model from Bedrock. This is an example for both Titan Express and Titan Lite. +- invokeImageModel: this operation will invoke a model from Bedrock. This is an example for Titan Image Generator. +._Java-only: uses `unmarshal().base64()` method chain and `simple()` expression builder_ [source,java] -------------------------------------------------------------------------------- from("direct:invoke") - .to("aws-bedrock://test?bedrockRuntimeClient=#amazonBedrockRuntimeClient&operation=invokeImageModel&modelId=" - + BedrockModels.TITAN_IMAGE_GENERATOR_V1.model)) - .split(body()) - .unmarshal().base64() - .setHeader("CamelFileName", simple("image-${random(128)}.png")).to("file:target/generated_images") + .to("aws-bedrock://test?bedrockRuntimeClient=#amazonBedrockRuntimeClient&operation=invokeImageModel&modelId=amazon.titan-image-generator-v1") + .split(body()) + .unmarshal().base64() + .setHeader("CamelFileName", simple("image-${random(128)}.png")) + .to("file:target/generated_images"); -------------------------------------------------------------------------------- and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with complex JSON construction_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:send_titan_image", exchange -> { @@ -940,8 +973,8 @@ and you can then send to the direct endpoint something like rootNode.putIfAbsent("imageGenerationConfig", childNode); exchange.getMessage().setBody(mapper.writer().writeValueAsString(rootNode)); - exchange.getMessage().setHeader(BedrockConstants.MODEL_CONTENT_TYPE, "application/json"); - exchange.getMessage().setHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE, "application/json"); + exchange.getMessage().setHeader("CamelAwsBedrockContentType", "application/json"); + exchange.getMessage().setHeader("CamelAwsBedrockAcceptContentType", "application/json"); }); -------------------------------------------------------------------------------- @@ -949,16 +982,51 @@ where template is a ProducerTemplate. - invokeEmbeddingsModel: this operation will invoke an Embeddings model from Bedrock. This is an example for Titan Embeddings G1. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:send_titan_embeddings") - .to("aws-bedrock:label?useDefaultCredentialsProvider=true®ion=us-east-1&operation=invokeEmbeddingsModel&modelId=" - + BedrockModels.TITAN_EMBEDDINGS_G1.model) - .to(result); --------------------------------------------------------------------------------- + .to("aws-bedrock:label?useDefaultCredentialsProvider=true®ion=us-east-1&operation=invokeEmbeddingsModel&modelId=amazon.titan-embed-text-v1") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:send_titan_embeddings + steps: + - to: + uri: aws-bedrock:label + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: invokeEmbeddingsModel + modelId: amazon.titan-embed-text-v1 + - to: + uri: mock:result +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with complex JSON construction_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:send_titan_embeddings", exchange -> { @@ -968,8 +1036,8 @@ and you can then send to the direct endpoint something like new TextNode("A Sci-fi camel running in the desert")); exchange.getMessage().setBody(mapper.writer().writeValueAsString(rootNode)); - exchange.getMessage().setHeader(BedrockConstants.MODEL_CONTENT_TYPE, "application/json"); - exchange.getMessage().setHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE, "*/*"); + exchange.getMessage().setHeader("CamelAwsBedrockContentType", "application/json"); + exchange.getMessage().setHeader("CamelAwsBedrockAcceptContentType", "*/*"); }); -------------------------------------------------------------------------------- @@ -977,17 +1045,52 @@ where template is a ProducerTemplate. - invokeTextModelStreaming (Complete Mode): this operation will invoke a model from Bedrock with streaming, accumulating the complete response. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:stream_complete") - .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=invokeTextModelStreaming&modelId=" + BedrockModels.TITAN_TEXT_EXPRESS_V1.model - + "&streamOutputMode=complete") + .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1&operation=invokeTextModelStreaming&modelId=amazon.titan-text-express-v1&streamOutputMode=complete") .to("log:response"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:stream_complete + steps: + - to: + uri: aws-bedrock://test + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: invokeTextModelStreaming + modelId: amazon.titan-text-express-v1 + streamOutputMode: complete + - to: + uri: log:response +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with complex JSON construction_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:stream_complete", exchange -> { @@ -1004,33 +1107,75 @@ and you can then send to the direct endpoint something like rootNode.put("textGenerationConfig", childNode); exchange.getMessage().setBody(mapper.writer().writeValueAsString(rootNode)); - exchange.getMessage().setHeader(BedrockConstants.MODEL_CONTENT_TYPE, "application/json"); - exchange.getMessage().setHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE, "application/json"); + exchange.getMessage().setHeader("CamelAwsBedrockContentType", "application/json"); + exchange.getMessage().setHeader("CamelAwsBedrockAcceptContentType", "application/json"); }); // Get the complete response String response = result.getMessage().getBody(String.class); // Get streaming metadata - Integer tokenCount = result.getMessage().getHeader(BedrockConstants.STREAMING_TOKEN_COUNT, Integer.class); - String completionReason = result.getMessage().getHeader(BedrockConstants.STREAMING_COMPLETION_REASON, String.class); - Integer chunkCount = result.getMessage().getHeader(BedrockConstants.STREAMING_CHUNK_COUNT, Integer.class); + Integer tokenCount = result.getMessage().getHeader("CamelAwsBedrockTokenCount", Integer.class); + String completionReason = result.getMessage().getHeader("CamelAwsBedrockCompletionReason", String.class); + Integer chunkCount = result.getMessage().getHeader("CamelAwsBedrockChunkCount", Integer.class); -------------------------------------------------------------------------------- - invokeTextModelStreaming (Chunks Mode): this operation will invoke a model from Bedrock with streaming, emitting individual chunks. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:stream_chunks") - .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=invokeTextModelStreaming&modelId=" + BedrockModels.ANTROPHIC_CLAUDE_V35_2.model - + "&streamOutputMode=chunks") + .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1&operation=invokeTextModelStreaming&modelId=anthropic.claude-3-5-sonnet-20241022-v2:0&streamOutputMode=chunks") .split(body()) - .to("websocket:chat-output"); // Send each chunk to websocket --------------------------------------------------------------------------------- + .to("websocket:chat-output"); +---- + +XML:: ++ +[source,xml] +---- + + + + + ${body} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:stream_chunks + steps: + - to: + uri: aws-bedrock://test + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: invokeTextModelStreaming + modelId: "anthropic.claude-3-5-sonnet-20241022-v2:0" + streamOutputMode: chunks + - split: + expression: + simple: "${body}" + steps: + - to: + uri: websocket:chat-output +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with complex JSON construction_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:stream_chunks", exchange -> { @@ -1055,8 +1200,8 @@ and you can then send to the direct endpoint something like rootNode.put("anthropic_version", "bedrock-2023-05-31"); exchange.getMessage().setBody(mapper.writer().writeValueAsString(rootNode)); - exchange.getMessage().setHeader(BedrockConstants.MODEL_CONTENT_TYPE, "application/json"); - exchange.getMessage().setHeader(BedrockConstants.MODEL_ACCEPT_CONTENT_TYPE, "application/json"); + exchange.getMessage().setHeader("CamelAwsBedrockContentType", "application/json"); + exchange.getMessage().setHeader("CamelAwsBedrockAcceptContentType", "application/json"); }); // Get the list of chunks @@ -1070,16 +1215,51 @@ and you can then send to the direct endpoint something like - converse: this operation uses the unified Converse API for model-agnostic conversations. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:converse") - .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=converse&modelId=" + BedrockModels.ANTROPHIC_CLAUDE_V3.model) + .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1&operation=converse&modelId=anthropic.claude-3-sonnet-20240229-v1:0") .to("log:response"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:converse + steps: + - to: + uri: aws-bedrock://test + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: converse + modelId: "anthropic.claude-3-sonnet-20240229-v1:0" + - to: + uri: log:response +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with AWS SDK objects_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:converse", exchange -> { @@ -1091,7 +1271,7 @@ and you can then send to the direct endpoint something like .fromText("What is Apache Camel and what are its main features?")) .build()); - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_MESSAGES, messages); + exchange.getMessage().setHeader("CamelAwsBedrockConverseMessages", messages); // Optional: Add inference configuration software.amazon.awssdk.services.bedrockruntime.model.InferenceConfiguration inferenceConfig @@ -1099,22 +1279,22 @@ and you can then send to the direct endpoint something like .maxTokens(500) .temperature(0.7f) .build(); - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_INFERENCE_CONFIG, inferenceConfig); + exchange.getMessage().setHeader("CamelAwsBedrockConverseInferenceConfig", inferenceConfig); // Optional: Add system prompt List systemPrompt = new ArrayList<>(); systemPrompt.add(software.amazon.awssdk.services.bedrockruntime.model.SystemContentBlock .fromText("You are a helpful assistant that explains software concepts clearly and concisely.")); - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_SYSTEM, systemPrompt); + exchange.getMessage().setHeader("CamelAwsBedrockConverseSystem", systemPrompt); }); // Get the response text String response = result.getMessage().getBody(String.class); // Get metadata from headers - String stopReason = result.getMessage().getHeader(BedrockConstants.CONVERSE_STOP_REASON, String.class); + String stopReason = result.getMessage().getHeader("CamelAwsBedrockConverseStopReason", String.class); software.amazon.awssdk.services.bedrockruntime.model.TokenUsage usage - = result.getMessage().getHeader(BedrockConstants.CONVERSE_USAGE, + = result.getMessage().getHeader("CamelAwsBedrockConverseUsage", software.amazon.awssdk.services.bedrockruntime.model.TokenUsage.class); System.out.println("Response: " + response); @@ -1125,16 +1305,51 @@ and you can then send to the direct endpoint something like - converseStream (Complete Mode): this operation uses the Converse API with streaming, accumulating the complete response. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:converse_stream") - .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=converseStream&modelId=" + BedrockModels.ANTROPHIC_CLAUDE_V3.model) + .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1&operation=converseStream&modelId=anthropic.claude-3-sonnet-20240229-v1:0") .to("log:response"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:converse_stream + steps: + - to: + uri: aws-bedrock://test + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: converseStream + modelId: "anthropic.claude-3-sonnet-20240229-v1:0" + - to: + uri: log:response +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with AWS SDK objects_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:converse_stream", exchange -> { @@ -1146,8 +1361,8 @@ and you can then send to the direct endpoint something like .fromText("Explain the Enterprise Integration Patterns in three sentences.")) .build()); - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_MESSAGES, messages); - exchange.getMessage().setHeader(BedrockConstants.STREAM_OUTPUT_MODE, "complete"); + exchange.getMessage().setHeader("CamelAwsBedrockConverseMessages", messages); + exchange.getMessage().setHeader("CamelAwsBedrockStreamOutputMode", "complete"); // Optional: Add inference configuration software.amazon.awssdk.services.bedrockruntime.model.InferenceConfiguration inferenceConfig @@ -1155,12 +1370,12 @@ and you can then send to the direct endpoint something like .maxTokens(300) .temperature(0.5f) .build(); - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_INFERENCE_CONFIG, inferenceConfig); + exchange.getMessage().setHeader("CamelAwsBedrockConverseInferenceConfig", inferenceConfig); }); // Get the complete streamed response String response = result.getMessage().getBody(String.class); - Integer chunkCount = result.getMessage().getHeader(BedrockConstants.STREAMING_CHUNK_COUNT, Integer.class); + Integer chunkCount = result.getMessage().getHeader("CamelAwsBedrockChunkCount", Integer.class); System.out.println("Response: " + response); System.out.println("Received " + chunkCount + " chunks"); @@ -1168,17 +1383,59 @@ and you can then send to the direct endpoint something like - converseStream (Chunks Mode): this operation uses the Converse API with streaming, emitting individual chunks. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:converse_stream_chunks") - .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=converseStream&modelId=" + BedrockModels.ANTROPHIC_CLAUDE_V3.model) + .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1&operation=converseStream&modelId=anthropic.claude-3-sonnet-20240229-v1:0") .split(body()) - .to("websocket:chat-output"); // Send each chunk to websocket --------------------------------------------------------------------------------- + .to("websocket:chat-output"); +---- + +XML:: ++ +[source,xml] +---- + + + + + ${body} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:converse_stream_chunks + steps: + - to: + uri: aws-bedrock://test + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: converseStream + modelId: "anthropic.claude-3-sonnet-20240229-v1:0" + - split: + expression: + simple: "${body}" + steps: + - to: + uri: websocket:chat-output +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with AWS SDK objects_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:converse_stream_chunks", exchange -> { @@ -1190,8 +1447,8 @@ and you can then send to the direct endpoint something like .fromText("Write a haiku about software integration.")) .build()); - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_MESSAGES, messages); - exchange.getMessage().setHeader(BedrockConstants.STREAM_OUTPUT_MODE, "chunks"); + exchange.getMessage().setHeader("CamelAwsBedrockConverseMessages", messages); + exchange.getMessage().setHeader("CamelAwsBedrockStreamOutputMode", "chunks"); }); // Get the list of chunks @@ -1205,16 +1462,51 @@ and you can then send to the direct endpoint something like - Multi-turn Conversation with Converse API: demonstrates maintaining conversation history. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:conversation") - .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=converse&modelId=" + BedrockModels.ANTROPHIC_CLAUDE_V3.model) + .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1&operation=converse&modelId=anthropic.claude-3-sonnet-20240229-v1:0") .to("log:response"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:conversation + steps: + - to: + uri: aws-bedrock://test + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: converse + modelId: "anthropic.claude-3-sonnet-20240229-v1:0" + - to: + uri: log:response +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with multi-turn conversation history_ [source,java] -------------------------------------------------------------------------------- // Maintain conversation history @@ -1228,13 +1520,13 @@ and you can then send to the direct endpoint something like .build()); Exchange result1 = template.send("direct:conversation", exchange -> { - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_MESSAGES, + exchange.getMessage().setHeader("CamelAwsBedrockConverseMessages", new ArrayList<>(conversationHistory)); }); // Add assistant's response to history software.amazon.awssdk.services.bedrockruntime.model.Message assistantMessage - = result1.getMessage().getHeader(BedrockConstants.CONVERSE_OUTPUT_MESSAGE, + = result1.getMessage().getHeader("CamelAwsBedrockConverseOutputMessage", software.amazon.awssdk.services.bedrockruntime.model.Message.class); conversationHistory.add(assistantMessage); @@ -1246,7 +1538,7 @@ and you can then send to the direct endpoint something like .build()); Exchange result2 = template.send("direct:conversation", exchange -> { - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_MESSAGES, + exchange.getMessage().setHeader("CamelAwsBedrockConverseMessages", new ArrayList<>(conversationHistory)); }); @@ -1258,17 +1550,54 @@ and you can then send to the direct endpoint something like - Converse with Guardrails (Endpoint Configuration): Apply guardrails configured at the endpoint level. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:converse_with_guardrails") - .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=converse&modelId=" + BedrockModels.ANTROPHIC_CLAUDE_V3.model - + "&guardrailIdentifier=abc123xyz&guardrailVersion=DRAFT&guardrailTrace=true") + .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1&operation=converse&modelId=anthropic.claude-3-sonnet-20240229-v1:0&guardrailIdentifier=abc123xyz&guardrailVersion=DRAFT&guardrailTrace=true") .to("log:response"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:converse_with_guardrails + steps: + - to: + uri: aws-bedrock://test + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: converse + modelId: "anthropic.claude-3-sonnet-20240229-v1:0" + guardrailIdentifier: abc123xyz + guardrailVersion: DRAFT + guardrailTrace: true + - to: + uri: log:response +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with AWS SDK objects_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:converse_with_guardrails", exchange -> { @@ -1280,7 +1609,7 @@ and you can then send to the direct endpoint something like .fromText("Tell me about Paris")) .build()); - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_MESSAGES, messages); + exchange.getMessage().setHeader("CamelAwsBedrockConverseMessages", messages); // Optional: Add inference configuration software.amazon.awssdk.services.bedrockruntime.model.InferenceConfiguration inferenceConfig @@ -1288,7 +1617,7 @@ and you can then send to the direct endpoint something like .maxTokens(200) .temperature(0.7f) .build(); - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_INFERENCE_CONFIG, inferenceConfig); + exchange.getMessage().setHeader("CamelAwsBedrockConverseInferenceConfig", inferenceConfig); }); // Get the response @@ -1296,7 +1625,7 @@ and you can then send to the direct endpoint something like // Check if guardrail trace is available software.amazon.awssdk.services.bedrockruntime.model.GuardrailTrace trace - = result.getMessage().getHeader(BedrockConstants.GUARDRAIL_TRACE, + = result.getMessage().getHeader("CamelAwsBedrockGuardrailTrace", software.amazon.awssdk.services.bedrockruntime.model.GuardrailTrace.class); if (trace != null) { @@ -1306,16 +1635,51 @@ and you can then send to the direct endpoint something like - Converse with Guardrails (Header Configuration): Apply guardrails configured per-message via headers. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:converse_dynamic_guardrails") - .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=converse&modelId=" + BedrockModels.ANTROPHIC_CLAUDE_V3.model) + .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1&operation=converse&modelId=anthropic.claude-3-sonnet-20240229-v1:0") .to("log:response"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:converse_dynamic_guardrails + steps: + - to: + uri: aws-bedrock://test + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: converse + modelId: "anthropic.claude-3-sonnet-20240229-v1:0" + - to: + uri: log:response +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with AWS SDK `GuardrailConfiguration` objects_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:converse_dynamic_guardrails", exchange -> { @@ -1327,7 +1691,7 @@ and you can then send to the direct endpoint something like .fromText("What is the capital of France?")) .build()); - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_MESSAGES, messages); + exchange.getMessage().setHeader("CamelAwsBedrockConverseMessages", messages); // Configure guardrail via header (can be dynamic per message) software.amazon.awssdk.services.bedrockruntime.model.GuardrailConfiguration guardrailConfig @@ -1336,7 +1700,7 @@ and you can then send to the direct endpoint something like .guardrailVersion("DRAFT") .trace(software.amazon.awssdk.services.bedrockruntime.model.GuardrailTrace.ENABLED) .build(); - exchange.getMessage().setHeader(BedrockConstants.GUARDRAIL_CONFIG, guardrailConfig); + exchange.getMessage().setHeader("CamelAwsBedrockGuardrailConfig", guardrailConfig); }); String response = result.getMessage().getBody(String.class); @@ -1345,17 +1709,53 @@ and you can then send to the direct endpoint something like - Converse Stream with Guardrails: Apply guardrails to streaming conversations. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:stream_with_guardrails") - .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=converseStream&modelId=" + BedrockModels.ANTROPHIC_CLAUDE_V3.model - + "&guardrailIdentifier=abc123xyz&guardrailVersion=DRAFT") + .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1&operation=converseStream&modelId=anthropic.claude-3-sonnet-20240229-v1:0&guardrailIdentifier=abc123xyz&guardrailVersion=DRAFT") .to("log:response"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:stream_with_guardrails + steps: + - to: + uri: aws-bedrock://test + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: converseStream + modelId: "anthropic.claude-3-sonnet-20240229-v1:0" + guardrailIdentifier: abc123xyz + guardrailVersion: DRAFT + - to: + uri: log:response +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with AWS SDK objects_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:stream_with_guardrails", exchange -> { @@ -1366,8 +1766,8 @@ and you can then send to the direct endpoint something like .fromText("Tell me a story about space exploration")) .build()); - exchange.getMessage().setHeader(BedrockConstants.CONVERSE_MESSAGES, messages); - exchange.getMessage().setHeader(BedrockConstants.STREAM_OUTPUT_MODE, "complete"); + exchange.getMessage().setHeader("CamelAwsBedrockConverseMessages", messages); + exchange.getMessage().setHeader("CamelAwsBedrockStreamOutputMode", "complete"); }); String streamedResponse = result.getMessage().getBody(String.class); @@ -1376,16 +1776,52 @@ and you can then send to the direct endpoint something like - Apply Guardrail: Validate content against a guardrail without invoking a model. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:validate_content") - .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=applyGuardrail&guardrailIdentifier=abc123xyz&guardrailVersion=DRAFT") + .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1&operation=applyGuardrail&guardrailIdentifier=abc123xyz&guardrailVersion=DRAFT") .to("log:validation_result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:validate_content + steps: + - to: + uri: aws-bedrock://test + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: applyGuardrail + guardrailIdentifier: abc123xyz + guardrailVersion: DRAFT + - to: + uri: log:validation_result +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with AWS SDK `GuardrailContentBlock` objects_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:validate_content", exchange -> { @@ -1398,8 +1834,8 @@ and you can then send to the direct endpoint something like .build()) .build()); - exchange.getMessage().setHeader(BedrockConstants.GUARDRAIL_CONTENT, content); - exchange.getMessage().setHeader(BedrockConstants.GUARDRAIL_SOURCE, "INPUT"); + exchange.getMessage().setHeader("CamelAwsBedrockGuardrailContent", content); + exchange.getMessage().setHeader("CamelAwsBedrockGuardrailSource", "INPUT"); }); // Get the action result (GUARDRAIL_INTERVENED or NONE) @@ -1409,11 +1845,11 @@ and you can then send to the direct endpoint something like System.out.println("Content was blocked by guardrail!"); // Get the assessments to see why it was blocked - List assessments = result.getMessage().getHeader(BedrockConstants.GUARDRAIL_ASSESSMENTS, List.class); + List assessments = result.getMessage().getHeader("CamelAwsBedrockGuardrailAssessments", List.class); System.out.println("Reasons: " + assessments); // Get the filtered output - List outputs = result.getMessage().getHeader(BedrockConstants.GUARDRAIL_OUTPUT, List.class); + List outputs = result.getMessage().getHeader("CamelAwsBedrockGuardrailOutput", List.class); System.out.println("Filtered content: " + outputs); } else { System.out.println("Content passed guardrail validation"); @@ -1422,16 +1858,51 @@ and you can then send to the direct endpoint something like - Apply Guardrail with POJO Request: Use the SDK request object directly for maximum control. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:validate_pojo") - .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=applyGuardrail&pojoRequest=true") + .to("aws-bedrock://test?useDefaultCredentialsProvider=true®ion=us-east-1&operation=applyGuardrail&pojoRequest=true") .to("log:validation_result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:validate_pojo + steps: + - to: + uri: aws-bedrock://test + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: applyGuardrail + pojoRequest: true + - to: + uri: log:validation_result +---- +==== and you can then send to the direct endpoint something like +._Java-only: uses `ProducerTemplate` test API with AWS SDK `ApplyGuardrailRequest` POJO_ [source,java] -------------------------------------------------------------------------------- final Exchange result = template.send("direct:validate_pojo", exchange -> { @@ -1462,25 +1933,84 @@ and you can then send to the direct endpoint something like - Content Moderation Pipeline: Combine guardrails with model invocation in a pipeline. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:moderated_conversation") - // First, validate input with guardrail - .to("aws-bedrock://validate?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=applyGuardrail&guardrailIdentifier=abc123xyz") + .to("aws-bedrock://validate?useDefaultCredentialsProvider=true®ion=us-east-1&operation=applyGuardrail&guardrailIdentifier=abc123xyz") .choice() .when(simple("${body} == 'GUARDRAIL_INTERVENED'")) .log("Input blocked by guardrail") .setBody(constant("Sorry, I cannot process this request.")) .otherwise() - // Input passed, proceed with model invocation - .to("aws-bedrock://converse?useDefaultCredentialsProvider=true®ion=us-east-1" - + "&operation=converse&modelId=" + BedrockModels.ANTROPHIC_CLAUDE_V3.model - + "&guardrailIdentifier=abc123xyz") + .to("aws-bedrock://converse?useDefaultCredentialsProvider=true®ion=us-east-1&operation=converse&modelId=anthropic.claude-3-sonnet-20240229-v1:0&guardrailIdentifier=abc123xyz") .log("Model response: ${body}") .end() .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + ${body} == 'GUARDRAIL_INTERVENED' + + Sorry, I cannot process this request. + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:moderated_conversation + steps: + - to: + uri: aws-bedrock://validate + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: applyGuardrail + guardrailIdentifier: abc123xyz + - choice: + when: + - simple: "${body} == 'GUARDRAIL_INTERVENED'" + steps: + - log: "Input blocked by guardrail" + - setBody: + constant: "Sorry, I cannot process this request." + otherwise: + steps: + - to: + uri: aws-bedrock://converse + parameters: + useDefaultCredentialsProvider: true + region: us-east-1 + operation: converse + modelId: "anthropic.claude-3-sonnet-20240229-v1:0" + guardrailIdentifier: abc123xyz + - log: "Model response: ${body}" + - to: + uri: mock:result +---- +==== == Dependencies From b8e78fe0d71e48719a9680484f58b532fd62e250 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:11:26 +0200 Subject: [PATCH 12/87] CAMEL-23789: Make AWS DynamoDB component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/aws2-ddb-component.adoc | 60 +++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/components/camel-aws/camel-aws2-ddb/src/main/docs/aws2-ddb-component.adoc b/components/camel-aws/camel-aws2-ddb/src/main/docs/aws2-ddb-component.adoc index ff1e0239a715e..b2dcdb187a48e 100644 --- a/components/camel-aws/camel-aws2-ddb/src/main/docs/aws2-ddb-component.adoc +++ b/components/camel-aws/camel-aws2-ddb/src/main/docs/aws2-ddb-component.adoc @@ -75,6 +75,7 @@ If you need more control over the `AmazonDynamoDB` instance configuration you can create your own instance and refer to it from the URI: +._Java-only: programmatic `DynamoDbClient` configuration and registry binding_ [source,java] ---------------------------------------------------- public class MyRouteBuilder extends RouteBuilder { @@ -142,6 +143,7 @@ where `$\{camel-version}` must be replaced by the actual version of Camel. - PutItem: this operation will create an entry into DynamoDB +._Java-only: uses AWS SDK `AttributeValue` builders and variable table name_ [source,java] -------------------------------------------------------------------------------- Map attributeMap = new HashMap<>(); @@ -150,16 +152,17 @@ attributeMap.put("id", AttributeValue.builder().s("1001").build()); attributeMap.put("barcode", AttributeValue.builder().s("9002811220001").build()); from("direct:start") - .setHeader(Ddb2Constants.OPERATION, constant(Ddb2Operations.PutItem)) - .setHeader(Ddb2Constants.CONSISTENT_READ, constant("true")) - .setHeader(Ddb2Constants.RETURN_VALUES, constant("ALL_OLD")) - .setHeader(Ddb2Constants.ITEM, constant(attributeMap)) - .setHeader(Ddb2Constants.ATTRIBUTE_NAMES, constant(attributeMap.keySet())) + .setHeader("CamelAwsDdbOperation", constant("PutItem")) + .setHeader("CamelAwsDdbConsistentRead", constant("true")) + .setHeader("CamelAwsDdbReturnValues", constant("ALL_OLD")) + .setHeader("CamelAwsDdbItem", constant(attributeMap)) + .setHeader("CamelAwsDdbAttributeNames", constant(attributeMap.keySet())) .to("aws2-ddb://" + tableName + "?amazonDDBClient=#client"); -------------------------------------------------------------------------------- - UpdateItem: this operation will update an entry into DynamoDB +._Java-only: uses AWS SDK `AttributeValue` and `AttributeValueUpdate` builders_ [source,java] -------------------------------------------------------------------------------- Map attributeMap = new HashMap<>(); @@ -172,14 +175,15 @@ keyMap.put("partitionKey", AttributeValue.builder().s("3000").build()); keyMap.put("sortKey", AttributeValue.builder().s("1001").build()); from("direct:start") - .setHeader(Ddb2Constants.OPERATION, constant(Ddb2Operations.UpdateItem)) - .setHeader(Ddb2Constants.UPDATE_VALUES, constant(attributeMap)) - .setHeader(Ddb2Constants.KEY, constant(keyMap)) + .setHeader("CamelAwsDdbOperation", constant("UpdateItem")) + .setHeader("CamelAwsDdbUpdateValues", constant(attributeMap)) + .setHeader("CamelAwsDdbKey", constant(keyMap)) .to("aws2-ddb://" + tableName + "?amazonDDBClient=#client"); -------------------------------------------------------------------------------- - GetItem: this operation will retrieve an entry from DynamoDB +._Java-only: uses `Processor` with AWS SDK `AttributeValue` builders_ [source,java] -------------------------------------------------------------------------------- from("direct:get") @@ -187,15 +191,16 @@ from("direct:get") final Map keyMap = new HashMap<>(); keyMap.put("table-key", AttributeValue.builder().s("1").build()); - exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.GetItem); - exchange.getIn().setHeader(Ddb2Constants.ATTRIBUTE_NAMES, constant(List.of("table-key", "message"))); - exchange.getIn().setHeader(Ddb2Constants.KEY, keyMap); + exchange.getIn().setHeader("CamelAwsDdbOperation", "GetItem"); + exchange.getIn().setHeader("CamelAwsDdbAttributeNames", constant(List.of("table-key", "message"))); + exchange.getIn().setHeader("CamelAwsDdbKey", keyMap); }) .toF("aws2-ddb://%s?amazonDDBClient=#client&consistentRead=true", tableName); -------------------------------------------------------------------------------- - DeleteItem: this operation will delete an entry from DynamoDB +._Java-only: uses `Processor` with AWS SDK `AttributeValue` builders_ [source,java] -------------------------------------------------------------------------------- from("direct:delete") @@ -203,8 +208,8 @@ from("direct:delete") final Map keyMap = new HashMap<>(); keyMap.put("table-key", AttributeValue.builder().s("1").build()); - exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.DeleteItem); - exchange.getIn().setHeader(Ddb2Constants.KEY, keyMap); + exchange.getIn().setHeader("CamelAwsDdbOperation", "DeleteItem"); + exchange.getIn().setHeader("CamelAwsDdbKey", keyMap); }) .toF("aws2-ddb://%s?amazonDDBClient=#client&consistentRead=true", tableName); -------------------------------------------------------------------------------- @@ -212,28 +217,30 @@ from("direct:delete") - ExecuteStatement (PartiQL): this operation runs a PartiQL statement against DynamoDB +._Java-only: uses `Processor` with AWS SDK `AttributeValue` builders_ [source,java] -------------------------------------------------------------------------------- from("direct:partiql") .process(exchange -> { - exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.ExecuteStatement); - exchange.getIn().setHeader(Ddb2Constants.STATEMENT, + exchange.getIn().setHeader("CamelAwsDdbOperation", "ExecuteStatement"); + exchange.getIn().setHeader("CamelAwsDdbStatement", "SELECT * FROM \"MyTable\" WHERE \"key\" = ?"); - exchange.getIn().setHeader(Ddb2Constants.STATEMENT_PARAMETERS, + exchange.getIn().setHeader("CamelAwsDdbStatementParameters", List.of(AttributeValue.builder().s("myKeyValue").build())); - exchange.getIn().setHeader(Ddb2Constants.CONSISTENT_READ, true); + exchange.getIn().setHeader("CamelAwsDdbConsistentRead", true); }) .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName); -------------------------------------------------------------------------------- - BatchExecuteStatement (PartiQL batch): this operation runs multiple PartiQL statements in a batch +._Java-only: uses `Processor` with AWS SDK `BatchStatementRequest` builders_ [source,java] -------------------------------------------------------------------------------- from("direct:batchPartiql") .process(exchange -> { - exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.BatchExecuteStatement); - exchange.getIn().setHeader(Ddb2Constants.BATCH_STATEMENTS, List.of( + exchange.getIn().setHeader("CamelAwsDdbOperation", "BatchExecuteStatement"); + exchange.getIn().setHeader("CamelAwsDdbBatchStatements", List.of( BatchStatementRequest.builder() .statement("INSERT INTO \"MyTable\" VALUE {'key': 'k1', 'data': 'v1'}") .build(), @@ -246,6 +253,7 @@ from("direct:batchPartiql") - TransactWriteItems: this operation performs a transactional write across one or more tables +._Java-only: uses `Processor` with AWS SDK `TransactWriteItem` builders_ [source,java] -------------------------------------------------------------------------------- Map item = new HashMap<>(); @@ -254,8 +262,8 @@ item.put("data", AttributeValue.builder().s("txValue").build()); from("direct:transactWrite") .process(exchange -> { - exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.TransactWriteItems); - exchange.getIn().setHeader(Ddb2Constants.TRANSACT_WRITE_ITEMS, List.of( + exchange.getIn().setHeader("CamelAwsDdbOperation", "TransactWriteItems"); + exchange.getIn().setHeader("CamelAwsDdbTransactWriteItems", List.of( TransactWriteItem.builder() .put(Put.builder().tableName("MyTable").item(item).build()) .build())); @@ -265,6 +273,7 @@ from("direct:transactWrite") - TransactGetItems: this operation performs a transactional read across one or more tables +._Java-only: uses `Processor` with AWS SDK `TransactGetItem` builders_ [source,java] -------------------------------------------------------------------------------- Map key = new HashMap<>(); @@ -272,8 +281,8 @@ key.put("key", AttributeValue.builder().s("txKey").build()); from("direct:transactGet") .process(exchange -> { - exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.TransactGetItems); - exchange.getIn().setHeader(Ddb2Constants.TRANSACT_GET_ITEMS, List.of( + exchange.getIn().setHeader("CamelAwsDdbOperation", "TransactGetItems"); + exchange.getIn().setHeader("CamelAwsDdbTransactGetItems", List.of( TransactGetItem.builder() .get(Get.builder().tableName("MyTable").key(key).build()) .build())); @@ -283,6 +292,7 @@ from("direct:transactGet") - BatchWriteItems: this operation puts or deletes multiple items in one or more tables in a single batch +._Java-only: uses AWS SDK `WriteRequest` and `PutRequest` builders_ [source,java] -------------------------------------------------------------------------------- Map item1 = new HashMap<>(); @@ -297,8 +307,8 @@ requestItems.put("MyTable", List.of( from("direct:batchWrite") .process(exchange -> { - exchange.getIn().setHeader(Ddb2Constants.OPERATION, Ddb2Operations.BatchWriteItems); - exchange.getIn().setHeader(Ddb2Constants.BATCH_WRITE_ITEMS, requestItems); + exchange.getIn().setHeader("CamelAwsDdbOperation", "BatchWriteItems"); + exchange.getIn().setHeader("CamelAwsDdbBatchWriteItems", requestItems); }) .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName); -------------------------------------------------------------------------------- From 3c303c08f9eb5691688f4e3baeebe833fa37db05 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:12:21 +0200 Subject: [PATCH 13/87] CAMEL-23789: Make Elasticsearch component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/elasticsearch-component.adoc | 62 ++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc b/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc index ec8dfbaec2737..8e6103cc16f3b 100644 --- a/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc +++ b/components/camel-elasticsearch/src/main/docs/elasticsearch-component.adoc @@ -104,6 +104,7 @@ to configure it globally at the component level thanks to the option _enableDocu === Configure the component and enable basic authentication To use the Elasticsearch component, it has to be configured with a minimum configuration. +._Java-only: programmatic component configuration_ [source,java] ---- ElasticsearchComponent elasticsearchComponent = new ElasticsearchComponent(); @@ -114,6 +115,7 @@ camelContext.addComponent("elasticsearch", elasticsearchComponent); For basic authentication with elasticsearch or using reverse http proxy in front of the elasticsearch cluster, simply setup basic authentication and SSL on the component like the example below +._Java-only: programmatic component configuration with basic authentication and SSL_ [source,java] ---- ElasticsearchComponent elasticsearchComponent = new ElasticsearchComponent(); @@ -219,6 +221,7 @@ YAML:: A client would simply need to pass a body message containing a Map to the route. The result body contains the indexId created. +._Java-only: ProducerTemplate test API_ [source,java] ---- Map map = new HashMap(); @@ -267,6 +270,7 @@ YAML:: ---- ==== +._Java-only: ProducerTemplate test API_ [source,java] ---- String query = "{\"query\":{\"match\":{\"content\":\"new release of ApacheCamel\"}}}"; @@ -276,6 +280,7 @@ HitsMetadata response = template.requestBody("direct:search", query, HitsMeta Search on specific field(s) using Map. +._Java-only: ProducerTemplate test API with `Map` query_ [source,java] ---- Map actualQuery = new HashMap<>(); @@ -330,6 +335,7 @@ YAML:: ---- ==== +._Java-only: ProducerTemplate test API with scroll iterator_ [source,java] ---- String query = "{\"query\":{\"match\":{\"content\":\"new release of ApacheCamel\"}}}"; @@ -340,16 +346,57 @@ try (ElasticsearchScrollRequestIterator response = template.requestBody("direct: xref:eips:split-eip.adoc[Split EIP] can also be used. +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:search") - .to("elasticsearch://elasticsearch?operation=Search&indexName=twitter&useScroll=true&scrollKeepAliveMs=30000") - .split() - .body() - .streaming() - .to("mock:output") - .end(); + .to("elasticsearch://elasticsearch?operation=Search&indexName=twitter&useScroll=true&scrollKeepAliveMs=30000") + .split(body()).streaming() + .to("mock:output") + .end(); +---- + +XML:: ++ +[source,xml] +---- + + + + + + + + +---- + +YAML:: ++ +[source,yaml] ---- +- route: + from: + uri: direct:search + steps: + - to: + uri: elasticsearch://elasticsearch + parameters: + operation: Search + indexName: twitter + useScroll: true + scrollKeepAliveMs: 30000 + - split: + expression: + body: {} + streaming: true + steps: + - to: + uri: mock:output +---- +==== === MultiSearch Example @@ -391,8 +438,9 @@ YAML:: ---- ==== -MultiSearch on specific field(s) +MultiSearch on specific field(s) +._Java-only: ProducerTemplate test API with Elasticsearch `MsearchRequest` builders_ [source,java] ---- MsearchRequest.Builder builder = new MsearchRequest.Builder().index("twitter").searches( From 2290d543062dec5254b327cf4cc5756d917ebe3e Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:15:15 +0200 Subject: [PATCH 14/87] CAMEL-23789: Make Salesforce component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/salesforce-component.adoc | 326 ++++++++++++++++-- 1 file changed, 302 insertions(+), 24 deletions(-) diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc b/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc index 7907f3c83f3c6..a0ad9c03b0d00 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc +++ b/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc @@ -159,16 +159,15 @@ message headers. For example, to fetch API limits, you can specify: +._Java-only: uses custom `Processor` implementation to read response headers_ [source,java] ---- // in your Camel route set the header before Salesforce endpoint -//... .setHeader("Sforce-Limit-Info", constant("api-usage")) .to("salesforce:getGlobalObjects") .to(myProcessor); -// myProcessor will receive `Sforce-Limit-Info` header on the outbound -// message +// myProcessor will receive `Sforce-Limit-Info` header on the outbound message class MyProcessor implements Processor { public void process(Exchange exchange) throws Exception { Message in = exchange.getIn(); @@ -185,6 +184,7 @@ In addition, HTTP response status code and text are available as headers `Exchan By default, SObject fields with null values are not sent to salesforce. In order to send null values to salesforce, use the `fieldsToNull` property, as follows: +._Java-only: programmatic SObject field manipulation_ [source,java] ---- accountSObject.getFieldsToNull().add("Site"); @@ -292,17 +292,65 @@ Notice how multiplying `1.0` with the integer value held in `body.dailyApiReques evaluate as with floating point arithmetic, without it - it would end up making integral division which would result with either `0` (some API limits consumed) or `1` (no API limits consumed). +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:querySalesforce") .to("salesforce:limits") .choice() - .when(spel("#{1.0 * body.dailyApiRequests.remaining / body.dailyApiRequests.max < 0.1}")) - .to("salesforce:query?...") - .otherwise() - .setBody(constant("Used up Salesforce API limits, leaving 10% for critical routes")) - .endChoice() + .when(spel("#{1.0 * body.dailyApiRequests.remaining / body.dailyApiRequests.max < 0.1}")) + .to("salesforce:query?...") + .otherwise() + .setBody(constant("Used up Salesforce API limits, leaving 10% for critical routes")) + .endChoice(); +---- + +XML:: ++ +[source,xml] +---- + + + + + + #{1.0 * body.dailyApiRequests.remaining / body.dailyApiRequests.max < 0.1} + + + + + Used up Salesforce API limits, leaving 10% for critical routes + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:querySalesforce + steps: + - to: + uri: salesforce:limits + - choice: + when: + - spel: "#{1.0 * body.dailyApiRequests.remaining / body.dailyApiRequests.max < 0.1}" + steps: + - to: + uri: "salesforce:query?..." + otherwise: + steps: + - setBody: + constant: "Used up Salesforce API limits, leaving 10% for critical routes" ---- +==== [[recent]] ===== Recently Viewed Items @@ -332,13 +380,49 @@ To fetch the recent items use `salesforce:recent` operation. This operation retu the `Id`, `Name` and `Attributes` (with `type` and `url` properties). You can limit the number of returned items by specifying `limit` parameter set to maximum number of records to return. For example: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:fetchRecentItems") - to("salesforce:recent") - .split().body() - .log("${body.name} at ${body.attributes.url}"); + .to("salesforce:recent") + .split(body()) + .log("${body.name} at ${body.attributes.url}"); +---- + +XML:: ++ +[source,xml] ---- + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:fetchRecentItems + steps: + - to: + uri: salesforce:recent + - split: + expression: + body: {} + steps: + - log: "${body.name} at ${body.attributes.url}" +---- +==== [[getGlobalObjects]] ===== Describe Global @@ -665,20 +749,61 @@ For example, to send one record for approval using values in headers use: Given a route: +[tabs] +==== +Java:: ++ [source,java] ---- -from("direct:example1")// - .setHeader("approval.ContextId", simple("${body['contextId']}")) - .setHeader("approval.NextApproverIds", simple("${body['nextApproverIds']}")) - .to("salesforce:approval?"// - + "approval.actionType=Submit"// - + "&approval.comments=this is a test"// - + "&approval.processDefinitionNameOrId=Test_Account_Process"// - + "&approval.skipEntryCriteria=true"); +from("direct:example1") + .setHeader("approval.ContextId", simple("${body['contextId']}")) + .setHeader("approval.NextApproverIds", simple("${body['nextApproverIds']}")) + .to("salesforce:approval?approval.actionType=Submit&approval.comments=this is a test&approval.processDefinitionNameOrId=Test_Account_Process&approval.skipEntryCriteria=true"); +---- + +XML:: ++ +[source,xml] +---- + + + + ${body['contextId']} + + + ${body['nextApproverIds']} + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:example1 + steps: + - setHeader: + name: approval.ContextId + simple: "${body['contextId']}" + - setHeader: + name: approval.NextApproverIds + simple: "${body['nextApproverIds']}" + - to: + uri: salesforce:approval + parameters: + approval.actionType: Submit + approval.comments: "this is a test" + approval.processDefinitionNameOrId: Test_Account_Process + approval.skipEntryCriteria: true +---- +==== + You could send a record for approval using: +._Java-only: ProducerTemplate test API_ [source,java] ---- final Map body = new HashMap<>(); @@ -737,6 +862,7 @@ strings and what values are numbers). Let's look at an example: +._Java-only: uses `SObjectComposite` builders and ProducerTemplate_ [source,java] ---- SObjectComposite composite = new SObjectComposite("38.0", true); @@ -831,6 +957,7 @@ from your database. Let's look at an example: +._Java-only: uses `SObjectTree` builders and ProducerTemplate_ [source,java] ---- Account account = ... @@ -885,6 +1012,7 @@ the result will be a `java.util.Map` with string keys and values or other `java. Let's look at an example: +._Java-only: uses `SObjectBatch` builders and ProducerTemplate_ [source,java] ---- final String acountId = ... @@ -1060,6 +1188,7 @@ When you populate a `pass:[***]Binary` field with an `InputStream`, the componen *Creating a ContentVersion with binary data:* +._Java-only: uses generated DTO classes and ProducerTemplate_ [source,java] ---- // Create ContentVersion with binary field @@ -1077,6 +1206,7 @@ template.requestBody("salesforce:createSObject", cv); *Updating a Document with binary content:* +._Java-only: uses generated DTO classes and ProducerTemplate_ [source,java] ---- // Update Document with binary field @@ -1865,18 +1995,82 @@ salesforce:subscribe:[?options] To create and subscribe to a topic +[tabs] +==== +Java:: ++ [source,java] ---- -from("salesforce:subscribe:CamelTestTopic?notifyForFields=ALL¬ifyForOperations=ALL&sObjectName=Merchandise__c&updateTopic=true&sObjectQuery=SELECT Id, Name FROM Merchandise__c")... +from("salesforce:subscribe:CamelTestTopic?notifyForFields=ALL¬ifyForOperations=ALL&sObjectName=Merchandise__c&updateTopic=true&sObjectQuery=SELECT Id, Name FROM Merchandise__c") + .to("..."); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: salesforce:subscribe:CamelTestTopic + parameters: + notifyForFields: ALL + notifyForOperations: ALL + sObjectName: Merchandise__c + updateTopic: true + sObjectQuery: "SELECT Id, Name FROM Merchandise__c" + steps: + - to: + uri: "..." ---- +==== To subscribe to an existing topic +[tabs] +==== +Java:: ++ [source,java] ---- -from("salesforce:subscribe:CamelTestTopic&sObjectName=Merchandise__c")... +from("salesforce:subscribe:CamelTestTopic?sObjectName=Merchandise__c") + .to("..."); +---- + +XML:: ++ +[source,xml] +---- + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: salesforce:subscribe:CamelTestTopic + parameters: + sObjectName: Merchandise__c + steps: + - to: + uri: "..." +---- +==== + |=== | Parameter | Type | Description| Default| Required @@ -1919,11 +2113,39 @@ salesforce:subscribe:event/ For example, to receive platform events use for the event type `Order_Event__e`: +[tabs] +==== +Java:: ++ [source,java] ---- from("salesforce:subscribe:event/Order_Event__e") + .to("..."); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: salesforce:subscribe:event/Order_Event__e + steps: + - to: + uri: "..." +---- +==== + |=== | Parameter | Type | Description| Default| Required @@ -1959,13 +2181,69 @@ salesforce:subscribe:data/__ChangeEvent ---- Here are a few examples + +[tabs] +==== +Java:: ++ [source,java] ---- -from("salesforce:subscribe:data/ChangeEvents?replayId=-1").log("being notified of all change events") -from("salesforce:subscribe:data/AccountChangeEvent?replayId=-1").log("being notified of change events for Account records") -from("salesforce:subscribe:data/Employee__ChangeEvent?replayId=-1").log("being notified of change events for Employee__c custom object") +from("salesforce:subscribe:data/ChangeEvents?replayId=-1") + .log("being notified of all change events"); + +from("salesforce:subscribe:data/AccountChangeEvent?replayId=-1") + .log("being notified of change events for Account records"); + +from("salesforce:subscribe:data/Employee__ChangeEvent?replayId=-1") + .log("being notified of change events for Employee__c custom object"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: salesforce:subscribe:data/ChangeEvents + parameters: + replayId: -1 + steps: + - log: "being notified of all change events" +- route: + from: + uri: salesforce:subscribe:data/AccountChangeEvent + parameters: + replayId: -1 + steps: + - log: "being notified of change events for Account records" +- route: + from: + uri: salesforce:subscribe:data/Employee__ChangeEvent + parameters: + replayId: -1 + steps: + - log: "being notified of change events for Employee__c custom object" +---- +==== + More details about how to use the Camel Salesforce component change data capture capabilities could be found in the https://github.com/apache/camel/tree/main/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/ChangeEventsConsumerIntegrationTest.java[ChangeEventsConsumerIntegrationTest]. The https://developer.salesforce.com/docs/atlas.en-us.change_data_capture.meta/change_data_capture/cdc_intro.htm[Salesforce developer guide] is a good fit to better know the subtleties of implementing a change data capture integration application. From 9355ca08f3a051f5b37d1e411724a118574fcffc Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:28:01 +0200 Subject: [PATCH 15/87] CAMEL-23789: Make SEDA component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/seda-component.adoc | 159 ++++++++++++------ 1 file changed, 110 insertions(+), 49 deletions(-) diff --git a/components/camel-seda/src/main/docs/seda-component.adoc b/components/camel-seda/src/main/docs/seda-component.adoc index 04aef560c8b4e..d97747dfb8ae5 100644 --- a/components/camel-seda/src/main/docs/seda-component.adoc +++ b/components/camel-seda/src/main/docs/seda-component.adoc @@ -160,11 +160,33 @@ By default, the SEDA endpoint uses a single consumer thread, but you can configure it to use concurrent consumer threads. So instead of thread pools, you can use: +[tabs] +==== +Java:: ++ [source,java] ---- from("seda:stageName?concurrentConsumers=5").process(...) ---- +XML:: ++ +[source,xml] +---- + +---- + +YAML:: ++ +[source,yaml] +---- +from: + uri: seda:stageName + parameters: + concurrentConsumers: 5 +---- +==== + As for the difference between the two, note a _thread pool_ can increase/shrink dynamically at runtime depending on load, whereas the number of concurrent consumers is always fixed. @@ -203,39 +225,56 @@ to the original caller. We send a _Hello World_ message and expect the reply to be _OK_. +[tabs] +==== +Java:: ++ [source,java] ---- - @Test - public void testSendAsync() throws Exception { - MockEndpoint mock = getMockEndpoint("mock:result"); - mock.expectedBodiesReceived("Hello World"); - - // START SNIPPET: e2 - Object out = template.requestBody("direct:start", "Hello World"); - assertEquals("OK", out); - // END SNIPPET: e2 +from("direct:start") + .to("seda:next") + .transform(constant("OK")); - MockEndpoint.assertIsSatisfied(context); - } - - @Override - protected RouteBuilder createRouteBuilder() throws Exception { - return new RouteBuilder() { - // START SNIPPET: e1 - public void configure() throws Exception { - from("direct:start") - // send it to the seda queue that is async - .to("seda:next") - // return a constant response - .transform(constant("OK")); +from("seda:next").to("mock:result"); +---- - from("seda:next").to("mock:result"); - } - // END SNIPPET: e1 - }; - } +XML:: ++ +[source,xml] +---- + + + + + OK + + + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: seda:next + - transform: + constant: "OK" +- route: + from: + uri: seda:next + steps: + - to: + uri: mock:result +---- +==== The _Hello World_ message will be consumed from the SEDA queue from another thread for further processing. Since this is from a unit test, @@ -246,43 +285,65 @@ unit test. In this example, we have defined two consumers. +[tabs] +==== +Java:: ++ [source,java] ---- - @Test - public void testSameOptionsProducerStillOkay() throws Exception { - getMockEndpoint("mock:foo").expectedBodiesReceived("Hello World"); - getMockEndpoint("mock:bar").expectedBodiesReceived("Hello World"); - - template.sendBody("seda:foo", "Hello World"); +from("seda:foo?multipleConsumers=true").routeId("foo").to("mock:foo"); +from("seda:foo?multipleConsumers=true").routeId("bar").to("mock:bar"); +---- - MockEndpoint.assertIsSatisfied(context); - } - - @Override - protected RouteBuilder createRouteBuilder() throws Exception { - return new RouteBuilder() { - @Override - public void configure() throws Exception { - from("seda:foo?multipleConsumers=true").routeId("foo").to("mock:foo"); - from("seda:foo?multipleConsumers=true").routeId("bar").to("mock:bar"); - } - }; - } +XML:: ++ +[source,xml] +---- + + + + + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + id: foo + from: + uri: seda:foo + parameters: + multipleConsumers: true + steps: + - to: + uri: mock:foo +- route: + id: bar + from: + uri: seda:foo + parameters: + multipleConsumers: true + steps: + - to: + uri: mock:bar +---- +==== Since we have specified `multipleConsumers=true` on the seda `foo` endpoint we can have those two consumers receive their own copy of the message as a kind of _publish/subscribe_ style messaging. -As the beans are part of a unit test, they simply send the message to a -mock endpoint. - === Extracting queue information. If needed, information such as queue size, etc. can be obtained without using JMX in this fashion: +._Java-only: programmatic access to `SedaEndpoint` internals_ [source,java] ---- SedaEndpoint seda = context.getEndpoint("seda:xxxx"); From 51b13d3f7443cd72abf083df4b5d399ede983f3f Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:28:20 +0200 Subject: [PATCH 16/87] CAMEL-23789: Make Bean component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../camel-bean/src/main/docs/bean-component.adoc | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/components/camel-bean/src/main/docs/bean-component.adoc b/components/camel-bean/src/main/docs/bean-component.adoc index a2ff792b0be6f..75f3eaaffd4b9 100644 --- a/components/camel-bean/src/main/docs/bean-component.adoc +++ b/components/camel-bean/src/main/docs/bean-component.adoc @@ -103,34 +103,30 @@ Java DSL comes with syntactic sugar for the xref:bean-component.adoc[Bean] component. Instead of specifying the bean explicitly as the endpoint (i.e., `to("bean:beanName")`) you can use the following syntax: +._Java-only: `.bean()` DSL shorthand for bean invocation_ [source,java] ------------------------------------------------------- -// Send a message to the bean endpoint -// and invoke method using Bean Binding. from("direct:start").bean("beanName"); -// Send a message to the bean endpoint -// and invoke given method. from("direct:start").bean("beanName", "methodName"); ------------------------------------------------------- Instead of passing the name of the reference to the bean (so that Camel will look up for it in the xref:manual::registry.adoc[Registry]), you can specify the bean itself: +._Java-only: `.bean()` DSL with inline bean instances and class references_ [source,java] --------------------------------------------------------------- -// Send a message to the given bean instance. from("direct:start").bean(new ExampleBean()); -// Explicit selection of bean method to be invoked. from("direct:start").bean(new ExampleBean(), "methodName"); -// Camel will create the instance of bean and cache it for you. from("direct:start").bean(ExampleBean.class); --------------------------------------------------------------- This bean could be a lambda if you cast the lambda to a `@FunctionalInterface` +._Java-only: lambda-based bean with `@FunctionalInterface`_ [source,java] --------------------------------------------------------------- @FunctionalInterface From 535d7de9a8b47b25e70fe4fe452b19192683e53c Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:30:26 +0200 Subject: [PATCH 17/87] chore(docs): fix unterminated listing block in mongodb docs Co-Authored-By: Claude Opus 4.6 Signed-off-by: Claus Ibsen --- components/camel-mongodb/src/main/docs/mongodb-component.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/camel-mongodb/src/main/docs/mongodb-component.adoc b/components/camel-mongodb/src/main/docs/mongodb-component.adoc index a2455b13f4d74..449ec7ce94dfd 100644 --- a/components/camel-mongodb/src/main/docs/mongodb-component.adoc +++ b/components/camel-mongodb/src/main/docs/mongodb-component.adoc @@ -794,7 +794,7 @@ from("direct:aggregate") .split(body()) .streaming() .to("mock:resultAggregate"); ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- Note that calling `.split(body())` is enough to send the entries down the route one-by-one, however it would still load all the entries into memory first. Calling `.streaming()` is thus required to load data into memory by batches. From b14506fce9324beed2d75e49a246f18eb5b20de6 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:31:02 +0200 Subject: [PATCH 18/87] CAMEL-23789: Make Vert.x HTTP component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/vertx-http-component.adoc | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/components/camel-vertx/camel-vertx-http/src/main/docs/vertx-http-component.adoc b/components/camel-vertx/camel-vertx-http/src/main/docs/vertx-http-component.adoc index 3354c54e0ad6f..70aebf6502c02 100644 --- a/components/camel-vertx/camel-vertx-http/src/main/docs/vertx-http-component.adoc +++ b/components/camel-vertx/camel-vertx-http/src/main/docs/vertx-http-component.adoc @@ -145,6 +145,7 @@ You can upload text or binary files by setting the message body as a https://ver When finer control of the Vert.x Web Client configuration is required, you can bind a custom https://vertx.io/docs/apidocs/io/vertx/ext/web/client/WebClientOptions.html[WebClientOptions] instance to the registry. +._Java-only: programmatic `WebClientOptions` configuration and registry binding_ [source,java] --------------------------- WebClientOptions options = new WebClientOptions().setMaxRedirects(5) @@ -156,11 +157,40 @@ camelContext.getRegistry.bind("clientOptions", options); Then reference the options on the `vertx-http` producer. +[tabs] +==== +Java:: ++ [source,java] ---------------------------- +---- from("direct:start") - .to("vertx-http:http://localhost:8080?webClientOptions=#clientOptions") ---------------------------- + .to("vertx-http:http://localhost:8080?webClientOptions=#clientOptions"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: vertx-http:http://localhost:8080 + parameters: + webClientOptions: "#clientOptions" +---- +==== === SSL From d894b15e3e575711488f0b98279d805231cba080 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:44:16 +0200 Subject: [PATCH 19/87] CAMEL-23789: Make Mail component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/mail-component.adoc | 109 ++++++++++++++---- 1 file changed, 89 insertions(+), 20 deletions(-) diff --git a/components/camel-mail/src/main/docs/mail-component.adoc b/components/camel-mail/src/main/docs/mail-component.adoc index a24d60938c606..409f02651533b 100644 --- a/components/camel-mail/src/main/docs/mail-component.adoc +++ b/components/camel-mail/src/main/docs/mail-component.adoc @@ -147,6 +147,7 @@ to use the utility with the mail component. [[Mail-Programmaticconfigurationoftheendpoint]] Programmatic configuration of the endpoint +._Java-only: programmatic `SSLContextParameters` configuration and registry binding_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------- KeyStoreParameters ksp = new KeyStoreParameters(); @@ -242,6 +243,7 @@ YAML:: The same applies for other MimeMessage headers such as recipients, so you can use a header property as `To`: +._Java-only: ProducerTemplate API with mail headers_ [source,java] ------------------------------------------------------------------------------------------------------------ Map headers = new HashMap(); @@ -250,7 +252,7 @@ headers.put("From", "jstrachan@apache.org"); headers.put("Subject", "Camel rocks"); headers.put("CamelFileName", "fileOne"); headers.put("org.apache.camel.test", "value"); - + String body = "Hello Claus.\nYes it does.\n\nRegards James."; template.sendBodyAndHeaders("smtp://davsclaus@apache.org", body, headers); ------------------------------------------------------------------------------------------------------------ @@ -278,13 +280,14 @@ recipients exclusively from the headers or exclusively from the pre-configured settings. It is not possible to mix and match headers and pre-configured settings. +._Java-only: ProducerTemplate API showing header override of pre-configured recipient_ [source,java] ------------------------------------------------------------------------------------------------------------- +---- Map headers = new HashMap(); headers.put("to", "davsclaus@apache.org"); template.sendBodyAndHeaders("smtp://admin@localhost?to=info@mycompany.com", "Hello World", headers); ------------------------------------------------------------------------------------------------------------- +---- ==== Opting out of header overrides (trust-boundary hardening) @@ -307,11 +310,36 @@ cannot be overridden by message headers: All four default to `true` so existing behaviour is preserved. Example: +[tabs] +==== +Java:: ++ [source,java] ---- -.to("smtp://relay@mailhost?to=safe@mycompany.com&from=noreply@mycompany.com" - + "&useHeaderRecipients=false&useHeaderFrom=false&useHeaderReplyTo=false"); +.to("smtp://relay@mailhost?to=safe@mycompany.com&from=noreply@mycompany.com&useHeaderRecipients=false&useHeaderFrom=false&useHeaderReplyTo=false"); +---- + +XML:: ++ +[source,xml] +---- + +---- + +YAML:: ++ +[source,yaml] +---- +- to: + uri: smtp://relay@mailhost + parameters: + to: "safe@mycompany.com" + from: "noreply@mycompany.com" + useHeaderRecipients: false + useHeaderFrom: false + useHeaderReplyTo: false ---- +==== NOTE: These options do *not* strip the headers from the exchange. See the xref:manual::security-model.adoc#_deployment_hardening[Deployment hardening] section of the Security Model. @@ -321,11 +349,12 @@ It is possible to set multiple recipients using a comma-separated or a semicolon-separated list. This applies both to header settings and to settings in an endpoint URI. For example: +._Java-only: programmatic header map with semicolon-separated recipients_ [source,java] ------------------------------------------------------------------------------------------------- +---- Map headers = new HashMap(); headers.put("to", "davsclaus@apache.org ; jstrachan@apache.org ; ningjiang@apache.org"); ------------------------------------------------------------------------------------------------- +---- The preceding example uses a semicolon, `;`, as the separator character. @@ -336,6 +365,7 @@ both the name and the email address of the recipient. For example, you define the following headers on the message: +._Java-only: programmatic header map construction_ [source,java] --------------------------------------------------------- Map headers = new HashMap(); @@ -469,6 +499,7 @@ The mail component supports attachments. In the sample below, we send a mail message containing a plain text message with a logo file attachment. +._Java-only: programmatic `Exchange` and attachment manipulation via Camel API_ [source,java] ------------------------------------------------------- // create an exchange with a normal body and attachment to be produced as email @@ -498,19 +529,52 @@ enable and configure SSL. This is done by logging into your Google Mail account and changing your settings to allow IMAP access. Google has extensive documentation on how to do this. +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------------- -from("imaps://imap.gmail.com?username=YOUR_USERNAME@gmail.com&password=YOUR_PASSWORD" - + "&delete=false&unseen=true&delay=60000").to("log:newmail"); -------------------------------------------------------------------------------------- +---- +from("imaps://imap.gmail.com?username=YOUR_USERNAME@gmail.com&password=YOUR_PASSWORD&delete=false&unseen=true&delay=60000") + .to("log:newmail"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: imaps://imap.gmail.com + parameters: + username: "YOUR_USERNAME@gmail.com" + password: YOUR_PASSWORD + delete: false + unseen: true + delay: 60000 + steps: + - to: + uri: log:newmail +---- +==== The preceding route polls the Google Mail inbox for new mails once every minute and logs the received messages to the `newmail` logger -category. + - Running the sample with `DEBUG` logging enabled, we can monitor the +category. +Running the sample with `DEBUG` logging enabled, we can monitor the progress in the logs: -[source,java] +[source,text] ------------------------------------------------------------------------------------------------------------------------------------------------------------------ 2008-05-08 06:32:09,640 DEBUG MailConsumer - Connecting to MailStore imaps//imap.gmail.com:993 (SSL enabled), folder=INBOX 2008-05-08 06:32:11,203 DEBUG MailConsumer - Polling mailfolder: imaps//imap.gmail.com:993 (SSL enabled), folder=INBOX @@ -526,15 +590,17 @@ mails as files. First, we define a route to poll the mailbox. As this sample is based on Google Mail, it uses the same route as shown in the SSL sample: +._Java-only: uses custom `Processor` to handle mail attachments_ [source,java] --------------------------------------------------------------------------------------- -from("imaps://imap.gmail.com?username=YOUR_USERNAME@gmail.com&password=YOUR_PASSWORD" - + "&delete=false&unseen=true&delay=60000").process(new MyMailProcessor()); +from("imaps://imap.gmail.com?username=YOUR_USERNAME@gmail.com&password=YOUR_PASSWORD&delete=false&unseen=true&delay=60000") + .process(new MyMailProcessor()); --------------------------------------------------------------------------------------- Instead of logging the mail, we use a processor where we can process the mail from java code: +._Java-only: custom `Processor` for extracting and saving attachments_ [source,java] --------------------------------------------------------------------------------- public void process(Exchange exchange) throws Exception { @@ -601,6 +667,7 @@ You can also split the attachments as byte[] to be stored as the message body. This is done by creating the expression with boolean true +._Java-only: programmatic `SplitAttachmentsExpression` configuration_ [source,java] -------------------------------------------------------------------- SplitAttachmentsExpression split = SplitAttachmentsExpression(true); @@ -657,7 +724,7 @@ back 24 hours which has Camel in the mail subject you can do: The `SimpleSearchTerm` is designed to be easily configurable from a POJO, so you can also configure it using a style in XML -[source,java] +[source,xml] --------------------------------------------------------------------------------- @@ -681,6 +748,7 @@ In Java there is a builder class to build compound `SearchTerms` using the `org.apache.camel.component.mail.SearchTermBuilder` class. This allows you to build complex terms such as: +._Java-only: programmatic `SearchTermBuilder` for complex mail filters_ [source,java] -------------------------------------------------------------- // we just want the unseen mails that are not spam @@ -703,11 +771,12 @@ You can set any of the `mail.smtp` properties which you can find in the Java Mai For example, to provide a dynamic uuid in `mail.smtp.from` (SMTP MAIL command): +._Java-only: `.method()` expression for dynamic UUID generation is Java DSL specific_ [source,java] ---- - .setHeader("from", constant("reply2me@foo.com")); - .setHeader("mail.smtp.from", method(UUID.class, "randomUUID")); - .to("smtp://mymailserver:1234?useJavaMailSessionPropertiesFromHeaders=true"); +.setHeader("from", constant("reply2me@foo.com")) +.setHeader("mail.smtp.from", method(UUID.class, "randomUUID")) +.to("smtp://mymailserver:1234?useJavaMailSessionPropertiesFromHeaders=true"); ---- NOTE: This is only supported when *not* using a custom `JavaMailSender`. From a8fe48eb63ee69fcb2bc6a6c71c7b76fe966fead Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:49:01 +0200 Subject: [PATCH 20/87] CAMEL-23789: Make AWS EventBridge component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/aws2-eventbridge-component.adoc | 689 ++++++++++++++---- 1 file changed, 542 insertions(+), 147 deletions(-) diff --git a/components/camel-aws/camel-aws2-eventbridge/src/main/docs/aws2-eventbridge-component.adoc b/components/camel-aws/camel-aws2-eventbridge/src/main/docs/aws2-eventbridge-component.adoc index f7391857860af..40ff529f810af 100644 --- a/components/camel-aws/camel-aws2-eventbridge/src/main/docs/aws2-eventbridge-component.adoc +++ b/components/camel-aws/camel-aws2-eventbridge/src/main/docs/aws2-eventbridge-component.adoc @@ -85,201 +85,513 @@ Camel-AWS2-Eventbridge component provides the following operation on the produce - PutRule: this operation creates a rule related to an eventbus +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:putRule").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(EventbridgeConstants.RULE_NAME, "firstrule"); - } - }) - .to("aws2-eventbridge://test?operation=putRule&eventPatternFile=file:src/test/resources/eventpattern.json") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:putRule") + .setHeader("CamelAwsEventbridgeRuleName", constant("firstrule")) + .to("aws2-eventbridge://test?operation=putRule&eventPatternFile=file:src/test/resources/eventpattern.json") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + firstrule + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:putRule + steps: + - setHeader: + name: CamelAwsEventbridgeRuleName + constant: firstrule + - to: + uri: aws2-eventbridge://test + parameters: + operation: putRule + eventPatternFile: "file:src/test/resources/eventpattern.json" + - to: + uri: mock:result +---- +==== This operation will create a rule named _firstrule_, and it will use a json file for defining the EventPattern. -- PutTargets: this operation will add a target to the rule +- PutTargets: this operation will add a target to the rule +._Java-only: uses AWS SDK `Target.builder()` to construct target objects_ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(EventbridgeConstants.RULE_NAME, "firstrule"); - Target target = Target.builder().id("sqs-queue").arn("arn:aws:sqs:eu-west-1:780410022472:camel-connector-test") +---- +from("direct:start") + .process(exchange -> { + exchange.getIn().setHeader("CamelAwsEventbridgeRuleName", "firstrule"); + Target target = Target.builder().id("sqs-queue") + .arn("arn:aws:sqs:eu-west-1:780410022472:camel-connector-test") .build(); - List targets = new ArrayList(); - targets.add(target); - exchange.getIn().setHeader(EventbridgeConstants.TARGETS, targets); - } - }) - .to("aws2-eventbridge://test?operation=putTargets") - .to("mock:result"); --------------------------------------------------------------------------------- + List targets = new ArrayList<>(); + targets.add(target); + exchange.getIn().setHeader("CamelAwsEventbridgeTargets", targets); + }) + .to("aws2-eventbridge://test?operation=putTargets") + .to("mock:result"); +---- This operation will add the target sqs-queue with the arn reported to the targets of the _firstrule_ rule. - RemoveTargets: this operation will remove a collection of targets from the rule +._Java-only: uses `List` to specify target IDs for removal_ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(EventbridgeConstants.RULE_NAME, "firstrule"); - List ids = new ArrayList(); - targets.add("sqs-queue"); - exchange.getIn().setHeader(EventbridgeConstants.TARGETS_IDS, targets); - } - }) - .to("aws2-eventbridge://test?operation=removeTargets") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .process(exchange -> { + exchange.getIn().setHeader("CamelAwsEventbridgeRuleName", "firstrule"); + List ids = new ArrayList<>(); + ids.add("sqs-queue"); + exchange.getIn().setHeader("CamelAwsEventbridgeTargetsIds", ids); + }) + .to("aws2-eventbridge://test?operation=removeTargets") + .to("mock:result"); +---- This operation will remove the target sqs-queue from the _firstrule_ rule. - DeleteRule: this operation will delete a rule related to an eventbus +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(EventbridgeConstants.RULE_NAME, "firstrule"); - } - }) - .to("aws2-eventbridge://test?operation=deleteRule") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelAwsEventbridgeRuleName", constant("firstrule")) + .to("aws2-eventbridge://test?operation=deleteRule") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + firstrule + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsEventbridgeRuleName + constant: firstrule + - to: + uri: aws2-eventbridge://test + parameters: + operation: deleteRule + - to: + uri: mock:result +---- +==== This operation will remove the _firstrule_ rule from the test eventbus. - EnableRule: this operation will enable a rule related to an eventbus +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(EventbridgeConstants.RULE_NAME, "firstrule"); - } - }) - .to("aws2-eventbridge://test?operation=enableRule") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelAwsEventbridgeRuleName", constant("firstrule")) + .to("aws2-eventbridge://test?operation=enableRule") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + firstrule + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsEventbridgeRuleName + constant: firstrule + - to: + uri: aws2-eventbridge://test + parameters: + operation: enableRule + - to: + uri: mock:result +---- +==== This operation will enable the _firstrule_ rule from the test eventbus. - DisableRule: this operation will disable a rule related to an eventbus +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(EventbridgeConstants.RULE_NAME, "firstrule"); - } - }) - .to("aws2-eventbridge://test?operation=disableRule") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelAwsEventbridgeRuleName", constant("firstrule")) + .to("aws2-eventbridge://test?operation=disableRule") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + firstrule + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsEventbridgeRuleName + constant: firstrule + - to: + uri: aws2-eventbridge://test + parameters: + operation: disableRule + - to: + uri: mock:result +---- +==== This operation will disable the _firstrule_ rule from the test eventbus. - ListRules: this operation will list all the rules related to an eventbus with prefix first +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(EventbridgeConstants.RULE_NAME_PREFIX, "first"); - } - }) - .to("aws2-eventbridge://test?operation=listRules") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelAwsEventbridgeRuleNamePrefix", constant("first")) + .to("aws2-eventbridge://test?operation=listRules") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + first + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsEventbridgeRuleNamePrefix + constant: first + - to: + uri: aws2-eventbridge://test + parameters: + operation: listRules + - to: + uri: mock:result +---- +==== This operation will list all the rules with prefix first from the test eventbus. - DescribeRule: this operation will describe a specified rule related to an eventbus +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(EventbridgeConstants.RULE_NAME, "firstrule"); - } - }) - .to("aws2-eventbridge://test?operation=describeRule") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelAwsEventbridgeRuleName", constant("firstrule")) + .to("aws2-eventbridge://test?operation=describeRule") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + firstrule + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsEventbridgeRuleName + constant: firstrule + - to: + uri: aws2-eventbridge://test + parameters: + operation: describeRule + - to: + uri: mock:result +---- +==== This operation will describe the _firstrule_ rule from the test eventbus. - ListTargetsByRule: this operation will return a list of targets associated with a rule +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(EventbridgeConstants.RULE_NAME, "firstrule"); - } - }) - .to("aws2-eventbridge://test?operation=listTargetsByRule") - .to("mock:result"); --------------------------------------------------------------------------------- - -this operation will return a list of targets associated with the _firstrule_ rule. +---- +from("direct:start") + .setHeader("CamelAwsEventbridgeRuleName", constant("firstrule")) + .to("aws2-eventbridge://test?operation=listTargetsByRule") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + firstrule + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsEventbridgeRuleName + constant: firstrule + - to: + uri: aws2-eventbridge://test + parameters: + operation: listTargetsByRule + - to: + uri: mock:result +---- +==== + +This operation will return a list of targets associated with the _firstrule_ rule. - ListRuleNamesByTarget: this operation will return a list of rules associated with a target +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(EventbridgeConstants.TARGET_ARN, "firstrule"); - } - }) - .to("aws2-eventbridge://test?operation=listRuleNamesByTarget") - .to("mock:result"); --------------------------------------------------------------------------------- - -this operation will return a list of rules associated with a target. +---- +from("direct:start") + .setHeader("CamelAwsEventbridgeTargetArn", constant("arn:aws:sqs:eu-west-1:123456789012:my-queue")) + .to("aws2-eventbridge://test?operation=listRuleNamesByTarget") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + arn:aws:sqs:eu-west-1:123456789012:my-queue + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsEventbridgeTargetArn + constant: "arn:aws:sqs:eu-west-1:123456789012:my-queue" + - to: + uri: aws2-eventbridge://test + parameters: + operation: listRuleNamesByTarget + - to: + uri: mock:result +---- +==== + +This operation will return a list of rules associated with a target. - PutEvent: this operation will send an event to the Servicebus +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(EventbridgeConstants.EVENT_RESOURCES_ARN, "arn:aws:sqs:eu-west-1:780410022472:camel-connector-test"); - exchange.getIn().setHeader(EventbridgeConstants.EVENT_SOURCE, "com.pippo"); - exchange.getIn().setHeader(EventbridgeConstants.EVENT_DETAIL_TYPE, "peppe"); - exchange.getIn().setBody("Test Event"); - } - }) - .to("aws2-eventbridge://test?operation=putEvent") - .to("mock:result"); --------------------------------------------------------------------------------- - -this operation will return a list of entries with related ID sent to servicebus. +---- +from("direct:start") + .setHeader("CamelAwsEventbridgeResourcesArn", constant("arn:aws:sqs:eu-west-1:780410022472:camel-connector-test")) + .setHeader("CamelAwsEventbridgeSource", constant("com.pippo")) + .setHeader("CamelAwsEventbridgeDetailType", constant("peppe")) + .setBody(constant("Test Event")) + .to("aws2-eventbridge://test?operation=putEvent") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + arn:aws:sqs:eu-west-1:780410022472:camel-connector-test + + + com.pippo + + + peppe + + + Test Event + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsEventbridgeResourcesArn + constant: "arn:aws:sqs:eu-west-1:780410022472:camel-connector-test" + - setHeader: + name: CamelAwsEventbridgeSource + constant: com.pippo + - setHeader: + name: CamelAwsEventbridgeDetailType + constant: peppe + - setBody: + constant: Test Event + - to: + uri: aws2-eventbridge://test + parameters: + operation: putEvent + - to: + uri: mock:result +---- +==== + +This operation will return a list of entries with related ID sent to servicebus. === Updating the rule @@ -393,31 +705,114 @@ The consumer auto-creates an SQS queue, wires it to the `my-rule` EventBridge ru === Consumer Example — User-Provided Queue +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -from("aws2-eventbridge://default?ruleName=my-rule" - + "&autoCreateQueue=false" - + "&queueUrl=https://sqs.us-east-1.amazonaws.com/123456789012/my-queue") +---- +from("aws2-eventbridge://default?ruleName=my-rule&autoCreateQueue=false&queueUrl=https://sqs.us-east-1.amazonaws.com/123456789012/my-queue") .log("Received: ${body}") .to("direct:process"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: aws2-eventbridge://default + parameters: + ruleName: my-rule + autoCreateQueue: false + queueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/my-queue" + steps: + - log: + message: "Received: ${body}" + - to: + uri: direct:process +---- +==== Use this when you manage the SQS queue and its policy yourself. === Consumer Example — Combined Producer and Consumer +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- // First create the rule from("direct:setup") - .to("aws2-eventbridge://default?operation=putRule" - + "&eventPatternFile=file:eventpattern.json"); + .to("aws2-eventbridge://default?operation=putRule&eventPatternFile=file:eventpattern.json"); // Consume events matching the rule from("aws2-eventbridge://default?ruleName=my-rule&delay=2000") .log("Event: ${body}") .to("mock:events"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +# First create the rule +- route: + from: + uri: direct:setup + steps: + - to: + uri: aws2-eventbridge://default + parameters: + operation: putRule + eventPatternFile: "file:eventpattern.json" + +# Consume events matching the rule +- route: + from: + uri: aws2-eventbridge://default + parameters: + ruleName: my-rule + delay: 2000 + steps: + - log: + message: "Event: ${body}" + - to: + uri: mock:events +---- +==== === IAM Permissions From 777c47c79b1c072e5845ef629a5152283724726b Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:51:08 +0200 Subject: [PATCH 21/87] CAMEL-23789: Make Reactive Streams component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/reactive-streams-component.adoc | 263 ++++++++++++++---- 1 file changed, 212 insertions(+), 51 deletions(-) diff --git a/components/camel-reactive-streams/src/main/docs/reactive-streams-component.adoc b/components/camel-reactive-streams/src/main/docs/reactive-streams-component.adoc index 0916c0479b667..8c05f4d7d7b9c 100644 --- a/components/camel-reactive-streams/src/main/docs/reactive-streams-component.adoc +++ b/components/camel-reactive-streams/src/main/docs/reactive-streams-component.adoc @@ -71,20 +71,51 @@ The library is aimed to support all the communication modes needed by an applica To subscribe to data flowing from a Camel route, exchanges should be redirected to a named stream, like in the following snippet: +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------------------- +---- from("timer:clock") -.setBody().header(Exchange.TIMER_COUNTER) -.to("reactive-streams:numbers"); ---------------------------------------------------------- + .setBody().header(Exchange.TIMER_COUNTER) + .to("reactive-streams:numbers"); +---- -Routes can also be written using the XML DSL. +XML:: ++ +[source,xml] +---- + + + +
CamelTimerCounter
+
+ +
+---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: timer:clock + steps: + - setBody: + header: CamelTimerCounter + - to: + uri: reactive-streams:numbers +---- +==== In the example, an unbounded stream of numbers is associated to the name `numbers`. The stream can be accessed using the `CamelReactiveStreams` utility class. +._Java-only: `CamelReactiveStreamsService` API to obtain a Publisher from a named stream_ [source,java] ---------------------------------------------------------- +---- CamelReactiveStreamsService camel = CamelReactiveStreams.get(context); // Getting a stream of exchanges @@ -92,18 +123,19 @@ Publisher exchanges = camel.fromStream("numbers"); // Getting a stream of Integers (using Camel standard conversion system) Publisher numbers = camel.fromStream("numbers", Integer.class); ---------------------------------------------------------- +---- The stream can be used easily with any reactive streams compatible library. Here is an example of how to use it with https://github.com/ReactiveX/RxJava[RxJava 2] (although any reactive framework can be used to process events). +._Java-only: RxJava `Flowable` consuming Camel stream_ [source,java] ---------------------------------------------------------- +---- Flowable.fromPublisher(numbers) .doOnNext(System.out::println) .subscribe(); ---------------------------------------------------------- +---- The example prints all numbers generated by Camel into `System.out`. @@ -113,8 +145,9 @@ For short Camel routes and for users that prefer defining the whole processing f using functional constructs of the reactive framework (without using the Camel DSL at all), streams can also be defined using Camel URIs. +._Java-only: direct API to create a reactive Publisher from a Camel endpoint URI_ [source,java] ---------------------------------------------------------- +---- CamelReactiveStreamsService camel = CamelReactiveStreams.get(context); // Get a stream from all the files in a directory @@ -124,7 +157,7 @@ Publisher files = camel.from("file:folder", String.class); Flowable.fromPublisher(files) .doOnNext(System.out::println) .subscribe(); ---------------------------------------------------------- +---- === Sending data to Camel When an external library needs to push events into a Camel route, the Reactive Streams @@ -165,24 +198,26 @@ YAML:: A handle to the `elements` stream can be obtained from the `CamelReactiveStreams` utility class. +._Java-only: obtaining a reactive `Subscriber` handle to push events into a Camel route_ [source,java] ---------------------------------------------------------- +---- CamelReactiveStreamsService camel = CamelReactiveStreams.get(context); Subscriber elements = camel.streamSubscriber("elements", String.class); ---------------------------------------------------------- +---- The subscriber can be used to push events to the Camel route that consumes from the `elements` stream. Here is an example of how to use it with https://github.com/ReactiveX/RxJava[RxJava 2] (although any reactive framework can be used to publish events). +._Java-only: RxJava `Flowable` publishing events into a Camel subscriber_ [source,java] ---------------------------------------------------------- +---- Flowable.interval(1, TimeUnit.SECONDS) .map(i -> "Item " + i) .subscribe(elements); ---------------------------------------------------------- +---- String items are generated every second by RxJava in the example, and they are pushed into the Camel route defined above. @@ -190,14 +225,15 @@ String items are generated every second by RxJava in the example, and they are p Also in this case, the direct API can be used to obtain a Camel subscriber from an endpoint URI. +._Java-only: direct API to push data into a Camel endpoint using RxJava_ [source,java] ---------------------------------------------------------- +---- CamelReactiveStreamsService camel = CamelReactiveStreams.get(context); // Send two strings to the "seda:queue" endpoint Flowable.just("hello", "world") .subscribe(camel.subscriber("seda:queue", String.class)); ---------------------------------------------------------- +---- === Request a transformation to Camel @@ -207,8 +243,9 @@ The same mechanism can be also used to e.g., send data to an _http_ endpoint and The following snippet shows how RxJava functional code can request the task of loading and marshalling files to Camel. +._Java-only: RxJava requesting a transformation from a Camel reactive stream_ [source,java] ---------------------------------------------------------- +---- CamelReactiveStreamsService camel = CamelReactiveStreams.get(context); // Process files starting from their names @@ -217,22 +254,23 @@ Flowable.just(new File("file1.txt"), new File("file2.txt")) // Camel output will be converted to String // other steps .subscribe(); ---------------------------------------------------------- +---- In order this to work, a route like the following should be defined in the Camel context: [source,java] ---------------------------------------------------------- +---- from("reactive-streams:readAndMarshal") -.marshal() // ... other details ---------------------------------------------------------- + .marshal() // ... other details +---- ==== Request a transformation to Camel using the direct API An alternative approach consists of using the URI endpoints directly in the reactive flow: +._Java-only: direct API using `to()` to invoke a Camel endpoint from RxJava_ [source,java] ---------------------------------------------------------- +---- CamelReactiveStreamsService camel = CamelReactiveStreams.get(context); // Process files starting from their names @@ -241,7 +279,7 @@ Flowable.just(new File("file1.txt"), new File("file2.txt")) // Camel output will be converted to String // other steps .subscribe(); ---------------------------------------------------------- +---- When using the `to()` method instead of the `toStream`, there is no need to define the route using `reactive-streams:` endpoints (although they are used under the hood). @@ -249,10 +287,10 @@ route using `reactive-streams:` endpoints (although they are used under the hood In this case, the Camel transformation can be just: [source,java] ---------------------------------------------------------- +---- from("direct:process") -.marshal() // ... other details ---------------------------------------------------------- + .marshal() // ... other details +---- === Process Camel data into the reactive framework @@ -266,24 +304,60 @@ define the entire transformation using the reactive framework. For example, given the following route: +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------------------- +---- from("timer:clock") -.setBody().header(Exchange.TIMER_COUNTER) -.to("direct:reactive") -.log("Continue with Camel route... n=${body}"); ---------------------------------------------------------- + .setBody().header(Exchange.TIMER_COUNTER) + .to("direct:reactive") + .log("Continue with Camel route... n=${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + +
CamelTimerCounter
+
+ + +
+---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: timer:clock + steps: + - setBody: + header: CamelTimerCounter + - to: + uri: direct:reactive + - log: + message: "Continue with Camel route... n=${body}" +---- +==== A reactive processing step can be associated with the "direct:reactive" endpoint: +._Java-only: reactive processing step using `CamelReactiveStreamsService.process()`_ [source,java] ---------------------------------------------------------- +---- CamelReactiveStreamsService camel = CamelReactiveStreams.get(context); camel.process("direct:reactive", Integer.class, items -> Flowable.fromPublisher(items) // RxJava .map(n -> -n)); // make every number negative ---------------------------------------------------------- +---- Data flowing in the Camel route will be processed by the external reactive framework then continue the processing flow inside Camel. @@ -291,15 +365,16 @@ framework then continue the processing flow inside Camel. This mechanism can also be used to define a In-Out exchange in a completely reactive way. +._Java-only: defining a REST endpoint entirely via reactive processing_ [source,java] ---------------------------------------------------------- +---- CamelReactiveStreamsService camel = CamelReactiveStreams.get(context); // requires a rest-capable Camel component camel.process("rest:get:orders", exchange -> - Flowable.fromPublisher(exchange) - .flatMap(ex -> allOrders())); // retrieve orders asynchronously ---------------------------------------------------------- + Flowable.fromPublisher(exchange) + .flatMap(ex -> allOrders())); // retrieve orders asynchronously +---- See Camel examples (*camel-example-reactive-streams*) for details. @@ -312,25 +387,53 @@ If the subscriber is slower than the exchange rate, the buffer may become too bi Considering the following route: +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------------------- +---- from("jms:queue") -.to("reactive-streams:flow"); ---------------------------------------------------------- + .to("reactive-streams:flow"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: jms:queue + steps: + - to: + uri: reactive-streams:flow +---- +==== If the JMS queue contains a high number of messages and the Subscriber associated with the `flow` stream is too slow, messages are dequeued from JMS and appended to the buffer, possibly causing an _"out of memory"_ error. To avoid such problems, a `ThrottlingInflightRoutePolicy` can be set in the route. +._Java-only: programmatic `ThrottlingInflightRoutePolicy` to limit in-flight exchanges_ [source,java] ---------------------------------------------------------- +---- ThrottlingInflightRoutePolicy policy = new ThrottlingInflightRoutePolicy(); policy.setMaxInflightExchanges(10); from("jms:queue") -.routePolicy(policy) -.to("reactive-streams:flow"); ---------------------------------------------------------- + .routePolicy(policy) + .to("reactive-streams:flow"); +---- The policy limits the maximum number of active exchanges (and so the maximum size of the buffer), keeping it lower than the threshold (`10` in the example). @@ -346,11 +449,40 @@ by limiting the number of requests to the http service (e.g., scaling out). In contexts where a certain amount of data loss is acceptable, setting a backpressure strategy other than `BUFFER` can be a solution for dealing with fast sources. +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------------------- +---- from("direct:thermostat") -.to("reactive-streams:flow?backpressureStrategy=LATEST"); ---------------------------------------------------------- + .to("reactive-streams:flow?backpressureStrategy=LATEST"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:thermostat + steps: + - to: + uri: reactive-streams:flow + parameters: + backpressureStrategy: LATEST +---- +==== When the `LATEST` backpressure strategy is used, the publisher keeps only the last exchange received from the route, while older data is discarded (other options are available). @@ -362,11 +494,40 @@ The subscriber associated with the consumer interacts with the publisher to keep An example of backpressure-aware route: +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------------------- +---- from("reactive-streams:numbers?maxInflightExchanges=10") -.to("direct:endpoint"); ---------------------------------------------------------- + .to("direct:endpoint"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: reactive-streams:numbers + parameters: + maxInflightExchanges: 10 + steps: + - to: + uri: direct:endpoint +---- +==== The number of items that Camel requests to the source publisher (through the reactive streams backpressure mechanism) is always lower than `10`. Messages are processed by a single thread in the Camel side. From c059eeb7d42c3601b41ef671a894b129d61e6b3c Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:52:53 +0200 Subject: [PATCH 22/87] CAMEL-23789: Make Spring WS component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/spring-ws-component.adoc | 134 +++++++++++------- 1 file changed, 86 insertions(+), 48 deletions(-) diff --git a/components/camel-spring-parent/camel-spring-ws/src/main/docs/spring-ws-component.adoc b/components/camel-spring-parent/camel-spring-ws/src/main/docs/spring-ws-component.adoc index ed0c73a05e6c6..eeff42f4a5fd5 100644 --- a/components/camel-spring-parent/camel-spring-ws/src/main/docs/spring-ws-component.adoc +++ b/components/camel-spring-parent/camel-spring-ws/src/main/docs/spring-ws-component.adoc @@ -126,10 +126,11 @@ YAML:: And sent a message: +._Java-only: ProducerTemplate test API_ [source,java] ------------------------------------------------------------------------------------------------------------- +---- template.requestBody("direct:example", "test message"); ------------------------------------------------------------------------------------------------------------- +---- Remember if it's a SOAP service you're calling, you don't have to include SOAP tags. Spring-WS will perform the XML-to-SOAP marshaling. @@ -177,12 +178,13 @@ YAML:: Optionally, you can override the endpoint options with header values: +._Java-only: ProducerTemplate setting SOAP action header_ [source,java] --------------------------------------------------------------------- +---- template.requestBodyAndHeader("direct:example", -"test message", -SpringWebserviceConstants.SPRING_WS_SOAP_ACTION, "http://baz.com"); --------------------------------------------------------------------- + "test message", + "CamelSpringWebserviceSoapAction", "http://baz.com"); +---- === Using SOAP headers @@ -190,19 +192,17 @@ You can provide the SOAP header(s) as a Camel Message header when sending a message to a spring-ws endpoint, for example, given the following SOAP header in a String +._Java-only: constructing SOAP header and setting it on the Exchange_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- String body = ... -String soapHeader = "12345678901111"; ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -We can set the body and header on the Camel Message as follows: +String soapHeader = "" + + "1234567890" + + "1111"; -[source,java] ----------------------------------------------------------------------------------------- exchange.getIn().setBody(body); -exchange.getIn().setHeader(SpringWebserviceConstants.SPRING_WS_SOAP_HEADER, soapHeader); ----------------------------------------------------------------------------------------- +exchange.getIn().setHeader("CamelSpringWebserviceSoapHeader", soapHeader); +---- And then send the Exchange to a `spring-ws` endpoint to call the Web Service. @@ -223,11 +223,12 @@ implementation is provided by `BasicMessageFilter`) to propagate the exchange headers and attachments into `WebServiceMessage` response. Now you can use +._Java-only: programmatic header and attachment manipulation_ [source,java] --------------------------------------------------------------------- -exchange.getOut().getHeaders().put("myCustom","myHeaderValue") -exchange.getIn().addAttachment("myAttachment", new DataHandler(...)) --------------------------------------------------------------------- +---- +exchange.getOut().getHeaders().put("myCustom", "myHeaderValue"); +exchange.getIn().addAttachment("myAttachment", new DataHandler(...)); +---- [NOTE] ==== @@ -281,9 +282,9 @@ all Spring-WS endpoints - the local messageFilter directly on the endpoint as follows: [source,java] -------------------------------------------------------------------------------------- +---- to("spring-ws:http://yourdomain.com?messageFilter=#myEndpointSpecificMessageFilter"); -------------------------------------------------------------------------------------- +---- For more information, see https://issues.apache.org/jira/browse/CAMEL-5724[CAMEL-5724] @@ -292,25 +293,58 @@ If you want to create your own `MessageFilter`, consider overriding the following methods in the default implementation of `MessageFilter` in class `BasicMessageFilter`: +._Java-only: custom `MessageFilter` method overrides_ [source,java] -------------------------------------------------------------------------------- -protected void doProcessSoapHeader(Message inOrOut, SoapMessage soapMessage) -{your code /*no need to call super*/ } +---- +protected void doProcessSoapHeader(Message inOrOut, SoapMessage soapMessage) { + // your code, no need to call super +} -protected void doProcessSoapAttachements(Message inOrOut, SoapMessage response) -{ your code /*no need to call super*/ } -------------------------------------------------------------------------------- +protected void doProcessSoapAttachements(Message inOrOut, SoapMessage response) { + // your code, no need to call super +} +---- === Using a custom MessageSender and MessageFactory A custom message sender or factory in the registry can be referenced like this: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------------------ +---- from("direct:example") -.to("spring-ws:http://foo.com/bar?messageFactory=#messageFactory&messageSender=#messageSender") ------------------------------------------------------------------------------------------------ + .to("spring-ws:http://foo.com/bar?messageFactory=#messageFactory&messageSender=#messageSender"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:example + steps: + - to: + uri: spring-ws:http://foo.com/bar + parameters: + messageFactory: "#messageFactory" + messageSender: "#messageSender" +---- +==== Spring configuration: @@ -395,38 +429,38 @@ The following route will receive all web service requests that have a root element named "GetFoo" within the `\http://example.com/` namespace. [source,java] ----------------------------------------------------------------------------------------- +---- from("spring-ws:rootqname:{http://example.com/}GetFoo?endpointMapping=#endpointMapping") -.convertBodyTo(String.class).to(mock:example) ----------------------------------------------------------------------------------------- + .convertBodyTo(String.class).to("mock:example"); +---- The following route will receive web service requests containing the `\http://example.com/GetFoo` SOAP action. [source,java] ---------------------------------------------------------------------------------------- +---- from("spring-ws:soapaction:http://example.com/GetFoo?endpointMapping=#endpointMapping") -.convertBodyTo(String.class).to(mock:example) ---------------------------------------------------------------------------------------- + .convertBodyTo(String.class).to("mock:example"); +---- The following route will receive all requests sent to `\http://example.com/foobar`. [source,java] --------------------------------------------------------------------------------- +---- from("spring-ws:uri:http://example.com/foobar?endpointMapping=#endpointMapping") -.convertBodyTo(String.class).to(mock:example) --------------------------------------------------------------------------------- + .convertBodyTo(String.class).to("mock:example"); +---- The route below will receive requests that contain the element `abc` anywhere inside the message (and the default namespace). [source,java] --------------------------------------------------------------------------------------- +---- from("spring-ws:xpathresult:abc?expression=//foobar&endpointMapping=#endpointMapping") -.convertBodyTo(String.class).to(mock:example) --------------------------------------------------------------------------------------- + .convertBodyTo(String.class).to("mock:example"); +---- === Alternative configuration, using existing endpoint mappings @@ -484,22 +518,26 @@ receive pojo's, to and from web services. When _accessing_ web services, you can marshal the request and unmarshal the response message: +._Java-only: programmatic JAXB data format configuration with marshal/unmarshal_ [source,java] ----------------------------------------------------------------------------------------- +---- JaxbDataFormat jaxb = new JaxbDataFormat(false); jaxb.setContextPath("com.example.model"); from("direct:example").marshal(jaxb).to("spring-ws:http://foo.com/bar").unmarshal(jaxb); ----------------------------------------------------------------------------------------- +---- Similarly, when _providing_ web services, you can unmarshal XML requests to POJO's and marshal the response message back to XML: +._Java-only: unmarshal incoming SOAP requests and marshal responses with JAXB_ [source,java] --------------------------------------------------------------------------------------------------------- -from("spring-ws:rootqname:{http://example.com/}GetFoo?endpointMapping=#endpointMapping").unmarshal(jaxb) -.to("mock:example").marshal(jaxb); --------------------------------------------------------------------------------------------------------- +---- +from("spring-ws:rootqname:{http://example.com/}GetFoo?endpointMapping=#endpointMapping") + .unmarshal(jaxb) + .to("mock:example") + .marshal(jaxb); +---- From e26e0e805b1e874afbca94430bd8187861ab1d76 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:53:58 +0200 Subject: [PATCH 23/87] CAMEL-23789: Make CXF component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/cxf-component.adoc | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/components/camel-cxf/camel-cxf-soap/src/main/docs/cxf-component.adoc b/components/camel-cxf/camel-cxf-soap/src/main/docs/cxf-component.adoc index 3bf710113b785..00b044e2a7506 100644 --- a/components/camel-cxf/camel-cxf-soap/src/main/docs/cxf-component.adoc +++ b/components/camel-cxf/camel-cxf-soap/src/main/docs/cxf-component.adoc @@ -598,21 +598,21 @@ public interface TextService { We can then create the simplest CXF service (note we didn't specify the `POJO` mode, as it is the default mode) as follows: +._Java-only: CXF POJO mode with `MessageContentsList` processing_ [source,java] ---- - from("cxf:textServiceResponseFromRoute?serviceClass=org.apache.camel.component.cxf.soap.server.TextService&address=/text-route", - .process(exchange -> { - String operation = (String) exchange.getIn().getHeader(CxfConstants.OPERATION_NAME); - String inputArg = ((MessageContentsList) exchange.getIn().getBody()).get(0).toString(); - String result = null; - if (operation.equals("upperCase")) { - result = inputArg.toUpperCase(); - } - else if (operation.equals("lowerCase")) { - result = inputArg.toLowerCase(); - } - exchange.getIn().setBody(result); - }); +from("cxf:textServiceResponseFromRoute?serviceClass=org.apache.camel.component.cxf.soap.server.TextService&address=/text-route") + .process(exchange -> { + String operation = (String) exchange.getIn().getHeader(CxfConstants.OPERATION_NAME); + String inputArg = ((MessageContentsList) exchange.getIn().getBody()).get(0).toString(); + String result = null; + if (operation.equals("upperCase")) { + result = inputArg.toUpperCase(); + } else if (operation.equals("lowerCase")) { + result = inputArg.toLowerCase(); + } + exchange.getIn().setBody(result); + }); ---- === How to prepare the message for the Camel CXF endpoint in POJO data format @@ -890,19 +890,15 @@ If your CXF endpoint is working in the `RAW` data format, you could set the SOAP Fault message in the message body and set the response code in the message header as demonstrated by https://github.com/apache/camel/blob/main/components/camel-cxf/camel-cxf-soap/src/test/java/org/apache/camel/component/cxf/jaxws/CxfMessageStreamExceptionTest.java#L43[CxfMessageStreamExceptionTest]: +._Java-only: setting SOAP fault response body and HTTP status code in RAW mode_ [source,java] ---- -from(routerEndpointURI).process(new Processor() { - - public void process(Exchange exchange) throws Exception { +from(routerEndpointURI) + .process(exchange -> { Message out = exchange.getMessage(); - // Set the message body out.setBody(this.getClass().getResourceAsStream("SoapFaultMessage.xml")); - // Set the response code here - out.setHeader(org.apache.cxf.message.Message.RESPONSE_CODE, new Integer(500)); - } - -}); + out.setHeader(org.apache.cxf.message.Message.RESPONSE_CODE, 500); + }); ---- Same for using POJO data format. You can set the SOAPFault on the _OUT_ body. @@ -1142,10 +1138,11 @@ remote connection IP easily. Here is the code snippet: +._Java-only: accessing the CXF message to get the remote IP address_ [source,java] ---- -// check the remote IP from the CXF Message -org.apache.cxf.message.Message cxfMessage = exchange.getIn().getHeader(CxfConstants.CAMEL_CXF_MESSAGE, org.apache.cxf.message.Message.class); +org.apache.cxf.message.Message cxfMessage = exchange.getIn().getHeader( + CxfConstants.CAMEL_CXF_MESSAGE, org.apache.cxf.message.Message.class); ServletRequest request = (ServletRequest) cxfMessage.get("HTTP.REQUEST"); String remoteAddress = request.getRemoteAddr(); ---- @@ -1219,7 +1216,7 @@ environment specific configurations could look like in Spring XML: The environment specific configurations are externalized into a properties file: *orderEntry.cfg* -[source,java] +[source,properties] ---- endpointUri=https://localhost:8181/OrderEntry trustStore.password=password From a9ee8283a4867bd1039c7f67192c544b47ebd0df Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:56:04 +0200 Subject: [PATCH 24/87] CAMEL-23789: Make Azure Storage Data Lake component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../azure-storage-datalake-component.adoc | 390 ++++++++++++++++-- 1 file changed, 358 insertions(+), 32 deletions(-) diff --git a/components/camel-azure/camel-azure-storage-datalake/src/main/docs/azure-storage-datalake-component.adoc b/components/camel-azure/camel-azure-storage-datalake/src/main/docs/azure-storage-datalake-component.adoc index a5b47ef07de65..8227487f1e33d 100644 --- a/components/camel-azure/camel-azure-storage-datalake/src/main/docs/azure-storage-datalake-component.adoc +++ b/components/camel-azure/camel-azure-storage-datalake/src/main/docs/azure-storage-datalake-component.adoc @@ -170,39 +170,132 @@ Refer to the examples section below for more details on how to use these operati === Consumer Examples To consume a file from the storage datalake into a file using the file component, this can be done like this: +[tabs] +==== +Java:: ++ [source,java] ---- -from("azure-storage-datalake":cameltesting/filesystem?fileName=test.txt&accountKey=yourAccountKey"). -to("file:/filelocation"); +from("azure-storage-datalake:cameltesting/filesystem?fileName=test.txt&accountKey=yourAccountKey") + .to("file:/filelocation"); +---- + +XML:: ++ +[source,xml] +---- + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: azure-storage-datalake:cameltesting/filesystem + parameters: + fileName: test.txt + accountKey: yourAccountKey + steps: + - to: + uri: file:/filelocation +---- +==== + You can also directly write to a file without using the file component. For this, you will need to specify the path in `fileDir` option, to save it to your machine. +[tabs] +==== +Java:: ++ [source,java] ---- -from("azure-storage-datalake":cameltesting/filesystem?fileName=test.txt&accountKey=yourAccountKey&fileDir=/test/directory"). -to("mock:results"); +from("azure-storage-datalake:cameltesting/filesystem?fileName=test.txt&accountKey=yourAccountKey&fileDir=/test/directory") + .to("mock:results"); +---- + +XML:: ++ +[source,xml] +---- + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: azure-storage-datalake:cameltesting/filesystem + parameters: + fileName: test.txt + accountKey: yourAccountKey + fileDir: /test/directory + steps: + - to: + uri: mock:results +---- +==== + This component also supports batch consumer. So, you can consume multiple files from a file system by specifying the path from where you want to consume the files. +[tabs] +==== +Java:: ++ [source,java] ---- -from("azure-storage-datalake":cameltesting/filesystem?accountKey=yourAccountKey&fileDir=/test/directory&path=abc/test"). -to("mock:results"); +from("azure-storage-datalake:cameltesting/filesystem?accountKey=yourAccountKey&fileDir=/test/directory&path=abc/test") + .to("mock:results"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: azure-storage-datalake:cameltesting/filesystem + parameters: + accountKey: yourAccountKey + fileDir: /test/directory + path: abc/test + steps: + - to: + uri: mock:results +---- +==== + === Producer Examples - `listFileSystem` +._Java-only: uses `ListFileSystemsOptions` SDK type_ [source,java] ---- from("direct:start") .process(exchange -> { - //required headers can be added here - exchange.getIn().setHeader(DataLakeConstants.LIST_FILESYSTEMS_OPTIONS, new ListFileSystemsOptions().setMaxResultsPerPage(10)); + exchange.getIn().setHeader(DataLakeConstants.LIST_FILESYSTEMS_OPTIONS, + new ListFileSystemsOptions().setMaxResultsPerPage(10)); }) .to("azure-storage-datalake:cameltesting?operation=listFileSystem&serviceClient=#serviceClient") .to("mock:results"); @@ -210,35 +303,111 @@ from("direct:start") - `createFileSystem` +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(DataLakeConstants.FILESYSTEM_NAME, "test1"); - }) + .setHeader("CamelAzureStorageDataLakeFileSystemName", constant("test1")) .to("azure-storage-datalake:cameltesting?operation=createFileSystem&serviceClient=#serviceClient") .to("mock:results"); ---- +XML:: ++ +[source,xml] +---- + + + + test1 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageDataLakeFileSystemName + constant: test1 + - to: + uri: azure-storage-datalake:cameltesting + parameters: + operation: createFileSystem + serviceClient: "#serviceClient" + - to: + uri: mock:results +---- +==== + - `deleteFileSystem` +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(DataLakeConstants.FILESYSTEM_NAME, "test1"); - }) + .setHeader("CamelAzureStorageDataLakeFileSystemName", constant("test1")) .to("azure-storage-datalake:cameltesting?operation=deleteFileSystem&serviceClient=#serviceClient") .to("mock:results"); ---- +XML:: ++ +[source,xml] +---- + + + + test1 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageDataLakeFileSystemName + constant: test1 + - to: + uri: azure-storage-datalake:cameltesting + parameters: + operation: deleteFileSystem + serviceClient: "#serviceClient" + - to: + uri: mock:results +---- +==== + - `listPaths` +._Java-only: uses `ListPathsOptions` SDK type_ [source,java] ---- from("direct:start") .process(exchange -> { - exchange.getIn().setHeader(DataLakeConstants.LIST_PATH_OPTIONS, new ListPathsOptions().setPath("/main")); + exchange.getIn().setHeader(DataLakeConstants.LIST_PATH_OPTIONS, + new ListPathsOptions().setPath("/main")); }) .to("azure-storage-datalake:cameltesting/filesystem?operation=listPaths&serviceClient=#serviceClient") .to("mock:results"); @@ -246,13 +415,13 @@ from("direct:start") - `getFile` -This can be done in two ways, We can either set an `OutputStream` in the exchange body +This can be done in two ways. We can either set an `OutputStream` in the exchange body: +._Java-only: sets an `OutputStream` for the file content to be written to_ [source,java] ---- from("direct:start") .process(exchange -> { - // set an OutputStream where the file data can should be written exchange.getIn().setBody(outputStream); }) .to("azure-storage-datalake:cameltesting/filesystem?operation=getFile&fileName=test.txt&serviceClient=#serviceClient") @@ -262,13 +431,14 @@ from("direct:start") Or if the body is not set, the operation will give an `InputStream`, given that you have already registered for query acceleration in azure portal. +._Java-only: reads the file content as an `InputStream`_ [source,java] ---- from("direct:start") .to("azure-storage-datalake:cameltesting/filesystem?operation=getFile&fileName=test.txt&serviceClient=#serviceClient") .process(exchange -> { InputStream inputStream = exchange.getMessage().getBody(InputStream.class); - System.out.Println(IOUtils.toString(inputStream, StandardCharcets.UTF_8.name())); + System.out.println(IOUtils.toString(inputStream, StandardCharsets.UTF_8.name())); }) .to("mock:results"); ---- @@ -362,6 +532,7 @@ YAML:: - `downloadLink` +._Java-only: processes the generated download link from the response body_ [source,java] ---- from("direct:start") @@ -375,6 +546,7 @@ from("direct:start") - `appendToFile` +._Java-only: creates an `InputStream` body for the data to append_ [source,java] ---- from("direct:start") @@ -389,25 +561,65 @@ from("direct:start") - `flushToFile` +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(DataLakeConstants.POSITION, 0); - }) + .setHeader("CamelAzureStorageDataLakePosition", constant(0)) .to("azure-storage-datalake:cameltesting/filesystem?operation=flushToFile&fileName=test.txt&serviceClient=#serviceClient") .to("mock:results"); ---- +XML:: ++ +[source,xml] +---- + + + + 0 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageDataLakePosition + constant: 0 + - to: + uri: azure-storage-datalake:cameltesting/filesystem + parameters: + operation: flushToFile + fileName: test.txt + serviceClient: "#serviceClient" + - to: + uri: mock:results +---- +==== + - `openQueryInputStream` -For this operation, you should have already registered for query acceleration on the azure portal +For this operation, you should have already registered for query acceleration on the azure portal. +._Java-only: uses `FileQueryOptions` SDK type_ [source,java] ---- from("direct:start") .process(exchange -> { - exchange.getIn().setHeader(DataLakeConstants.QUERY_OPTIONS, new FileQueryOptions("SELECT * from BlobStorage")); + exchange.getIn().setHeader(DataLakeConstants.QUERY_OPTIONS, + new FileQueryOptions("SELECT * from BlobStorage")); }) .to("azure-storage-datalake:cameltesting/filesystem?operation=openQueryInputStream&fileName=test.txt&serviceClient=#serviceClient") .to("mock:results"); @@ -415,6 +627,7 @@ from("direct:start") - `upload` +._Java-only: creates an `InputStream` body for the data to upload_ [source,java] ---- from("direct:start") @@ -429,40 +642,153 @@ from("direct:start") - `uploadFromFile` +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(DataLakeConstants.PATH, "test/file.txt"); - }) + .setHeader("CamelAzureStorageDataLakePath", constant("test/file.txt")) .to("azure-storage-datalake:cameltesting/filesystem?operation=uploadFromFile&fileName=test.txt&serviceClient=#serviceClient") .to("mock:results"); ---- +XML:: ++ +[source,xml] +---- + + + + test/file.txt + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageDataLakePath + constant: test/file.txt + - to: + uri: azure-storage-datalake:cameltesting/filesystem + parameters: + operation: uploadFromFile + fileName: test.txt + serviceClient: "#serviceClient" + - to: + uri: mock:results +---- +==== + - `createFile` +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(DataLakeConstants.DIRECTORY_NAME, "test/file/"); - }) + .setHeader("CamelAzureStorageDataLakeDirectoryName", constant("test/file/")) .to("azure-storage-datalake:cameltesting/filesystem?operation=createFile&fileName=test.txt&serviceClient=#serviceClient") .to("mock:results"); ---- +XML:: ++ +[source,xml] +---- + + + + test/file/ + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageDataLakeDirectoryName + constant: "test/file/" + - to: + uri: azure-storage-datalake:cameltesting/filesystem + parameters: + operation: createFile + fileName: test.txt + serviceClient: "#serviceClient" + - to: + uri: mock:results +---- +==== + - `deleteDirectory` +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(DataLakeConstants.DIRECTORY_NAME, "test/file/"); - }) + .setHeader("CamelAzureStorageDataLakeDirectoryName", constant("test/file/")) .to("azure-storage-datalake:cameltesting/filesystem?operation=deleteDirectory&serviceClient=#serviceClient") .to("mock:results"); ---- +XML:: ++ +[source,xml] +---- + + + + test/file/ + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageDataLakeDirectoryName + constant: "test/file/" + - to: + uri: azure-storage-datalake:cameltesting/filesystem + parameters: + operation: deleteDirectory + serviceClient: "#serviceClient" + - to: + uri: mock:results +---- +==== + === Testing Please run all the unit tests and integration tests while making changes to the component as changes or version upgrades can break things. From 04ca700b8db2f264d74589bb89446c789f9a7762 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 20:56:57 +0200 Subject: [PATCH 25/87] CAMEL-23789: Make Netty HTTP component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/netty-http-component.adoc | 84 +++++++++++++++---- 1 file changed, 67 insertions(+), 17 deletions(-) diff --git a/components/camel-netty-http/src/main/docs/netty-http-component.adoc b/components/camel-netty-http/src/main/docs/netty-http-component.adoc index 4405e317edb4c..dcce4ce17271c 100644 --- a/components/camel-netty-http/src/main/docs/netty-http-component.adoc +++ b/components/camel-netty-http/src/main/docs/netty-http-component.adoc @@ -187,23 +187,24 @@ users to get access to the original Netty request/response instances if needed, as shown below. Mind that the original response may not be accessible at all times. +._Java-only: accessing the underlying Netty HTTP request object_ [source,java] ----------------------------------------------------------------------------------------------------------- +---- io.netty.handler.codec.http.HttpRequest request = exchange.getIn(NettyHttpMessage.class).getHttpRequest(); ----------------------------------------------------------------------------------------------------------- +---- === Using HTTP Basic Authentication The Netty HTTP consumer supports HTTP basic authentication by specifying the security realm name to use, as shown below -[source,java] ------------------------------------------------------------------------------------------- +[source,xml] +---- ... ------------------------------------------------------------------------------------------- +---- The realm name is mandatory to enable basic authentication. By default, the JAAS based authenticator is used, which will use the realm name @@ -304,11 +305,12 @@ YAML:: And we can call this HTTP server using Camel also, with the ProducerTemplate as shown below: +._Java-only: ProducerTemplate test API_ [source,java] ------------------------------------------------------------------------------------------------------------- - String out = template.requestBody("netty-http:http://0.0.0.0:8080/foo", "Hello World", String.class); - System.out.println(out); ------------------------------------------------------------------------------------------------------------- +---- +String out = template.requestBody("netty-http:http://0.0.0.0:8080/foo", "Hello World", String.class); +System.out.println(out); +---- And we get _"Bye World"_ as the output. @@ -450,16 +452,63 @@ Here is an example with two routes that share the same port. *Two routes sharing the same port* +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------ +---- from("netty-http:http://0.0.0.0:{{port}}/foo") - .to("mock:foo") - .transform().constant("Bye World"); + .to("mock:foo") + .transform().constant("Bye World"); from("netty-http:http://0.0.0.0:{{port}}/bar") - .to("mock:bar") - .transform().constant("Bye Camel"); ------------------------------------------------ + .to("mock:bar") + .transform().constant("Bye Camel"); +---- + +XML:: ++ +[source,xml] +---- + + + + + Bye World + + + + + + + Bye Camel + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: netty-http:http://0.0.0.0:{{port}}/foo + steps: + - to: + uri: mock:foo + - transform: + constant: "Bye World" +- route: + from: + uri: netty-http:http://0.0.0.0:{{port}}/bar + steps: + - to: + uri: mock:bar + - transform: + constant: "Bye Camel" +---- +==== And here is an example of a mis-configured second route that does not have identical @@ -529,8 +578,9 @@ URL received on the request line of the HTTP request. Here's an example of an HTTP proxy that simply transforms the response from the origin server to uppercase. +._Java-only: reverse proxy with dynamic `toD` and Netty response processing_ [source,java] ------------------------------------------------------------------------------------------- +---- from("netty-http:proxy://0.0.0.0:8080") .toD("netty-http:" + "${headers." + Exchange.HTTP_SCHEME + "}://" @@ -548,7 +598,7 @@ void processResponse(final Exchange exchange) { buf.resetWriterIndex(); ByteBufUtil.writeUtf8(buf, string.toUpperCase(Locale.US)); } ------------------------------------------------------------------------------------------- +---- From a3da917bcb5649c79f90a51e14d433d7280ffa8c Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:00:33 +0200 Subject: [PATCH 26/87] CAMEL-23789: Make Stripe component docs multi-DSL friendly (Wave 1) - Resolve StripeConstants references to string values (OBJECT_ID, METHOD_HEADER, METHOD_RETRIEVE, METHOD_UPDATE, METHOD_LIST, METHOD_CANCEL) - Convert createCustomer JSON, REST payment, retrieveCustomer, cancelPayment, and auth examples to Java/XML/YAML tabs - Add Java-only markers to Map.of() examples (createCustomer, paymentIntent, updatePayment, listCustomers, product+price, refund) - Add Java-only markers to programmatic component configuration and error handling examples Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/stripe-component.adoc | 190 ++++++++++++++++-- 1 file changed, 178 insertions(+), 12 deletions(-) diff --git a/components/camel-stripe/src/main/docs/stripe-component.adoc b/components/camel-stripe/src/main/docs/stripe-component.adoc index 2102bd78e538b..2a1da3e10f1a0 100644 --- a/components/camel-stripe/src/main/docs/stripe-component.adoc +++ b/components/camel-stripe/src/main/docs/stripe-component.adoc @@ -71,6 +71,7 @@ Camel components are configured on two separate levels: At the component level, you set general and shared configurations that are, then, inherited by the endpoints. You can set them directly via Java code, or through the properties component. +._Java-only: programmatic component configuration_ [source,java] ---- StripeComponent stripe = context.getComponent("stripe", StripeComponent.class); @@ -139,6 +140,7 @@ You can configure the API key in several ways: ==== Option 1: Component Level (Recommended for Single Key) +._Java-only: programmatic API key configuration_ [source,java] ---- StripeComponent stripe = context.getComponent("stripe", StripeComponent.class); @@ -237,6 +239,7 @@ The Stripe component accepts both Map objects and JSON strings as input, providi Using a Map: +._Java-only: uses `Map.of()` to construct request parameters_ [source,java] ---- from("direct:createCustomer") @@ -251,6 +254,10 @@ from("direct:createCustomer") Using JSON: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:createCustomerJson") @@ -265,10 +272,44 @@ from("direct:createCustomerJson") .log("Created customer: ${body.id}"); ---- +XML:: ++ +[source,xml] +---- + + + + {"email": "customer@example.com", "name": "John Doe", "description": "New customer"} + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:createCustomerJson + steps: + - setBody: + constant: '{"email": "customer@example.com", "name": "John Doe", "description": "New customer"}' + - to: + uri: stripe:customers + parameters: + apiKey: "{{stripe.apiKey}}" + - log: + message: "Created customer: ${body.id}" +---- +==== + === Creating a Payment Intent Using a Map: +._Java-only: uses `Map.of()` and `List.of()` to construct request parameters_ [source,java] ---- from("direct:payment") @@ -284,33 +325,112 @@ from("direct:payment") Using JSON (useful when integrating with REST endpoints): +[tabs] +==== +Java:: ++ [source,java] ---- from("rest:post:/payments") .log("Received payment request: ${body}") - // Body is already JSON from REST endpoint .to("stripe:paymentIntents?apiKey={{stripe.apiKey}}") .log("Payment intent created: ${body.id}"); ---- +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: rest:post:/payments + steps: + - log: + message: "Received payment request: ${body}" + - to: + uri: stripe:paymentIntents + parameters: + apiKey: "{{stripe.apiKey}}" + - log: + message: "Payment intent created: ${body.id}" +---- +==== + === Retrieving a Customer +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:getCustomer") - .setHeader(StripeConstants.OBJECT_ID, constant("cus_xxxxx")) - .setHeader(StripeConstants.METHOD_HEADER, constant(StripeConstants.METHOD_RETRIEVE)) + .setHeader("CamelStripeObjectId", constant("cus_xxxxx")) + .setHeader("CamelStripeMethod", constant("retrieve")) .to("stripe:customers?apiKey={{stripe.apiKey}}") .log("Retrieved customer: ${body.email}"); ---- +XML:: ++ +[source,xml] +---- + + + + cus_xxxxx + + + retrieve + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:getCustomer + steps: + - setHeader: + name: CamelStripeObjectId + constant: "cus_xxxxx" + - setHeader: + name: CamelStripeMethod + constant: "retrieve" + - to: + uri: stripe:customers + parameters: + apiKey: "{{stripe.apiKey}}" + - log: + message: "Retrieved customer: ${body.email}" +---- +==== + === Updating a Payment Intent +._Java-only: uses `Map.of()` with nested `Map.of()` to construct request parameters_ [source,java] ---- from("direct:updatePayment") - .setHeader(StripeConstants.OBJECT_ID, simple("${exchangeProperty.paymentIntentId}")) - .setHeader(StripeConstants.METHOD_HEADER, constant(StripeConstants.METHOD_UPDATE)) + .setHeader("CamelStripeObjectId", simple("${exchangeProperty.paymentIntentId}")) + .setHeader("CamelStripeMethod", constant("update")) .setBody(constant(Map.of( "description", "Updated description", "metadata", Map.of("order_id", "12345") @@ -320,10 +440,11 @@ from("direct:updatePayment") === Listing Customers +._Java-only: uses `Map.of()` to construct request parameters_ [source,java] ---- from("direct:listCustomers") - .setHeader(StripeConstants.METHOD_HEADER, constant(StripeConstants.METHOD_LIST)) + .setHeader("CamelStripeMethod", constant("list")) .setBody(constant(Map.of("limit", 10))) .to("stripe:customers?apiKey={{stripe.apiKey}}") .log("Found ${body.data.size()} customers"); @@ -331,22 +452,21 @@ from("direct:listCustomers") === Creating a Product with Price +._Java-only: uses `Map.of()` and `process` lambda to construct multi-step request_ [source,java] ---- from("direct:createProduct") - // Create product .setBody(constant(Map.of( "name", "Premium Subscription", "description", "Monthly premium access" ))) .to("stripe:products?apiKey={{stripe.apiKey}}") .setProperty("productId", simple("${body.id}")) - // Create price for the product .process(exchange -> { Map priceParams = new HashMap<>(); priceParams.put("product", exchange.getProperty("productId", String.class)); priceParams.put("currency", "usd"); - priceParams.put("unit_amount", 2999L); // $29.99 + priceParams.put("unit_amount", 2999L); priceParams.put("recurring", Map.of("interval", "month")); exchange.getMessage().setBody(priceParams); }) @@ -356,12 +476,13 @@ from("direct:createProduct") === Processing a Refund +._Java-only: uses `Map.of()` to construct request parameters_ [source,java] ---- from("direct:refund") .setBody(constant(Map.of( "charge", "ch_xxxxx", - "amount", 1000L, // Partial refund of $10.00 + "amount", 1000L, "reason", "requested_by_customer" ))) .to("stripe:refunds?apiKey={{stripe.apiKey}}") @@ -370,15 +491,59 @@ from("direct:refund") === Canceling a Payment Intent +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:cancelPayment") - .setHeader(StripeConstants.OBJECT_ID, simple("${header.paymentIntentId}")) - .setHeader(StripeConstants.METHOD_HEADER, constant(StripeConstants.METHOD_CANCEL)) + .setHeader("CamelStripeObjectId", simple("${header.paymentIntentId}")) + .setHeader("CamelStripeMethod", constant("cancel")) .to("stripe:paymentIntents?apiKey={{stripe.apiKey}}") .log("Payment intent canceled: ${body.id}"); ---- +XML:: ++ +[source,xml] +---- + + + + ${header.paymentIntentId} + + + cancel + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:cancelPayment + steps: + - setHeader: + name: CamelStripeObjectId + simple: "${header.paymentIntentId}" + - setHeader: + name: CamelStripeMethod + constant: "cancel" + - to: + uri: stripe:paymentIntents + parameters: + apiKey: "{{stripe.apiKey}}" + - log: + message: "Payment intent canceled: ${body.id}" +---- +==== + == Running Integration Tests The Stripe component includes comprehensive integration tests that verify functionality against the Stripe API. @@ -559,6 +724,7 @@ You can see all the test data created during integration test runs. The Stripe API may return various errors. The component propagates these as exceptions: +._Java-only: uses Stripe SDK exception types in `doCatch` blocks_ [source,java] ---- from("direct:createPayment") From 3e6f6425c13754faeb41014aa945a303842e7701 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:03:18 +0200 Subject: [PATCH 27/87] CAMEL-23789: Make Dapr component docs multi-DSL friendly (Wave 1) - Resolve all DaprConstants references to string values (CamelDaprVerb, CamelDaprConcurrency, etc.) - Convert anonymous Processor classes to setHeader/setBody DSL equivalents - Convert 14 producer examples to Java/XML/YAML tabs (invokeService, state save/get, pubSub, invokeBinding, lock tryLock/unlock, workflow scheduleNew/terminate/purge/suspend/resume/state/raiseEvent) - Add Java-only markers to examples using SDK types (State, TransactionalStateOperation, Duration, List.of, Map.of) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/dapr-component.adoc | 921 +++++++++++++----- 1 file changed, 700 insertions(+), 221 deletions(-) diff --git a/components/camel-dapr/src/main/docs/dapr-component.adoc b/components/camel-dapr/src/main/docs/dapr-component.adoc index 911d7b4363952..f583171393157 100644 --- a/components/camel-dapr/src/main/docs/dapr-component.adoc +++ b/components/camel-dapr/src/main/docs/dapr-component.adoc @@ -112,139 +112,312 @@ To configure the consumer, the configStore name and configKeys must be provided. === Producer Operations Examples - `invokeService` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.VERB, "GET"); - }) - .to("dapr:invokeService?serviceToInvoke=myService&methodToInvoke=myMethod") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprVerb", constant("GET")) + .to("dapr:invokeService?serviceToInvoke=myService&methodToInvoke=myMethod") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + GET + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprVerb + constant: "GET" + - to: + uri: dapr:invokeService + parameters: + serviceToInvoke: myService + methodToInvoke: myMethod + - to: + uri: mock:result +---- +==== - `state: save` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the payload you want to save as state - exchange.getIn().setBody("myValue"); - }) - .to("dapr:state?stateOperation=save&stateStore=myStore&key=myKey") - .to("mock:result"); --------------------------------------------------------------------------------- + .setBody(constant("myValue")) + .to("dapr:state?stateOperation=save&stateStore=myStore&key=myKey") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myValue + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: "myValue" + - to: + uri: dapr:state + parameters: + stateOperation: save + stateStore: myStore + key: myKey + - to: + uri: mock:result +---- +==== - `state: saveBulk` - +._Java-only: uses Dapr SDK `State` types and `List.of()` to set bulk states_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the list of states you want to save - State state1 = new State<>("key1", "val1", "etag1"); - State state2 = new State<>("key2", "val1", "etag2"); - List> states = List.of(state1, state2); - exchange.getMessage().setHeader(DaprConstants.STATES, states); - }) - .to("dapr:state?stateOperation=saveBulk&stateStore=myStore") - .to("mock:result"); --------------------------------------------------------------------------------- + .process(exchange -> { + State state1 = new State<>("key1", "val1", "etag1"); + State state2 = new State<>("key2", "val1", "etag2"); + List> states = List.of(state1, state2); + exchange.getMessage().setHeader("CamelDaprStates", states); + }) + .to("dapr:state?stateOperation=saveBulk&stateStore=myStore") + .to("mock:result"); +---- - `state: get` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.CONCURRENCY, "FIRST_WRITE"); - exchange.getIn().setHeader(DaprConstants.CONSISTENCY, "EVENTUAL"); - }) - .to("dapr:state?stateOperation=get&stateStore=myStore&key=myKey") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprConcurrency", constant("FIRST_WRITE")) + .setHeader("CamelDaprConsistency", constant("EVENTUAL")) + .to("dapr:state?stateOperation=get&stateStore=myStore&key=myKey") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + FIRST_WRITE + + + EVENTUAL + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprConcurrency + constant: "FIRST_WRITE" + - setHeader: + name: CamelDaprConsistency + constant: "EVENTUAL" + - to: + uri: dapr:state + parameters: + stateOperation: get + stateStore: myStore + key: myKey + - to: + uri: mock:result +---- +==== - `state: getBulk` - +._Java-only: uses `List.of()` to set bulk key list_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.KEYS, List.of("key1", "key2")); - }) - .to("dapr:state?stateOperation=getBulk&stateStore=myStore") - .to("mock:result"); --------------------------------------------------------------------------------- + .process(exchange -> { + exchange.getIn().setHeader("CamelDaprKeys", List.of("key1", "key2")); + }) + .to("dapr:state?stateOperation=getBulk&stateStore=myStore") + .to("mock:result"); +---- - `state: delete` - +._Java-only: uses `Map.of()` to set metadata_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.METADATA, Map.of("partitionKey", "myPartitionKey")); - }) - .to("dapr:state?stateOperation=delete&stateStore=myStore&key=myKey") - .to("mock:result"); --------------------------------------------------------------------------------- + .process(exchange -> { + exchange.getIn().setHeader("CamelDaprMetadata", Map.of("partitionKey", "myPartitionKey")); + }) + .to("dapr:state?stateOperation=delete&stateStore=myStore&key=myKey") + .to("mock:result"); +---- - `state: executeTransaction` - +._Java-only: uses Dapr SDK `TransactionalStateOperation` and `State` types_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - TransactionalStateOperation.OperationType op = TransactionalStateOperation.OperationType.UPSERT; - List> transactions = List.of(new TransactionalStateOperation<>(op, new State<>("myKey"))); - exchange.getIn().setHeader(DaprConstants.TRANSACTIONS, transactions); - }) - .to("dapr:state?stateOperation=executeTransaction&stateStore=myStore") - .to("mock:result"); --------------------------------------------------------------------------------- + .process(exchange -> { + TransactionalStateOperation.OperationType op = TransactionalStateOperation.OperationType.UPSERT; + List> transactions = List.of(new TransactionalStateOperation<>(op, new State<>("myKey"))); + exchange.getIn().setHeader("CamelDaprTransactions", transactions); + }) + .to("dapr:state?stateOperation=executeTransaction&stateStore=myStore") + .to("mock:result"); +---- - `pubSub` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.CONTENT_TYPE, "application/json"); - }) - .to("dapr:pubSub?pubSubName=myPubSub&topic=myTopic") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprContentType", constant("application/json")) + .to("dapr:pubSub?pubSubName=myPubSub&topic=myTopic") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + application/json + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprContentType + constant: "application/json" + - to: + uri: dapr:pubSub + parameters: + pubSubName: myPubSub + topic: myTopic + - to: + uri: mock:result +---- +==== - `invokeBinding` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the message body to the payload to send to the output binding - // e.g.: - exchange.getMessage().setBody("myBody"); - }) - .to("dapr:invokeBinding?bindingName=myBinding&bindingOperation=myOperation") - .to("mock:result"); --------------------------------------------------------------------------------- + .setBody(constant("myBody")) + .to("dapr:invokeBinding?bindingName=myBinding&bindingOperation=myOperation") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myBody + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: "myBody" + - to: + uri: dapr:invokeBinding + parameters: + bindingName: myBinding + bindingOperation: myOperation + - to: + uri: mock:result +---- +==== - `secret` - @@ -338,193 +511,499 @@ YAML:: - `configuration` - +._Java-only: uses `List.of()` to set configuration key list_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.CONFIG_KEYS, List.of("k1", "k2")); - }) - .to("dapr:configuration?configStore=myStore") - .log("Received config updates from Dapr: ${body}") - .to("mock:result"); --------------------------------------------------------------------------------- + .process(exchange -> { + exchange.getIn().setHeader("CamelDaprConfigKeys", List.of("k1", "k2")); + }) + .to("dapr:configuration?configStore=myStore") + .log("Received config updates from Dapr: ${body}") + .to("mock:result"); +---- - `lock: tryLock` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.RESOURCE_ID, "myResource"); - exchange.getIn().setHeader(DaprConstants.STORE_NAME, "myStore"); - }) - .to("dapr:lock?lockOperation=tryLock&storeName=myStore&expiryInSeconds=100") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprResourceId", constant("myResource")) + .to("dapr:lock?lockOperation=tryLock&storeName=myStore&expiryInSeconds=100") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myResource + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprResourceId + constant: "myResource" + - to: + uri: dapr:lock + parameters: + lockOperation: tryLock + storeName: myStore + expiryInSeconds: 100 + - to: + uri: mock:result +---- +==== - `lock: unlock` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.RESOURCE_ID, "myResource"); - exchange.getIn().setHeader(DaprConstants.STORE_NAME, "myStore"); - }) - .to("dapr:lock?lockOperation=unlock&storeName=myStore") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprResourceId", constant("myResource")) + .to("dapr:lock?lockOperation=unlock&storeName=myStore") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myResource + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprResourceId + constant: "myResource" + - to: + uri: dapr:lock + parameters: + lockOperation: unlock + storeName: myStore + - to: + uri: mock:result +---- +==== - `workflow: scheduleNew` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .setBody(input) - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.WORKFLOW_CLASS, "my.package.MyWorkflow"); - }) - .to("dapr:workflow?workflowOperation=scheduleNew") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprWorkflowClass", constant("my.package.MyWorkflow")) + .to("dapr:workflow?workflowOperation=scheduleNew") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + my.package.MyWorkflow + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprWorkflowClass + constant: "my.package.MyWorkflow" + - to: + uri: dapr:workflow + parameters: + workflowOperation: scheduleNew + - to: + uri: mock:result +---- +==== - `workflow: terminate` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .setBody(ouput) - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.WORKFLOW_INSTANCE_ID, "myWorkflowInstanceId"); - }) - .to("dapr:workflow?workflowOperation=terminate") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprWorkflowInstanceId", constant("myWorkflowInstanceId")) + .to("dapr:workflow?workflowOperation=terminate") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myWorkflowInstanceId + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprWorkflowInstanceId + constant: "myWorkflowInstanceId" + - to: + uri: dapr:workflow + parameters: + workflowOperation: terminate + - to: + uri: mock:result +---- +==== - `workflow: purge` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.WORKFLOW_INSTANCE_ID, "myWorkflowInstanceId"); - }) - .to("dapr:workflow?workflowOperation=purge") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprWorkflowInstanceId", constant("myWorkflowInstanceId")) + .to("dapr:workflow?workflowOperation=purge") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myWorkflowInstanceId + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprWorkflowInstanceId + constant: "myWorkflowInstanceId" + - to: + uri: dapr:workflow + parameters: + workflowOperation: purge + - to: + uri: mock:result +---- +==== - `workflow: suspend` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.WORKFLOW_INSTANCE_ID, "myWorkflowInstanceId"); - exchange.getIn().setHeader(DaprConstants.REASON, "Suspended for maintenance."); - }) - .to("dapr:workflow?workflowOperation=suspend") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprWorkflowInstanceId", constant("myWorkflowInstanceId")) + .setHeader("CamelDaprSuspendReason", constant("Suspended for maintenance.")) + .to("dapr:workflow?workflowOperation=suspend") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myWorkflowInstanceId + + + Suspended for maintenance. + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprWorkflowInstanceId + constant: "myWorkflowInstanceId" + - setHeader: + name: CamelDaprSuspendReason + constant: "Suspended for maintenance." + - to: + uri: dapr:workflow + parameters: + workflowOperation: suspend + - to: + uri: mock:result +---- +==== - `workflow: resume` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.WORKFLOW_INSTANCE_ID, "myWorkflowInstanceId"); - exchange.getIn().setHeader(DaprConstants.REASON, "Maintenance complete."); - }) - .to("dapr:workflow?workflowOperation=resume") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprWorkflowInstanceId", constant("myWorkflowInstanceId")) + .setHeader("CamelDaprSuspendReason", constant("Maintenance complete.")) + .to("dapr:workflow?workflowOperation=resume") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myWorkflowInstanceId + + + Maintenance complete. + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprWorkflowInstanceId + constant: "myWorkflowInstanceId" + - setHeader: + name: CamelDaprSuspendReason + constant: "Maintenance complete." + - to: + uri: dapr:workflow + parameters: + workflowOperation: resume + - to: + uri: mock:result +---- +==== - `workflow: state` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.WORKFLOW_INSTANCE_ID, "myWorkflowInstanceId"); - }) - .to("dapr:workflow?workflowOperation=state") - .log("Workflow state: ${body}") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprWorkflowInstanceId", constant("myWorkflowInstanceId")) + .to("dapr:workflow?workflowOperation=state") + .log("Workflow state: ${body}") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myWorkflowInstanceId + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprWorkflowInstanceId + constant: "myWorkflowInstanceId" + - to: + uri: dapr:workflow + parameters: + workflowOperation: state + - log: + message: "Workflow state: ${body}" + - to: + uri: mock:result +---- +==== - `workflow: waitForInstanceStart` - +._Java-only: uses `Duration.ofSeconds()` to set timeout_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.WORKFLOW_INSTANCE_ID, "myWorkflowInstanceId"); - exchange.getIn().setHeader(DaprConstants.TIMEOUT, Duration.ofSeconds(30)); - }) - .to("dapr:workflow?workflowOperation=waitForInstanceStart") - .to("mock:result"); --------------------------------------------------------------------------------- + .process(exchange -> { + exchange.getIn().setHeader("CamelDaprWorkflowInstanceId", "myWorkflowInstanceId"); + exchange.getIn().setHeader("CamelDaprTimeout", Duration.ofSeconds(30)); + }) + .to("dapr:workflow?workflowOperation=waitForInstanceStart") + .to("mock:result"); +---- - `workflow: waitForInstanceCompletion` - +._Java-only: uses `Duration.ofSeconds()` to set timeout_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.WORKFLOW_INSTANCE_ID, "myWorkflowInstanceId"); - exchange.getIn().setHeader(DaprConstants.TIMEOUT, Duration.ofSeconds(30)); - }) - .to("dapr:workflow?workflowOperation=waitForInstanceCompletion") - .to("mock:result"); --------------------------------------------------------------------------------- + .process(exchange -> { + exchange.getIn().setHeader("CamelDaprWorkflowInstanceId", "myWorkflowInstanceId"); + exchange.getIn().setHeader("CamelDaprTimeout", Duration.ofSeconds(30)); + }) + .to("dapr:workflow?workflowOperation=waitForInstanceCompletion") + .to("mock:result"); +---- - `workflow: raiseEvent` - +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(DaprConstants.WORKFLOW_INSTANCE_ID, "myWorkflowInstanceId"); - }) - .to("dapr:workflow?workflowOperation=raiseEvent&eventName=MyEvent") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelDaprWorkflowInstanceId", constant("myWorkflowInstanceId")) + .to("dapr:workflow?workflowOperation=raiseEvent&eventName=MyEvent") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myWorkflowInstanceId + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDaprWorkflowInstanceId + constant: "myWorkflowInstanceId" + - to: + uri: dapr:workflow + parameters: + workflowOperation: raiseEvent + eventName: MyEvent + - to: + uri: mock:result +---- +==== === Consumer Operations Examples From 94e23b1595577fdbc8d472f98a1000d8ada0973f Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:05:23 +0200 Subject: [PATCH 28/87] CAMEL-23789: Make Neo4j component docs multi-DSL friendly (Wave 1) - Resolve Neo4j.Headers and Neo4jConstants.Headers references to string values - Add Java-only markers to all 14 ProducerTemplate examples - Clean up indentation and code formatting Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/neo4j-component.adoc | 184 ++++++++++-------- 1 file changed, 105 insertions(+), 79 deletions(-) diff --git a/components/camel-ai/camel-neo4j/src/main/docs/neo4j-component.adoc b/components/camel-ai/camel-neo4j/src/main/docs/neo4j-component.adoc index 240a81beca211..48e431e34d56c 100644 --- a/components/camel-ai/camel-neo4j/src/main/docs/neo4j-component.adoc +++ b/components/camel-ai/camel-neo4j/src/main/docs/neo4j-component.adoc @@ -52,14 +52,16 @@ To create a node in a database named `test`, define the body as a string contain The URI endpoint should contain also specify the label and the alias. .Example: + +._Java-only: ProducerTemplate test API_ [source,java] ---- - var body = "{name: 'Alice', email: 'alice@example.com', age: 30}"; +var body = "{name: 'Alice', email: 'alice@example.com', age: 30}"; - Exchange result = fluentTemplate.to("neo4j:test?alias=u1&label=User") - .withBodyAs(body, String.class) - .withHeader(Neo4j.Headers.OPERATION, Neo4Operation.CREATE_NODE) - .request(Exchange.class); +Exchange result = fluentTemplate.to("neo4j:test?alias=u1&label=User") + .withBodyAs(body, String.class) + .withHeader("CamelNeo4jOperation", Neo4Operation.CREATE_NODE) + .request(Exchange.class); ---- === Create a Node with properties @@ -68,17 +70,19 @@ To create a node in a database named `test` with properties, define the body as The URI endpoint should contain also specify the label and the alias. .Example: + +._Java-only: ProducerTemplate test API with `Map.of()`_ [source,java] ---- - Map params = Map.of( - "name", "Bob", - "email", "bob@example.com", - "age", 25); +Map params = Map.of( + "name", "Bob", + "email", "bob@example.com", + "age", 25); - Exchange result = fluentTemplate.to("neo4j:test?alias=u2&label=User") - .withBodyAs(params, Map.class) - .withHeader(Neo4j.Headers.OPERATION, Neo4Operation.CREATE_NODE) - .request(Exchange.class); +Exchange result = fluentTemplate.to("neo4j:test?alias=u2&label=User") + .withBodyAs(params, Map.class) + .withHeader("CamelNeo4jOperation", Neo4Operation.CREATE_NODE) + .request(Exchange.class); ---- @@ -89,22 +93,26 @@ The URI endpoint should also specify the label and the alias. The response is a List of Map. Each map represents the list of properties of a single node. .Example: + +._Java-only: ProducerTemplate test API_ [source,java] ---- - Exchange result = fluentTemplate.to("neo4j:test?alias=u&label=User") - .withHeader(Neo4j.Headers.OPERATION, Neo4Operation.RETRIEVE_NODES) - .withHeader(Neo4j.Headers.MATCH_PROPERTIES, "{name: 'Alice'}") - .request(Exchange.class); +Exchange result = fluentTemplate.to("neo4j:test?alias=u&label=User") + .withHeader("CamelNeo4jOperation", Neo4Operation.RETRIEVE_NODES) + .withHeader("CamelNeo4jMatchProperties", "{name: 'Alice'}") + .request(Exchange.class); ---- -To retrieve all nodes with label=`User`, use the same request without specifying any `MATCH_PROPERTIES`. +To retrieve all nodes with label=`User`, use the same request without specifying any `CamelNeo4jMatchProperties`. .Example: + +._Java-only: ProducerTemplate test API_ [source,java] ---- - Exchange result = fluentTemplate.to("neo4j:test?alias=u&label=User") - .withHeader(Neo4j.Headers.OPERATION, Neo4Operation.RETRIEVE_NODES) - .request(Exchange.class); +Exchange result = fluentTemplate.to("neo4j:test?alias=u&label=User") + .withHeader("CamelNeo4jOperation", Neo4Operation.RETRIEVE_NODES) + .request(Exchange.class); ---- === Delete Node @@ -113,12 +121,14 @@ To delete a node in a database named `test`. Define the header `MATCH_PROPERTIES The URI endpoint should also specify the label and the alias. .Example: + +._Java-only: ProducerTemplate test API_ [source,java] ---- - Exchange result = fluentTemplate.to("neo4j:test?alias=u&label=User") - .withHeader(Neo4j.Headers.OPERATION, Neo4Operation.DELETE_NODE) - .withHeader(Neo4j.Headers.MATCH_PROPERTIES, "{name: 'Alice'}") - .request(Exchange.class); +Exchange result = fluentTemplate.to("neo4j:test?alias=u&label=User") + .withHeader("CamelNeo4jOperation", Neo4Operation.DELETE_NODE) + .withHeader("CamelNeo4jMatchProperties", "{name: 'Alice'}") + .request(Exchange.class); ---- === Delete Node with relationships @@ -127,12 +137,14 @@ If a node has relationships, it won't be deleted unless we either delete the rel To delete a node with detached relationships, set the option `detachRelationship` to `true`. .Example: + +._Java-only: ProducerTemplate test API_ [source,java] ---- - Exchange result = fluentTemplate.to("neo4j:test?alias=u&label=User&detachRelationship=true") - .withHeader(Neo4j.Headers.OPERATION, Neo4Operation.DELETE_NODE) - .withHeader(Neo4j.Headers.MATCH_PROPERTIES, "{name: 'Alice'}") - .request(Exchange.class); +Exchange result = fluentTemplate.to("neo4j:test?alias=u&label=User&detachRelationship=true") + .withHeader("CamelNeo4jOperation", Neo4Operation.DELETE_NODE) + .withHeader("CamelNeo4jMatchProperties", "{name: 'Alice'}") + .request(Exchange.class); ---- == Graph database usage - use Cypher Queries @@ -143,23 +155,27 @@ To create or delete nodes with a Cypher query in a database named `test`, set th The operation can be used too to create multiple nodes and relationships between nodes. .Example creating a node: + +._Java-only: ProducerTemplate test API_ [source,java] ---- - var cypherQuery = "CREATE (u3:User {name: 'Charlie', email: 'charlie@example.com', age: 35})"; - Exchange result = fluentTemplate.to("neo4j:test") - .withHeader(Neo4j.Headers.OPERATION, Neo4Operation.ADD_OR_DELETE_NODE_WITH_CYPHER_QUERY) - .withBodyAs(cypherQuery, String.class) - .request(Exchange.class); +var cypherQuery = "CREATE (u3:User {name: 'Charlie', email: 'charlie@example.com', age: 35})"; +Exchange result = fluentTemplate.to("neo4j:test") + .withHeader("CamelNeo4jOperation", Neo4Operation.ADD_OR_DELETE_NODE_WITH_CYPHER_QUERY) + .withBodyAs(cypherQuery, String.class) + .request(Exchange.class); ---- .Example deleting a node: + +._Java-only: ProducerTemplate test API_ [source,java] ---- - var cypherQuery = "MATCH (u:User {name: 'Bob'}) DELETE u"; - Exchange result = fluentTemplate.to("neo4j:test") - .withHeader(Neo4j.Headers.OPERATION, Neo4Operation.ADD_OR_DELETE_NODE_WITH_CYPHER_QUERY) - .withBodyAs(cypherQuery, String.class) - .request(Exchange.class); +var cypherQuery = "MATCH (u:User {name: 'Bob'}) DELETE u"; +Exchange result = fluentTemplate.to("neo4j:test") + .withHeader("CamelNeo4jOperation", Neo4Operation.ADD_OR_DELETE_NODE_WITH_CYPHER_QUERY) + .withBodyAs(cypherQuery, String.class) + .request(Exchange.class); ---- === Retrieve / Update nodes with a Cypher query @@ -168,17 +184,19 @@ To retrieve or update nodes with Cypher Query in a database named `test`, set th The operation is the same as `ADD_OR_DELETE_NODE_WITH_CYPHER_QUERY`, except that it returns a list of retrieved or updated nodes represented as `Map`. .Example updating a node: + +._Java-only: ProducerTemplate test API with string concatenation_ [source,java] ---- - var cypherQuery = "MATCH " + - "(u:User {name: 'Ethan'})" + - "SET u.age=41 " + - "RETURN u"; +var cypherQuery = "MATCH " + + "(u:User {name: 'Ethan'})" + + "SET u.age=41 " + + "RETURN u"; - Exchange result = fluentTemplate.to("neo4j:test") - .withBodyAs(cypherQuery, String.class) - .withHeader(Neo4j.Headers.OPERATION, Neo4Operation.RETRIEVE_NODES_AND_UPDATE_WITH_CYPHER_QUERY) - .request(Exchange.class); +Exchange result = fluentTemplate.to("neo4j:test") + .withBodyAs(cypherQuery, String.class) + .withHeader("CamelNeo4jOperation", Neo4Operation.RETRIEVE_NODES_AND_UPDATE_WITH_CYPHER_QUERY) + .request(Exchange.class); ---- == Vector database embeddings usage @@ -190,11 +208,13 @@ To create a vector index in a database named `test`, use the operation `CREATE_V The URI endpoint should also specify the label, the alias, the vector index name and the dimension of embeddings. .Example: + +._Java-only: ProducerTemplate test API_ [source,java] ---- - Exchange result = fluentTemplate.to("neo4j:test?vectorIndexName=movieIdx&alias=m&label=Movie&dimension=2") - .withHeader(Neo4j.Headers.OPERATION, Neo4Operation.CREATE_VECTOR_INDEX) - .request(Exchange.class); +Exchange result = fluentTemplate.to("neo4j:test?vectorIndexName=movieIdx&alias=m&label=Movie&dimension=2") + .withHeader("CamelNeo4jOperation", Neo4Operation.CREATE_VECTOR_INDEX) + .request(Exchange.class); ---- === Drop a vector index @@ -202,11 +222,13 @@ To drop a vector index in a database named `test`, use the operation `DROP_VECTO The URI endpoint should contain also specify the vector index name. .Example: + +._Java-only: ProducerTemplate test API_ [source,java] ---- - Exchange result = fluentTemplate.to("neo4j:test?vectorIndexName=movieIdx") - .withHeader(Neo4j.Headers.OPERATION, Neo4Operation.DROP_VECTOR_INDEX) - .request(Exchange.class); +Exchange result = fluentTemplate.to("neo4j:test?vectorIndexName=movieIdx") + .withHeader("CamelNeo4jOperation", Neo4Operation.DROP_VECTOR_INDEX) + .request(Exchange.class); ---- === Create a vector @@ -219,14 +241,16 @@ Camel Neo4j will create the node and store the vector as an `embedding` property .Example: + +._Java-only: ProducerTemplate test API with `float[]` vector_ [source,java] ---- - Exchange result = fluentTemplate.to("neo4j:test?vectorIndexName=myIndex&label=Test&alias=t") - .withHeader(Neo4jConstants.Headers.OPERATION, Neo4Operation.CREATE_VECTOR) - .withHeader(Neo4jConstants.Headers.VECTOR_ID, "1") - .withHeader("CamelLangChain4jEmbeddingsVector", new float[] { 10.8f, 10.6f }) - .withBody("Hello World!") - .request(Exchange.class); +Exchange result = fluentTemplate.to("neo4j:test?vectorIndexName=myIndex&label=Test&alias=t") + .withHeader("CamelNeo4jOperation", Neo4Operation.CREATE_VECTOR) + .withHeader("CamelNeo4jVectorEmbeddingId", "1") + .withHeader("CamelLangChain4jEmbeddingsVector", new float[] { 10.8f, 10.6f }) + .withBody("Hello World!") + .request(Exchange.class); ---- === Similarity search @@ -235,26 +259,30 @@ To perform a similarity search using vectors in a database named `test`, use the The URI endpoint should also specify the label, the alias and the vector index name. .Example: + +._Java-only: ProducerTemplate test API with `List.of()` vector_ [source,java] ---- - Exchange result = fluentTemplate.to("neo4j:test?vectorIndexName=myIndex&label=Test&alias=t") - .withHeader(Neo4jConstants.Headers.OPERATION, Neo4Operation.VECTOR_SIMILARITY_SEARCH) - .withBody(List.of(0.75f, 0.65f)) - .request(Exchange.class); +Exchange result = fluentTemplate.to("neo4j:test?vectorIndexName=myIndex&label=Test&alias=t") + .withHeader("CamelNeo4jOperation", Neo4Operation.VECTOR_SIMILARITY_SEARCH) + .withBody(List.of(0.75f, 0.65f)) + .request(Exchange.class); ---- == Generate Embeddings with Langchain4j-embeddings You can generate embeddings with an Embedding Models using the camel Lancghain4j Embeddings components. Camel Neo4j introduces a DataType `neo4j:embeddings` that automates the transformations of the Lancghain4j embeddings to Neo4j vectors. .Example of a camel Route that create embeddings with Camel Langchain4j Embeddings, and ingest them into Neo4j database. + +._Java-only: uses `DataType` and `Neo4Operation` enum for embedding transformation_ [source,java] ---- - from("direct:in") - .to("langchain4j-embeddings:test") - .setHeader(Neo4j.Headers.OPERATION).constant(Neo4Operation.CREATE_VECTOR) - .setHeader(Neo4j.Headers.LABEL).constant("Test") - .transformDataType(new DataType("neo4j:embeddings")) - .to("neo4j:neo4j?vectorIndexName=myIndex&label=Test"); +from("direct:in") + .to("langchain4j-embeddings:test") + .setHeader("CamelNeo4jOperation").constant(Neo4Operation.CREATE_VECTOR) + .setHeader("CamelNeo4jLabel").constant("Test") + .transformDataType(new DataType("neo4j:embeddings")) + .to("neo4j:neo4j?vectorIndexName=myIndex&label=Test"); ---- == Similarity Search for LangChain4j RAG @@ -267,16 +295,14 @@ Next, use the `neo4j:rag` DataType to convert the retrieved embeddings into a Li NOTE: The retrieved embeddings must be ingested in Neo4j as LangChain4j embeddings. .Example of a camel Route that performs a similarity search in the Vector index, using a string and returning a list of strings + +._Java-only: uses `DataType` transforms for embedding and RAG conversion_ [source,java] ---- - from("direct:search") - .to("langchain4j-embeddings:test") - // transform prompt into embeddings for search - .transform( - new DataType("neo4j:embeddings")) - .setHeader(Neo4jConstants.Headers.OPERATION, constant(Neo4Operation.VECTOR_SIMILARITY_SEARCH)) - .to("neo4j:neo4j?vectorIndexName=myIndex&label=Test") - // decode retrieved embeddings for RAG - .transform( - new DataType("neo4j:rag")); +from("direct:search") + .to("langchain4j-embeddings:test") + .transform(new DataType("neo4j:embeddings")) + .setHeader("CamelNeo4jOperation", constant(Neo4Operation.VECTOR_SIMILARITY_SEARCH)) + .to("neo4j:neo4j?vectorIndexName=myIndex&label=Test") + .transform(new DataType("neo4j:rag")); ---- From dd33a67826cb0daf9d30684b91d7f5733191c98a Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:07:26 +0200 Subject: [PATCH 29/87] CAMEL-23789: Make OpenAI component docs multi-DSL friendly (Wave 1) - Convert 6 simple route examples to Java/XML/YAML tabs (file prompt, image input, S3 image, media type header, JSON schema, schema resource) - Add YAML tab to MCP OAuth example - Add Java-only markers to SDK-specific examples (outputClass, SSLContextParameters, SimilarityUtils, conversation history, batch embeddings, multi-turn) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/openai-component.adoc | 255 +++++++++++++++++- 1 file changed, 247 insertions(+), 8 deletions(-) diff --git a/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc b/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc index cdef262e4a516..f545bd2d8653f 100644 --- a/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc +++ b/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc @@ -117,6 +117,10 @@ YAML:: MCP servers can also use OAuth independently via per-server `oauthProfile`: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:chat") @@ -127,6 +131,25 @@ from("direct:chat") + "&mcpServer.tools.oauthProfile=keycloak"); ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: openai:chat-completion + parameters: + model: gpt-4 + oauthProfile: azure + mcpServer.tools.transportType: streamableHttp + mcpServer.tools.url: https://mcp.internal/mcp + mcpServer.tools.oauthProfile: keycloak +---- +==== + === Basic Chat Completion with String Input [tabs] @@ -174,7 +197,10 @@ YAML:: === File-Backed Prompt with Text File -.Usage example: +[tabs] +==== +Java:: ++ [source,java] ---- from("file:prompts?noop=true") @@ -182,11 +208,38 @@ from("file:prompts?noop=true") .log("Response: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:prompts?noop=true + steps: + - to: + uri: openai:chat-completion + - log: + message: "Response: ${body}" +---- +==== === Image File Input with Vision Model -.Usage example: +[tabs] +==== +Java:: ++ [source,java] ---- from("file:images?noop=true") @@ -194,9 +247,41 @@ from("file:images?noop=true") .log("Response: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:images?noop=true + steps: + - to: + uri: openai:chat-completion + parameters: + model: gpt-4.1-mini + userMessage: Describe what you see in this image + - log: + message: "Response: ${body}" +---- +==== + Image input also works with bodies produced by remote file and cloud storage components, such as FTP/SFTP (`WrappedFile`), AWS S3, Azure Blob Storage or MinIO (`byte[]` or `InputStream`). The MIME type is detected from the component's content-type header or the file name: -.Usage example: +[tabs] +==== +Java:: ++ [source,java] ---- from("aws2-s3:my-bucket") @@ -204,9 +289,41 @@ from("aws2-s3:my-bucket") .log("Response: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: aws2-s3:my-bucket + steps: + - to: + uri: openai:chat-completion + parameters: + model: gpt-4.1-mini + userMessage: Describe what you see in this image + - log: + message: "Response: ${body}" +---- +==== + When no content-type header is available, set the `CamelOpenAIMediaType` header explicitly: -.Usage example: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:image") @@ -216,6 +333,46 @@ from("direct:image") .log("Response: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + image/png + + + Describe what you see in this image + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:image + steps: + - setHeader: + name: CamelOpenAIMediaType + constant: "image/png" + - setHeader: + name: CamelOpenAIUserMessage + constant: "Describe what you see in this image" + - to: + uri: openai:chat-completion + parameters: + model: gpt-4.1-mini + - log: + message: "Response: ${body}" +---- +==== + [NOTE] ==== When using image input, the userMessage is required. Supported image formats are detected by MIME type (e.g., `image/png`, `image/jpeg`, `image/gif`, `image/webp`). @@ -263,7 +420,7 @@ When `streaming=true`, the component returns an `Iterator` .When `outputClass` is set, the model is instructed to produce JSON matching the given class, but the component returns the raw String. Deserialize the body yourself (e.g., with Camel's Jackson) if you need a typed object. -.Usage example: +._Java-only: uses Java class definition for `outputClass` schema_ [source,java] ---- public class Person { @@ -282,7 +439,10 @@ from("direct:structured") The `jsonSchema` option instructs the model to return JSON that conforms to the provided schema. The response will be valid JSON but is not automatically validated against the schema: -.Usage example: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:json-schema") @@ -292,9 +452,49 @@ from("direct:json-schema") .log("JSON response: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + Create a product description + + + {"type":"object","properties":{"name":{"type":"string"},"price":{"type":"number"}}} + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:json-schema + steps: + - setBody: + constant: "Create a product description" + - setHeader: + name: CamelOpenAIJsonSchema + constant: '{"type":"object","properties":{"name":{"type":"string"},"price":{"type":"number"}}}' + - to: + uri: openai:chat-completion + - log: + message: "JSON response: ${body}" +---- +==== + You can also load the schema from a resource file: -.Usage example: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:json-schema-resource") @@ -303,6 +503,39 @@ from("direct:json-schema-resource") .log("JSON response: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + Create a product description + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:json-schema-resource + steps: + - setBody: + constant: "Create a product description" + - to: + uri: openai:chat-completion + parameters: + jsonSchema: "resource:classpath:schemas/product.schema.json" + - log: + message: "JSON response: ${body}" +---- +==== + [NOTE] ==== For full schema validation, integrate with the `camel-json-validator` component after receiving the response. @@ -388,7 +621,7 @@ IMPORTANT: Example of manual conversation history: -.Usage example: +._Java-only: uses OpenAI SDK `ChatCompletionMessageParam` types_ [source,java] ---- List history = new ArrayList<>(); @@ -412,6 +645,7 @@ When no SSL parameters are set, the default JVM trust store is used. The component implements `SSLContextParametersAware` and supports Camel's standard `SSLContextParameters` for SSL configuration. When set, `SSLContextParameters` takes precedence over the individual `ssl*` properties (same pattern as `camel-kafka`). +._Java-only: programmatic `SSLContextParameters` configuration_ [source,java] ---- KeyStoreParameters trustStoreParams = new KeyStoreParameters(); @@ -432,6 +666,7 @@ from("direct:chat") To use global SSL context parameters for all OpenAI endpoints: +._Java-only: programmatic component configuration_ [source,java] ---- OpenAIComponent openai = context.getComponent("openai", OpenAIComponent.class); @@ -762,6 +997,7 @@ Additional metadata (model, token usage, vector size, count) is exposed via head You can embed multiple texts in a single request by passing a `List`: +._Java-only: uses `List.of()` for batch input_ [source,java] ---- from("direct:batch-embed") @@ -842,6 +1078,7 @@ For specialized vector workloads, you can also use `camel-qdrant`, `camel-weavia The component can automatically calculate cosine similarity when a reference embedding is provided: +._Java-only: uses `List` variable for reference embedding_ [source,java] ---- List referenceEmbedding = /* previously computed embedding */; @@ -855,6 +1092,7 @@ from("direct:compare") You can also use `SimilarityUtils` directly for manual calculations: +._Java-only: `SimilarityUtils` API for vector math_ [source,java] ---- import org.apache.camel.component.openai.SimilarityUtils; @@ -1240,6 +1478,7 @@ YAML:: With this route, a multi-turn conversation works as follows: +._Java-only: ProducerTemplate test API with conversation history management_ [source,java] ---- // Turn 1: the model calls the "add" tool and returns the result From e01a57a079c7f73495b213cd30e98e21a7a13c80 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:09:27 +0200 Subject: [PATCH 30/87] CAMEL-23789: Make Spring AI Chat component docs multi-DSL friendly (Wave 1) - Convert simple chat route to Java/XML/YAML tabs - Add Java-only markers to 14 SDK-specific examples (ChatMemory, VectorStore, Message types, @Tool, ChatClient, multimodal, structured output, RAG, ProducerTemplate) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/spring-ai-chat-component.adoc | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-chat/src/main/docs/spring-ai-chat-component.adoc b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-chat/src/main/docs/spring-ai-chat-component.adoc index 80af04348f109..98f99780c8c53 100644 --- a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-chat/src/main/docs/spring-ai-chat-component.adoc +++ b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-chat/src/main/docs/spring-ai-chat-component.adoc @@ -67,12 +67,44 @@ The component supports three types of chat operations: ==== Simple Chat (Single Message) +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:chat") .to("spring-ai-chat:test?chatModel=#chatModel"); +---- -// Usage: +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: spring-ai-chat:test + parameters: + chatModel: "#chatModel" +---- +==== + +._Java-only: ProducerTemplate test API_ +[source,java] +---- String response = template.requestBody("direct:chat", "What is the capital of Italy?", String.class); ---- @@ -80,6 +112,7 @@ String response = template.requestBody("direct:chat", "What is the capital of It Use the `CHAT_SINGLE_MESSAGE_WITH_PROMPT` operation to leverage Spring AI's template engine: +._Java-only: ProducerTemplate test API with `Map.of()` and Spring AI constants_ [source,java] ---- from("direct:chat") @@ -105,6 +138,7 @@ String response = template.requestBodyAndHeader( Maintain conversation context by sending multiple messages: +._Java-only: uses Spring AI `Message` types and ProducerTemplate_ [source,java] ---- import org.springframework.ai.chat.messages.*; @@ -130,6 +164,7 @@ RAG allows you to augment prompts with relevant context from your data sources, Configure a VectorStore for automatic context retrieval: +._Java-only: programmatic VectorStore and registry configuration_ [source,java] ---- import org.springframework.ai.vectorstore.VectorStore; @@ -156,6 +191,7 @@ The component will automatically: Use the `SpringAiRagAggregatorStrategy` with Camel's Content Enricher EIP: +._Java-only: programmatic aggregation strategy configuration_ [source,java] ---- import org.apache.camel.component.springai.chat.rag.SpringAiRagAggregatorStrategy; @@ -174,6 +210,7 @@ from("direct:retrieve-context") Directly provide augmented data via the `AUGMENTED_DATA` header: +._Java-only: uses Spring AI `Document` type and ProducerTemplate_ [source,java] ---- import org.springframework.ai.document.Document; @@ -299,6 +336,7 @@ NOTE: Chat memory is only activated when the `CamelSpringAiChatConversationId` h Configure a `ChatMemory` on the endpoint for automatic conversation tracking using traditional message window approach. This strategy keeps a configurable number of recent messages in memory. +._Java-only: programmatic Spring AI `ChatMemory` setup and ProducerTemplate usage_ [source,java] ---- // Create chat memory with message window @@ -325,6 +363,7 @@ template.requestBodyAndHeader("direct:chat", "What's my name?", For long-term memory with semantic retrieval capabilities, configure a `VectorStore` for chat memory. This strategy uses vector embeddings to enable semantic search over conversation history, making it ideal for retrieving contextually relevant information rather than just recent messages. +._Java-only: programmatic Ollama embedding model and VectorStore setup_ [source,java] ---- OllamaApi ollamaApi = OllamaApi.builder() @@ -423,6 +462,7 @@ The component supports multimodal input for models that support vision, audio, a The component seamlessly integrates with Camel file components (file, ftp, sftp, smb) through `WrappedFile` support, enabling direct routing from file sources to AI chat. Media can also be sent as byte arrays or as lists of files with appropriate headers. +._Java-only: uses ProducerTemplate, `WrappedFile` aggregation, and Spring AI `UserMessage`/`Media` types_ [source,java] ---- // Direct file-to-AI pipeline (MIME type auto-detected) @@ -532,6 +572,7 @@ The component supports structured output conversion, allowing you to convert LLM Three output formats are supported: **BEAN** (Java records/POJOs), **MAP** (key-value structures), and **LIST** (arrays). Each can be configured via converter bean, endpoint parameters, or headers. +._Java-only: uses Java record definition and ProducerTemplate_ [source,java] ---- // Bean output - convert to typed Java objects @@ -566,6 +607,7 @@ template.requestBodyAndHeader("direct:chat", "List programming languages", For maximum control, you can provide a pre-configured `ChatClient` instead of a `ChatModel`: +._Java-only: programmatic `ChatClient` builder configuration_ [source,java] ---- ChatClient chatClient = ChatClient.builder(chatModel) @@ -589,6 +631,7 @@ When using Camel Spring Boot, Spring AI's auto-configuration automatically disco methods from Spring beans via `ToolCallbackResolver`. Simply define your tool as a Spring bean and reference it by name using `toolNames`: +._Java-only: Spring `@Component` with `@Tool` annotation_ [source,java] ---- @Component @@ -615,6 +658,7 @@ from("direct:chat") Outside Spring Boot (e.g., in plain Camel or tests), there is no `ToolCallbackResolver`. You need to resolve the callbacks manually and bind them in the registry: +._Java-only: programmatic `ToolCallbackProvider` setup_ [source,java] ---- ToolCallbackProvider provider = MethodToolCallbackProvider.builder() @@ -650,6 +694,7 @@ both tool sources are additive. Pass contextual data (user ID, session info, tenant ID, etc.) to tools during execution. Tools with a `ToolContext` parameter receive these values automatically: +._Java-only: `@Tool` with `ToolContext` and ProducerTemplate_ [source,java] ---- // Tool that uses context From c1af55b256981f43adc4b6bab776fd16c547988c Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:17:50 +0200 Subject: [PATCH 31/87] CAMEL-23789: Make IBM watsonx.ai component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/ibm-watsonx-ai-component.adoc | 1194 ++++++++++++++--- 1 file changed, 984 insertions(+), 210 deletions(-) diff --git a/components/camel-ibm/camel-ibm-watsonx-ai/src/main/docs/ibm-watsonx-ai-component.adoc b/components/camel-ibm/camel-ibm-watsonx-ai/src/main/docs/ibm-watsonx-ai-component.adoc index 9abe5d8aa45fc..73bd6d887e4e1 100644 --- a/components/camel-ibm/camel-ibm-watsonx-ai/src/main/docs/ibm-watsonx-ai-component.adoc +++ b/components/camel-ibm/camel-ibm-watsonx-ai/src/main/docs/ibm-watsonx-ai-component.adoc @@ -72,12 +72,44 @@ camel.oauth.ibm.client-secret=my-secret camel.oauth.ibm.token-endpoint=https://iam.cloud.ibm.com/identity/token ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:generate") .to("ibm-watsonx-ai:myLabel?oauthProfile=ibm&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=my-project&modelId=ibm/granite-13b-instruct-v2"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:generate + steps: + - to: + uri: ibm-watsonx-ai:myLabel + parameters: + oauthProfile: ibm + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: my-project + modelId: ibm/granite-13b-instruct-v2 +---- +==== + == Security Considerations === Sensitive Data Logging @@ -225,40 +257,121 @@ If you don't specify an operation explicitly, you must set it via the `operation Chat with a simple string message (automatically converted to a user message): +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:simpleChat") - .setBody(constant("What is the capital of France?")) - .to("ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&modelId=ibm/granite-4-h-small" + - "&operation=chat") - .log("Response: ${body}"); --------------------------------------------------------------------------------- + .setBody(constant("What is the capital of France?")) + .to("ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-4-h-small&operation=chat") + .log("Response: ${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + What is the capital of France? + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:simpleChat + steps: + - setBody: + constant: "What is the capital of France?" + - to: + uri: ibm-watsonx-ai:chat + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + modelId: ibm/granite-4-h-small + operation: chat + - log: + message: "Response: ${body}" +---- +==== === Chat with System Message Use a system message to control the assistant's behavior: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:chatWithSystem") - .setHeader("CamelIBMWatsonxAiSystemMessage", - constant("You are a helpful assistant. Keep your answers brief.")) - .setBody(constant("What is the capital of Italy?")) - .to("ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&modelId=ibm/granite-4-h-small" + - "&operation=chat") - .log("Response: ${body}"); --------------------------------------------------------------------------------- + .setHeader("CamelIBMWatsonxAiSystemMessage", + constant("You are a helpful assistant. Keep your answers brief.")) + .setBody(constant("What is the capital of Italy?")) + .to("ibm-watsonx-ai:chat?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-4-h-small&operation=chat") + .log("Response: ${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + You are a helpful assistant. Keep your answers brief. + + + What is the capital of Italy? + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chatWithSystem + steps: + - setHeader: + name: CamelIBMWatsonxAiSystemMessage + constant: "You are a helpful assistant. Keep your answers brief." + - setBody: + constant: "What is the capital of Italy?" + - to: + uri: ibm-watsonx-ai:chat + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + modelId: ibm/granite-4-h-small + operation: chat + - log: + message: "Response: ${body}" +---- +==== === Streaming Chat Stream chat responses with a callback consumer: +._Java-only: uses `Consumer` callback and `UserMessage` SDK type_ [source,java] -------------------------------------------------------------------------------- import com.ibm.watsonx.ai.chat.model.UserMessage; @@ -459,6 +572,7 @@ NOTE: Tool operations require the `wxUrl` configuration (e.g., `https://api.data Generate embeddings for semantic search and similarity: +._Java-only: uses `List.of()` for batch input and `process` lambda for typed result handling_ [source,java] -------------------------------------------------------------------------------- from("direct:embed") @@ -482,22 +596,60 @@ from("direct:embed") Generate embedding for a single text input: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:embedSingle") - .setBody(constant("Apache Camel makes integration easy")) - .to("ibm-watsonx-ai:embed?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&modelId=ibm/slate-125m-english-rtrvr" + - "&operation=embedding") - .log("Embedding vector size: ${header.CamelIBMWatsonxAiEmbeddings[0].size()}"); --------------------------------------------------------------------------------- + .setBody(constant("Apache Camel makes integration easy")) + .to("ibm-watsonx-ai:embed?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/slate-125m-english-rtrvr&operation=embedding") + .log("Embedding vector size: ${header.CamelIBMWatsonxAiEmbeddings[0].size()}"); +---- + +XML:: ++ +[source,xml] +---- + + + + Apache Camel makes integration easy + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:embedSingle + steps: + - setBody: + constant: "Apache Camel makes integration easy" + - to: + uri: ibm-watsonx-ai:embed + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + modelId: ibm/slate-125m-english-rtrvr + operation: embedding + - log: + message: "Embedding vector size: ${header.CamelIBMWatsonxAiEmbeddings[0].size()}" +---- +==== === Embedding with Vector Database (Qdrant) Generate an embedding and store it in a Qdrant vector database for semantic search: +._Java-only: uses Qdrant SDK types (`Points.PointStruct`, `VectorsFactory`, etc.) for vector construction_ [source,java] -------------------------------------------------------------------------------- import org.apache.camel.component.qdrant.QdrantHeaders; @@ -535,6 +687,7 @@ NOTE: This example requires the `camel-qdrant` dependency. See the xref:qdrant-c Rerank documents by relevance to a query: +._Java-only: uses `process` lambda with `List.of()` for document input_ [source,java] -------------------------------------------------------------------------------- from("direct:rerank") @@ -565,6 +718,7 @@ from("direct:rerank") Return only the top N most relevant documents: +._Java-only: uses `List.of()` for document input_ [source,java] -------------------------------------------------------------------------------- from("direct:rerankTopN") @@ -589,67 +743,217 @@ from("direct:rerankTopN") Count tokens in text (useful for context window management): +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:tokenize") - .setBody(constant("Hello, how are you today?")) - .to("ibm-watsonx-ai:tokenize?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&modelId=ibm/granite-4-h-small" + - "&operation=tokenize") - .log("Token count: ${header.CamelIBMWatsonxAiTokenCount}") - .log("Tokens: ${header.CamelIBMWatsonxAiTokens}"); --------------------------------------------------------------------------------- + .setBody(constant("Hello, how are you today?")) + .to("ibm-watsonx-ai:tokenize?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-4-h-small&operation=tokenize") + .log("Token count: ${header.CamelIBMWatsonxAiTokenCount}") + .log("Tokens: ${header.CamelIBMWatsonxAiTokens}"); +---- + +XML:: ++ +[source,xml] +---- + + + + Hello, how are you today? + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:tokenize + steps: + - setBody: + constant: "Hello, how are you today?" + - to: + uri: ibm-watsonx-ai:tokenize + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + modelId: ibm/granite-4-h-small + operation: tokenize + - log: + message: "Token count: ${header.CamelIBMWatsonxAiTokenCount}" + - log: + message: "Tokens: ${header.CamelIBMWatsonxAiTokens}" +---- +==== === Content Detection (PII/HAP) Detect personally identifiable information (PII) and harmful/abusive/profane (HAP) content: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:detect") - .setBody(constant("Contact John Smith at john.smith@example.com or call 555-123-4567")) - .to("ibm-watsonx-ai:detect?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&operation=detect" + - "&detectPii=true") - .choice() - .when(header("CamelIBMWatsonxAiDetected").isEqualTo(true)) - .log("PII detected! Count: ${header.CamelIBMWatsonxAiDetectionCount}") - .log("Detection details: ${header.CamelIBMWatsonxAiDetectionResults}") - .otherwise() - .log("No PII detected in content") - .end(); --------------------------------------------------------------------------------- + .setBody(constant("Contact John Smith at john.smith@example.com or call 555-123-4567")) + .to("ibm-watsonx-ai:detect?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=detect&detectPii=true") + .choice() + .when(header("CamelIBMWatsonxAiDetected").isEqualTo(true)) + .log("PII detected! Count: ${header.CamelIBMWatsonxAiDetectionCount}") + .log("Detection details: ${header.CamelIBMWatsonxAiDetectionResults}") + .otherwise() + .log("No PII detected in content") + .end(); +---- + +XML:: ++ +[source,xml] +---- + + + + Contact John Smith at john.smith@example.com or call 555-123-4567 + + + + + ${header.CamelIBMWatsonxAiDetected} == true + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:detect + steps: + - setBody: + constant: "Contact John Smith at john.smith@example.com or call 555-123-4567" + - to: + uri: ibm-watsonx-ai:detect + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + operation: detect + detectPii: true + - choice: + when: + - simple: "${header.CamelIBMWatsonxAiDetected} == true" + steps: + - log: + message: "PII detected! Count: ${header.CamelIBMWatsonxAiDetectionCount}" + - log: + message: "Detection details: ${header.CamelIBMWatsonxAiDetectionResults}" + otherwise: + steps: + - log: + message: "No PII detected in content" +---- +==== === Content Detection with HAP Threshold Detect harmful content with a custom threshold: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:detectHap") - .setBody(constant("Some text that might contain harmful content")) - .to("ibm-watsonx-ai:detect?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&operation=detect" + - "&detectHap=true" + - "&detectionThreshold=0.5") - .choice() - .when(header("CamelIBMWatsonxAiDetected").isEqualTo(true)) - .log("ALERT: Harmful content detected!") - .otherwise() - .log("Content is safe") - .end(); --------------------------------------------------------------------------------- + .setBody(constant("Some text that might contain harmful content")) + .to("ibm-watsonx-ai:detect?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=detect&detectHap=true&detectionThreshold=0.5") + .choice() + .when(header("CamelIBMWatsonxAiDetected").isEqualTo(true)) + .log("ALERT: Harmful content detected!") + .otherwise() + .log("Content is safe") + .end(); +---- + +XML:: ++ +[source,xml] +---- + + + + Some text that might contain harmful content + + + + + ${header.CamelIBMWatsonxAiDetected} == true + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:detectHap + steps: + - setBody: + constant: "Some text that might contain harmful content" + - to: + uri: ibm-watsonx-ai:detect + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + operation: detect + detectHap: true + detectionThreshold: 0.5 + - choice: + when: + - simple: "${header.CamelIBMWatsonxAiDetected} == true" + steps: + - log: + message: "ALERT: Harmful content detected!" + otherwise: + steps: + - log: + message: "Content is safe" +---- +==== === Content Detection with Custom Detectors Provide custom detectors via header: +._Java-only: uses watsonx.ai SDK detector types (`Pii`, `Hap`)_ [source,java] -------------------------------------------------------------------------------- import com.ibm.watsonx.ai.detection.detector.Pii; @@ -676,68 +980,179 @@ Extract text from documents stored in IBM Cloud Object Storage: NOTE: This operation requires COS configuration including cosUrl, documentConnectionId, documentBucket, resultConnectionId, and resultBucket. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:extract") - .setBody(constant("documents/report.pdf")) // Path in COS bucket - .to("ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&operation=textExtraction" + - "&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud" + - "&documentConnectionId=your-cos-connection-id" + - "&documentBucket=your-input-bucket" + - "&resultConnectionId=your-cos-connection-id" + - "&resultBucket=your-output-bucket") - .process(exchange -> { - String extractionId = exchange.getMessage().getHeader("CamelIBMWatsonxAiExtractionId", String.class); - String status = exchange.getMessage().getHeader("CamelIBMWatsonxAiExtractionStatus", String.class); - System.out.println("Extraction job started: " + extractionId); - System.out.println("Status: " + status); - }); --------------------------------------------------------------------------------- + .setBody(constant("documents/report.pdf")) + .to("ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textExtraction&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket&resultConnectionId=your-cos-connection-id&resultBucket=your-output-bucket") + .log("Extraction job started: ${header.CamelIBMWatsonxAiExtractionId}") + .log("Status: ${header.CamelIBMWatsonxAiExtractionStatus}"); +---- + +XML:: ++ +[source,xml] +---- + + + + documents/report.pdf + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:extract + steps: + - setBody: + constant: "documents/report.pdf" + - to: + uri: ibm-watsonx-ai:extract + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + operation: textExtraction + cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud" + documentConnectionId: your-cos-connection-id + documentBucket: your-input-bucket + resultConnectionId: your-cos-connection-id + resultBucket: your-output-bucket + - log: + message: "Extraction job started: ${header.CamelIBMWatsonxAiExtractionId}" + - log: + message: "Status: ${header.CamelIBMWatsonxAiExtractionStatus}" +---- +==== === Fetch Text Extraction Results Poll for extraction completion and get results: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:fetchExtraction") - .setHeader("CamelIBMWatsonxAiExtractionId", constant("your-extraction-job-id")) - .to("ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&operation=textExtractionFetch" + - "&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud" + - "&documentConnectionId=your-cos-connection-id" + - "&documentBucket=your-input-bucket" + - "&resultConnectionId=your-cos-connection-id" + - "&resultBucket=your-output-bucket") - .log("Extraction status: ${header.CamelIBMWatsonxAiExtractionStatus}"); --------------------------------------------------------------------------------- + .setHeader("CamelIBMWatsonxAiExtractionId", constant("your-extraction-job-id")) + .to("ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textExtractionFetch&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket&resultConnectionId=your-cos-connection-id&resultBucket=your-output-bucket") + .log("Extraction status: ${header.CamelIBMWatsonxAiExtractionStatus}"); +---- + +XML:: ++ +[source,xml] +---- + + + + your-extraction-job-id + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:fetchExtraction + steps: + - setHeader: + name: CamelIBMWatsonxAiExtractionId + constant: "your-extraction-job-id" + - to: + uri: ibm-watsonx-ai:extract + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + operation: textExtractionFetch + cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud" + documentConnectionId: your-cos-connection-id + documentBucket: your-input-bucket + resultConnectionId: your-cos-connection-id + resultBucket: your-output-bucket + - log: + message: "Extraction status: ${header.CamelIBMWatsonxAiExtractionStatus}" +---- +==== === Upload and Extract Local Files (Synchronous) Upload a local file and get extracted text synchronously using `textExtractionUploadAndFetch`: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("file:/path/to/documents?noop=true") - .to("ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&operation=textExtractionUploadAndFetch" + - "&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud" + - "&documentConnectionId=your-cos-connection-id" + - "&documentBucket=your-input-bucket" + - "&resultConnectionId=your-cos-connection-id" + - "&resultBucket=your-output-bucket") - .log("Extracted text: ${body}") - .log("File processed: ${header.CamelFileName}"); --------------------------------------------------------------------------------- + .to("ibm-watsonx-ai:extract?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textExtractionUploadAndFetch&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket&resultConnectionId=your-cos-connection-id&resultBucket=your-output-bucket") + .log("Extracted text: ${body}") + .log("File processed: ${header.CamelFileName}"); +---- -This operation: +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:/path/to/documents + parameters: + noop: true + steps: + - to: + uri: ibm-watsonx-ai:extract + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + operation: textExtractionUploadAndFetch + cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud" + documentConnectionId: your-cos-connection-id + documentBucket: your-input-bucket + resultConnectionId: your-cos-connection-id + resultBucket: your-output-bucket + - log: + message: "Extracted text: ${body}" + - log: + message: "File processed: ${header.CamelFileName}" +---- +==== + +This operation: 1. Automatically handles `File`, `GenericFile` (from `file://`, `ftp://`, `sftp://`), `InputStream`, or `byte[]` body types 2. Uploads the file to COS @@ -749,6 +1164,7 @@ This operation: The text extraction operations integrate seamlessly with Camel file components: +._Java-only: illustrative snippets showing various file source integrations_ [source,java] -------------------------------------------------------------------------------- // From local file system @@ -782,40 +1198,111 @@ IMPORTANT: The COS connection in your watsonx.ai project must be configured with Classify documents already stored in Cloud Object Storage: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:classify") - .setBody(constant("documents/contract.pdf")) - .to("ibm-watsonx-ai:classify?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&operation=textClassification" + - "&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud" + - "&documentConnectionId=your-cos-connection-id" + - "&documentBucket=your-input-bucket") - .process(exchange -> { - String classificationId = exchange.getMessage().getHeader("CamelIBMWatsonxAiClassificationId", String.class); - System.out.println("Classification job started: " + classificationId); - }); --------------------------------------------------------------------------------- + .setBody(constant("documents/contract.pdf")) + .to("ibm-watsonx-ai:classify?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textClassification&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket") + .log("Classification job started: ${header.CamelIBMWatsonxAiClassificationId}"); +---- + +XML:: ++ +[source,xml] +---- + + + + documents/contract.pdf + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:classify + steps: + - setBody: + constant: "documents/contract.pdf" + - to: + uri: ibm-watsonx-ai:classify + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + operation: textClassification + cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud" + documentConnectionId: your-cos-connection-id + documentBucket: your-input-bucket + - log: + message: "Classification job started: ${header.CamelIBMWatsonxAiClassificationId}" +---- +==== ==== Upload and Classify Local Files (Synchronous) Upload a local file and get classification results synchronously using `textClassificationUploadAndFetch`: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("file:/path/to/documents?noop=true") - .to("ibm-watsonx-ai:classify?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&operation=textClassificationUploadAndFetch" + - "&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud" + - "&documentConnectionId=your-cos-connection-id" + - "&documentBucket=your-input-bucket") - .log("Document type: ${header.CamelIBMWatsonxAiClassificationResult}") - .log("Document classified: ${header.CamelIBMWatsonxAiDocumentClassified}"); --------------------------------------------------------------------------------- + .to("ibm-watsonx-ai:classify?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&operation=textClassificationUploadAndFetch&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket") + .log("Document type: ${header.CamelIBMWatsonxAiClassificationResult}") + .log("Document classified: ${header.CamelIBMWatsonxAiDocumentClassified}"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:/path/to/documents + parameters: + noop: true + steps: + - to: + uri: ibm-watsonx-ai:classify + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + operation: textClassificationUploadAndFetch + cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud" + documentConnectionId: your-cos-connection-id + documentBucket: your-input-bucket + - log: + message: "Document type: ${header.CamelIBMWatsonxAiClassificationResult}" + - log: + message: "Document classified: ${header.CamelIBMWatsonxAiDocumentClassified}" +---- +==== This operation: @@ -829,6 +1316,7 @@ This operation: For more control, use the async flow with `textClassificationUpload` and `textClassificationFetch` in a single route with polling loop: +._Java-only: complex async polling pattern with `loopDoWhile`, `delay`, `exchangeProperty`, and `choice`_ [source,java] -------------------------------------------------------------------------------- // Start classification and poll until complete @@ -867,6 +1355,7 @@ from("direct:startClassification") The classification operations integrate seamlessly with Camel file components: +._Java-only: illustrative snippets showing various file source integrations_ [source,java] -------------------------------------------------------------------------------- // From local file system @@ -894,19 +1383,56 @@ from("azure-storage-blob://mycontainer?prefix=documents/") Clean up a classification job: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:deleteClassification") - .setBody(constant("classification-job-id")) - .to("ibm-watsonx-ai:classify?operation=textClassificationDeleteRequest" + - "&apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud" + - "&documentConnectionId=your-cos-connection-id" + - "&documentBucket=your-input-bucket") - .log("Delete success: ${header.CamelIBMWatsonxAiDeleteSuccess}"); --------------------------------------------------------------------------------- + .setBody(constant("classification-job-id")) + .to("ibm-watsonx-ai:classify?operation=textClassificationDeleteRequest&apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&cosUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud&documentConnectionId=your-cos-connection-id&documentBucket=your-input-bucket") + .log("Delete success: ${header.CamelIBMWatsonxAiDeleteSuccess}"); +---- + +XML:: ++ +[source,xml] +---- + + + + classification-job-id + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:deleteClassification + steps: + - setBody: + constant: "classification-job-id" + - to: + uri: ibm-watsonx-ai:classify + parameters: + operation: textClassificationDeleteRequest + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + cosUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud" + documentConnectionId: your-cos-connection-id + documentBucket: your-input-bucket + - log: + message: "Delete success: ${header.CamelIBMWatsonxAiDeleteSuccess}" +---- +==== ==== Supported File Types @@ -933,41 +1459,126 @@ For the latest list of supported models, see the https://cloud.ibm.com/apidocs/w Provide input via header instead of body: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:headerInput") - .setHeader("CamelIBMWatsonxAiInput", constant("What is machine learning?")) - .to("ibm-watsonx-ai:gen?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&modelId=ibm/granite-13b-instruct-v2" + - "&operation=textGeneration") - .log("Generated text: ${body}"); --------------------------------------------------------------------------------- + .setHeader("CamelIBMWatsonxAiInput", constant("What is machine learning?")) + .to("ibm-watsonx-ai:gen?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-13b-instruct-v2&operation=textGeneration") + .log("Generated text: ${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + What is machine learning? + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:headerInput + steps: + - setHeader: + name: CamelIBMWatsonxAiInput + constant: "What is machine learning?" + - to: + uri: ibm-watsonx-ai:gen + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + modelId: ibm/granite-13b-instruct-v2 + operation: textGeneration + - log: + message: "Generated text: ${body}" +---- +==== === Accessing Response Metadata Access token counts and stop reason from response headers: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:metadata") - .setBody(constant("Summarize the benefits of cloud computing")) - .to("ibm-watsonx-ai:gen?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&projectId=yourProjectId" + - "&modelId=ibm/granite-13b-instruct-v2" + - "&operation=textGeneration") - .log("Generated: ${body}") - .log("Input tokens: ${header.CamelIBMWatsonxAiInputTokenCount}") - .log("Output tokens: ${header.CamelIBMWatsonxAiOutputTokenCount}") - .log("Stop reason: ${header.CamelIBMWatsonxAiStopReason}"); --------------------------------------------------------------------------------- + .setBody(constant("Summarize the benefits of cloud computing")) + .to("ibm-watsonx-ai:gen?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&projectId=yourProjectId&modelId=ibm/granite-13b-instruct-v2&operation=textGeneration") + .log("Generated: ${body}") + .log("Input tokens: ${header.CamelIBMWatsonxAiInputTokenCount}") + .log("Output tokens: ${header.CamelIBMWatsonxAiOutputTokenCount}") + .log("Stop reason: ${header.CamelIBMWatsonxAiStopReason}"); +---- + +XML:: ++ +[source,xml] +---- + + + + Summarize the benefits of cloud computing + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:metadata + steps: + - setBody: + constant: "Summarize the benefits of cloud computing" + - to: + uri: ibm-watsonx-ai:gen + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + projectId: yourProjectId + modelId: ibm/granite-13b-instruct-v2 + operation: textGeneration + - log: + message: "Generated: ${body}" + - log: + message: "Input tokens: ${header.CamelIBMWatsonxAiInputTokenCount}" + - log: + message: "Output tokens: ${header.CamelIBMWatsonxAiOutputTokenCount}" + - log: + message: "Stop reason: ${header.CamelIBMWatsonxAiStopReason}" +---- +==== === Time Series Forecasting Generate time series forecasts: +._Java-only: uses watsonx.ai SDK types (`InputSchema`, `ForecastData`) for time series data construction_ [source,java] -------------------------------------------------------------------------------- import com.ibm.watsonx.ai.timeseries.InputSchema; @@ -1002,52 +1613,149 @@ from("direct:forecast") Explore the model catalog: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listModels") - .to("ibm-watsonx-ai:models?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&operation=listModels") - .process(exchange -> { - List models = exchange.getMessage().getBody(List.class); - models.forEach(model -> System.out.println("Model: " + model)); - }); --------------------------------------------------------------------------------- + .to("ibm-watsonx-ai:models?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&operation=listModels") + .log("Available models: ${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:listModels + steps: + - to: + uri: ibm-watsonx-ai:models + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + operation: listModels + - log: + message: "Available models: ${body}" +---- +==== === List Supported Tasks Discover available tasks: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listTasks") - .to("ibm-watsonx-ai:tasks?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&operation=listTasks") - .log("Available tasks: ${body}"); --------------------------------------------------------------------------------- + .to("ibm-watsonx-ai:tasks?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&operation=listTasks") + .log("Available tasks: ${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:listTasks + steps: + - to: + uri: ibm-watsonx-ai:tasks + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + operation: listTasks + - log: + message: "Available tasks: ${body}" +---- +==== === Deployment Chat Chat using a deployed model: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -import com.ibm.watsonx.ai.chat.model.UserMessage; - +---- from("direct:deploymentChat") - .setBody(constant("What is the capital of France?")) - .to("ibm-watsonx-ai:deploy?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&deploymentId=your-deployment-id" + - "&operation=deploymentChat") - .log("Response: ${body}"); --------------------------------------------------------------------------------- + .setBody(constant("What is the capital of France?")) + .to("ibm-watsonx-ai:deploy?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&deploymentId=your-deployment-id&operation=deploymentChat") + .log("Response: ${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + What is the capital of France? + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:deploymentChat + steps: + - setBody: + constant: "What is the capital of France?" + - to: + uri: ibm-watsonx-ai:deploy + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + deploymentId: your-deployment-id + operation: deploymentChat + - log: + message: "Response: ${body}" +---- +==== === Run Utility Tool Use watsonx.ai utility tools (experimental): +._Java-only: uses `process` lambda with `Map.of()` for tool input and config_ [source,java] -------------------------------------------------------------------------------- from("direct:runTool") @@ -1069,17 +1777,46 @@ from("direct:runTool") Discover available utility tools: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listTools") - .to("ibm-watsonx-ai:tools?apiKey=RAW(yourApiKey)" + - "&baseUrl=https://us-south.ml.cloud.ibm.com" + - "&operation=listTools") - .process(exchange -> { - List tools = exchange.getMessage().getBody(List.class); - System.out.println("Available tools: " + tools.size()); - }); --------------------------------------------------------------------------------- + .to("ibm-watsonx-ai:tools?apiKey=RAW(yourApiKey)&baseUrl=https://us-south.ml.cloud.ibm.com&operation=listTools") + .log("Available tools: ${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:listTools + steps: + - to: + uri: ibm-watsonx-ai:tools + parameters: + apiKey: "RAW(yourApiKey)" + baseUrl: "https://us-south.ml.cloud.ibm.com" + operation: listTools + - log: + message: "Available tools: ${body}" +---- +==== == Spring Boot and Camel Main Configuration @@ -1100,13 +1837,50 @@ camel.component.ibm-watsonx-ai.configuration.max-new-tokens=200 Then use the component in routes without repeating configuration: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:generate") - .setBody(constant("Explain microservices architecture")) - .to("ibm-watsonx-ai:gen?operation=textGeneration") - .log("Generated: ${body}"); --------------------------------------------------------------------------------- + .setBody(constant("Explain microservices architecture")) + .to("ibm-watsonx-ai:gen?operation=textGeneration") + .log("Generated: ${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + Explain microservices architecture + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:generate + steps: + - setBody: + constant: "Explain microservices architecture" + - to: + uri: ibm-watsonx-ai:gen + parameters: + operation: textGeneration + - log: + message: "Generated: ${body}" +---- +==== == watsonx.ai Authentication From 5082691677fa5d64f7b7d1a095d68f019d011c55 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:27:10 +0200 Subject: [PATCH 32/87] CAMEL-23789: Make LangChain4j Agent component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../docs/langchain4j-agent-component.adoc | 913 +++++++++++++++++- 1 file changed, 889 insertions(+), 24 deletions(-) diff --git a/components/camel-ai/camel-langchain4j-agent/src/main/docs/langchain4j-agent-component.adoc b/components/camel-ai/camel-langchain4j-agent/src/main/docs/langchain4j-agent-component.adoc index f98183b9daf4b..a8b368632ebb1 100644 --- a/components/camel-ai/camel-langchain4j-agent/src/main/docs/langchain4j-agent-component.adoc +++ b/components/camel-ai/camel-langchain4j-agent/src/main/docs/langchain4j-agent-component.adoc @@ -82,19 +82,48 @@ camel.oauth.keycloak.client-secret=camel-client-secret camel.oauth.keycloak.token-endpoint=https://keycloak.example.com/realms/camel/protocol/openid-connect/token ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:agent") - .to("langchain4j-agent:myAgent" - + "?mcpServer.tools.transportType=http" - + "&mcpServer.tools.url=https://mcp.internal/mcp" - + "&mcpServer.tools.oauthProfile=keycloak"); + .to("langchain4j-agent:myAgent?mcpServer.tools.transportType=http&mcpServer.tools.url=https://mcp.internal/mcp&mcpServer.tools.oauthProfile=keycloak"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:agent + steps: + - to: + uri: langchain4j-agent:myAgent + parameters: + mcpServer.tools.transportType: http + mcpServer.tools.url: "https://mcp.internal/mcp" + mcpServer.tools.oauthProfile: keycloak +---- +==== + === LLM Provider Authentication The langchain4j-agent component accepts a pre-built `Agent` or `ChatModel` bean — it does not create the LLM client itself. For LLM providers that require OAuth authentication (e.g., Azure OpenAI), use `OAuthHelper` when building the bean programmatically: +._Java-only: programmatic `ChatModel` bean registration with `OAuthHelper`_ [source,java] ---- import org.apache.camel.support.OAuthHelper; @@ -142,6 +171,7 @@ Agents are configured using the `AgentConfiguration` class which provides a flue ==== Creating an Agent without Memory +._Java-only: LangChain4j `AgentConfiguration` and programmatic bean registration_ [source, java] ---- // Create and configure the chat model @@ -167,14 +197,44 @@ context.getRegistry().bind("simpleAgent", simpleAgent); Use the agent in your Camel route: +[tabs] +==== +Java:: ++ [source, java] ---- from("direct:chat") .to("langchain4j-agent:test?agent=#simpleAgent") ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:test + parameters: + agent: "#simpleAgent" +---- +==== + ==== Creating an Agent with Memory +._Java-only: LangChain4j `ChatMemoryProvider` and `AgentConfiguration` setup_ [source, java] ---- // Create chat model (same as above) @@ -221,19 +281,53 @@ Instead of manually instantiating `AgentWithoutMemory` or `AgentWithMemory`, you ==== Stateless agent +._Java-only: `AgentConfiguration` bean registration_ [source,java] ---- AgentConfiguration config = new AgentConfiguration() .withChatModel(chatModel); context.getRegistry().bind("myConfig", config); +---- +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:chat") .to("langchain4j-agent:assistant?agentConfiguration=#myConfig"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:assistant + parameters: + agentConfiguration: "#myConfig" +---- +==== + ==== Stateful agent (with memory) +._Java-only: `ChatMemoryProvider` and `AgentConfiguration` bean registration_ [source,java] ---- ChatMemoryProvider memoryProvider = memoryId -> MessageWindowChatMemory.builder() @@ -247,26 +341,89 @@ AgentConfiguration config = new AgentConfiguration() .withChatMemoryProvider(memoryProvider); context.getRegistry().bind("myConfig", config); +---- +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:chat") .to("langchain4j-agent:assistant?agentConfiguration=#myConfig"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:assistant + parameters: + agentConfiguration: "#myConfig" +---- +==== + If an `agentFactory` is also configured on the endpoint, the factory takes precedence over `agentConfiguration`. === Basic Chat with only a userMessage For simple chat interactions, you can use an agent without memory. +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:chat") .to("langchain4j-agent:simple?agent=#simpleAgent") ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:simple + parameters: + agent: "#simpleAgent" +---- +==== + The body can either contain the prompt as a String, or you can create an object of type *org.apache.camel.component.langchain4j.agent.api.AiAgentBody* containing the userMessage. .Usage example with a body as String: + +._Java-only: ProducerTemplate test API_ [source, java] ---- var prompt = "What is Apache Camel"; @@ -275,6 +432,8 @@ String response = template.requestBody("direct:chat", prompt, String.class); ---- .Usage example with a body as AiAgentBody: + +._Java-only: ProducerTemplate test API with `AiAgentBody`_ [source, java] ---- var prompt = "What is Apache Camel"; @@ -287,15 +446,46 @@ String response = template.requestBody("direct:chat", body, String.class); For chat interactions with system prompts, you can use an agent without memory. +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:chat") .to("langchain4j-agent:simple?agent=#simpleAgent") ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:simple + parameters: + agent: "#simpleAgent" +---- +==== + The body can either contain the user prompt as a String and specifying the *CamelLangChain4jAgentSystemMessage* header for the system prompt, or you can create an object of type *org.apache.camel.component.langchain4j.agent.api.AiAgentBody* containing both *userMessage* and *systemMessage*. .Usage example with a body as String: + +._Java-only: ProducerTemplate test API_ [source, java] ---- var userPrompt = "Write a short story about a lost cat."; @@ -306,6 +496,8 @@ String response = template.requestBodyAndHeader("direct:chat", ---- .Usage example with a body as AiAgentBody: + +._Java-only: ProducerTemplate test API with `AiAgentBody`_ [source, java] ---- var userPrompt = "Write a short story about a lost cat."; @@ -322,6 +514,10 @@ String response = template.requestBody("direct:chat", body, String.class); Integrate with Camel routes as tools. The LangChain4j Agent component integrates with Camel Routes defined using the Camel LangChain4j Tools component via the `tags` parameter. +[tabs] +==== +Java:: ++ [source,java] ---- // Define tool routes @@ -336,7 +532,75 @@ from("direct:chat") .to("langchain4j-agent:tools?agent=#simpleAgent&tags=users,weather"); ---- -.Usage example : +XML:: ++ +[source,xml] +---- + + + + + {"name": "John Doe", "id": "123"} + + + + + + + {"weather": "sunny", "temperature": "22°C"} + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +# Define tool routes +- route: + from: + uri: langchain4j-tools:userDb + parameters: + tags: users + description: Query user database + parameter.userId: string + steps: + - setBody: + constant: '{"name": "John Doe", "id": "123"}' + +- route: + from: + uri: langchain4j-tools:weather + parameters: + tags: weather + description: Get weather information + parameter.city: string + steps: + - setBody: + constant: '{"weather": "sunny", "temperature": "22°C"}' + +# Agent with tools +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:tools + parameters: + agent: "#simpleAgent" + tags: users,weather +---- +==== + +.Usage example: + +._Java-only: ProducerTemplate test API_ [source, java] ---- var userPrompt = "Can you tell me the name of user 123 and the weather in New York?"; @@ -359,6 +623,7 @@ You can also add custom LangChain4j tools using the `@Tool` annotation. These to Create a class with methods annotated with `@Tool`: +._Java-only: LangChain4j `@Tool` annotated class_ [source,java] ---- import dev.langchain4j.agent.tool.P; @@ -387,6 +652,7 @@ public class CalculatorTool { Pass your custom tool instances to the agent configuration: +._Java-only: LangChain4j `@Tool` instances and `AgentConfiguration` setup_ [source,java] ---- // Create tool instances @@ -409,6 +675,10 @@ context.getRegistry().bind("customToolsAgent", agent); Use the agent with custom tools in your routes: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:chat") @@ -416,11 +686,40 @@ from("direct:chat") .to("mock:agent-response"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:assistant + parameters: + agent: "#customToolsAgent" + - to: + uri: mock:agent-response +---- +==== + ==== Usage Example +._Java-only: ProducerTemplate test API_ [source,java] ---- -String response = template.requestBody("direct:chat", +String response = template.requestBody("direct:chat", "Calculate 10 * 5 and tell me the weather in Paris", String.class); ---- @@ -433,6 +732,7 @@ Custom LangChain4j tools are executed directly by the LangChain4j framework. No You can combine both Camel route tools (via `tags`) and custom LangChain4j tools (via `customTools`) in the same agent: +._Java-only: LangChain4j `@Tool` instances, `AgentConfiguration`, and bean registration_ [source,java] ---- // Define Camel route tools @@ -457,6 +757,10 @@ context.getRegistry().bind("mixedToolsAgent", agent); ==== Route Configuration with Mixed Tools +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:chat") @@ -464,11 +768,41 @@ from("direct:chat") .to("mock:agent-response"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:assistant + parameters: + agent: "#mixedToolsAgent" + tags: weather + - to: + uri: mock:agent-response +---- +==== + ==== Usage Example +._Java-only: ProducerTemplate test API_ [source,java] ---- -String response = template.requestBody("direct:chat", +String response = template.requestBody("direct:chat", "Calculate 10 * 5 and tell me the weather in London", String.class); ---- @@ -485,6 +819,7 @@ The LangChain4j Agent component supports integration with MCP (Model Context Pro To use MCP tools with your agent, you need to configure MCP clients in your `AgentConfiguration`: +._Java-only: LangChain4j MCP transport and client configuration_ [source,java] ---- // Create MCP transport for filesystem server @@ -511,6 +846,7 @@ Agent agent = new AgentWithoutMemory(config); You can apply filters to control which MCP tools are available to your agent: +._Java-only: `BiPredicate` filter with LangChain4j `ToolSpecification`_ [source,java] ---- // Create security filter to only allow read operations @@ -530,6 +866,7 @@ AgentConfiguration config = new AgentConfiguration() Here's a complete example showing how to use MCP tools with an agent: +._Java-only: LangChain4j MCP client setup and bean registration_ [source,java] ---- // Create MCP client for filesystem access @@ -555,6 +892,10 @@ context.getRegistry().bind("mcpAgent", agent); ==== Route Configuration with MCP Tools +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:chat") @@ -562,8 +903,37 @@ from("direct:chat") .to("mock:agent-response"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:assistant + parameters: + agent: "#mcpAgent" + - to: + uri: mock:agent-response +---- +==== + ==== Usage Example with MCP Tools +._Java-only: ProducerTemplate test API_ [source,java] ---- String response = template.requestBody("direct:chat", @@ -578,6 +948,7 @@ MCP servers can also be configured directly on the endpoint, without setting the Register pre-built `McpClient` beans and reference them via the `mcpClients` endpoint parameter: +._Java-only: LangChain4j `McpClient` bean registration_ [source,java] ---- // Register MCP clients as beans @@ -588,13 +959,49 @@ McpClient timeClient = new DefaultMcpClient.Builder() .build()) .build(); context.getRegistry().bind("timeMcpClient", timeClient); +---- -// Reference in endpoint URI +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:chat") .to("langchain4j-agent:assistant?agent=#myAgent&tags=users&mcpClients=#timeMcpClient") .to("mock:response"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:assistant + parameters: + agent: "#myAgent" + tags: users + mcpClients: "#timeMcpClient" + - to: + uri: mock:response +---- +==== + ===== Inline URI Configuration MCP servers can be defined inline on the endpoint URI using the `mcpServer..` pattern. The component creates and manages the MCP client lifecycle automatically. @@ -617,17 +1024,50 @@ Supported properties: Example with two MCP servers configured inline: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:chat") - .to("langchain4j-agent:assistant?agent=#myAgent&tags=users" - + "&mcpServer.everything.transportType=http" - + "&mcpServer.everything.url=http://localhost:3001/mcp" - + "&mcpServer.time.transportType=stdio" - + "&mcpServer.time.command=docker,run,-i,--rm,mcp/time") + .to("langchain4j-agent:assistant?agent=#myAgent&tags=users&mcpServer.everything.transportType=http&mcpServer.everything.url=http://localhost:3001/mcp&mcpServer.time.transportType=stdio&mcpServer.time.command=docker,run,-i,--rm,mcp/time") .to("mock:response"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:assistant + parameters: + agent: "#myAgent" + tags: users + mcpServer.everything.transportType: http + mcpServer.everything.url: "http://localhost:3001/mcp" + mcpServer.time.transportType: stdio + mcpServer.time.command: "docker,run,-i,--rm,mcp/time" + - to: + uri: mock:response +---- +==== + Both `mcpClients` (bean references) and `mcpServer` (inline) can be used together on the same endpoint. All tool sources -- Camel route tools, endpoint-level MCP tools, and agent-level MCP tools -- are automatically composed into a single tool provider. ==== Dynamic Tool Exclusion via Headers @@ -644,26 +1084,80 @@ Tools can be dynamically excluded on a per-message basis using Camel headers. Th Example -- exclude specific tools based on a condition: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:chat") .choice() .when(header("userRole").isEqualTo("readonly")) - // Exclude write-capable tools for read-only users .setHeader("CamelLangChain4jAgentExcludeTags", constant("admin-tools")) .setHeader("CamelLangChain4jAgentExcludeMcpServers", constant("filesystem")) .end() - .to("langchain4j-agent:assistant?agent=#myAgent&tags=users,admin-tools" - + "&mcpClients=#fsMcpClient,#timeMcpClient") + .to("langchain4j-agent:assistant?agent=#myAgent&tags=users,admin-tools&mcpClients=#fsMcpClient,#timeMcpClient") .to("mock:response"); ---- +XML:: ++ +[source,xml] +---- + + + + + ${header.userRole} == 'readonly' + + admin-tools + + + filesystem + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - choice: + when: + - simple: "${header.userRole} == 'readonly'" + steps: + - setHeader: + name: CamelLangChain4jAgentExcludeTags + constant: admin-tools + - setHeader: + name: CamelLangChain4jAgentExcludeMcpServers + constant: filesystem + - to: + uri: langchain4j-agent:assistant + parameters: + agent: "#myAgent" + tags: users,admin-tools + mcpClients: "#fsMcpClient,#timeMcpClient" + - to: + uri: mock:response +---- +==== + MCP servers are matched by their key, which is set via `DefaultMcpClient.Builder.key(name)` or automatically from the server name in inline `mcpServer.` configuration. MCP clients without a key are never excluded. === RAG Integration RAG (Retrieval-Augmented Generation) is supported by configuring a `RetrievalAugmentor` in the `AgentConfiguration`. Create an agent with RAG capabilities: +._Java-only: LangChain4j `RetrievalAugmentor` and `AgentConfiguration` setup_ [source,java] ---- // Create the retrieval augmentor (shown below) @@ -678,13 +1172,48 @@ AgentConfiguration configuration = new AgentConfiguration() Agent ragAgent = new AgentWithoutMemory(configuration); context.getRegistry().bind("ragAgent", ragAgent); +---- + +Use the RAG agent: -// Use the RAG agent +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:chat") .to("langchain4j-agent:rag?agent=#ragAgent") ---- -.Usage example with Retrieval Augmentor serving as naive RAG : +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:rag + parameters: + agent: "#ragAgent" +---- +==== + +.Usage example with Retrieval Augmentor serving as naive RAG: + +._Java-only: LangChain4j `EmbeddingStoreContentRetriever` and ProducerTemplate test API_ [source, java] ---- // creating the retrieval Augmentor @@ -721,13 +1250,45 @@ The memory works for multiple users/sessions. For each context window, the users - By setting the AiAgentBody.memoryId field. This supposes that that user is using a body as AiAgentBody. .Example of Route with Memory Agent + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:chat") .to("langchain4j-agent:memory?agent=#memoryAgent") ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-agent:memory + parameters: + agent: "#memoryAgent" +---- +==== + .Example of usage with AiAgentBody + +._Java-only: `ChatMemoryProvider`, `AiAgentBody`, and ProducerTemplate test API_ [source,java] ---- // Example of creating a Chat Memory Provider : Create a message window memory that keeps the last 10 messages @@ -754,6 +1315,7 @@ Guardrails validate and filter AI interactions to ensure security and quality. T Create classes defining InputGuardrails and OutputGuardrails as defined in the https://docs.langchain4j.dev/tutorials/guardrails[LangChain4j Guardrails documentation] page. +._Java-only: `AgentConfiguration` with guardrail classes and bean registration_ [source,java] ---- // Create agent configuration with custom guardrails @@ -764,12 +1326,45 @@ AgentConfiguration configuration = new AgentConfiguration() Agent safeAgent = new AgentWithoutMemory(configuration); context.getRegistry().bind("safeAgent", safeAgent); +---- + +Use the agent with guardrails: -// Use the agent with guardrails +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:agent-with-guardrails") .to("langchain4j-agent:safe?agent=#safeAgent") ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:agent-with-guardrails + steps: + - to: + uri: langchain4j-agent:safe + parameters: + agent: "#safeAgent" +---- +==== + [NOTE] ==== The current version of the component returns a String as response. If the outputGuardrails extends JsonExtractorOutputGuardrail class, make sure to return a Json in String format. @@ -836,6 +1431,7 @@ The `camel-langchain4j-agent-api` module provides production-ready guardrails in The `Guardrails` helper class provides convenient factory methods: +._Java-only: `Guardrails` factory methods and bean registration_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.Guardrails; @@ -848,11 +1444,43 @@ AgentConfiguration configuration = new AgentConfiguration() Agent secureAgent = new AgentWithoutMemory(configuration); context.getRegistry().bind("secureAgent", secureAgent); +---- +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:secure-chat") .to("langchain4j-agent:chat?agent=#secureAgent"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:secure-chat + steps: + - to: + uri: langchain4j-agent:chat + parameters: + agent: "#secureAgent" +---- +==== + The default guardrails include: * **Input**: `InputLengthGuardrail`, `PiiDetectorGuardrail`, `PromptInjectionGuardrail` @@ -862,6 +1490,7 @@ The default guardrails include: The `Guardrails.configure()` method provides a fluent API for building configurations: +._Java-only: `Guardrails` fluent builder API_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.Guardrails; @@ -883,6 +1512,7 @@ Agent agent = new AgentWithoutMemory(configuration); You can specify exactly which guardrails to use: +._Java-only: `AgentConfiguration` with specific guardrail classes_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.*; @@ -904,6 +1534,7 @@ AgentConfiguration configuration = new AgentConfiguration() The `Guardrails` class provides preset configurations for different security levels: +._Java-only: `Guardrails` preset factory methods_ [source,java] ---- // Minimal protection (just length validation) @@ -920,6 +1551,7 @@ configuration.withInputGuardrailClasses(Guardrails.strictInputGuardrails()); The `Guardrails` class provides static factory methods to create guardrail instances: +._Java-only: `Guardrails` static factory methods_ [source,java] ---- // Input guardrails @@ -940,6 +1572,7 @@ Each guardrail provides a builder for custom configuration: ===== PII Detection Configuration +._Java-only: `PiiDetectorGuardrail` builder API_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.PiiDetectorGuardrail; @@ -954,6 +1587,7 @@ PiiDetectorGuardrail guardrail = PiiDetectorGuardrail.builder() ===== Prompt Injection Detection Configuration +._Java-only: `PromptInjectionGuardrail` builder API_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.PromptInjectionGuardrail; @@ -972,6 +1606,7 @@ PromptInjectionGuardrail customGuardrail = PromptInjectionGuardrail.builder() ===== Sensitive Data Output Configuration +._Java-only: `SensitiveDataOutputGuardrail` builder API_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.SensitiveDataOutputGuardrail; @@ -987,6 +1622,7 @@ SensitiveDataOutputGuardrail guardrail = SensitiveDataOutputGuardrail.builder() ===== JSON Format Validation Configuration +._Java-only: `JsonFormatGuardrail` builder API_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.JsonFormatGuardrail; @@ -1001,6 +1637,7 @@ JsonFormatGuardrail guardrail = JsonFormatGuardrail.builder() ===== Keyword Filtering Configuration +._Java-only: `KeywordFilterGuardrail` and `KeywordOutputFilterGuardrail` builder APIs_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.KeywordFilterGuardrail; @@ -1024,6 +1661,7 @@ KeywordOutputFilterGuardrail outputFilter = KeywordOutputFilterGuardrail.builder ===== Language Validation Configuration +._Java-only: `LanguageGuardrail` builder API_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.LanguageGuardrail; @@ -1049,6 +1687,7 @@ LanguageGuardrail customLanguage = LanguageGuardrail.builder() ===== Code Injection Detection Configuration +._Java-only: `CodeInjectionGuardrail` builder API_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.CodeInjectionGuardrail; @@ -1073,6 +1712,7 @@ CodeInjectionGuardrail customGuard = CodeInjectionGuardrail.builder() ===== Regex Pattern Guardrail Configuration +._Java-only: `RegexPatternGuardrail` builder API_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.RegexPatternGuardrail; @@ -1096,6 +1736,7 @@ RegexPatternGuardrail customPatterns = RegexPatternGuardrail.builder() ===== Not Empty Guardrail Configuration +._Java-only: `NotEmptyGuardrail` configuration_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.NotEmptyGuardrail; @@ -1118,6 +1759,7 @@ NotEmptyGuardrail customNotEmpty = new NotEmptyGuardrail( ===== Word Count Guardrail Configuration +._Java-only: `WordCountGuardrail` builder API_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.guardrails.WordCountGuardrail; @@ -1140,6 +1782,7 @@ WordCountGuardrail custom = WordCountGuardrail.builder() ==== Complete Example with Memory and Guardrails +._Java-only: `RouteBuilder` class with `AgentConfiguration`, guardrails, memory, and `doTry`/`doCatch`_ [source,java] ---- import org.apache.camel.component.langchain4j.agent.api.*; @@ -1215,6 +1858,7 @@ langchain4j.open-ai.chat-model.temperature=0.7 Create the Agent bean using the auto-configured ChatLanguageModel: +._Java-only: Spring Boot `@Configuration` with auto-configured `ChatLanguageModel`_ [source,java] ---- import org.springframework.context.annotation.Bean; @@ -1256,6 +1900,7 @@ Refer to the https://docs.langchain4j.dev/tutorials/spring-boot-integration[Lang Alternatively, you can manually configure the ChatModel bean: +._Java-only: Spring Boot `@Configuration` with manual `ChatModel` bean_ [source,java] ---- import org.springframework.context.annotation.Bean; @@ -1371,21 +2016,67 @@ Create a JSON schema file, for example `src/main/resources/person-schema.json`: Then use it in a route: +._Java-only: `AgentConfiguration` bean registration_ [source,java] ---- AgentConfiguration agentConfiguration = new AgentConfiguration() .withChatModel(chatModel); context.getRegistry().bind("myAgentConfig", agentConfiguration); +---- +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:extract-person-info") .setBody(constant("Extract information about John Smith, a 35-year-old software engineer")) - .to("langchain4j-agent:structured?agentConfiguration=#myAgentConfig" - + "&jsonSchema=classpath:person-schema.json") + .to("langchain4j-agent:structured?agentConfiguration=#myAgentConfig&jsonSchema=classpath:person-schema.json") .unmarshal().json() .log("Extracted person: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + Extract information about John Smith, a 35-year-old software engineer + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:extract-person-info + steps: + - setBody: + constant: "Extract information about John Smith, a 35-year-old software engineer" + - to: + uri: langchain4j-agent:structured + parameters: + agentConfiguration: "#myAgentConfig" + jsonSchema: "classpath:person-schema.json" + - unmarshal: + json: {} + - log: + message: "Extracted person: ${body}" +---- +==== + The `jsonSchema` option accepts: * Classpath resources: `jsonSchema=classpath:schemas/person.json` @@ -1410,6 +2101,7 @@ This approach is mutually exclusive with `jsonSchema` — you can use one or the First, define your response class. Annotate required fields with `@JsonProperty(required = true)` so they appear in the `required` array of the generated JSON schema, ensuring the model always populates them. Use `@Description` to add semantic hints: +._Java-only: Java POJO with `@JsonProperty` and `@Description` annotations_ [source,java] ---- import com.fasterxml.jackson.annotation.JsonProperty; @@ -1434,6 +2126,7 @@ public class PersonInfo { Then configure the endpoint to use this class. Use the fully qualified class name (FQCN) directly — no registry binding needed. Add `.unmarshal().json()` to convert the raw JSON response to a POJO: +._Java-only: `AgentConfiguration` bean setup, `unmarshal` with POJO class, and `process` lambda_ [source,java] ---- AgentConfiguration agentConfiguration = new AgentConfiguration() @@ -1443,8 +2136,7 @@ context.getRegistry().bind("myAgentConfig", agentConfiguration); from("direct:extract-person-info") .setBody(constant("Extract information about John Smith, a 35-year-old software engineer")) - .to("langchain4j-agent:structured?agentConfiguration=#myAgentConfig" - + "&outputClass=com.example.PersonInfo") + .to("langchain4j-agent:structured?agentConfiguration=#myAgentConfig&outputClass=com.example.PersonInfo") .unmarshal().json(PersonInfo.class) .process(exchange -> { PersonInfo person = exchange.getIn().getBody(PersonInfo.class); @@ -1480,6 +2172,7 @@ The LangChain4j Agent component supports multimodal content, allowing you to sen You can explicitly create an `AiAgentBody` with multimodal content: +._Java-only: `AiAgentBody` with `ImageContent`, `Files.readAllBytes()`, and ProducerTemplate test API_ [source,java] ---- // Load an image and create ImageContent @@ -1524,6 +2217,10 @@ The agent component automatically converts files from various Camel components t ===== Example: Processing Images from File Component +[tabs] +==== +Java:: ++ [source,java] ---- from("file:inbox/images?noop=true&include=.*\\.png") @@ -1532,8 +2229,49 @@ from("file:inbox/images?noop=true&include=.*\\.png") .to("log:response"); ---- +XML:: ++ +[source,xml] +---- + + + + Describe this image + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:inbox/images + parameters: + noop: true + include: ".*\\.png" + steps: + - setHeader: + name: CamelLangChain4jAgentUserMessage + constant: Describe this image + - to: + uri: langchain4j-agent:vision + parameters: + agent: "#visionAgent" + - to: + uri: log:response +---- +==== + ===== Example: Processing Files from AWS S3 +[tabs] +==== +Java:: ++ [source,java] ---- from("aws2-s3://my-bucket?prefix=images/&includeBody=true") @@ -1542,6 +2280,43 @@ from("aws2-s3://my-bucket?prefix=images/&includeBody=true") .to("log:response"); ---- +XML:: ++ +[source,xml] +---- + + + + What do you see in this image? + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: aws2-s3://my-bucket + parameters: + prefix: images/ + includeBody: true + steps: + - setHeader: + name: CamelLangChain4jAgentUserMessage + constant: "What do you see in this image?" + - to: + uri: langchain4j-agent:vision + parameters: + agent: "#visionAgent" + - to: + uri: log:response +---- +==== + [NOTE] ==== When using `byte[]` or `InputStream` inputs, a MIME type header is required since the type cannot be auto-detected from the content. The component checks for MIME type in this priority order: @@ -1554,6 +2329,10 @@ When using `byte[]` or `InputStream` inputs, a MIME type header is required sinc ===== Example: Overriding MIME Type +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:process-file") @@ -1562,10 +2341,48 @@ from("direct:process-file") .to("langchain4j-agent:analyzer?agent=#analyzerAgent"); ---- +XML:: ++ +[source,xml] +---- + + + + Analyze this document + + + application/pdf + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:process-file + steps: + - setHeader: + name: CamelLangChain4jAgentUserMessage + constant: Analyze this document + - setHeader: + name: CamelLangChain4jAgentMediaType + constant: application/pdf + - to: + uri: langchain4j-agent:analyzer + parameters: + agent: "#analyzerAgent" +---- +==== + ==== Complete Multimodal Route Example Here's a complete example showing how to process images from a file system and send them to an AI agent for analysis: +._Java-only: `ChatModel` and `AgentConfiguration` bean registration_ [source,java] ---- // Create a vision-capable chat model @@ -1580,8 +2397,16 @@ AgentConfiguration configuration = new AgentConfiguration() Agent visionAgent = new AgentWithoutMemory(configuration); context.getRegistry().bind("visionAgent", visionAgent); +---- -// Route to process images +Route to process images: + +[tabs] +==== +Java:: ++ +[source,java] +---- from("file:inbox/images?noop=true&include=.*\\.(png|jpg|jpeg)") .setHeader("CamelLangChain4jAgentUserMessage", constant("Describe what you see in this image. Be detailed but concise.")) @@ -1589,3 +2414,43 @@ from("file:inbox/images?noop=true&include=.*\\.(png|jpg|jpeg)") .log("AI Response: ${body}") .to("file:outbox/descriptions"); ---- + +XML:: ++ +[source,xml] +---- + + + + Describe what you see in this image. Be detailed but concise. + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:inbox/images + parameters: + noop: true + include: ".*\\.(png|jpg|jpeg)" + steps: + - setHeader: + name: CamelLangChain4jAgentUserMessage + constant: "Describe what you see in this image. Be detailed but concise." + - to: + uri: langchain4j-agent:vision + parameters: + agent: "#visionAgent" + - log: + message: "AI Response: ${body}" + - to: + uri: file:outbox/descriptions +---- +==== From b8c850690327b7ad74f3ef989384fc23c90af06e Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:29:49 +0200 Subject: [PATCH 33/87] CAMEL-23789: Make MINA SFTP component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/mina-sftp-component.adoc | 644 +++++++++++++++++- 1 file changed, 631 insertions(+), 13 deletions(-) diff --git a/components/camel-mina-sftp/src/main/docs/mina-sftp-component.adoc b/components/camel-mina-sftp/src/main/docs/mina-sftp-component.adoc index 3866579b38afe..33e4590c6dec2 100644 --- a/components/camel-mina-sftp/src/main/docs/mina-sftp-component.adoc +++ b/components/camel-mina-sftp/src/main/docs/mina-sftp-component.adoc @@ -93,6 +93,10 @@ IMPORTANT: The OS username fallback only occurs when the SSH config file exists. For production deployments, always specify the username explicitly in the URI to ensure predictable behavior across different environments: +[tabs] +==== +Java:: ++ [source,java] ---- // Recommended: explicit username @@ -104,6 +108,49 @@ from("mina-sftp://host/path?password=secret") .to("file:local"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +# Recommended: explicit username +- route: + from: + uri: mina-sftp://deployuser@host/path + parameters: + password: secret + steps: + - to: + uri: file:local + +# Not recommended: relies on SSH config or OS username +- route: + from: + uri: mina-sftp://host/path + parameters: + password: secret + steps: + - to: + uri: file:local +---- +==== + === Compatibility with camel-sftp This username resolution behavior is identical to the JSch-based camel-sftp component, ensuring seamless migration. Both components: @@ -118,40 +165,158 @@ The MINA SFTP component supports multiple authentication methods: === Password Authentication +[tabs] +==== +Java:: ++ [source,java] ---- from("mina-sftp://admin@host/path?password=secret") .to("file:local"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: mina-sftp://admin@host/path + parameters: + password: secret + steps: + - to: + uri: file:local +---- +==== + === Public Key Authentication ==== Using Private Key File +[tabs] +==== +Java:: ++ [source,java] ---- from("mina-sftp://user@host/path?privateKeyFile=/home/user/.ssh/id_rsa") .to("file:local"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: mina-sftp://user@host/path + parameters: + privateKeyFile: /home/user/.ssh/id_rsa + steps: + - to: + uri: file:local +---- +==== + ==== Using Private Key from Classpath +[tabs] +==== +Java:: ++ [source,java] ---- from("mina-sftp://user@host/path?privateKeyUri=classpath:keys/id_rsa") .to("file:local"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: mina-sftp://user@host/path + parameters: + privateKeyUri: "classpath:keys/id_rsa" + steps: + - to: + uri: file:local +---- +==== + ==== Using Encrypted Private Key +[tabs] +==== +Java:: ++ [source,java] ---- from("mina-sftp://user@host/path?privateKeyFile=/path/to/encrypted_key&privateKeyPassphrase=mypassphrase") .to("file:local"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: mina-sftp://user@host/path + parameters: + privateKeyFile: /path/to/encrypted_key + privateKeyPassphrase: mypassphrase + steps: + - to: + uri: file:local +---- +==== + ==== Using Direct KeyPair Object +._Java-only: programmatic `KeyPairGenerator` and endpoint configuration_ [source,java] ---- KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); @@ -317,26 +482,83 @@ The first non-empty option wins. This matches the priority order used for privat ==== Example: Certificate from File +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .to("mina-sftp://user@host/path" - + "?privateKeyFile=/path/to/id_rsa" - + "&certFile=/path/to/id_rsa-cert.pub"); + .to("mina-sftp://user@host/path?privateKeyFile=/path/to/id_rsa&certFile=/path/to/id_rsa-cert.pub"); +---- + +XML:: ++ +[source,xml] +---- + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: mina-sftp://user@host/path + parameters: + privateKeyFile: /path/to/id_rsa + certFile: /path/to/id_rsa-cert.pub +---- +==== + ==== Example: Certificate from Classpath +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .to("mina-sftp://user@host/path" - + "?privateKeyUri=classpath:keys/id_rsa" - + "&certUri=classpath:keys/id_rsa-cert.pub"); + .to("mina-sftp://user@host/path?privateKeyUri=classpath:keys/id_rsa&certUri=classpath:keys/id_rsa-cert.pub"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: mina-sftp://user@host/path + parameters: + privateKeyUri: "classpath:keys/id_rsa" + certUri: "classpath:keys/id_rsa-cert.pub" +---- +==== + ==== Example: Certificate from Byte Array +._Java-only: programmatic endpoint configuration with byte arrays from secret manager_ [source,java] ---- // Load certificate from external secret manager @@ -364,54 +586,233 @@ Invalid certificates result in clear error messages indicating the issue. === Upload Files +[tabs] +==== +Java:: ++ [source,java] ---- from("file:inbox") .to("mina-sftp://user@sftp.example.com/upload?password=secret"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:inbox + steps: + - to: + uri: mina-sftp://user@sftp.example.com/upload + parameters: + password: secret +---- +==== + === Download Files +[tabs] +==== +Java:: ++ [source,java] ---- from("mina-sftp://user@sftp.example.com/download?password=secret&delete=true") .to("file:outbox"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: mina-sftp://user@sftp.example.com/download + parameters: + password: secret + delete: true + steps: + - to: + uri: file:outbox +---- +==== + === Poll and Move +[tabs] +==== +Java:: ++ [source,java] ---- from("mina-sftp://user@host/inbox?password=secret&move=.done") .to("file:local"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: mina-sftp://user@host/inbox + parameters: + password: secret + move: .done + steps: + - to: + uri: file:local +---- +==== + === Filter by Extension +[tabs] +==== +Java:: ++ [source,java] ---- from("mina-sftp://user@host/data?password=secret&antInclude=*.csv") .to("direct:process-csv"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: mina-sftp://user@host/data + parameters: + password: secret + antInclude: "*.csv" + steps: + - to: + uri: direct:process-csv +---- +==== + == Migration from JSch SFTP Users migrating from the JSch-based `sftp` component can switch by changing only the URI scheme: .Before (JSch) + +[tabs] +==== +Java:: ++ [source,java] ---- from("sftp://user@host/path?password=secret") .to("file:local"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: sftp://user@host/path + parameters: + password: secret + steps: + - to: + uri: file:local +---- +==== + .After (MINA SSHD) + +[tabs] +==== +Java:: ++ [source,java] ---- from("mina-sftp://user@host/path?password=secret") .to("file:local"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: mina-sftp://user@host/path + parameters: + password: secret + steps: + - to: + uri: file:local +---- +==== + All standard configuration options remain the same for supported features. === Features Not Supported @@ -890,16 +1291,44 @@ For security-hardened environments, configure only modern, recommended algorithm === Recommended Configuration +[tabs] +==== +Java:: ++ [source,java] ---- -// Security-hardened SFTP connection -from("mina-sftp://user@host/path?password=secret" - + "&keyExchangeProtocols=curve25519-sha256,ecdh-sha2-nistp256,diffie-hellman-group16-sha512" - + "&serverHostKeys=ssh-ed25519,rsa-sha2-512,ecdsa-sha2-nistp256" - + "&ciphers=aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr") +from("mina-sftp://user@host/path?password=secret&keyExchangeProtocols=curve25519-sha256,ecdh-sha2-nistp256,diffie-hellman-group16-sha512&serverHostKeys=ssh-ed25519,rsa-sha2-512,ecdsa-sha2-nistp256&ciphers=aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr") .to("file:local"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: mina-sftp://user@host/path + parameters: + password: secret + keyExchangeProtocols: "curve25519-sha256,ecdh-sha2-nistp256,diffie-hellman-group16-sha512" + serverHostKeys: "ssh-ed25519,rsa-sha2-512,ecdsa-sha2-nistp256" + ciphers: "aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr" + steps: + - to: + uri: file:local +---- +==== + === Algorithms to Avoid The following algorithms are deprecated and should be avoided for new deployments: @@ -1147,6 +1576,7 @@ For advanced use cases, you can provide a custom `ServerKeyVerifier` implementat ==== Using Custom Verifier via Bean Reference +._Java-only: `ServerKeyVerifier` lambda and registry bean binding_ [source,java] ---- // Register custom verifier in Camel registry @@ -1155,14 +1585,47 @@ ServerKeyVerifier myVerifier = (session, remoteAddress, serverKey) -> { return verifyAgainstEnterpriseKeyStore(serverKey); }; context.getRegistry().bind("myVerifier", myVerifier); +---- -// Use in endpoint URI +[tabs] +==== +Java:: ++ +[source,java] +---- from("mina-sftp://user@host/path?password=secret&serverKeyVerifier=#myVerifier") .to("file:local"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: mina-sftp://user@host/path + parameters: + password: secret + serverKeyVerifier: "#myVerifier" + steps: + - to: + uri: file:local +---- +==== + ==== Using Custom Verifier Programmatically +._Java-only: programmatic endpoint configuration with `ServerKeyVerifier` lambda_ [source,java] ---- MinaSftpEndpoint endpoint = context.getEndpoint( @@ -1419,6 +1882,10 @@ The mina-sftp component supports setting POSIX file permissions on uploaded file Use the `chmod` option to set permissions on files after they are uploaded: +[tabs] +==== +Java:: ++ [source,java] ---- // Set file permissions to rw-r--r-- (644) @@ -1430,10 +1897,59 @@ from("file:/data/secrets") .to("mina-sftp://user@host/secure?password=secret&chmod=600"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +# Set file permissions to rw-r--r-- (644) +- route: + from: + uri: file:/data/outbound + steps: + - to: + uri: mina-sftp://user@host/uploads + parameters: + password: secret + chmod: "644" + +# Set file permissions to rw------- (600) for sensitive files +- route: + from: + uri: file:/data/secrets + steps: + - to: + uri: mina-sftp://user@host/secure + parameters: + password: secret + chmod: "600" +---- +==== + === Setting Directory Permissions Use the `chmodDirectory` option to set permissions on directories when they are created: +[tabs] +==== +Java:: ++ [source,java] ---- // Set directory permissions to rwxr-xr-x (755) @@ -1445,6 +1961,52 @@ from("file:/data/outbound") .to("mina-sftp://user@host/uploads?password=secret&chmod=644&chmodDirectory=755"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +# Set directory permissions to rwxr-xr-x (755) +- route: + from: + uri: file:/data/outbound + steps: + - to: + uri: mina-sftp://user@host/uploads + parameters: + password: secret + chmodDirectory: "755" + +# Combine with chmod for complete control +- route: + from: + uri: file:/data/outbound + steps: + - to: + uri: mina-sftp://user@host/uploads + parameters: + password: secret + chmod: "644" + chmodDirectory: "755" +---- +==== + === Permission Format Permissions are specified as octal strings, just like the Unix `chmod` command: @@ -1547,9 +2109,12 @@ The mina-sftp component handles thread safety internally. The underlying MINA SS Multiple Camel routes can safely share the same SFTP endpoint. The component serializes access to the underlying SFTP connection: +[tabs] +==== +Java:: ++ [source,java] ---- -// Safe: Multiple routes can use the same endpoint from("timer:upload1?period=5000") .setBody(constant("data1")) .to("mina-sftp://user@host/uploads?password=secret"); @@ -1559,6 +2124,59 @@ from("timer:upload2?period=5000") .to("mina-sftp://user@host/uploads?password=secret"); ---- +XML:: ++ +[source,xml] +---- + + + + data1 + + + + + + + + data2 + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: timer:upload1 + parameters: + period: 5000 + steps: + - setBody: + constant: data1 + - to: + uri: mina-sftp://user@host/uploads + parameters: + password: secret + +- route: + from: + uri: timer:upload2 + parameters: + period: 5000 + steps: + - setBody: + constant: data2 + - to: + uri: mina-sftp://user@host/uploads + parameters: + password: secret +---- +==== + === Connection Pooling Each endpoint maintains its own connection. For high-throughput scenarios with many concurrent operations, consider using multiple endpoints or connection pooling strategies at the route level. From 1b4ae8ba5b5acd0409615e4030d00356120272bc Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:35:50 +0200 Subject: [PATCH 34/87] CAMEL-23789: Make Hazelcast Queue component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/hazelcast-queue-component.adoc | 618 ++++++++++++++++-- 1 file changed, 555 insertions(+), 63 deletions(-) diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-queue-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-queue-component.adoc index e5981a1104701..2e87d02ace23d 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-queue-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-queue-component.adoc @@ -45,105 +45,507 @@ The queue producer provides 12 operations: === Example for *add*: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------- +---- from("direct:add") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.ADD)) -.toF("hazelcast-%sbar", HazelcastConstants.QUEUE_PREFIX); ------------------------------------------------------------------------------------- + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.ADD)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + add + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:add + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: add + - to: + uri: hazelcast-queue:bar +---- +==== === Example for *put*: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------- +---- from("direct:put") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.PUT)) -.toF("hazelcast-%sbar", HazelcastConstants.QUEUE_PREFIX); ------------------------------------------------------------------------------------- + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.PUT)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + put + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:put + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: put + - to: + uri: hazelcast-queue:bar +---- +==== === Example for *poll*: +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------------- +---- from("direct:poll") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.POLL)) -.toF("hazelcast:%sbar", HazelcastConstants.QUEUE_PREFIX); -------------------------------------------------------------------------------------- + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.POLL)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + poll + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:poll + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: poll + - to: + uri: hazelcast-queue:bar +---- +==== === Example for *peek*: +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------------- +---- from("direct:peek") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.PEEK)) -.toF("hazelcast:%sbar", HazelcastConstants.QUEUE_PREFIX); -------------------------------------------------------------------------------------- + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.PEEK)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + peek + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:peek + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: peek + - to: + uri: hazelcast-queue:bar +---- +==== === Example for *offer*: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------- +---- from("direct:offer") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.OFFER)) -.toF("hazelcast:%sbar", HazelcastConstants.QUEUE_PREFIX); --------------------------------------------------------------------------------------- + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.OFFER)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + offer + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:offer + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: offer + - to: + uri: hazelcast-queue:bar +---- +==== === Example for *removevalue*: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------- +---- from("direct:removevalue") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.REMOVE_VALUE)) -.toF("hazelcast-%sbar", HazelcastConstants.QUEUE_PREFIX); --------------------------------------------------------------------------------------------- + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.REMOVE_VALUE)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + removeValue + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:removevalue + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: removeValue + - to: + uri: hazelcast-queue:bar +---- +==== === Example for *remaining capacity*: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------- -from("direct:remaining-capacity").setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.REMAINING_CAPACITY)).to( -String.format("hazelcast-%sbar", HazelcastConstants.QUEUE_PREFIX)); --------------------------------------------------------------------------------------------- +---- +from("direct:remaining-capacity") + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.REMAINING_CAPACITY)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + remainingCapacity + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:remaining-capacity + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: remainingCapacity + - to: + uri: hazelcast-queue:bar +---- +==== === Example for *remove all*: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------- -from("direct:removeAll").setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.REMOVE_ALL)).to( -String.format("hazelcast-%sbar", HazelcastConstants.QUEUE_PREFIX)); --------------------------------------------------------------------------------------------- +---- +from("direct:removeAll") + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.REMOVE_ALL)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + removeAll + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:removeAll + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: removeAll + - to: + uri: hazelcast-queue:bar +---- +==== === Example for *remove if*: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------- -from("direct:removeIf").setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.REMOVE_IF)).to( -String.format("hazelcast-%sbar", HazelcastConstants.QUEUE_PREFIX)); --------------------------------------------------------------------------------------------- +---- +from("direct:removeIf") + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.REMOVE_IF)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + removeIf + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:removeIf + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: removeIf + - to: + uri: hazelcast-queue:bar +---- +==== === Example for *drain to*: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------- -from("direct:drainTo").setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.DRAIN_TO)).to( -String.format("hazelcast-%sbar", HazelcastConstants.QUEUE_PREFIX)); --------------------------------------------------------------------------------------------- +---- +from("direct:drainTo") + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.DRAIN_TO)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + drainTo + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:drainTo + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: drainTo + - to: + uri: hazelcast-queue:bar +---- +==== === Example for *take*: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------- -from("direct:take").setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.TAKE)).to( -String.format("hazelcast-%sbar", HazelcastConstants.QUEUE_PREFIX)); --------------------------------------------------------------------------------------------- +---- +from("direct:take") + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.TAKE)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + take + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:take + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: take + - to: + uri: hazelcast-queue:bar +---- +==== === Example for *retain all*: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------- -from("direct:retainAll").setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.RETAIN_ALL)).to( -String.format("hazelcast-%sbar", HazelcastConstants.QUEUE_PREFIX)); --------------------------------------------------------------------------------------------- +---- +from("direct:retainAll") + .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.RETAIN_ALL)) + .to("hazelcast-queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + retainAll + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:retainAll + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: retainAll + - to: + uri: hazelcast-queue:bar +---- +==== == Queue consumer – from(“hazelcast-queue:foo”) @@ -154,10 +556,40 @@ The queue consumer provides two different modes: Sample for *Poll* mode +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------------------- -fromF("hazelcast-%sfoo?queueConsumerMode=Poll", HazelcastConstants.QUEUE_PREFIX)).to("mock:result"); -------------------------------------------------------------------------------------------- +---- +from("hazelcast-queue:foo?queueConsumerMode=Poll") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: hazelcast-queue:foo + parameters: + queueConsumerMode: Poll + steps: + - to: + uri: mock:result +---- +==== In this way, the consumer will poll the queue and return the head of the queue or null after a timeout. @@ -170,20 +602,80 @@ The queue consumer in Listen mode provides 2 operations: Sample for *Listen* mode +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------------------- -fromF("hazelcast-%smm", HazelcastConstants.QUEUE_PREFIX) - .log("object...") - .choice() - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.ADDED)) +---- +from("hazelcast-queue:mm") + .log("object...") + .choice() + .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.ADDED)) .log("...added") - .to("mock:added") - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.REMOVED)) - .log("...removed") - .to("mock:removed") - .otherwise() - .log("fail!"); -------------------------------------------------------------------------------------------- + .to("mock:added") + .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.REMOVED)) + .log("...removed") + .to("mock:removed") + .otherwise() + .log("fail!"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + ${header.CamelHazelcastListenerAction} == 'added' + + + + + ${header.CamelHazelcastListenerAction} == 'removed' + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: hazelcast-queue:mm + steps: + - log: + message: "object..." + - choice: + when: + - simple: "${header.CamelHazelcastListenerAction} == 'added'" + steps: + - log: + message: "...added" + - to: + uri: mock:added + - simple: "${header.CamelHazelcastListenerAction} == 'removed'" + steps: + - log: + message: "...removed" + - to: + uri: mock:removed + otherwise: + steps: + - log: + message: "fail!" +---- +==== include::spring-boot:partial$starter.adoc[] From 486b8d6e67a2c9d89ed43710e011a3a5a684191e Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:37:16 +0200 Subject: [PATCH 35/87] CAMEL-23789: Make Dynamic Router Control component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../dynamic-router-control-component.adoc | 87 +++++++++++++++++-- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/components/camel-dynamic-router/src/main/docs/dynamic-router-control-component.adoc b/components/camel-dynamic-router/src/main/docs/dynamic-router-control-component.adoc index 154439314a0ad..8cf5ffa62f210 100644 --- a/components/camel-dynamic-router/src/main/docs/dynamic-router-control-component.adoc +++ b/components/camel-dynamic-router/src/main/docs/dynamic-router-control-component.adoc @@ -39,13 +39,52 @@ Subscribing can be achieved by using query parameters in the control endpoint UR === URI examples -.Example Java URI `RouteBuilder` Subscription +.Example URI `RouteBuilder` Subscription + +[tabs] +==== +Java:: ++ [source,java] ---- -// Send a subscribe request to the dynamic router that will match every exchange and route messages to the URI: "direct:myDestination" -from("direct:subscribe").to("dynamic-router-control:subscribe?subscribeChannel=myChannel&subscriptionId=mySubId&destinationUri=direct:myDestination&priority=5&predicate=true&expressionLanguage=simple"); +// Send a subscribe request to the dynamic router that will match every exchange +// and route messages to the URI: "direct:myDestination" +from("direct:subscribe") + .to("dynamic-router-control:subscribe?subscribeChannel=myChannel&subscriptionId=mySubId&destinationUri=direct:myDestination&priority=5&predicate=true&expressionLanguage=simple"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:subscribe + steps: + - to: + uri: dynamic-router-control:subscribe + parameters: + subscribeChannel: myChannel + subscriptionId: mySubId + destinationUri: direct:myDestination + priority: 5 + predicate: "true" + expressionLanguage: simple +---- +==== + +._Java-only: ProducerTemplate API_ + .Example Java URI `ProducerTemplate` Subscription [source,java] ---- @@ -81,6 +120,8 @@ deliberately. === DynamicRouterControlMessage example +._Java-only: DynamicRouterControlMessage builder API_ + .Example Java `DynamicRouterControlMessage` Subscription [source,java] ---- @@ -103,12 +144,46 @@ achieved by using either one or two parameters. === URI examples -.Example Java URI `RouteBuilder` Unsubscribe +.Example URI `RouteBuilder` Unsubscribe + +[tabs] +==== +Java:: ++ [source,java] ---- -from("direct:subscribe").to("dynamic-router-control:unsubscribe?subscribeChannel=myChannel&subscriptionId=mySubId"); +from("direct:subscribe") + .to("dynamic-router-control:unsubscribe?subscribeChannel=myChannel&subscriptionId=mySubId"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:subscribe + steps: + - to: + uri: dynamic-router-control:unsubscribe + parameters: + subscribeChannel: myChannel + subscriptionId: mySubId +---- +==== + +._Java-only: ProducerTemplate API_ + .Example Java URI `ProducerTemplate` Unsubscribe [source,java] ---- @@ -131,6 +206,8 @@ dynamic-aware endpoint uses headers, rather than URI params, so we set the heade === DynamicRouterControlMessage example +._Java-only: DynamicRouterControlMessage builder API_ + .Example Java `DynamicRouterControlMessage` Unsubscribe [source,java] ---- From 8401fbc0416a69c95895cd28c47bad5de4dd5605 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:38:39 +0200 Subject: [PATCH 36/87] CAMEL-23789: Make Flink component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/flink-component.adoc | 184 ++++++++++++++---- 1 file changed, 145 insertions(+), 39 deletions(-) diff --git a/components/camel-flink/src/main/docs/flink-component.adoc b/components/camel-flink/src/main/docs/flink-component.adoc index 1dc503a19d5bd..90d08646a0664 100644 --- a/components/camel-flink/src/main/docs/flink-component.adoc +++ b/components/camel-flink/src/main/docs/flink-component.adoc @@ -60,8 +60,10 @@ include::partial$component-endpoint-headers.adoc[] === Flink DataSet Callback +._Java-only: Flink DataSetCallback API_ + [source,java] ------------------------------------ +---- @Bean public DataSetCallback dataSetCallback() { return new DataSetCallback() { @@ -75,12 +77,14 @@ public DataSetCallback dataSetCallback() { } }; } ------------------------------------ +---- === Flink DataStream Callback +._Java-only: Flink DataStreamCallback API_ + [source,java] ---------------------------- +---- @Bean public VoidDataStreamCallback dataStreamCallback() { return new VoidDataStreamCallback() { @@ -92,12 +96,14 @@ public VoidDataStreamCallback dataStreamCallback() { } }; } ---------------------------- +---- === Camel-Flink Producer call +._Java-only: ProducerTemplate API_ + [source,java] ------------------------------------ +---- CamelContext camelContext = new SpringCamelContext(context); String pattern = "foo"; @@ -109,14 +115,16 @@ try { } finally { camelContext.stop(); } ------------------------------------ +---- === Modern DataStream Batch Processing Example -The recommended approach using the DataStream API in batch mode: +The recommended approach using the DataStream API in batch mode. + +._Java-only: Spring @Bean configuration_ [source,java] ------------------------------------ +---- @Bean public StreamExecutionEnvironment streamExecutionEnvironment() { StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); @@ -148,18 +156,54 @@ public DataStreamCallback wordCountCallback() { } }; } +---- -// In your route +Then use the beans in the route: + +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:wordCount") .to("flink:datastream?dataStream=#myDataStream&dataStreamCallback=#wordCountCallback"); ------------------------------------ +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:wordCount + steps: + - to: + uri: flink:datastream + parameters: + dataStream: "#myDataStream" + dataStreamCallback: "#wordCountCallback" +---- +==== === Real-time Streaming Example For true streaming use cases with unbounded data: +._Java-only: Spring @Bean configuration with Flink streaming API_ + [source,java] ------------------------------------ +---- @Bean public StreamExecutionEnvironment streamingEnvironment() { StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); @@ -187,7 +231,7 @@ public DataStreamCallback streamingProcessCallback() { } }; } ------------------------------------ +---- === Advanced Configuration Examples @@ -195,34 +239,92 @@ public DataStreamCallback streamingProcessCallback() { Configure a DataStream endpoint for batch processing with custom settings: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------ +---- from("direct:batchProcess") - .to("flink:datastream?dataStream=#myDataStream" - + "&dataStreamCallback=#myCallback" - + "&executionMode=BATCH" - + "¶llelism=4" - + "&jobName=MyBatchJob"); ------------------------------------ + .to("flink:datastream?dataStream=#myDataStream&dataStreamCallback=#myCallback&executionMode=BATCH¶llelism=4&jobName=MyBatchJob"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:batchProcess + steps: + - to: + uri: flink:datastream + parameters: + dataStream: "#myDataStream" + dataStreamCallback: "#myCallback" + executionMode: BATCH + parallelism: 4 + jobName: MyBatchJob +---- +==== ==== Streaming with Checkpointing Configure a streaming job with checkpointing for fault tolerance: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------ +---- from("direct:streamProcess") - .to("flink:datastream?dataStream=#myDataStream" - + "&dataStreamCallback=#streamCallback" - + "&executionMode=STREAMING" - + "&checkpointInterval=60000" // Checkpoint every 60 seconds - + "&checkpointingMode=EXACTLY_ONCE" // Exactly-once semantics - + "&checkpointTimeout=120000" // 2 minute timeout - + "&minPauseBetweenCheckpoints=30000" // 30 second minimum pause - + "¶llelism=8" - + "&maxParallelism=128" - + "&jobName=StreamingPipeline"); ------------------------------------ + .to("flink:datastream?dataStream=#myDataStream&dataStreamCallback=#streamCallback&executionMode=STREAMING&checkpointInterval=60000&checkpointingMode=EXACTLY_ONCE&checkpointTimeout=120000&minPauseBetweenCheckpoints=30000¶llelism=8&maxParallelism=128&jobName=StreamingPipeline"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:streamProcess + steps: + - to: + uri: flink:datastream + parameters: + dataStream: "#myDataStream" + dataStreamCallback: "#streamCallback" + executionMode: STREAMING + checkpointInterval: 60000 + checkpointingMode: EXACTLY_ONCE + checkpointTimeout: 120000 + minPauseBetweenCheckpoints: 30000 + parallelism: 8 + maxParallelism: 128 + jobName: StreamingPipeline +---- +==== ==== Configuration Options Reference @@ -281,36 +383,40 @@ from("direct:streamProcess") ==== Counting Elements +._Java-only: Flink DataSet/DataStream API migration pattern_ + .Before (DataSet) [source,java] ------------------------------------ +---- long count = dataSet.count(); ------------------------------------ +---- .After (DataStream) [source,java] ------------------------------------ +---- // Use a custom sink or reduce operation dataStream .map(e -> 1L) .reduce(Long::sum) .print(); ------------------------------------ +---- ==== Collecting Results +._Java-only: Flink DataSet/DataStream API migration pattern_ + .Before (DataSet) [source,java] ------------------------------------ +---- List results = dataSet.collect(); ------------------------------------ +---- .After (DataStream) [source,java] ------------------------------------ +---- // In batch mode, use executeAndCollect() or a sink List results = dataStream.executeAndCollect(1000); ------------------------------------ +---- === Additional Resources From 33aed2a12971a20f2bb18113e003d223fe1e5e60 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:48:16 +0200 Subject: [PATCH 37/87] CAMEL-23789: Make CyberArk Vault component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/cyberark-vault-component.adoc | 401 ++++++++++++++++-- 1 file changed, 375 insertions(+), 26 deletions(-) diff --git a/components/camel-cyberark-vault/src/main/docs/cyberark-vault-component.adoc b/components/camel-cyberark-vault/src/main/docs/cyberark-vault-component.adoc index 3acac13014555..5d4a921db8a74 100644 --- a/components/camel-cyberark-vault/src/main/docs/cyberark-vault-component.adoc +++ b/components/camel-cyberark-vault/src/main/docs/cyberark-vault-component.adoc @@ -29,17 +29,7 @@ cyberark-vault:label[?options] Where `label` is a logical name for the endpoint. -You can specify the secret ID either as a URI parameter or via message header: - -[source,java] ----- -// Using URI parameter -.to("cyberark-vault:secret?secretId=db/password&...") - -// Using message header -.setHeader(CyberArkVaultConstants.SECRET_ID, constant("db/password")) -.to("cyberark-vault:secret?...") ----- +You can specify the secret ID either as a URI parameter or via a message header (`CamelCyberArkVaultSecretId`). You can append query options to the URI in the following format: @@ -111,17 +101,7 @@ The component supports the following operations: * **getSecret** (default) - Retrieve a secret value from CyberArk Conjur * **createSecret** - Create or update a secret in CyberArk Conjur -You can specify the operation either as a URI parameter or via message header: - -[source,java] ----- -// Using URI parameter -.to("cyberark-vault:secret?operation=getSecret&secretId=db/password&...") - -// Using message header -.setHeader(CyberArkVaultConstants.OPERATION, constant(CyberArkVaultOperations.createSecret)) -.to("cyberark-vault:secret?...") ----- +You can specify the operation either as a URI parameter or via a message header (`CamelCyberArkVaultOperation`). === Examples @@ -129,39 +109,149 @@ You can specify the operation either as a URI parameter or via message header: At this point, you can access secrets using property placeholders in your routes: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") .setHeader("DatabasePassword", simple("{{cyberark:db/password}}")) - .to("..."); + .to("direct:next"); ---- +XML:: ++ +[source,xml] +---- + + + + {{cyberark:db/password}} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: DatabasePassword + simple: "{{cyberark:db/password}}" + - to: + uri: direct:next +---- +==== + You can also specify a default value in case the secret doesn't exist: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") .setHeader("Password", simple("{{cyberark:db/password:defaultPassword}}")) - .to("..."); + .to("direct:next"); +---- + +XML:: ++ +[source,xml] +---- + + + + {{cyberark:db/password:defaultPassword}} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: Password + simple: "{{cyberark:db/password:defaultPassword}}" + - to: + uri: direct:next ---- +==== ==== Retrieve JSON Field from Secret If your secret contains JSON data, you can extract specific fields: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") .setHeader("Username", simple("{{cyberark:database#username}}")) .setHeader("Password", simple("{{cyberark:database#password}}")) - .to("..."); ----- + .to("direct:next"); +---- + +XML:: ++ +[source,xml] +---- + + + + {{cyberark:database#username}} + + + {{cyberark:database#password}} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: Username + simple: "{{cyberark:database#username}}" + - setHeader: + name: Password + simple: "{{cyberark:database#password}}" + - to: + uri: direct:next +---- +==== ==== Retrieve a Secret (getSecret) You can retrieve a secret using the component endpoint: Using URI parameter: + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") @@ -169,7 +259,45 @@ from("direct:start") .log("Retrieved secret: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: cyberark-vault:secret + parameters: + operation: getSecret + secretId: db/password + url: "https://conjur.example.com" + account: myaccount + username: admin + password: secretpass + - log: + message: "Retrieved secret: ${body}" +---- +==== + Using message header for dynamic secret retrieval: + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") @@ -178,7 +306,50 @@ from("direct:start") .log("Retrieved secret: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + ${header.secretName} + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelCyberArkVaultSecretId + simple: "${header.secretName}" + - to: + uri: cyberark-vault:secret + parameters: + operation: getSecret + url: "https://conjur.example.com" + account: myaccount + username: admin + password: secretpass + - log: + message: "Retrieved secret: ${body}" +---- +==== + Retrieve a specific version of a secret: + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") @@ -187,11 +358,54 @@ from("direct:start") .log("Retrieved secret version 3: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + 3 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelCyberArkVaultSecretVersion + constant: "3" + - to: + uri: cyberark-vault:secret + parameters: + secretId: db/password + url: "https://conjur.example.com" + account: myaccount + username: admin + apiKey: "3ahx8dy3..." + - log: + message: "Retrieved secret version 3: ${body}" +---- +==== + ==== Create or Update a Secret (createSecret) To create or update a secret, use the createSecret operation with the secret value in the message body or header: Using message body: + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") @@ -200,7 +414,50 @@ from("direct:start") .log("Secret created/updated"); ---- +XML:: ++ +[source,xml] +---- + + + + mySecretValue123 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: mySecretValue123 + - to: + uri: cyberark-vault:secret + parameters: + operation: createSecret + secretId: app/apikey + url: "https://conjur.example.com" + account: myaccount + username: admin + apiKey: "3ahx8dy3..." + - log: + message: "Secret created/updated" +---- +==== + Using message header: + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") @@ -210,7 +467,56 @@ from("direct:start") .log("Secret created/updated"); ---- +XML:: ++ +[source,xml] +---- + + + + myNewPassword + + + db/password + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelCyberArkVaultSecretValue + constant: myNewPassword + - setHeader: + name: CamelCyberArkVaultSecretId + constant: db/password + - to: + uri: cyberark-vault:secret + parameters: + operation: createSecret + url: "https://conjur.example.com" + account: myaccount + username: admin + apiKey: "3ahx8dy3..." + - log: + message: "Secret created/updated" +---- +==== + Dynamic secret creation: + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") @@ -220,6 +526,49 @@ from("direct:start") .log("Secret ${header.secretPath} created/updated"); ---- +XML:: ++ +[source,xml] +---- + + + + ${header.newSecretValue} + + + ${header.secretPath} + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + simple: "${header.newSecretValue}" + - setHeader: + name: CamelCyberArkVaultSecretId + simple: "${header.secretPath}" + - to: + uri: cyberark-vault:secret + parameters: + operation: createSecret + url: "https://conjur.example.com" + account: myaccount + username: admin + apiKey: "3ahx8dy3..." + - log: + message: "Secret ${header.secretPath} created/updated" +---- +==== + === SSL Certificate Verification By default, SSL certificate verification is enabled. You can disable it for testing purposes (not recommended for production): From fbf01c8d297039c87a288ab29b947c8da66901c0 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:49:41 +0200 Subject: [PATCH 38/87] CAMEL-23789: Make Google Cloud Functions component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/google-functions-component.adoc | 408 ++++++++++++++++-- 1 file changed, 374 insertions(+), 34 deletions(-) diff --git a/components/camel-google/camel-google-functions/src/main/docs/google-functions-component.adoc b/components/camel-google/camel-google-functions/src/main/docs/google-functions-component.adoc index 5c66fa30920de..4c07401cb24c1 100644 --- a/components/camel-google/camel-google-functions/src/main/docs/google-functions-component.adoc +++ b/components/camel-google/camel-google-functions/src/main/docs/google-functions-component.adoc @@ -65,11 +65,43 @@ You can append query options to the URI in the following format, For example, to call the function `myCamelFunction` from the project `myProject` and location `us-central1`, use the following snippet: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .to("google-functions://myCamelFunction?project=myProject&location=us-central1&operation=callFunction&serviceAccountKey=/home/user/Downloads/my-key.json"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-functions://myCamelFunction + parameters: + project: myProject + location: us-central1 + operation: callFunction + serviceAccountKey: /home/user/Downloads/my-key.json +---- +==== @@ -101,94 +133,364 @@ If you don't specify an operation by default, the producer will use the `callFun If you need to have more control over the `client` instance configuration, you can create your own instance and refer to it in your Camel google-functions component configuration: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .to("google-functions://myCamelFunction?client=#myClient"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-functions://myCamelFunction + parameters: + client: "#myClient" +---- +==== === Google Functions Producer Operation examples - `ListFunctions`: This operation invokes the Google Functions client and gets the list of cloud Functions +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -//list functions +---- from("direct:start") .to("google-functions://myCamelFunction?serviceAccountKey=/home/user/Downloads/my-key.json&project=myProject&location=us-central1&operation=listFunctions") - .log("body:${body}") --------------------------------------------------------------------------------- + .log("body:${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-functions://myCamelFunction + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + project: myProject + location: us-central1 + operation: listFunctions + - log: + message: "body:${body}" +---- +==== This operation will get the list of cloud functions for the project `myProject` and location `us-central1`. - `GetFunction`: this operation gets the Cloud Functions object +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -//get function +---- from("direct:start") .to("google-functions://myCamelFunction?serviceAccountKey=/home/user/Downloads/my-key.json&project=myProject&location=us-central1&operation=getFunction") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-functions://myCamelFunction + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + project: myProject + location: us-central1 + operation: getFunction + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== This operation will get the `CloudFunction` object for the project `myProject`, location `us-central1` and functionName `myCamelFunction`. - `CallFunction`: this operation calls the function using an HTTP request +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -//call function +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setBody("just a message"); - }) + .setBody(constant("just a message")) .to("google-functions://myCamelFunction?serviceAccountKey=/home/user/Downloads/my-key.json&project=myProject&location=us-central1&operation=callFunction") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + just a message + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: just a message + - to: + uri: google-functions://myCamelFunction + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + project: myProject + location: us-central1 + operation: callFunction + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== - `GenerateDownloadUrl`: this operation generates the signed URL for downloading deployed function source code. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -//generate download url +---- from("direct:start") .to("google-functions://myCamelFunction?serviceAccountKey=/home/user/Downloads/my-key.json&project=myProject&location=us-central1&operation=generateDownloadUrl") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-functions://myCamelFunction + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + project: myProject + location: us-central1 + operation: generateDownloadUrl + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== - `GenerateUploadUrl`: this operation generates a signed URL for uploading a function source code. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .to("google-functions://myCamelFunction?serviceAccountKey=/home/user/Downloads/my-key.json&project=myProject&location=us-central1&operation=generateUploadUrl") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-functions://myCamelFunction + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + project: myProject + location: us-central1 + operation: generateUploadUrl + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== - `createFunction`: this operation creates a new function. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(GoogleCloudFunctionsConstants.ENTRY_POINT, "com.example.Example"); - exchange.getIn().setHeader(GoogleCloudFunctionsConstants.RUNTIME, "java11"); - exchange.getIn().setHeader(GoogleCloudFunctionsConstants.SOURCE_ARCHIVE_URL, "gs://myBucket/source.zip"); - }) + .setHeader(GoogleCloudFunctionsConstants.ENTRY_POINT, constant("com.example.Example")) + .setHeader(GoogleCloudFunctionsConstants.RUNTIME, constant("java11")) + .setHeader(GoogleCloudFunctionsConstants.SOURCE_ARCHIVE_URL, constant("gs://myBucket/source.zip")) .to("google-functions://myCamelFunction?serviceAccountKey=/home/user/Downloads/my-key.json&project=myProject&location=us-central1&operation=createFunction") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + com.example.Example + + + java11 + + + gs://myBucket/source.zip + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleCloudFunctionsEntryPoint + constant: com.example.Example + - setHeader: + name: CamelGoogleCloudFunctionsRuntime + constant: java11 + - setHeader: + name: CamelGoogleCloudFunctionsSourceArchiveUrl + constant: "gs://myBucket/source.zip" + - to: + uri: google-functions://myCamelFunction + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + project: myProject + location: us-central1 + operation: createFunction + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== - `updateFunction`: this operation updates existing function. +._Java-only: Google Cloud SDK UpdateFunctionRequest builder_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { UpdateFunctionRequest request = UpdateFunctionRequest.newBuilder() @@ -199,17 +501,55 @@ from("direct:start") .to("google-functions://myCamelFunction?serviceAccountKey=/home/user/Downloads/my-key.json&project=myProject&location=us-central1&operation=updateFunction&pojoRequest=true") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- - `deleteFunction`: this operation Deletes a function with the given name from the specified project. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .to("google-functions://myCamelFunction?serviceAccountKey=/home/user/Downloads/my-key.json&project=myProject&location=us-central1&operation=deleteFunction") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-functions://myCamelFunction + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + project: myProject + location: us-central1 + operation: deleteFunction + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== include::spring-boot:partial$starter.adoc[] From a39603afbeaeb6883eb234b871be84fec64f8a7f Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:51:07 +0200 Subject: [PATCH 39/87] CAMEL-23789: Make Google Cloud Vision component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/google-vision-component.adoc | 384 +++++++++++++++--- 1 file changed, 334 insertions(+), 50 deletions(-) diff --git a/components/camel-google/camel-google-vision/src/main/docs/google-vision-component.adoc b/components/camel-google/camel-google-vision/src/main/docs/google-vision-component.adoc index d00bd8824a165..f94cec2785d34 100644 --- a/components/camel-google/camel-google-vision/src/main/docs/google-vision-component.adoc +++ b/components/camel-google/camel-google-vision/src/main/docs/google-vision-component.adoc @@ -64,11 +64,40 @@ You can append query options to the URI in the following format, For example, in order to perform label detection on an image, use the following snippet: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .to("google-vision://labelDetection?serviceAccountKey=/home/user/Downloads/my-key.json"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-vision://labelDetection + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json +---- +==== @@ -110,114 +139,332 @@ You can override the operation at runtime by setting the `GoogleCloudVisionOpera If you need to have more control over the `ImageAnnotatorClient` instance configuration, you can create your own instance and refer to it in your Camel google-vision component configuration: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .to("google-vision://labelDetection?client=#myVisionClient"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-vision://labelDetection + parameters: + client: "#myVisionClient" +---- +==== === Google Cloud Vision Producer Operation examples -- `labelDetection`: this operation detects labels in an image +- `labelDetection`: this operation detects labels in an image. The message body should contain the image data as a `byte[]`. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - byte[] imageData = Files.readAllBytes(Path.of("/path/to/image.jpg")); - exchange.getIn().setBody(imageData); - }) .to("google-vision://labelDetection?serviceAccountKey=/home/user/Downloads/my-key.json&maxResults=10") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-vision://labelDetection + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + maxResults: 10 + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== This operation will return a `List` with the detected labels. - `textDetection`: this operation extracts text from an image (OCR) +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - byte[] imageData = Files.readAllBytes(Path.of("/path/to/document.png")); - exchange.getIn().setBody(imageData); - }) .to("google-vision://textDetection?serviceAccountKey=/home/user/Downloads/my-key.json") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-vision://textDetection + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== This operation will return a `List` with the detected text. - `faceDetection`: this operation detects faces in an image +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - byte[] imageData = Files.readAllBytes(Path.of("/path/to/photo.jpg")); - exchange.getIn().setBody(imageData); - }) .to("google-vision://faceDetection?serviceAccountKey=/home/user/Downloads/my-key.json") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-vision://faceDetection + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== This operation will return a `List` with the detected faces. - `safeSearchDetection`: this operation detects explicit content +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - byte[] imageData = Files.readAllBytes(Path.of("/path/to/image.jpg")); - exchange.getIn().setBody(imageData); - }) .to("google-vision://safeSearchDetection?serviceAccountKey=/home/user/Downloads/my-key.json") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-vision://safeSearchDetection + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== This operation will return a `SafeSearchAnnotation` with likelihood ratings for adult, spoof, medical, violence and racy content. - `objectLocalization`: this operation detects and localizes objects +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - byte[] imageData = Files.readAllBytes(Path.of("/path/to/image.jpg")); - exchange.getIn().setBody(imageData); - }) .to("google-vision://objectLocalization?serviceAccountKey=/home/user/Downloads/my-key.json") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-vision://objectLocalization + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== This operation will return a `List` with detected objects and their bounding polygons. - `webDetection`: this operation finds web references and visually similar images +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - byte[] imageData = Files.readAllBytes(Path.of("/path/to/image.jpg")); - exchange.getIn().setBody(imageData); - }) .to("google-vision://webDetection?serviceAccountKey=/home/user/Downloads/my-key.json") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-vision://webDetection + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== This operation will return a `WebDetection` with matching pages, images and best guess labels. - Using POJO request for full control: +._Java-only: Google Cloud Vision SDK AnnotateImageRequest builder_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { Image image = Image.newBuilder() @@ -236,24 +483,61 @@ from("direct:start") .to("google-vision://labelDetection?serviceAccountKey=/home/user/Downloads/my-key.json&pojoRequest=true") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- When using `pojoRequest=true`, the body should be an `AnnotateImageRequest` and the full `AnnotateImageResponse` is returned. - Overriding the operation at runtime via header: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - byte[] imageData = Files.readAllBytes(Path.of("/path/to/image.jpg")); - exchange.getIn().setBody(imageData); - exchange.getIn().setHeader(GoogleCloudVisionConstants.OPERATION, GoogleCloudVisionOperations.logoDetection); - }) + .setHeader(GoogleCloudVisionConstants.OPERATION, constant(GoogleCloudVisionOperations.logoDetection)) .to("google-vision://labelDetection?serviceAccountKey=/home/user/Downloads/my-key.json") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + logoDetection + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleCloudVisionOperation + constant: logoDetection + - to: + uri: google-vision://labelDetection + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== include::spring-boot:partial$starter.adoc[] From 028e075955978ff6081cbea9e3a6d6a083494785 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:52:42 +0200 Subject: [PATCH 40/87] CAMEL-23789: Make Dynamic Router component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/dynamic-router-component.adoc | 129 ++++++++++++++++-- 1 file changed, 119 insertions(+), 10 deletions(-) diff --git a/components/camel-dynamic-router/src/main/docs/dynamic-router-component.adoc b/components/camel-dynamic-router/src/main/docs/dynamic-router-component.adoc index e14d7c4095152..ddfc714886095 100644 --- a/components/camel-dynamic-router/src/main/docs/dynamic-router-component.adoc +++ b/components/camel-dynamic-router/src/main/docs/dynamic-router-component.adoc @@ -145,6 +145,8 @@ For the purpose of this example, the exact steps that each service carries out a each service needs to be notified that it needs to do something under the right condition(s). So, each service will subscribe to participate in routing: +._Java-only: DynamicRouterControlMessage builder API_ + .Orders processing service subscription [source,java] ---- @@ -159,6 +161,8 @@ DynamicRouterControlMessage controlMessage = DynamicRouterControlMessage.newBuil producerTemplate.sendBody("dynamic-router-control:subscribe", controlMessage); ---- +._Java-only: DynamicRouterControlMessage builder API_ + .Inventory service subscription [source,java] ---- @@ -173,6 +177,8 @@ DynamicRouterControlMessage controlMessage = DynamicRouterControlMessage.newBuil producerTemplate.sendBody("dynamic-router-control:subscribe", controlMessage); ---- +._Java-only: DynamicRouterControlMessage builder API_ + .Returns processing service subscription [source,java] ---- @@ -196,6 +202,11 @@ will be notified. The order messages get sent to the dynamic router: .Routing order/return request messages + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") @@ -203,6 +214,32 @@ from("direct:start") .to("dynamic-router:orders"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: bean:myOrderProcessor + - to: + uri: dynamic-router:orders +---- +==== + Note the `.process(myOrderProcessor)` step. If incoming messages need to be validated, enriched, transformed, or otherwise augmented, that can be done before the Dynamic Router receives the message. Then, when the Dynamic Router receives a message, it checks the `Exchange` against all subscriptions for the _orders_ channel to determine if it is @@ -231,6 +268,8 @@ their own microservice (application). Similar to the single-JVM example, all se need to send their subscriptions through a transport that can communicate to another JVM. Their subscriptions might look like: +._Java-only: DynamicRouterControlMessage builder with ProducerTemplate/Kafka_ + .Orders processing service subscription [source,java] ---- @@ -246,6 +285,8 @@ ObjectMapper mapper = new ObjectMapper(new JsonFactory()); producerTemplate.sendBody("kafka://subscriptions", mapper.writeValueAsString(controlMessage)); ---- +._Java-only: DynamicRouterControlMessage builder with ProducerTemplate/Kafka_ + .Inventory service subscription [source,java] ---- @@ -261,6 +302,8 @@ ObjectMapper mapper = new ObjectMapper(new JsonFactory()); producerTemplate.sendBody("kafka://subscriptions", mapper.writeValueAsString(controlMessage)); ---- +._Java-only: DynamicRouterControlMessage builder with ProducerTemplate/Kafka_ + .Returns processing service subscription [source,java] ---- @@ -280,26 +323,59 @@ In another module, additional routing will serve as a bridge to get the message Dynamic Router: .Bridge from Kafka to the Dynamic Router control channel + +[tabs] +==== +Java:: ++ [source,java] ---- -RouteBuilder subscriptionRouter() { - return new RouteBuilder(camelContext) { - @Override - public void configure() { - from("kafka:subscriptions") - .unmarshal().json(DynamicRouterControlMessage.class) - .to("dynamic-router-control:subscribe"); - } - }; -} +from("kafka:subscriptions") + .unmarshal().json(DynamicRouterControlMessage.class) + .to("dynamic-router-control:subscribe"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: kafka:subscriptions + steps: + - unmarshal: + json: + library: Jackson + unmarshalType: org.apache.camel.component.dynamicrouter.control.DynamicRouterControlMessage + - to: + uri: dynamic-router-control:subscribe +---- +==== + Order requests or return requests might also arrive via Kafka. The route is essentially the same as the route in the single-JVM example. Instead of forwarding the incoming message, as-is, from the "direct" component to the router, the messages are deserialized from a String, and converted to an instance of the "order" object. Then, it can be sent to the Dynamic Router for evaluation and distribution to the appropriate subscribing recipients: .Routing order/return request messages from Kafka to the Dynamic Router + +[tabs] +==== +Java:: ++ [source,java] ---- from("kafka://orders") @@ -308,6 +384,39 @@ from("kafka://orders") .to("dynamic-router:orders"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: kafka://orders + steps: + - unmarshal: + json: + library: Jackson + unmarshalType: com.example.MyOrderMessage + - to: + uri: bean:myOrderProcessor + - to: + uri: dynamic-router:orders +---- +==== + Note the `.process(myOrderProcessor)` step. If incoming messages need to be validated, enriched, transformed, or otherwise augmented, that can be done before the Dynamic Router receives the message. Then, when the Dynamic Router receives a message, it checks the `Exchange` against all subscriptions for the "orders" channel to determine if it is From db4bfe648dc7735a3c3fefd2f4eaeeabee402525 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 17 Jun 2026 21:54:48 +0200 Subject: [PATCH 41/87] CAMEL-23789: Make AWS Athena component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/aws2-athena-component.adoc | 570 ++++++++++++++++-- 1 file changed, 524 insertions(+), 46 deletions(-) diff --git a/components/camel-aws/camel-aws2-athena/src/main/docs/aws2-athena-component.adoc b/components/camel-aws/camel-aws2-athena/src/main/docs/aws2-athena-component.adoc index 446c6909d5224..80f4d66d56f02 100644 --- a/components/camel-aws/camel-aws2-athena/src/main/docs/aws2-athena-component.adoc +++ b/components/camel-aws/camel-aws2-athena/src/main/docs/aws2-athena-component.adoc @@ -50,8 +50,12 @@ the https://aws.amazon.com/athena/[AWS Athena] service. For example, to run a simple query, wait up to 60 seconds for completion, and log the results: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant("SELECT 1")) .to("aws2-athena://label?waitTimeout=60000&outputLocation=s3://bucket/path/") @@ -59,7 +63,57 @@ from("direct:start") .split(body()).streaming() .to("log:out") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + SELECT 1 + + + + + ${body} + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: SELECT 1 + - to: + uri: aws2-athena://label + parameters: + waitTimeout: "60000" + outputLocation: s3://bucket/path/ + - to: + uri: aws2-athena://label + parameters: + operation: getQueryResults + outputType: StreamList + - split: + simple: "${body}" + streaming: true + steps: + - to: + uri: log:out + - to: + uri: mock:result +---- +==== Similarly, running the query and returning a path to the results in S3: @@ -150,11 +204,40 @@ If your Camel Application is running behind a firewall or if you need to have more control over the `AthenaClient` instance configuration, you can create your own instance and refer to it in your Camel aws2-athena component configuration: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -from("aws2-athena://MyQuery?amazonAthenaClient=#client&...") -.to("mock:result"); --------------------------------------------------------------------------------- +---- +from("aws2-athena://MyQuery?amazonAthenaClient=#client") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: aws2-athena://MyQuery + parameters: + amazonAthenaClient: "#client" + steps: + - to: + uri: mock:result +---- +==== === Overriding query parameters with message headers @@ -163,13 +246,51 @@ query parameters listed in "Query Parameters". For example: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setHeader(Athena2Constants.OUTPUT_LOCATION, constant("s3://other/location/")) .to("aws2-athena:label?outputLocation=s3://foo/bar/") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + s3://other/location/ + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsAthenaOutputLocation + constant: "s3://other/location/" + - to: + uri: aws2-athena:label + parameters: + outputLocation: "s3://foo/bar/" + - to: + uri: mock:result +---- +==== Will cause the output location to be `s3://other/location/`. @@ -224,14 +345,57 @@ The getQueryExecution operation also supports retrieving the query execution ID (`CamelAwsAthenaQueryExecutionId`), and since startQueryExecution sets the same header, upon starting a query, these operations can be used together: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant("SELECT 1")) .to("aws2-athena://label?operation=startQueryExecution&outputLocation=s3://bucket/path/") .to("aws2-athena://label?operation=getQueryExecution") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + SELECT 1 + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: SELECT 1 + - to: + uri: aws2-athena://label + parameters: + operation: startQueryExecution + outputLocation: s3://bucket/path/ + - to: + uri: aws2-athena://label + parameters: + operation: getQueryExecution + - to: + uri: mock:result +---- +==== The preceding example will yield an Athena QueryExecution in the body for the query that was just started. @@ -242,47 +406,82 @@ body in one of three formats. https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/athena/paginators/GetQueryResultsIterable.html[GetQueryResultsIterable] in the body that can page through all results: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant("SELECT 1")) .to("aws2-athena://label?operation=startQueryExecution&waitTimeout=60000&outputLocation=s3://bucket/path/") .to("aws2-athena://label?operation=getQueryResults&outputType=StreamList") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + SELECT 1 + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: SELECT 1 + - to: + uri: aws2-athena://label + parameters: + operation: startQueryExecution + waitTimeout: "60000" + outputLocation: s3://bucket/path/ + - to: + uri: aws2-athena://label + parameters: + operation: getQueryResults + outputType: StreamList + - to: + uri: mock:result +---- +==== The output of StreamList can be processed in various ways: +._Java-only: AWS SDK GetQueryResultsResponse processing_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .setBody(constant( - "SELECT * FROM (" - + " VALUES" - + " (1, 'a')," - + " (2, 'b')" - + ") AS t (id, name)")) + .setBody(constant("SELECT * FROM (VALUES (1, 'a'), (2, 'b')) AS t (id, name)")) .to("aws2-athena://label?operation=startQueryExecution&waitTimeout=60000&outputLocation=s3://bucket/path/") .to("aws2-athena://label?operation=getQueryResults&outputType=StreamList") .split(body()).streaming() - .process(new Processor() { - - @Override - public void process(Exchange exchange) { - GetQueryResultsResponse page = exchange - .getMessage() - .getBody(GetQueryResultsResponse.class); + .process(exchange -> { + GetQueryResultsResponse page = exchange.getMessage().getBody(GetQueryResultsResponse.class); for (Row row : page.resultSet().rows()) { - String line = row.data() - .stream() - .map(Datum::varCharValue) - .collect(Collectors.joining(",")); + String line = row.data().stream() + .map(Datum::varCharValue) + .collect(Collectors.joining(",")); System.out.println(line); } - } }) .to("mock:result"); --------------------------------------------------------------------------------- +---- The preceding example will print the results of the query as CSV to the console. @@ -291,14 +490,59 @@ https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/athena in the body containing at most 1,000 rows, plus the NextToken value as a header (`CamelAwsAthenaNextToken`), which can be used for manual pagination of results: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant("SELECT 1")) .to("aws2-athena://label?operation=startQueryExecution&waitTimeout=60000&outputLocation=s3://bucket/path/") .to("aws2-athena://label?operation=getQueryResults&outputType=SelectList") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + SELECT 1 + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: SELECT 1 + - to: + uri: aws2-athena://label + parameters: + operation: startQueryExecution + waitTimeout: "60000" + outputLocation: s3://bucket/path/ + - to: + uri: aws2-athena://label + parameters: + operation: getQueryResults + outputType: SelectList + - to: + uri: mock:result +---- +==== The preceding example will return a https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/athena/model/GetQueryResultsResponse.html[GetQueryResponse] @@ -307,14 +551,59 @@ through the results 1,000 rows at a time. `S3Pointer` - return an S3 path (e.g. `s3://bucket/path/`) pointing to the results: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant("SELECT 1")) .to("aws2-athena://label?operation=startQueryExecution&waitTimeout=60000&outputLocation=s3://bucket/path/") .to("aws2-athena://label?operation=getQueryResults&outputType=S3Pointer") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + SELECT 1 + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: SELECT 1 + - to: + uri: aws2-athena://label + parameters: + operation: startQueryExecution + waitTimeout: "60000" + outputLocation: s3://bucket/path/ + - to: + uri: aws2-athena://label + parameters: + operation: getQueryResults + outputType: S3Pointer + - to: + uri: mock:result +---- +==== The preceding example will return an S3 path (e.g. `s3://bucket/path/`) in the body pointing to the results. The path will also be set in a header @@ -417,25 +706,107 @@ The preceding example will start the query `SELECT 1` and configure the results to be saved to `s3://bucket/path/`, but will not wait for the query to complete. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant("SELECT 1")) .to("aws2-athena://label?operation=startQueryExecution&waitTimeout=60000&outputLocation=s3://bucket/path/") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + SELECT 1 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: SELECT 1 + - to: + uri: aws2-athena://label + parameters: + operation: startQueryExecution + waitTimeout: "60000" + outputLocation: s3://bucket/path/ + - to: + uri: mock:result +---- +==== The preceding example will start a query and wait up to 60 seconds for it to reach a status that indicates it is complete (one of SUCCEEDED, FAILED, CANCELLED, or UNKNOWN_TO_SDK_VERSION). Upon failure, the query would not be retried. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant("SELECT 1")) .to("aws2-athena://label?operation=startQueryExecution&waitTimeout=60000&initialDelay=10000&delay=1000&maxAttempts=3&retry=retryable&outputLocation=s3://bucket/path/") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + SELECT 1 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: SELECT 1 + - to: + uri: aws2-athena://label + parameters: + operation: startQueryExecution + waitTimeout: "60000" + initialDelay: "10000" + delay: "1000" + maxAttempts: 3 + retry: retryable + outputLocation: s3://bucket/path/ + - to: + uri: mock:result +---- +==== The preceding example will start a query and wait up to 60 seconds for it to reach a status that indicates it is complete (one of SUCCEEDED, FAILED, CANCELLED, @@ -448,14 +819,60 @@ initial delay of 10 seconds, and subsequently every 1 second until the query com === Putting it all together +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant("SELECT 1")) - .to("aws2-athena://label?waitTimeout=60000&&maxAttempts=3&retry=retryable&outputLocation=s3://bucket/path/") + .to("aws2-athena://label?waitTimeout=60000&maxAttempts=3&retry=retryable&outputLocation=s3://bucket/path/") .to("aws2-athena://label?operation=getQueryResults&outputType=StreamList") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + SELECT 1 + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: SELECT 1 + - to: + uri: aws2-athena://label + parameters: + waitTimeout: "60000" + maxAttempts: 3 + retry: retryable + outputLocation: s3://bucket/path/ + - to: + uri: aws2-athena://label + parameters: + operation: getQueryResults + outputType: StreamList + - to: + uri: mock:result +---- +==== The preceding example will start the query and wait up to 60 seconds for it to complete. Upon completion, getQueryResults put the results of the query into @@ -463,18 +880,79 @@ the body of the message for further processing. For the sake of completeness, a similar outcome could be achieved with the following: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant("SELECT 1")) .to("aws2-athena://label?operation=startQueryExecution&outputLocation=s3://bucket/path/") - .loopDoWhile(simple("${header." + Athena2Constants.QUERY_EXECUTION_STATE + "} != 'SUCCEEDED'")) + .loopDoWhile(simple("${header.CamelAwsAthenaQueryExecutionState} != 'SUCCEEDED'")) .delay(1_000) .to("aws2-athena://label?operation=getQueryExecution") .end() .to("aws2-athena://label?operation=getQueryResults&outputType=StreamList") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + SELECT 1 + + + + ${header.CamelAwsAthenaQueryExecutionState} != 'SUCCEEDED' + + 1000 + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: SELECT 1 + - to: + uri: aws2-athena://label + parameters: + operation: startQueryExecution + outputLocation: s3://bucket/path/ + - loop: + doWhile: true + simple: "${header.CamelAwsAthenaQueryExecutionState} != 'SUCCEEDED'" + steps: + - delay: + constant: 1000 + - to: + uri: aws2-athena://label + parameters: + operation: getQueryExecution + - to: + uri: aws2-athena://label + parameters: + operation: getQueryResults + outputType: StreamList + - to: + uri: mock:result +---- +==== Caution: the preceding example would block indefinitely, however, if the query did not complete with a status of SUCCEEDED. From 49640d6beb4a55beb80d41f34dca46d453d202b2 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:13:49 +0200 Subject: [PATCH 42/87] CAMEL-23789: Fix unterminated listing block in MongoDB component docs Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- components/camel-mongodb/src/main/docs/mongodb-component.adoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/camel-mongodb/src/main/docs/mongodb-component.adoc b/components/camel-mongodb/src/main/docs/mongodb-component.adoc index 449ec7ce94dfd..fd8ae66808634 100644 --- a/components/camel-mongodb/src/main/docs/mongodb-component.adoc +++ b/components/camel-mongodb/src/main/docs/mongodb-component.adoc @@ -698,8 +698,7 @@ Object result = template.requestBodyAndHeaders("direct:update", updateObj, heade // route: from("direct:update").to("mongodb:myDb?database=science&collection=notableScientists&operation=update"); String updateObj = "[{\"filterField\": true}, {\"$set\", {\"scientist\", \"Darwin\"}}]"; Object result = template.requestBodyAndHeader("direct:update", updateObj, "CamelMongoDbMultiUpdate", true); - ------------------------------------------------------------------------------------------------------------------------------------------- +---- ==== Delete operations From e945d96b66d6f6616911ba90f744d89d22a0e0b0 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:21:19 +0200 Subject: [PATCH 43/87] CAMEL-23789: Make Dropbox component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/dropbox-component.adoc | 533 ++++++++++++++++-- 1 file changed, 492 insertions(+), 41 deletions(-) diff --git a/components/camel-dropbox/src/main/docs/dropbox-component.adoc b/components/camel-dropbox/src/main/docs/dropbox-component.adoc index 09b60395225fb..515c356ceeff9 100644 --- a/components/camel-dropbox/src/main/docs/dropbox-component.adoc +++ b/components/camel-dropbox/src/main/docs/dropbox-component.adoc @@ -97,20 +97,100 @@ Below are listed the options for this operation: |`remotePath` |`true` |Folder or file to delete on Dropbox |=== -.Examples +.Deleting a folder + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .to("dropbox://del?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX" - +"&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1") - .to("mock:result"); + .to("dropbox://del?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: dropbox://del + parameters: + accessToken: XXX + clientIdentifier: XXX + expireIn: 1000 + refreshToken: XXXX + apiKey: XXXXX + apiSecret: XXXXXX + remotePath: /root/folder1 + - to: + uri: mock:result +---- +==== + +.Deleting a file + +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:start") - .to("dropbox://del?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX" - +"&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1/file1.tar.gz") - .to("mock:result"); + .to("dropbox://del?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1/file1.tar.gz") + .to("mock:result"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: dropbox://del + parameters: + accessToken: XXX + clientIdentifier: XXX + expireIn: 1000 + refreshToken: XXXX + apiKey: XXXXX + apiSecret: XXXXXX + remotePath: /root/folder1/file1.tar.gz + - to: + uri: mock:result +---- +==== + ==== Result Message Body The following objects are set on message body result: @@ -137,24 +217,143 @@ Below are listed the options for this operation: |`remotePath` |`true` |Folder or file to download from Dropbox |=== -.Examples +.Downloading a single file + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .to("dropbox://get?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX" - +"&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1/file1.tar.gz") - .to("file:///home/kermit/?fileName=file1.tar.gz"); + .to("dropbox://get?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1/file1.tar.gz") + .to("file:///home/kermit/?fileName=file1.tar.gz"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: dropbox://get + parameters: + accessToken: XXX + clientIdentifier: XXX + expireIn: 1000 + refreshToken: XXXX + apiKey: XXXXX + apiSecret: XXXXXX + remotePath: /root/folder1/file1.tar.gz + - to: + uri: "file:///home/kermit/?fileName=file1.tar.gz" +---- +==== + +.Downloading a folder + +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:start") - .to("dropbox://get?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX" - +"&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1") - .to("mock:result"); + .to("dropbox://get?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1") + .to("mock:result"); +---- -from("dropbox://get?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX" - +"&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1") - .to("file:///home/kermit/"); +XML:: ++ +[source,xml] +---- + + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: dropbox://get + parameters: + accessToken: XXX + clientIdentifier: XXX + expireIn: 1000 + refreshToken: XXXX + apiKey: XXXXX + apiSecret: XXXXXX + remotePath: /root/folder1 + - to: + uri: mock:result +---- +==== + +.Using as a consumer to download files + +[tabs] +==== +Java:: ++ +[source,java] +---- +from("dropbox://get?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1") + .to("file:///home/kermit/"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: dropbox://get + parameters: + accessToken: XXX + clientIdentifier: XXX + expireIn: 1000 + refreshToken: XXXX + apiKey: XXXXX + apiSecret: XXXXXX + remotePath: /root/folder1 + steps: + - to: + uri: "file:///home/kermit/" +---- +==== + ==== Result Message Body The following objects are set on message body result: @@ -188,14 +387,53 @@ Below are listed the options for this operation: |=== .Examples + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .to("dropbox://move?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX" - +"&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1&newRemotePath=/root/folder2") - .to("mock:result"); + .to("dropbox://move?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/root/folder1&newRemotePath=/root/folder2") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: dropbox://move + parameters: + accessToken: XXX + clientIdentifier: XXX + expireIn: 1000 + refreshToken: XXXX + apiKey: XXXXX + apiSecret: XXXXXX + remotePath: /root/folder1 + newRemotePath: /root/folder2 + - to: + uri: mock:result +---- +==== + ==== Result Message Body The following objects are set on message body result: @@ -238,31 +476,160 @@ Caused by: java.lang.IllegalArgumentException: 'path': bad path: must start with |=== -.Examples +.Uploading from local path + +[tabs] +==== +Java:: ++ [source,java] ---- -from("direct:start").to("dropbox://put?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX" - +"&apiKey=XXXXX&apiSecret=XXXXXX&uploadMode=add&localPath=/root/folder1") - .to("mock:result"); +from("direct:start") + .to("dropbox://put?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX&apiKey=XXXXX&apiSecret=XXXXXX&uploadMode=add&localPath=/root/folder1") + .to("mock:result"); +---- -from("direct:start").to("dropbox://put?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX" - +"&apiKey=XXXXX&apiSecret=XXXXXX&uploadMode=add&localPath=/root/folder1&remotePath=/root/folder2") - .to("mock:result"); +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: dropbox://put + parameters: + accessToken: XXX + clientIdentifier: XXX + expireIn: 1000 + refreshToken: XXXX + apiKey: XXXXX + apiSecret: XXXXXX + uploadMode: add + localPath: /root/folder1 + - to: + uri: mock:result +---- +==== + +.Uploading to a specific remote path + +[tabs] +==== +Java:: ++ +[source,java] +---- +from("direct:start") + .to("dropbox://put?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX&apiKey=XXXXX&apiSecret=XXXXXX&uploadMode=add&localPath=/root/folder1&remotePath=/root/folder2") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: dropbox://put + parameters: + accessToken: XXX + clientIdentifier: XXX + expireIn: 1000 + refreshToken: XXXX + apiKey: XXXXX + apiSecret: XXXXXX + uploadMode: add + localPath: /root/folder1 + remotePath: /root/folder2 + - to: + uri: mock:result ---- +==== And to upload a single file with content from the message body +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .setHeader(DropboxConstants.HEADER_PUT_FILE_NAME, constant("myfile.txt")) - .to("dropbox://put?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX" - +"&apiKey=XXXXX&apiSecret=XXXXXX&uploadMode=add&remotePath=/root/folder2") - .to("mock:result"); + .setHeader("CamelDropboxPutFileName", constant("myfile.txt")) + .to("dropbox://put?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX&apiKey=XXXXX&apiSecret=XXXXXX&uploadMode=add&remotePath=/root/folder2") + .to("mock:result"); ---- -The name of the file can be provided in the header `DropboxConstants.HEADER_PUT_FILE_NAME` -or `Exchange.FILE_NAME` in that order of precedence. If no header has been provided then the message id (uuid) is +XML:: ++ +[source,xml] +---- + + + + myfile.txt + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDropboxPutFileName + constant: myfile.txt + - to: + uri: dropbox://put + parameters: + accessToken: XXX + clientIdentifier: XXX + expireIn: 1000 + refreshToken: XXXX + apiKey: XXXXX + apiSecret: XXXXXX + uploadMode: add + remotePath: /root/folder2 + - to: + uri: mock:result +---- +==== + +The name of the file can be provided in the header `CamelDropboxPutFileName` +or `CamelFileName` in that order of precedence. If no header has been provided then the message id (uuid) is used as the file name. ==== Result Message Body @@ -300,19 +667,103 @@ will be matched. The query is required to be provided in either the endpoint con or as a header `CamelDropboxQuery` on the Camel message. |=== -.Examples +.Searching with a query in the URI + +[tabs] +==== +Java:: ++ [source,java] ---- -from("dropbox://search?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX" - +"&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/XXX&query=XXX") - .to("mock:result"); +from("dropbox://search?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/XXX&query=XXX") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: dropbox://search + parameters: + accessToken: XXX + clientIdentifier: XXX + expireIn: 1000 + refreshToken: XXXX + apiKey: XXXXX + apiSecret: XXXXXX + remotePath: /XXX + query: XXX + steps: + - to: + uri: mock:result +---- +==== + +.Searching with a query set via header + +[tabs] +==== +Java:: ++ +[source,java] +---- from("direct:start") - .setHeader("CamelDropboxQuery", constant("XXX")) - .to("dropbox://search?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX" - +"&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/XXX") - .to("mock:result"); + .setHeader("CamelDropboxQuery", constant("XXX")) + .to("dropbox://search?accessToken=XXX&clientIdentifier=XXX&expireIn=1000&refreshToken=XXXX&apiKey=XXXXX&apiSecret=XXXXXX&remotePath=/XXX") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + XXX + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelDropboxQuery + constant: XXX + - to: + uri: dropbox://search + parameters: + accessToken: XXX + clientIdentifier: XXX + expireIn: 1000 + refreshToken: XXXX + apiKey: XXXXX + apiSecret: XXXXXX + remotePath: /XXX + - to: + uri: mock:result ---- +==== ==== Result Message Body From 3322df0a499cfd90f13ddba8fd8889611ccd2d3c Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:23:23 +0200 Subject: [PATCH 44/87] CAMEL-23789: Make Google Text/Speech-to-Text component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../docs/google-speech-to-text-component.adoc | 216 ++++++++++++-- .../docs/google-text-to-speech-component.adoc | 273 ++++++++++++++++-- 2 files changed, 438 insertions(+), 51 deletions(-) diff --git a/components/camel-google/camel-google-speech-to-text/src/main/docs/google-speech-to-text-component.adoc b/components/camel-google/camel-google-speech-to-text/src/main/docs/google-speech-to-text-component.adoc index d8f813e0a1a3a..400e5f1581e2d 100644 --- a/components/camel-google/camel-google-speech-to-text/src/main/docs/google-speech-to-text-component.adoc +++ b/components/camel-google/camel-google-speech-to-text/src/main/docs/google-speech-to-text-component.adoc @@ -64,11 +64,40 @@ You can append query options to the URI in the following format, For example, in order to perform speech recognition on audio data, use the following snippet: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .to("google-speech-to-text://recognize?serviceAccountKey=/home/user/Downloads/my-key.json"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-speech-to-text://recognize + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json +---- +==== @@ -100,48 +129,146 @@ You can override the operation at runtime by setting the `GoogleCloudSpeechToTex If you need to have more control over the `SpeechClient` instance configuration, you can create your own instance and refer to it in your Camel google-speech-to-text component configuration: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .to("google-speech-to-text://recognize?client=#mySpeechClient"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-speech-to-text://recognize + parameters: + client: "#mySpeechClient" +---- +==== === Google Cloud Speech To Text Producer Operation examples -- `recognize`: this operation transcribes audio data to text +- `recognize`: this operation transcribes audio data to text. The message body should contain the audio data as a `byte[]`. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - byte[] audioData = Files.readAllBytes(Path.of("/path/to/audio.wav")); - exchange.getIn().setBody(audioData); - }) .to("google-speech-to-text://recognize?serviceAccountKey=/home/user/Downloads/my-key.json&encoding=LINEAR16&sampleRateHertz=16000&languageCode=en-US") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-speech-to-text://recognize + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + encoding: LINEAR16 + sampleRateHertz: 16000 + languageCode: en-US + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== This operation will return the transcribed text as a `String`. The full `RecognizeResponse` is available via the `GoogleCloudSpeechToTextResponseObject` message header. - Using different audio encodings: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - byte[] audioData = Files.readAllBytes(Path.of("/path/to/audio.flac")); - exchange.getIn().setBody(audioData); - }) .to("google-speech-to-text://recognize?serviceAccountKey=/home/user/Downloads/my-key.json&encoding=FLAC&languageCode=fr-FR") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-speech-to-text://recognize + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + encoding: FLAC + languageCode: fr-FR + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== - Using POJO request for full control: +._Java-only: Google Cloud SDK RecognizeRequest builder_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { RecognitionConfig config = RecognitionConfig.newBuilder() @@ -161,24 +288,61 @@ from("direct:start") .to("google-speech-to-text://recognize?serviceAccountKey=/home/user/Downloads/my-key.json&pojoRequest=true") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- When using `pojoRequest=true`, the body should be a `RecognizeRequest` and the transcribed text is returned as the body. - Overriding the operation at runtime via header: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - byte[] audioData = Files.readAllBytes(Path.of("/path/to/audio.wav")); - exchange.getIn().setBody(audioData); - exchange.getIn().setHeader(GoogleCloudSpeechToTextConstants.OPERATION, GoogleCloudSpeechToTextOperations.recognize); - }) + .setHeader("CamelGoogleCloudSpeechToTextOperation", constant("recognize")) .to("google-speech-to-text://recognize?serviceAccountKey=/home/user/Downloads/my-key.json") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + recognize + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleCloudSpeechToTextOperation + constant: recognize + - to: + uri: google-speech-to-text://recognize + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-google/camel-google-text-to-speech/src/main/docs/google-text-to-speech-component.adoc b/components/camel-google/camel-google-text-to-speech/src/main/docs/google-text-to-speech-component.adoc index 2a2d6881f27be..2ff794b0a6130 100644 --- a/components/camel-google/camel-google-text-to-speech/src/main/docs/google-text-to-speech-component.adoc +++ b/components/camel-google/camel-google-text-to-speech/src/main/docs/google-text-to-speech-component.adoc @@ -64,11 +64,40 @@ You can append query options to the URI in the following format, For example, in order to synthesize speech from text, use the following snippet: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .to("google-text-to-speech://synthesize?serviceAccountKey=/home/user/Downloads/my-key.json"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-text-to-speech://synthesize + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json +---- +==== @@ -103,60 +132,210 @@ You can override the operation at runtime by setting the `GoogleCloudTextToSpeec If you need to have more control over the `TextToSpeechClient` instance configuration, you can create your own instance and refer to it in your Camel google-text-to-speech component configuration: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .to("google-text-to-speech://synthesize?client=#myTextToSpeechClient"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-text-to-speech://synthesize + parameters: + client: "#myTextToSpeechClient" +---- +==== === Google Cloud Text-to-Speech Producer Operation examples -- `synthesize`: this operation converts text to speech audio +- `synthesize`: this operation converts text to speech audio. The message body should contain the text to synthesize as a `String`. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setBody("Hello, how are you today?"); - }) + .setBody(constant("Hello, how are you today?")) .to("google-text-to-speech://synthesize?serviceAccountKey=/home/user/Downloads/my-key.json&languageCode=en-US&audioEncoding=MP3") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + Hello, how are you today? + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: "Hello, how are you today?" + - to: + uri: google-text-to-speech://synthesize + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + languageCode: en-US + audioEncoding: MP3 + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== This operation will return a `byte[]` containing the synthesized audio content. - `synthesize` with voice customization: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setBody("Bonjour, comment allez-vous?"); - }) + .setBody(constant("Bonjour, comment allez-vous?")) .to("google-text-to-speech://synthesize?serviceAccountKey=/home/user/Downloads/my-key.json&languageCode=fr-FR&voiceName=fr-FR-Wavenet-A&audioEncoding=OGG_OPUS&speakingRate=1.2&pitch=-2.0") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + Bonjour, comment allez-vous? + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: "Bonjour, comment allez-vous?" + - to: + uri: google-text-to-speech://synthesize + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + languageCode: fr-FR + voiceName: fr-FR-Wavenet-A + audioEncoding: OGG_OPUS + speakingRate: 1.2 + pitch: -2.0 + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== This operation will return a `byte[]` with the audio in OGG_OPUS format using a specific French voice. - `listVoices`: this operation lists available voices +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .to("google-text-to-speech://listVoices?serviceAccountKey=/home/user/Downloads/my-key.json&languageCode=en-US") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: google-text-to-speech://listVoices + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + languageCode: en-US + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== This operation will return a `List` with the available voices for the specified language. - Using POJO request for full control: +._Java-only: Google Cloud SDK SynthesizeSpeechRequest builder_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { SynthesisInput input = SynthesisInput.newBuilder() @@ -179,23 +358,67 @@ from("direct:start") .to("google-text-to-speech://synthesize?serviceAccountKey=/home/user/Downloads/my-key.json&pojoRequest=true") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- When using `pojoRequest=true`, the body should be a `SynthesizeSpeechRequest` and the audio bytes are returned as body. - Overriding the operation at runtime via header: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setBody("Hello world"); - exchange.getIn().setHeader(GoogleCloudTextToSpeechConstants.OPERATION, GoogleCloudTextToSpeechOperations.synthesize); - }) + .setBody(constant("Hello world")) + .setHeader("CamelGoogleCloudTextToSpeechOperation", constant("synthesize")) .to("google-text-to-speech://listVoices?serviceAccountKey=/home/user/Downloads/my-key.json") .log("body:${body}") .to("mock:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + Hello world + + + synthesize + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: Hello world + - setHeader: + name: CamelGoogleCloudTextToSpeechOperation + constant: synthesize + - to: + uri: google-text-to-speech://listVoices + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + - log: + message: "body:${body}" + - to: + uri: mock:result +---- +==== include::spring-boot:partial$starter.adoc[] From 2067954076e1ed0cd0623f27d140cbea0d1f7a04 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:24:11 +0200 Subject: [PATCH 45/87] CAMEL-23789: Make IBM Secrets Manager component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../docs/ibm-secrets-manager-component.adoc | 254 +++++++++++++++++- 1 file changed, 241 insertions(+), 13 deletions(-) diff --git a/components/camel-ibm/camel-ibm-secrets-manager/src/main/docs/ibm-secrets-manager-component.adoc b/components/camel-ibm/camel-ibm-secrets-manager/src/main/docs/ibm-secrets-manager-component.adoc index a03a774b6bdf9..5cd5290dae22d 100644 --- a/components/camel-ibm/camel-ibm-secrets-manager/src/main/docs/ibm-secrets-manager-component.adoc +++ b/components/camel-ibm/camel-ibm-secrets-manager/src/main/docs/ibm-secrets-manager-component.adoc @@ -55,73 +55,301 @@ The component supports operations at the producer level. Specifically, it provid ==== Create an Arbitrary Secret +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:createArbitrarySecret") - .setHeader(IBMSecretsManagerConstants.SECRET_NAME, constant("my-secret")) + .setHeader("CamelIbmSecretsManagerSecretName", constant("my-secret")) .setBody(constant("my-secret-value")) - .to("ibm-secrets-manager://label?operation=createArbitrarySecret&token={{token}}&serviceUrl={{serviceUrl}}") + .to("ibm-secrets-manager://label?operation=createArbitrarySecret&token={{token}}&serviceUrl={{serviceUrl}}"); ---- +XML:: ++ +[source,xml] +---- + + + + my-secret + + + my-secret-value + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:createArbitrarySecret + steps: + - setHeader: + name: CamelIbmSecretsManagerSecretName + constant: my-secret + - setBody: + constant: my-secret-value + - to: + uri: ibm-secrets-manager://label + parameters: + operation: createArbitrarySecret + token: "{{token}}" + serviceUrl: "{{serviceUrl}}" +---- +==== + ==== Create a Key-Value Secret +._Java-only: requires programmatic Map construction_ + [source,java] ---- from("direct:createKVSecret") - .setHeader(IBMSecretsManagerConstants.SECRET_NAME, constant("database-creds")) + .setHeader("CamelIbmSecretsManagerSecretName", constant("database-creds")) .process(exchange -> { Map data = new HashMap<>(); data.put("username", "admin"); data.put("password", "secret123"); exchange.getMessage().setBody(data); }) - .to("ibm-secrets-manager://label?operation=createKVSecret&token={{token}}&serviceUrl={{serviceUrl}}") + .to("ibm-secrets-manager://label?operation=createKVSecret&token={{token}}&serviceUrl={{serviceUrl}}"); ---- ==== Get a Secret +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:getSecret") - .setHeader(IBMSecretsManagerConstants.SECRET_ID, constant("secret-id-here")) - .to("ibm-secrets-manager://label?operation=getSecret&token={{token}}&serviceUrl={{serviceUrl}}") + .setHeader("CamelIbmSecretsManagerSecretId", constant("secret-id-here")) + .to("ibm-secrets-manager://label?operation=getSecret&token={{token}}&serviceUrl={{serviceUrl}}"); +---- + +XML:: ++ +[source,xml] ---- + + + + secret-id-here + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:getSecret + steps: + - setHeader: + name: CamelIbmSecretsManagerSecretId + constant: secret-id-here + - to: + uri: ibm-secrets-manager://label + parameters: + operation: getSecret + token: "{{token}}" + serviceUrl: "{{serviceUrl}}" +---- +==== ==== Update a Secret +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:updateSecret") - .setHeader(IBMSecretsManagerConstants.SECRET_ID, constant("secret-id-here")) + .setHeader("CamelIbmSecretsManagerSecretId", constant("secret-id-here")) .setBody(constant("new-secret-value")) - .to("ibm-secrets-manager://label?operation=updateSecret&token={{token}}&serviceUrl={{serviceUrl}}") + .to("ibm-secrets-manager://label?operation=updateSecret&token={{token}}&serviceUrl={{serviceUrl}}"); +---- + +XML:: ++ +[source,xml] ---- + + + + secret-id-here + + + new-secret-value + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:updateSecret + steps: + - setHeader: + name: CamelIbmSecretsManagerSecretId + constant: secret-id-here + - setBody: + constant: new-secret-value + - to: + uri: ibm-secrets-manager://label + parameters: + operation: updateSecret + token: "{{token}}" + serviceUrl: "{{serviceUrl}}" +---- +==== ==== List All Secrets +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:listSecrets") - .to("ibm-secrets-manager://label?operation=listSecrets&token={{token}}&serviceUrl={{serviceUrl}}") + .to("ibm-secrets-manager://label?operation=listSecrets&token={{token}}&serviceUrl={{serviceUrl}}"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:listSecrets + steps: + - to: + uri: ibm-secrets-manager://label + parameters: + operation: listSecrets + token: "{{token}}" + serviceUrl: "{{serviceUrl}}" +---- +==== + ==== List Secret Versions +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:listSecretVersions") - .setHeader(IBMSecretsManagerConstants.SECRET_ID, constant("secret-id-here")) - .to("ibm-secrets-manager://label?operation=listSecretVersions&token={{token}}&serviceUrl={{serviceUrl}}") + .setHeader("CamelIbmSecretsManagerSecretId", constant("secret-id-here")) + .to("ibm-secrets-manager://label?operation=listSecretVersions&token={{token}}&serviceUrl={{serviceUrl}}"); ---- +XML:: ++ +[source,xml] +---- + + + + secret-id-here + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:listSecretVersions + steps: + - setHeader: + name: CamelIbmSecretsManagerSecretId + constant: secret-id-here + - to: + uri: ibm-secrets-manager://label + parameters: + operation: listSecretVersions + token: "{{token}}" + serviceUrl: "{{serviceUrl}}" +---- +==== + ==== Delete a Secret +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:deleteSecret") - .setHeader(IBMSecretsManagerConstants.SECRET_ID, constant("secret-id-here")) - .to("ibm-secrets-manager://label?operation=deleteSecret&token={{token}}&serviceUrl={{serviceUrl}}") + .setHeader("CamelIbmSecretsManagerSecretId", constant("secret-id-here")) + .to("ibm-secrets-manager://label?operation=deleteSecret&token={{token}}&serviceUrl={{serviceUrl}}"); +---- + +XML:: ++ +[source,xml] ---- + + + + secret-id-here + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:deleteSecret + steps: + - setHeader: + name: CamelIbmSecretsManagerSecretId + constant: secret-id-here + - to: + uri: ibm-secrets-manager://label + parameters: + operation: deleteSecret + token: "{{token}}" + serviceUrl: "{{serviceUrl}}" +---- +==== === Using IBM Secrets Manager Vault Property Function From 34c0fb31b2f9ce80b8ca905657d428a878684886 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:25:01 +0200 Subject: [PATCH 46/87] CAMEL-23789: Make Azure Functions component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/azure-functions-component.adoc | 261 ++++++++++++++++-- 1 file changed, 243 insertions(+), 18 deletions(-) diff --git a/components/camel-azure/camel-azure-functions/src/main/docs/azure-functions-component.adoc b/components/camel-azure/camel-azure-functions/src/main/docs/azure-functions-component.adoc index 420d681b848ef..7c748cfc20c11 100644 --- a/components/camel-azure/camel-azure-functions/src/main/docs/azure-functions-component.adoc +++ b/components/camel-azure/camel-azure-functions/src/main/docs/azure-functions-component.adoc @@ -85,36 +85,125 @@ See the documentation https://docs.microsoft.com/en-us/azure/active-directory/au For invoking HTTP-triggered functions, you can use function keys or host keys: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:invoke") .to("azure-functions:myFunctionApp/myFunction?credentialType=FUNCTION_KEY&functionKey=your-function-key"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:invoke + steps: + - to: + uri: azure-functions:myFunctionApp/myFunction + parameters: + credentialType: FUNCTION_KEY + functionKey: your-function-key +---- +==== + *TOKEN_CREDENTIAL*: Provide an implementation of `com.azure.core.credential.TokenCredential` into the Camel Registry: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:invoke") .to("azure-functions:myFunctionApp/myFunction?credentialType=TOKEN_CREDENTIAL&tokenCredential=#myCredential"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:invoke + steps: + - to: + uri: azure-functions:myFunctionApp/myFunction + parameters: + credentialType: TOKEN_CREDENTIAL + tokenCredential: "#myCredential" +---- +==== + === Service Principal Authentication For service principal authentication, provide the client credentials: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:manage") - .to("azure-functions:myFunctionApp?operation=listFunctionApps" - + "&subscriptionId=your-subscription-id" - + "&resourceGroup=your-resource-group" - + "&clientId=your-client-id" - + "&clientSecret=your-client-secret" - + "&tenantId=your-tenant-id"); + .to("azure-functions:myFunctionApp?operation=listFunctionApps&subscriptionId=your-subscription-id&resourceGroup=your-resource-group&clientId=your-client-id&clientSecret=your-client-secret&tenantId=your-tenant-id"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:manage + steps: + - to: + uri: azure-functions:myFunctionApp + parameters: + operation: listFunctionApps + subscriptionId: your-subscription-id + resourceGroup: your-resource-group + clientId: your-client-id + clientSecret: your-client-secret + tenantId: your-tenant-id ---- +==== == Operations @@ -175,6 +264,10 @@ The component supports the following operations: === Invoke a Function +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:invoke") @@ -183,49 +276,181 @@ from("direct:invoke") .log("Response: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + {"name": "World"} + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:invoke + steps: + - setBody: + constant: '{"name": "World"}' + - to: + uri: azure-functions:myFunctionApp/HelloFunction + parameters: + functionKey: your-key + - log: + message: "Response: ${body}" +---- +==== + === List Function Apps +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:list") - .to("azure-functions:myFunctionApp?operation=listFunctionApps" - + "&subscriptionId=xxx&resourceGroup=myResourceGroup") + .to("azure-functions:myFunctionApp?operation=listFunctionApps&subscriptionId=xxx&resourceGroup=myResourceGroup") .log("Function Apps: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:list + steps: + - to: + uri: azure-functions:myFunctionApp + parameters: + operation: listFunctionApps + subscriptionId: xxx + resourceGroup: myResourceGroup + - log: + message: "Function Apps: ${body}" +---- +==== + === Stop a Function App +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:stop") - .to("azure-functions:myFunctionApp?operation=stopFunctionApp" - + "&subscriptionId=xxx&resourceGroup=myResourceGroup") + .to("azure-functions:myFunctionApp?operation=stopFunctionApp&subscriptionId=xxx&resourceGroup=myResourceGroup") .log("Function App stopped"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:stop + steps: + - to: + uri: azure-functions:myFunctionApp + parameters: + operation: stopFunctionApp + subscriptionId: xxx + resourceGroup: myResourceGroup + - log: + message: "Function App stopped" +---- +==== + === Update Configuration +._Java-only: requires Java Map.of() for app settings_ + [source,java] ---- from("direct:updateConfig") .setHeader("CamelAzureFunctionsAppSettings", constant(Map.of("MY_SETTING", "value"))) - .to("azure-functions:myFunctionApp?operation=updateFunctionAppConfiguration" - + "&subscriptionId=xxx&resourceGroup=myResourceGroup") + .to("azure-functions:myFunctionApp?operation=updateFunctionAppConfiguration&subscriptionId=xxx&resourceGroup=myResourceGroup") .log("Configuration updated: ${body}"); ---- === Create a Function App +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:create") - .to("azure-functions:newFunctionApp?operation=createFunctionApp" - + "&subscriptionId=xxx" - + "&resourceGroup=myResourceGroup" - + "&location=eastus" - + "&runtime=java" - + "&storageAccountConnectionString=DefaultEndpointsProtocol=https;...") + .to("azure-functions:newFunctionApp?operation=createFunctionApp&subscriptionId=xxx&resourceGroup=myResourceGroup&location=eastus&runtime=java&storageAccountConnectionString=RAW(DefaultEndpointsProtocol=https;...)") .log("Created function app: ${header.CamelAzureFunctionsResourceId}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:create + steps: + - to: + uri: azure-functions:newFunctionApp + parameters: + operation: createFunctionApp + subscriptionId: xxx + resourceGroup: myResourceGroup + location: eastus + runtime: java + storageAccountConnectionString: "RAW(DefaultEndpointsProtocol=https;...)" + - log: + message: "Created function app: ${header.CamelAzureFunctionsResourceId}" +---- +==== + include::spring-boot:partial$starter.adoc[] From bf95ddac1aac47e2606e4d175c9e17fee52e5df7 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:27:35 +0200 Subject: [PATCH 47/87] CAMEL-23789: Make Google VertexAI component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/google-vertexai-component.adoc | 350 ++++++++++++++++-- 1 file changed, 326 insertions(+), 24 deletions(-) diff --git a/components/camel-google/camel-google-vertexai/src/main/docs/google-vertexai-component.adoc b/components/camel-google/camel-google-vertexai/src/main/docs/google-vertexai-component.adoc index f61d348762fd5..59c5216685586 100644 --- a/components/camel-google/camel-google-vertexai/src/main/docs/google-vertexai-component.adoc +++ b/components/camel-google/camel-google-vertexai/src/main/docs/google-vertexai-component.adoc @@ -115,6 +115,10 @@ Partner models require the `publisher` parameter: `anthropic`, `meta`, or `mistr === Text Generation with Gemini +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:prompt") @@ -123,99 +127,398 @@ from("direct:prompt") .log("${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + Explain quantum computing briefly + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:prompt + steps: + - setBody: + constant: Explain quantum computing briefly + - to: + uri: google-vertexai:my-project:us-central1:gemini-2.0-flash + - log: + message: "${body}" +---- +==== + === Using a Service Account +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:prompt") - .to("google-vertexai:my-project:us-central1:gemini-2.0-flash" - + "?serviceAccountKey=file:/path/to/key.json") + .to("google-vertexai:my-project:us-central1:gemini-2.0-flash?serviceAccountKey=file:/path/to/key.json") .log("${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:prompt + steps: + - to: + uri: google-vertexai:my-project:us-central1:gemini-2.0-flash + parameters: + serviceAccountKey: "file:/path/to/key.json" + - log: + message: "${body}" +---- +==== + === Calling Claude with rawPredict +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:claude") .setBody(constant("What is Apache Camel?")) - .to("google-vertexai:my-project:us-east5:claude-sonnet-4@20250514" - + "?operation=rawPredict&publisher=anthropic") + .to("google-vertexai:my-project:us-east5:claude-sonnet-4@20250514?operation=rawPredict&publisher=anthropic") .log("${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + What is Apache Camel? + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:claude + steps: + - setBody: + constant: What is Apache Camel? + - to: + uri: "google-vertexai:my-project:us-east5:claude-sonnet-4@20250514" + parameters: + operation: rawPredict + publisher: anthropic + - log: + message: "${body}" +---- +==== + The component automatically wraps simple text prompts in the required Anthropic format. === Streaming Chat with Gemini +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:streaming") .setBody(constant("Tell me a story")) - .to("google-vertexai:my-project:us-central1:gemini-2.0-flash" - + "?operation=generateChatStreaming&maxOutputTokens=512") + .to("google-vertexai:my-project:us-central1:gemini-2.0-flash?operation=generateChatStreaming&maxOutputTokens=512") .log("Response: ${body}, Chunks: ${header.CamelGoogleVertexAIChunkCount}"); ---- +XML:: ++ +[source,xml] +---- + + + + Tell me a story + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:streaming + steps: + - setBody: + constant: Tell me a story + - to: + uri: google-vertexai:my-project:us-central1:gemini-2.0-flash + parameters: + operation: generateChatStreaming + maxOutputTokens: 512 + - log: + message: "Response: ${body}, Chunks: ${header.CamelGoogleVertexAIChunkCount}" +---- +==== + === Image Generation with Imagen +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:image") .setBody(constant("A sunset over mountains")) - .setHeader(GoogleVertexAIConstants.IMAGE_NUMBER_OF_IMAGES, constant(1)) - .to("google-vertexai:my-project:us-central1:imagen-3.0-generate-002" - + "?operation=generateImage") + .setHeader("CamelGoogleVertexAIImageNumberOfImages", constant(1)) + .to("google-vertexai:my-project:us-central1:imagen-3.0-generate-002?operation=generateImage") .log("Generated ${body.size()} image(s)"); ---- +XML:: ++ +[source,xml] +---- + + + + A sunset over mountains + + + 1 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:image + steps: + - setBody: + constant: A sunset over mountains + - setHeader: + name: CamelGoogleVertexAIImageNumberOfImages + constant: 1 + - to: + uri: google-vertexai:my-project:us-central1:imagen-3.0-generate-002 + parameters: + operation: generateImage + - log: + message: "Generated ${body.size()} image(s)" +---- +==== + The body will contain a `List` with the generated images. Each `Image` has `imageBytes()` and `mimeType()` methods. === Text Embeddings +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:embed") .setBody(constant("Apache Camel is an integration framework")) - .to("google-vertexai:my-project:us-central1:text-embedding-005" - + "?operation=generateEmbeddings") + .to("google-vertexai:my-project:us-central1:text-embedding-005?operation=generateEmbeddings") .log("Embedding dimensions: ${body[0].size()}"); ---- +XML:: ++ +[source,xml] +---- + + + + Apache Camel is an integration framework + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:embed + steps: + - setBody: + constant: Apache Camel is an integration framework + - to: + uri: google-vertexai:my-project:us-central1:text-embedding-005 + parameters: + operation: generateEmbeddings + - log: + message: "Embedding dimensions: ${body[0].size()}" +---- +==== + The body will contain a `List>` — one embedding vector per input text. For batch embeddings, pass a `List` as the body. === Multimodal Input (Image + Text) +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:multimodal") - .process(exchange -> { - exchange.getMessage().setHeader(GoogleVertexAIConstants.PROMPT, "Describe this image"); - exchange.getMessage().setHeader(GoogleVertexAIConstants.MEDIA_GCS_URI, - "gs://my-bucket/photo.jpg"); - exchange.getMessage().setHeader(GoogleVertexAIConstants.MEDIA_MIME_TYPE, "image/jpeg"); - }) - .to("google-vertexai:my-project:us-central1:gemini-2.0-flash" - + "?operation=generateMultimodal") + .setHeader("CamelGoogleVertexAIPrompt", constant("Describe this image")) + .setHeader("CamelGoogleVertexAIMediaGcsUri", constant("gs://my-bucket/photo.jpg")) + .setHeader("CamelGoogleVertexAIMediaMimeType", constant("image/jpeg")) + .to("google-vertexai:my-project:us-central1:gemini-2.0-flash?operation=generateMultimodal") .log("${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + Describe this image + + + gs://my-bucket/photo.jpg + + + image/jpeg + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:multimodal + steps: + - setHeader: + name: CamelGoogleVertexAIPrompt + constant: Describe this image + - setHeader: + name: CamelGoogleVertexAIMediaGcsUri + constant: "gs://my-bucket/photo.jpg" + - setHeader: + name: CamelGoogleVertexAIMediaMimeType + constant: image/jpeg + - to: + uri: google-vertexai:my-project:us-central1:gemini-2.0-flash + parameters: + operation: generateMultimodal + - log: + message: "${body}" +---- +==== + You can also pass inline image bytes via the `CamelGoogleVertexAIMediaData` header instead of a GCS URI. === Streaming Claude with streamRawPredict +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:stream-claude") .setBody(constant("What is Apache Camel?")) - .to("google-vertexai:my-project:us-east5:claude-sonnet-4@20250514" - + "?operation=streamRawPredict&publisher=anthropic") + .to("google-vertexai:my-project:us-east5:claude-sonnet-4@20250514?operation=streamRawPredict&publisher=anthropic") .log("${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + What is Apache Camel? + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:stream-claude + steps: + - setBody: + constant: What is Apache Camel? + - to: + uri: "google-vertexai:my-project:us-east5:claude-sonnet-4@20250514" + parameters: + operation: streamRawPredict + publisher: anthropic + - log: + message: "${body}" +---- +==== + === Claude with Custom Request -For more control, pass a JSON or Map body: +For more control, pass a JSON body: + +._Java-only: requires Java text block for JSON request body_ [source,java] ---- @@ -230,8 +533,7 @@ from("direct:claude") """; exchange.getMessage().setBody(json); }) - .to("google-vertexai:my-project:us-east5:claude-sonnet-4@20250514" - + "?operation=rawPredict&publisher=anthropic") + .to("google-vertexai:my-project:us-east5:claude-sonnet-4@20250514?operation=rawPredict&publisher=anthropic") .log("${body}"); ---- From 62f4071d0a5426b81d60cfb424f2464f778f246b Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:38:17 +0200 Subject: [PATCH 48/87] CAMEL-23789: Make TensorFlow Serving, IBM Watson TTS and STT component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../docs/tensorflow-serving-component.adoc | 190 ++++++++++++- .../ibm-watson-speech-to-text-component.adoc | 202 +++++++++++--- .../ibm-watson-text-to-speech-component.adoc | 261 ++++++++++++++++-- 3 files changed, 580 insertions(+), 73 deletions(-) diff --git a/components/camel-ai/camel-tensorflow-serving/src/main/docs/tensorflow-serving-component.adoc b/components/camel-ai/camel-tensorflow-serving/src/main/docs/tensorflow-serving-component.adoc index 106a0eb35a63f..5c293c9f7c7b1 100644 --- a/components/camel-ai/camel-tensorflow-serving/src/main/docs/tensorflow-serving-component.adoc +++ b/components/camel-ai/camel-tensorflow-serving/src/main/docs/tensorflow-serving-component.adoc @@ -108,6 +108,11 @@ tensorflow-serving:[?options] === Model status API .Check model status + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:model-status") @@ -115,22 +120,99 @@ from("direct:model-status") .log("Status: ${body.getModelVersionStatus(0).state}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:model-status + steps: + - to: + uri: tensorflow-serving:model-status + parameters: + modelName: half_plus_two + modelVersion: 123 + - log: + message: "Status: ${body.getModelVersionStatus(0).state}" +---- +==== + .Specify the model name and version with headers + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:model-status-with-headers") - .setHeader(TensorFlowServingConstants.MODEL_NAME, constant("half_plus_two")) - .setHeader(TensorFlowServingConstants.MODEL_VERSION, constant(123)) + .setHeader("CamelTensorFlowServingModelName", constant("half_plus_two")) + .setHeader("CamelTensorFlowServingModelVersion", constant(123)) .to("tensorflow-serving:model-status") .log("Status: ${body.getModelVersionStatus(0).state}"); ---- +XML:: ++ +[source,xml] +---- + + + + half_plus_two + + + 123 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:model-status-with-headers + steps: + - setHeader: + name: CamelTensorFlowServingModelName + constant: half_plus_two + - setHeader: + name: CamelTensorFlowServingModelVersion + constant: 123 + - to: + uri: tensorflow-serving:model-status + - log: + message: "Status: ${body.getModelVersionStatus(0).state}" +---- +==== + === Model Metadata API Currently, TensorFlow Serving only supports `signature_def` as the metadata field. See: https://github.com/tensorflow/serving/blob/2.18.0/tensorflow_serving/apis/get_model_metadata.proto#L26-L28[get_model_metadata.proto] .Fetch model metadata + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:model-metadata") @@ -138,20 +220,94 @@ from("direct:model-metadata") .log("Metadata: ${body.getMetadataOrThrow('signature_def')}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:model-metadata + steps: + - to: + uri: tensorflow-serving:model-metadata + parameters: + modelName: half_plus_two + modelVersion: 123 + - log: + message: "Metadata: ${body.getMetadataOrThrow('signature_def')}" +---- +==== + .Specify the model name and version with headers + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:model-metadata-with-headers") - .setHeader(TensorFlowServingConstants.MODEL_NAME, constant("half_plus_two")) - .setHeader(TensorFlowServingConstants.MODEL_VERSION, constant(123)) + .setHeader("CamelTensorFlowServingModelName", constant("half_plus_two")) + .setHeader("CamelTensorFlowServingModelVersion", constant(123)) .to("tensorflow-serving:model-metadata") .log("Metadata: ${body.getMetadataOrThrow('signature_def')}"); ---- +XML:: ++ +[source,xml] +---- + + + + half_plus_two + + + 123 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:model-metadata-with-headers + steps: + - setHeader: + name: CamelTensorFlowServingModelName + constant: half_plus_two + - setHeader: + name: CamelTensorFlowServingModelVersion + constant: 123 + - to: + uri: tensorflow-serving:model-metadata + - log: + message: "Metadata: ${body.getMetadataOrThrow('signature_def')}" +---- +==== + === Classify API The signature name should be resolved by looking up <>. +._Java-only: requires TensorFlow protobuf Input builder_ + .Classify [source,java] ---- @@ -168,6 +324,8 @@ from("direct:classify") .log("Result: ${body.result.getClassifications(0).getClasses(0).score}"); ---- +._Java-only: requires TensorFlow protobuf Input builder with header overrides_ + .Specify the model and signature name with headers [source,java] ---- @@ -180,9 +338,9 @@ from("direct:classify-with-headers") .setFloatList(FloatList.newBuilder().addValue(1.0f)) .build())))) .build())) - .setHeader(TensorFlowServingConstants.MODEL_NAME, constant("half_plus_two")) - .setHeader(TensorFlowServingConstants.MODEL_VERSION, constant(123)) - .setHeader(TensorFlowServingConstants.SIGNATURE_NAME, constant("classify_x_to_y")) + .setHeader("CamelTensorFlowServingModelName", constant("half_plus_two")) + .setHeader("CamelTensorFlowServingModelVersion", constant(123)) + .setHeader("CamelTensorFlowServingSignatureName", constant("classify_x_to_y")) .to("tensorflow-serving:classify") .log("Result: ${body.result.getClassifications(0).getClasses(0).score}"); ---- @@ -191,6 +349,8 @@ from("direct:classify-with-headers") The signature name should be resolved by looking up <>. +._Java-only: requires TensorFlow protobuf Input builder_ + .Regress [source,java] ---- @@ -207,6 +367,8 @@ from("direct:regress") .log("Result: ${body.result.getRegressions(0).value}"); ---- +._Java-only: requires TensorFlow protobuf Input builder with header overrides_ + .Specify the model and signature name with headers [source,java] ---- @@ -219,9 +381,9 @@ from("direct:regress-with-headers") .setFloatList(FloatList.newBuilder().addValue(1.0f)) .build())))) .build())) - .setHeader(TensorFlowServingConstants.MODEL_NAME, constant("half_plus_two")) - .setHeader(TensorFlowServingConstants.MODEL_VERSION, constant(123)) - .setHeader(TensorFlowServingConstants.SIGNATURE_NAME, constant("regress_x_to_y")) + .setHeader("CamelTensorFlowServingModelName", constant("half_plus_two")) + .setHeader("CamelTensorFlowServingModelVersion", constant(123)) + .setHeader("CamelTensorFlowServingSignatureName", constant("regress_x_to_y")) .to("tensorflow-serving:regress") .log("Result: ${body.result.getRegressions(0).value}"); ---- @@ -230,6 +392,8 @@ from("direct:regress-with-headers") The labels of inputs (`x`) and outputs (`y`) should be resolved by looking up <>. +._Java-only: requires TensorFlow protobuf PredictRequest builder_ + .Predict [source,java] ---- @@ -250,6 +414,8 @@ from("direct:predict") .log("Result3: ${body.getOutputsOrThrow('y').getFloatVal(2)}"); ---- +._Java-only: requires TensorFlow protobuf PredictRequest builder with header overrides_ + .Specify the model name and version with headers [source,java] ---- @@ -264,8 +430,8 @@ from("direct:predict-with-headers") .addFloatVal(5.0f) .build()) .build())) - .setHeader(TensorFlowServingConstants.MODEL_NAME, constant("half_plus_two")) - .setHeader(TensorFlowServingConstants.MODEL_VERSION, constant(123)) + .setHeader("CamelTensorFlowServingModelName", constant("half_plus_two")) + .setHeader("CamelTensorFlowServingModelVersion", constant(123)) .to("tensorflow-serving:predict") .log("Result1: ${body.getOutputsOrThrow('y').getFloatVal(0)}") .log("Result2: ${body.getOutputsOrThrow('y').getFloatVal(1)}") diff --git a/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/docs/ibm-watson-speech-to-text-component.adoc b/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/docs/ibm-watson-speech-to-text-component.adoc index 4688128fbd614..c571de13be826 100644 --- a/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/docs/ibm-watson-speech-to-text-component.adoc +++ b/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/docs/ibm-watson-speech-to-text-component.adoc @@ -64,15 +64,48 @@ If you don't specify an operation explicitly, you must set it via the `operation Transcribe a WAV audio file to text: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("file:/var/audio?noop=true") .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=recognize&contentType=audio/wav") - .process(exchange -> { - String transcript = exchange.getMessage().getHeader(WatsonSpeechToTextConstants.TRANSCRIPT, String.class); - System.out.println("Transcription: " + transcript); - }); --------------------------------------------------------------------------------- + .log("Transcription: ${header.CamelIBMWatsonSTTTranscript}"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:/var/audio + parameters: + noop: true + steps: + - to: + uri: ibm-watson-speech-to-text:mySTT + parameters: + apiKey: "RAW(yourApiKey)" + operation: recognize + contentType: audio/wav + - log: + message: "Transcription: ${header.CamelIBMWatsonSTTTranscript}" +---- +==== This will transcribe the audio file and extract the text. @@ -80,11 +113,13 @@ This will transcribe the audio file and extract the text. Transcribe audio and get word-level timestamps: +._Java-only: requires File object and processes typed SpeechRecognitionResults SDK object_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .setHeader(WatsonSpeechToTextConstants.AUDIO_FILE, constant(new File("/path/to/audio.wav"))) - .setHeader(WatsonSpeechToTextConstants.TIMESTAMPS, constant(true)) + .setHeader("CamelIBMWatsonSTTAudioFile", constant(new File("/path/to/audio.wav"))) + .setHeader("CamelIBMWatsonSTTTimestamps", constant(true)) .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=recognize") .process(exchange -> { SpeechRecognitionResults results = exchange.getMessage().getBody(SpeechRecognitionResults.class); @@ -98,18 +133,20 @@ from("direct:start") }); }); }); --------------------------------------------------------------------------------- +---- === Recognize with Word Confidence Get confidence scores for each transcribed word: +._Java-only: requires Java variable and processes typed SpeechRecognitionResults SDK object_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant(audioInputStream)) - .setHeader(WatsonSpeechToTextConstants.WORD_CONFIDENCE, constant(true)) - .setHeader(WatsonSpeechToTextConstants.CONTENT_TYPE, constant("audio/mp3")) + .setHeader("CamelIBMWatsonSTTWordConfidence", constant(true)) + .setHeader("CamelIBMWatsonSTTContentType", constant("audio/mp3")) .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=recognize") .process(exchange -> { SpeechRecognitionResults results = exchange.getMessage().getBody(SpeechRecognitionResults.class); @@ -122,7 +159,7 @@ from("direct:start") }); }); }); --------------------------------------------------------------------------------- +---- === Available Language Models @@ -161,8 +198,10 @@ Some commonly used models include: Get a list of all available language models: +._Java-only: processes typed SpeechModel SDK objects_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:listModels") .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=listModels") .process(exchange -> { @@ -173,22 +212,24 @@ from("direct:listModels") " - Description: " + model.getDescription()); }); }); --------------------------------------------------------------------------------- +---- === Get Model Information Get detailed information about a specific model: +._Java-only: processes typed SpeechModel SDK object_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:getModel") - .setHeader(WatsonSpeechToTextConstants.MODEL_NAME, constant("en-US_BroadbandModel")) + .setHeader("CamelIBMWatsonSTTModelName", constant("en-US_BroadbandModel")) .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=getModel") .process(exchange -> { SpeechModel model = exchange.getMessage().getBody(SpeechModel.class); System.out.println("Model details: " + model); }); --------------------------------------------------------------------------------- +---- === Audio Format Options @@ -202,23 +243,61 @@ The component supports various audio formats via the `contentType` parameter: Example with MP3 input: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("file:/var/audio?include=.*\\.mp3") .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=recognize&contentType=audio/mp3") .log("Transcript: ${header.CamelIBMWatsonSTTTranscript}"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:/var/audio + parameters: + include: ".*\\.mp3" + steps: + - to: + uri: ibm-watson-speech-to-text:mySTT + parameters: + apiKey: "RAW(yourApiKey)" + operation: recognize + contentType: audio/mp3 + - log: + message: "Transcript: ${header.CamelIBMWatsonSTTTranscript}" +---- +==== === Recognize Different Languages Transcribe audio in different languages by specifying the appropriate model: +._Java-only: requires Java audio file variables_ + [source,java] --------------------------------------------------------------------------------- +---- // Transcribe Spanish audio from("direct:spanish") .setBody(constant(spanishAudioFile)) - .setHeader(WatsonSpeechToTextConstants.MODEL, constant("es-ES_BroadbandModel")) + .setHeader("CamelIBMWatsonSTTModel", constant("es-ES_BroadbandModel")) .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=recognize") .log("Spanish transcript: ${header.CamelIBMWatsonSTTTranscript}"); @@ -227,17 +306,19 @@ from("direct:french") .setBody(constant(frenchAudioFile)) .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=recognize&model=fr-FR_BroadbandModel") .log("French transcript: ${header.CamelIBMWatsonSTTTranscript}"); --------------------------------------------------------------------------------- +---- === Speaker Identification Identify different speakers in multi-speaker audio: +._Java-only: processes typed SpeechRecognitionResults SDK object_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:speakers") - .setHeader(WatsonSpeechToTextConstants.SPEAKER_LABELS, constant(true)) - .setHeader(WatsonSpeechToTextConstants.TIMESTAMPS, constant(true)) + .setHeader("CamelIBMWatsonSTTSpeakerLabels", constant(true)) + .setHeader("CamelIBMWatsonSTTTimestamps", constant(true)) .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=recognize") .process(exchange -> { SpeechRecognitionResults results = exchange.getMessage().getBody(SpeechRecognitionResults.class); @@ -248,26 +329,67 @@ from("direct:speakers") ": " + label.getFinal()); }); }); --------------------------------------------------------------------------------- +---- === Using Custom Language Models If you have created a custom language model, you can use it for recognition: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:customModel") - .setHeader(WatsonSpeechToTextConstants.MODEL, constant("your-custom-model-guid")) + .setHeader("CamelIBMWatsonSTTModel", constant("your-custom-model-guid")) .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=recognize") .log("Custom model transcript: ${header.CamelIBMWatsonSTTTranscript}"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + your-custom-model-guid + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:customModel + steps: + - setHeader: + name: CamelIBMWatsonSTTModel + constant: your-custom-model-guid + - to: + uri: ibm-watson-speech-to-text:mySTT + parameters: + apiKey: "RAW(yourApiKey)" + operation: recognize + - log: + message: "Custom model transcript: ${header.CamelIBMWatsonSTTTranscript}" +---- +==== === List Custom Models List all your custom language models: +._Java-only: processes typed LanguageModel SDK objects_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:listCustomModels") .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=listCustomModels") .process(exchange -> { @@ -279,16 +401,18 @@ from("direct:listCustomModels") " - Status: " + model.getStatus()); }); }); --------------------------------------------------------------------------------- +---- === Get Custom Model Details Get detailed information about a custom model: +._Java-only: processes typed LanguageModel SDK object_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:getCustomModel") - .setHeader(WatsonSpeechToTextConstants.MODEL_NAME, constant("your-custom-model-guid")) + .setHeader("CamelIBMWatsonSTTModelName", constant("your-custom-model-guid")) .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&operation=getCustomModel") .process(exchange -> { LanguageModel model = exchange.getMessage().getBody(LanguageModel.class); @@ -296,7 +420,7 @@ from("direct:getCustomModel") " - Status: " + model.getStatus() + " - Progress: " + model.getProgress() + "%"); }); --------------------------------------------------------------------------------- +---- === Watson Speech to Text Authentication @@ -315,13 +439,15 @@ https://cloud.ibm.com/docs/speech-to-text?topic=speech-to-text-getting-started[I If you have a dedicated or regional instance, you can specify a custom service URL: +._Java-only: requires Java audio file variable_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant(audioFile)) .to("ibm-watson-speech-to-text:mySTT?apiKey=RAW(yourApiKey)&serviceUrl=https://api.eu-gb.speech-to-text.watson.cloud.ibm.com&operation=recognize") .log("Transcript: ${header.CamelIBMWatsonSTTTranscript}"); --------------------------------------------------------------------------------- +---- Common regional endpoints: - Dallas: https://api.us-south.speech-to-text.watson.cloud.ibm.com diff --git a/components/camel-ibm/camel-ibm-watson-text-to-speech/src/main/docs/ibm-watson-text-to-speech-component.adoc b/components/camel-ibm/camel-ibm-watson-text-to-speech/src/main/docs/ibm-watson-text-to-speech-component.adoc index 9f48d26c61e18..11d6f5af0dc83 100644 --- a/components/camel-ibm/camel-ibm-watson-text-to-speech/src/main/docs/ibm-watson-text-to-speech-component.adoc +++ b/components/camel-ibm/camel-ibm-watson-text-to-speech/src/main/docs/ibm-watson-text-to-speech-component.adoc @@ -65,13 +65,54 @@ If you don't specify an operation explicitly, you must set it via the `operation Convert text to speech using the default voice: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .setHeader(WatsonTextToSpeechConstants.TEXT, constant("Hello, welcome to IBM Watson Text to Speech!")) + .setHeader("CamelIBMWatsonTTSText", constant("Hello, welcome to IBM Watson Text to Speech!")) .to("ibm-watson-text-to-speech:myTTS?apiKey=RAW(yourApiKey)&operation=synthesize") .to("file:/var/audio?fileName=output.wav"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + Hello, welcome to IBM Watson Text to Speech! + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelIBMWatsonTTSText + constant: "Hello, welcome to IBM Watson Text to Speech!" + - to: + uri: ibm-watson-text-to-speech:myTTS + parameters: + apiKey: "RAW(yourApiKey)" + operation: synthesize + - to: + uri: file:/var/audio + parameters: + fileName: output.wav +---- +==== This will synthesize the text and produce an audio WAV file. @@ -79,13 +120,55 @@ This will synthesize the text and produce an audio WAV file. Convert text to speech using a specific voice: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant("Bonjour, bienvenue sur IBM Watson!")) .to("ibm-watson-text-to-speech:myTTS?apiKey=RAW(yourApiKey)&operation=synthesize&voice=fr-FR_NicolasV3Voice&accept=audio/mp3") .to("file:/var/audio?fileName=output.mp3"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + Bonjour, bienvenue sur IBM Watson! + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: "Bonjour, bienvenue sur IBM Watson!" + - to: + uri: ibm-watson-text-to-speech:myTTS + parameters: + apiKey: "RAW(yourApiKey)" + operation: synthesize + voice: fr-FR_NicolasV3Voice + accept: audio/mp3 + - to: + uri: file:/var/audio + parameters: + fileName: output.mp3 +---- +==== This will synthesize French text using the Nicolas voice and produce an MP3 file. @@ -106,8 +189,10 @@ Some commonly used voices include: Get a list of all available voices: +._Java-only: processes typed Voice SDK objects_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:listVoices") .to("ibm-watson-text-to-speech:myTTS?apiKey=RAW(yourApiKey)&operation=listVoices") .process(exchange -> { @@ -118,22 +203,24 @@ from("direct:listVoices") " - Description: " + voice.getDescription()); }); }); --------------------------------------------------------------------------------- +---- === Get Voice Information Get detailed information about a specific voice: +._Java-only: processes typed Voice SDK object_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:getVoice") - .setHeader(WatsonTextToSpeechConstants.VOICE_NAME, constant("en-US_AllisonV3Voice")) + .setHeader("CamelIBMWatsonTTSVoiceName", constant("en-US_AllisonV3Voice")) .to("ibm-watson-text-to-speech:myTTS?apiKey=RAW(yourApiKey)&operation=getVoice") .process(exchange -> { Voice voice = exchange.getMessage().getBody(Voice.class); System.out.println("Voice details: " + voice); }); --------------------------------------------------------------------------------- +---- === Audio Format Options @@ -147,33 +234,120 @@ The component supports various audio formats via the `accept` parameter: Example with MP3 output: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:mp3") .setBody(constant("This will be an MP3 file")) .to("ibm-watson-text-to-speech:myTTS?apiKey=RAW(yourApiKey)&operation=synthesize&accept=audio/mp3") .to("file:/var/audio?fileName=speech.mp3"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + This will be an MP3 file + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:mp3 + steps: + - setBody: + constant: This will be an MP3 file + - to: + uri: ibm-watson-text-to-speech:myTTS + parameters: + apiKey: "RAW(yourApiKey)" + operation: synthesize + accept: audio/mp3 + - to: + uri: file:/var/audio + parameters: + fileName: speech.mp3 +---- +==== === Using Custom Voice Models If you have created a custom voice model, you can use it for synthesis: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:customVoice") .setBody(constant("Text to synthesize with custom voice")) - .setHeader(WatsonTextToSpeechConstants.CUSTOMIZATION_ID, constant("your-customization-guid")) + .setHeader("CamelIBMWatsonTTSCustomizationId", constant("your-customization-guid")) .to("ibm-watson-text-to-speech:myTTS?apiKey=RAW(yourApiKey)&operation=synthesize") .to("file:/var/audio"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + Text to synthesize with custom voice + + + your-customization-guid + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:customVoice + steps: + - setBody: + constant: Text to synthesize with custom voice + - setHeader: + name: CamelIBMWatsonTTSCustomizationId + constant: your-customization-guid + - to: + uri: ibm-watson-text-to-speech:myTTS + parameters: + apiKey: "RAW(yourApiKey)" + operation: synthesize + - to: + uri: file:/var/audio +---- +==== === List Custom Models List all your custom voice models: +._Java-only: processes typed CustomModel SDK objects_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:listCustomModels") .to("ibm-watson-text-to-speech:myTTS?apiKey=RAW(yourApiKey)&operation=listCustomModels") .process(exchange -> { @@ -184,23 +358,25 @@ from("direct:listCustomModels") " - Language: " + model.getLanguage()); }); }); --------------------------------------------------------------------------------- +---- === Get Pronunciation Get the pronunciation for a specific word: +._Java-only: processes typed Pronunciation SDK object_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:pronunciation") - .setHeader(WatsonTextToSpeechConstants.WORD, constant("synthesize")) - .setHeader(WatsonTextToSpeechConstants.FORMAT, constant("ipa")) + .setHeader("CamelIBMWatsonTTSWord", constant("synthesize")) + .setHeader("CamelIBMWatsonTTSFormat", constant("ipa")) .to("ibm-watson-text-to-speech:myTTS?apiKey=RAW(yourApiKey)&operation=getPronunciation") .process(exchange -> { Pronunciation pronunciation = exchange.getMessage().getBody(Pronunciation.class); System.out.println("IPA Pronunciation: " + pronunciation.getPronunciation()); }); --------------------------------------------------------------------------------- +---- === Watson Text to Speech Authentication @@ -219,13 +395,52 @@ https://cloud.ibm.com/docs/text-to-speech?topic=text-to-speech-getting-started[I If you have a dedicated or regional instance, you can specify a custom service URL: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setBody(constant("Hello World")) .to("ibm-watson-text-to-speech:myTTS?apiKey=RAW(yourApiKey)&serviceUrl=https://api.eu-gb.text-to-speech.watson.cloud.ibm.com&operation=synthesize") .to("file:/var/audio"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + Hello World + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: Hello World + - to: + uri: ibm-watson-text-to-speech:myTTS + parameters: + apiKey: "RAW(yourApiKey)" + serviceUrl: "https://api.eu-gb.text-to-speech.watson.cloud.ibm.com" + operation: synthesize + - to: + uri: file:/var/audio +---- +==== Common regional endpoints: - Dallas: https://api.us-south.text-to-speech.watson.cloud.ibm.com From 9187f70769b7e0edb3b758064a9bdc5ae245de7a Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:39:48 +0200 Subject: [PATCH 49/87] CAMEL-23789: Make KServe and SFTP component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/kserve-component.adoc | 263 +++++++++++++++++- .../src/main/docs/sftp-component.adoc | 185 ++++++++++-- 2 files changed, 419 insertions(+), 29 deletions(-) diff --git a/components/camel-ai/camel-kserve/src/main/docs/kserve-component.adoc b/components/camel-ai/camel-kserve/src/main/docs/kserve-component.adoc index 6c6c550ee8a0a..1625610f90c69 100644 --- a/components/camel-ai/camel-kserve/src/main/docs/kserve-component.adoc +++ b/components/camel-ai/camel-kserve/src/main/docs/kserve-component.adoc @@ -103,6 +103,8 @@ kserve:[?options] === Infer (ModelInfer) API +._Java-only: requires protobuf ModelInferRequest builder and response post-processing_ + .Perform inference [source,java] ---- @@ -145,13 +147,15 @@ void postprocess(Exchange exchange) { } ---- +._Java-only: requires protobuf ModelInferRequest builder with header overrides_ + .Specify the model name and version with headers [source,java] ---- from("direct:infer-with-headers") .setBody(constant(createRequest())) - .setHeader(KServeConstants.MODEL_NAME, constant("simple")) - .setHeader(KServeConstants.MODEL_VERSION, constant("1")) + .setHeader("CamelKServeModelName", constant("simple")) + .setHeader("CamelKServeModelVersion", constant("1")) .to("kserve:infer") .process(this::postprocess) .log("Result: ${body}"); @@ -162,6 +166,11 @@ from("direct:infer-with-headers") === ModelReady API .Check if a model is ready + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:model-ready") @@ -169,19 +178,96 @@ from("direct:model-ready") .log("Status: ${body.ready}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:model-ready + steps: + - to: + uri: kserve:model/ready + parameters: + modelName: simple + modelVersion: 1 + - log: + message: "Status: ${body.ready}" +---- +==== + .Specify the model name and version with headers + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:model-ready-with-headers") - .setHeader(KServeConstants.MODEL_NAME, constant("simple")) - .setHeader(KServeConstants.MODEL_VERSION, constant("1")) + .setHeader("CamelKServeModelName", constant("simple")) + .setHeader("CamelKServeModelVersion", constant("1")) .to("kserve:model/ready") .log("Status: ${body.ready}"); ---- +XML:: ++ +[source,xml] +---- + + + + simple + + + 1 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:model-ready-with-headers + steps: + - setHeader: + name: CamelKServeModelName + constant: simple + - setHeader: + name: CamelKServeModelVersion + constant: "1" + - to: + uri: kserve:model/ready + - log: + message: "Status: ${body.ready}" +---- +==== + === ModelMetadata API .Fetch model metadata + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:model-metadata") @@ -189,19 +275,96 @@ from("direct:model-metadata") .log("Metadata: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:model-metadata + steps: + - to: + uri: kserve:model/metadata + parameters: + modelName: simple + modelVersion: 1 + - log: + message: "Metadata: ${body}" +---- +==== + .Specify the model name and version with headers + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:model-metadata-with-headers") - .setHeader(KServeConstants.MODEL_NAME, constant("simple")) - .setHeader(KServeConstants.MODEL_VERSION, constant("1")) + .setHeader("CamelKServeModelName", constant("simple")) + .setHeader("CamelKServeModelVersion", constant("1")) .to("kserve:model/metadata") .log("Metadata: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + simple + + + 1 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:model-metadata-with-headers + steps: + - setHeader: + name: CamelKServeModelName + constant: simple + - setHeader: + name: CamelKServeModelVersion + constant: "1" + - to: + uri: kserve:model/metadata + - log: + message: "Metadata: ${body}" +---- +==== + === ServerReady API .Check if the server is ready + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:server-ready") @@ -209,9 +372,40 @@ from("direct:server-ready") .log("Status: ${body.ready}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:server-ready + steps: + - to: + uri: kserve:server/ready + - log: + message: "Status: ${body.ready}" +---- +==== + === ServerLive API .Check if the server is live + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:server-live") @@ -219,9 +413,40 @@ from("direct:server-live") .log("Status: ${body.live}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:server-live + steps: + - to: + uri: kserve:server/live + - log: + message: "Status: ${body.live}" +---- +==== + === ServerMetadata API .Fetch server metadata + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:server-metadata") @@ -229,4 +454,30 @@ from("direct:server-metadata") .log("Metadata: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:server-metadata + steps: + - to: + uri: kserve:server/metadata + - log: + message: "Metadata: ${body}" +---- +==== + include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-ftp/src/main/docs/sftp-component.adoc b/components/camel-ftp/src/main/docs/sftp-component.adoc index 73506836b7aa1..74ad967b1f3c5 100644 --- a/components/camel-ftp/src/main/docs/sftp-component.adoc +++ b/components/camel-ftp/src/main/docs/sftp-component.adoc @@ -77,40 +77,123 @@ Endpoint-level configurations will override component-level settings. This allow To enable strict host key checking at the endpoint level, set `strictHostKeyChecking=yes` and provide a known hosts file: +[tabs] +==== +Java:: ++ [source,java] ---- -from("sftp://host:22/path" - + "?username=myuser" - + "&password=secret" - + "&knownHostsFile=/path/to/known_hosts" - + "&strictHostKeyChecking=yes") +from("sftp://host:22/path?username=myuser&password=secret&knownHostsFile=/path/to/known_hosts&strictHostKeyChecking=yes") .to("direct:result"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: sftp://host:22/path + parameters: + username: myuser + password: secret + knownHostsFile: /path/to/known_hosts + strictHostKeyChecking: "yes" + steps: + - to: + uri: direct:result +---- +==== + Alternatively, load the known hosts from the classpath: +[tabs] +==== +Java:: ++ [source,java] ---- -from("sftp://host:22/path" - + "?username=myuser" - + "&privateKeyFile=/path/to/id_rsa" - + "&knownHostsUri=classpath:known_hosts" - + "&strictHostKeyChecking=yes") +from("sftp://host:22/path?username=myuser&privateKeyFile=/path/to/id_rsa&knownHostsUri=classpath:known_hosts&strictHostKeyChecking=yes") .to("direct:result"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: sftp://host:22/path + parameters: + username: myuser + privateKeyFile: /path/to/id_rsa + knownHostsUri: "classpath:known_hosts" + strictHostKeyChecking: "yes" + steps: + - to: + uri: direct:result +---- +==== + If you do not have a known hosts file, you can create one by connecting to the server using the `ssh` command, which will add the host key to `~/.ssh/known_hosts`. By default, the SFTP component will use this file if `useUserKnownHostsFile=true` (which is the default). +[tabs] +==== +Java:: ++ [source,java] ---- -// Uses ~/.ssh/known_hosts by default -from("sftp://host:22/path" - + "?username=myuser" - + "&privateKeyFile=/path/to/id_rsa" - + "&strictHostKeyChecking=yes") +from("sftp://host:22/path?username=myuser&privateKeyFile=/path/to/id_rsa&strictHostKeyChecking=yes") .to("direct:result"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: sftp://host:22/path + parameters: + username: myuser + privateKeyFile: /path/to/id_rsa + strictHostKeyChecking: "yes" + steps: + - to: + uri: direct:result +---- +==== + NOTE: When `strictHostKeyChecking=yes` is enabled, Camel's security policy enforcement framework will not flag this as a security violation. The default `strictHostKeyChecking=no` may trigger warnings or failures depending on your configured security policy. === OpenSSH Certificate Authentication @@ -119,26 +202,82 @@ Camel supports OpenSSH certificate-based authentication for SFTP connections, wh To use certificate authentication, provide the certificate file alongside the private key: +[tabs] +==== +Java:: ++ [source,java] ---- -from("sftp://host:22/path" - + "?username=myuser" - + "&privateKeyFile=/path/to/user_key" - + "&certFile=/path/to/user_key-cert.pub") +from("sftp://host:22/path?username=myuser&privateKeyFile=/path/to/user_key&certFile=/path/to/user_key-cert.pub") .to("direct:result"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: sftp://host:22/path + parameters: + username: myuser + privateKeyFile: /path/to/user_key + certFile: /path/to/user_key-cert.pub + steps: + - to: + uri: direct:result +---- +==== + The certificate can also be loaded from a classpath resource using `certUri`: +[tabs] +==== +Java:: ++ [source,java] ---- -from("sftp://host:22/path" - + "?username=myuser" - + "&privateKeyFile=/path/to/user_key" - + "&certUri=classpath:user_key-cert.pub") +from("sftp://host:22/path?username=myuser&privateKeyFile=/path/to/user_key&certUri=classpath:user_key-cert.pub") .to("direct:result"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: sftp://host:22/path + parameters: + username: myuser + privateKeyFile: /path/to/user_key + certUri: "classpath:user_key-cert.pub" + steps: + - to: + uri: direct:result +---- +==== + Or provided as raw bytes using `certBytes` (useful when the certificate is loaded programmatically, e.g., from a vault). NOTE: When a certificate is loaded, Camel automatically adds the certificate's key type to From f7ecf9c459e7c26a61b14d9cf2e4e49e2771f8eb Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:40:44 +0200 Subject: [PATCH 50/87] CAMEL-23789: Make IBM watsonx.data component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/ibm-watsonx-data-component.adoc | 211 ++++++++++++++++-- 1 file changed, 189 insertions(+), 22 deletions(-) diff --git a/components/camel-ibm/camel-ibm-watsonx-data/src/main/docs/ibm-watsonx-data-component.adoc b/components/camel-ibm/camel-ibm-watsonx-data/src/main/docs/ibm-watsonx-data-component.adoc index a31c793b93894..e7f42716bc6cd 100644 --- a/components/camel-ibm/camel-ibm-watsonx-data/src/main/docs/ibm-watsonx-data-component.adoc +++ b/components/camel-ibm/camel-ibm-watsonx-data/src/main/docs/ibm-watsonx-data-component.adoc @@ -59,23 +59,81 @@ include::partial$component-endpoint-headers.adoc[] The component supports authentication via IBM Cloud API Key: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .to("ibm-watsonx-data:myLakehouse?apiKey=YOUR_API_KEY" - + "&serviceUrl=https://us-south.lakehouse.cloud.ibm.com/lakehouse/api/v2" - + "&operation=listCatalogs"); + .to("ibm-watsonx-data:myLakehouse?apiKey=YOUR_API_KEY&serviceUrl=https://us-south.lakehouse.cloud.ibm.com/lakehouse/api/v2&operation=listCatalogs"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: ibm-watsonx-data:myLakehouse + parameters: + apiKey: YOUR_API_KEY + serviceUrl: "https://us-south.lakehouse.cloud.ibm.com/lakehouse/api/v2" + operation: listCatalogs +---- +==== + OAuth 2.0 Client Credentials grant is also supported when `camel-oauth` is on the classpath: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .to("ibm-watsonx-data:myLakehouse?oauthProfile=ibm" - + "&serviceUrl=https://us-south.lakehouse.cloud.ibm.com/lakehouse/api/v2" - + "&operation=listCatalogs"); + .to("ibm-watsonx-data:myLakehouse?oauthProfile=ibm&serviceUrl=https://us-south.lakehouse.cloud.ibm.com/lakehouse/api/v2&operation=listCatalogs"); +---- + +XML:: ++ +[source,xml] ---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: ibm-watsonx-data:myLakehouse + parameters: + oauthProfile: ibm + serviceUrl: "https://us-south.lakehouse.cloud.ibm.com/lakehouse/api/v2" + operation: listCatalogs +---- +==== == Operations @@ -143,51 +201,160 @@ The component supports the following operations: === List Catalogs +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:listCatalogs") - .to("ibm-watsonx-data:lakehouse?apiKey={{ibm.apiKey}}" - + "&serviceUrl={{ibm.watsonxdata.url}}" - + "&operation=listCatalogs") + .to("ibm-watsonx-data:lakehouse?apiKey={{ibm.apiKey}}&serviceUrl={{ibm.watsonxdata.url}}&operation=listCatalogs") .log("Catalogs: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:listCatalogs + steps: + - to: + uri: ibm-watsonx-data:lakehouse + parameters: + apiKey: "{{ibm.apiKey}}" + serviceUrl: "{{ibm.watsonxdata.url}}" + operation: listCatalogs + - log: + message: "Catalogs: ${body}" +---- +==== + === List Tables in a Schema +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:listTables") - .to("ibm-watsonx-data:lakehouse?apiKey={{ibm.apiKey}}" - + "&serviceUrl={{ibm.watsonxdata.url}}" - + "&catalogName=my-catalog" - + "&schemaName=my-schema" - + "&engineId=my-presto-engine" - + "&operation=listTables") + .to("ibm-watsonx-data:lakehouse?apiKey={{ibm.apiKey}}&serviceUrl={{ibm.watsonxdata.url}}&catalogName=my-catalog&schemaName=my-schema&engineId=my-presto-engine&operation=listTables") .log("Tables: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:listTables + steps: + - to: + uri: ibm-watsonx-data:lakehouse + parameters: + apiKey: "{{ibm.apiKey}}" + serviceUrl: "{{ibm.watsonxdata.url}}" + catalogName: my-catalog + schemaName: my-schema + engineId: my-presto-engine + operation: listTables + - log: + message: "Tables: ${body}" +---- +==== + === Create a Schema +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:createSchema") .setHeader("CamelIBMWatsonxDataSchemaName", constant("new_schema")) .setHeader("CamelIBMWatsonxDataCustomPath", constant("s3a://my-bucket/new_schema")) - .to("ibm-watsonx-data:lakehouse?apiKey={{ibm.apiKey}}" - + "&serviceUrl={{ibm.watsonxdata.url}}" - + "&catalogName=my-catalog" - + "&engineId=my-engine" - + "&operation=createSchema") + .to("ibm-watsonx-data:lakehouse?apiKey={{ibm.apiKey}}&serviceUrl={{ibm.watsonxdata.url}}&catalogName=my-catalog&engineId=my-engine&operation=createSchema") .log("Schema created: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + new_schema + + + s3a://my-bucket/new_schema + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:createSchema + steps: + - setHeader: + name: CamelIBMWatsonxDataSchemaName + constant: new_schema + - setHeader: + name: CamelIBMWatsonxDataCustomPath + constant: "s3a://my-bucket/new_schema" + - to: + uri: ibm-watsonx-data:lakehouse + parameters: + apiKey: "{{ibm.apiKey}}" + serviceUrl: "{{ibm.watsonxdata.url}}" + catalogName: my-catalog + engineId: my-engine + operation: createSchema + - log: + message: "Schema created: ${body}" +---- +==== + === Using Dynamic Operations via Headers +._Java-only: requires Java enum WatsonxDataOperations constant_ + [source,java] ---- from("direct:dynamic") .setHeader("CamelIBMWatsonxDataOperation", constant(WatsonxDataOperations.listPrestoEngines)) - .to("ibm-watsonx-data:lakehouse?apiKey={{ibm.apiKey}}" - + "&serviceUrl={{ibm.watsonxdata.url}}") + .to("ibm-watsonx-data:lakehouse?apiKey={{ibm.apiKey}}&serviceUrl={{ibm.watsonxdata.url}}") .log("Engines: ${body}"); ---- From 49fbc8946cd366282bd06b53c01fddcfde1d5547 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:42:37 +0200 Subject: [PATCH 51/87] CAMEL-23789: Make Azure Key Vault and DigitalOcean component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/azure-key-vault-component.adoc | 188 +++++++++++++++-- .../src/main/docs/digitalocean-component.adoc | 199 +++++++++++++++++- 2 files changed, 360 insertions(+), 27 deletions(-) diff --git a/components/camel-azure/camel-azure-key-vault/src/main/docs/azure-key-vault-component.adoc b/components/camel-azure/camel-azure-key-vault/src/main/docs/azure-key-vault-component.adoc index d7b9ec9fdd90b..75e3d7ee62c97 100644 --- a/components/camel-azure/camel-azure-key-vault/src/main/docs/azure-key-vault-component.adoc +++ b/components/camel-azure/camel-azure-key-vault/src/main/docs/azure-key-vault-component.adoc @@ -424,40 +424,196 @@ Azure Key Vault component provides the following operation on the producer side: - createSecret: this operation will create a secret in Azure Key Vault +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:createSecret") - .setHeader(KeyVaultConstants.SECRET_NAME, "Test") + .setHeader("CamelAzureKeyVaultSecretName", constant("Test")) .setBody(constant("Test")) - .to("azure-key-vault://test123?clientId=RAW({{clientId}})&clientSecret=RAW({{clientSecret}})&tenantId=RAW({{tenantId}})") --------------------------------------------------------------------------------- + .to("azure-key-vault://test123?clientId=RAW({{clientId}})&clientSecret=RAW({{clientSecret}})&tenantId=RAW({{tenantId}})"); +---- + +XML:: ++ +[source,xml] +---- + + + + Test + + + Test + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:createSecret + steps: + - setHeader: + name: CamelAzureKeyVaultSecretName + constant: Test + - setBody: + constant: Test + - to: + uri: azure-key-vault://test123 + parameters: + clientId: "RAW({{clientId}})" + clientSecret: "RAW({{clientSecret}})" + tenantId: "RAW({{tenantId}})" +---- +==== - getSecret: this operation will get a secret from Azure Key Vault +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:getSecret") - .setHeader(KeyVaultConstants.SECRET_NAME, "Test") - .to("azure-key-vault://test123?clientId=RAW({{clientId}})&clientSecret=RAW({{clientSecret}})&tenantId=RAW({{tenantId}})&operation=getSecret") --------------------------------------------------------------------------------- + .setHeader("CamelAzureKeyVaultSecretName", constant("Test")) + .to("azure-key-vault://test123?clientId=RAW({{clientId}})&clientSecret=RAW({{clientSecret}})&tenantId=RAW({{tenantId}})&operation=getSecret"); +---- + +XML:: ++ +[source,xml] +---- + + + + Test + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:getSecret + steps: + - setHeader: + name: CamelAzureKeyVaultSecretName + constant: Test + - to: + uri: azure-key-vault://test123 + parameters: + clientId: "RAW({{clientId}})" + clientSecret: "RAW({{clientSecret}})" + tenantId: "RAW({{tenantId}})" + operation: getSecret +---- +==== - deleteSecret: this operation will delete a Secret from Azure Key Vault +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:deleteSecret") - .setHeader(KeyVaultConstants.SECRET_NAME, "Test") - .to("azure-key-vault://test123?clientId=RAW({{clientId}})&clientSecret=RAW({{clientSecret}})&tenantId=RAW({{tenantId}})&operation=deleteSecret") --------------------------------------------------------------------------------- + .setHeader("CamelAzureKeyVaultSecretName", constant("Test")) + .to("azure-key-vault://test123?clientId=RAW({{clientId}})&clientSecret=RAW({{clientSecret}})&tenantId=RAW({{tenantId}})&operation=deleteSecret"); +---- + +XML:: ++ +[source,xml] +---- + + + + Test + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:deleteSecret + steps: + - setHeader: + name: CamelAzureKeyVaultSecretName + constant: Test + - to: + uri: azure-key-vault://test123 + parameters: + clientId: "RAW({{clientId}})" + clientSecret: "RAW({{clientSecret}})" + tenantId: "RAW({{tenantId}})" + operation: deleteSecret +---- +==== - purgeDeletedSecret: this operation will purge a deleted Secret from Azure Key Vault +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:purgeDeletedSecret") - .setHeader(KeyVaultConstants.SECRET_NAME, "Test") - .to("azure-key-vault://test123?clientId=RAW({{clientId}})&clientSecret=RAW({{clientSecret}})&tenantId=RAW({{tenantId}})&operation=purgeDeletedSecret") --------------------------------------------------------------------------------- + .setHeader("CamelAzureKeyVaultSecretName", constant("Test")) + .to("azure-key-vault://test123?clientId=RAW({{clientId}})&clientSecret=RAW({{clientSecret}})&tenantId=RAW({{tenantId}})&operation=purgeDeletedSecret"); +---- + +XML:: ++ +[source,xml] +---- + + + + Test + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:purgeDeletedSecret + steps: + - setHeader: + name: CamelAzureKeyVaultSecretName + constant: Test + - to: + uri: azure-key-vault://test123 + parameters: + clientId: "RAW({{clientId}})" + clientSecret: "RAW({{clientSecret}})" + tenantId: "RAW({{tenantId}})" + operation: purgeDeletedSecret +---- +==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-digitalocean/src/main/docs/digitalocean-component.adoc b/components/camel-digitalocean/src/main/docs/digitalocean-component.adoc index 38c9421f4d882..2044a311b3d18 100644 --- a/components/camel-digitalocean/src/main/docs/digitalocean-component.adoc +++ b/components/camel-digitalocean/src/main/docs/digitalocean-component.adoc @@ -377,50 +377,227 @@ ou can find the per-method limits in the https://developers.digitalocean.com/doc == Examples +._Java-only: requires Java enum DigitalOceanOperations.get_ + .Get your account info [source,java] ---- from("direct:getAccountInfo") - .setHeader(DigitalOceanConstants.OPERATION, constant(DigitalOceanOperations.get)) + .setHeader("CamelDigitalOceanOperation", constant(DigitalOceanOperations.get)) .to("digitalocean:account?oAuthToken=XXXXXX") ---- .Create a droplet + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:createDroplet") - .setHeader(DigitalOceanConstants.OPERATION, constant("create")) - .setHeader(DigitalOceanHeaders.NAME, constant("myDroplet")) - .setHeader(DigitalOceanHeaders.REGION, constant("fra1")) - .setHeader(DigitalOceanHeaders.DROPLET_IMAGE, constant("ubuntu-14-04-x64")) - .setHeader(DigitalOceanHeaders.DROPLET_SIZE, constant("512mb")) + .setHeader("CamelDigitalOceanOperation", constant("create")) + .setHeader("CamelDigitalOceanName", constant("myDroplet")) + .setHeader("CamelDigitalOceanRegion", constant("fra1")) + .setHeader("CamelDigitalOceanDropletImage", constant("ubuntu-14-04-x64")) + .setHeader("CamelDigitalOceanDropletSize", constant("512mb")) .to("digitalocean:droplet?oAuthToken=XXXXXX") ---- +XML:: ++ +[source,xml] +---- + + + + create + + + myDroplet + + + fra1 + + + ubuntu-14-04-x64 + + + 512mb + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:createDroplet + steps: + - setHeader: + name: CamelDigitalOceanOperation + constant: create + - setHeader: + name: CamelDigitalOceanName + constant: myDroplet + - setHeader: + name: CamelDigitalOceanRegion + constant: fra1 + - setHeader: + name: CamelDigitalOceanDropletImage + constant: ubuntu-14-04-x64 + - setHeader: + name: CamelDigitalOceanDropletSize + constant: 512mb + - to: + uri: digitalocean:droplet + parameters: + oAuthToken: XXXXXX +---- +==== + .List all your droplets + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:getDroplets") - .setHeader(DigitalOceanConstants.OPERATION, constant("list")) + .setHeader("CamelDigitalOceanOperation", constant("list")) .to("digitalocean:droplets?oAuthToken=XXXXXX") ---- +XML:: ++ +[source,xml] +---- + + + + list + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:getDroplets + steps: + - setHeader: + name: CamelDigitalOceanOperation + constant: list + - to: + uri: digitalocean:droplets + parameters: + oAuthToken: XXXXXX +---- +==== + .Retrieve information for the Droplet (dropletId = 34772987) + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:getDroplet") - .setHeader(DigitalOceanConstants.OPERATION, constant("get")) - .setHeader(DigitalOceanConstants.ID, 34772987) + .setHeader("CamelDigitalOceanOperation", constant("get")) + .setHeader("CamelDigitalOceanId", constant(34772987)) .to("digitalocean:droplet?oAuthToken=XXXXXX") ---- -.Shutdown information for the Droplet (dropletId = 34772987) +XML:: ++ +[source,xml] +---- + + + + get + + + 34772987 + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:getDroplet + steps: + - setHeader: + name: CamelDigitalOceanOperation + constant: get + - setHeader: + name: CamelDigitalOceanId + constant: 34772987 + - to: + uri: digitalocean:droplet + parameters: + oAuthToken: XXXXXX +---- +==== + +.Shutdown information for the Droplet (dropletId = 34772987) + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:shutdown") - .setHeader(DigitalOceanConstants.ID, 34772987) + .setHeader("CamelDigitalOceanId", constant(34772987)) .to("digitalocean:droplet?operation=shutdown&oAuthToken=XXXXXX") ---- +XML:: ++ +[source,xml] +---- + + + + 34772987 + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:shutdown + steps: + - setHeader: + name: CamelDigitalOceanId + constant: 34772987 + - to: + uri: digitalocean:droplet + parameters: + operation: shutdown + oAuthToken: XXXXXX +---- +==== + include::spring-boot:partial$starter.adoc[] From 3c5f10f4649a4910c7aaf28b295eb7c75d7a2373 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:54:45 +0200 Subject: [PATCH 52/87] CAMEL-23789: Make Huawei Cloud component docs multi-DSL friendly (Wave 1) Converted hwcloud-obs, hwcloud-iam, hwcloud-dms, hwcloud-functiongraph, and hwcloud-smn to use tabs blocks for Java/XML/YAML examples. - 8 tabs blocks (JSON body, ServiceKeys, simple routes) - 6 Java-only markers (SDK constructors, builders, Java variables) - Resolved Java constants to string values - Fixed typo in OBS listObjects JSON example - Fixed missing quote in IAM ServiceKeys example Co-Authored-By: Claude Signed-off-by: Claus Ibsen Signed-off-by: Claus Ibsen --- .../src/main/docs/hwcloud-dms-component.adoc | 109 +++++++++++++++ .../docs/hwcloud-functiongraph-component.adoc | 55 +++++++- .../src/main/docs/hwcloud-iam-component.adoc | 132 +++++++++++++++++- .../src/main/docs/hwcloud-obs-component.adoc | 132 +++++++++++++++++- .../src/main/docs/hwcloud-smn-component.adoc | 16 ++- 5 files changed, 428 insertions(+), 16 deletions(-) diff --git a/components/camel-huawei/camel-huaweicloud-dms/src/main/docs/hwcloud-dms-component.adoc b/components/camel-huawei/camel-huaweicloud-dms/src/main/docs/hwcloud-dms-component.adoc index 448c65f767e4a..32823b802641b 100644 --- a/components/camel-huawei/camel-huaweicloud-dms/src/main/docs/hwcloud-dms-component.adoc +++ b/components/camel-huawei/camel-huaweicloud-dms/src/main/docs/hwcloud-dms-component.adoc @@ -115,6 +115,8 @@ If any of the above properties are set, they will override their corresponding q === Create Instance To create an instance, you can pass the parameters through the endpoint, the exchange properties, and the exchange body as a CreateInstanceRequestBody object or a valid JSON String representation of it. Refer to this for the https://support.huaweicloud.com/en-us/api-kafka/kafka-api-180514002.html[Kafka parameters] and the https://support.huaweicloud.com/en-us/api-rabbitmq/rabbitmq-api-180514002.html[RabbitMQ parameters]. If you choose to pass these parameters through the endpoint or through exchange properties, you can only input the mandatory parameters shown in those links. If you would like to have access to all the parameters, you must pass a CreateInstanceRequestBody object or a valid JSON String representation of it through the exchange body, as shown below: +._Java-only: requires SDK CreateInstanceRequestBody builder_ + [source,java] ---- from("direct:triggerRoute") @@ -122,6 +124,10 @@ from("direct:triggerRoute") .to("hwcloud-dms:createInstance?region=cn-north-4&accessKey=********&secretKey=********&projectId=*******") ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:triggerRoute") @@ -129,9 +135,44 @@ from("direct:triggerRoute") .to("hwcloud-dms:createInstance?region=cn-north-4&accessKey=********&secretKey=********&projectId=*******") ---- +XML:: ++ +[source,xml] +---- + + + + {"name":"new-instance","description":"description"} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:triggerRoute + steps: + - setBody: + constant: '{"name":"new-instance","description":"description"}' + - to: + uri: hwcloud-dms:createInstance + parameters: + region: cn-north-4 + accessKey: "********" + secretKey: "********" + projectId: "*******" +---- +==== + === Update Instance To update an instance, you must pass the parameters through the exchange body as an UpdateInstanceRequestBody or a valid JSON String representation of it. Refer to this for the https://support.huaweicloud.com/en-us/api-kafka/kafka-api-180514004.html[Kafka parameters] and the https://support.huaweicloud.com/en-us/api-rabbitmq/rabbitmq-api-180514004.html[RabbitMQ parameters]. An example of how to do this is shown below: +._Java-only: requires SDK UpdateInstanceRequestBody builder_ + [source,java] ---- from("direct:triggerRoute") @@ -139,6 +180,10 @@ from("direct:triggerRoute") .to("hwcloud-dms:updateInstance?instanceId=******®ion=cn-north-4&accessKey=********&secretKey=********&projectId=*******") ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:triggerRoute") @@ -146,6 +191,40 @@ from("direct:triggerRoute") .to("hwcloud-dms:updateInstance?instanceId=******®ion=cn-north-4&accessKey=********&secretKey=********&projectId=*******") ---- +XML:: ++ +[source,xml] +---- + + + + {"name":"new-instance","description":"description"} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:triggerRoute + steps: + - setBody: + constant: '{"name":"new-instance","description":"description"}' + - to: + uri: hwcloud-dms:updateInstance + parameters: + instanceId: "******" + region: cn-north-4 + accessKey: "********" + secretKey: "********" + projectId: "*******" +---- +==== + === Using ServiceKey Configuration Bean Access key and secret keys are required to authenticate against cloud DMS service. You can avoid having them being exposed @@ -161,11 +240,41 @@ Check the following code snippets:
---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:triggerRoute") .to("hwcloud-dms:listInstances?region=cn-north-4&serviceKeys=#myServiceKeyConfig") ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:triggerRoute + steps: + - to: + uri: hwcloud-dms:listInstances + parameters: + region: cn-north-4 + serviceKeys: "#myServiceKeyConfig" +---- +==== + include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-huawei/camel-huaweicloud-functiongraph/src/main/docs/hwcloud-functiongraph-component.adoc b/components/camel-huawei/camel-huaweicloud-functiongraph/src/main/docs/hwcloud-functiongraph-component.adoc index c5413e44d0df1..a89403151bda8 100644 --- a/components/camel-huawei/camel-huaweicloud-functiongraph/src/main/docs/hwcloud-functiongraph-component.adoc +++ b/components/camel-huawei/camel-huaweicloud-functiongraph/src/main/docs/hwcloud-functiongraph-component.adoc @@ -92,14 +92,63 @@ Check the following code snippets:
---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:triggerRoute") - .setProperty(FunctionGraphProperties.OPERATION, constant("invokeFunction")) - .setProperty(FunctionGraphProperties.FUNCTION_NAME ,constant("your_function_name")) - .setProperty(FunctionGraphProperties.FUNCTION_PACKAGE, constant("your_function_package")) + .setProperty("CamelHwCloudFgOperation", constant("invokeFunction")) + .setProperty("CamelHwCloudFgFunction", constant("your_function_name")) + .setProperty("CamelHwCloudFgPackage", constant("your_function_package")) .to("hwcloud-functiongraph:invokeFunction?projectId=9071a38e7f6a4ba7b7bcbeb7d4ea6efc®ion=cn-north-4&serviceKeys=#myServiceKeyConfig") ---- +XML:: ++ +[source,xml] +---- + + + + invokeFunction + + + your_function_name + + + your_function_package + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:triggerRoute + steps: + - setProperty: + name: CamelHwCloudFgOperation + constant: invokeFunction + - setProperty: + name: CamelHwCloudFgFunction + constant: your_function_name + - setProperty: + name: CamelHwCloudFgPackage + constant: your_function_package + - to: + uri: hwcloud-functiongraph:invokeFunction + parameters: + projectId: 9071a38e7f6a4ba7b7bcbeb7d4ea6efc + region: cn-north-4 + serviceKeys: "#myServiceKeyConfig" +---- +==== + include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-huawei/camel-huaweicloud-iam/src/main/docs/hwcloud-iam-component.adoc b/components/camel-huawei/camel-huaweicloud-iam/src/main/docs/hwcloud-iam-component.adoc index b5bd7d7710a71..6340796abb1df 100644 --- a/components/camel-huawei/camel-huaweicloud-iam/src/main/docs/hwcloud-iam-component.adoc +++ b/components/camel-huawei/camel-huaweicloud-iam/src/main/docs/hwcloud-iam-component.adoc @@ -74,6 +74,8 @@ There are many options that can be submitted to https://support.huaweicloud.com/ For the `updateUser` operation, you can pass the user options as an UpdateUserOption object or a Json string: +._Java-only: requires SDK UpdateUserOption builder_ + [source,java] ---- from("direct:triggerRoute") @@ -81,6 +83,10 @@ from("direct:triggerRoute") .to("hwcloud-iam:updateUser?userId=********®ion=cn-north-4&accessKey=********&secretKey=********") ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:triggerRoute") @@ -88,8 +94,43 @@ from("direct:triggerRoute") .to("hwcloud-iam:updateUser?userId=********®ion=cn-north-4&accessKey=********&secretKey=********") ---- +XML:: ++ +[source,xml] +---- + + + + {"name":"user","description":"employee","email":"user@email.com"} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:triggerRoute + steps: + - setBody: + constant: '{"name":"user","description":"employee","email":"user@email.com"}' + - to: + uri: hwcloud-iam:updateUser + parameters: + userId: "********" + region: cn-north-4 + accessKey: "********" + secretKey: "********" +---- +==== + For the `updateGroup` operation, you can pass the group options as a KeystoneUpdateGroupOption object or a Json string: +._Java-only: requires SDK KeystoneUpdateGroupOption builder_ + [source,java] ---- from("direct:triggerRoute") @@ -97,6 +138,10 @@ from("direct:triggerRoute") .to("hwcloud-iam:updateUser?groupId=********®ion=cn-north-4&accessKey=********&secretKey=********") ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:triggerRoute") @@ -104,6 +149,39 @@ from("direct:triggerRoute") .to("hwcloud-iam:updateUser?groupId=********®ion=cn-north-4&accessKey=********&secretKey=********") ---- +XML:: ++ +[source,xml] +---- + + + + {"name":"group","description":"employees","domain_id":"1234"} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:triggerRoute + steps: + - setBody: + constant: '{"name":"group","description":"employees","domain_id":"1234"}' + - to: + uri: hwcloud-iam:updateUser + parameters: + groupId: "********" + region: cn-north-4 + accessKey: "********" + secretKey: "********" +---- +==== + === Using ServiceKey Configuration Bean Access key and secret keys are required to authenticate against cloud IAM service. You can avoid having them being exposed @@ -120,14 +198,62 @@ Check the following code snippets: ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:triggerRoute") - .setProperty(IAMPropeties.OPERATION, constant("listUsers")) - .setProperty(IAMPropeties.USER_ID ,constant("your_user_id")) - .setProperty(IAMPropeties.GROUP_ID, constant("your_group_id)) + .setProperty("CamelHwCloudIamOperation", constant("listUsers")) + .setProperty("CamelHwCloudIamUserId", constant("your_user_id")) + .setProperty("CamelHwCloudIamGroupId", constant("your_group_id")) .to("hwcloud-iam:listUsers?region=cn-north-4&serviceKeys=#myServiceKeyConfig") ---- +XML:: ++ +[source,xml] +---- + + + + listUsers + + + your_user_id + + + your_group_id + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:triggerRoute + steps: + - setProperty: + name: CamelHwCloudIamOperation + constant: listUsers + - setProperty: + name: CamelHwCloudIamUserId + constant: your_user_id + - setProperty: + name: CamelHwCloudIamGroupId + constant: your_group_id + - to: + uri: hwcloud-iam:listUsers + parameters: + region: cn-north-4 + serviceKeys: "#myServiceKeyConfig" +---- +==== + include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-huawei/camel-huaweicloud-obs/src/main/docs/hwcloud-obs-component.adoc b/components/camel-huawei/camel-huaweicloud-obs/src/main/docs/hwcloud-obs-component.adoc index 0be10f5e8f108..649c5dde56cbc 100644 --- a/components/camel-huawei/camel-huaweicloud-obs/src/main/docs/hwcloud-obs-component.adoc +++ b/components/camel-huawei/camel-huaweicloud-obs/src/main/docs/hwcloud-obs-component.adoc @@ -89,6 +89,8 @@ There are many options that can be submitted to the `createBucket` and `listObje If you would like to configure all the https://support.huaweicloud.com/intl/en-us/api-obs/obs_04_0021.html[parameters] when creating a bucket, you can pass a https://obssdk-intl.obs.ap-southeast-1.myhuaweicloud.com/apidoc/en/java/com/obs/services/model/CreateBucketRequest.html[CreateBucketRequest] object or a Json string into the exchange body. If the exchange body is empty, a new bucket will be created using the bucketName and bucketLocation (if provided) passed through the endpoint uri. +._Java-only: requires SDK CreateBucketRequest constructor_ + [source,java] ---- from("direct:triggerRoute") @@ -96,6 +98,10 @@ from("direct:triggerRoute") .to("hwcloud-obs:createBucket?region=cn-north-4&accessKey=********&secretKey=********") ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:triggerRoute") @@ -103,8 +109,42 @@ from("direct:triggerRoute") .to("hwcloud-obs:createBucket?region=cn-north-4&accessKey=********&secretKey=********") ---- +XML:: ++ +[source,xml] +---- + + + + {"bucketName":"Bucket name","location":"Bucket location"} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:triggerRoute + steps: + - setBody: + constant: '{"bucketName":"Bucket name","location":"Bucket location"}' + - to: + uri: hwcloud-obs:createBucket + parameters: + region: cn-north-4 + accessKey: "********" + secretKey: "********" +---- +==== + If you would like to configure all the https://support.huaweicloud.com/intl/en-us/api-obs/obs_04_0022.html[parameters] when listing objects, you can pass a https://obssdk-intl.obs.ap-southeast-1.myhuaweicloud.com/apidoc/en/java/com/obs/services/model/ListObjectsRequest.html[ListObjectsRequest] object or a Json string into the exchange body. If the exchange body is empty, objects will be listed based on the bucketName passed through the endpoint uri. +._Java-only: requires SDK ListObjectsRequest constructor_ + [source,java] ---- from("direct:triggerRoute") @@ -112,13 +152,49 @@ from("direct:triggerRoute") .to("hwcloud-obs:listObjects?region=cn-north-4&accessKey=********&secretKey=********") ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:triggerRoute") - .setBody("{\"bucketName\":\"Bucket name\",\"maxKeys\":1000"}") + .setBody("{\"bucketName\":\"Bucket name\",\"maxKeys\":1000}") .to("hwcloud-obs:listObjects?region=cn-north-4&accessKey=********&secretKey=********") ---- +XML:: ++ +[source,xml] +---- + + + + {"bucketName":"Bucket name","maxKeys":1000} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:triggerRoute + steps: + - setBody: + constant: '{"bucketName":"Bucket name","maxKeys":1000}' + - to: + uri: hwcloud-obs:listObjects + parameters: + region: cn-north-4 + accessKey: "********" + secretKey: "********" +---- +==== + === Using ServiceKey Configuration Bean @@ -135,14 +211,62 @@ Check the following code snippets: ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:triggerRoute") - .setProperty(OBSPropeties.OPERATION, constant("createBucket")) - .setProperty(OBSPropeties.BUCKET_NAME ,constant("your_bucket_name")) - .setProperty(OBSPropeties.BUCKET_LOCATION, constant("your_bucket_location")) + .setProperty("CamelHwCloudObsOperation", constant("createBucket")) + .setProperty("CamelHwCloudObsBucketName", constant("your_bucket_name")) + .setProperty("CamelHwCloudObsBucketLocation", constant("your_bucket_location")) .to("hwcloud-obs:createBucket?region=cn-north-4&serviceKeys=#myServiceKeyConfig") ---- +XML:: ++ +[source,xml] +---- + + + + createBucket + + + your_bucket_name + + + your_bucket_location + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:triggerRoute + steps: + - setProperty: + name: CamelHwCloudObsOperation + constant: createBucket + - setProperty: + name: CamelHwCloudObsBucketName + constant: your_bucket_name + - setProperty: + name: CamelHwCloudObsBucketLocation + constant: your_bucket_location + - to: + uri: hwcloud-obs:createBucket + parameters: + region: cn-north-4 + serviceKeys: "#myServiceKeyConfig" +---- +==== + include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-huawei/camel-huaweicloud-smn/src/main/docs/hwcloud-smn-component.adoc b/components/camel-huawei/camel-huaweicloud-smn/src/main/docs/hwcloud-smn-component.adoc index ff7f86c8bbf68..c064517492297 100644 --- a/components/camel-huawei/camel-huaweicloud-smn/src/main/docs/hwcloud-smn-component.adoc +++ b/components/camel-huawei/camel-huaweicloud-smn/src/main/docs/hwcloud-smn-component.adoc @@ -163,9 +163,11 @@ YAML:: === publishAsTemplatedMessage -Java DSL + +._Java-only: requires Java Map variable for template tags_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:triggerRoute") .setProperty("CamelHwCloudSmnSubject", constant("This is my subjectline")) .setProperty("CamelHwCloudSmnTopic", constant("reji-test")) @@ -173,7 +175,7 @@ from("direct:triggerRoute") .setProperty("CamelHwCloudSmnTemplateTags", constant(tags)) .setProperty("CamelHwCloudSmnTemplateName", constant("hello-template")) .to("hwcloud-smn:publishMessageService?operation=publishAsTemplatedMessage&accessKey=*********&secretKey=********&projectId=9071a38e7f6a4ba7b7bcbeb7d4ea6efc®ion=cn-north-4") --------------------------------------------------------------------------------- +---- === Using ServiceKey configuration Bean @@ -189,14 +191,16 @@ Check the following code snippets ---- +._Java-only: requires Java constants and test configuration properties_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:triggerRoute") .setProperty(SmnProperties.NOTIFICATION_SUBJECT, constant("Notification Subject")) - .setProperty(SmnProperties.NOTIFICATION_TOPIC_NAME,constant(testConfiguration.getProperty("topic"))) + .setProperty(SmnProperties.NOTIFICATION_TOPIC_NAME, constant(testConfiguration.getProperty("topic"))) .setProperty(SmnProperties.NOTIFICATION_TTL, constant(60)) .to("hwcloud-smn:publishMessageService?operation=publishAsTextMessage&projectId=9071a38e7f6a4ba7b7bcbeb7d4ea6efc®ion=cn-north-4&serviceKeys=#myServiceKeyConfig") --------------------------------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] From 1263b1e39a3cc0d85bdff7f49fb4912c4e43bf49 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 07:59:32 +0200 Subject: [PATCH 53/87] CAMEL-23789: Make LangChain4j Tools component docs multi-DSL friendly (Wave 1) Converted langchain4j-tools to use tabs blocks for Java/XML/YAML examples. - 8 tabs blocks: consumer routes, producer+consumer pair, tool naming, stop() pattern, chatModel reference, exposed/searchable tools - 2 Java-only markers (variable source endpoint, URI concatenation+process) - YAML examples show parameters: block for consumer endpoint options Co-Authored-By: Claude Signed-off-by: Claus Ibsen Signed-off-by: Claus Ibsen --- .../docs/langchain4j-tools-component.adoc | 378 +++++++++++++++++- 1 file changed, 363 insertions(+), 15 deletions(-) diff --git a/components/camel-ai/camel-langchain4j-tools/src/main/docs/langchain4j-tools-component.adoc b/components/camel-ai/camel-langchain4j-tools/src/main/docs/langchain4j-tools-component.adoc index 43ed974d824b6..4f29f7fbe99c8 100644 --- a/components/camel-ai/camel-langchain4j-tools/src/main/docs/langchain4j-tools-component.adoc +++ b/components/camel-ai/camel-langchain4j-tools/src/main/docs/langchain4j-tools-component.adoc @@ -61,19 +61,81 @@ can be called (i.e.; routed). Consider, for instance, two consumer routes capable of query an user database by user ID or by social security number (SSN). .Queries user by ID -[source, java] + +[tabs] +==== +Java:: ++ +[source,java] ---- from("langchain4j-tools:userInfo?tags=users&description=Query database by user ID") .to("sql:SELECT name FROM users WHERE id = :#number"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: langchain4j-tools:userInfo + parameters: + tags: users + description: Query database by user ID + steps: + - to: + uri: "sql:SELECT name FROM users WHERE id = :#number" +---- +==== + .Queries user by SSN -[source, java] + +[tabs] +==== +Java:: ++ +[source,java] ---- from("langchain4j-tools:userInfo?tags=users&description=Query database by user social security ID") .to("sql:SELECT name FROM users WHERE ssn = :#ssn"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: langchain4j-tools:userInfo + parameters: + tags: users + description: Query database by user social security ID + steps: + - to: + uri: "sql:SELECT name FROM users WHERE ssn = :#ssn" +---- +==== + Now, consider a producer route that receives unstructured data as input. Such a route could consume this data, pass it to a LLM with function-calling capabilities (such as https://huggingface.co/meta-llama/Meta-Llama-3.1-8B[llama3.1], https://huggingface.co/ibm-granite/granite-20b-functioncalling[Granite Code 20b function calling, etc]) and have @@ -84,8 +146,9 @@ Such a route could receive questions in english such as: - _"What is the name of the user with user ID 1?"_ - _"What is the name of the user with SSN 34.400.96?"_ -.Produce -[source, java] +._Java-only: uses a Java variable for the source endpoint_ + +[source,java] ---- from(source) .to("langchain4j-tools:userInfo?tags=users"); @@ -111,7 +174,12 @@ Parameters support optional metadata: * `parameter..enum=` — restricts the parameter to a set of allowed values (comma-separated) .Producer and consumer example: -[source, java] + +[tabs] +==== +Java:: ++ +[source,java] ---- from("direct:test") .to("langchain4j-tools:test1?tags=users"); @@ -120,8 +188,52 @@ from("langchain4j-tools:test1?tags=users&description=Query user database by user .to("sql:SELECT name FROM users WHERE id = :#userId"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:test + steps: + - to: + uri: langchain4j-tools:test1 + parameters: + tags: users + +- route: + from: + uri: langchain4j-tools:test1 + parameters: + tags: users + description: Query user database by user ID + parameter.userId: integer + steps: + - to: + uri: "sql:SELECT name FROM users WHERE id = :#userId" +---- +==== + .Example with required parameters and descriptions: -[source, java] + +._Java-only: uses string concatenation for URI and process callback_ + +[source,java] ---- from("langchain4j-tools:weather?tags=weather&description=Get weather forecast" + "¶meter.location=string" @@ -183,34 +295,136 @@ from the `description` option by converting it to CamelCase. For example: You can override the generated name by setting the `name` option explicitly on the consumer endpoint: -[source, java] +[tabs] +==== +Java:: ++ +[source,java] ---- from("langchain4j-tools:test1?tags=orders&name=amendOrder&description=Amend an order by its ID¶meter.orderId=string") .setBody(constant("order amended")); ---- +XML:: ++ +[source,xml] +---- + + + + order amended + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: langchain4j-tools:test1 + parameters: + tags: orders + name: amendOrder + description: Amend an order by its ID + parameter.orderId: string + steps: + - setBody: + constant: order amended +---- +==== + === Using stop() in Tool Routes Tool routes can use the `stop()` EIP to discontinue route processing early. When the LLM invokes multiple tools in parallel, each tool route executes independently — `stop()` in one tool does not affect the others. .Example with two tools where one uses stop(): -[source, java] + +[tabs] +==== +Java:: ++ +[source,java] ---- from("direct:chat") .to("langchain4j-tools:test1?tags=orders") .log("response is: ${body}"); -// Tool that uses stop() to end processing early from("langchain4j-tools:test1?tags=orders&description=Amend an order by its ID¶meter.orderId=string") .setBody(constant("order amended")) .stop(); -// Tool that returns JSON — executes independently from("langchain4j-tools:test1?tags=orders&description=Get current promotions") .setBody(constant("{\"status\":\"ok\",\"promotions\":[\"10% off\"]}")); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + + order amended + + + + + + + + {"status":"ok","promotions":["10% off"]} + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-tools:test1 + parameters: + tags: orders + - log: + message: "response is: ${body}" + +- route: + from: + uri: langchain4j-tools:test1 + parameters: + tags: orders + description: Amend an order by its ID + parameter.orderId: string + steps: + - setBody: + constant: order amended + - stop: {} + +- route: + from: + uri: langchain4j-tools:test1 + parameters: + tags: orders + description: Get current promotions + steps: + - setBody: + constant: '{"status":"ok","promotions":["10% off"]}' +---- +==== + When the LLM invokes both tools, each produces its own result. The `stop()` in the first tool does not prevent the second tool from executing, nor does it stop the calling route from continuing after the tools producer completes. @@ -252,12 +466,42 @@ context.getRegistry().bind("chatModel", model); Use the model in the Camel LangChain4j Chat Producer -[source, java] +[tabs] +==== +Java:: ++ +[source,java] +---- +from("direct:chat") + .to("langchain4j-tools:test?tags=users&chatModel=#chatModel"); ---- - from("direct:chat") - .to("langchain4j-tools:test?tags=users&chatModel=#chatModel"); + +XML:: ++ +[source,xml] +---- + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:chat + steps: + - to: + uri: langchain4j-tools:test + parameters: + tags: users + chatModel: "#chatModel" +---- +==== + [NOTE] ==== To switch to another Large Language Model and its corresponding dependency, replace the `langchain4j-open-ai` dependency with the appropriate dependency for the desired model. Update the initialization parameters accordingly in the code snippet provided above. @@ -288,12 +532,44 @@ The Tool Search Tool solves this by allowing you to mark certain tools as "searc By default, all tools are exposed to the LLM (`exposed=true`). To make a tool searchable instead: -[source, java] +[tabs] +==== +Java:: ++ +[source,java] ---- from("langchain4j-tools:queryBySSN?tags=users&description=Query user database by social security number¶meter.ssn=string&exposed=false") .to("sql:SELECT name FROM users WHERE ssn = :#ssn"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: langchain4j-tools:queryBySSN + parameters: + tags: users + description: Query user database by social security number + parameter.ssn: string + exposed: false + steps: + - to: + uri: "sql:SELECT name FROM users WHERE ssn = :#ssn" +---- +==== + ==== How It Works 1. When you define tools with `exposed=false`, they are added to a searchable tool registry @@ -303,7 +579,11 @@ from("langchain4j-tools:queryBySSN?tags=users&description=Query user database by ==== Example: Mixed Exposed and Searchable Tools -[source, java] +[tabs] +==== +Java:: ++ +[source,java] ---- // This tool is immediately available to the LLM from("langchain4j-tools:queryById?tags=users&description=Query user database by user ID¶meter.userId=integer") @@ -318,6 +598,74 @@ from("langchain4j-tools:sendEmail?tags=users,email&description=Send email to a u .to("smtp://mailserver"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +# This tool is immediately available to the LLM +- route: + from: + uri: langchain4j-tools:queryById + parameters: + tags: users + description: Query user database by user ID + parameter.userId: integer + steps: + - to: + uri: "sql:SELECT name FROM users WHERE id = :#userId" + +# This tool is searchable but not immediately exposed +- route: + from: + uri: langchain4j-tools:queryBySSN + parameters: + tags: users + description: Query user database by social security number + parameter.ssn: string + exposed: false + steps: + - to: + uri: "sql:SELECT name FROM users WHERE ssn = :#ssn" + +# Another searchable tool with different tags +- route: + from: + uri: langchain4j-tools:sendEmail + parameters: + tags: "users,email" + description: Send email to a user + parameter.email: string + parameter.message: string + exposed: false + steps: + - to: + uri: smtp://mailserver +---- +==== + In this example: * The `queryById` tool is immediately available to the LLM From 2aa1417779bc796fdb8848c5e15744b887eaa257 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:04:35 +0200 Subject: [PATCH 54/87] CAMEL-23789: Make Hazelcast component docs multi-DSL friendly (Wave 1) Converted remaining Hazelcast component docs (list, instance, topic, map consumer, multimap consumer, ringbuffer readOnceHead) to multi-DSL tabs with Java/XML/YAML alternatives. Resolved Java constants (HazelcastConstants, HazelcastOperation) to their string values and replaced toF()/fromF() format patterns with literal URIs. Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../docs/hazelcast-instance-component.adoc | 74 +++++- .../main/docs/hazelcast-list-component.adoc | 247 ++++++++++++++++-- .../main/docs/hazelcast-map-component.adoc | 120 +++++++-- .../docs/hazelcast-multimap-component.adoc | 87 ++++-- .../docs/hazelcast-ringbuffer-component.adoc | 48 +++- .../main/docs/hazelcast-topic-component.adoc | 102 +++++++- 6 files changed, 587 insertions(+), 91 deletions(-) diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-instance-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-instance-component.adoc index 6bfc792f3b75b..5d3ec1d5c335a 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-instance-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-instance-component.adoc @@ -31,17 +31,69 @@ The instance consumer fires if a new cache instance joins or leaves the cluster. Here's a sample: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------------ -fromF("hazelcast-%sfoo", HazelcastConstants.INSTANCE_PREFIX) -.log("instance...") -.choice() - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.ADDED)) - .log("...added") - .to("mock:added") - .otherwise() - .log("...removed") - .to("mock:removed"); ------------------------------------------------------------------------------------------ +---- +from("hazelcast-instance:foo") + .log("instance...") + .choice() + .when(header("CamelHazelcastListenerAction").isEqualTo("added")) + .log("...added") + .to("mock:added") + .otherwise() + .log("...removed") + .to("mock:removed"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + ${header.CamelHazelcastListenerAction} == 'added' + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: hazelcast-instance:foo + steps: + - log: + message: "instance..." + - choice: + when: + - simple: "${header.CamelHazelcastListenerAction} == 'added'" + steps: + - log: + message: "...added" + - to: + uri: mock:added + otherwise: + steps: + - log: + message: "...removed" + - to: + uri: mock:removed +---- +==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-list-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-list-component.adoc index cce9805be34d0..51c2623216709 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-list-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-list-component.adoc @@ -41,40 +41,175 @@ The list producer provides eight operations: === Example for *add*: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------- +---- from("direct:add") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.ADD)) -.toF("hazelcast-%sbar", HazelcastConstants.LIST_PREFIX); ------------------------------------------------------------------------------------- + .setHeader("CamelHazelcastOperationType", constant("add")) + .to("hazelcast-list:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + add + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:add + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: add + - to: + uri: hazelcast-list:bar +---- +==== === Example for *get*: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------- +---- from("direct:get") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.GET)) -.toF("hazelcast-%sbar", HazelcastConstants.LIST_PREFIX) -.to("seda:out"); ------------------------------------------------------------------------------------- + .setHeader("CamelHazelcastOperationType", constant("get")) + .to("hazelcast-list:bar") + .to("seda:out"); +---- + +XML:: ++ +[source,xml] +---- + + + + get + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:get + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: get + - to: + uri: hazelcast-list:bar + - to: + uri: seda:out +---- +==== === Example for *setvalue*: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------------ +---- from("direct:set") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.SET_VALUE)) -.toF("hazelcast-%sbar", HazelcastConstants.LIST_PREFIX); ------------------------------------------------------------------------------------------ + .setHeader("CamelHazelcastOperationType", constant("setvalue")) + .to("hazelcast-list:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + setvalue + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:set + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: setvalue + - to: + uri: hazelcast-list:bar +---- +==== === Example for *removevalue*: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------- +---- from("direct:removevalue") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.REMOVE_VALUE)) -.toF("hazelcast-%sbar", HazelcastConstants.LIST_PREFIX); --------------------------------------------------------------------------------------------- + .setHeader("CamelHazelcastOperationType", constant("removevalue")) + .to("hazelcast-list:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + removevalue + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:removevalue + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: removevalue + - to: + uri: hazelcast-list:bar +---- +==== Note that *CamelHazelcastObjectIndex* header is used for indexing purpose. @@ -86,20 +221,80 @@ The list consumer provides two operations: * add * remove +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------------------ -fromF("hazelcast-%smm", HazelcastConstants.LIST_PREFIX) +---- +from("hazelcast-list:mm") .log("object...") .choice() - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.ADDED)) + .when(header("CamelHazelcastListenerAction").isEqualTo("added")) .log("...added") - .to("mock:added") - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.REMOVED)) + .to("mock:added") + .when(header("CamelHazelcastListenerAction").isEqualTo("removed")) .log("...removed") - .to("mock:removed") - .otherwise() - .log("fail!"); ------------------------------------------------------------------------------------------------ + .to("mock:removed") + .otherwise() + .log("fail!"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + ${header.CamelHazelcastListenerAction} == 'added' + + + + + ${header.CamelHazelcastListenerAction} == 'removed' + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: hazelcast-list:mm + steps: + - log: + message: "object..." + - choice: + when: + - simple: "${header.CamelHazelcastListenerAction} == 'added'" + steps: + - log: + message: "...added" + - to: + uri: mock:added + - simple: "${header.CamelHazelcastListenerAction} == 'removed'" + steps: + - log: + message: "...removed" + - to: + uri: mock:removed + otherwise: + steps: + - log: + message: "fail!" +---- +==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-map-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-map-component.adoc index 16cea6f4a1fd3..7658013ac5906 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-map-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-map-component.adoc @@ -286,26 +286,108 @@ the message body. Here's a sample: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------- -fromF("hazelcast-%sfoo", HazelcastConstants.MAP_PREFIX) -.log("object...") -.choice() - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.ADDED)) - .log("...added") - .to("mock:added") - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.ENVICTED)) - .log("...envicted") - .to("mock:envicted") - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.UPDATED)) - .log("...updated") - .to("mock:updated") - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.REMOVED)) - .log("...removed") - .to("mock:removed") - .otherwise() - .log("fail!"); --------------------------------------------------------------------------------------------- +---- +from("hazelcast-map:foo") + .log("object...") + .choice() + .when(header("CamelHazelcastListenerAction").isEqualTo("added")) + .log("...added") + .to("mock:added") + .when(header("CamelHazelcastListenerAction").isEqualTo("envicted")) + .log("...envicted") + .to("mock:envicted") + .when(header("CamelHazelcastListenerAction").isEqualTo("updated")) + .log("...updated") + .to("mock:updated") + .when(header("CamelHazelcastListenerAction").isEqualTo("removed")) + .log("...removed") + .to("mock:removed") + .otherwise() + .log("fail!"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + ${header.CamelHazelcastListenerAction} == 'added' + + + + + ${header.CamelHazelcastListenerAction} == 'envicted' + + + + + ${header.CamelHazelcastListenerAction} == 'updated' + + + + + ${header.CamelHazelcastListenerAction} == 'removed' + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: hazelcast-map:foo + steps: + - log: + message: "object..." + - choice: + when: + - simple: "${header.CamelHazelcastListenerAction} == 'added'" + steps: + - log: + message: "...added" + - to: + uri: mock:added + - simple: "${header.CamelHazelcastListenerAction} == 'envicted'" + steps: + - log: + message: "...envicted" + - to: + uri: mock:envicted + - simple: "${header.CamelHazelcastListenerAction} == 'updated'" + steps: + - log: + message: "...updated" + - to: + uri: mock:updated + - simple: "${header.CamelHazelcastListenerAction} == 'removed'" + steps: + - log: + message: "...removed" + - to: + uri: mock:removed + otherwise: + steps: + - log: + message: "fail!" +---- +==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-multimap-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-multimap-component.adoc index 3305868ea57f1..41944d4903e0c 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-multimap-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-multimap-component.adoc @@ -184,22 +184,79 @@ variables as for the map cache consumer (except the update and eviction listener). The only difference is the *multimap* prefix inside the URI. Here is a sample: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------------- -fromF("hazelcast-%sbar", HazelcastConstants.MULTIMAP_PREFIX) -.log("object...") -.choice() - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.ADDED)) - .log("...added") - .to("mock:added") - //.when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.ENVICTED)) - // .log("...envicted") - // .to("mock:envicted") - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.REMOVED)) - .log("...removed") - .to("mock:removed") +---- +from("hazelcast-multimap:bar") + .log("object...") + .choice() + .when(header("CamelHazelcastListenerAction").isEqualTo("added")) + .log("...added") + .to("mock:added") + .when(header("CamelHazelcastListenerAction").isEqualTo("removed")) + .log("...removed") + .to("mock:removed") .otherwise() - .log("fail!"); --------------------------------------------------------------------------------------------------- + .log("fail!"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + ${header.CamelHazelcastListenerAction} == 'added' + + + + + ${header.CamelHazelcastListenerAction} == 'removed' + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: hazelcast-multimap:bar + steps: + - log: + message: "object..." + - choice: + when: + - simple: "${header.CamelHazelcastListenerAction} == 'added'" + steps: + - log: + message: "...added" + - to: + uri: mock:added + - simple: "${header.CamelHazelcastListenerAction} == 'removed'" + steps: + - log: + message: "...removed" + - to: + uri: mock:removed + otherwise: + steps: + - log: + message: "fail!" +---- +==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-ringbuffer-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-ringbuffer-component.adoc index 2f97f05624864..ea5feaec835d7 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-ringbuffer-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-ringbuffer-component.adoc @@ -68,15 +68,49 @@ Spring XML:: === Example for *readonce from head*: -Java DSL: - +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------------------------------ +---- from("direct:get") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.READ_ONCE_HEAD)) -.toF("hazelcast-%sbar", HazelcastConstants.RINGBUFFER_PREFIX) -.to("seda:out"); ------------------------------------------------------------------------------------------------ + .setHeader("CamelHazelcastOperationType", constant("readOnceHead")) + .to("hazelcast-ringbuffer:bar") + .to("seda:out"); +---- + +XML:: ++ +[source,xml] +---- + + + + readOnceHead + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:get + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: readOnceHead + - to: + uri: hazelcast-ringbuffer:bar + - to: + uri: seda:out +---- +==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-topic-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-topic-component.adoc index 2470153d42ebb..7f7857a119122 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-topic-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-topic-component.adoc @@ -33,12 +33,45 @@ The topic producer provides only one operation (publish). === Example for *publish*: +[tabs] +==== +Java:: ++ [source,java] ----------------------------------------------------------------------------------------- -from("direct:add") -.setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.PUBLISH)) -.toF("hazelcast-%sbar", HazelcastConstants.PUBLISH_OPERATION); ----------------------------------------------------------------------------------------- +---- +from(“direct:add”) + .setHeader(“CamelHazelcastOperationType”, constant(“publish”)) + .to(“hazelcast-topic:bar”); +---- + +XML:: ++ +[source,xml] +---- + + + + publish + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:add + steps: + - setHeader: + name: CamelHazelcastOperationType + constant: publish + - to: + uri: hazelcast-topic:bar +---- +==== == Topic consumer – from(“hazelcast-topic:foo”) @@ -47,15 +80,58 @@ component is supposed to support multiple consumption as it's expected when it comes to topics, so you are free to have as many consumers as you need on the same hazelcast topic. +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------- -fromF("hazelcast-%sfoo", HazelcastConstants.TOPIC_PREFIX) - .choice() - .when(header(HazelcastConstants.LISTENER_ACTION).isEqualTo(HazelcastConstants.RECEIVED)) - .log("...message received") - .otherwise() - .log("...this should never have happened") --------------------------------------------------------------------------------------------- +---- +from(“hazelcast-topic:foo”) + .choice() + .when(header(“CamelHazelcastListenerAction”).isEqualTo(“received”)) + .log(“...message received”) + .otherwise() + .log(“...this should never have happened”); +---- + +XML:: ++ +[source,xml] +---- + + + + + ${header.CamelHazelcastListenerAction} == 'received' + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: hazelcast-topic:foo + steps: + - choice: + when: + - simple: “${header.CamelHazelcastListenerAction} == 'received'” + steps: + - log: + message: “...message received” + otherwise: + steps: + - log: + message: “...this should never have happened” +---- +==== include::spring-boot:partial$starter.adoc[] From 6689ef6960f0f3b77e9ac4b6322d5cab9ed527dc Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:06:42 +0200 Subject: [PATCH 55/87] CAMEL-23789: Make Event component docs multi-DSL friendly (Wave 1) Converted remaining untabbed examples (wildcard subscriptions, async processing, backpressure, event batching, distributed events) to multi-DSL tabs with Java/XML/YAML alternatives. Split multi-parameter URIs into YAML parameters blocks. Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/event-component.adoc | 244 ++++++++++++++++++ 1 file changed, 244 insertions(+) diff --git a/components/camel-event/src/main/docs/event-component.adoc b/components/camel-event/src/main/docs/event-component.adoc index 304547da6cc5c..19a5fe657024d 100644 --- a/components/camel-event/src/main/docs/event-component.adoc +++ b/components/camel-event/src/main/docs/event-component.adoc @@ -114,6 +114,10 @@ The following event types are available (corresponding to `org.apache.camel.spi. Instead of listing each event type individually, you can use wildcard patterns with a `*` suffix to match all event types that start with a given prefix. +[tabs] +==== +Java:: ++ [source,java] ---- // Subscribe to all route events (RouteStarted, RouteStopped, RouteAdded, etc.) @@ -133,6 +137,65 @@ from("event:Route*,ExchangeFailed") .log("Event: ${header.CamelEventType}"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + + + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: "event:Route*" + steps: + - log: + message: "Route event: ${header.CamelEventType}" + +- route: + from: + uri: "event:Exchange*" + steps: + - log: + message: "Exchange event: ${header.CamelEventType}" + +- route: + from: + uri: "event:*" + steps: + - log: + message: "Event: ${header.CamelEventType}" + +- route: + from: + uri: "event:Route*,ExchangeFailed" + steps: + - log: + message: "Event: ${header.CamelEventType}" +---- +==== + == Filtering You can filter events using the `include` option. For route events, this matches the route ID. @@ -511,6 +574,10 @@ This dispatches event processing to a thread pool, freeing the event notifier th Use the `asyncPoolSize` option to control the maximum number of concurrent event processing threads (default: 10). +[tabs] +==== +Java:: ++ [source,java] ---- // Process events asynchronously with default pool size (10) @@ -522,6 +589,46 @@ from("event:Exchange*?async=true&asyncPoolSize=5") .log("Exchange event: ${header.CamelEventType}"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: event:ExchangeCompleted + parameters: + async: true + steps: + - log: + message: "Exchange completed: ${header.CamelEventExchangeId}" + +- route: + from: + uri: "event:Exchange*" + parameters: + async: true + asyncPoolSize: 5 + steps: + - log: + message: "Exchange event: ${header.CamelEventType}" +---- +==== + === Backpressure When async processing is enabled, events are placed into a bounded blocking queue @@ -532,6 +639,10 @@ the `backpressurePolicy` option controls the behavior: * `Drop` — silently discards the event. * `Fail` — throws an exception. +[tabs] +==== +Java:: ++ [source,java] ---- // Async with a small queue and Drop policy (discard events when overloaded) @@ -543,6 +654,49 @@ from("event:Exchange*?async=true&asyncQueueSize=500&backpressurePolicy=Fail") .log("Exchange event: ${header.CamelEventType}"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: event:ExchangeCompleted + parameters: + async: true + asyncQueueSize: 100 + backpressurePolicy: Drop + steps: + - log: + message: "Exchange completed: ${header.CamelEventExchangeId}" + +- route: + from: + uri: "event:Exchange*" + parameters: + async: true + asyncQueueSize: 500 + backpressurePolicy: Fail + steps: + - log: + message: "Exchange event: ${header.CamelEventType}" +---- +==== + == Event Batching For high-throughput scenarios, events can be collected into batches and dispatched as a single @@ -555,6 +709,10 @@ controls the maximum time to wait for a full batch before flushing a partial bat When batching is enabled, the `CamelEventBatchSize` header is set with the number of events in the batch. +[tabs] +==== +Java:: ++ [source,java] ---- // Collect events in batches of 50, flush every 2 seconds @@ -566,6 +724,48 @@ from("event:Exchange*?async=true&batchSize=100&batchTimeout=5000") .log("Batch of ${header.CamelEventBatchSize} exchange events"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: event:ExchangeCompleted + parameters: + batchSize: 50 + batchTimeout: 2000 + steps: + - log: + message: "Received batch of ${header.CamelEventBatchSize} events" + +- route: + from: + uri: "event:Exchange*" + parameters: + async: true + batchSize: 100 + batchTimeout: 5000 + steps: + - log: + message: "Batch of ${header.CamelEventBatchSize} exchange events" +---- +==== + == JBang Quick Start You can quickly try the Event component using xref:manual::camel-jbang.adoc[Camel CLI]. @@ -613,6 +813,10 @@ camel run event-monitor.yaml The Event component captures events within a single CamelContext (JVM). To propagate events across multiple Camel instances, use standard Camel routes to forward events to a messaging system: +[tabs] +==== +Java:: ++ [source,java] ---- // Producer side: capture local events and publish to Kafka @@ -625,6 +829,46 @@ from("kafka:camel-events") .to("log:distributed-events"); ---- +XML:: ++ +[source,xml] +---- + + + + ${header.CamelEventType}: ${header.CamelEventRouteId} at ${header.CamelEventTimestamp} + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: event:RouteStarted,RouteStopped,ExchangeFailed + steps: + - setBody: + simple: "${header.CamelEventType}: ${header.CamelEventRouteId} at ${header.CamelEventTimestamp}" + - to: + uri: kafka:camel-events + +- route: + from: + uri: kafka:camel-events + steps: + - to: + uri: log:distributed-events +---- +==== + This approach is transport-agnostic — you can use Kafka, JMS, AMQP, NATS, or any other Camel messaging component. It gives you full control over event serialization, filtering, and routing logic. From 00537cea05d7d3186727170fd880306346d229aa Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:08:09 +0200 Subject: [PATCH 56/87] CAMEL-23789: Make Azure CosmosDB component docs multi-DSL friendly (Wave 1) Converted 10 producer operation examples from Java-only .process() blocks to multi-DSL tabs with setHeader DSL equivalents. Resolved CosmosDbConstants to string values. Converted createItem/replaceItem from Java Map to JSON body. Marked replaceDatabaseThroughput as Java-only (requires SDK ThroughputProperties). Fixed typo myAwersomeContainer -> myAwesomeContainer. Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/azure-cosmosdb-component.adoc | 619 +++++++++++++++--- 1 file changed, 517 insertions(+), 102 deletions(-) diff --git a/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc b/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc index 2b9a4f86e7fa8..fecc61681b104 100644 --- a/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc +++ b/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc @@ -252,160 +252,575 @@ YAML:: - `createDatabase`: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(CosmosDbConstants.DATABASE_NAME, "myDb"); - }) - .to("azure-cosmosdb://?operation=createDatabase") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelAzureCosmosDbDatabaseName", constant("myDb")) + .to("azure-cosmosdb://?operation=createDatabase") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myDb + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureCosmosDbDatabaseName + constant: myDb + - to: + uri: azure-cosmosdb:// + parameters: + operation: createDatabase + - to: + uri: mock:result +---- +==== - `deleteDatabase`: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(CosmosDbConstants.DATABASE_NAME, "myDb"); - }) - .to("azure-cosmosdb://?operation=deleteDatabase") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelAzureCosmosDbDatabaseName", constant("myDb")) + .to("azure-cosmosdb://?operation=deleteDatabase") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + myDb + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureCosmosDbDatabaseName + constant: myDb + - to: + uri: azure-cosmosdb:// + parameters: + operation: deleteDatabase + - to: + uri: mock:result +---- +==== - `createContainer`: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(CosmosDbConstants.DATABASE_NAME, "databaseName"); - exchange.getIn().setHeader(CosmosDbConstants.CONTAINER_NAME, "containerName"); - exchange.getIn().setHeader(CosmosDbConstants.CONTAINER_PARTITION_KEY_PATH, "path"); - exchange.getIn().setHeader(CosmosDbConstants.CREATE_DATABASE_IF_NOT_EXIST, true); - }) - .to("azure-cosmosdb://?operation=createContainer") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelAzureCosmosDbDatabaseName", constant("databaseName")) + .setHeader("CamelAzureCosmosDbContainerName", constant("containerName")) + .setHeader("CamelAzureCosmosDbContainerPartitionKeyPath", constant("path")) + .setHeader("CamelAzureCosmosDbCreateDatabaseIfNotExist", constant(true)) + .to("azure-cosmosdb://?operation=createContainer") + .to("mock:result"); +---- +XML:: ++ +[source,xml] +---- + + + + databaseName + + + containerName + + + path + + + true + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureCosmosDbDatabaseName + constant: databaseName + - setHeader: + name: CamelAzureCosmosDbContainerName + constant: containerName + - setHeader: + name: CamelAzureCosmosDbContainerPartitionKeyPath + constant: path + - setHeader: + name: CamelAzureCosmosDbCreateDatabaseIfNotExist + constant: true + - to: + uri: azure-cosmosdb:// + parameters: + operation: createContainer + - to: + uri: mock:result +---- +==== - `deleteContainer`: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(CosmosDbConstants.DATABASE_NAME, "databaseName"); - exchange.getIn().setHeader(CosmosDbConstants.CONTAINER_NAME, "containerName"); - }) - .to("azure-cosmosdb://?operation=deleteContainer") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelAzureCosmosDbDatabaseName", constant("databaseName")) + .setHeader("CamelAzureCosmosDbContainerName", constant("containerName")) + .to("azure-cosmosdb://?operation=deleteContainer") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + databaseName + + + containerName + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureCosmosDbDatabaseName + constant: databaseName + - setHeader: + name: CamelAzureCosmosDbContainerName + constant: containerName + - to: + uri: azure-cosmosdb:// + parameters: + operation: deleteContainer + - to: + uri: mock:result +---- +==== - `replaceDatabaseThroughput`: +._Java-only: requires SDK ThroughputProperties object_ + [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { - exchange.getIn().setHeader(CosmosDbConstants.DATABASE_NAME, "databaseName"); - exchange.getIn().setHeader(CosmosDbConstants.THROUGHPUT_PROPERTIES, - ThroughputProperties.createManualThroughput(700)); - }) - .to("azure-cosmosdb://?operation=replaceDatabaseThroughput") - .to("mock:result"); --------------------------------------------------------------------------------- + exchange.getIn().setHeader("CamelAzureCosmosDbDatabaseName", "databaseName"); + exchange.getIn().setHeader("CamelAzureCosmosDbThroughputProperties", + ThroughputProperties.createManualThroughput(700)); + }) + .to("azure-cosmosdb://?operation=replaceDatabaseThroughput") + .to("mock:result"); +---- - `queryContainers`: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(CosmosDbConstants.DATABASE_NAME, "databaseName"); - exchange.getIn().setHeader(CosmosDbConstants.QUERY, "SELECT * from c where c.id = 'myAwersomeContainer'"); - }) - .to("azure-cosmosdb://?operation=queryContainers") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelAzureCosmosDbDatabaseName", constant("databaseName")) + .setHeader("CamelAzureCosmosDbQuery", constant("SELECT * from c where c.id = 'myAwesomeContainer'")) + .to("azure-cosmosdb://?operation=queryContainers") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + databaseName + + + SELECT * from c where c.id = 'myAwesomeContainer' + + + + +---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureCosmosDbDatabaseName + constant: databaseName + - setHeader: + name: CamelAzureCosmosDbQuery + constant: "SELECT * from c where c.id = 'myAwesomeContainer'" + - to: + uri: azure-cosmosdb:// + parameters: + operation: queryContainers + - to: + uri: mock:result +---- +==== - `createItem`: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // create item to send - final Map item = new HashMap<>(); - item1.put("id", "test-id-1"); - item1.put("partition", "test-1"); - item1.put("field1", "awesome!"); - - exchange.getIn().setHeader(CosmosDbConstants.DATABASE_NAME, "databaseName"); - exchange.getIn().setHeader(CosmosDbConstants.CONTAINER_NAME, "containerName"); - exchange.getIn().setHeader(CosmosDbConstants.CONTAINER_PARTITION_KEY_PATH, "partition"); - exchange.getIn().setHeader(CosmosDbConstants.ITEM_PARTITION_KEY, "test-1"); - exchange.getIn().setBody(item); - }) - .to("azure-cosmosdb://?operation=createItem") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelAzureCosmosDbDatabaseName", constant("databaseName")) + .setHeader("CamelAzureCosmosDbContainerName", constant("containerName")) + .setHeader("CamelAzureCosmosDbContainerPartitionKeyPath", constant("partition")) + .setHeader("CamelAzureCosmosDbItemPartitionKey", constant("test-1")) + .setBody(constant("{\"id\":\"test-id-1\",\"partition\":\"test-1\",\"field1\":\"awesome!\"}")) + .to("azure-cosmosdb://?operation=createItem") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + databaseName + + + containerName + + + partition + + + test-1 + + + {"id":"test-id-1","partition":"test-1","field1":"awesome!"} + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureCosmosDbDatabaseName + constant: databaseName + - setHeader: + name: CamelAzureCosmosDbContainerName + constant: containerName + - setHeader: + name: CamelAzureCosmosDbContainerPartitionKeyPath + constant: partition + - setHeader: + name: CamelAzureCosmosDbItemPartitionKey + constant: "test-1" + - setBody: + constant: '{"id":"test-id-1","partition":"test-1","field1":"awesome!"}' + - to: + uri: azure-cosmosdb:// + parameters: + operation: createItem + - to: + uri: mock:result +---- +==== - `replaceItem`: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - // create item to send - final Map item = new HashMap<>(); - item1.put("id", "test-id-1"); - item1.put("partition", "test-1"); - item1.put("field1", "awesome!"); - - exchange.getIn().setHeader(CosmosDbConstants.DATABASE_NAME, "databaseName"); - exchange.getIn().setHeader(CosmosDbConstants.CONTAINER_NAME, "containerName"); - exchange.getIn().setHeader(CosmosDbConstants.ITEM_PARTITION_KEY, "test-1"); - exchange.getIn().setHeader(CosmosDbConstants.ITEM_ID, "test-id-1"); - exchange.getIn().setBody(item); - }) - .to("azure-cosmosdb://?operation=replaceItem") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelAzureCosmosDbDatabaseName", constant("databaseName")) + .setHeader("CamelAzureCosmosDbContainerName", constant("containerName")) + .setHeader("CamelAzureCosmosDbItemPartitionKey", constant("test-1")) + .setHeader("CamelAzureCosmosDbItemId", constant("test-id-1")) + .setBody(constant("{\"id\":\"test-id-1\",\"partition\":\"test-1\",\"field1\":\"awesome!\"}")) + .to("azure-cosmosdb://?operation=replaceItem") + .to("mock:result"); +---- +XML:: ++ +[source,xml] +---- + + + + databaseName + + + containerName + + + test-1 + + + test-id-1 + + + {"id":"test-id-1","partition":"test-1","field1":"awesome!"} + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureCosmosDbDatabaseName + constant: databaseName + - setHeader: + name: CamelAzureCosmosDbContainerName + constant: containerName + - setHeader: + name: CamelAzureCosmosDbItemPartitionKey + constant: "test-1" + - setHeader: + name: CamelAzureCosmosDbItemId + constant: "test-id-1" + - setBody: + constant: '{"id":"test-id-1","partition":"test-1","field1":"awesome!"}' + - to: + uri: azure-cosmosdb:// + parameters: + operation: replaceItem + - to: + uri: mock:result +---- +==== - `deleteItem`: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(CosmosDbConstants.DATABASE_NAME, "databaseName"); - exchange.getIn().setHeader(CosmosDbConstants.CONTAINER_NAME, "containerName"); - exchange.getIn().setHeader(CosmosDbConstants.ITEM_PARTITION_KEY, "test-1"); - exchange.getIn().setHeader(CosmosDbConstants.ITEM_ID, "test-id-1"); - exchange.getIn().setBody(item); - }) - .to("azure-cosmosdb://?operation=deleteItem") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelAzureCosmosDbDatabaseName", constant("databaseName")) + .setHeader("CamelAzureCosmosDbContainerName", constant("containerName")) + .setHeader("CamelAzureCosmosDbItemPartitionKey", constant("test-1")) + .setHeader("CamelAzureCosmosDbItemId", constant("test-id-1")) + .to("azure-cosmosdb://?operation=deleteItem") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + databaseName + + + containerName + + + test-1 + + + test-id-1 + + + + +---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureCosmosDbDatabaseName + constant: databaseName + - setHeader: + name: CamelAzureCosmosDbContainerName + constant: containerName + - setHeader: + name: CamelAzureCosmosDbItemPartitionKey + constant: "test-1" + - setHeader: + name: CamelAzureCosmosDbItemId + constant: "test-id-1" + - to: + uri: azure-cosmosdb:// + parameters: + operation: deleteItem + - to: + uri: mock:result +---- +==== - `queryItems`: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .process(exchange -> { - exchange.getIn().setHeader(CosmosDbConstants.DATABASE_NAME, "databaseName"); - exchange.getIn().setHeader(CosmosDbConstants.CONTAINER_NAME, "containerName"); - exchange.getIn().setHeader(CosmosDbConstants.QUERY, "SELECT c.id,c.field2,c.field1 from c where c.id = 'test-id-1'"); - }) - .to("azure-cosmosdb://?operation=queryItems") - .to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelAzureCosmosDbDatabaseName", constant("databaseName")) + .setHeader("CamelAzureCosmosDbContainerName", constant("containerName")) + .setHeader("CamelAzureCosmosDbQuery", constant("SELECT c.id,c.field2,c.field1 from c where c.id = 'test-id-1'")) + .to("azure-cosmosdb://?operation=queryItems") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + databaseName + + + containerName + + + SELECT c.id,c.field2,c.field1 from c where c.id = 'test-id-1' + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureCosmosDbDatabaseName + constant: databaseName + - setHeader: + name: CamelAzureCosmosDbContainerName + constant: containerName + - setHeader: + name: CamelAzureCosmosDbQuery + constant: "SELECT c.id,c.field2,c.field1 from c where c.id = 'test-id-1'" + - to: + uri: azure-cosmosdb:// + parameters: + operation: queryItems + - to: + uri: mock:result +---- +==== === Azure CosmosDB Consumer From 4c339070f274b5b565cdb7619600cbaae5923c8b Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:09:10 +0200 Subject: [PATCH 57/87] CAMEL-23789: Make Azure Storage Queue component docs multi-DSL friendly (Wave 1) Converted 8 producer operation examples to multi-DSL tabs. Resolved QueueConstants to string values. Simplified sendMessage/updateMessage by converting .process() body-setting to setBody DSL. Marked listQueues as Java-only (requires SDK QueuesSegmentOptions). Simplified receiveMessages/peekMessages by removing Java-only .process() handlers. Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../docs/azure-storage-queue-component.adoc | 412 ++++++++++++++---- 1 file changed, 331 insertions(+), 81 deletions(-) diff --git a/components/camel-azure/camel-azure-storage-queue/src/main/docs/azure-storage-queue-component.adoc b/components/camel-azure/camel-azure-storage-queue/src/main/docs/azure-storage-queue-component.adoc index a3e437ea0f385..94a5e7a38293f 100644 --- a/components/camel-azure/camel-azure-storage-queue/src/main/docs/azure-storage-queue-component.adoc +++ b/components/camel-azure/camel-azure-storage-queue/src/main/docs/azure-storage-queue-component.adoc @@ -255,141 +255,391 @@ YAML:: === Producer Operations Examples - `listQueues`: +._Java-only: requires SDK QueuesSegmentOptions object_ + [source,java] ------------------------------------------------------------------------ +---- from("direct:start") .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g., to only returns a list of queues with 'awesome' prefix: - exchange.getIn().setHeader(QueueConstants.QUEUES_SEGMENT_OPTIONS, new QueuesSegmentOptions().setPrefix("awesome")); - }) + exchange.getIn().setHeader("CamelAzureStorageQueueSegmentOptions", + new QueuesSegmentOptions().setPrefix("awesome")); + }) .to("azure-storage-queue://cameldev?serviceClient=#client&operation=listQueues") .log("${body}") .to("mock:result"); ------------------------------------------------------------------------ - +---- - `createQueue`: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------ +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(QueueConstants.QUEUE_NAME, "overrideName"); - }) + .setHeader("CamelAzureStorageQueueName", constant("overrideName")) .to("azure-storage-queue://cameldev/test?serviceClient=#client&operation=createQueue"); ------------------------------------------------------------------------ +---- + +XML:: ++ +[source,xml] +---- + + + + overrideName + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageQueueName + constant: overrideName + - to: + uri: azure-storage-queue://cameldev/test + parameters: + serviceClient: "#client" + operation: createQueue +---- +==== - `deleteQueue`: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------ +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(QueueConstants.QUEUE_NAME, "overrideName"); - }) + .setHeader("CamelAzureStorageQueueName", constant("overrideName")) .to("azure-storage-queue://cameldev/test?serviceClient=#client&operation=deleteQueue"); ------------------------------------------------------------------------ +---- + +XML:: ++ +[source,xml] +---- + + + + overrideName + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageQueueName + constant: overrideName + - to: + uri: azure-storage-queue://cameldev/test + parameters: + serviceClient: "#client" + operation: deleteQueue +---- +==== - `clearQueue`: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------ +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setHeader(QueueConstants.QUEUE_NAME, "overrideName"); - }) + .setHeader("CamelAzureStorageQueueName", constant("overrideName")) .to("azure-storage-queue://cameldev/test?serviceClient=#client&operation=clearQueue"); ------------------------------------------------------------------------ +---- + +XML:: ++ +[source,xml] +---- + + + + overrideName + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageQueueName + constant: overrideName + - to: + uri: azure-storage-queue://cameldev/test + parameters: + serviceClient: "#client" + operation: clearQueue +---- +==== - `sendMessage`: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------ +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setBody("message to send"); - // we set a visibility of 1min - exchange.getIn().setHeader(QueueConstants.VISIBILITY_TIMEOUT, Duration.ofMinutes(1)); - }) + .setBody(constant("message to send")) .to("azure-storage-queue://cameldev/test?serviceClient=#client"); ------------------------------------------------------------------------ +---- + +XML:: ++ +[source,xml] +---- + + + + message to send + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: message to send + - to: + uri: azure-storage-queue://cameldev/test + parameters: + serviceClient: "#client" +---- +==== - `deleteMessage`: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------ +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - // Mandatory header: - exchange.getIn().setHeader(QueueConstants.MESSAGE_ID, "1"); - // Mandatory header: - exchange.getIn().setHeader(QueueConstants.POP_RECEIPT, "PAAAAHEEERXXX-1"); - }) + .setHeader("CamelAzureStorageQueueMessageId", constant("1")) + .setHeader("CamelAzureStorageQueuePopReceipt", constant("PAAAAHEEERXXX-1")) .to("azure-storage-queue://cameldev/test?serviceClient=#client&operation=deleteMessage"); ------------------------------------------------------------------------ +---- + +XML:: ++ +[source,xml] +---- + + + + 1 + + + PAAAAHEEERXXX-1 + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAzureStorageQueueMessageId + constant: "1" + - setHeader: + name: CamelAzureStorageQueuePopReceipt + constant: PAAAAHEEERXXX-1 + - to: + uri: azure-storage-queue://cameldev/test + parameters: + serviceClient: "#client" + operation: deleteMessage +---- +==== - `receiveMessages`: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------ +---- from("direct:start") .to("azure-storage-queue://cameldev/test?serviceClient=#client&operation=receiveMessages") - .process(exchange -> { - final List messageItems = exchange.getMessage().getBody(List.class); - messageItems.forEach(messageItem -> System.out.println(messageItem.getMessageText())); - }) - .to("mock:result"); ------------------------------------------------------------------------ + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: azure-storage-queue://cameldev/test + parameters: + serviceClient: "#client" + operation: receiveMessages + - to: + uri: mock:result +---- +==== - `peekMessages`: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------ +---- from("direct:start") .to("azure-storage-queue://cameldev/test?serviceClient=#client&operation=peekMessages") - .process(exchange -> { - final List messageItems = exchange.getMessage().getBody(List.class); - messageItems.forEach(messageItem -> System.out.println(messageItem.getMessageText())); - }) - .to("mock:result"); ------------------------------------------------------------------------ + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: azure-storage-queue://cameldev/test + parameters: + serviceClient: "#client" + operation: peekMessages + - to: + uri: mock:result +---- +==== - `updateMessage`: +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------------------ +---- from("direct:start") - .process(exchange -> { - // set the header you want the producer to evaluate, refer to the previous - // section to learn about the headers that can be set - // e.g.: - exchange.getIn().setBody("new message text"); - // Mandatory header: - exchange.getIn().setHeader(QueueConstants.MESSAGE_ID, "1"); - // Mandatory header: - exchange.getIn().setHeader(QueueConstants.POP_RECEIPT, "PAAAAHEEERXXX-1"); - // Mandatory header: - exchange.getIn().setHeader(QueueConstants.VISIBILITY_TIMEOUT, Duration.ofMinutes(1)); - }) + .setBody(constant("new message text")) + .setHeader("CamelAzureStorageQueueMessageId", constant("1")) + .setHeader("CamelAzureStorageQueuePopReceipt", constant("PAAAAHEEERXXX-1")) .to("azure-storage-queue://cameldev/test?serviceClient=#client&operation=updateMessage"); ------------------------------------------------------------------------ +---- + +XML:: ++ +[source,xml] +---- + + + + new message text + + + 1 + + + PAAAAHEEERXXX-1 + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: new message text + - setHeader: + name: CamelAzureStorageQueueMessageId + constant: "1" + - setHeader: + name: CamelAzureStorageQueuePopReceipt + constant: PAAAAHEEERXXX-1 + - to: + uri: azure-storage-queue://cameldev/test + parameters: + serviceClient: "#client" + operation: updateMessage +---- +==== == Important Development Notes From 6ee7ca50f833d35bcad99cdb5e38b87d8c58014d Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:10:20 +0200 Subject: [PATCH 58/87] CAMEL-23789: Make Google Firestore component docs multi-DSL friendly (Wave 1) Converted 6 remaining untabbed producer examples to multi-DSL tabs. Replaced Java HashMap/Date constructors with JSON string bodies for createDocument, setDocument (with merge), and updateDocument. Added XML/YAML alternatives for URI format example and listCollections. Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/google-firestore-component.adoc | 354 +++++++++++++++--- 1 file changed, 309 insertions(+), 45 deletions(-) diff --git a/components/camel-google/camel-google-firestore/src/main/docs/google-firestore-component.adoc b/components/camel-google/camel-google-firestore/src/main/docs/google-firestore-component.adoc index 1321eabacfa79..4af72ee8ea77a 100644 --- a/components/camel-google/camel-google-firestore/src/main/docs/google-firestore-component.adoc +++ b/components/camel-google/camel-google-firestore/src/main/docs/google-firestore-component.adoc @@ -67,13 +67,53 @@ You can append query options to the URI in the following format: `?options=value For example, to get a document from the `users` collection: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setHeader("CamelGoogleFirestoreDocumentId", constant("user123")) .to("google-firestore://users?operation=getDocumentById&serviceAccountKey=/path/to/key.json&projectId=my-project") .to("log:result"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + user123 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleFirestoreDocumentId + constant: user123 + - to: + uri: google-firestore://users + parameters: + operation: getDocumentById + serviceAccountKey: /path/to/key.json + projectId: my-project + - to: + uri: log:result +---- +==== // component options: START @@ -110,23 +150,53 @@ For operations that require document data (`setDocument`, `createDocument`, `upd JSON String Example: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -// Using JSON string as input -String json = """ - { - "name": "John Doe", - "email": "john@example.com", - "age": 30, - "active": true - } - """; - +---- from("direct:start") - .setBody(constant(json)) + .setBody(constant("{\"name\":\"John Doe\",\"email\":\"john@example.com\",\"age\":30,\"active\":true}")) .setHeader("CamelGoogleFirestoreDocumentId", constant("user123")) .to("google-firestore://users?operation=setDocument"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + {"name":"John Doe","email":"john@example.com","age":30,"active":true} + + + user123 + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: '{"name":"John Doe","email":"john@example.com","age":30,"active":true}' + - setHeader: + name: CamelGoogleFirestoreDocumentId + constant: user123 + - to: + uri: google-firestore://users + parameters: + operation: setDocument +---- +==== === Google Firestore Consumer @@ -217,52 +287,169 @@ YAML:: This operation creates a new document with an auto-generated unique ID: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -Map document = new HashMap<>(); -document.put("name", "John Doe"); -document.put("email", "john@example.com"); -document.put("age", 30); - +---- from("direct:start") - .setBody(constant(document)) + .setBody(constant("{\"name\":\"John Doe\",\"email\":\"john@example.com\",\"age\":30}")) .to("google-firestore://users?operation=createDocument") .log("Created document with ID: ${header.CamelGoogleFirestoreResponseDocumentId}"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + {"name":"John Doe","email":"john@example.com","age":30} + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: '{"name":"John Doe","email":"john@example.com","age":30}' + - to: + uri: google-firestore://users + parameters: + operation: createDocument + - log: + message: "Created document with ID: ${header.CamelGoogleFirestoreResponseDocumentId}" +---- +==== === Set Document with Specific ID This operation creates or overwrites a document with a specific ID: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -Map document = new HashMap<>(); -document.put("name", "Jane Doe"); -document.put("email", "jane@example.com"); - +---- from("direct:start") - .setBody(constant(document)) + .setBody(constant("{\"name\":\"Jane Doe\",\"email\":\"jane@example.com\"}")) .setHeader("CamelGoogleFirestoreDocumentId", constant("user123")) .to("google-firestore://users?operation=setDocument") .log("Document saved"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + {"name":"Jane Doe","email":"jane@example.com"} + + + user123 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: '{"name":"Jane Doe","email":"jane@example.com"}' + - setHeader: + name: CamelGoogleFirestoreDocumentId + constant: user123 + - to: + uri: google-firestore://users + parameters: + operation: setDocument + - log: + message: "Document saved" +---- +==== === Set Document with Merge To merge data with an existing document instead of overwriting: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -Map updates = new HashMap<>(); -updates.put("lastLogin", new Date()); - +---- from("direct:start") - .setBody(constant(updates)) + .setBody(constant("{\"lastLogin\":\"2025-01-15T10:30:00Z\"}")) .setHeader("CamelGoogleFirestoreDocumentId", constant("user123")) .setHeader("CamelGoogleFirestoreMerge", constant(true)) .to("google-firestore://users?operation=setDocument") .log("Document merged"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + {"lastLogin":"2025-01-15T10:30:00Z"} + + + user123 + + + true + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: '{"lastLogin":"2025-01-15T10:30:00Z"}' + - setHeader: + name: CamelGoogleFirestoreDocumentId + constant: user123 + - setHeader: + name: CamelGoogleFirestoreMerge + constant: true + - to: + uri: google-firestore://users + parameters: + operation: setDocument + - log: + message: "Document merged" +---- +==== === Get Document by ID @@ -320,18 +507,57 @@ The response body will contain a `Map` with the document data, o This operation updates specific fields without overwriting the entire document: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -Map updates = new HashMap<>(); -updates.put("status", "active"); -updates.put("updatedAt", new Date()); - +---- from("direct:start") - .setBody(constant(updates)) + .setBody(constant("{\"status\":\"active\",\"updatedAt\":\"2025-01-15T10:30:00Z\"}")) .setHeader("CamelGoogleFirestoreDocumentId", constant("user123")) .to("google-firestore://users?operation=updateDocument") .log("Document updated"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + {"status":"active","updatedAt":"2025-01-15T10:30:00Z"} + + + user123 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setBody: + constant: '{"status":"active","updatedAt":"2025-01-15T10:30:00Z"}' + - setHeader: + name: CamelGoogleFirestoreDocumentId + constant: user123 + - to: + uri: google-firestore://users + parameters: + operation: updateDocument + - log: + message: "Document updated" +---- +==== === Delete Document @@ -563,13 +789,51 @@ YAML:: To list subcollections under a specific document: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setHeader("CamelGoogleFirestoreDocumentId", constant("user123")) .to("google-firestore://users?operation=listCollections") .log("Subcollections: ${body}"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + user123 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleFirestoreDocumentId + constant: user123 + - to: + uri: google-firestore://users + parameters: + operation: listCollections + - log: + message: "Subcollections: ${body}" +---- +==== == Consumer Examples From 990d67b0c50f1006f1f1ca63a6cb3310b163819d Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:11:46 +0200 Subject: [PATCH 59/87] CAMEL-23789: Make IBM COS component docs multi-DSL friendly (Wave 1) Converted 7 producer operation examples from Java-only .process() blocks to multi-DSL tabs with setHeader DSL equivalents. Resolved IBMCOSConstants to string values. Marked multipart upload and deleteObjects as Java-only (require Java File/List objects). Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/ibm-cos-component.adoc | 476 ++++++++++++++---- 1 file changed, 370 insertions(+), 106 deletions(-) diff --git a/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc b/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc index 5f90fceee38d6..9c0be3c728833 100644 --- a/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc +++ b/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc @@ -196,19 +196,59 @@ Note that several operations requires a regional endpoint, as opposed to a cross - Single Upload: This operation will upload a file to IBM COS based on the body content +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(IBMCOSConstants.KEY, "camel.txt"); - exchange.getIn().setBody("Camel rocks!"); - } - }) - .to("ibm-cos://mycamelbucket?apiKey=RAW(myApiKey)&serviceInstanceId=RAW(myServiceInstanceId)&endpointUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelIBMCOSKey", constant("camel.txt")) + .setBody(constant("Camel rocks!")) + .to("ibm-cos://mycamelbucket?apiKey=RAW(myApiKey)&serviceInstanceId=RAW(myServiceInstanceId)&endpointUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camel.txt + + + Camel rocks! + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelIBMCOSKey + constant: camel.txt + - setBody: + constant: "Camel rocks!" + - to: + uri: ibm-cos://mycamelbucket + parameters: + apiKey: RAW(myApiKey) + serviceInstanceId: RAW(myServiceInstanceId) + endpointUrl: "https://s3.us-south.cloud-object-storage.appdomain.cloud" + - to: + uri: mock:result +---- +==== This operation will upload the file camel.txt with the content "Camel rocks!" in the _mycamelbucket_ bucket. @@ -216,73 +256,149 @@ NOTE: Use `RAW()` wrapper for sensitive values like API keys to prevent property - Multipart Upload: This operation will perform a multipart upload of a file to IBM COS based on the body content +._Java-only: requires Java File object as body_ + [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(IBMCOSConstants.KEY, "largefile.zip"); - exchange.getIn().setBody(new File("src/largefile.zip")); - } - }) - .to("ibm-cos://mycamelbucket?cosClient=#cosClient&multiPartUpload=true&partSize=5242880") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelIBMCOSKey", constant("largefile.zip")) + .process(exchange -> exchange.getIn().setBody(new File("src/largefile.zip"))) + .to("ibm-cos://mycamelbucket?cosClient=#cosClient&multiPartUpload=true&partSize=5242880") + .to("mock:result"); +---- This operation will perform a multipart upload of the file largefile.zip in the _mycamelbucket_ bucket with a part size of 5MB. - CopyObject: this operation copies an object from one bucket to a different one +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(IBMCOSConstants.BUCKET_DESTINATION_NAME, "camelDestinationBucket"); - exchange.getIn().setHeader(IBMCOSConstants.KEY, "camelKey"); - exchange.getIn().setHeader(IBMCOSConstants.DESTINATION_KEY, "camelDestinationKey"); - } - }) - .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=copyObject") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelIBMCOSBucketDestinationName", constant("camelDestinationBucket")) + .setHeader("CamelIBMCOSKey", constant("camelKey")) + .setHeader("CamelIBMCOSDestinationKey", constant("camelDestinationKey")) + .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=copyObject") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camelDestinationBucket + + + camelKey + + + camelDestinationKey + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelIBMCOSBucketDestinationName + constant: camelDestinationBucket + - setHeader: + name: CamelIBMCOSKey + constant: camelKey + - setHeader: + name: CamelIBMCOSDestinationKey + constant: camelDestinationKey + - to: + uri: ibm-cos://mycamelbucket + parameters: + cosClient: "#cosClient" + operation: copyObject + - to: + uri: mock:result +---- +==== This operation will copy the object with the name expressed in the header camelKey to camelDestinationKey in the camelDestinationBucket bucket, from the bucket _mycamelbucket_. - DeleteObject: this operation deletes an object from a bucket +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(IBMCOSConstants.KEY, "camelKey"); - } - }) - .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=deleteObject") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelIBMCOSKey", constant("camelKey")) + .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=deleteObject") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camelKey + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelIBMCOSKey + constant: camelKey + - to: + uri: ibm-cos://mycamelbucket + parameters: + cosClient: "#cosClient" + operation: deleteObject + - to: + uri: mock:result +---- +==== This operation will delete the object camelKey from the bucket _mycamelbucket_. - DeleteObjects: this operation deletes multiple objects from a bucket in a single request +._Java-only: requires Java List for keys to delete_ + [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - List keys = Arrays.asList("file1.txt", "file2.txt", "file3.txt"); - exchange.getIn().setHeader(IBMCOSConstants.KEYS_TO_DELETE, keys); - } - }) - .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=deleteObjects") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .process(exchange -> { + List keys = Arrays.asList("file1.txt", "file2.txt", "file3.txt"); + exchange.getIn().setHeader("CamelIBMCOSKeysToDelete", keys); + }) + .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=deleteObjects") + .to("mock:result"); +---- This operation will delete the objects file1.txt, file2.txt, and file3.txt from the bucket _mycamelbucket_ in a single batch request. @@ -376,18 +492,52 @@ This operation will delete the bucket _mycamelbucket_. - CreateBucket: this operation creates a new bucket +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(IBMCOSConstants.BUCKET_NAME, "newBucket"); - } - }) - .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=createBucket") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelIBMCOSBucketName", constant("newBucket")) + .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=createBucket") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + newBucket + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelIBMCOSBucketName + constant: newBucket + - to: + uri: ibm-cos://mycamelbucket + parameters: + cosClient: "#cosClient" + operation: createBucket + - to: + uri: mock:result +---- +==== This operation will create a new bucket named _newBucket_. @@ -437,54 +587,168 @@ This operation will list the objects in the _mycamelbucket_ bucket. - ListObjects with prefix: this operation lists objects in a specific bucket with a prefix filter +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(IBMCOSConstants.PREFIX, "backup/"); - } - }) - .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=listObjects") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelIBMCOSPrefix", constant("backup/")) + .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=listObjects") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + backup/ + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelIBMCOSPrefix + constant: "backup/" + - to: + uri: ibm-cos://mycamelbucket + parameters: + cosClient: "#cosClient" + operation: listObjects + - to: + uri: mock:result +---- +==== This operation will list only the objects in the _mycamelbucket_ bucket that start with "backup/". - GetObject: this operation gets a single object in a specific bucket +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(IBMCOSConstants.KEY, "camelKey"); - } - }) - .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=getObject") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelIBMCOSKey", constant("camelKey")) + .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=getObject") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camelKey + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelIBMCOSKey + constant: camelKey + - to: + uri: ibm-cos://mycamelbucket + parameters: + cosClient: "#cosClient" + operation: getObject + - to: + uri: mock:result +---- +==== This operation will return an InputStream with the content of the camelKey object in _mycamelbucket_ bucket. - GetObjectRange: this operation gets a single object range in a specific bucket +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(IBMCOSConstants.KEY, "camelKey"); - exchange.getIn().setHeader(IBMCOSConstants.RANGE_START, 0L); - exchange.getIn().setHeader(IBMCOSConstants.RANGE_END, 9L); - } - }) - .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=getObjectRange") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelIBMCOSKey", constant("camelKey")) + .setHeader("CamelIBMCOSRangeStart", constant(0L)) + .setHeader("CamelIBMCOSRangeEnd", constant(9L)) + .to("ibm-cos://mycamelbucket?cosClient=#cosClient&operation=getObjectRange") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camelKey + + + 0 + + + 9 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelIBMCOSKey + constant: camelKey + - setHeader: + name: CamelIBMCOSRangeStart + constant: 0 + - setHeader: + name: CamelIBMCOSRangeEnd + constant: 9 + - to: + uri: ibm-cos://mycamelbucket + parameters: + cosClient: "#cosClient" + operation: getObjectRange + - to: + uri: mock:result +---- +==== This operation will return an InputStream with the content of the camelKey object in _mycamelbucket_ bucket, containing bytes from 0 to 9. From 67c92473c09e96e4e3e5aa899a00359a96cb2204 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:44:58 +0200 Subject: [PATCH 60/87] CAMEL-23789: Make Vertx-WebSocket, Minio, Google Storage component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../main/docs/google-storage-component.adoc | 340 +++++++++++++--- .../src/main/docs/minio-component.adoc | 384 ++++++++++++++---- .../main/docs/vertx-websocket-component.adoc | 136 ++++++- 3 files changed, 733 insertions(+), 127 deletions(-) diff --git a/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc b/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc index 7d55734e70b0f..66b1038c6f572 100644 --- a/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc +++ b/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc @@ -169,49 +169,173 @@ YAML:: - File Upload: This operation will upload a file to the Google Storage based on the body content +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- -//upload a file -byte[] payload = "Camel rocks!".getBytes(); -ByteArrayInputStream bais = new ByteArrayInputStream(payload); +---- from("direct:start") -.process( exchange -> { - exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, "camel.txt"); - exchange.getIn().setBody(bais); -}) -.to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json") -.log("uploaded file object:${header.CamelGoogleCloudStorageObjectName}, body:${body}"); --------------------------------------------------------------------------------- + .setHeader("CamelGoogleCloudStorageObjectName").constant("camel.txt") + .setBody().constant("Camel rocks!") + .to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json") + .log("uploaded file object:${header.CamelGoogleCloudStorageObjectName}, body:${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + camel.txt + + + Camel rocks! + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleCloudStorageObjectName + constant: camel.txt + - setBody: + constant: "Camel rocks!" + - to: + uri: google-storage://myCamelBucket + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + - log: + message: "uploaded file object:${header.CamelGoogleCloudStorageObjectName}, body:${body}" +---- +==== This operation will upload the file `camel.txt` with the content `"Camel rocks!"` in the myCamelBucket bucket - `CopyObject`: this operation copies an object from one bucket to a different one +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process( exchange -> { - exchange.getIn().setHeader(GoogleCloudStorageConstants.OPERATION, GoogleCloudStorageOperations.copyObject); - exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, "camel.txt" ); - exchange.getIn().setHeader(GoogleCloudStorageConstants.DESTINATION_BUCKET_NAME, "myCamelBucket_dest"); - exchange.getIn().setHeader(GoogleCloudStorageConstants.DESTINATION_OBJECT_NAME, "camel_copy.txt"); - }) - .to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelGoogleCloudStorageObjectName").constant("camel.txt") + .setHeader("CamelGoogleCloudStorageDestinationBucketName").constant("myCamelBucket_dest") + .setHeader("CamelGoogleCloudStorageDestinationObjectName").constant("camel_copy.txt") + .to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&operation=copyObject") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camel.txt + + + myCamelBucket_dest + + + camel_copy.txt + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleCloudStorageObjectName + constant: camel.txt + - setHeader: + name: CamelGoogleCloudStorageDestinationBucketName + constant: myCamelBucket_dest + - setHeader: + name: CamelGoogleCloudStorageDestinationObjectName + constant: camel_copy.txt + - to: + uri: google-storage://myCamelBucket + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + operation: copyObject + - to: + uri: mock:result +---- +==== This operation will copy the object with the name expressed in the header DESTINATION_OBJECT_NAME to the DESTINATION_BUCKET_NAME bucket, from the bucket myCamelBucket. - `DeleteObject`: this operation deletes an object from a bucket +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process( exchange -> { - exchange.getIn().setHeader(GoogleCloudStorageConstants.OPERATION, GoogleCloudStorageOperations.deleteObject); - exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, "camel.txt" ); - }) - .to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelGoogleCloudStorageObjectName").constant("camel.txt") + .to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&operation=deleteObject") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camel.txt + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleCloudStorageObjectName + constant: camel.txt + - to: + uri: google-storage://myCamelBucket + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + operation: deleteObject + - to: + uri: mock:result +---- +==== This operation will delete the object from the bucket myCamelBucket. @@ -349,30 +473,110 @@ This operation will list the objects in the myCamelBucket bucket. - `GetObject`: this operation gets a single object in a specific bucket +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") -.process( exchange -> { - exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, "camel.txt"); -}) -.to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&operation=getObject") -.to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelGoogleCloudStorageObjectName").constant("camel.txt") + .to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&operation=getObject") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camel.txt + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleCloudStorageObjectName + constant: camel.txt + - to: + uri: google-storage://myCamelBucket + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + operation: getObject + - to: + uri: mock:result +---- +==== This operation will return a Blob object instance related to the `OBJECT_NAME` object in `myCamelBucket` bucket. - `CreateDownloadLink`: this operation will return a download link +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") -.process( exchange -> { - exchange.getIn().setHeader(GoogleCloudStorageConstants.OBJECT_NAME, "camel.txt" ); - exchange.getIn().setHeader(GoogleCloudStorageConstants.DOWNLOAD_LINK_EXPIRATION_TIME, 86400000L); //1 day -}) -.to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&operation=createDownloadLink") -.to("mock:result"); --------------------------------------------------------------------------------- + .setHeader("CamelGoogleCloudStorageObjectName").constant("camel.txt") + .setHeader("CamelGoogleCloudStorageDownloadLinkExpirationTime").constant(86400000L) + .to("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&operation=createDownloadLink") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camel.txt + + + 86400000 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleCloudStorageObjectName + constant: camel.txt + - setHeader: + name: CamelGoogleCloudStorageDownloadLinkExpirationTime + constant: 86400000 + - to: + uri: google-storage://myCamelBucket + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + operation: createDownloadLink + - to: + uri: mock:result +---- +==== This operation will return a download link url for the file OBJECT_NAME in the bucket myCamelBucket. It's possible to specify the expiration time for the created link through the header DOWNLOAD_LINK_EXPIRATION_TIME. If not specified, by default it is 5 minutes. @@ -387,17 +591,45 @@ In addition to `deleteAfterRead` it has been added another option, `moveAfterRea With this option enabled the consumed object will be moved to a target `destinationBucket` instead of being only deleted. This will require specifying the destinationBucket option. As example: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json" - + "&autoCreateBucket=true" - + "&destinationBucket=myCamelProcessedBucket" - + "&moveAfterRead=true" - + "&deleteAfterRead=true" - + "&includeBody=true" - ) - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json&autoCreateBucket=true&destinationBucket=myCamelProcessedBucket&moveAfterRead=true&deleteAfterRead=true&includeBody=true") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: google-storage://myCamelBucket + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + autoCreateBucket: true + destinationBucket: myCamelProcessedBucket + moveAfterRead: true + deleteAfterRead: true + includeBody: true + steps: + - to: + uri: mock:result +---- +==== In this case, the objects consumed will be moved to myCamelProcessedBucket bucket and deleted from the original one (because of deleteAfterRead). diff --git a/components/camel-minio/src/main/docs/minio-component.adoc b/components/camel-minio/src/main/docs/minio-component.adoc index 7e4756833251c..6ab1149a7e34b 100644 --- a/components/camel-minio/src/main/docs/minio-component.adoc +++ b/components/camel-minio/src/main/docs/minio-component.adoc @@ -152,37 +152,117 @@ YAML:: - `CopyObject`: this operation copies an object from one bucket to a different one +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(MinioConstants.DESTINATION_BUCKET_NAME, "camelDestinationBucket"); - exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "camelKey"); - exchange.getIn().setHeader(MinioConstants.DESTINATION_OBJECT_NAME, "camelDestinationKey"); - } - }) - .to("minio://mycamelbucket?minioClient=#minioClient&operation=copyObject") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelMinioDestinationBucketName").constant("camelDestinationBucket") + .setHeader("CamelMinioObjectName").constant("camelKey") + .setHeader("CamelMinioDestinationObjectName").constant("camelDestinationKey") + .to("minio://mycamelbucket?minioClient=#minioClient&operation=copyObject") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camelDestinationBucket + + + camelKey + + + camelDestinationKey + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelMinioDestinationBucketName + constant: camelDestinationBucket + - setHeader: + name: CamelMinioObjectName + constant: camelKey + - setHeader: + name: CamelMinioDestinationObjectName + constant: camelDestinationKey + - to: + uri: minio://mycamelbucket + parameters: + minioClient: "#minioClient" + operation: copyObject + - to: + uri: mock:result +---- +==== This operation will copy the object with the name expressed in the header camelDestinationKey to the camelDestinationBucket bucket, from the bucket mycamelbucket. - `DeleteObject`: this operation deletes an object from a bucket +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "camelKey"); - } - }) - .to("minio://mycamelbucket?minioClient=#minioClient&operation=deleteObject") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelMinioObjectName").constant("camelKey") + .to("minio://mycamelbucket?minioClient=#minioClient&operation=deleteObject") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camelKey + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelMinioObjectName + constant: camelKey + - to: + uri: minio://mycamelbucket + parameters: + minioClient: "#minioClient" + operation: deleteObject + - to: + uri: mock:result +---- +==== This operation will delete the object camelKey from the bucket mycamelbucket. @@ -320,70 +400,230 @@ This operation will list the objects in the mycamelbucket bucket - `GetObject`: this operation gets a single object in a specific bucket +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "camelKey"); - } - }) - .to("minio://mycamelbucket?minioClient=#minioClient&operation=getObject") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelMinioObjectName").constant("camelKey") + .to("minio://mycamelbucket?minioClient=#minioClient&operation=getObject") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camelKey + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelMinioObjectName + constant: camelKey + - to: + uri: minio://mycamelbucket + parameters: + minioClient: "#minioClient" + operation: getObject + - to: + uri: mock:result +---- +==== This operation will return a MinioObject instance related to the camelKey object in `mycamelbucket` bucket. - `GetObjectRange`: this operation gets a single object range in a specific bucket +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "camelKey"); - exchange.getIn().setHeader(MinioConstants.OFFSET, "0"); - exchange.getIn().setHeader(MinioConstants.LENGTH, "9"); - } - }) - .to("minio://mycamelbucket?minioClient=#minioClient&operation=getObjectRange") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelMinioObjectName").constant("camelKey") + .setHeader("CamelMinioOffset").constant("0") + .setHeader("CamelMinioLength").constant("9") + .to("minio://mycamelbucket?minioClient=#minioClient&operation=getObjectRange") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camelKey + + + 0 + + + 9 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelMinioObjectName + constant: camelKey + - setHeader: + name: CamelMinioOffset + constant: "0" + - setHeader: + name: CamelMinioLength + constant: "9" + - to: + uri: minio://mycamelbucket + parameters: + minioClient: "#minioClient" + operation: getObjectRange + - to: + uri: mock:result +---- +==== This operation will return a MinioObject instance related to the camelKey object in `mycamelbucket` bucket, containing bytes from 0 to 9. - `createDownloadLink`: this operation will return a presigned url through which a file can be downloaded using GET method +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "camelKey"); - exchange.getIn().setHeader(MinioConstants.PRESIGNED_URL_EXPIRATION_TIME, 60 * 60); - } - }) - .to("minio://mycamelbucket?minioClient=#minioClient&operation=createDownloadLink") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelMinioObjectName").constant("camelKey") + .setHeader("CamelMinioPresignedURLExpirationTime").constant(3600) + .to("minio://mycamelbucket?minioClient=#minioClient&operation=createDownloadLink") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camelKey + + + 3600 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelMinioObjectName + constant: camelKey + - setHeader: + name: CamelMinioPresignedURLExpirationTime + constant: 3600 + - to: + uri: minio://mycamelbucket + parameters: + minioClient: "#minioClient" + operation: createDownloadLink + - to: + uri: mock:result +---- +==== - `createUploadLink`: this operation will return a presigned url through which a file can be uploaded using PUT method +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- - from("direct:start").process(new Processor() { - - @Override - public void process(Exchange exchange) throws Exception { - exchange.getIn().setHeader(MinioConstants.OBJECT_NAME, "camelKey"); - exchange.getIn().setHeader(MinioConstants.PRESIGNED_URL_EXPIRATION_TIME, 60 * 60); - } - }) - .to("minio://mycamelbucket?minioClient=#minioClient&operation=createUploadLink") - .to("mock:result"); --------------------------------------------------------------------------------- +---- +from("direct:start") + .setHeader("CamelMinioObjectName").constant("camelKey") + .setHeader("CamelMinioPresignedURLExpirationTime").constant(3600) + .to("minio://mycamelbucket?minioClient=#minioClient&operation=createUploadLink") + .to("mock:result"); +---- + +XML:: ++ +[source,xml] +---- + + + + camelKey + + + 3600 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelMinioObjectName + constant: camelKey + - setHeader: + name: CamelMinioPresignedURLExpirationTime + constant: 3600 + - to: + uri: minio://mycamelbucket + parameters: + minioClient: "#minioClient" + operation: createUploadLink + - to: + uri: mock:result +---- +==== `createDownLink` and `createUploadLink` have a default expiry of 3600s which can be overridden by setting the header `MinioConstants.PRESIGNED_URL_EXPIRATION_TIME` (value in seconds) diff --git a/components/camel-vertx/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc b/components/camel-vertx/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc index 5464d49e3ed64..df3eada8d9c15 100644 --- a/components/camel-vertx/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc +++ b/components/camel-vertx/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc @@ -162,6 +162,10 @@ YAML:: Similarly, you can retrieve any query parameter values used by the WebSocket client to connect to the server endpoint: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:sendChatMessage") @@ -171,6 +175,42 @@ from("vertx-websocket:localhost:8080/chat/{user}") .log("New message from ${header.user} (${header.role}) >>> ${body}") ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:sendChatMessage + steps: + - to: + uri: vertx-websocket:localhost:8080/chat/camel + parameters: + role: admin +- route: + from: + uri: vertx-websocket:localhost:8080/chat/{user} + steps: + - log: + message: "New message from ${header.user} (${header.role}) >>> ${body}" +---- +==== + === Sending messages to peers connected to the vertx-websocket server consumer NOTE: This section only applies when producing messages to a WebSocket hosted by the camel-vertx-websocket consumer. @@ -179,6 +219,10 @@ It is not relevant when producing messages to an externally hosted WebSocket. To send a message to all peers connected to a WebSocket hosted by the vertx-websocket server consumer, use the `sendToAll=true` endpoint option, or the `CamelVertxWebsocket.sendToAll` header. +[tabs] +==== +Java:: ++ [source,java] ---- from("vertx-websocket:localhost:8080/chat") @@ -189,12 +233,57 @@ from("direct:broadcastMessage") .to("vertx-websocket:localhost:8080/chat?sendToAll=true"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + This is a broadcast message! + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: vertx-websocket:localhost:8080/chat + steps: + - log: + message: "Got WebSocket message ${body}" +- route: + from: + uri: direct:broadcastMessage + steps: + - setBody: + constant: "This is a broadcast message!" + - to: + uri: vertx-websocket:localhost:8080/chat + parameters: + sendToAll: true +---- +==== + Alternatively, you can send messages to specific peers by using the `CamelVertxWebsocket.connectionKey` header. Multiple peers can be specified as a comma separated list. The value of the `connectionKey` can be determined whenever a peer triggers an event on the vertx-websocket consumer, where a unique key identifying the peer will be propagated via the `CamelVertxWebsocket.connectionKey` header. +[tabs] +==== +Java:: ++ [source,java] ---- from("vertx-websocket:localhost:8080/chat") @@ -202,10 +291,55 @@ from("vertx-websocket:localhost:8080/chat") from("direct:broadcastMessage") .setBody().constant("This is a broadcast message!") - .setHeader(VertxWebsocketConstants.CONNECTION_KEY).constant("key-1,key-2,key-3") + .setHeader("CamelVertxWebsocket.connectionKey").constant("key-1,key-2,key-3") .to("vertx-websocket:localhost:8080/chat"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + This is a broadcast message! + + + key-1,key-2,key-3 + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: vertx-websocket:localhost:8080/chat + steps: + - log: + message: "Got WebSocket message ${body}" +- route: + from: + uri: direct:broadcastMessage + steps: + - setBody: + constant: "This is a broadcast message!" + - setHeader: + name: CamelVertxWebsocket.connectionKey + constant: "key-1,key-2,key-3" + - to: + uri: vertx-websocket:localhost:8080/chat +---- +==== + === SSL By default, the `ws://` protocol is used, but secure connections with `wss://` are supported by configuring the consumer or producer From e31706b82fa163e55a427c5c1c324170edb8af1c Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:47:34 +0200 Subject: [PATCH 61/87] CAMEL-23789: Make Infinispan component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/infinispan-component.adoc | 162 +++++++++++++++--- 1 file changed, 142 insertions(+), 20 deletions(-) diff --git a/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc b/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc index 6b93df29c00e7..473402d4a121f 100644 --- a/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc +++ b/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc @@ -206,44 +206,138 @@ Write methods like put(key, value) and remove(key) do not return the previous va * Put a key/value into a named cache: + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUT) // <1> - .setHeader(InfinispanConstants.KEY).constant("123") // <2> - .to("infinispan:myCacheName&cacheContainer=#cacheContainer"); // <3> + .setHeader("CamelInfinispanOperation").constant("PUT") // <1> + .setHeader("CamelInfinispanKey").constant("123") // <2> + .to("infinispan:myCacheName?cacheContainer=#cacheContainer"); // <3> ---- <1> Set the operation to perform <2> Set the key used to identify the element in the cache <3> Use the configured cache manager `cacheContainer` from the registry to put an element to the cache named `myCacheName` + +XML:: ++ +[source,xml] +---- + + + + PUT + + + 123 + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelInfinispanOperation + constant: PUT + - setHeader: + name: CamelInfinispanKey + constant: "123" + - to: + uri: infinispan:myCacheName + parameters: + cacheContainer: "#cacheContainer" +---- +==== + It is possible to configure the lifetime and/or the idle time before the entry expires and gets evicted from the cache, as example: + +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.GET) - .setHeader(InfinispanConstants.KEY).constant("123") - .setHeader(InfinispanConstants.LIFESPAN_TIME).constant(100L) // <1> - .setHeader(InfinispanConstants.LIFESPAN_TIME_UNIT).constant(TimeUnit.MILLISECONDS.toString()) // <2> + .setHeader("CamelInfinispanOperation").constant("GET") + .setHeader("CamelInfinispanKey").constant("123") + .setHeader("CamelInfinispanLifespanTime").constant(100L) // <1> + .setHeader("CamelInfinispanTimeUnit").constant("MILLISECONDS") // <2> .to("infinispan:myCacheName"); ---- <1> Set the lifespan of the entry <2> Set the time unit for the lifespan -* Queries +XML:: ++ +[source,xml] +---- + + + + GET + + + 123 + + + 100 + + + MILLISECONDS + + + +---- + +YAML:: + +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelInfinispanOperation + constant: GET + - setHeader: + name: CamelInfinispanKey + constant: "123" + - setHeader: + name: CamelInfinispanLifespanTime + constant: 100 + - setHeader: + name: CamelInfinispanTimeUnit + constant: MILLISECONDS + - to: + uri: infinispan:myCacheName +---- +==== + +* Queries + +._Java-only: requires InfinispanQueryBuilder implementation_ + [source,java] ---- from("direct:start") - .setHeader(InfinispanConstants.OPERATION, InfinispanConstants.QUERY) - .setHeader(InfinispanConstants.QUERY_BUILDER, new InfinispanQueryBuilder() { + .setHeader("CamelInfinispanOperation").constant("QUERY") + .setHeader("CamelInfinispanQueryBuilder", new InfinispanQueryBuilder() { @Override public Query build(QueryFactory qf) { return qf.from(User.class).having("name").like("%abc%").build(); } }) - .to("infinispan:myCacheName?cacheContainer=#cacheManager") ; + .to("infinispan:myCacheName?cacheContainer=#cacheManager"); ---- + @@ -254,11 +348,41 @@ The .proto descriptors for domain objects must be registered with the remote Dat * Custom Listeners + +[tabs] +==== +Java:: ++ [source,java] ---- from("infinispan://?cacheContainer=#cacheManager&customListener=#myCustomListener") - .to("mock:result"); + .to("mock:result"); ---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: "infinispan://" + parameters: + cacheContainer: "#cacheManager" + customListener: "#myCustomListener" + steps: + - to: + uri: mock:result +---- +==== + The instance of `myCustomListener` must exist and Camel should be able to look it up from the `Registry`. Users are encouraged to extend the `org.apache.camel.component.infinispan.remote.InfinispanRemoteCustomListener` class and annotate the resulting class with `@ClientListener` which can be found in the package `org.infinispan.client.hotrod.annotation`. @@ -412,15 +536,14 @@ If you want to disable this functionality, set the `embeddingStoreEnabled` optio To store an embedding: +._Java-only: requires DataType constructor for embedding transformation_ + [source,java] ---- from("direct:put") - // Create an embedding from the message body .to("langchain4j-embeddings:create") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUT) - // Transform the embedding to a format usable by Infinispan + .setHeader("CamelInfinispanOperation").constant("PUT") .transformDataType(new DataType("infinispan:embeddings")) - // Store the embedding .to("infinispan:myCache?embeddingStoreDimension=384"); ---- @@ -428,15 +551,14 @@ The `embeddingStoreDimension` option *must* be specified. It must also match the To query embeddings: +._Java-only: requires DataType constructor for embedding transformation_ + [source,java] ---- from("direct:query") - // Create an embedding from the message body .to("langchain4j-embeddings:create") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.QUERY) - // Transforms the embedding to a vector kNN search + .setHeader("CamelInfinispanOperation").constant("QUERY") .transformDataType(new DataType("infinispan:embeddings")) - // Query embeddings .to("infinispan:myCache?embeddingStoreDimension=384"); ---- From d43fdbc43a1ff8564382902ea5d8a1cd2ac8c6f9 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:48:41 +0200 Subject: [PATCH 62/87] CAMEL-23789: Make Metrics component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/metrics-component.adoc | 193 +++++++++++++++++- 1 file changed, 188 insertions(+), 5 deletions(-) diff --git a/components/camel-metrics/src/main/docs/metrics-component.adoc b/components/camel-metrics/src/main/docs/metrics-component.adoc index c5422fc8541ce..3121b466e7b4e 100644 --- a/components/camel-metrics/src/main/docs/metrics-component.adoc +++ b/components/camel-metrics/src/main/docs/metrics-component.adoc @@ -131,14 +131,50 @@ Metric name defined in URI can be overridden by using header with name For example +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:in") - .setHeader(MetricsConstants.HEADER_METRIC_NAME, constant("new.name")) + .setHeader("CamelMetricsName").constant("new.name") .to("metrics:counter:name.not.used") .to("direct:out"); ---- +XML:: ++ +[source,xml] +---- + + + + new.name + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsName + constant: new.name + - to: + uri: metrics:counter:name.not.used + - to: + uri: direct:out +---- +==== + will update counter with name `new.name` instead of `name.not.used`. All Metrics specific headers are removed from the message once Metrics @@ -296,24 +332,97 @@ values specified in Metrics component URI. |CamelMetricsCounterDecrement |Override decrement value in URI |Long |==================================================================== +[tabs] +==== +Java:: ++ [source,java] ---- // update counter simple.counter by 417 from("direct:in") - .setHeader(MetricsConstants.HEADER_COUNTER_INCREMENT, constant(417L)) + .setHeader("CamelMetricsCounterIncrement").constant(417L) .to("metrics:counter:simple.counter?increment=7") .to("direct:out"); ---- +XML:: ++ +[source,xml] +---- + + + + 417 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsCounterIncrement + constant: 417 + - to: + uri: metrics:counter:simple.counter + parameters: + increment: 7 + - to: + uri: direct:out +---- +==== + +[tabs] +==== +Java:: ++ [source,java] ---- // updates counter using simple language to evaluate body.length from("direct:in") - .setHeader(MetricsConstants.HEADER_COUNTER_INCREMENT, simple("${body.length}")) + .setHeader("CamelMetricsCounterIncrement", simple("${body.length}")) .to("metrics:counter:body.length") .to("mock:out"); +---- + +XML:: ++ +[source,xml] +---- + + + + ${body.length} + + + + +---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsCounterIncrement + simple: "${body.length}" + - to: + uri: metrics:counter:body.length + - to: + uri: mock:out ---- +==== [[MetricsComponent-histogram]] === Metric type histogram @@ -628,15 +737,51 @@ component URI. |`org.apache.camel.component.metrics.MetricsTimerAction` |======================================================================= +[tabs] +==== +Java:: ++ [source,java] ---- // sets timer action using header from("direct:in") - .setHeader(MetricsConstants.HEADER_TIMER_ACTION, MetricsTimerAction.start) + .setHeader("CamelMetricsTimerAction").constant("start") .to("metrics:timer:simple.timer") .to("direct:out"); ---- +XML:: ++ +[source,xml] +---- + + + + start + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsTimerAction + constant: start + - to: + uri: metrics:timer:simple.timer + - to: + uri: direct:out +---- +==== + [[MetricsComponent-gauge]] === Metric type gauge @@ -706,15 +851,53 @@ default one specified in a URI. |CamelMetricsGaugeSubject |Override subject value in URI |Object |==================================================================== +[tabs] +==== +Java:: ++ [source,java] ---- // update gauge simple.gauge by a String literal "myUpdatedSubject" from("direct:in") - .setHeader(MetricsConstants.HEADER_GAUGE_SUBJECT, constant("myUpdatedSubject")) + .setHeader("CamelMetricsGaugeSubject").constant("myUpdatedSubject") .to("metrics:counter:simple.gauge?subject=#mySubjectBean") .to("direct:out"); ---- +XML:: ++ +[source,xml] +---- + + + + myUpdatedSubject + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsGaugeSubject + constant: myUpdatedSubject + - to: + uri: metrics:counter:simple.gauge + parameters: + subject: "#mySubjectBean" + - to: + uri: direct:out +---- +==== + === MetricsRoutePolicyFactory This factory allows adding a `RoutePolicy` for each From 7e5436dcf1cbefd209c6444c1c0a55693b197fde Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:51:03 +0200 Subject: [PATCH 63/87] CAMEL-23789: Make Crypto component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/crypto-component.adoc | 191 ++++++++++++++++-- 1 file changed, 172 insertions(+), 19 deletions(-) diff --git a/components/camel-crypto/src/main/docs/crypto-component.adoc b/components/camel-crypto/src/main/docs/crypto-component.adoc index b540b239aa355..f4173c4532c2e 100644 --- a/components/camel-crypto/src/main/docs/crypto-component.adoc +++ b/components/camel-crypto/src/main/docs/crypto-component.adoc @@ -102,17 +102,19 @@ include::partial$component-endpoint-headers.adoc[] The most basic way to sign and verify an exchange is with a KeyPair as follows. +._Java-only: requires Java KeyPair objects_ + [source,java] ---- KeyPair keyPair = KeyGenerator.getInstance("RSA").generateKeyPair(); from("direct:sign") - .setHeader(DigitalSignatureConstants.SIGNATURE_PRIVATE_KEY, constant(keys.getPrivate())) + .setHeader("CamelSignaturePrivateKey", constant(keyPair.getPrivate())) .to("crypto:sign:message") .to("direct:verify"); from("direct:verify") - .setHeader(DigitalSignatureConstants.SIGNATURE_PUBLIC_KEY_OR_CERT, constant(keys.getPublic())) + .setHeader("CamelSignaturePublicKeyOrCert", constant(keyPair.getPublic())) .to("crypto:verify:check"); ---- @@ -137,6 +139,10 @@ keytool -genkey -keyalg RSA -keysize 2048 -keystore keystore.jks -storepass letm The following route first signs an exchange using Bob's alias from the KeyStore bound into the Camel Registry, and then verifies it using the same alias. +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:sign") @@ -146,6 +152,46 @@ from("direct:sign") .log("Verified: ${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:sign + steps: + - to: + uri: crypto:sign:keystoreSign + parameters: + alias: bob + keystoreName: myKeystore + password: letmein + - log: + message: "Signature: ${header.CamelDigitalSignature}" + - to: + uri: crypto:verify:keystoreVerify + parameters: + alias: bob + keystoreName: myKeystore + password: letmein + - log: + message: "Verified: ${body}" +---- +==== + The following code shows how to load the keystore created using the above `keytool` command and bind it into the registry with the name `myKeystore` for use in the above route. The example makes use of the `@Configuration` and `@BindToRegistry` annotations introduced in Camel 3 to instantiate the KeyStore and register it with the name `myKeyStore`. [source,java] @@ -178,6 +224,10 @@ It may be desirable to change the message header used to store the signature. A different header name can be specified in the route definition as follows +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:sign") @@ -186,6 +236,45 @@ from("direct:sign") .to("crypto:verify:keystoreVerify?alias=bob&keystoreName=myKeystore&password=letmein&signatureHeaderName=mySignature"); ---- +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:sign + steps: + - to: + uri: crypto:sign:keystoreSign + parameters: + alias: bob + keystoreName: myKeystore + password: letmein + signatureHeaderName: mySignature + - log: + message: "Signature: ${header.mySignature}" + - to: + uri: crypto:verify:keystoreVerify + parameters: + alias: bob + keystoreName: myKeystore + password: letmein + signatureHeaderName: mySignature +---- +==== + === Changing the bufferSize In case you need to update the size of the buffer... @@ -210,18 +299,20 @@ alias can be supplied in a message header The header would be set as follows: +._Java-only: Java test API (ProducerTemplate)_ + [source,java] -------------------------------------------------------------------------------------------------- +---- Exchange unsigned = getMandatoryEndpoint("direct:alias-sign").createExchange(); unsigned.getIn().setBody(payload); -unsigned.getIn().setHeader(DigitalSignatureConstants.KEYSTORE_ALIAS, "bob"); -unsigned.getIn().setHeader(DigitalSignatureConstants.KEYSTORE_PASSWORD, "letmein".toCharArray()); +unsigned.getIn().setHeader("CamelSignatureKeyStoreAlias", "bob"); +unsigned.getIn().setHeader("CamelSignatureKeyStorePassword", "letmein".toCharArray()); template.send("direct:alias-sign", unsigned); Exchange signed = getMandatoryEndpoint("direct:alias-sign").createExchange(); signed.getIn().copyFrom(unsigned.getMessage()); -signed.getIn().setHeader(DigitalSignatureConstants.KEYSTORE_ALIAS, "bob"); +signed.getIn().setHeader("CamelSignatureKeyStoreAlias", "bob"); template.send("direct:alias-verify", signed); -------------------------------------------------------------------------------------------------- +---- == Using Post-Quantum Cryptography (PQC) Algorithms @@ -381,6 +472,8 @@ The following ML-DSA parameter sets are available: SLH-DSA (Stateless Hash-Based Digital Signature Algorithm, formerly SPHINCS+) is the secondary NIST-standardized PQC signature algorithm, based on hash functions. +._Java-only: requires Java KeyPair and registry binding_ + [source,java] ---- private KeyPair slhDsaKeyPair; @@ -486,27 +579,87 @@ See the xref:components::pqc-component.adoc[PQC component] for the full list of Alternatively, you can chain two `crypto:sign` / `crypto:verify` endpoints to produce both a classical and a PQC signature, storing each in a separate header: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:sign") - // Classical ECDSA signature - .to("crypto:sign:classical?algorithm=SHA256withECDSA&privateKeyName=#ecPrivateKey" - + "&signatureHeaderName=ClassicalSignature") - // PQC ML-DSA signature - .to("crypto:sign:pqc?algorithm=ML-DSA&provider=BC&privateKeyName=#mlDsaPrivateKey" - + "&signatureHeaderName=PQCSignature") + .to("crypto:sign:classical?algorithm=SHA256withECDSA&privateKeyName=#ecPrivateKey&signatureHeaderName=ClassicalSignature") + .to("crypto:sign:pqc?algorithm=ML-DSA&provider=BC&privateKeyName=#mlDsaPrivateKey&signatureHeaderName=PQCSignature") .to("direct:verify"); from("direct:verify") - // Verify classical signature - .to("crypto:verify:classical?algorithm=SHA256withECDSA&publicKeyName=#ecPublicKey" - + "&signatureHeaderName=ClassicalSignature") - // Verify PQC signature - .to("crypto:verify:pqc?algorithm=ML-DSA&provider=BC&publicKeyName=#mlDsaPublicKey" - + "&signatureHeaderName=PQCSignature") + .to("crypto:verify:classical?algorithm=SHA256withECDSA&publicKeyName=#ecPublicKey&signatureHeaderName=ClassicalSignature") + .to("crypto:verify:pqc?algorithm=ML-DSA&provider=BC&publicKeyName=#mlDsaPublicKey&signatureHeaderName=PQCSignature") .to("mock:result"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:sign + steps: + - to: + uri: crypto:sign:classical + parameters: + algorithm: SHA256withECDSA + privateKeyName: "#ecPrivateKey" + signatureHeaderName: ClassicalSignature + - to: + uri: crypto:sign:pqc + parameters: + algorithm: ML-DSA + provider: BC + privateKeyName: "#mlDsaPrivateKey" + signatureHeaderName: PQCSignature + - to: + uri: direct:verify +- route: + from: + uri: direct:verify + steps: + - to: + uri: crypto:verify:classical + parameters: + algorithm: SHA256withECDSA + publicKeyName: "#ecPublicKey" + signatureHeaderName: ClassicalSignature + - to: + uri: crypto:verify:pqc + parameters: + algorithm: ML-DSA + provider: BC + publicKeyName: "#mlDsaPublicKey" + signatureHeaderName: PQCSignature + - to: + uri: mock:result +---- +==== + NOTE: The chaining approach stores two independent signatures in separate headers, while the PQC component's hybrid operations produce a single combined signature. For new implementations, the PQC component's hybrid operations are recommended as they handle the wire format, key management, and verification logic in a single step. From 5a9b71d3ecceeb03b6772b64c753646f8f818c82 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:56:51 +0200 Subject: [PATCH 64/87] CAMEL-23789: Make Micrometer component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/micrometer-component.adoc | 162 +++++++++++++++++- 1 file changed, 155 insertions(+), 7 deletions(-) diff --git a/components/camel-micrometer/src/main/docs/micrometer-component.adoc b/components/camel-micrometer/src/main/docs/micrometer-component.adoc index 97c79780d4e7f..685ef2e56f04f 100644 --- a/components/camel-micrometer/src/main/docs/micrometer-component.adoc +++ b/components/camel-micrometer/src/main/docs/micrometer-component.adoc @@ -135,11 +135,13 @@ The meter tags defined as URI parameters can be augmented by populating a header For example +._Java-only: requires Micrometer Tags API_ + [source,java] ---- from("direct:in") - .setHeader(MicrometerConstants.HEADER_METRIC_NAME, constant("new.name")) - .setHeader(MicrometerConstants.HEADER_METRIC_TAGS, constant(Tags.of("dynamic-key", "dynamic-value"))) + .setHeader("CamelMetricsName").constant("new.name") + .setHeader("CamelMetricsTags", constant(Tags.of("dynamic-key", "dynamic-value"))) .to("micrometer:counter:name.not.used?tags=key=value") .to("direct:out"); ---- @@ -304,24 +306,97 @@ Like in `camel-metrics`, specific Message headers can be used to override |CamelMetricsCounterDecrement |Override decrement value in URI |Double |==================================================================== +[tabs] +==== +Java:: ++ [source,java] ---- // update counter simple.counter by 417 from("direct:in") - .setHeader(MicrometerConstants.HEADER_COUNTER_INCREMENT, constant(417.0D)) + .setHeader("CamelMetricsCounterIncrement").constant(417.0D) .to("micrometer:counter:simple.counter?increment=7") .to("direct:out"); ---- +XML:: ++ +[source,xml] +---- + + + + 417.0 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsCounterIncrement + constant: 417.0 + - to: + uri: micrometer:counter:simple.counter + parameters: + increment: 7 + - to: + uri: direct:out +---- +==== + +[tabs] +==== +Java:: ++ [source,java] ---- // updates counter using simple language to evaluate body.length from("direct:in") - .setHeader(MicrometerConstants.HEADER_COUNTER_INCREMENT, simple("${body.length}")) + .setHeader("CamelMetricsCounterIncrement", simple("${body.length}")) .to("micrometer:counter:body.length") .to("direct:out"); +---- + +XML:: ++ +[source,xml] +---- + + + + ${body.length} + + + + +---- +YAML:: ++ +[source,yaml] ---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsCounterIncrement + simple: "${body.length}" + - to: + uri: micrometer:counter:body.length + - to: + uri: direct:out +---- +==== [[MicrometerComponent-summary]] === Distribution Summary @@ -472,15 +547,52 @@ the Micrometer endpoint URI. |CamelMetricsHistogramValue |Override histogram value in URI |Long |================================================================= +[tabs] +==== +Java:: ++ [source,java] ---- // adds value 992.0 to simple.histogram from("direct:in") - .setHeader(MicrometerConstants.HEADER_HISTOGRAM_VALUE, constant(992.0D)) + .setHeader("CamelMetricsHistogramValue").constant(992.0D) .to("micrometer:summary:simple.histogram?value=700") - .to("direct:out") + .to("direct:out"); +---- + +XML:: ++ +[source,xml] +---- + + + + 992.0 + + + + +---- +YAML:: ++ +[source,yaml] ---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsHistogramValue + constant: 992.0 + - to: + uri: micrometer:summary:simple.histogram + parameters: + value: 700 + - to: + uri: direct:out +---- +==== [[MicrometerComponent-timer]] @@ -566,15 +678,51 @@ the Micrometer endpoint URI. |`org.apache.camel.component.micrometer.MicrometerTimerAction` |======================================================================= +[tabs] +==== +Java:: ++ [source,java] ---- // sets timer action using header from("direct:in") - .setHeader(MicrometerConstants.HEADER_TIMER_ACTION, MicrometerTimerAction.start) + .setHeader("CamelMetricsTimerAction").constant("start") .to("micrometer:timer:simple.timer") .to("direct:out"); ---- +XML:: ++ +[source,xml] +---- + + + + start + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsTimerAction + constant: start + - to: + uri: micrometer:timer:simple.timer + - to: + uri: direct:out +---- +==== + === Using Micrometer route policy factory From 106c21bf0e5cbcdbc40185b139ad99a08b020a25 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 08:57:59 +0200 Subject: [PATCH 65/87] CAMEL-23789: Make File component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/file-component.adoc | 159 +++++++++++++++++- 1 file changed, 155 insertions(+), 4 deletions(-) diff --git a/components/camel-file/src/main/docs/file-component.adoc b/components/camel-file/src/main/docs/file-component.adoc index 767c8ac054b3e..4de277efdac76 100644 --- a/components/camel-file/src/main/docs/file-component.adoc +++ b/components/camel-file/src/main/docs/file-component.adoc @@ -1424,11 +1424,41 @@ problems. By default, Camel will move any processed file into a `.camel` subdirectory in the directory the file was consumed from. +[tabs] +==== +Java:: ++ [source,java] ---- -from("file://inputdir/?recursive=true&delete=true").to("file://outputdir") +from("file://inputdir/?recursive=true&delete=true").to("file://outputdir"); +---- + +XML:: ++ +[source,xml] +---- + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://inputdir/ + parameters: + recursive: true + delete: true + steps: + - to: + uri: file://outputdir +---- +==== + Affects the layout as follows: + *before* @@ -1448,29 +1478,119 @@ outputdir/sub/bar.txt === Read from a directory and write to another directory +[tabs] +==== +Java:: ++ [source,java] ---- -from("file://inputdir/?delete=true").to("file://outputdir") +from("file://inputdir/?delete=true").to("file://outputdir"); +---- + +XML:: ++ +[source,xml] +---- + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://inputdir/ + parameters: + delete: true + steps: + - to: + uri: file://outputdir +---- +==== + === Read from a directory and write to another directory using a dynamic name +[tabs] +==== +Java:: ++ [source,java] ---- -from("file://inputdir/?delete=true").to("file://outputdir?fileName=copy-of-${file:name}") +from("file://inputdir/?delete=true").to("file://outputdir?fileName=copy-of-${file:name}"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://inputdir/ + parameters: + delete: true + steps: + - to: + uri: file://outputdir + parameters: + fileName: "copy-of-${file:name}" +---- +==== + Listen to a directory and create a message for each file dropped there. Copy the contents to the `outputdir` and delete the file in the `inputdir`. === Reading recursively from a directory and writing to another +[tabs] +==== +Java:: ++ [source,java] ---- -from("file://inputdir/?recursive=true&delete=true").to("file://outputdir") +from("file://inputdir/?recursive=true&delete=true").to("file://outputdir"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://inputdir/ + parameters: + recursive: true + delete: true + steps: + - to: + uri: file://outputdir +---- +==== + Listen to a directory and create a message for each file dropped there. Copy the contents to the `outputdir` and delete the file in the `inputdir`. Will scan recursively into subdirectories. Will lay out the @@ -1492,6 +1612,8 @@ outputdir/sub/bar.txt === Read from a directory and process the message in java +._Java-only: inline Processor implementation_ + [source,java] ---- from("file://inputdir/").process(new Processor() { @@ -1510,11 +1632,40 @@ dropped into the `inputdir` directory. In this sample, we want to move consumed files to a backup folder using today's date as a subfolder name: +[tabs] +==== +Java:: ++ [source,java] ---- from("file://inbox?move=backup/${date:now:yyyyMMdd}/${file:name}").to("..."); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://inbox + parameters: + move: "backup/${date:now:yyyyMMdd}/${file:name}" + steps: + - to: + uri: "..." +---- +==== + See xref:languages:file-language.adoc[File Language] for more samples. From 5add11d4f4b1da54717b45cde57c8805ef059026 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 09:05:09 +0200 Subject: [PATCH 66/87] CAMEL-23789: Make AWS IAM, AWS Lambda, Azure Storage Blob component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/aws2-iam-component.adoc | 64 ++++---- .../src/main/docs/aws2-lambda-component.adoc | 140 ++++++++++++++++-- .../docs/azure-storage-blob-component.adoc | 2 + 3 files changed, 159 insertions(+), 47 deletions(-) diff --git a/components/camel-aws/camel-aws2-iam/src/main/docs/aws2-iam-component.adoc b/components/camel-aws/camel-aws2-iam/src/main/docs/aws2-iam-component.adoc index bf77169b599b3..df03b40732b77 100644 --- a/components/camel-aws/camel-aws2-iam/src/main/docs/aws2-iam-component.adoc +++ b/components/camel-aws/camel-aws2-iam/src/main/docs/aws2-iam-component.adoc @@ -126,7 +126,7 @@ Java:: [source,java] ---- from("direct:createUser") - .setHeader(IAM2Constants.USERNAME, constant("camel")) + .setHeader("CamelAwsIAMUsername", constant("camel")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=createUser"); ---- @@ -171,7 +171,7 @@ Java:: [source,java] ---- from("direct:deleteUser") - .setHeader(IAM2Constants.USERNAME, constant("camel")) + .setHeader("CamelAwsIAMUsername", constant("camel")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=deleteUser"); ---- @@ -254,7 +254,7 @@ Java:: [source,java] ---- from("direct:createGroup") - .setHeader(IAM2Constants.GROUP_NAME, constant("camel")) + .setHeader("CamelAwsIAMGroupName", constant("camel")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=createGroup"); ---- @@ -299,7 +299,7 @@ Java:: [source,java] ---- from("direct:deleteGroup") - .setHeader(IAM2Constants.GROUP_NAME, constant("camel")) + .setHeader("CamelAwsIAMGroupName", constant("camel")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=deleteGroup"); ---- @@ -384,8 +384,8 @@ Java:: [source,java] ---- from("direct:createRole") - .setHeader(IAM2Constants.ROLE_NAME, constant("myRole")) - .setHeader(IAM2Constants.ASSUME_ROLE_POLICY_DOCUMENT, constant("{...}")) + .setHeader("CamelAwsIAMRoleName", constant("myRole")) + .setHeader("CamelAwsIAMAssumeRolePolicyDocument", constant("{...}")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=createRole"); ---- @@ -436,7 +436,7 @@ Java:: [source,java] ---- from("direct:deleteRole") - .setHeader(IAM2Constants.ROLE_NAME, constant("myRole")) + .setHeader("CamelAwsIAMRoleName", constant("myRole")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=deleteRole"); ---- @@ -481,7 +481,7 @@ Java:: [source,java] ---- from("direct:getRole") - .setHeader(IAM2Constants.ROLE_NAME, constant("myRole")) + .setHeader("CamelAwsIAMRoleName", constant("myRole")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=getRole"); ---- @@ -566,8 +566,8 @@ Java:: [source,java] ---- from("direct:createPolicy") - .setHeader(IAM2Constants.POLICY_NAME, constant("myPolicy")) - .setHeader(IAM2Constants.POLICY_DOCUMENT, constant("{...}")) + .setHeader("CamelAwsIAMPolicyName", constant("myPolicy")) + .setHeader("CamelAwsIAMPolicyDocument", constant("{...}")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=createPolicy"); ---- @@ -618,7 +618,7 @@ Java:: [source,java] ---- from("direct:deletePolicy") - .setHeader(IAM2Constants.POLICY_ARN, constant("arn:aws:iam::123456789012:policy/myPolicy")) + .setHeader("CamelAwsIAMPolicyArn", constant("arn:aws:iam::123456789012:policy/myPolicy")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=deletePolicy"); ---- @@ -663,7 +663,7 @@ Java:: [source,java] ---- from("direct:getPolicy") - .setHeader(IAM2Constants.POLICY_ARN, constant("arn:aws:iam::123456789012:policy/myPolicy")) + .setHeader("CamelAwsIAMPolicyArn", constant("arn:aws:iam::123456789012:policy/myPolicy")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=getPolicy"); ---- @@ -748,8 +748,8 @@ Java:: [source,java] ---- from("direct:attachUserPolicy") - .setHeader(IAM2Constants.USERNAME, constant("camel")) - .setHeader(IAM2Constants.POLICY_ARN, constant("arn:aws:iam::123456789012:policy/myPolicy")) + .setHeader("CamelAwsIAMUsername", constant("camel")) + .setHeader("CamelAwsIAMPolicyArn", constant("arn:aws:iam::123456789012:policy/myPolicy")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=attachUserPolicy"); ---- @@ -800,8 +800,8 @@ Java:: [source,java] ---- from("direct:detachUserPolicy") - .setHeader(IAM2Constants.USERNAME, constant("camel")) - .setHeader(IAM2Constants.POLICY_ARN, constant("arn:aws:iam::123456789012:policy/myPolicy")) + .setHeader("CamelAwsIAMUsername", constant("camel")) + .setHeader("CamelAwsIAMPolicyArn", constant("arn:aws:iam::123456789012:policy/myPolicy")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=detachUserPolicy"); ---- @@ -852,8 +852,8 @@ Java:: [source,java] ---- from("direct:attachGroupPolicy") - .setHeader(IAM2Constants.GROUP_NAME, constant("myGroup")) - .setHeader(IAM2Constants.POLICY_ARN, constant("arn:aws:iam::123456789012:policy/myPolicy")) + .setHeader("CamelAwsIAMGroupName", constant("myGroup")) + .setHeader("CamelAwsIAMPolicyArn", constant("arn:aws:iam::123456789012:policy/myPolicy")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=attachGroupPolicy"); ---- @@ -904,8 +904,8 @@ Java:: [source,java] ---- from("direct:detachGroupPolicy") - .setHeader(IAM2Constants.GROUP_NAME, constant("myGroup")) - .setHeader(IAM2Constants.POLICY_ARN, constant("arn:aws:iam::123456789012:policy/myPolicy")) + .setHeader("CamelAwsIAMGroupName", constant("myGroup")) + .setHeader("CamelAwsIAMPolicyArn", constant("arn:aws:iam::123456789012:policy/myPolicy")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=detachGroupPolicy"); ---- @@ -956,8 +956,8 @@ Java:: [source,java] ---- from("direct:attachRolePolicy") - .setHeader(IAM2Constants.ROLE_NAME, constant("myRole")) - .setHeader(IAM2Constants.POLICY_ARN, constant("arn:aws:iam::123456789012:policy/myPolicy")) + .setHeader("CamelAwsIAMRoleName", constant("myRole")) + .setHeader("CamelAwsIAMPolicyArn", constant("arn:aws:iam::123456789012:policy/myPolicy")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=attachRolePolicy"); ---- @@ -1008,8 +1008,8 @@ Java:: [source,java] ---- from("direct:detachRolePolicy") - .setHeader(IAM2Constants.ROLE_NAME, constant("myRole")) - .setHeader(IAM2Constants.POLICY_ARN, constant("arn:aws:iam::123456789012:policy/myPolicy")) + .setHeader("CamelAwsIAMRoleName", constant("myRole")) + .setHeader("CamelAwsIAMPolicyArn", constant("arn:aws:iam::123456789012:policy/myPolicy")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=detachRolePolicy"); ---- @@ -1062,7 +1062,7 @@ Java:: [source,java] ---- from("direct:createInstanceProfile") - .setHeader(IAM2Constants.INSTANCE_PROFILE_NAME, constant("myInstanceProfile")) + .setHeader("CamelAwsIAMInstanceProfileName", constant("myInstanceProfile")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=createInstanceProfile"); ---- @@ -1107,7 +1107,7 @@ Java:: [source,java] ---- from("direct:deleteInstanceProfile") - .setHeader(IAM2Constants.INSTANCE_PROFILE_NAME, constant("myInstanceProfile")) + .setHeader("CamelAwsIAMInstanceProfileName", constant("myInstanceProfile")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=deleteInstanceProfile"); ---- @@ -1152,7 +1152,7 @@ Java:: [source,java] ---- from("direct:getInstanceProfile") - .setHeader(IAM2Constants.INSTANCE_PROFILE_NAME, constant("myInstanceProfile")) + .setHeader("CamelAwsIAMInstanceProfileName", constant("myInstanceProfile")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=getInstanceProfile"); ---- @@ -1235,8 +1235,8 @@ Java:: [source,java] ---- from("direct:addRoleToInstanceProfile") - .setHeader(IAM2Constants.INSTANCE_PROFILE_NAME, constant("myInstanceProfile")) - .setHeader(IAM2Constants.ROLE_NAME, constant("myRole")) + .setHeader("CamelAwsIAMInstanceProfileName", constant("myInstanceProfile")) + .setHeader("CamelAwsIAMRoleName", constant("myRole")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=addRoleToInstanceProfile"); ---- @@ -1287,8 +1287,8 @@ Java:: [source,java] ---- from("direct:removeRoleFromInstanceProfile") - .setHeader(IAM2Constants.INSTANCE_PROFILE_NAME, constant("myInstanceProfile")) - .setHeader(IAM2Constants.ROLE_NAME, constant("myRole")) + .setHeader("CamelAwsIAMInstanceProfileName", constant("myInstanceProfile")) + .setHeader("CamelAwsIAMRoleName", constant("myRole")) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=removeRoleFromInstanceProfile"); ---- @@ -1335,6 +1335,8 @@ YAML:: Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as a body. In AWS IAM, there are multiple operations you can submit, as an example for Create User request, you can do something like: +._Java-only: requires AWS SDK builder_ + [source,java] -------------------------- from("direct:createUser") diff --git a/components/camel-aws/camel-aws2-lambda/src/main/docs/aws2-lambda-component.adoc b/components/camel-aws/camel-aws2-lambda/src/main/docs/aws2-lambda-component.adoc index 05c651aef9c70..781235f2e1236 100644 --- a/components/camel-aws/camel-aws2-lambda/src/main/docs/aws2-lambda-component.adoc +++ b/components/camel-aws/camel-aws2-lambda/src/main/docs/aws2-lambda-component.adoc @@ -155,6 +155,8 @@ YAML:: and by sending +._Java-only: Java test API (ProducerTemplate with file upload)_ + [source,java] ---- template.send("direct:createFunction", ExchangePattern.InOut, new Processor() { @@ -190,7 +192,7 @@ Java:: [source,java] ---- from("direct:createFunctionUrl") - .setHeader(Lambda2Constants.FUNCTION_URL_AUTH_TYPE, constant("NONE")) + .setHeader("CamelAwsLambdaFunctionUrlAuthType", constant("NONE")) .to("aws2-lambda://myFunction?operation=createFunctionUrlConfig") .to("mock:result"); ---- @@ -281,7 +283,7 @@ Java:: [source,java] ---- from("direct:updateFunctionUrl") - .setHeader(Lambda2Constants.FUNCTION_URL_AUTH_TYPE, constant("AWS_IAM")) + .setHeader("CamelAwsLambdaFunctionUrlAuthType", constant("AWS_IAM")) .to("aws2-lambda://myFunction?operation=updateFunctionUrlConfig") .to("mock:result"); ---- @@ -449,18 +451,66 @@ YAML:: - updateFunctionConfiguration: this operation will update the configuration of a function +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:updateFunctionConfiguration") - .process(exchange -> { - exchange.getIn().setHeader(Lambda2Constants.FUNCTION_MEMORY_SIZE, 512); - exchange.getIn().setHeader(Lambda2Constants.FUNCTION_TIMEOUT, 60); - exchange.getIn().setHeader(Lambda2Constants.DESCRIPTION, "Updated function description"); - }) + .setHeader("CamelAwsLambdaFunctionMemorySize", constant(512)) + .setHeader("CamelAwsLambdaFunctionTimeout", constant(60)) + .setHeader("CamelAwsLambdaDescription", constant("Updated function description")) .to("aws2-lambda://myFunction?operation=updateFunctionConfiguration") .to("mock:result"); ---- +XML:: ++ +[source,xml] +---- + + + + 512 + + + 60 + + + Updated function description + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:updateFunctionConfiguration + steps: + - setHeader: + name: CamelAwsLambdaFunctionMemorySize + constant: 512 + - setHeader: + name: CamelAwsLambdaFunctionTimeout + constant: 60 + - setHeader: + name: CamelAwsLambdaDescription + constant: Updated function description + - to: + uri: aws2-lambda://myFunction + parameters: + operation: updateFunctionConfiguration + - to: + uri: mock:result +---- +==== + === Concurrency Operations Concurrency operations allow you to manage reserved concurrency for your Lambda functions. @@ -474,7 +524,7 @@ Java:: [source,java] ---- from("direct:putFunctionConcurrency") - .setHeader(Lambda2Constants.RESERVED_CONCURRENT_EXECUTIONS, constant(100)) + .setHeader("CamelAwsLambdaReservedConcurrentExecutions", constant(100)) .to("aws2-lambda://myFunction?operation=putFunctionConcurrency") .to("mock:result"); ---- @@ -601,19 +651,73 @@ Permission operations allow you to manage the resource-based policy for your Lam - addPermission: this operation will add a permission to the function's resource-based policy +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:addPermission") - .process(exchange -> { - exchange.getIn().setHeader(Lambda2Constants.STATEMENT_ID, "s3-invoke"); - exchange.getIn().setHeader(Lambda2Constants.ACTION, "lambda:InvokeFunction"); - exchange.getIn().setHeader(Lambda2Constants.PRINCIPAL, "s3.amazonaws.com"); - exchange.getIn().setHeader(Lambda2Constants.SOURCE_ARN, "arn:aws:s3:::my-bucket"); - }) + .setHeader("CamelAwsLambdaStatementId", constant("s3-invoke")) + .setHeader("CamelAwsLambdaAction", constant("lambda:InvokeFunction")) + .setHeader("CamelAwsLambdaPrincipal", constant("s3.amazonaws.com")) + .setHeader("CamelAwsLambdaSourceArn", constant("arn:aws:s3:::my-bucket")) .to("aws2-lambda://myFunction?operation=addPermission") .to("mock:result"); ---- +XML:: ++ +[source,xml] +---- + + + + s3-invoke + + + lambda:InvokeFunction + + + s3.amazonaws.com + + + arn:aws:s3:::my-bucket + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:addPermission + steps: + - setHeader: + name: CamelAwsLambdaStatementId + constant: s3-invoke + - setHeader: + name: CamelAwsLambdaAction + constant: "lambda:InvokeFunction" + - setHeader: + name: CamelAwsLambdaPrincipal + constant: s3.amazonaws.com + - setHeader: + name: CamelAwsLambdaSourceArn + constant: "arn:aws:s3:::my-bucket" + - to: + uri: aws2-lambda://myFunction + parameters: + operation: addPermission + - to: + uri: mock:result +---- +==== + - removePermission: this operation will remove a permission from the function's resource-based policy [tabs] @@ -623,7 +727,7 @@ Java:: [source,java] ---- from("direct:removePermission") - .setHeader(Lambda2Constants.STATEMENT_ID, constant("s3-invoke")) + .setHeader("CamelAwsLambdaStatementId", constant("s3-invoke")) .to("aws2-lambda://myFunction?operation=removePermission") .to("mock:result"); ---- @@ -705,11 +809,13 @@ YAML:: You can also configure CORS settings for function URLs: +._Java-only: requires List values for CORS headers_ + [source,java] ---- from("direct:createFunctionUrlWithCors") .process(exchange -> { - exchange.getIn().setHeader(Lambda2Constants.FUNCTION_URL_AUTH_TYPE, "NONE"); + exchange.getIn().setHeader("CamelAwsLambdaFunctionUrlAuthType", "NONE"); exchange.getIn().setHeader(Lambda2Constants.FUNCTION_URL_CORS_ALLOW_ORIGINS, Arrays.asList("https://example.com")); exchange.getIn().setHeader(Lambda2Constants.FUNCTION_URL_CORS_ALLOW_METHODS, @@ -727,6 +833,8 @@ from("direct:createFunctionUrlWithCors") Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as the body. In AWS Lambda there are multiple operations you can submit, as an example for Get Function request, you can do something like: +._Java-only: requires AWS SDK builder_ + [source,java] -------------------------- from("direct:getFunction") diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc b/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc index ce27bca299518..b60d916313d9e 100644 --- a/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc +++ b/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc @@ -117,6 +117,8 @@ If your Camel Application is running behind a firewall or if you need to have more control over the `BlobServiceClient` instance configuration, you can create your own instance: +._Java-only: programmatic BlobServiceClient setup_ + [source,java] ----------------------------------------------------------------------- StorageSharedKeyCredential credential = new StorageSharedKeyCredential("yourAccountName", "yourAccessKey"); From 2f08f519fa8278700d260fa14f896df67efaee57 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 09:06:18 +0200 Subject: [PATCH 67/87] CAMEL-23789: Make OpenTelemetry Metrics component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../docs/opentelemetry-metrics-component.adoc | 132 +++++++++++++++++- 1 file changed, 127 insertions(+), 5 deletions(-) diff --git a/components/camel-opentelemetry-metrics/src/main/docs/opentelemetry-metrics-component.adoc b/components/camel-opentelemetry-metrics/src/main/docs/opentelemetry-metrics-component.adoc index 9617be0e87dde..c6aebcb488e1a 100644 --- a/components/camel-opentelemetry-metrics/src/main/docs/opentelemetry-metrics-component.adoc +++ b/components/camel-opentelemetry-metrics/src/main/docs/opentelemetry-metrics-component.adoc @@ -79,6 +79,8 @@ The meter attributes defined as URI parameters can be augmented by populating a For example +._Java-only: requires OpenTelemetry Attributes API_ + [source,java] ---- from("direct:in") @@ -244,25 +246,98 @@ Message headers can be used to override `increment` and `decrement` values speci |CamelMetricsCounterDecrement |Override decrement value in URI |Long |==================================================================== +[tabs] +==== +Java:: ++ [source,java] ---- // update counter 'simple.counter' by 417 from("direct:in") - .setHeader(OpenTelemetryConstants.HEADER_COUNTER_INCREMENT, constant(417)) + .setHeader("CamelMetricsCounterIncrement", constant(417L)) .to("opentelemetry-metrics:counter:simple.counter?increment=7") .to("direct:out"); ---- +XML:: ++ +[source,xml] +---- + + + + 417 + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsCounterIncrement + constant: 417 + - to: + uri: opentelemetry-metrics:counter:simple.counter + parameters: + increment: 7 + - to: + uri: direct:out +---- +==== + +[tabs] +==== +Java:: ++ [source,java] ---- // updates counter using simple language to evaluate 'body.length' from("direct:in") - .setHeader(OpenTelemetryConstants.HEADER_COUNTER_INCREMENT, simple("${body.length}")) + .setHeader("CamelMetricsCounterIncrement", simple("${body.length}")) .to("opentelemetry-metrics:counter:body.len") .to("direct:out"); +---- +XML:: ++ +[source,xml] +---- + + + + ${body.length} + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsCounterIncrement + simple: "${body.length}" + - to: + uri: opentelemetry-metrics:counter:body.len + - to: + uri: direct:out +---- +==== + [[OpenTelemetryComponent-summary]] === Distribution Summary @@ -410,16 +485,53 @@ A specific Message header can be used to override the value specified in the Ope |CamelMetricsHistogramValue |Override histogram value in URI |Long |================================================================= +[tabs] +==== +Java:: ++ [source,java] ---- -// adds value 992.0 to 'simple.histogram' +// adds value 992 to 'simple.histogram' from("direct:in") - .setHeader(OpenTelemetryConstants.HEADER_HISTOGRAM_VALUE, constant(992)) + .setHeader("CamelMetricsHistogramValue", constant(992L)) .to("opentelemetry-metrics:summary:simple.histogram?value=700") - .to("direct:out") + .to("direct:out"); +---- +XML:: ++ +[source,xml] +---- + + + + 992 + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:in + steps: + - setHeader: + name: CamelMetricsHistogramValue + constant: 992 + - to: + uri: opentelemetry-metrics:summary:simple.histogram + parameters: + value: 700 + - to: + uri: direct:out +---- +==== + [[OpenTelemetryComponent-timer]] === Timer @@ -497,6 +609,8 @@ A specific Message header can be used to override action value specified in the |`org.apache.camel.component.opentelemetry.OpenTelemetryTimerAction` |======================================================================= +._Java-only: requires OpenTelemetryTimerAction enum_ + [source,java] ---- // sets timer action using header @@ -517,6 +631,8 @@ while the xref:#OpenTelemetryComponent-exchange-event-notifier[Exchange Event No A Route event notifier can be added to the CamelContext as follows: +._Java-only: programmatic CamelContext API_ + [source,java] ---- camelContext.getManagementStrategy().addEventNotifier(new OpenTelemetryRouteEventNotifier()); @@ -545,6 +661,8 @@ The following options are supported: An Exchange event notifier can be added to the CamelContext as follows: +._Java-only: programmatic CamelContext API_ + [source,java] ---- camelContext.getManagementStrategy().addEventNotifier(new OpenTelemetryExchangeEventNotifier()); @@ -579,6 +697,8 @@ leading to high cardinality in metrics. Route policy metrics can be enabled by adding the `OpenTelemetryRoutePolicyFactory` to the `CamelContext`: +._Java-only: programmatic CamelContext API_ + [source,java] ---- context.addRoutePolicyFactory(new OpenTelemetryRoutePolicyFactory()); @@ -622,6 +742,8 @@ It works by using an OpenTelemetry Timer to record the time taken to process eac The `OpenTelemetryMessageHistoryFactory` can be added to the `CamelContext`: +._Java-only: programmatic CamelContext API_ + [source,java] ---- context.setMessageHistoryFactory(new OpenTelemetryMessageHistoryFactory()); From 7c1b5e2666cd6123edfc6e2ca905ddacd1292477 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 09:10:00 +0200 Subject: [PATCH 68/87] CAMEL-23789: Make Salesforce component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/salesforce-component.adoc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc b/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc index a0ad9c03b0d00..1fc8fceaf0f0c 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc +++ b/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc @@ -1226,6 +1226,8 @@ template.requestBody("salesforce:updateSObject", doc); When using the <>, binary fields are automatically generated for blob fields: +._Java-only: generated DTO class_ + [source,java] ---- public class ContentVersion extends AbstractSObjectBase { @@ -1263,6 +1265,8 @@ Using binary fields provides significant performance improvements: The existing base64 string approach continues to work: +._Java-only: Salesforce DTO API_ + [source,java] ---- // Still supported - base64 approach @@ -2447,6 +2451,8 @@ The response is: For efficient document uploads without base64 encoding overhead, use the binary field approach: +._Java-only: Processor implementation with Salesforce DTO and binary fields_ + [source,java] ---- public class ContentProcessor implements Processor { @@ -2475,6 +2481,8 @@ public class ContentProcessor implements Processor { Give the output from the processor to the Salesforce component: +._Java-only: inline Processor instantiation_ + [source,java] ---- from("file:///home/camel/library") @@ -2487,6 +2495,8 @@ from("file:///home/camel/library") The traditional base64 encoding approach is still supported for backward compatibility: +._Java-only: Processor implementation with base64 encoding_ + [source,java] ---- public class ContentProcessor implements Processor { @@ -2519,6 +2529,8 @@ public class ContentProcessor implements Processor { methods to generate SOQL queries. For instance, to fetch all custom fields from _Account_ SObject, you can generate the SOQL SELECT by invoking: +._Java-only: QueryHelper API_ + [source,java] ---- String allCustomFieldsQuery = QueryHelper.queryToFetchFilteredFieldsOf(new Account(), SObjectField::isCustom); From 5692e27da8ab2fca7e8888e91ec673394079dfca Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 09:16:14 +0200 Subject: [PATCH 69/87] CAMEL-23789: Make XPath language docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/xpath-language.adoc | 94 ++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/components/camel-xpath/src/main/docs/xpath-language.adoc b/components/camel-xpath/src/main/docs/xpath-language.adoc index 4c4ceebf8de4f..6d0ef9fe63c71 100644 --- a/components/camel-xpath/src/main/docs/xpath-language.adoc +++ b/components/camel-xpath/src/main/docs/xpath-language.adoc @@ -70,6 +70,9 @@ local part. Camel will try to resolve a variable in the following steps: ==== Example of using variables, header and body in XPath expression You can combine headers, properties, body and variables in an XPath expression as shown in the example below: + +._Java-only: uses Document.class type conversion in setVariable/setHeader_ + [source,java] ---- from("timer:java?period=1000,repeatCount=1") @@ -268,6 +271,8 @@ TIP: Classes from `java.lang` can omit the FQN name, so you can use `resultType= Using `@XPath` annotation: +._Java-only: Java bean integration annotation_ + [source,java] ---- @XPath(value = "concat('foo-',//order/name/)", resultType = String.class) String name) @@ -348,6 +353,8 @@ If you have a standard set of namespaces you wish to work with and wish to share them across many XPath expressions, you can use the `org.apache.camel.support.builder.Namespaces` when using Java DSL as shown: +._Java-only: Namespaces builder API_ + [source,java] ---- Namespaces ns = new Namespaces("c", "http://acme.com/cheese"); @@ -370,6 +377,8 @@ In the XPath expression then the namespace is used by its prefix, e.g.: The namespace builder supports adding multiple namespaces as shown: +._Java-only: Namespaces builder API_ + [source,java] ---- Namespaces ns = new Namespaces("c", "http://acme.com/cheese") @@ -416,10 +425,12 @@ value from the message and bind it to a method parameter. NOTE: The default `@XPath` annotation has SOAP and XML namespaces available. +._Java-only: Java bean integration annotation_ + [source,java] ---- public class Foo { - + @Consume(uri = "activemq:my.queue") public void doSomething(@XPath("/person/@name") String name, String xml) { // process the inbound message here @@ -440,6 +451,8 @@ and hence why `CamelContext` is needed. For example, you can do something like this: +._Java-only: XPathBuilder API_ + [source,java] ---- boolean matches = XPathBuilder.xpath("/foo/bar/@xyz").matches(context, "")); @@ -449,6 +462,8 @@ This will match the given predicate. You can also evaluate as shown in the following three examples: +._Java-only: XPathBuilder API_ + [source,java] ---- String name = XPathBuilder.xpath("foo/bar").evaluate(context, "cheese", String.class); @@ -458,6 +473,8 @@ Boolean bool = XPathBuilder.xpath("foo/bar").evaluate(context, "truecheese"); @@ -630,6 +647,8 @@ such as `"classpath:"`, `"file:"`, or `"http:"`. This is done using the following syntax: `"resource:scheme:location"`, e.g., to refer to a file on the classpath you can do: +._Java-only: Java DSL expression syntax_ + [source,java] ---- .setHeader("myHeader").xpath("resource:classpath:myxpath.txt", String.class) @@ -668,6 +687,10 @@ Which you want to transform to a smaller structure: Then you can use simple as template and XPath to grab the content from the message payload, as shown in the route snippet below: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") @@ -680,11 +703,52 @@ from("direct:start") .to("mock:result"); ---- +XML:: ++ +[source,xml] +---- + + + + + ${xpath(/order/@id)} + ${xpath(/order/address/co/text())} + ${xpath(/order/first/text())} +]]> + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - transform: + simple: | + + ${xpath(/order/@id)} + ${xpath(/order/address/co/text())} + ${xpath(/order/first/text())} + + - to: + uri: mock:result +---- +==== + Notice how we use `${xpath(exp}` syntax in the simple template to use xpath that will be evaluated on the message body, to extract the content to be used in the output (see previous for output). Since the simple language can output anything, you can also use this to output in plain text or JSON, etc. +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") @@ -692,6 +756,34 @@ from("direct:start") .to("mock:result"); ---- +XML:: ++ +[source,xml] +---- + + + + The order ${xpath(/order/@id)} is being shipped to ${xpath(/order/address/co/text())} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - transform: + simple: "The order ${xpath(/order/@id)} is being shipped to ${xpath(/order/address/co/text())}" + - to: + uri: mock:result +---- +==== + == Dependencies To use XPath in your camel routes, you need to add the dependency on From 49f7dd0b699a69282a99188a4fd1a76500450ab9 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 09:18:16 +0200 Subject: [PATCH 70/87] CAMEL-23789: Make Docling component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/docling-component.adoc | 49 +++++++++++++++++-- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc b/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc index 16ee1514a8502..ce4318ede5608 100644 --- a/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc +++ b/components/camel-ai/camel-docling/src/main/docs/docling-component.adoc @@ -693,6 +693,8 @@ YAML:: When using YAML DSL, the processor references used in the examples above would be implemented as Spring beans: +._Java-only: Spring bean Processor implementation_ + [source,java] ---- @Component("htmlProcessor") @@ -997,6 +999,8 @@ YAML:: NOTE: For the aggregation example above, you can also use a custom processor. Create a Java class: +._Java-only: Processor implementation_ + [source,java] ---- public class DocumentListProcessor implements Processor { @@ -1196,6 +1200,8 @@ Headers can be used to override batch configuration per-message: The batch operations accept multiple input formats: +._Java-only: Java collection types_ + [source,java] ---- // List of file paths @@ -1792,6 +1798,8 @@ NOTE: Custom polling workflows require Java processors and are more complex. The The simplest custom workflow uses a Java loop to poll for status: +._Java-only: Java test API (ProducerTemplate with polling loop)_ + [source,java] ---- // Submit conversion @@ -2336,17 +2344,48 @@ camel.oauth.docling.client-secret=my-secret camel.oauth.docling.token-endpoint=https://idp.example.com/token ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("file:///data/input") - .to("docling:CONVERT_TO_MARKDOWN" - + "?useDoclingServe=true" - + "&doclingServeUrl=http://localhost:5001" - + "&oauthProfile=docling" - + "&contentInBody=true") + .to("docling:CONVERT_TO_MARKDOWN?useDoclingServe=true&doclingServeUrl=http://localhost:5001&oauthProfile=docling&contentInBody=true") .log("${body}"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:///data/input + steps: + - to: + uri: docling:CONVERT_TO_MARKDOWN + parameters: + useDoclingServe: true + doclingServeUrl: "http://localhost:5001" + oauthProfile: docling + contentInBody: true + - log: + message: "${body}" +---- +==== + == Advanced Processing Options (API Mode) When using docling-serve API mode (`useDoclingServe=true`), the component exposes advanced processing options that control how the server processes documents. These options are passed directly to the docling-serve API and provide fine-grained control over OCR, table recognition, enrichment features, and output formatting. From ae354fb74379a0f1ce4c8f22272a8982d1cbd9cf Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 09:25:57 +0200 Subject: [PATCH 71/87] CAMEL-23789: Make Keycloak component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/keycloak-component.adoc | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/components/camel-keycloak/src/main/docs/keycloak-component.adoc b/components/camel-keycloak/src/main/docs/keycloak-component.adoc index e363f40f2e28d..208e418271cf4 100644 --- a/components/camel-keycloak/src/main/docs/keycloak-component.adoc +++ b/components/camel-keycloak/src/main/docs/keycloak-component.adoc @@ -1218,6 +1218,8 @@ YAML:: Identity providers allow you to configure external authentication systems like LDAP, Active Directory, Google, GitHub, and other SAML/OIDC providers. +._Java-only: Keycloak admin API_ + [source,java] ---- // Create OIDC identity provider @@ -1260,6 +1262,8 @@ template.sendBodyAndHeaders("keycloak:admin?operation=deleteIdentityProvider", n Organizations (introduced in Keycloak 26) allow you to model multi-tenant scenarios within a realm. Each organization can have members and can be linked to one or more identity providers. +._Java-only: Keycloak admin API_ + [source,java] ---- // Create a new organization @@ -1722,6 +1726,8 @@ Keycloak Authorization Services provide fine-grained authorization with resource NOTE: These operations require a client with authorization services enabled in Keycloak. +._Java-only: Keycloak authorization API_ + [source,java] ---- // Create authorization resource @@ -1990,6 +1996,8 @@ YAML:: ===== Fine-Grained Resource Authorization +._Java-only: Keycloak authorization API_ + [source,java] ---- // Check if user can access a specific document @@ -2020,6 +2028,8 @@ public Map checkMultipleResources(String accessToken, List` 3. **Exchange Property**: `CamelKeycloakAccessToken` +._Java-only: accessing token from exchange_ + [source,java] ---- // Using header @@ -5122,6 +5144,8 @@ beans: === Sending Requests with Tokens +._Java-only: HTTP client authentication_ + [source,java] ---- // In your client code, include the access token @@ -5231,6 +5255,8 @@ keycloak.client-secret=your-client-secret === Spring Configuration +._Java-only: Spring configuration class_ + [source,java] ---- @Configuration @@ -5600,6 +5626,8 @@ For permissions-based authorization, you have several options to include permiss 3. In your application code, you can then use scopes as permissions: +._Java-only: programmatic security policy configuration_ + [source,java] ---- KeycloakSecurityPolicy policy = new KeycloakSecurityPolicy(); From faf15afa81208c3569b429aab26c27e353c37f15 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 09:36:50 +0200 Subject: [PATCH 72/87] CAMEL-23789: Make Bindy data format docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/bindy-dataformat.adoc | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/components/camel-bindy/src/main/docs/bindy-dataformat.adoc b/components/camel-bindy/src/main/docs/bindy-dataformat.adoc index 95c9a813401c9..5d1f9ec6f0256 100644 --- a/components/camel-bindy/src/main/docs/bindy-dataformat.adoc +++ b/components/camel-bindy/src/main/docs/bindy-dataformat.adoc @@ -160,6 +160,7 @@ The separator used to segregate the fields in the CSV record is `,` : 10, J, Pauline, M, XD12345678, Fortis Dynamic 15/15, 2500, USD, 08-01-2009 ---- +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord( separator = "," ) @@ -176,6 +177,7 @@ Compare to the previous case, the separator here is `;` instead of `,` : 10; J; Pauline; M; XD12345678; Fortis Dynamic 15/15; 2500; USD; 08-01-2009 ---- +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord( separator = ";" ) @@ -192,6 +194,7 @@ Compare to the previous case, the separator here is `|` instead of `;` : 10| J| Pauline| M| XD12345678| Fortis Dynamic 15/15| 2500| USD| 08-01-2009 ---- +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord( separator = "\\|" ) @@ -220,6 +223,7 @@ In this case, bindy will remove the first and last character of the line which i "10","J","Pauline"," M","XD12345678","Fortis Dynamic 15,15","2500","USD","08-01-2009" ---- +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord( separator = "\",\"" ) @@ -236,6 +240,7 @@ record is enclosed with either single or double quotes and automatically removes "10","J","Pauline"," M","XD12345678","Fortis Dynamic 15,15","2500","USD","08-01-2009" ---- +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord( separator = "," ) @@ -248,6 +253,7 @@ Notice that if you want to marshal from Object to CSV and use quotes, then you need to specify which quote character to use, using the `quote` attribute on the `@CsvRecord` as shown below: +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord( separator = ",", quote = "\"" ) @@ -268,6 +274,7 @@ order id, client id, first name, last name, isin code, instrument name, quantity To inform bindy that this first line must be skipped during the parsing process, then we use the attribute : +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",", skipFirstLine = true) @@ -281,6 +288,7 @@ public Class Order { To include at the first line of the CSV generated, the attribute `generateHeaderColumns` must be set to true in the annotation like this : +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord( generateHeaderColumns = true ) @@ -303,6 +311,7 @@ If the platform where camel-bindy will run is not Windows but Macintosh or Unix, then you can change the crlf property like this. Three values are available: `WINDOWS`, `UNIX` or `MAC`. +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",", crlf="MAC") @@ -316,6 +325,7 @@ character, you can opt to specify it using the crlf parameter. In the following example, we can end the line with a comma followed by the newline character: +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",", crlf=",\n") @@ -332,6 +342,7 @@ Then, in this case, we can use the attribute `isOrdered = true` to indicate this in combination with attribute `position` of the DataField annotation. +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(isOrdered = true) @@ -381,6 +392,7 @@ annotation Link in the Order class like this : *Property Link* +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",") @@ -398,6 +410,7 @@ And for the class Client : *Class Link* +._Java-only: Java annotation model class_ [source,java] ---- @Link @@ -493,6 +506,7 @@ record. *Position* +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",") @@ -513,6 +527,7 @@ the class Client (see here after). *Position continues in another model class* +._Java-only: Java annotation model class_ [source,java] ---- public class Client { @@ -534,6 +549,7 @@ The pattern allows enriching or validates the format of your data *Pattern* +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",") @@ -567,6 +583,7 @@ your number. *Precision* +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",") @@ -607,6 +624,7 @@ Here is an example: *Position is different in output* +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",", isOrdered = true) @@ -644,6 +662,7 @@ true. *Required* +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",") @@ -678,6 +697,7 @@ true. *Trim* +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",") @@ -704,6 +724,7 @@ If a field is not defined then uses the value indicated by the *Default value* +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",") @@ -728,6 +749,8 @@ public class Order { Specifies the column name for the property only if `@CsvRecord` has annotation `generateHeaderColumns = true`. *Column Name* + +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",", generateHeaderColumns = true) @@ -823,6 +846,7 @@ This example shows how to design the model to parse/format a fixed message: *Fixed-simple* +._Java-only: Java annotation model class_ [source,java] ---- @FixedLengthRecord(length=54, paddingChar=' ') @@ -874,6 +898,7 @@ field and how to assign a padding character which is `' '` here: *Fixed-padding-align* +._Java-only: Java annotation model class_ [source,java] ---- @FixedLengthRecord(length=60, paddingChar=' ') @@ -927,6 +952,7 @@ the field as we have a number format where we would like to pad with *Fixed-padding-field* +._Java-only: Java annotation model class_ [source,java] ---- @FixedLengthRecord(length = 65, paddingChar = ' ') @@ -979,6 +1005,7 @@ in the following example: *Fixed-delimited* +._Java-only: Java annotation model class_ [source,java] ---- @FixedLengthRecord @@ -1036,6 +1063,7 @@ defined by the value of `instrumentNumberLen` field in the record. *Fixed-delimited* +._Java-only: Java annotation model class_ [source,java] ---- @FixedLengthRecord @@ -1096,6 +1124,7 @@ record and footer record. ---- *Fixed-header-and-footer-main-class* +._Java-only: Java annotation model class_ [source,java] ---- @FixedLengthRecord(header = OrderHeader.class, footer = OrderFooter.class) @@ -1171,6 +1200,7 @@ of interest. In this case, you can tell Bindy to skip parsing of everything beyond the last mapped field by setting the `ignoreTrailingChars` property on the `@FixedLengthRecord` declaration. +._Java-only: Java annotation model class_ [source,java] ---- @FixedLengthRecord(ignoreTrailingChars = true) @@ -1263,6 +1293,7 @@ and how to use the annotation: *FIX - message* +._Java-only: Java annotation model class_ [source,java] ---- @Message(keyValuePairSeparator = "=", pairSeparator = "\\u0001", type="FIX", version="4.1") @@ -1332,6 +1363,7 @@ This parameter represents the key of the field in the message: *FIX message - Tag* +._Java-only: Java annotation model class_ [source,java] ---- @Message(keyValuePairSeparator = "=", pairSeparator = "\\u0001", type="FIX", version="4.1") @@ -1369,6 +1401,7 @@ annotation `@KeyValuePairField`. *FIX message - Tag - sort* +._Java-only: Java annotation model class_ [source,java] ---- @Message(keyValuePairSeparator = "=", pairSeparator = "\\u0001", type = "FIX", version = "4.1", isOrdered = true) @@ -1420,6 +1453,7 @@ Definition of the header section: *FIX message - Section - Header* +._Java-only: Java annotation model class_ [source,java] ---- @Section(number = 1) @@ -1437,6 +1471,7 @@ Definition of the body section: *FIX message - Section - Body* +._Java-only: Java annotation model class_ [source,java] ---- @Section(number = 2) @@ -1458,6 +1493,7 @@ Definition of the footer section: *FIX message - Section - Footer* +._Java-only: Java annotation model class_ [source,java] ---- @Section(number = 3) @@ -1532,6 +1568,7 @@ of Book. *Generate CSV with repetitive data* +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator=",") @@ -1581,6 +1618,7 @@ And the code: *Reading FIX message containing group of tags/keys* +._Java-only: Java annotation model class_ [source,java] ---- public class Order { @@ -1621,6 +1659,7 @@ The purpose of the annotation `@BindyConverter` is to define a converter to be used on field level. The provided class must implement the Format interface. +._Java-only: Java annotation model class_ [source,java] ---- @FixedLengthRecord(length = 10, paddingChar = ' ') @@ -1648,6 +1687,7 @@ public static class CustomConverter implements Format { The purpose of the annotation `@FormatFactories` is to define a set of converters at record-level. The provided classes must implement the `FormatFactoryInterface` interface. +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",") @@ -1743,6 +1783,7 @@ explicit `defaultValue = "0"` on the field. ==== Example +._Java-only: Java annotation model class_ [source,java] ---- @CsvRecord(separator = ",", continueParseOnFailure = true) @@ -1805,6 +1846,7 @@ corresponds to the class associated with the CSV record type) which is configured with _com.acme.model.MyModel.class_ to initialize the model objects configured in this package. +._Java-only: Java annotation model class_ [source,java] ---- DataFormat bindy = new BindyCsvDataFormat(com.acme.model.MyModel.class); @@ -1812,8 +1854,9 @@ DataFormat bindy = new BindyCsvDataFormat(com.acme.model.MyModel.class); === Setting locale -Bindy supports configuring the locale on the dataformat, such as +Bindy supports configuring the locale on the dataformat, such as +._Java-only: Java annotation model class_ [source,java] ---- BindyCsvDataFormat bindy = new BindyCsvDataFormat(com.acme.model.MyModel.class); @@ -1824,6 +1867,7 @@ bindy.setLocale("us"); Or to use the platform default locale, then use "default" as the locale name. +._Java-only: Java annotation model class_ [source,java] ---- BindyCsvDataFormat bindy = new BindyCsvDataFormat(com.acme.model.MyModel.class); @@ -1833,6 +1877,7 @@ bindy.setLocale("default"); === Unmarshaling +._Java-only: Java annotation model class_ [source,java] ---- from("file://inbox") @@ -1844,6 +1889,7 @@ Alternatively, you can use a named reference to a data format which can then be defined in your registry, e.g., your Spring XML file: +._Java-only: Java annotation model class_ [source,java] ---- from("file://inbox") @@ -1863,6 +1909,7 @@ object to be returned per line. Each object can be retrieved using its class name. +._Java-only: Java annotation model class_ [source,java] ---- List> unmarshaledModels = (List>) exchange.getIn().getBody(); @@ -1884,6 +1931,7 @@ for processing in a route, you could use a combination of a Splitter and a Processor as per the following: +._Java-only: inline Processor implementation_ [source,java] ---- from("file://inbox") @@ -1907,6 +1955,7 @@ can already do the character set conversion. Sometimes you need to remove this p exchange before sending it to the unmarshal. If you don't remove it, the conversion might be done twice, which might lead to unwanted results. +._Java-only: Java constant reference_ [source,java] ---- from("file://inbox?charset=Cp922") @@ -1920,6 +1969,7 @@ from("file://inbox?charset=Cp922") To generate CSV records from a collection of model objects, you create the following route : +._Java-only: Java annotation model class_ [source,java] ---- from("direct:handleOrders") From 39804f2265c951302c70689a2bb0cd529ca1972e Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 09:37:59 +0200 Subject: [PATCH 73/87] CAMEL-23789: Make OpenSearch and REST component docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/opensearch-component.adoc | 51 ++++++++++++++++++- .../src/main/docs/rest-component.adoc | 7 +++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/components/camel-opensearch/src/main/docs/opensearch-component.adoc b/components/camel-opensearch/src/main/docs/opensearch-component.adoc index fafa4e6def1fa..20463af1d98e8 100644 --- a/components/camel-opensearch/src/main/docs/opensearch-component.adoc +++ b/components/camel-opensearch/src/main/docs/opensearch-component.adoc @@ -102,6 +102,7 @@ the key "indexId". === Configure the component and enable basic authentication To use the OpenSearch component, it has to be configured with a minimum configuration. +._Java-only: programmatic CamelContext configuration_ [source,java] ---- OpensearchComponent opensearchComponent = new OpensearchComponent(); @@ -112,6 +113,7 @@ camelContext.addComponent("opensearch", opensearchComponent); For basic authentication with OpenSearch or using reverse http proxy in front of the OpenSearch cluster, simply setup basic authentication and SSL on the component like the example below +._Java-only: programmatic CamelContext configuration_ [source,java] ---- OpenSearchComponent opensearchComponent = new OpenSearchComponent(); @@ -176,6 +178,7 @@ NOTE: For this operation, you'll need to specify an indexId header. A client would simply need to pass a body message containing a Map to the route. The result body contains the indexId created. +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- Map map = new HashMap(); @@ -224,6 +227,7 @@ YAML:: ---- ==== +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- String query = "{\"query\":{\"match\":{\"doc.content\":\"new release of ApacheCamel\"}}}"; @@ -233,6 +237,7 @@ HitsMetadata response = template.requestBody("direct:search", query, HitsMeta Search on specific field(s) using Map. +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- Map actualQuery = new HashMap<>(); @@ -287,6 +292,7 @@ YAML:: ---- ==== +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- String query = "{\"query\":{\"match\":{\"doc.content\":\"new release of ApacheCamel\"}}}"; @@ -297,6 +303,10 @@ try (OpenSearchScrollRequestIterator response = template.requestBody("direct:sea xref:eips:split-eip.adoc[Split EIP] can also be used. +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:search") @@ -308,6 +318,44 @@ from("direct:search") .end(); ---- +XML:: ++ +[source,xml] +---- + + + + + ${body} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:search + steps: + - to: + uri: opensearch://opensearch + parameters: + operation: Search + indexName: twitter + useScroll: true + scrollKeepAliveMs: 30000 + - split: + simple: "${body}" + streaming: true + steps: + - to: + uri: mock:output +---- +==== + === MultiSearch Example MultiSearching on specific field(s) and value uses the Operation `MultiSearch`. @@ -348,8 +396,9 @@ YAML:: ---- ==== -MultiSearch on specific field(s) +MultiSearch on specific field(s) +._Java-only: Java SDK builder API (ProducerTemplate)_ [source,java] ---- MsearchRequest.Builder builder = new MsearchRequest.Builder().index("twitter").searches( diff --git a/components/camel-rest/src/main/docs/rest-component.adoc b/components/camel-rest/src/main/docs/rest-component.adoc index 272eed6610511..c28e90fd6f9f9 100644 --- a/components/camel-rest/src/main/docs/rest-component.adoc +++ b/components/camel-rest/src/main/docs/rest-component.adoc @@ -239,6 +239,7 @@ YAML:: And then the dynamic value `\{me}` is mapped to a header or variable with the same name. So to call this REST service, you can send an empty message body and a header as shown: +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- template.sendBodyAndHeader("direct:start", null, "me", "Donald Duck"); @@ -246,6 +247,7 @@ template.sendBodyAndHeader("direct:start", null, "me", "Donald Duck"); Instead of a header you can also use exchange variable such as: +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- String response = template.withVariable("me", "Donald Duck").to("direct:start").request(String.class); @@ -291,6 +293,7 @@ YAML:: Instead of using the host option, you can configure the host on the `restConfiguration` as shown: +._Java-only: Java programmatic REST configuration API_ [source,java] ---- restConfiguration().host("myserver:8080/foo"); @@ -302,6 +305,7 @@ from("direct:start") You can use the `producerComponent` to select which Camel component to use as the HTTP client, for example to use http, you can do: +._Java-only: Java programmatic REST configuration API_ [source,java] ---- restConfiguration().host("myserver:8080/foo").producerComponent("http"); @@ -317,6 +321,7 @@ The REST producer supports binding using JSON or XML like the rest-dsl does. For example, to use jetty with JSON binding mode turned on, you can configure this in the REST configuration: +._Java-only: Java programmatic REST configuration API_ [source,java] ---- restConfiguration().component("jetty").host("localhost").port(8080).bindingMode(RestBindingMode.json); @@ -327,6 +332,7 @@ from("direct:start") Then when calling the REST service using the REST producer, it will automatically bind any POJOs to JSON before calling the REST service: +._Java-only: Java POJO API (ProducerTemplate)_ [source,java] ---- UserPojo user = new UserPojo(); @@ -344,6 +350,7 @@ would need to configure the `outType` option to specify what is the class name o For example, if the REST service returns a JSON payload that binds to `com.foo.MyResponsePojo` you can configure this as shown: +._Java-only: Java programmatic REST configuration API_ [source,java] ---- restConfiguration().component("jetty").host("localhost").port(8080).bindingMode(RestBindingMode.json); From 0403d6b59ed87cf0920c5b1f1fad60ad17b79840 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 09:41:59 +0200 Subject: [PATCH 74/87] CAMEL-23789: Make ControlBus, AMQP, Zeebe, and CSV docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../camel-amqp/src/main/docs/amqp-component.adoc | 12 ++++++++++-- .../src/main/docs/controlbus-component.adoc | 7 +++++++ .../camel-csv/src/main/docs/csv-dataformat.adoc | 8 +++++++- .../camel-zeebe/src/main/docs/zeebe-component.adoc | 9 +++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/components/camel-amqp/src/main/docs/amqp-component.adoc b/components/camel-amqp/src/main/docs/amqp-component.adoc index 66022bb98abfe..7ac82c059e06d 100644 --- a/components/camel-amqp/src/main/docs/amqp-component.adoc +++ b/components/camel-amqp/src/main/docs/amqp-component.adoc @@ -33,6 +33,7 @@ for this component: == URI format +._Java-only: URI format syntax_ [source,java] ---- amqp:[queue:|topic:]destinationName[?options] @@ -53,12 +54,13 @@ former is almost identical to the latter: *Using AMQP component* +._Java-only: Java DSL snippet (incomplete route)_ [source,java] ---- // Consuming from AMQP queue from("amqp:queue:incoming"). to(...); - + // Sending messages to the AMQP topic from(...). to("amqp:topic:notify"); @@ -69,10 +71,12 @@ from(...). *Creating AMQP 1.0 component* AMQPComponents may be created using the provided factory methods, for example: + +._Java-only: Java programmatic component factory_ [source,java] ---- AMQPComponent amqp = AMQPComponent.amqpComponent("amqp://localhost:5672"); - + AMQPComponent authorizedAmqp = AMQPComponent.amqpComponent("amqp://localhost:5672", "user", "password"); ---- @@ -84,6 +88,7 @@ configuring SSL, authentication, and AMQP Broker host and port. The component can be configured to connect to an AMQP broker using SSL by setting the `useSsl` option and providing keystore and truststore details, for example: +._Java-only: Java programmatic SSL configuration_ [source,java] ---- AMQPComponent component = new AMQPComponent(); @@ -102,6 +107,7 @@ component.setKeyStoreType("PKCS12"); A username and password may be provided for AMQP broker authentication: +._Java-only: Java programmatic component configuration_ [source,java] ---- AMQPComponent component = new AMQPComponent(); @@ -111,6 +117,7 @@ component.setPassword("rider"); *AMQP Broker host and port configuration* +._Java-only: Java programmatic component configuration_ [source,java] ---- AMQPComponent amqpComponent = new AMQPComponent(); @@ -127,6 +134,7 @@ if not provided. If you, for example, need to enable `amqp.traceFrames` you can do that by appending the option to your URI, like the following example: +._Java-only: Java programmatic component factory_ [source,java] ---- AMQPComponent amqp = AMQPComponent.amqpComponent("amqp://localhost:5672?amqp.traceFrames=true"); diff --git a/components/camel-controlbus/src/main/docs/controlbus-component.adoc b/components/camel-controlbus/src/main/docs/controlbus-component.adoc index fd2b1d2ae1231..2ea706e279a99 100644 --- a/components/camel-controlbus/src/main/docs/controlbus-component.adoc +++ b/components/camel-controlbus/src/main/docs/controlbus-component.adoc @@ -71,6 +71,7 @@ include::partial$component-endpoint-headers.adoc[] The route command allows you to do common tasks on a given route very easily. For example, to start a route, you can send an empty message to this endpoint: +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- template.sendBody("controlbus:route?routeId=foo&action=start", null); @@ -78,6 +79,7 @@ template.sendBody("controlbus:route?routeId=foo&action=start", null); To get the status of the route, you can do: +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- String status = template.requestBody("controlbus:route?routeId=foo&action=status", null, String.class); @@ -90,6 +92,7 @@ This requires JMX to be enabled (it is enabled by default) then you can get the performance statics per route, or for the CamelContext. For example, to get the statics for a route named foo, we can use: +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- String xml = template.requestBody("controlbus:route?routeId=foo&action=stats", null, String.class); @@ -100,6 +103,7 @@ It is the same data you can get from JMX with the `dumpRouteStatsAsXml` operatio To get statics for the entire `CamelContext` you just omit the routeId parameter as shown below: +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- String xml = template.requestBody("controlbus:route?action=stats", null, String.class); @@ -110,6 +114,7 @@ String xml = template.requestBody("controlbus:route?action=stats", null, String. You can use the xref:languages:simple-language.adoc[Simple] language with the control bus. For example, to stop a specific route, you can send a message to the `"controlbus:language:simple"` endpoint containing the following message: +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- template.sendBody("controlbus:language:simple", "${camelContext.getRouteController().stopRoute('myRoute')}"); @@ -118,6 +123,7 @@ template.sendBody("controlbus:language:simple", "${camelContext.getRouteControll As this is a void operation, no result is returned. However, if you want the route status, you can use: +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- String status = template.requestBody("controlbus:language:simple", "${camelContext.getRouteController().getRouteStatus('myRoute')}", String.class); @@ -130,6 +136,7 @@ extend the xref:languages:simple-language.adoc[Simple] language. For example, to shut down Apache Camel itself, you can do: +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- template.sendBody("controlbus:language:simple?async=true", "${camelContext.stop()}"); diff --git a/components/camel-csv/src/main/docs/csv-dataformat.adoc b/components/camel-csv/src/main/docs/csv-dataformat.adoc index 12c337a57480a..ee6493c1c478a 100644 --- a/components/camel-csv/src/main/docs/csv-dataformat.adoc +++ b/components/camel-csv/src/main/docs/csv-dataformat.adoc @@ -47,6 +47,7 @@ CSV payload. Considering the following body: +._Java-only: Java collection API_ [source,java] ------------------------------------------------------- Map body = new LinkedHashMap<>(); @@ -165,6 +166,7 @@ YAML:: The resulting message will contain a `List>` like... +._Java-only: Java collection API_ [source,java] -------------------------------------------------------------------------------------------------------------- List> data = (List>) exchange.getIn().getBody(); @@ -188,6 +190,7 @@ Given a bean which can handle the incoming data... *MyCsvHandler.java* +._Java-only: Java handler class_ [source,java] ------------------------------------------------------- // Some comments here @@ -212,12 +215,13 @@ public void doHandleCsvData(List> csvData) === Marshaling with a pipe as delimiter Considering the following body: +._Java-only: Java collection API_ [source,java] ------------------------------------------------------- Map body = new LinkedHashMap<>(); body.put("foo", "abc"); body.put("bar", 123); -------------------------------------------------------- +------------------------------------------------------- And this Java route definition: @@ -315,6 +319,7 @@ should illustrate this customization. You can instruct the CSV Data Format to collect the headers into a message header called CamelCsvHeaderRecord. +._Java-only: Java programmatic data format configuration_ [source,java] -------------------------------------------- CsvDataFormat csv = new CsvDataFormat(); @@ -464,6 +469,7 @@ YAML:: It looks like that +._Java-only: Java programmatic configuration_ [source,java] -------------------------------------- CSVConfig csvConfig = new CSVConfig(); diff --git a/components/camel-zeebe/src/main/docs/zeebe-component.adoc b/components/camel-zeebe/src/main/docs/zeebe-component.adoc index 75f8fed5d7ac8..8fe804763a166 100644 --- a/components/camel-zeebe/src/main/docs/zeebe-component.adoc +++ b/components/camel-zeebe/src/main/docs/zeebe-component.adoc @@ -81,6 +81,7 @@ The endpoints accept either Java request objects as shown in the examples below * startProcess +._Java-only: inline Processor with Zeebe SDK types_ [source,java] ---------------------------------------------------------------------------------------------------------------------- from("direct:start") @@ -125,6 +126,7 @@ The endpoints accept either Java request objects as shown in the examples below * cancelProcess +._Java-only: inline Processor with Zeebe SDK types_ [source,java] ---------------------------------------------------------------------------------------------------------------------- from("direct:start") @@ -144,6 +146,7 @@ The endpoints accept either Java request objects as shown in the examples below * publishMessage +._Java-only: inline Processor with Zeebe SDK types_ [source,java] ---------------------------------------------------------------------------------------------------------------------- from("direct:start") @@ -190,6 +193,7 @@ The endpoints accept either Java request objects as shown in the examples below * completeJob +._Java-only: inline Processor with Zeebe SDK types_ [source,java] ---------------------------------------------------------------------------------------------------------------------- from("direct:start") @@ -210,6 +214,7 @@ The endpoints accept either Java request objects as shown in the examples below * failJob +._Java-only: inline Processor with Zeebe SDK types_ [source,java] ---------------------------------------------------------------------------------------------------------------------- from("direct:start") @@ -231,6 +236,7 @@ The endpoints accept either Java request objects as shown in the examples below * updateJobRetries +._Java-only: inline Processor with Zeebe SDK types_ [source,java] ---------------------------------------------------------------------------------------------------------------------- from("direct:start") @@ -251,6 +257,7 @@ The endpoints accept either Java request objects as shown in the examples below * throwError +._Java-only: inline Processor with Zeebe SDK types_ [source,java] ---------------------------------------------------------------------------------------------------------------------- from("direct:start") @@ -272,6 +279,7 @@ The endpoints accept either Java request objects as shown in the examples below * deployResource +._Java-only: inline Processor with Zeebe SDK types_ [source,java] ---------------------------------------------------------------------------------------------------------------------- from("direct:start") @@ -306,6 +314,7 @@ The endpoints accept either Java request objects as shown in the examples below *Example* +._Java-only: inline Processor with Zeebe SDK types_ [source,java] --------------------------------------------------------------------------------------------------------------------------------------------- from("zeebe://worker?jobKey=job1&timeout=20") From be2bf0197d1741413a73ff0e11a4cb52ee061d02 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 09:50:36 +0200 Subject: [PATCH 75/87] CAMEL-23789: Make JSONPath, HL7, and Netty docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/hl7-dataformat.adoc | 61 ++++++++++++++++++- .../src/main/docs/jsonpath-language.adoc | 44 +++++++++++++ .../src/main/docs/netty-component.adoc | 9 +++ 3 files changed, 112 insertions(+), 2 deletions(-) diff --git a/components/camel-hl7/src/main/docs/hl7-dataformat.adoc b/components/camel-hl7/src/main/docs/hl7-dataformat.adoc index 31f1d6fccbe07..7d96e8956d679 100644 --- a/components/camel-hl7/src/main/docs/hl7-dataformat.adoc +++ b/components/camel-hl7/src/main/docs/hl7-dataformat.adoc @@ -99,6 +99,7 @@ up in the Spring XML file: The endpoint *hl7MinaLlistener* can then be used in a route as a consumer, as this Java DSL example illustrates: +._Java-only: Java DSL with Spring bean endpoint reference_ [source,java] ---- from("hl7MinaListener") @@ -117,6 +118,7 @@ configured in the Spring XML as: The business logic can be implemented in POJO classes that do not depend on Camel, as shown here: +._Java-only: Java service class_ [source,java] ---- import ca.uhn.hl7v2.HL7Exception; @@ -159,6 +161,7 @@ The beans can be set in the Spring XML file: The endpoint *hl7NettyListener* can then be used in a route as a consumer, as this Java DSL example illustrates: +._Java-only: Java DSL with Spring bean endpoint reference_ [source,java] ---- from("hl7NettyListener") @@ -195,6 +198,7 @@ QRD|200612211200|R|I|GetPatient|||1^RD|0101701234|DEM|| Using the HL7 model, you can work with a `ca.uhn.hl7v2.model.Message` object, e.g., to retrieve a patient ID: +._Java-only: Java HAPI model API_ [source,java] ---- Message msg = exchange.getIn().getBody(Message.class); @@ -207,6 +211,7 @@ have to work with `byte[]`, `String` or any other simple object formats. You can just use the HAPI HL7v2 model objects. If you know the message type in advance, you can be more type-safe: +._Java-only: Java HAPI model API_ [source,java] ---- QRY_A19 msg = exchange.getIn().getBody(QRY_A19.class); @@ -231,6 +236,7 @@ streamed data from the HL7 MLLP To use the data format, simply instantiate an instance and invoke the marshal or unmarshal operation in the route builder: +._Java-only: Java programmatic data format instantiation_ [source,java] ---- DataFormat hl7 = new HL7DataFormat(); @@ -244,6 +250,7 @@ In the sample above, the HL7 is marshalled from a HAPI Message object to a byte stream and put on a JMS queue. + The next example is the opposite: +._Java-only: Java programmatic data format instantiation_ [source,java] ---- DataFormat hl7 = new HL7DataFormat(); @@ -279,6 +286,7 @@ TypeConverter handles `Document` to `Message` conversion automatically. ==== EDI to XML conversion +._Java-only: Java programmatic data format configuration_ [source,java] ---- HL7DataFormat hl7xml = new HL7DataFormat(); @@ -293,6 +301,7 @@ In this example, the HL7 EDI input is unmarshalled directly to an XML `Document` ==== XML to Message conversion +._Java-only: Java programmatic data format configuration_ [source,java] ---- HL7DataFormat hl7xml = new HL7DataFormat(); @@ -307,6 +316,7 @@ Here, a HAPI `Message` is marshalled to HL7 XML bytes. ==== Round-trip EDI to XML to EDI +._Java-only: Java programmatic data format configuration_ [source,java] ---- HL7DataFormat hl7xml = new HL7DataFormat(); @@ -336,17 +346,64 @@ There is a shorthand syntax in Camel for well-known data formats that are commonly used. Then you don't need to create an instance of the `HL7DataFormat` object: +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:hl7in") +from("direct:hl7in") .marshal().hl7() .to("jms:queue:hl7out"); - from("jms:queue:hl7out") +from("jms:queue:hl7out") .unmarshal().hl7() .to("patientLookupService"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:hl7in + steps: + - marshal: + hl7: {} + - to: + uri: jms:queue:hl7out +- route: + from: + uri: jms:queue:hl7out + steps: + - unmarshal: + hl7: {} + - to: + uri: patientLookupService +---- +==== + == Message Headers The unmarshal operation adds these fields from the MSH segment as diff --git a/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc b/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc index a0b46ecb13e39..213e90df60632 100644 --- a/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc +++ b/components/camel-jsonpath/src/main/docs/jsonpath-language.adoc @@ -258,6 +258,10 @@ By default, the message body is the source for the jsonpath evaluation. However, if you need to refer to a variable or message header instead as the body, then this is easy as shown below: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:start") @@ -266,6 +270,40 @@ from("direct:start") .to("mock:cars"); ---- +XML:: ++ +[source,xml] +---- + + + + ["Ford", "BMW", "Fiat"] + + + ${jsonpath(variable:cars , $.length())} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setVariable: + name: cars + constant: '["Ford", "BMW", "Fiat"]' + - setBody: + simple: "${jsonpath(variable:cars , $.length())}" + - to: + uri: mock:cars +---- +==== + Here we set a variable named _cars_ with a json array of 3 cars. Then we want to count the length of the array using jsonpath length function. Notice how we use the inlined simple language, and can easily refer to the variable as the source using `variable:cars`. @@ -276,6 +314,7 @@ You can use xref:manual::bean-integration.adoc[Bean Integration] to invoke a method on a bean and use various languages such as JSONPath (via the `@JsonPath` annotation) to extract a value from the message and bind it to a method parameter, as shown below: +._Java-only: Java annotation bean integration_ [source,java] ---- public class Foo { @@ -301,6 +340,7 @@ is defined as a constant in: `JsonpathConstants.HEADER_JSON_ENCODING`. You can use JSONPath to split a JSON document, such as: +._Java-only: Java DSL with class literal parameter_ [source,java] ---- from("direct:start") @@ -317,6 +357,7 @@ Then each book is logged, however the message body is a `Map` instance. Sometime you may want to output this as plain String JSON value instead, which can be done with the `writeAsString` option as shown: +._Java-only: Java DSL with class literal parameter_ [source,java] ---- from("direct:start") @@ -330,6 +371,7 @@ Then each book is logged as a String JSON value. It is possible to unpack a single-element array into an object: +._Java-only: Java DSL with class literal parameter_ [source,java] ---- from("direct:start") @@ -347,6 +389,7 @@ by specifying the `source` option. For example, to count the number of books from a JSON document that was stored in a header named `books` you can do: +._Java-only: Java fluent expression builder API_ [source,java] ---- var jp = expression().jsonpath("$..store.book.length()").resultType(int.class) @@ -359,6 +402,7 @@ from("direct:start") And you can also inline the expression: +._Java-only: Java fluent expression builder API_ [source,java] ---- from("direct:start") diff --git a/components/camel-netty/src/main/docs/netty-component.adoc b/components/camel-netty/src/main/docs/netty-component.adoc index dfba17778a667..83013f320856c 100644 --- a/components/camel-netty/src/main/docs/netty-component.adoc +++ b/components/camel-netty/src/main/docs/netty-component.adoc @@ -178,6 +178,7 @@ Read further about using < Date: Thu, 18 Jun 2026 09:53:27 +0200 Subject: [PATCH 76/87] CAMEL-23789: Make SOAP, JacksonXML, Jackson3XML, and CXF-RS docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/cxfrs-component.adoc | 89 +++++++++++++++++-- .../src/main/docs/jacksonXml3-dataformat.adoc | 51 +++++++++-- .../src/main/docs/jacksonXml2-dataformat.adoc | 51 +++++++++-- .../src/main/docs/soap-dataformat.adoc | 6 ++ 4 files changed, 182 insertions(+), 15 deletions(-) diff --git a/components/camel-cxf/camel-cxf-rest/src/main/docs/cxfrs-component.adoc b/components/camel-cxf/camel-cxf-rest/src/main/docs/cxfrs-component.adoc index e5c97f6400b80..de84604988d3b 100644 --- a/components/camel-cxf/camel-cxf-rest/src/main/docs/cxfrs-component.adoc +++ b/components/camel-cxf/camel-cxf-rest/src/main/docs/cxfrs-component.adoc @@ -88,6 +88,7 @@ You can find a Camel REST service route configuration example there. The `camel-cxfrs` producer supports overriding the service address by setting the message with the key of `CamelDestinationOverrideUrl`. +._Java-only: inline exchange header manipulation_ [source,java] ---------------------------------------------------------------------------------------------- // set up the service address from the message header to override the setting of CXF endpoint @@ -137,11 +138,38 @@ respected, and it becomes the final response. This binding style can be activated by setting the `bindingStyle` parameter in the consumer endpoint to value `SimpleConsumer`: +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------------------- - from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer") +---- +from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer") .to("log:TEST?showAll=true"); ---------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: "cxfrs:bean:rsServer?bindingStyle=SimpleConsumer" + steps: + - to: + uri: "log:TEST?showAll=true" +---- +==== === Examples of request binding with different method signatures @@ -166,6 +194,7 @@ is preserved as the _IN_ message body. Given a JAX-RS resource class with this method: +._Java-only: Java JAX-RS annotation_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------------ @POST @Path("/customers/{type}") @@ -176,14 +205,53 @@ public Response newCustomer(Customer customer, @PathParam("type") String type, @ Serviced by the following route: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------------------- +---- from("cxfrs:bean:rsServer?bindingStyle=SimpleConsumer") .recipientList(simple("direct:${header.CamelCxfOperationName}")); from("direct:newCustomer") .log("Request: type=${header.type}, active=${header.active}, customerData=${body}"); --------------------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + direct:${header.CamelCxfOperationName} + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: "cxfrs:bean:rsServer?bindingStyle=SimpleConsumer" + steps: + - recipientList: + simple: "direct:${header.CamelCxfOperationName}" +- route: + from: + uri: direct:newCustomer + steps: + - log: + message: "Request: type=${header.type}, active=${header.active}, customerData=${body}" +---- +==== The following HTTP request with XML payload (given that the Customer DTO is JAXB-annotated): @@ -225,6 +293,8 @@ JSR-311 specification. All you need to do in Camel is delegate this method request to the right processor or endpoint. Here is an example of a CXFRS route... + +._Java-only: Java RouteBuilder with constants and Processors_ [source,java] ---- private static final String CXF_RS_ENDPOINT_URI = @@ -281,6 +351,7 @@ set on the Camel exchange, and the route execution will continue as usual. This can be useful for integrating the existing JAX-RS implementations into Camel routes and for post-processing JAX-RS Responses in custom processors. +._Java-only: Java JAX-RS interface definition_ [source,java] ---- @Path("/customerservice/") @@ -319,6 +390,8 @@ prepare the parameter in the message body, the camel-cxfrs producer will generate the right REST request for you. Here is an example: + +._Java-only: Java test API (ProducerTemplate with inline Processor)_ [source,java] ---- Exchange exchange = template.send("direct://proxy", new Processor() { @@ -362,6 +435,8 @@ https://www.javadoc.io/doc/org.apache.camel/camel-cxf-transport/current/org/apac You can turn the response object to the type class specified with the message header https://www.javadoc.io/doc/org.apache.camel/camel-cxf-transport/current/org/apache/camel/component/cxf/common/message/CxfConstants.html#CAMEL_CXF_RS_RESPONSE_CLASS[CxfConstants.CAMEL_CXF_RS_RESPONSE_CLASS]. + +._Java-only: Java test API (ProducerTemplate with inline Processor)_ [source,java] ---- Exchange exchange = template.send("direct://http", new Processor() { @@ -385,6 +460,8 @@ Exchange exchange = template.send("direct://http", new Processor() { ---- We also support to specify the query parameters from cxfrs URI for the CXFRS http centric client. + +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- Exchange exchange = template.send("cxfrs://http://localhost:9003/testQuery?httpClientAPI=true&q1=12&q2=13" @@ -392,6 +469,8 @@ Exchange exchange = template.send("cxfrs://http://localhost:9003/testQuery?httpC To support the Dynamical routing, you can override the URI's query parameters by using the https://www.javadoc.io/doc/org.apache.camel/camel-cxf-transport/current/org/apache/camel/component/cxf/common/message/CxfConstants.html#CAMEL_CXF_RS_QUERY_MAP[CxfConstants.CAMEL_CXF_RS_QUERY_MAP] header to set the parameter map for it. + +._Java-only: Java collection API_ [source,java] ---- Map queryMap = new LinkedHashMap<>(); diff --git a/components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc b/components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc index f257a2cfcee82..69144c7f6b959 100644 --- a/components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc +++ b/components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc @@ -32,12 +32,44 @@ This data format relies on https://github.com/FasterXML/Woodstox[Woodstox] (especially for features like pretty printing), a fast and efficient XML processor. +[tabs] +==== +Java:: ++ [source,java] -------------------------------- -from("activemq:My.Queue"). - unmarshal().jacksonXml(). - to("mqseries:Another.Queue"); -------------------------------- +---- +from("activemq:My.Queue") + .unmarshal().jacksonXml() + .to("mqseries:Another.Queue"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: activemq:My.Queue + steps: + - unmarshal: + jacksonXml: {} + - to: + uri: mqseries:Another.Queue +---- +==== == JacksonXML Options @@ -98,6 +130,7 @@ Note that the weight field is missing in the resulting XML: As an example of using this attribute, you can instead of: +._Java-only: Java programmatic data format with class literal_ [source,java] --------------------------------------------------------------------------------------------------- JacksonXMLDataFormat ageViewFormat = new JacksonXMLDataFormat(TestPojoView.class, Views.Age.class); @@ -109,6 +142,7 @@ from("direct:inPojoAgeView") Directly specify your https://github.com/FasterXML/jackson-annotations/blob/master/src/main/java/tools/jackson/annotation/JsonView.java[JSON view] inside the Java DSL as: +._Java-only: Java DSL with class literal parameters_ [source,java] ------------------------------------------------------------ from("direct:inPojoAgeView") @@ -133,6 +167,7 @@ If you want to marshal a POJO to XML, and the POJO has some fields with null values. And you want to skip these null values, then you need to set either an annotation on the POJO: +._Java-only: Java annotation_ [source,java] ------------------------------ @JsonInclude(Include.NON_NULL) @@ -145,6 +180,7 @@ But this requires you to include that annotation in your POJO source code. You can also configure the Camel JacksonXMLDataFormat to set the `include` option, as shown below: +._Java-only: Java programmatic data format configuration_ [source,java] --------------------------------------------------------- JacksonXMLDataFormat format = new JacksonXMLDataFormat(); @@ -172,6 +208,7 @@ For JMS end users, there is the `JMSType` header from the JMS spec that indicates that also. To enable support for `JMSType` you would need to turn that on, on the Jackson data format as shown: +._Java-only: Java programmatic data format configuration_ [source,java] --------------------------------------------------- JacksonDataFormat format = new JacksonDataFormat(); @@ -194,6 +231,7 @@ now specify this by setting `useList="true"` or use the `org.apache.camel.component.jackson3xml.ListJacksonXMLDataFormat`. For example, with Java, you can do as shown below: +._Java-only: Java programmatic data format configuration_ [source,java] ------------------------------------------------------------- JacksonXMLDataFormat format = new ListJacksonXMLDataFormat(); @@ -282,6 +320,7 @@ To enable a feature, use the enableFeatures options instead. From Java code, you can use the type safe methods from camel-jackson module: +._Java-only: Java programmatic data format configuration_ [source,java] ---------------------------------------------------------------------- JacksonDataFormat df = new JacksonDataFormat(MyPojo.class); @@ -296,6 +335,7 @@ Jackson component comes with the data converter that can be used to convert `java.util.Map` instance to non-String, non-primitive and non-Number objects. +._Java-only: Java collection API (ProducerTemplate)_ [source,java] ---------------------------------------------------------------- Map invoiceData = new HashMap(); @@ -324,6 +364,7 @@ marshalling: And in Java DSL: +._Java-only: Java DSL shorthand_ [source,java] --------------------------------------------------- from("direct:inPretty").marshal().jacksonXml(true); diff --git a/components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc b/components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc index 78cdee962deb0..0c28b7145391b 100644 --- a/components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc +++ b/components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc @@ -32,12 +32,44 @@ This data format relies on https://github.com/FasterXML/Woodstox[Woodstox] (especially for features like pretty printing), a fast and efficient XML processor. +[tabs] +==== +Java:: ++ [source,java] -------------------------------- -from("activemq:My.Queue"). - unmarshal().jacksonXml(). - to("mqseries:Another.Queue"); -------------------------------- +---- +from("activemq:My.Queue") + .unmarshal().jacksonXml() + .to("mqseries:Another.Queue"); +---- + +XML:: ++ +[source,xml] +---- + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: activemq:My.Queue + steps: + - unmarshal: + jacksonXml: {} + - to: + uri: mqseries:Another.Queue +---- +==== == JacksonXML Options @@ -98,6 +130,7 @@ Note that the weight field is missing in the resulting XML: As an example of using this attribute, you can instead of: +._Java-only: Java programmatic data format with class literal_ [source,java] --------------------------------------------------------------------------------------------------- JacksonXMLDataFormat ageViewFormat = new JacksonXMLDataFormat(TestPojoView.class, Views.Age.class); @@ -109,6 +142,7 @@ from("direct:inPojoAgeView") Directly specify your https://github.com/FasterXML/jackson-annotations/blob/master/src/main/java/com/fasterxml/jackson/annotation/JsonView.java[JSON view] inside the Java DSL as: +._Java-only: Java DSL with class literal parameters_ [source,java] ------------------------------------------------------------ from("direct:inPojoAgeView") @@ -133,6 +167,7 @@ If you want to marshal a POJO to XML, and the POJO has some fields with null values. And you want to skip these null values, then you need to set either an annotation on the POJO: +._Java-only: Java annotation_ [source,java] ------------------------------ @JsonInclude(Include.NON_NULL) @@ -145,6 +180,7 @@ But this requires you to include that annotation in your POJO source code. You can also configure the Camel JacksonXMLDataFormat to set the `include` option, as shown below: +._Java-only: Java programmatic data format configuration_ [source,java] --------------------------------------------------------- JacksonXMLDataFormat format = new JacksonXMLDataFormat(); @@ -172,6 +208,7 @@ For JMS end users, there is the `JMSType` header from the JMS spec that indicates that also. To enable support for `JMSType` you would need to turn that on, on the Jackson data format as shown: +._Java-only: Java programmatic data format configuration_ [source,java] --------------------------------------------------- JacksonDataFormat format = new JacksonDataFormat(); @@ -194,6 +231,7 @@ now specify this by setting `useList="true"` or use the `org.apache.camel.component.jacksonxml.ListJacksonXMLDataFormat`. For example, with Java, you can do as shown below: +._Java-only: Java programmatic data format configuration_ [source,java] ------------------------------------------------------------- JacksonXMLDataFormat format = new ListJacksonXMLDataFormat(); @@ -282,6 +320,7 @@ To enable a feature, use the enableFeatures options instead. From Java code, you can use the type safe methods from camel-jackson module: +._Java-only: Java programmatic data format configuration_ [source,java] ---------------------------------------------------------------------- JacksonDataFormat df = new JacksonDataFormat(MyPojo.class); @@ -296,6 +335,7 @@ Jackson component comes with the data converter that can be used to convert `java.util.Map` instance to non-String, non-primitive and non-Number objects. +._Java-only: Java collection API (ProducerTemplate)_ [source,java] ---------------------------------------------------------------- Map invoiceData = new HashMap(); @@ -324,6 +364,7 @@ marshalling: And in Java DSL: +._Java-only: Java DSL shorthand_ [source,java] --------------------------------------------------- from("direct:inPretty").marshal().jacksonXml(true); diff --git a/components/camel-soap/src/main/docs/soap-dataformat.adoc b/components/camel-soap/src/main/docs/soap-dataformat.adoc index cc893ca5c6058..9ed5646704cc9 100644 --- a/components/camel-soap/src/main/docs/soap-dataformat.adoc +++ b/components/camel-soap/src/main/docs/soap-dataformat.adoc @@ -73,6 +73,7 @@ case it would be a one way SOAP request. If you need to request a reply, then you should look at the next example. ==== +._Java-only: Java programmatic data format instantiation_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------- SoapDataFormat soap = new SoapDataFormat("com.example.customerservice", new ServiceInterfaceStrategy(CustomerService.class)); @@ -94,6 +95,7 @@ most settings apply here as well *Since Camel 2.11* +._Java-only: Java programmatic data format configuration_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------- SoapDataFormat soap = new SoapDataFormat("com.example.customerservice", new ServiceInterfaceStrategy(CustomerService.class)); @@ -146,6 +148,7 @@ The `ServiceInterfaceStrategy` should be initialized with a boolean parameter that indicates whether the mapping strategy applies to the request parameters or response parameters. +._Java-only: Java class instantiation_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------- ServiceInterfaceStrategy strat = new ServiceInterfaceStrategy(com.example.customerservice.multipart.MultiPartCustomerService.class, true); @@ -168,6 +171,7 @@ unmarshalled response. The following route supports marshalling the request and unmarshalling a response or fault. +._Java-only: Java programmatic data format with exception handling_ [source,java] --------------------------------------------------------------------------------------------------------------------------------------- String WS_URI = "cxf://http://myserver/customerservice?serviceClass=com.example.customerservice&dataFormat=RAW"; @@ -185,6 +189,7 @@ from("direct:customerServiceClient") The below snippet creates a proxy for the service interface and makes a SOAP call to the above route. +._Java-only: Java proxy API_ [source,java] --------------------------------------------------------------------------------------------------- import org.apache.camel.Endpoint; @@ -206,6 +211,7 @@ jms queue `customerServiceQueue` and processes requests using the class the interface `CustomerService`. Instead of directly instantiating the server class it could be defined in a spring context as a regular bean. +._Java-only: Java programmatic data format with bean processing_ [source,java] --------------------------------------------------------------------------------------------------------------------------------------- SoapDataFormat soapDF = new SoapDataFormat("com.example.customerservice", new ServiceInterfaceStrategy(CustomerService.class)); From eb65ec3242f7bea834e1556c0ca8a072c913a309 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 10:01:29 +0200 Subject: [PATCH 77/87] CAMEL-23789: Make Shiro security docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- components/camel-shiro/src/main/docs/shiro.adoc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/camel-shiro/src/main/docs/shiro.adoc b/components/camel-shiro/src/main/docs/shiro.adoc index 603447f5713f2..414684c02b996 100644 --- a/components/camel-shiro/src/main/docs/shiro.adoc +++ b/components/camel-shiro/src/main/docs/shiro.adoc @@ -90,6 +90,7 @@ sec-level1 = zone1:readonly:* A ShiroSecurityPolicy object is instantiated as follows +._Java-only: Java class instantiation and configuration_ [source,java] ---------------------------------------------------------------------------------------- private final String iniResourcePath = "classpath:shiro.ini"; @@ -164,6 +165,7 @@ further following proper authentication. The SecurityToken object contains a Username/Password details that are used to determine where the user is a valid user. +._Java-only: Java RouteBuilder with security policy_ [source,java] ----------------------------------------------------------------------- protected RouteBuilder createRouteBuilder() throws Exception { @@ -199,6 +201,7 @@ specifies the permissions necessary for the user to proceed with the execution of the route segment. If the user does not have the proper permission set, the request is not authorized to continue any further. +._Java-only: Java RouteBuilder with security policy_ [source,java] ------------------------------------------------------------------------------------------- protected RouteBuilder createRouteBuilder() throws Exception { @@ -233,6 +236,7 @@ Exchange using a Shiro Processor called ShiroSecurityTokenInjector. An example of injecting a ShiroSecurityToken using a ShiroSecurityTokenInjector in the client is shown below +._Java-only: Java security token injection_ [source,java] ------------------------------------------------------------------------------------- ShiroSecurityToken shiroSecurityToken = new ShiroSecurityToken("ringo", "starr"); @@ -256,6 +260,7 @@ bit security by default and can be changed to any cipher of your choice. Given below is an example of how a request may be sent using a ProducerTemplate in Camel along with a SecurityToken +._Java-only: Java test method (ProducerTemplate)_ [source,java] ------------------------------------------------------------------------------------------------- @@ -286,6 +291,7 @@ You can send a message to a Camel route with a header of key `org.apache.camel.component.shiro.security.ShiroSecurityToken` that contains the username and password. For example: +._Java-only: Java test API (ProducerTemplate)_ [source,java] --------------------------------------------------------------------------------------------------------------------------------------------- ShiroSecurityToken shiroSecurityToken = new ShiroSecurityToken("ringo", "starr"); @@ -296,6 +302,7 @@ contains the username and password. For example: You can also provide the username and password in two different headers as shown below: +._Java-only: Java test API (ProducerTemplate)_ [source,java] -------------------------------------------------------------------------------------- Map headers = new HashMap(); From 44d1baacf62bbe98f0fda401be9774bf4bba893e Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 10:08:58 +0200 Subject: [PATCH 78/87] CAMEL-23789: Make Barcode, Disruptor, JAXB, Mina, TarFile, and ZipFile docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../camel-barcode/src/main/docs/barcode-dataformat.adoc | 5 +++++ .../camel-disruptor/src/main/docs/disruptor-component.adoc | 7 ++++++- components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc | 6 ++++++ components/camel-mina/src/main/docs/mina-component.adoc | 7 ++++++- .../camel-tarfile/src/main/docs/tarFile-dataformat.adoc | 7 ++++++- .../camel-zipfile/src/main/docs/zipFile-dataformat.adoc | 7 ++++++- 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/components/camel-barcode/src/main/docs/barcode-dataformat.adoc b/components/camel-barcode/src/main/docs/barcode-dataformat.adoc index c9e7464a2765f..bacbd5a0d8d54 100644 --- a/components/camel-barcode/src/main/docs/barcode-dataformat.adoc +++ b/components/camel-barcode/src/main/docs/barcode-dataformat.adoc @@ -61,6 +61,7 @@ The default values are: |barcode format (BarcodeFormat) |QR-Code |======================================================================= +._Java-only: Java programmatic data format instantiation_ [source,java] ------------------------------------------ // QR-Code default @@ -70,6 +71,7 @@ DataFormat code = new BarcodeDataFormat(); If you want to use zxing hints, you can use the 'addToHintMap' method of your BarcodeDataFormat instance: +._Java-only: Java data format configuration API_ [source,java] ----------------------------------------------------------- code.addToHintMap(DecodeHintType.TRY_HARDER, Boolean.true); @@ -79,6 +81,7 @@ For possible hints, please consult the xzing documentation. === Marshalling +._Java-only: route using Java data format variable_ [source,java] ---------------------------- from("direct://code") @@ -88,6 +91,7 @@ from("direct://code") You can call the route from a test class with: +._Java-only: Java test API (ProducerTemplate)_ [source,java] ------------------------------------------------------------- template.sendBody("direct://code", "This is a testmessage!"); @@ -103,6 +107,7 @@ The unmarshaller is generic. For unmarshalling, you can use any BarcodeDataFormat instance. If you've two instances, one for (generating) QR-Code and one for PDF417, it doesn't matter which one will be used. +._Java-only: route using Java data format variable_ [source,java] -------------------------------------------------------------------- from("file://barcode_in?noop=true") diff --git a/components/camel-disruptor/src/main/docs/disruptor-component.adoc b/components/camel-disruptor/src/main/docs/disruptor-component.adoc index 4ba6319181677..2e12a1ee25c59 100644 --- a/components/camel-disruptor/src/main/docs/disruptor-component.adoc +++ b/components/camel-disruptor/src/main/docs/disruptor-component.adoc @@ -179,7 +179,7 @@ By default, the Disruptor endpoint uses a single consumer thread, but you can configure it to use concurrent consumer threads. So instead of thread pools, you can use: -.Concurrent consumers example +._Java-only: concurrent consumers example (incomplete route)_ [source,java] -------------------------------------------------------------- from("disruptor:stageName?concurrentConsumers=5").process(...) @@ -195,6 +195,7 @@ Disruptor internally, so performance will be higher. Be aware that adding a thread pool to a Disruptor endpoint by doing something like: +._Java-only: incomplete route (thread pool example)_ [source,java] -------------------------------------------------- from("disruptor:stageName").thread(5).process(...) @@ -217,6 +218,7 @@ As such, it is able to send a _fire-and-forget_ message for further processing in another thread, and return a constant reply in this thread to the original caller. +._Java-only: Java RouteBuilder with multiple routes_ [source,java] ------------------------------------------------- public void configure() { @@ -232,6 +234,7 @@ public void configure() { Here we send a _Hello World_ message and expect the reply to be _OK_. +._Java-only: Java test API (ProducerTemplate)_ [source,java] ----------------------------------------------------------------- Object out = template.requestBody("direct:start", "Hello World"); @@ -267,6 +270,7 @@ of the message as a kind of _publish/subscriber_ style messaging. As the beans are part of a unit test, they simply send the message to a mock endpoint, but notice how we can use _@Consume_ to consume from the Disruptor. +._Java-only: Java annotation-based consumer class_ [source,java] ------------------------------------------- public class FooEventConsumer { @@ -287,6 +291,7 @@ public class FooEventConsumer { If needed, information such as buffer size, etc. can be obtained without using JMX in this fashion: +._Java-only: Java endpoint API_ [source,java] -------------------------------------------------------------------- DisruptorEndpoint disruptor = context.getEndpoint("disruptor:xxxx"); diff --git a/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc b/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc index aed39ed82b6c7..d9ba0fe8bc4a1 100644 --- a/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc +++ b/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc @@ -28,6 +28,7 @@ The following example uses a named DataFormat of `jaxb` which is configured with a Java package name to initialize the https://jakarta.ee/specifications/xml-binding/2.3/apidocs/javax/xml/bind/jaxbcontext[JAXBContext]. +._Java-only: Java programmatic data format instantiation_ [source,java] ------------------------------------------------------- DataFormat jaxb = new JaxbDataFormat("com.acme.model"); @@ -41,6 +42,7 @@ You can, if you prefer, use a named reference to a data format which can then be defined in your Registry such as via your Spring XML file. e.g. +._Java-only: Java DSL with named data format reference_ [source,java] ------------------------------- from("activemq:My.Queue"). @@ -109,6 +111,7 @@ on the `JaxbDataFormat`. While setting `partNamespace` through `JaxbConstants.JAXB_PART_NAMESPACE`, please note that you need to specify its value in the format `\{namespaceUri\}localPart`, as per the example below. +._Java-only: Java constant reference_ [source,java] -------------------------------------------------------------------------------------- .setHeader(JaxbConstants.JAXB_PART_NAMESPACE, constant("{http://www.camel.apache.org/jaxb/example/address/1}address")); @@ -145,6 +148,7 @@ marshal the stream to XML. Using this configuration, you can add your own stream writer to completely remove, escape, or replace non-XML characters. +._Java-only: Java programmatic data format configuration_ [source,java] -------------------------------------------------------------------------------------- JaxbDataFormat customWriterFormat = new JaxbDataFormat("org.apache.camel.foo.bar"); @@ -226,6 +230,7 @@ then you need to enable file protocol (or others to allow access) Using the Java DSL, you can configure it in the following way: +._Java-only: Java programmatic data format configuration_ [source,java] ----------------------------------------------------------------------- JaxbDataFormat jaxbDataFormat = new JaxbDataFormat(); @@ -250,6 +255,7 @@ The `JaxbDataFormat` supports to specify the `SchemaLocation` when marshalling t Using the Java DSL, you can configure it in the following way: +._Java-only: Java programmatic data format configuration_ [source,java] ------------------------------------------------------------------- JaxbDataFormat jaxbDataFormat = new JaxbDataFormat(); diff --git a/components/camel-mina/src/main/docs/mina-component.adoc b/components/camel-mina/src/main/docs/mina-component.adoc index 419fcf82b5c65..9fad0d73efee5 100644 --- a/components/camel-mina/src/main/docs/mina-component.adoc +++ b/components/camel-mina/src/main/docs/mina-component.adoc @@ -106,7 +106,7 @@ is, after `codec` and `logger`. In this sample, Camel exposes a service that listens for TCP connections on port 6200. We use the *textline* codec. In our route, we create a Mina consumer endpoint that listens to on port 6200: - +._Java-only: Java string concatenation with port variable_ [source,java] --------------------------------------------------------------------------------------- from("mina:tcp://localhost:" + port1 + "?textline=true&sync=false").to("mock:result"); @@ -115,6 +115,7 @@ from("mina:tcp://localhost:" + port1 + "?textline=true&sync=false").to("mock:res As the sample is part of a unit test, we test it by sending some data to it on port 6200. +._Java-only: Java test API (MockEndpoint and ProducerTemplate)_ [source,java] ------------------------------------------------------------------------------------------------- MockEndpoint mock = getMockEndpoint("mock:result"); @@ -132,6 +133,7 @@ service on port 6201 also use the `textline` codec. However, this time we want to return a response, so we set the `sync` option to `true` on the consumer. +._Java-only: inline Processor class_ [source,java] --------------------------------------------------------------------------------------------- fromF("mina:tcp://localhost:%d?textline=true&sync=true", port2).process(new Processor() { @@ -147,6 +149,7 @@ using the `template.requestBody()` method. As we know the response is a `String`, we cast it to `String` and can assert that the response is, in fact, something we have dynamically set in our processor code logic. +._Java-only: Java test API (ProducerTemplate)_ [source,java] ----------------------------------------------------------------------------------------------------------------------- String response = (String)template.requestBody("mina:tcp://localhost:" + port2 + "?textline=true&sync=true", "World"); @@ -171,6 +174,7 @@ textline codec. We let the Spring bean with ID, `myTCPOrderHandler`, handle the request and return a reply. For instance, the handler bean could be implemented as follows: +._Java-only: Java handler class_ [source,java] ----------------------------------------------- public String handleOrder(String payload) { @@ -189,6 +193,7 @@ the session, you should add a header with the key For instance, the example below will close the session after it has written the `bye` message back to the client: +._Java-only: inline Processor class_ [source,java] --------------------------------------------------------------------------------------------------- from("mina:tcp://localhost:8080?sync=true&textline=true").process(new Processor() { diff --git a/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc b/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc index bc5d20e494c5a..27e2ba63d8fd9 100644 --- a/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc +++ b/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc @@ -185,6 +185,7 @@ In this example we unmarshal a Tar File payload from an ActiveMQ queue called MY_QUEUE to its original format, and forward it for processing to the `UnTarpedMessageProcessor`. +._Java-only: inline Processor class_ [source,java] ----------------------------------------------------------------------------------------------- from("activemq:queue:MY_QUEUE").unmarshal().tarFile().process(new UnTarpedMessageProcessor()); @@ -194,6 +195,7 @@ If the Tar File has more than one entry, the usingIterator option of TarFileDataFormat to be true, and you can use splitter to do the further work. +._Java-only: Java programmatic data format configuration_ [source,java] ---------------------------------------------------------------------------------------------------- TarFileDataFormat tarFile = new TarFileDataFormat(); @@ -209,6 +211,7 @@ work. Or you can use the TarSplitter as an expression for splitter directly like this +._Java-only: Java TarSplitter class_ [source,java] ---------------------------------------------------------------------------------------------------- from("file:src/test/resources/org/apache/camel/dataformat/tarfile?delay=1000&noop=true") @@ -230,8 +233,9 @@ check to work properly. ==== In this example, we aggregate all text files found in the input directory -into a single Tar File that is stored in the output directory. +into a single Tar File that is stored in the output directory. +._Java-only: Java TarAggregationStrategy class_ [source,java] ------------------------------------------------- from("file:input/directory?antInclude=*/.txt") @@ -247,6 +251,7 @@ java.io.File.createTempFile, with the ".tar" suffix. If you want to override this behavior, then you can set the value of the `CamelFileName` header explicitly in your route: +._Java-only: Java TarAggregationStrategy class_ [source,java] ------------------------------------------------------------ from("file:input/directory?antInclude=*/.txt") diff --git a/components/camel-zipfile/src/main/docs/zipFile-dataformat.adoc b/components/camel-zipfile/src/main/docs/zipFile-dataformat.adoc index d2976ee7db03b..eb5be75523047 100644 --- a/components/camel-zipfile/src/main/docs/zipFile-dataformat.adoc +++ b/components/camel-zipfile/src/main/docs/zipFile-dataformat.adoc @@ -180,6 +180,7 @@ In this example we unmarshal a Zip file payload from an ActiveMQ queue called MY_QUEUE to its original format, and forward it for processing to the `UnZippedMessageProcessor`. +._Java-only: inline Processor class_ [source,java] ---- from("activemq:queue:MY_QUEUE") @@ -191,6 +192,7 @@ If the zip file has more than one entry, the usingIterator option of ZipFileDataFormat to be true, and you can use splitter to do the further work. +._Java-only: Java programmatic data format configuration_ [source,java] ---- ZipFileDataFormat zipFile = new ZipFileDataFormat(); @@ -205,6 +207,7 @@ from("file:src/test/resources/org/apache/camel/dataformat/zipfile/?delay=1000&no Or you can use the ZipSplitter as an expression for splitter directly like this: +._Java-only: Java ZipSplitter class_ [source,java] ---- from("file:src/test/resources/org/apache/camel/dataformat/zipfile?delay=1000&noop=true") @@ -226,8 +229,9 @@ Please note that this aggregation strategy requires eager completion check to wo ==== In this example, we aggregate all text files found in the input directory -into a single Zip file that is stored in the output directory. +into a single Zip file that is stored in the output directory. +._Java-only: Java ZipAggregationStrategy class_ [source,java] ---- from("file:input/directory?antInclude=*/.txt") @@ -241,6 +245,7 @@ java.io.File.createTempFile, with the ".zip" suffix. If you want to override this behavior, then you can set the value of the `CamelFileName` header explicitly in your route: +._Java-only: Java ZipAggregationStrategy class_ [source,java] ---- from("file:input/directory?antInclude=*/.txt") From f2e958c008fcc4b9b7461d4f379dd8366b9de3f8 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 10:16:18 +0200 Subject: [PATCH 79/87] CAMEL-23789: Make Spring AI, Spring RabbitMQ, LDAP, StAX, Stitch, QuickFIX, HL7 Terser, IRC, JCache, and JGroups docs multi-DSL friendly (Wave 1) Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/hl7terser-language.adoc | 5 + .../src/main/docs/irc-component.adoc | 5 + .../src/main/docs/jcache-component.adoc | 5 + .../src/main/docs/jgroups-component.adoc | 5 + .../src/main/docs/ldap-component.adoc | 2 + .../src/main/docs/quickfix-component.adoc | 5 + .../main/docs/spring-ai-image-component.adoc | 73 ++++++++++++ .../main/docs/spring-ai-tools-component.adoc | 9 ++ .../spring-ai-vector-store-component.adoc | 108 ++++++++++++++++++ .../main/docs/spring-rabbitmq-component.adoc | 30 ++++- .../src/main/docs/stax-component.adoc | 5 + .../src/main/docs/stitch-component.adoc | 5 + 12 files changed, 256 insertions(+), 1 deletion(-) diff --git a/components/camel-hl7/src/main/docs/hl7terser-language.adoc b/components/camel-hl7/src/main/docs/hl7terser-language.adoc index 32c96b0a35fc5..53a7dafaba160 100644 --- a/components/camel-hl7/src/main/docs/hl7terser-language.adoc +++ b/components/camel-hl7/src/main/docs/hl7terser-language.adoc @@ -31,6 +31,7 @@ include::partial$language-options.adoc[] In the example below, we want to set a header with the patent id from field QRD-8 in the QRY_A19 message: +._Java-only: HL7 Terser expression builder API for extracting and filtering fields_ [source,java] ---- import static org.apache.camel.component.hl7.HL7.hl7terser; @@ -55,6 +56,7 @@ https://hapifhir.github.io/hapi-hl7v2/base/apidocs/ca/uhn/hl7v2/validation/Valid The example below shows how to do that. Notice how we use the static method `messageConformsTo` which validates that the message is a HL7v2 message. +._Java-only: HL7 message validation with HAPI ValidationContext_ [source,java] ---- import static org.apache.camel.component.hl7.HL7.messageConformsTo; @@ -80,6 +82,7 @@ so you can access the validation rules indirectly. Furthermore, when unmarshalling the HL7 data format forwards the configured HAPI context in the `CamelHL7Context` header, and the validation rules of this context can be reused: +._Java-only: HapiContext configuration with custom ValidationRuleBuilder_ [source,java] ---- import static org.apache.camel.component.hl7.HL7.messageConformsTo; @@ -116,6 +119,7 @@ message as a response to an incoming HL7v2 message, e.g., based on a validation result. The `ack` expression lets us accomplish this very elegantly: +._Java-only: HL7 acknowledgement expression builder API_ [source,java] ---- import static org.apache.camel.component.hl7.HL7.messageConformsTo; @@ -142,6 +146,7 @@ from("direct:test1") In special situations, you may want to set a custom acknowledgement without using Exceptions. This can be achieved using the `ack` expression: +._Java-only: Custom MLLP acknowledgement using HAPI AcknowledgmentCode API_ [source,java] ---- import org.apache.camel.component.mllp.MllpConstants; diff --git a/components/camel-irc/src/main/docs/irc-component.adoc b/components/camel-irc/src/main/docs/irc-component.adoc index bf0a61b5cc76f..5c39da2c7572e 100644 --- a/components/camel-irc/src/main/docs/irc-component.adoc +++ b/components/camel-irc/src/main/docs/irc-component.adoc @@ -56,6 +56,7 @@ to use the utility with the IRC component. [[IRC-Programmaticconfigurationoftheendpoint]] Programmatic configuration of the endpoint +._Java-only: Java programmatic SSL configuration_ [source,java] ----------------------------------------------------------------------------------------------------------------------------------------- KeyStoreParameters ksp = new KeyStoreParameters(); @@ -99,6 +100,7 @@ Spring DSL based configuration of endpoint You can also connect to an SSL enabled IRC server, as follows: +._Java-only: endpoint URI syntax_ [source,java] -------------------------------------------------- ircs:host[:port]/#room?username=user&password=pass @@ -109,6 +111,7 @@ http://moepii.sourceforge.net/irclib/javadoc/org/schwering/irc/lib/ssl/SSLDefaul If you need to provide your own custom trust manager, use the `trustManager` parameter as follows: +._Java-only: endpoint URI syntax with trustManager_ [source,java] ---------------------------------------------------------------------------------------------- ircs:host[:port]/#room?username=user&password=pass&trustManager=#referenceToMyTrustManagerBean @@ -123,6 +126,7 @@ channel. The key is just a secret word. For example, we join three channels whereas only channel 1 and 3 use a key. +._Java-only: endpoint URI syntax with channel keys_ [source,java] ----------------------------------------------------------------------------- irc:nick@irc.server.org?channels=#chan1,#chan2,#chan3&keys=chan1Key,,chan3key @@ -136,6 +140,7 @@ Furthermore, one has to filter the `onReply` exchanges to get the names. For example, we want to get all exchanges that contain the usernames of the channel: +._Java-only: Java DSL with choice and filter EIPs_ [source,java] ----------------------------------------------------------------------------- from("ircs:nick@myserver:1234/#mychannelname?namesOnJoin=true&onReply=true") diff --git a/components/camel-jcache/src/main/docs/jcache-component.adoc b/components/camel-jcache/src/main/docs/jcache-component.adoc index 039e16ec7b524..fbba3462b6ebe 100644 --- a/components/camel-jcache/src/main/docs/jcache-component.adoc +++ b/components/camel-jcache/src/main/docs/jcache-component.adoc @@ -74,6 +74,7 @@ The cache used by the policy can be set directly. This means you have to configu but this gives the most flexibility. For example, it can be setup in the config xml of the cache provider (Hazelcast, EhCache, ...) and used here. Or it's possible to use the standard Caching API as below: +._Java-only: Java programmatic cache configuration with JCachePolicy_ [source,java] ---------------------------- MutableConfiguration configuration = new MutableConfiguration<>(); @@ -97,6 +98,7 @@ If the `cache` is not set, the policy will try to look up or create the cache au If the `cacheManager` is set on the policy, it will try to get cache with the set `cacheName` (routeId by default) from the CacheManager. If the cache does not exist, it will create a new one using the `cacheConfiguration` (new MutableConfiguration by default). +._Java-only: Java programmatic CacheManager configuration_ [source,java] ---------------------------- //In a Spring environment, for example, the CacheManager may already exist as a bean @@ -117,6 +119,7 @@ If `cacheManager` (and the `cache`) is not set, the policy will try to find a JC * Lookup a CacheManager in Camel registry. That falls back on JNDI or Spring context based on the environment * Use the standard api `Caching.getCachingProvider().getCacheManager()` +._Java-only: Java DSL with JCachePolicy_ [source,java] ---------------------------- //A Cache "getorders" will be used (or created) from the found CacheManager @@ -131,6 +134,7 @@ from("direct:get-orders").routeId("getorders") In the examples above, the whole route was executed or skipped. A policy can be used to wrap only a segment of the route instead of all processors. +._Java-only: Java DSL with partial JCachePolicy wrapping_ [source,java] ---------------------------- from("direct:get-orders") @@ -154,6 +158,7 @@ set `header("orderId")` (or `simple("$\{header.orderId\}")` as `keyExpression`. The expression is evaluated only once at the beginning of the route to determine the _key_. If nothing was found in cache, this _key_ is used to store the _value_ in cache at the end of the route. +._Java-only: Java programmatic JCachePolicy with keyExpression_ [source,java] ---------------------------- MutableConfiguration configuration = new MutableConfiguration<>(); diff --git a/components/camel-jgroups/src/main/docs/jgroups-component.adoc b/components/camel-jgroups/src/main/docs/jgroups-component.adoc index f619992b2b367..03a1b99a3bec9 100644 --- a/components/camel-jgroups/src/main/docs/jgroups-component.adoc +++ b/components/camel-jgroups/src/main/docs/jgroups-component.adoc @@ -136,6 +136,7 @@ master in the cluster, because messages passing this filter notifies you below demonstrates how to collect only messages received by the master node. +._Java-only: Java static import and filter EIP_ [source,java] ---------------------------------------------------------------------------------------- import static org.apache.camel.component.jgroups.JGroupsFilters.dropNonCoordinatorViews; @@ -168,6 +169,7 @@ The snippet below demonstrates how to use conditional delaying with the JGroups component to delay the initial startup of master node in the cluster. +._Java-only: Java static imports with conditional delay expression_ [source,java] ----------------------------------------------------------------------------------------------------------------------------------------------------------------- import static java.util.concurrent.TimeUnit.SECONDS; @@ -189,6 +191,7 @@ from("timer://master?repeatCount=1").routeId("masterRoute").autoStartup(false).t To send a message to the JGroups cluster, use producer endpoint, just as demonstrated in the snippet below. +._Java-only: Java test API (ProducerTemplate)_ [source,java] ------------------------------------------------ from("direct:start").to("jgroups:myCluster"); @@ -200,6 +203,7 @@ To receive the message from the snippet above (on the same, or the other physical machine), listen to the messages coming from the given cluster, just as demonstrated on the code fragment below. +._Java-only: Java test API (MockEndpoint assertions)_ [source,java] ------------------------------------------------------------ mockEndpoint.setExpectedMessageCount(1); @@ -216,6 +220,7 @@ The snippet below demonstrates how to create the consumer endpoint listening to the notifications regarding cluster membership changes. By default, the endpoint consumes only regular messages. +._Java-only: Java test API (MockEndpoint assertions)_ [source,java] --------------------------------------------------------------------- mockEndpoint.setExpectedMessageCount(1); diff --git a/components/camel-ldap/src/main/docs/ldap-component.adoc b/components/camel-ldap/src/main/docs/ldap-component.adoc index 980e55a8fe2a7..db54a2cc7a3f5 100644 --- a/components/camel-ldap/src/main/docs/ldap-component.adoc +++ b/components/camel-ldap/src/main/docs/ldap-component.adoc @@ -126,6 +126,7 @@ Following on from the configuration above, the code sample below sends an LDAP request to filter search a group for a member. The Common Name is then extracted from the response. +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---------------------------------------------------------- ProducerTemplate template = exchange.getContext().createProducerTemplate(); @@ -159,6 +160,7 @@ If the LDAP entry has a Common Name, use a filter expression like: A Camel end user donated this sample code he used to bind to the ldap server using credentials. +._Java-only: Java programmatic CamelContext and LDAP context setup_ [source,java] --------------------------------------------------------------------------------------- Properties props = new Properties(); diff --git a/components/camel-quickfix/src/main/docs/quickfix-component.adoc b/components/camel-quickfix/src/main/docs/quickfix-component.adoc index a99e0cae83dc3..6b065813f63c8 100644 --- a/components/camel-quickfix/src/main/docs/quickfix-component.adoc +++ b/components/camel-quickfix/src/main/docs/quickfix-component.adoc @@ -240,6 +240,7 @@ method returns the response to the request (an ExecutionReport in this case) which is then sent back to the requestor session. +._Java-only: route definition using Java DSL for InOut consumer exchange_ [source,java] ---- from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:MARKET->TRADER&exchangePattern=InOut") @@ -275,6 +276,7 @@ matches our request. The session ID should be for the __requestor__, the sender and target CompID fields will be reversed when looking for the reply. +._Java-only: programmatic correlation criteria setup using QuickFIX/J API_ [source,java] ---- exchange.setProperty(QuickfixjProducer.CORRELATION_CRITERIA_KEY, @@ -408,6 +410,7 @@ uses the URI scheme "trade-executor". The following route receives messages for the trade executor session and passes application messages to the trade executor component. +._Java-only: route definition using Java DSL to filter and forward FIX messages_ [source,java] ---- from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:MARKET->TRADER"). @@ -419,6 +422,7 @@ The trade executor component generates messages that are routed back to the trade session. The session ID must be set in the FIX message itself since no session ID is specified in the endpoint URI. +._Java-only: route definition using Java DSL to send messages back to FIX session_ [source,java] ---- from("trade-executor:market").to("quickfix:examples/inprocess.qf.cfg"); @@ -427,6 +431,7 @@ from("trade-executor:market").to("quickfix:examples/inprocess.qf.cfg"); The trader session consumes execution report messages from the market and processes them. +._Java-only: route definition using Java DSL to consume and process execution reports_ [source,java] ---- from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:TRADER->MARKET"). diff --git a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-image/src/main/docs/spring-ai-image-component.adoc b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-image/src/main/docs/spring-ai-image-component.adoc index f371c09e15a58..67b0c7e711b1f 100644 --- a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-image/src/main/docs/spring-ai-image-component.adoc +++ b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-image/src/main/docs/spring-ai-image-component.adoc @@ -55,6 +55,7 @@ The component requires a Spring AI `ImageModel` bean. When using Spring Boot wit Send a text prompt as the message body to generate an image: +._Java-only: Java lambda Processor with Spring AI Image API_ [source,java] ---- from("direct:generate") @@ -84,6 +85,7 @@ Headers override endpoint configuration at runtime. ==== Via Endpoint Configuration +._Java-only: Java string concatenation in URI_ [source,java] ---- from("direct:generate") @@ -96,6 +98,7 @@ from("direct:generate") ==== Via Headers +._Java-only: Java test API (ProducerTemplate with lambda)_ [source,java] ---- Exchange exchange = template.request("direct:generate", e -> { @@ -113,6 +116,10 @@ The component includes a built-in `TypeConverter` that automatically converts `I to `byte[]`. This means you can pipe generated images directly to the `file:` component without any intermediate processing: +[tabs] +==== +Java:: ++ [source,java] ---- // Generate and save — no processor needed @@ -121,6 +128,36 @@ from("direct:generate") .to("file:output?fileName=generated.png"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:generate + steps: + - to: + uri: spring-ai-image:gen + parameters: + imageModel: "#imageModel" + width: 512 + height: 512 + - to: + uri: file:output?fileName=generated.png +---- +==== + The `Image` → `byte[]` conversion decodes the base64 data automatically. === Using with Ollama (Local Image Generation) @@ -128,6 +165,7 @@ The `Image` → `byte[]` conversion decodes the base64 data automatically. Ollama supports image generation models via its OpenAI-compatible API. Configure the Spring AI OpenAI `ImageModel` to point at Ollama: +._Java-only: Java Spring AI SDK configuration_ [source,java] ---- // Ollama returns application/x-ndjson — register a converter that handles it @@ -154,6 +192,10 @@ ImageModel imageModel = new OpenAiImageModel(imageApi, defaultOptions, Then use the Camel endpoint to control resolution: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:generate") @@ -161,11 +203,42 @@ from("direct:generate") .to("file:output?fileName=camel-image.png"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:generate + steps: + - to: + uri: spring-ai-image:gen + parameters: + imageModel: "#imageModel" + width: 512 + height: 512 + - to: + uri: file:output?fileName=camel-image.png +---- +==== + === Multiple Image Generation Set the `n` parameter to generate multiple images. When `n > 1`, the body contains a `List` instead of a single `Image`: +._Java-only: Java test API (ProducerTemplate)_ [source,java] ---- from("direct:batch") diff --git a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-tools/src/main/docs/spring-ai-tools-component.adoc b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-tools/src/main/docs/spring-ai-tools-component.adoc index 2bcdc6b972a35..913a5be597809 100644 --- a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-tools/src/main/docs/spring-ai-tools-component.adoc +++ b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-tools/src/main/docs/spring-ai-tools-component.adoc @@ -48,6 +48,7 @@ IMPORTANT: This component is designed to work with the xref:spring-ai-chat-compo === Basic Tool Definition +._Java-only: Java DSL with class literal parameter_ [source,java] ---- from("spring-ai-tools:weatherTool?tags=weather&description=Get current weather for a location") @@ -62,6 +63,7 @@ The AI model can invoke this tool when it needs weather information, and the rou Tools can define typed parameters using the `parameter.*` prefix: +._Java-only: Java lambda Processor with string concatenation_ [source,java] ---- from("spring-ai-tools:weatherTool?tags=weather" + @@ -89,6 +91,7 @@ Parameter metadata is passed to the AI model to help it understand how to call t Instead of parameter maps, you can use a Java class to define the tool's input schema: +._Java-only: Java class definition with lambda Processor_ [source,java] ---- public class WeatherRequest { @@ -112,6 +115,7 @@ from("spring-ai-tools:weatherTool?tags=weather" + By default, tool results are passed back to the AI model for further processing. Use `returnDirect=true` to return the tool's result directly to the user: +._Java-only: Java lambda Processor_ [source,java] ---- from("spring-ai-tools:calculator?tags=math" + @@ -127,6 +131,7 @@ from("spring-ai-tools:calculator?tags=math" + Tags are used to organize and group tools. The xref:spring-ai-chat-component.adoc[Spring AI Chat Component] uses tags to discover which tools should be available to the AI model: +._Java-only: Java lambda Processor with multiple routes_ [source,java] ---- // Define tools with tags @@ -152,6 +157,7 @@ A single tool can have multiple tags, allowing flexible tool organization and re If a tool execution fails, the error is propagated back to the AI model, which can handle it or report it to the user: +._Java-only: Java onException handler_ [source,java] ---- from("spring-ai-tools:riskyOperation?tags=ops&description=Perform risky operation") @@ -166,6 +172,7 @@ from("spring-ai-tools:riskyOperation?tags=ops&description=Perform risky operatio Here's a complete example showing tool registration and usage: +._Java-only: Java RouteBuilder class_ [source,java] ---- // Register a database query tool @@ -201,6 +208,7 @@ When a user sends "Show me all customers and notify me when done" to the assista When a tool is invoked, all tool parameters are set as message headers. The parameter names correspond to header names: +._Java-only: Java lambda Processor_ [source,java] ---- // Tool definition with parameter.location=string @@ -228,6 +236,7 @@ When you configure the `tags` parameter on a `spring-ai-chat` endpoint: === Complete Integration Example +._Java-only: Java RouteBuilder class_ [source,java] ---- public class ChatWithToolsConfig { diff --git a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-vector-store/src/main/docs/spring-ai-vector-store-component.adoc b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-vector-store/src/main/docs/spring-ai-vector-store-component.adoc index 221f424ca399a..c640165189cb5 100644 --- a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-vector-store/src/main/docs/spring-ai-vector-store-component.adoc +++ b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-vector-store/src/main/docs/spring-ai-vector-store-component.adoc @@ -75,12 +75,42 @@ The component returns matching documents in the message body and sets the follow This is the *recommended best practice* for adding documents. The vector store component handles embedding generation internally: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:store") .to("spring-ai-vector-store:myStore?operation=ADD&vectorStore=#vectorStore"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:store + steps: + - to: + uri: spring-ai-vector-store:myStore + parameters: + operation: ADD + vectorStore: "#vectorStore" +---- +==== + When you send plain text to this route, the component automatically: 1. Generates embeddings using the embedding model configured in the vector store 2. Creates a Document object @@ -92,6 +122,10 @@ This single-step approach is simpler and more efficient than manually chaining t If you need explicit control over the embedding process or want to manipulate embeddings before storing, you can chain the components: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:embedAndStore") @@ -99,10 +133,44 @@ from("direct:embedAndStore") .to("spring-ai-vector-store:test?vectorStore=#vectorStore"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:embedAndStore + steps: + - to: + uri: spring-ai-embeddings:test + parameters: + embeddingModel: "#embeddingModel" + - to: + uri: spring-ai-vector-store:test + parameters: + vectorStore: "#vectorStore" +---- +==== + NOTE: This approach is only necessary when you need to access or modify the embeddings between generation and storage. For most use cases, the direct ADD operation (shown above) is preferred. === Similarity Search +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:search") @@ -112,10 +180,47 @@ from("direct:search") .log("Document IDs: ${header.CamelSpringAiVectorStoreDocumentIds}"); ---- +XML:: ++ +[source,xml] +---- + + + What is AI? + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:search + steps: + - setBody: + constant: "What is AI?" + - to: + uri: spring-ai-vector-store:myStore + parameters: + operation: SIMILARITY_SEARCH + topK: 5 + similarityThreshold: 0.7 + - log: + message: "Found ${header.CamelSpringAiVectorStoreSimilarDocuments.size()} similar documents" + - log: + message: "Document IDs: ${header.CamelSpringAiVectorStoreDocumentIds}" +---- +==== + === Delete Documents Delete documents by specifying their IDs: +._Java-only: Java constants and Arrays.asList()_ [source,java] ---- from("direct:delete") @@ -125,6 +230,7 @@ from("direct:delete") You can also chain operations to search for documents and then delete them using the returned IDs: +._Java-only: Java constants and enum values_ [source,java] ---- from("direct:searchAndDelete") @@ -138,6 +244,7 @@ from("direct:searchAndDelete") === Dynamic Operation +._Java-only: Java constants and enum values_ [source,java] ---- from("direct:dynamic") @@ -151,6 +258,7 @@ from("direct:dynamic") To use the ADD operation with automatic embedding generation (recommended), configure your vector store with an embedding model: +._Java-only: Java Spring AI SDK configuration_ [source,java] ---- // Create a Qdrant Client diff --git a/components/camel-spring-parent/camel-spring-rabbitmq/src/main/docs/spring-rabbitmq-component.adoc b/components/camel-spring-parent/camel-spring-rabbitmq/src/main/docs/spring-rabbitmq-component.adoc index ccfef3045eae0..b7f9345ee8427 100644 --- a/components/camel-spring-parent/camel-spring-rabbitmq/src/main/docs/spring-rabbitmq-component.adoc +++ b/components/camel-spring-parent/camel-spring-rabbitmq/src/main/docs/spring-rabbitmq-component.adoc @@ -231,6 +231,7 @@ part of the RabbitMQ endpoint URL, but it will be ignored in this example. In the `computeDestination` bean, specify the real destination by setting the `CamelRabbitmqExchangeOverrideName` header as follows: +._Java-only: Java handler method_ [source,java] ---- public void setExchangeHeader(Exchange exchange) { @@ -258,19 +259,46 @@ with simple language using xref:eips:toD-eip.adoc[toD]. For example, suppose you need to send messages to exchanges with order types, then using toD could, for example, be done as follows: -.Example SJMS2 route with `toD` +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:order") .toD("spring-rabbit:order-${header.orderType}"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:order + steps: + - toD: + uri: "spring-rabbit:order-${header.orderType}" +---- +==== + === Manual Acknowledgement If we need to manually acknowledge a message for some use case, we can do it by setting and acknowledgeMode to Manual and using the below snippet of code to get Channel and deliveryTag to manually acknowledge the message: +._Java-only: inline Processor with Spring RabbitMQ API_ [source,java] ---- from("spring-rabbitmq:%s?queues=%s&acknowledgeMode=MANUAL") diff --git a/components/camel-stax/src/main/docs/stax-component.adoc b/components/camel-stax/src/main/docs/stax-component.adoc index bb64d7047351b..4ea503605a860 100644 --- a/components/camel-stax/src/main/docs/stax-component.adoc +++ b/components/camel-stax/src/main/docs/stax-component.adoc @@ -67,6 +67,7 @@ The message body after the handling is the handler itself. Here is an example: +._Java-only: inline Processor class_ [source,java] -------------------------------------------------------------------------------------------------------- from("file:target/in") @@ -87,6 +88,7 @@ First, we suppose you have JAXB objects. For instance, a list of records in a wrapper object: +._Java-only: Java JAXB annotated class_ [source,java] ------------------------------------------------- import java.util.ArrayList; @@ -113,6 +115,7 @@ public class Records { and +._Java-only: Java JAXB annotated class_ [source,java] --------------------------------------------------------- import javax.xml.bind.annotation.XmlAccessType; @@ -165,6 +168,7 @@ Then you get an XML file to process: The StAX component provides an `StAXBuilder` which can be used when iterating XML elements with the Camel Splitter +._Java-only: Java static method with class literal_ [source,java] ------------------------------------------ from("file:target/in") @@ -178,6 +182,7 @@ import in the Java code. The stax builder is by default namespace aware on the XMLReader it uses. You can turn this off by setting the boolean parameter to false, as shown below: +._Java-only: Java static method with class literal_ [source,java] ------------------------------------------------- from("file:target/in") diff --git a/components/camel-stitch/src/main/docs/stitch-component.adoc b/components/camel-stitch/src/main/docs/stitch-component.adoc index c9fe3401bec5c..1aba630e8a5fa 100644 --- a/components/camel-stitch/src/main/docs/stitch-component.adoc +++ b/components/camel-stitch/src/main/docs/stitch-component.adoc @@ -62,6 +62,7 @@ This component implements the async Consumer and producer. This allows camel route to consume and produce events asynchronously without blocking any threads. +._Java-only: Java lambda Processor with Stitch SDK builders_ .Example showing how to produce data to Stitch from a custom processor: [source,java] -------------------------------------------------------------------------------- @@ -105,6 +106,7 @@ can be type of `StitchMessage`, `StitchRequestBody` or `Map` but this Map here i Here is list of examples showing data that can be proceeded to Stitch: ==== Input body type `org.apache.camel.component.stitch.client.models.StitchRequestBody`: +._Java-only: Java lambda Processor with Stitch SDK builders_ [source,java] -------------------------------------------------------------------------------- from("direct:sendStitch") @@ -128,6 +130,7 @@ from("direct:sendStitch") ==== Input body type `org.apache.camel.component.stitch.client.models.StitchMessage`: +._Java-only: Java lambda Processor with Stitch SDK API_ [source,java] -------------------------------------------------------------------------------- from("direct:sendStitch") @@ -147,6 +150,7 @@ from("direct:sendStitch") ==== Input body type `Map`: +._Java-only: Java lambda Processor with Map construction_ [source,java] -------------------------------------------------------------------------------- from("direct:sendStitch") @@ -170,6 +174,7 @@ from("direct:sendStitch") -------------------------------------------------------------------------------- ==== Input body type `Iterable`: +._Java-only: Java lambda Processor with Iterable construction_ [source,java] -------------------------------------------------------------------------------- from("direct:sendStitch") From 3f1fb76a89d3a58599689c952d44749abb3e06aa Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 10:21:57 +0200 Subject: [PATCH 80/87] CAMEL-23789: Make component docs multi-DSL friendly (Wave 1) - batch 3 Components: langchain4j-web-search, asn1, aws2-ec2, bean-language, box, couchbase, couchdb, cxf-transport, diagram, ftp, google-bigquery, google-secret-manager, iec60870-client, jooq, knative, knative-http, kubernetes-deployments, kubernetes-events, kubernetes-hpa, kubernetes-job, kubernetes-namespaces, kubernetes-nodes, kubernetes-pods, kubernetes-replication-controllers, kubernetes-services, openshift-deploymentconfigs, mongodb-gridfs, oauth, opentelemetry2, platform-http-vertx, xquery-language, xmlsecurity Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../langchain4j-web-search-component.adoc | 41 +++- .../src/main/docs/asn1-dataformat.adoc | 5 +- .../src/main/docs/aws2-ec2-component.adoc | 61 +++++- .../src/main/docs/bean-language.adoc | 5 + .../src/main/docs/box-component.adoc | 57 ++++++ .../src/main/docs/couchbase-component.adoc | 5 + .../src/main/docs/couchdb-component.adoc | 98 ++++++++- .../src/main/docs/cxf-transport.adoc | 7 +- .../camel-diagram/src/main/docs/diagram.adoc | 5 + .../src/main/docs/ftp-component.adoc | 138 ++++++++++++- .../main/docs/google-bigquery-component.adoc | 3 + .../docs/google-secret-manager-component.adoc | 192 ++++++++++++++++-- .../main/docs/iec60870-client-component.adoc | 143 +++++++++++++ .../src/main/docs/jooq-component.adoc | 36 +++- .../src/main/docs/knative-component.adoc | 5 + .../src/main/docs/knative-http-component.adoc | 5 + .../kubernetes-deployments-component.adoc | 3 + .../docs/kubernetes-events-component.adoc | 5 + .../main/docs/kubernetes-hpa-component.adoc | 3 + .../main/docs/kubernetes-job-component.adoc | 3 + .../docs/kubernetes-namespaces-component.adoc | 3 + .../main/docs/kubernetes-nodes-component.adoc | 3 + .../main/docs/kubernetes-pods-component.adoc | 3 + ...tes-replication-controllers-component.adoc | 3 + .../docs/kubernetes-services-component.adoc | 3 + ...openshift-deploymentconfigs-component.adoc | 3 + .../main/docs/mongodb-gridfs-component.adoc | 5 + .../camel-oauth/src/main/docs/oauth.adoc | 5 + .../src/main/docs/opentelemetry2.adoc | 36 +++- .../src/main/docs/platform-http-vertx.adoc | 40 +++- .../src/main/docs/xquery-language.adoc | 47 ++++- .../src/main/docs/xmlSecurity-dataformat.adoc | 4 + 32 files changed, 921 insertions(+), 54 deletions(-) diff --git a/components/camel-ai/camel-langchain4j-web-search/src/main/docs/langchain4j-web-search-component.adoc b/components/camel-ai/camel-langchain4j-web-search/src/main/docs/langchain4j-web-search-component.adoc index 4c21e0dab5e13..ecaa8ab9aff5e 100644 --- a/components/camel-ai/camel-langchain4j-web-search/src/main/docs/langchain4j-web-search-component.adoc +++ b/components/camel-ai/camel-langchain4j-web-search/src/main/docs/langchain4j-web-search-component.adoc @@ -69,7 +69,7 @@ Add the dependency for LangChain4j Tavily Web Search Engine support : Initialize the Web Search Engine instance, and bind it to the Camel Registry: -.Example: +._Java-only: binding a Tavily Web Search Engine to the registry_ [source,java] ---- @BindToRegistry("web-search-engine") @@ -132,7 +132,7 @@ By default, the `maxResults` property is set to 1. You can adjust this value to When `maxResults` is set to 1, you can by default retrieve by default the content as a single string. -.Example: +._Java-only: retrieving a single search result as a string_ [source,java] ---- String response = template.requestBody("langchain4j-web-search:test", "Who won the European Cup in 2024?", String.class); @@ -140,7 +140,7 @@ String response = template.requestBody("langchain4j-web-search:test", "Who won t When `maxResults` is greater than 1, you can retrieve a list of strings. -.Example: +._Java-only: retrieving multiple search results as a list of strings_ [source,java] ---- List responses = template.requestBody("langchain4j-web-search:test?maxResults=3", "Who won the European Cup in 2024?", List.class); @@ -165,7 +165,7 @@ When using a WebSearchRequest, the body and the parameters of the search will be A WebSearchRequest should be bound to the registry. -.Example of binding the request to the registry. +._Java-only: binding a WebSearchRequest to the registry_ [source,java] ---- @BindToRegistry("web-search-request") @@ -178,8 +178,37 @@ WebSearchRequest request = WebSearchRequest.builder() The request will be autowired automatically if its bound name is `web-search-request`. Otherwise, it should be added as a configured parameter to the Camel route. .Example of route: +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:web-search") - .to("langchain4j-web-search:test?webSearchRequest=#searchRequestTest"); +from("direct:web-search") + .to("langchain4j-web-search:test?webSearchRequest=#searchRequestTest"); +---- + +XML:: ++ +[source,xml] ---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:web-search + steps: + - to: + uri: langchain4j-web-search:test + parameters: + webSearchRequest: "#searchRequestTest" +---- +==== diff --git a/components/camel-asn1/src/main/docs/asn1-dataformat.adoc b/components/camel-asn1/src/main/docs/asn1-dataformat.adoc index a679b9e3f934f..122cc733c2164 100644 --- a/components/camel-asn1/src/main/docs/asn1-dataformat.adoc +++ b/components/camel-asn1/src/main/docs/asn1-dataformat.adoc @@ -27,6 +27,7 @@ There are 3 different ways to unmarshal ASN.1 structured messages. (Usually bina In this first example, we unmarshal BER file payload to OutputStream and send it to mock endpoint. +._Java-only: uses the asn1 data format object directly_ [source,java] ----------------------------------------------------------------------- from("direct:unmarshal").unmarshal(asn1).to("mock:unmarshal"); @@ -37,6 +38,7 @@ The reason for applying Split EIP is that usually each BER file or (ASN.1 struct Byte arrays then may be converted to ASN1Primitive by the help of public static method in (ASN1Primitive.fromByteArray) In such example, note that you need to set `usingIterator=true` +._Java-only: uses the asn1 data format object and Split EIP with bodyAs_ [source,java] ----------------------------------------------------------------------- from("direct:unmarshal") @@ -49,8 +51,9 @@ In the last example, we unmarshalled a BER file payload to plain old Java Object The important thing to note here is that your object should have been generated by jasn1 compiler, which is a nice tool to generate java object representations of your ASN.1 structure. For the reference usage of jasn1 compiler, see the https://www.beanit.com/asn1/[JASN.1 Project Page] and please also see how the compiler is invoked with the help of maven's exec plugin. For example, in this data format's unit tests an example ASN.1 structure(TestSMSBerCdr.asn1) is added in `src/test/resources/asn1_structure`. jasn1 compiler is invoked, and java object's representations are generated in `$\{basedir}/target/generated/src/test/java` -The nice thing about this example, you will get POJO instance at the mock endpoint or at whatever your endpoint is. +The nice thing about this example, you will get POJO instance at the mock endpoint or at whatever your endpoint is. +._Java-only: uses unmarshal with class name and Split EIP with bodyAs_ [source,java] ----------------------------------------------------------------------- from("direct:unmarshaldsl") diff --git a/components/camel-aws/camel-aws2-ec2/src/main/docs/aws2-ec2-component.adoc b/components/camel-aws/camel-aws2-ec2/src/main/docs/aws2-ec2-component.adoc index 583f40066bc4e..05e6fc1869148 100644 --- a/components/camel-aws/camel-aws2-ec2/src/main/docs/aws2-ec2-component.adoc +++ b/components/camel-aws/camel-aws2-ec2/src/main/docs/aws2-ec2-component.adoc @@ -89,18 +89,74 @@ For more information about this you can look at https://docs.aws.amazon.com/sdk- - createAndRunInstances: this operation will create an EC2 instance and run it +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------------------------- from("direct:createAndRun") .setHeader(EC2Constants.IMAGE_ID, constant("ami-fd65ba94")) - .setHeader(EC2Constants.INSTANCE_TYPE, constant(InstanceType.T2Micro)) + .setHeader(EC2Constants.INSTANCE_TYPE, constant(InstanceType.T2_MICRO)) .setHeader(EC2Constants.INSTANCE_MIN_COUNT, constant("1")) .setHeader(EC2Constants.INSTANCE_MAX_COUNT, constant("1")) .to("aws2-ec2://TestDomain?accessKey=xxxx&secretKey=xxxx&operation=createAndRunInstances"); -------------------------------------------------------------------------------- +XML:: ++ +[source,xml] +-------------------------------------------------------------------------------- + + + + ami-fd65ba94 + + + t2.micro + + + 1 + + + 1 + + + +-------------------------------------------------------------------------------- + +YAML:: ++ +[source,yaml] +-------------------------------------------------------------------------------- +- route: + from: + uri: direct:createAndRun + steps: + - setHeader: + name: CamelAwsEC2ImageId + constant: "ami-fd65ba94" + - setHeader: + name: CamelAwsEC2InstanceType + constant: "t2.micro" + - setHeader: + name: CamelAwsEC2InstanceMinCount + constant: "1" + - setHeader: + name: CamelAwsEC2InstanceMaxCount + constant: "1" + - to: + uri: aws2-ec2://TestDomain + parameters: + accessKey: xxxx + secretKey: xxxx + operation: createAndRunInstances +-------------------------------------------------------------------------------- +==== + - startInstances: this operation will start a list of EC2 instances +._Java-only: using a Processor to set the instance IDs collection_ [source,java] -------------------------------------------------------------------------------- from("direct:start") @@ -117,6 +173,7 @@ from("direct:start") - stopInstances: this operation will stop a list of EC2 instances +._Java-only: using a Processor to set the instance IDs collection_ [source,java] -------------------------------------------------------------------------------- from("direct:stop") @@ -133,6 +190,7 @@ from("direct:stop") - terminateInstances: this operation will terminate a list of EC2 instances +._Java-only: using a Processor to set the instance IDs collection_ [source,java] -------------------------------------------------------------------------------- from("direct:stop") @@ -152,6 +210,7 @@ from("direct:stop") Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as a body. In AWS EC2 there are multiple operations you can submit, as an example for Create and run an instance, you can do something like: +._Java-only: using AWS SDK RunInstancesRequest as POJO body_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") diff --git a/components/camel-bean/src/main/docs/bean-language.adoc b/components/camel-bean/src/main/docs/bean-language.adoc index 093e200f0ae87..35c0ce2ee1367 100644 --- a/components/camel-bean/src/main/docs/bean-language.adoc +++ b/components/camel-bean/src/main/docs/bean-language.adoc @@ -81,6 +81,7 @@ YAML:: The bean could be implemented as follows: +._Java-only: bean class implementation with Exchange parameter_ [source,java] ---- public class MyBean { @@ -94,6 +95,7 @@ How this method uses `Exchange` in the method signature. You would often not do and use non-Camel types. For example, by using `String` then Camel will automatically convert the message body to this type when calling the method: +._Java-only: bean method with automatic type conversion_ [source,java] ---- public boolean isGoldCustomer(String body) {...} @@ -104,6 +106,7 @@ public boolean isGoldCustomer(String body) {...} You can also use the xref:manual::bean-integration.adoc[Bean Integration] annotations, such as `@Header`, `@Body`, `@Variable` etc +._Java-only: using bean integration annotations for parameter binding_ [source,java] ---- public boolean isGoldCustomer(@Header(name = "foo") Integer fooHeader) {...} @@ -121,6 +124,7 @@ that are not registered in the xref:manual::registry.adoc[Registry]. Camel can instantiate the bean of a given type and invoke the method or invoke the method on an already existing instance. +._Java-only: invoking a bean by class type_ [source,java] ---- from("activemq:topic:OrdersTopic") @@ -130,6 +134,7 @@ from("activemq:topic:OrdersTopic") The first parameter can also be an existing instance of a Bean such as: +._Java-only: invoking a method on an existing bean instance_ [source,java] ---- private MyBean my = ...; diff --git a/components/camel-box/camel-box-component/src/main/docs/box-component.adoc b/components/camel-box/camel-box-component/src/main/docs/box-component.adoc index 95a2d01d143e2..e985c5c300873 100644 --- a/components/camel-box/camel-box-component/src/main/docs/box-component.adoc +++ b/components/camel-box/camel-box-component/src/main/docs/box-component.adoc @@ -77,26 +77,83 @@ The Box component supports three different types of authenticated connections. The following route uploads new files to the user's root folder: +[tabs] +==== +Java:: ++ [source,java] ---- from("file:...") .to("box://files/upload/inBody=fileUploadRequest"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:... + steps: + - to: + uri: box://files/upload/inBody=fileUploadRequest +---- +==== + The following route polls user's account for updates: +[tabs] +==== +Java:: ++ [source,java] ---- from("box://events/listen?startingPosition=-1") .to("bean:blah"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: box://events/listen + parameters: + startingPosition: -1 + steps: + - to: + uri: bean:blah +---- +==== + The following route uses a producer with dynamic header options. The *fileId* property has the Box file id and the *output* property has the output stream of the file contents, so they are assigned to the *CamelBox.fileId* header and *CamelBox.output* header respectively as follows: +._Java-only: uses header() expression to set dynamic headers_ [source,java] ---- from("direct:foo") diff --git a/components/camel-couchbase/src/main/docs/couchbase-component.adoc b/components/camel-couchbase/src/main/docs/couchbase-component.adoc index 4fba1980dcce6..d233060ea01ba 100644 --- a/components/camel-couchbase/src/main/docs/couchbase-component.adoc +++ b/components/camel-couchbase/src/main/docs/couchbase-component.adoc @@ -108,6 +108,7 @@ This generates: `SELECT META().id AS \__id, * FROM \`myBucket\` ORDER BY META(). For complex queries (filters, joins, aggregations), set the `statement` option directly: +._Java-only: string concatenation in endpoint URI_ [source,java] ---- from("couchbase:http://localhost?bucket=myBucket&username=user&password=pass" @@ -129,6 +130,7 @@ The consumer can also poll documents using MapReduce Views by setting `useView=t `designDocumentName` and `viewName` endpoint options. This mode is deprecated and will be removed in a future release. +._Java-only: string concatenation in endpoint URI_ [source,java] ---- from("couchbase:http://localhost?bucket=myBucket&username=user&password=pass" @@ -167,6 +169,7 @@ are automatically translated to SQL++ clauses: For example, a view-based consumer: +._Java-only: string concatenation in endpoint URI_ [source,java] ---- from("couchbase:http://localhost?bucket=myBucket&username=user&password=pass" @@ -175,6 +178,7 @@ from("couchbase:http://localhost?bucket=myBucket&username=user&password=pass" Can be migrated by simply removing the view-specific options: +._Java-only: string concatenation in endpoint URI_ [source,java] ---- from("couchbase:http://localhost?bucket=myBucket&username=user&password=pass" @@ -183,6 +187,7 @@ from("couchbase:http://localhost?bucket=myBucket&username=user&password=pass" Or with an explicit SQL++ statement for more control: +._Java-only: string concatenation in endpoint URI_ [source,java] ---- from("couchbase:http://localhost?bucket=myBucket&username=user&password=pass" diff --git a/components/camel-couchdb/src/main/docs/couchdb-component.adoc b/components/camel-couchdb/src/main/docs/couchdb-component.adoc index e1a99f36e78b0..d0fbd32455b36 100644 --- a/components/camel-couchdb/src/main/docs/couchdb-component.adoc +++ b/components/camel-couchdb/src/main/docs/couchdb-component.adoc @@ -91,24 +91,110 @@ For example, if you wish to consume all inserts, updates and deletes from a CouchDB instance running locally, on port 9999, then you could use the following: +[tabs] +==== +Java:: ++ [source,java] -------------------------------------------------------------- +---- from("couchdb:http://localhost:9999").process(someProcessor); -------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: couchdb:http://localhost:9999 + steps: + - process: + ref: someProcessor +---- +==== If you were only interested in deleting, then you could use the following: +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------------------------------------- +---- from("couchdb:http://localhost:9999?updates=false").process(someProcessor); ---------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: couchdb:http://localhost:9999 + parameters: + updates: false + steps: + - process: + ref: someProcessor +---- +==== If you want to insert a message as a document, then the body of the exchange is used: +[tabs] +==== +Java:: ++ [source,java] ----------------------------------------------------------------------------------------- +---- from("someProducingEndpoint").process(someProcessor).to("couchdb:http://localhost:9999") ----------------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: someProducingEndpoint + steps: + - process: + ref: someProcessor + - to: + uri: couchdb:http://localhost:9999 +---- +==== To start tracking the changes immediately after an update sequence, implement a custom resume strategy. To do so, it is necessary to implement a CouchDbResumeStrategy and use the resumable to set the last (update) offset to start tracking the changes: diff --git a/components/camel-cxf/camel-cxf-transport/src/main/docs/cxf-transport.adoc b/components/camel-cxf/camel-cxf-transport/src/main/docs/cxf-transport.adoc index 11973aee1105c..c50991636fe5e 100644 --- a/components/camel-cxf/camel-cxf-transport/src/main/docs/cxf-transport.adoc +++ b/components/camel-cxf/camel-cxf-transport/src/main/docs/cxf-transport.adoc @@ -73,6 +73,7 @@ the Camel context into the transport factory. If you want this factory take effect, you need to register the factory into the CXF bus. Here is a full example for you. +._Java-only: programmatic CXF bus and transport factory setup_ [source,java] ------------------------------------------------------------------------------------------------------------------ import org.apache.cxf.Bus; @@ -116,7 +117,7 @@ the `xsi:schemaLocation` attribute. *Adding the Configuration Namespace* -[source,java] +[source,xml] --------------------------------------------------------------------- @@ -154,7 +155,7 @@ endpoint's target namespace was `\http://widgets.widgetvendor.net`. - + ... --------------------------------------------------------------------------------------------------------------------------- diff --git a/components/camel-diagram/src/main/docs/diagram.adoc b/components/camel-diagram/src/main/docs/diagram.adoc index 5d95e0cfb5d2e..f624170dfa069 100644 --- a/components/camel-diagram/src/main/docs/diagram.adoc +++ b/components/camel-diagram/src/main/docs/diagram.adoc @@ -39,6 +39,7 @@ Add the `camel-diagram` dependency to your project: You can use the diagram renderer with the Camel API to render as PNG images: +._Java-only: using RouteDiagramDumper to render as PNG image_ [source,java] ---- RouteDiagramDumper dumper = PluginHelper.getRouteDiagramDumper(context); @@ -47,6 +48,7 @@ BufferedImage image = dumper.dumpRoutesAsImage("*", RouteDiagramDumper.Theme.DAR Or render as ASCII art text: +._Java-only: using RouteDiagramDumper to render as ASCII art_ [source,java] ---- RouteDiagramDumper dumper = PluginHelper.getRouteDiagramDumper(context); @@ -57,6 +59,7 @@ String ascii = dumper.dumpRoutesAsAsciiArt("*"); Then use the API to render diagrams: +._Java-only: standalone rendering to PNG image_ [source,java] ---- import org.apache.camel.diagram.*; @@ -80,6 +83,7 @@ ImageIO.write(image, "PNG", new File("diagram.png")); To render as ASCII art instead: +._Java-only: standalone rendering to ASCII art_ [source,java] ---- import org.apache.camel.diagram.*; @@ -255,6 +259,7 @@ or they typically follow the pattern ``. === With Java API +._Java-only: path highlighting with ASCII and PNG renderers_ [source,java] ---- import org.apache.camel.diagram.*; diff --git a/components/camel-ftp/src/main/docs/ftp-component.adoc b/components/camel-ftp/src/main/docs/ftp-component.adoc index 365ba2b47b476..b74ab2553c704 100644 --- a/components/camel-ftp/src/main/docs/ftp-component.adoc +++ b/components/camel-ftp/src/main/docs/ftp-component.adoc @@ -582,11 +582,40 @@ The file paths are matched with the following rules: The sample below demonstrates how to use it: +[tabs] +==== +Java:: ++ [source,java] ---- from("ftp://admin@localhost:2222/public/camel?antInclude=**/*.txt").to("..."); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: ftp://admin@localhost:2222/public/camel + parameters: + antInclude: "**/*.txt" + steps: + - to: + uri: "..." +---- +==== + === Using a proxy with SFTP To use an HTTP proxy to connect to your remote host, you can configure @@ -619,11 +648,42 @@ with a private/public SSH key and fallback to user/password authentication in the case when no public key is available, use the following route configuration: +[tabs] +==== +Java:: ++ [source,java] ---- -from("sftp://localhost:9999/root?username=admin&password=admin&preferredAuthentications=publickey,password"). - to("bean:processFile"); +from("sftp://localhost:9999/root?username=admin&password=admin&preferredAuthentications=publickey,password") + .to("bean:processFile"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: sftp://localhost:9999/root + parameters: + username: admin + password: admin + preferredAuthentications: publickey,password + steps: + - to: + uri: bean:processFile ---- +==== === Consuming a single file using a fixed name @@ -689,6 +749,7 @@ Notice that we have used all the options we talked above. You can also use this with `ConsumerTemplate`. For example, to download a single file (if it exists) and grab the file content as a String type: +._Java-only: using ConsumerTemplate to download a single file_ [source,java] ---- String data = template.retrieveBodyNoWait("ftp://admin@localhost:21/nolist/?password=admin&stepwise=false&useList=false&ignoreFileNotFoundOrPermissionError=true&fileName=report.txt&delete=true", String.class); @@ -749,21 +810,84 @@ YAML:: === Consuming a remote FTPS server (implicit SSL) and client authentication +[tabs] +==== +Java:: ++ [source,java] ---- -from("ftps://admin@localhost:2222/public/camel?password=admin&securityProtocol=SSL&implicit=true - &ftpClient.keyStore.file=./src/test/resources/server.jks - &ftpClient.keyStore.password=password&ftpClient.keyStore.keyPassword=password") - .to("bean:foo"); +from("ftps://admin@localhost:2222/public/camel?password=admin&securityProtocol=SSL&implicit=true&ftpClient.keyStore.file=./src/test/resources/server.jks&ftpClient.keyStore.password=password&ftpClient.keyStore.keyPassword=password") + .to("bean:foo"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: ftps://admin@localhost:2222/public/camel + parameters: + password: admin + securityProtocol: SSL + implicit: true + ftpClient.keyStore.file: ./src/test/resources/server.jks + ftpClient.keyStore.password: password + ftpClient.keyStore.keyPassword: password + steps: + - to: + uri: bean:foo ---- +==== === Consuming a remote FTPS server (explicit TLS) and a custom trust store configuration +[tabs] +==== +Java:: ++ [source,java] ---- from("ftps://admin@localhost:2222/public/camel?password=admin&ftpClient.trustStore.file=./src/test/resources/server.jks&ftpClient.trustStore.password=password") - .to("bean:foo"); + .to("bean:foo"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] ---- +- route: + from: + uri: ftps://admin@localhost:2222/public/camel + parameters: + password: admin + ftpClient.trustStore.file: ./src/test/resources/server.jks + ftpClient.trustStore.password: password + steps: + - to: + uri: bean:foo +---- +==== === Examples diff --git a/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-component.adoc b/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-component.adoc index e902d40a50f42..dfb099b3b174a 100644 --- a/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-component.adoc +++ b/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-component.adoc @@ -52,6 +52,7 @@ https://developers.google.com/identity/protocols/application-default-credentials When you have the **service account key**, you can provide authentication credentials to your application code. Google security credentials can be set through the component endpoint: +._Java-only: constructing the endpoint URI as a Java string_ [source,java] -------------------------------------------------------- String endpoint = "google-bigquery://project-id:datasetId[:tableId]?serviceAccountKey=/home/user/Downloads/my-key.json"; @@ -59,6 +60,7 @@ String endpoint = "google-bigquery://project-id:datasetId[:tableId]?serviceAccou You can also use the base64 encoded content of the authentication credentials file if you don't want to set a file system path. +._Java-only: constructing the endpoint URI with base64 credentials_ [source,java] -------------------------------------------------------- String endpoint = "google-bigquery://project-id:datasetId[:tableId]?serviceAccountKey=base64:"; @@ -104,6 +106,7 @@ Templated tables can be specified using the `GoogleBigQueryConstants.TABLE_SUFFI I.e. the following route will create tables and insert records sharded on a per-day basis: +._Java-only: uses GoogleBigQueryConstants to set the table suffix header_ [source,java] ------------------------------------------------------ from("direct:start") diff --git a/components/camel-google/camel-google-secret-manager/src/main/docs/google-secret-manager-component.adoc b/components/camel-google/camel-google-secret-manager/src/main/docs/google-secret-manager-component.adoc index 6ac8dc177daa6..f753095b923c7 100644 --- a/components/camel-google/camel-google-secret-manager/src/main/docs/google-secret-manager-component.adoc +++ b/components/camel-google/camel-google-secret-manager/src/main/docs/google-secret-manager-component.adoc @@ -41,6 +41,7 @@ For more information, please refer to https://github.com/googleapis/google-cloud When you have the **service account key**, you can provide authentication credentials to your application code. Google security credentials can be set through the component endpoint: +._Java-only: setting the endpoint URI with service account key_ [source,java] -------------------------------------------------------- String endpoint = "google-secret-manager://myCamelFunction?serviceAccountKey=/home/user/Downloads/my-key.json"; @@ -415,44 +416,199 @@ If you don't specify an operation by default, the producer will use the `createS - `createSecret`: This operation will create a secret in the Secret Manager service +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .setHeader("GoogleSecretManagerConstants.SECRET_ID, constant("test")) + .setHeader("CamelGoogleSecretManagerSecretId", constant("test")) .setBody(constant("hello")) - .to("google-functions://myProject?serviceAccountKey=/home/user/Downloads/my-key.json&operation=createSecret") - .log("body:${body}") --------------------------------------------------------------------------------- + .to("google-secret-manager://myProject?serviceAccountKey=/home/user/Downloads/my-key.json&operation=createSecret") + .log("body:${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + test + + + hello + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleSecretManagerSecretId + constant: test + - setBody: + constant: hello + - to: + uri: google-secret-manager://myProject + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + operation: createSecret + - log: + message: "body:${body}" +---- +==== - `getSecretVersion`: This operation will retrieve a secret value with the latest version in the Secret Manager service +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .setHeader("GoogleSecretManagerConstants.SECRET_ID, constant("test")) - .to("google-functions://myProject?serviceAccountKey=/home/user/Downloads/my-key.json&operation=getSecretVersion") - .log("body:${body}") --------------------------------------------------------------------------------- + .setHeader("CamelGoogleSecretManagerSecretId", constant("test")) + .to("google-secret-manager://myProject?serviceAccountKey=/home/user/Downloads/my-key.json&operation=getSecretVersion") + .log("body:${body}"); +---- + +XML:: ++ +[source,xml] +---- + + + + test + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleSecretManagerSecretId + constant: test + - to: + uri: google-secret-manager://myProject + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + operation: getSecretVersion + - log: + message: "body:${body}" +---- +==== This will log the value of the secret "test". - `deleteSecret`: This operation will delete a secret +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .setHeader("GoogleSecretManagerConstants.SECRET_ID, constant("test")) - .to("google-functions://myProject?serviceAccountKey=/home/user/Downloads/my-key.json&operation=deleteSecret") --------------------------------------------------------------------------------- + .setHeader("CamelGoogleSecretManagerSecretId", constant("test")) + .to("google-secret-manager://myProject?serviceAccountKey=/home/user/Downloads/my-key.json&operation=deleteSecret"); +---- + +XML:: ++ +[source,xml] +---- + + + + test + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleSecretManagerSecretId + constant: test + - to: + uri: google-secret-manager://myProject + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + operation: deleteSecret +---- +==== - `listSecrets`: This operation will return the secrets' list for the project myProject +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") - .setHeader("GoogleSecretManagerConstants.SECRET_ID, constant("test")) - .to("google-functions://myProject?serviceAccountKey=/home/user/Downloads/my-key.json&operation=listSecrets") --------------------------------------------------------------------------------- + .setHeader("CamelGoogleSecretManagerSecretId", constant("test")) + .to("google-secret-manager://myProject?serviceAccountKey=/home/user/Downloads/my-key.json&operation=listSecrets"); +---- + +XML:: ++ +[source,xml] +---- + + + + test + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelGoogleSecretManagerSecretId + constant: test + - to: + uri: google-secret-manager://myProject + parameters: + serviceAccountKey: /home/user/Downloads/my-key.json + operation: listSecrets +---- +==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-iec60870/src/main/docs/iec60870-client-component.adoc b/components/camel-iec60870/src/main/docs/iec60870-client-component.adoc index 33907d92a1a98..1dbd9aace0ba2 100644 --- a/components/camel-iec60870/src/main/docs/iec60870-client-component.adoc +++ b/components/camel-iec60870/src/main/docs/iec60870-client-component.adoc @@ -88,6 +88,7 @@ The producer supports different command types via the `CamelIec60870CommandType` === Getting Connection Status (Producer) +._Java-only: using ProducerTemplate to send and inspect connection state headers_ [source,java] ---- from("direct:status") @@ -102,6 +103,10 @@ Long uptime = result.getMessage().getHeader("CamelIec60870ConnectionUptime", Lon === Triggering Interrogation +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:interrogate") @@ -114,8 +119,65 @@ from("direct:interrogateGroup") .to("iec60870-client:localhost:2404/00-01-00-00-01"); ---- +XML:: ++ +[source,xml] +---- + + + + interrogation + + + + + + + + interrogation + + + 21 + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:interrogate + steps: + - setHeader: + name: CamelIec60870CommandType + constant: interrogation + - to: + uri: iec60870-client:localhost:2404/00-01-00-00-01 + +- route: + from: + uri: direct:interrogateGroup + steps: + - setHeader: + name: CamelIec60870CommandType + constant: interrogation + - setHeader: + name: CamelIec60870Qoi + constant: 21 + - to: + uri: iec60870-client:localhost:2404/00-01-00-00-01 +---- +==== + === Sending Value Commands +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:bool").setBody(constant(true)) @@ -125,12 +187,58 @@ from("direct:float").setBody(constant(42.5f)) .to("iec60870-client:localhost:2404/00-01-00-00-01"); ---- +XML:: ++ +[source,xml] +---- + + + + true + + + + + + + + 42.5 + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:bool + steps: + - setBody: + constant: true + - to: + uri: iec60870-client:localhost:2404/00-01-00-00-01 + +- route: + from: + uri: direct:float + steps: + - setBody: + constant: 42.5 + - to: + uri: iec60870-client:localhost:2404/00-01-00-00-01 +---- +==== + == Consumer Examples Each message received by the consumer includes connection state and quality headers. === Getting Connection Status (Consumer) +._Java-only: using a Processor lambda to access typed connection state and quality headers_ [source,java] ---- from("iec60870-client:localhost:2404/00-01-00-00-01") @@ -150,6 +258,10 @@ from("iec60870-client:localhost:2404/00-01-00-00-01") === Filtering by Quality +[tabs] +==== +Java:: ++ [source,java] ---- from("iec60870-client:localhost:2404/00-01-00-00-01") @@ -158,4 +270,35 @@ from("iec60870-client:localhost:2404/00-01-00-00-01") .to("seda:process"); ---- +XML:: ++ +[source,xml] +---- + + + + ${header.CamelIec60870QualityValid} == true + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: iec60870-client:localhost:2404/00-01-00-00-01 + steps: + - filter: + simple: "${header.CamelIec60870QualityValid} == true" + steps: + - log: "Good value: ${header.CamelIec60870Value}" + - to: + uri: seda:process +---- +==== + include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jooq/src/main/docs/jooq-component.adoc b/components/camel-jooq/src/main/docs/jooq-component.adoc index 068919c929e47..e96d5ecfcb5b0 100644 --- a/components/camel-jooq/src/main/docs/jooq-component.adoc +++ b/components/camel-jooq/src/main/docs/jooq-component.adoc @@ -31,6 +31,8 @@ There are two types of queries: . `org.jooq.ResultQuery`: can return results For example: + +._Java-only: JOOQ DSL API for creating Query and ResultQuery objects_ [source,java] ---- // Create a Query object and execute it: @@ -46,11 +48,41 @@ Result result = resultQuery.fetch(); SQL could be executed using JOOQ's objects "Query" or "ResultQuery". Also, the SQL query could be specified inside URI: +[tabs] +==== +Java:: ++ [source,java] ---- -from("jooq://org.apache.camel.component.jooq.db.tables.records.BookStoreRecord?query=select * from book_store x where x.name = 'test'").to("bean:myBusinessLogic"); +from("jooq://org.apache.camel.component.jooq.db.tables.records.BookStoreRecord?query=select * from book_store x where x.name = 'test'") + .to("bean:myBusinessLogic"); +---- + +XML:: ++ +[source,xml] +---- + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: jooq://org.apache.camel.component.jooq.db.tables.records.BookStoreRecord + parameters: + query: "select * from book_store x where x.name = 'test'" + steps: + - to: + uri: bean:myBusinessLogic +---- +==== + See the examples below. === Consuming from endpoint @@ -200,6 +232,8 @@ When using jooq as a producer you can use any of the following `JooqOperation` o ---- .Sample bean: + +._Java-only: JOOQ bean with Query and ResultQuery factory methods_ [source,java] ---- @Component diff --git a/components/camel-knative/camel-knative-component/src/main/docs/knative-component.adoc b/components/camel-knative/camel-knative-component/src/main/docs/knative-component.adoc index ac57195524a12..527f5db1a77f1 100644 --- a/components/camel-knative/camel-knative-component/src/main/docs/knative-component.adoc +++ b/components/camel-knative/camel-knative-component/src/main/docs/knative-component.adoc @@ -119,6 +119,7 @@ The `metadata` fields has some additional advanced fields: |=== .Example +._Java-only: programmatic Knative component configuration with CamelContext API_ [source,java] ---- CamelContext context = new DefaultCamelContext(); @@ -147,6 +148,7 @@ camel.component.knative.environmentPath=classpath:knative.json As today the Knative component only supports `http` as transport as this is the only supported protocol on Knative side. The transport implementation is pluggable though by implementing the following interface: +._Java-only: KnativeTransport SPI interface for custom transport implementations_ [source,java] ---- public interface KnativeTransport extends Service { @@ -208,6 +210,7 @@ The `Knative Environment` configuration is set on the Knative component and spec You can then use the `event` resource type in your Camel route to send data to the Knative broker. .Example +._Java-only: programmatic CamelContext setup with CloudEvents data type transformation_ [source,java] ---- CamelContext context = new DefaultCamelContext(); @@ -307,6 +310,7 @@ The Camel application may run into errors because of the missing variable when s When using Knative producer with a ProducerTemplate, it is necessary to specify a value for the CloudEvent source, simply by setting a value for the header 'CamelCloudEventSource'. .Example +._Java-only: ProducerTemplate API for sending events with CloudEvent headers_ [source,java] ---- producerTemplate.sendBodyAndHeader("knative:event/broker-test", body, CloudEvent.CAMEL_CLOUD_EVENT_SOURCE, "my-source-name"); @@ -350,6 +354,7 @@ The Knative Camel component will automatically configure this Http service when Just use the `event` resource type in your Camel route like this: .Example +._Java-only: programmatic route setup with RouteBuilder.addRoutes API_ [source,java] ---- RouteBuilder.addRoutes(context, b -> { diff --git a/components/camel-knative/camel-knative-http/src/main/docs/knative-http-component.adoc b/components/camel-knative/camel-knative-http/src/main/docs/knative-http-component.adoc index b424b2764675b..81b008bb9e785 100644 --- a/components/camel-knative/camel-knative-http/src/main/docs/knative-http-component.adoc +++ b/components/camel-knative/camel-knative-http/src/main/docs/knative-http-component.adoc @@ -36,6 +36,7 @@ The factory provides some configuration options that you can set to customize th First of all the producer factory performs a lookup on the Vertx instance and the VertxOptions, so you can customize these resources and bind them to the Camel context prior to using the Kntive component. +._Java-only: binding custom Vertx instance and options to the Camel registry_ .Example [source,java] ---- @@ -52,6 +53,7 @@ context.getRegistry().bind("vertxInstance", vertx); In the very same manner you may also bind the Vertx web client options to the Camel context. The producer factory will automatically perform the lookup of the options instance. +._Java-only: binding custom Vertx web client options to the Camel registry_ .Example [source,java] ---- @@ -79,6 +81,7 @@ The Apache Camel Knative component supports special web client options to easily You can set the client options on the Knative Http producer factory as follows: +._Java-only: configuring SSL client options on the Knative Http producer factory_ .Example [source,java] ---- @@ -108,6 +111,7 @@ camel.component.knative.producerFactory.clientOptions=#bean:myClientOptions TIP: When there is no proper trust certificate available (e.g. on test environments) you can use a trust all strategy on the client options with the class `org.apache.camel.component.knative.http.TrustAllOptions`. +._Java-only: using TrustAllOptions for test environments_ .TrustAllOptions [source,java] ---- @@ -179,6 +183,7 @@ This means the OIDC access token is mounted as a file into the application conta You need to enable OIDC support on the Knative Http client in the options like this: +._Java-only: configuring OIDC client options on the Knative Http producer factory_ .Example [source,java] ---- diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-deployments-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-deployments-component.adoc index ad21cc4e25e8f..2e0dc494859e4 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-deployments-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-deployments-component.adoc @@ -42,6 +42,7 @@ include::partial$component-endpoint-headers.adoc[] - `listDeployments`: this operation lists the deployments on a kubernetes cluster +._Java-only: uses toF() for endpoint URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -53,6 +54,7 @@ This operation returns a List of Deployment from your cluster - `listDeploymentsByLabels`: this operation lists the deployments by labels on a kubernetes cluster +._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { @@ -72,6 +74,7 @@ This operation returns a List of Deployments from your cluster, using a label se === Kubernetes Deployments Consumer Example +._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] -------------------------------------------------------------------------------- fromF("kubernetes-deployments://%s?oauthToken=%s", host, authToken) diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-events-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-events-component.adoc index 96c8aa53ffb41..b03273a6a22b0 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-events-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-events-component.adoc @@ -88,6 +88,7 @@ To indicate from which namespace, the events are expected, it is possible to set - `listEventsByLabels`: this operation lists the events selected by labels +._Java-only: using a Processor to set label headers on the exchange_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { @@ -110,6 +111,7 @@ This operation expects the message header `CamelKubernetesEventsLabels` to be se - `getEvent`: this operation gives a specific event +._Java-only: using a Processor to set namespace and event name headers_ [source,java] -------------------------------------------------------------------------------- from("direct:get").process(new Processor() { @@ -132,6 +134,7 @@ If no matching event could be found, `null` is returned. - `createEvent`: this operation creates a new event +._Java-only: using a Processor to set event headers for creation_ [source,java] -------------------------------------------------------------------------------- from("direct:get").process(new Processor() { @@ -171,6 +174,7 @@ The behavior is exactly the same as `createEvent`, only the name of the operatio - `deleteEvent`: this operation deletes an existing event. +._Java-only: using a Processor to set namespace and event name headers_ [source,java] -------------------------------------------------------------------------------- from("direct:get").process(new Processor() { @@ -191,6 +195,7 @@ This operation expects two message headers which are `CamelKubernetesNamespaceNa === Kubernetes Events Consumer Example +._Java-only: using fromF with parameters and a custom Processor to handle Event objects_ [source,java] -------------------------------------------------------------------------------- fromF("kubernetes-events://%s?oauthToken=%s", host, authToken) diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-hpa-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-hpa-component.adoc index 9346c6afc0dbb..6953f2b36573a 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-hpa-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-hpa-component.adoc @@ -41,6 +41,7 @@ include::partial$component-endpoint-headers.adoc[] - `listHPA`: this operation lists the HPAs on a kubernetes cluster +._Java-only: uses toF() for endpoint URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -52,6 +53,7 @@ This operation returns a list of HPAs from your cluster - `listDeploymentsByLabels`: this operation lists the HPAs by labels on a kubernetes cluster +._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { @@ -71,6 +73,7 @@ This operation returns a List of HPAs from your cluster using a label selector ( === Kubernetes HPA Consumer Example +._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] -------------------------------------------------------------------------------- fromF("kubernetes-hpa://%s?oauthToken=%s", host, authToken) diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-job-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-job-component.adoc index 14bee1328520d..e5c1e6da8baaa 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-job-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-job-component.adoc @@ -42,6 +42,7 @@ include::partial$component-endpoint-headers.adoc[] - `listJob`: this operation lists the jobs on a kubernetes cluster +._Java-only: uses toF() for endpoint URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -53,6 +54,7 @@ This operation returns a list of jobs from your cluster - `listJobByLabels`: this operation lists the jobs by labels on a kubernetes cluster +._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { @@ -74,6 +76,7 @@ This operation returns a list of jobs from your cluster, using a label selector We have a wonderful example of this operation thanks to https://github.com/Emmerson-Miranda[Emmerson Miranda] from this https://github.com/Emmerson-Miranda/camel/blob/master/camel3-cdi/cdi-k8s-pocs/src/main/java/edu/emmerson/camel/k8s/jobs/camel_k8s_jobs/KubernetesCreateJob.java[Java test] +._Java-only: full RouteBuilder class with KubernetesConstants, lambda Processors, and programmatic JobSpec construction_ [source,java] -------------------------------------------------------------------------------- import java.util.ArrayList; diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-namespaces-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-namespaces-component.adoc index 2b3818784650d..8cdbc7ddf54e9 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-namespaces-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-namespaces-component.adoc @@ -42,6 +42,7 @@ include::partial$component-endpoint-headers.adoc[] - `listNamespaces`: this operation lists the namespaces on a kubernetes cluster +._Java-only: uses toF() for endpoint URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -53,6 +54,7 @@ This operation returns a list of namespaces from your cluster - `listNamespacesByLabels`: this operation lists the namespaces by labels on a kubernetes cluster +._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { @@ -72,6 +74,7 @@ This operation returns a list of namespaces from your cluster, using a label sel === Kubernetes Namespaces Consumer Example +._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] -------------------------------------------------------------------------------- fromF("kubernetes-namespaces://%s?oauthToken=%s", host, authToken) diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-nodes-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-nodes-component.adoc index b07eb3e5f8621..ea6728dc2fde8 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-nodes-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-nodes-component.adoc @@ -43,6 +43,7 @@ include::partial$component-endpoint-headers.adoc[] - `listNodes`: this operation lists the nodes on a kubernetes cluster +._Java-only: uses toF() for endpoint URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -54,6 +55,7 @@ This operation returns a List of Nodes from your cluster - `listNodesByLabels`: this operation lists the nodes by labels on a kubernetes cluster +._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { @@ -73,6 +75,7 @@ This operation returns a list of nodes from your cluster, using a label selector === Kubernetes Nodes Consumer Example +._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] -------------------------------------------------------------------------------- fromF("kubernetes-nodes://%s?oauthToken=%s", host, authToken) diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-pods-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-pods-component.adoc index 43f018a03a18f..979f8da521fdd 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-pods-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-pods-component.adoc @@ -43,6 +43,7 @@ include::partial$component-endpoint-headers.adoc[] - `listPods`: this operation lists the pods on a kubernetes cluster +._Java-only: uses toF() for endpoint URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -54,6 +55,7 @@ This operation returns a list of pods from your cluster - `listPodsByLabels`: this operation lists the pods by labels on a kubernetes cluster +._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { @@ -73,6 +75,7 @@ This operation returns a list of pods from your cluster using a label selector ( === Kubernetes Pods Consumer Example +._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] -------------------------------------------------------------------------------- fromF("kubernetes-pods://%s?oauthToken=%s", host, authToken) diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-replication-controllers-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-replication-controllers-component.adoc index 6196132488ead..4bc5d7f421fb6 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-replication-controllers-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-replication-controllers-component.adoc @@ -45,6 +45,7 @@ include::partial$component-endpoint-headers.adoc[] - `listReplicationControllers`: this operation lists the RCs on a kubernetes cluster +._Java-only: uses toF() for endpoint URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -56,6 +57,7 @@ This operation returns a list of RCs from your cluster - `listReplicationControllersByLabels`: this operation lists the RCs by labels on a kubernetes cluster +._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { @@ -75,6 +77,7 @@ This operation returns a list of RCs from your cluster using a label selector (w === Kubernetes Replication Controllers Consumer Example +._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] -------------------------------------------------------------------------------- fromF("kubernetes-replication-controllers://%s?oauthToken=%s", host, authToken) diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-services-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-services-component.adoc index 636c9aaab8a51..2917956e5e7a5 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-services-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-services-component.adoc @@ -42,6 +42,7 @@ include::partial$component-endpoint-headers.adoc[] - `listServices`: this operation lists the services on a kubernetes cluster +._Java-only: uses toF() for endpoint URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -53,6 +54,7 @@ This operation returns a List of services from your cluster - `listServicesByLabels`: this operation lists the deployments by labels on a kubernetes cluster +._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { @@ -72,6 +74,7 @@ This operation returns a list of services from your cluster using a label select === Kubernetes Services Consumer Example +._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] -------------------------------------------------------------------------------- fromF("kubernetes-services://%s?oauthToken=%s", host, authToken) diff --git a/components/camel-kubernetes/src/main/docs/openshift-deploymentconfigs-component.adoc b/components/camel-kubernetes/src/main/docs/openshift-deploymentconfigs-component.adoc index 1c8975ad0ee66..bf5d2e6143402 100644 --- a/components/camel-kubernetes/src/main/docs/openshift-deploymentconfigs-component.adoc +++ b/components/camel-kubernetes/src/main/docs/openshift-deploymentconfigs-component.adoc @@ -42,6 +42,7 @@ include::partial$component-endpoint-headers.adoc[] - `listDeploymentConfigs`: this operation lists the deployments on an Openshift cluster +._Java-only: uses toF() for endpoint URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -53,6 +54,7 @@ This operation returns a list of deployment configs from your cluster - `listDeploymentConfigsByLabels`: this operation lists the deployment configs by labels on an Openshift cluster +._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { @@ -72,6 +74,7 @@ This operation returns a list of deployment configs from your cluster using a la === Openshift Deployment Configs Consumer Example +._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] -------------------------------------------------------------------------------- fromF("openshift-deploymentconfigs://%s?oauthToken=%s", host, authToken) diff --git a/components/camel-mongodb-gridfs/src/main/docs/mongodb-gridfs-component.adoc b/components/camel-mongodb-gridfs/src/main/docs/mongodb-gridfs-component.adoc index 590ee6b57813c..9f4e2f9110dad 100644 --- a/components/camel-mongodb-gridfs/src/main/docs/mongodb-gridfs-component.adoc +++ b/components/camel-mongodb-gridfs/src/main/docs/mongodb-gridfs-component.adoc @@ -49,6 +49,7 @@ include::partial$component-endpoint-headers.adoc[] Returns the total number of files in the collection, returning an Integer as the OUT message body. +._Java-only: using ProducerTemplate to invoke the count operation_ [source,java] --------------------------------------------------------------------------------- // from("direct:count").to("mongodb-gridfs?database=tickets&operation=count"); @@ -59,6 +60,7 @@ assertTrue("Result is not of type Long", result instanceof Integer); You can provide a filename header to provide a count of files matching that filename. +._Java-only: using ProducerTemplate with filename header_ [source,java] ------------------------------------------------------------------------------- Map headers = new HashMap(); @@ -85,6 +87,7 @@ Finds a file in the GridFS system and sets the body to an InputStream of the content. Also provides the metadata has headers. It uses `Exchange.FILE_NAME` from the incoming headers to determine the file to find. +._Java-only: using ProducerTemplate to find a file by name_ [source,java] ------------------------------------------------------------------------------------------------- // from("direct:findOne").to("mongodb-gridfs?database=tickets&operation=findOne"); @@ -99,6 +102,7 @@ Create a new file in the GridFs database. It uses the `Exchange.FILE_NAME` from the incoming headers for the name and the body contents (as an InputStream) as the content. +._Java-only: using ProducerTemplate to create a file_ [source,java] ------------------------------------------------------------------------ // from("direct:create").to("mongodb-gridfs?database=tickets&operation=create"); @@ -112,6 +116,7 @@ template.requestBodyAndHeaders("direct:create", stream, headers); Removes a file from the GridFS database. +._Java-only: using ProducerTemplate to remove a file_ [source,java] ------------------------------------------------------------------------ // from("direct:remove").to("mongodb-gridfs?database=tickets&operation=remove"); diff --git a/components/camel-oauth/src/main/docs/oauth.adoc b/components/camel-oauth/src/main/docs/oauth.adoc index 673f6594de416..3ab95f9c7ea53 100644 --- a/components/camel-oauth/src/main/docs/oauth.adoc +++ b/components/camel-oauth/src/main/docs/oauth.adoc @@ -352,6 +352,7 @@ The `OAuthHelper` utility from `camel-support` can be used for both outgoing cli ==== Validate an Incoming Bearer Token +._Java-only: programmatic token validation using OAuthHelper API_ [source,java] ---- import org.apache.camel.spi.OAuthTokenValidationResult; @@ -379,6 +380,7 @@ String email = result.getClaim("email", String.class); For the default unnamed profile, use: +._Java-only: default profile token validation_ [source,java] ---- OAuthTokenValidationResult result = OAuthHelper.validateOAuthToken(camelContext, bearerToken); @@ -386,6 +388,7 @@ OAuthTokenValidationResult result = OAuthHelper.validateOAuthToken(camelContext, For advanced validation use cases, resolve `OAuthTokenValidationFactory` directly and pass an explicit `OAuthTokenValidationConfig`. +._Java-only: advanced validation with explicit config and factory_ [source,java] ---- import org.apache.camel.spi.OAuthTokenValidationConfig; @@ -405,6 +408,7 @@ OAuthTokenValidationResult result = factory.validateToken(config, bearerToken); ==== Resolve an Outgoing Client Credentials Token +._Java-only: resolving an OAuth token using OAuthHelper_ [source,java] ---- import org.apache.camel.support.OAuthHelper; @@ -414,6 +418,7 @@ String token = OAuthHelper.resolveOAuthToken(camelContext, "keycloak"); For advanced use cases, the `OAuthClientAuthenticationFactory` can be used directly with an explicit `OAuthClientConfig`: +._Java-only: advanced token resolution with explicit OAuthClientConfig_ [source,java] ---- import org.apache.camel.spi.OAuthClientAuthenticationFactory; diff --git a/components/camel-opentelemetry2/src/main/docs/opentelemetry2.adoc b/components/camel-opentelemetry2/src/main/docs/opentelemetry2.adoc index 16687556b4ce6..b8c02364e088d 100644 --- a/components/camel-opentelemetry2/src/main/docs/opentelemetry2.adoc +++ b/components/camel-opentelemetry2/src/main/docs/opentelemetry2.adoc @@ -248,6 +248,7 @@ Then add the following dependency for the OpenTelemetry Spring Boot starter: The starter auto-configures most aspects of the OpenTelemetry instrumentation, with two exceptions: No `Tracer` or `ContextPropagators` beans are autoconfigured, they need to be configured manually: +._Java-only: Spring configuration class for OpenTelemetry beans_ [source,java] ---- import io.opentelemetry.api.OpenTelemetry; @@ -288,6 +289,7 @@ otel: When you're working at a very low level, you may need to tweak your metrics and add some in-process custom `span` in order to trace some specific measure of your application. If you need this advanced use case, you can create it during your process by configuring an Opentelemetry Tracer object and share it to your route. For example, in Java DSL: +._Java-only: creating custom spans with the OpenTelemetry Tracer API_ [source,java] ---- private Tracer otelTracer = otelExtension.getOpenTelemetry().getTracer("traceTest"); @@ -307,6 +309,7 @@ public void process(Exchange exchange) throws Exception { In complex integrations it is advisable to have third party dependencies or add custom spans at a Processor level in order to get advanced telemetry information. When these spans are added at Processor level, then, you can expect the span to be nested under the specific core Processor. For example: +._Java-only: bean with @WithSpan annotation for custom span nesting_ [source,java] ---- from("direct:start") @@ -324,12 +327,38 @@ You should expect your custom span "myLogic" to be nested under the Bean process If you instead call it with an endpoint producer, the process is converted to an event, and as we cannot capture the scope, then it would nest the custom span under the endpoint instead. For example: +[tabs] +==== +Java:: ++ [source,java] ---- - from("direct:start") - .to("bean:myBean") -... +from("direct:start") + .to("bean:myBean"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - to: + uri: bean:myBean ---- +==== The spans produced are slightly different because now they include an additional span for the endpoint ("to" node). And, more important, as highlighted above, the custom span is going to be nested directly under the endpoint span "to" instead of the processor span ("bean"). @@ -339,6 +368,7 @@ For this reason, whenever you need to provide custom telemetry information, it i `Baggage` is a way to attach key-value metadata to a request and carry it across service boundaries. In the context of OpenTelemetry, baggage travels along with the context (like trace/span), but it's meant for custom data you define, not telemetry internals. Camel allows you to programmatically provide any `Baggage` information via Exchange property settings. Whenever the component finds a property defined as `CamelBaggage_xyz` it will consider it as a baggage variable named `xyz`. For example, in Java DSL: +._Java-only: inline Processor accessing OpenTelemetry Baggage API_ [source,java] ---- from("direct:start") diff --git a/components/camel-platform-http-vertx/src/main/docs/platform-http-vertx.adoc b/components/camel-platform-http-vertx/src/main/docs/platform-http-vertx.adoc index 1f011be736fed..21570df320950 100644 --- a/components/camel-platform-http-vertx/src/main/docs/platform-http-vertx.adoc +++ b/components/camel-platform-http-vertx/src/main/docs/platform-http-vertx.adoc @@ -42,6 +42,7 @@ header named `orderid` with value `123`. In addition to the implementation of the `PlatformHttp` SPI based on Vert.x, this module provides a Vert.x based HTTP server compatible with the `VertxPlatformHttpEngine`: +._Java-only: programmatic CamelContext and VertxPlatformHttpServer setup_ [source,java] ---- final int port = AvailablePortFinder.getNextAvailable(); @@ -69,6 +70,7 @@ Platform HTTP component can act as a reverse proxy, in that case `Exchange.HTTP_ Here's an example of an HTTP proxy that simply redirects the Exchange to the origin server. +._Java-only: reverse proxy using string concatenation with Exchange constants_ [source,java] ---- from("platform-http:proxy") @@ -81,6 +83,7 @@ from("platform-http:proxy") The Vertx HTTP server has its own API abstraction for HTTP request/response objects which you can access via Camel `HttpMessage` as shown in the custom `Processor` below : +._Java-only: inline Processor accessing Vertx request and response objects_ [source,java] ---- .process(exchange -> { @@ -100,14 +103,46 @@ Camel `HttpMessage` as shown in the custom `Processor` below : When large request / response payloads are expected, there is a `useStreaming` option, which can be enabled to improve performance. When `useStreaming` is `true`, it will take advantage of xref:manual::stream-caching.adoc[stream caching]. In conjunction with enabling disk spooling, you can avoid having to store the entire request body payload in memory. +[tabs] +==== +Java:: ++ [source,java] ---- -// Handle a large request body and stream it to a file from("platform-http:/upload?httpMethodRestrict=POST&useStreaming=true") .log("Processing large request body...") - .to("file:/uploads?fileName=uploaded.txt") + .to("file:/uploads?fileName=uploaded.txt"); ---- +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: platform-http:/upload + parameters: + httpMethodRestrict: POST + useStreaming: true + steps: + - log: + message: "Processing large request body..." + - to: + uri: file:/uploads?fileName=uploaded.txt +---- +==== + NOTE: This requires to upload the content as `application/octet-stream` to leverage streaming mode. You cannot upload using `multipart`. == Setting up http authentication @@ -120,6 +155,7 @@ To set up authentication, you need to create `AuthenticationConfigEntries`, as s This example uses Vert.x https://vertx.io/docs/apidocs/io/vertx/ext/web/handler/BasicAuthHandler.html[BasicAuthHandler] and https://vertx.io/docs/vertx-auth-properties/java/[PropertyFileAuthentication] to configure Basic http authentication with users info stored in `myPropFile.properties` file. Mind that in Vert.x order of adding `AuthenticationHandlers` matters, so `AuthenticationConfigEntries` with a more specific url path are applied first. +._Java-only: programmatic authentication configuration with Vertx handlers_ [source,java] ---- final int port = AvailablePortFinder.getNextAvailable(); diff --git a/components/camel-saxon/src/main/docs/xquery-language.adoc b/components/camel-saxon/src/main/docs/xquery-language.adoc index a42267db1832b..a1bb3c2dcb676 100644 --- a/components/camel-saxon/src/main/docs/xquery-language.adoc +++ b/components/camel-saxon/src/main/docs/xquery-language.adoc @@ -139,6 +139,7 @@ If you have a standard set of namespaces you wish to work with and wish to share them across many XQuery expressions, you can use the `org.apache.camel.support.builder.Namespaces` when using Java DSL as shown: +._Java-only: programmatic namespace configuration with Namespaces builder_ [source,java] ---- Namespaces ns = new Namespaces("c", "http://acme.com/cheese"); @@ -161,6 +162,7 @@ In the XQuery expression then the namespace is used by its prefix, e.g.: The namespace builder supports adding multiple namespaces as shown: +._Java-only: adding multiple namespaces with the Namespaces builder_ [source,java] ---- Namespaces ns = new Namespaces("c", "http://acme.com/cheese") @@ -202,21 +204,53 @@ This namespace uses `foo` as prefix, so the `` expression uses `foo:` to We can do a message translation using transform or setBody in the route, as shown below: +[tabs] +==== +Java:: ++ [source,java] ----------------------------------------- +---- from("direct:start"). transform().xquery("/people/person"); ----------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + /people/person + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - transform: + expression: + xquery: + expression: /people/person +---- +==== Notice that xquery will use DOMResult by default, so if we want to grab the value of the person node, using `text()` we need to tell XQuery to use String as the result type, as shown: +._Java-only: specifying result type with String.class parameter_ [source,java] -------------------------------------------------------------- +---- from("direct:start"). transform().xquery("/people/person/text()", String.class); -------------------------------------------------------------- +---- If you want to use Camel variables like headers, you have to explicitly declare them in the XQuery expression. @@ -238,10 +272,11 @@ such as `"classpath:"`, `"file:"`, or `"http:"`. This is done using the following syntax: `"resource:scheme:location"`, e.g., to refer to a file on the classpath you can do: +._Java-only: loading XQuery script from classpath with class literal_ [source,java] ------------------------------------------------------------------------------- +---- .setHeader("myHeader").xquery("resource:classpath:myxquery.txt", String.class) ------------------------------------------------------------------------------- +---- == Learning XQuery diff --git a/components/camel-xmlsecurity/src/main/docs/xmlSecurity-dataformat.adoc b/components/camel-xmlsecurity/src/main/docs/xmlSecurity-dataformat.adoc index 3ae29e8733387..95c12a890a624 100644 --- a/components/camel-xmlsecurity/src/main/docs/xmlSecurity-dataformat.adoc +++ b/components/camel-xmlsecurity/src/main/docs/xmlSecurity-dataformat.adoc @@ -82,6 +82,7 @@ at the Document, Element, and Content levels. === Full Payload encryption/decryption +._Java-only: full payload encryption using generated AES key_ [source,java] ---------------------------- KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); @@ -96,6 +97,7 @@ from("direct:start") === Partial Payload Content Only encryption/decryption with choice of passPhrase(password) +._Java-only: partial payload encryption with passPhrase_ [source,java] ------------------------------------------------------------------ String tagXPATH = "//cheesesites/italy/cheese"; @@ -110,6 +112,7 @@ from("direct:start") === Partial Payload Content Only encryption/decryption with passPhrase(password) and Algorithm +._Java-only: partial payload encryption with passPhrase and algorithm_ [source,java] ----------------------------------------------------------------------------- import org.apache.xml.security.encryption.XMLCipher; @@ -129,6 +132,7 @@ from("direct:start") [[XMLSecurityDataFormat-JavaDSL]] Java DSL +._Java-only: namespace-aware encryption with asymmetric key and KeyStore_ [source,java] ------------------------------------------------------------------------------------------ final Map namespaces = new HashMap(); From dfd238a99a0964d8e5bf92939e2b2ecc48fa6b1d Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 10:27:37 +0200 Subject: [PATCH 81/87] CAMEL-23789: Make component docs multi-DSL friendly (Wave 1) - batch 4 Components: langchain4j-embeddingstore, atom, aws-security-hub, aws2-comprehend, aws2-polly, bean-validator, elasticsearch-rest-client, flatpack, google-pubsub, hazelcast-replicatedmap, infinispan-embedded, jdbc, jetty, jt400, lucene, olingo2, olingo4, openapi-java, opentelemetry, protobuf, ref, robotframework, sap-netweaver, xquery-component, spel-language, spring-summary, telegram, thrift, xmlsecurity-sign, zookeeper-master Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../langchain4j-embeddingstore-component.adoc | 2 + .../src/main/docs/arangodb-component.adoc | 37 +++++++- .../src/main/docs/atom-component.adoc | 90 ++++++++++++++++++- .../main/docs/aws-security-hub-component.adoc | 4 + .../main/docs/aws2-comprehend-component.adoc | 4 + .../src/main/docs/aws2-polly-component.adoc | 4 + .../main/docs/bean-validator-component.adoc | 5 +- .../elasticsearch-rest-client-component.adoc | 4 + .../src/main/docs/flatpack-component.adoc | 4 + .../main/docs/google-pubsub-component.adoc | 4 + .../hazelcast-replicatedmap-component.adoc | 2 + .../docs/infinispan-embedded-component.adoc | 33 +++++++ .../src/main/docs/jdbc-component.adoc | 43 +++++++++ .../src/main/docs/jetty-component.adoc | 31 +++++++ .../src/main/docs/jt400-component.adoc | 24 ++--- ...s-persistent-volumes-claims-component.adoc | 1 + .../src/main/docs/lucene-component.adoc | 12 ++- .../src/main/docs/olingo2-component.adoc | 74 +++++++++++++-- .../src/main/docs/olingo4-component.adoc | 70 +++++++++++++-- .../src/main/docs/openapi-java.adoc | 4 + .../src/main/docs/opentelemetry.adoc | 4 + .../src/main/docs/protobuf-dataformat.adoc | 5 +- .../src/main/docs/ref-component.adoc | 7 +- .../main/docs/robotframework-component.adoc | 4 + .../src/main/docs/rocketmq-component.adoc | 2 + .../main/docs/sap-netweaver-component.adoc | 24 ++--- .../src/main/docs/xquery-component.adoc | 50 +++++++++-- .../src/main/docs/spel-language.adoc | 4 + .../src/main/docs/spring-summary.adoc | 22 +++-- .../src/main/docs/telegram-component.adoc | 4 + .../src/main/docs/thrift-dataformat.adoc | 54 +++++++++-- .../main/docs/xmlsecurity-sign-component.adoc | 86 ++++++++++++++---- .../main/docs/zookeeper-master-component.adoc | 78 ++++++++++------ 33 files changed, 680 insertions(+), 116 deletions(-) diff --git a/components/camel-ai/camel-langchain4j-embeddingstore/src/main/docs/langchain4j-embeddingstore-component.adoc b/components/camel-ai/camel-langchain4j-embeddingstore/src/main/docs/langchain4j-embeddingstore-component.adoc index 50b9bcb1a41fb..3799f422599fa 100644 --- a/components/camel-ai/camel-langchain4j-embeddingstore/src/main/docs/langchain4j-embeddingstore-component.adoc +++ b/components/camel-ai/camel-langchain4j-embeddingstore/src/main/docs/langchain4j-embeddingstore-component.adoc @@ -58,6 +58,7 @@ include::spring-boot:partial$starter.adoc[] The component requires an `EmbeddingStore` instance. Register it in the Camel registry: +._Java-only: programmatic EmbeddingStore configuration and registry binding_ [source,java] ---- EmbeddingStore embeddingStore = PgVectorEmbeddingStore.builder() @@ -218,6 +219,7 @@ YAML:: A complete example showing document ingestion and retrieval: +._Java-only: multi-route RAG pipeline with split and tokenize_ [source,java] ---- // Ingestion route: chunk, embed, and store documents diff --git a/components/camel-arangodb/src/main/docs/arangodb-component.adoc b/components/camel-arangodb/src/main/docs/arangodb-component.adoc index 8ef5d9f6050b3..0b67f07631716 100644 --- a/components/camel-arangodb/src/main/docs/arangodb-component.adoc +++ b/components/camel-arangodb/src/main/docs/arangodb-component.adoc @@ -95,14 +95,45 @@ myObject.addAttribute("b", 42); ==== Query a collection +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:query") - .to("arangodb:testDb?operation=AQL_QUERY --------------------------------------------------------------------------------- + .to("arangodb:testDb?operation=AQL_QUERY"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:query + steps: + - to: + uri: arangodb:testDb + parameters: + operation: AQL_QUERY +---- +==== And you can invoke an AQL Query in this way +._Java-only: ProducerTemplate with AQL query parameters and string concatenation_ +[source,java] -------------------------------------------------------------------------------- String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.value == @value"; Map bindVars = new MapBuilder().put("value", "hello") diff --git a/components/camel-atom/src/main/docs/atom-component.adoc b/components/camel-atom/src/main/docs/atom-component.adoc index d7964722286d9..2f2a22bfaa4aa 100644 --- a/components/camel-atom/src/main/docs/atom-component.adoc +++ b/components/camel-atom/src/main/docs/atom-component.adoc @@ -35,7 +35,6 @@ for this component: == URI format -[source,java] ------------------------ atom://atomUri[?options] ------------------------ @@ -77,31 +76,118 @@ Camel supports Idempotent Consumer directly within the component, so it will skip already processed entries. This feature is enabled by default, but can be disabled by setting the `idempotent=false` option. +[tabs] +==== +Java:: ++ [source,java] ---- from("file://inbox?idempotent=false").to("..."); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://inbox + parameters: + idempotent: false + steps: + - to: + uri: "..." +---- +==== + The default Idempotency strategy uses Atom published and updated timestamps to identify already read entries, by filtering all entries older that the _last read_ entry. The idempotency strategy can be changed by setting the `idempotentStrategy` option. The components support two -strategies _out-of-the-box_, but custom strategies can be used, by referencing a subclass +strategies _out-of-the-box_, but custom strategies can be used, by referencing a subclass of `org.apache.camel.component.atom.AtomIdempotentStrategy`, with Apache Camel's # notation. +[tabs] +==== +Java:: ++ [source,java] ---- from("file://inbox?idempotentStrategy=#myIdempotentStrategy").to("..."); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://inbox + parameters: + idempotentStrategy: "#myIdempotentStrategy" + steps: + - to: + uri: "..." +---- +==== + ==== Repository idempotent strategy As an alternative to the default idempotent strategy, a repository based strategy can be use: +[tabs] +==== +Java:: ++ [source,java] ---- from("file://inbox?idempotentStrategy=repository").to("..."); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://inbox + parameters: + idempotentStrategy: repository + steps: + - to: + uri: "..." +---- +==== + This strategy checks for idempotency by storing the Atom Entry GUID in an `IdempotentRepository`. The strategy defaults a MemoryIdempotentRepository, but the repository can be changes to any subclass of `IdempotentRepository`, using the `idempotentRepository` option. diff --git a/components/camel-aws/camel-aws-security-hub/src/main/docs/aws-security-hub-component.adoc b/components/camel-aws/camel-aws-security-hub/src/main/docs/aws-security-hub-component.adoc index bcde10dc7956b..96d8a398a2c93 100644 --- a/components/camel-aws/camel-aws-security-hub/src/main/docs/aws-security-hub-component.adoc +++ b/components/camel-aws/camel-aws-security-hub/src/main/docs/aws-security-hub-component.adoc @@ -79,6 +79,7 @@ Camel-AWS Security Hub component provides the following operation on the produce Import security findings into Security Hub. This is the primary way to send findings from custom integrations. +._Java-only: uses inline Processor with AWS SDK builder API_ [source,java] -------------------------------------------------------------------------------- from("direct:importFindings") @@ -110,6 +111,7 @@ from("direct:importFindings") Retrieve security findings from Security Hub with optional filtering. +._Java-only: uses inline Processor with AWS SDK builder API_ [source,java] -------------------------------------------------------------------------------- from("direct:getFindings") @@ -131,6 +133,7 @@ from("direct:getFindings") Update security findings with notes, severity changes, workflow status, etc. +._Java-only: uses inline Processor with AWS SDK builder API and Java constants_ [source,java] -------------------------------------------------------------------------------- from("direct:updateFindings") @@ -205,6 +208,7 @@ YAML:: AWS Security Hub uses the https://schema.ocsf.io/[Open Cybersecurity Schema Framework (OCSF)] for findings. You can use the Camel OCSF DataFormat to work with security events in a vendor-neutral format, then convert them for import into Security Hub. +._Java-only: uses inline Processor with class literal and method reference_ [source,java] -------------------------------------------------------------------------------- from("direct:ocsfToSecurityHub") diff --git a/components/camel-aws/camel-aws2-comprehend/src/main/docs/aws2-comprehend-component.adoc b/components/camel-aws/camel-aws2-comprehend/src/main/docs/aws2-comprehend-component.adoc index 3499d7528dd8f..b2e8f40db1c2d 100644 --- a/components/camel-aws/camel-aws2-comprehend/src/main/docs/aws2-comprehend-component.adoc +++ b/components/camel-aws/camel-aws2-comprehend/src/main/docs/aws2-comprehend-component.adoc @@ -528,6 +528,7 @@ Returns toxicity scores for categories like PROFANITY, HATE_SPEECH, THREAT, INSU For more control, you can pass AWS SDK request objects directly by setting `pojoRequest=true`: +._Java-only: uses lambda expression and AWS SDK request builder API_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:pojoRequest") @@ -543,6 +544,7 @@ from("direct:pojoRequest") You can dynamically set the operation and language code using message headers: +._Java-only: uses Java enum constant for operation header value_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:dynamicOperation") @@ -609,6 +611,7 @@ YAML:: A practical example combining multiple Comprehend operations for content moderation: +._Java-only: uses choice/when/otherwise with inline comments_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:moderateContent") @@ -634,6 +637,7 @@ from("direct:moderateContent") Analyze customer feedback for sentiment and key topics: +._Java-only: uses body() method reference and choice/when/otherwise with inline comments_ [source,java] ------------------------------------------------------------------------------------------------------ from("kafka:customer-feedback") diff --git a/components/camel-aws/camel-aws2-polly/src/main/docs/aws2-polly-component.adoc b/components/camel-aws/camel-aws2-polly/src/main/docs/aws2-polly-component.adoc index c080604edbdf1..7838c38b0a541 100644 --- a/components/camel-aws/camel-aws2-polly/src/main/docs/aws2-polly-component.adoc +++ b/components/camel-aws/camel-aws2-polly/src/main/docs/aws2-polly-component.adoc @@ -87,6 +87,7 @@ Camel-AWS Polly component provides the following operations on the producer side === Synthesize Speech example +._Java-only: uses AWS SDK enum constants for header values_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") @@ -100,6 +101,7 @@ As a result, you'll get an exchange containing the audio stream (InputStream) wi === Using Neural Voices +._Java-only: uses AWS SDK enum constants for header values_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") @@ -154,6 +156,7 @@ YAML:: For long text, you can use asynchronous synthesis which stores the result in S3: +._Java-only: uses Java constants for header names_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") @@ -169,6 +172,7 @@ from("direct:start") Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as the body. In AWS Polly, you can do something like: +._Java-only: uses AWS SDK request builder API_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") diff --git a/components/camel-bean-validator/src/main/docs/bean-validator-component.adoc b/components/camel-bean-validator/src/main/docs/bean-validator-component.adoc index 0fbb166ab8a8c..1b1e050b93a3d 100644 --- a/components/camel-bean-validator/src/main/docs/bean-validator-component.adoc +++ b/components/camel-bean-validator/src/main/docs/bean-validator-component.adoc @@ -76,6 +76,7 @@ Assumed we have a java bean with the following annotations *Car.java* +._Java-only: Java Bean with validation annotations_ [source,java] ----------------------------------------------------------- public class Car { @@ -86,7 +87,7 @@ public class Car { @NotNull @Size(min = 5, max = 14, groups = OptionalChecks.class) private String licensePlate; - + // getter and setter } ----------------------------------------------------------- @@ -95,6 +96,7 @@ and an interface definition for our custom validation group *OptionalChecks.java* +._Java-only: custom validation group interface_ [source,java] --------------------------------- public interface OptionalChecks { @@ -189,6 +191,7 @@ define a new interface first: *AllChecks.java* +._Java-only: combined validation group interface using @GroupSequence_ [source,java] ----------------------------------------------------- @GroupSequence({Default.class, OptionalChecks.class}) diff --git a/components/camel-elasticsearch-rest-client/src/main/docs/elasticsearch-rest-client-component.adoc b/components/camel-elasticsearch-rest-client/src/main/docs/elasticsearch-rest-client-component.adoc index 25e7eb36b1298..5f8fea438ff7d 100644 --- a/components/camel-elasticsearch-rest-client/src/main/docs/elasticsearch-rest-client-component.adoc +++ b/components/camel-elasticsearch-rest-client/src/main/docs/elasticsearch-rest-client-component.adoc @@ -308,11 +308,13 @@ YAML:: To create a new index with some custom settings. +._Java-only: uses a Java String variable for index settings_ [source,java] ---- String indexSettings = "{\"settings\":{\"number_of_replicas\": 1,\"number_of_shards\": 3,\"analysis\": {},\"refresh_interval\": \"1s\"},\"mappings\":{\"dynamic\": false,\"properties\": {\"title\": {\"type\": \"text\", \"analyzer\": \"english\"}}}}"; ---- +._Java-only: route using the indexSettings Java variable_ [source,java] ---- from("direct:createIndex") @@ -409,12 +411,14 @@ YAML:: Search on specific field(s) using `Map`. +._Java-only: creating a search criteria Map_ [source,java] ---- Map criteria = new HashMap<>(); criteria.put("content", "Camel"); ---- +._Java-only: route using the criteria Java variable_ [source,java] ---- from("direct:search") diff --git a/components/camel-flatpack/src/main/docs/flatpack-component.adoc b/components/camel-flatpack/src/main/docs/flatpack-component.adoc index 3fd43bfb6f8a9..ae4792946d592 100644 --- a/components/camel-flatpack/src/main/docs/flatpack-component.adoc +++ b/components/camel-flatpack/src/main/docs/flatpack-component.adoc @@ -63,6 +63,7 @@ value. For example, to get the firstname from the sample below: +._Java-only: accessing row data from the exchange body_ [source,java] ------------------------------------------------ Map row = exchange.getIn().getBody(Map.class); @@ -72,6 +73,7 @@ For example, to get the firstname from the sample below: However, you can also always get it as a `List` (even for `splitRows=true`). The same example: +._Java-only: accessing row data as a List from the exchange body_ [source,java] --------------------------------------------------- List data = exchange.getIn().getBody(List.class); @@ -185,6 +187,7 @@ expected and ignores the extra characters. To use the data format, instantiate an instance and invoke the marshal or unmarshal operation in the route builder: +._Java-only: programmatic FlatpackDataFormat configuration and unmarshal_ [source,java] --------------------------------------------------------------------------- FlatpackDataFormat fp = new FlatpackDataFormat(); @@ -198,6 +201,7 @@ unmarshal the input using the Flatpack configuration file `INVENTORY-Delimited.pzmap.xml` that configures the structure of the files. The result is a `DataSetList` object we store on the SEDA queue. +._Java-only: programmatic FlatpackDataFormat configuration and marshal_ [source,java] ----------------------------------------------------------------------------------- FlatpackDataFormat df = new FlatpackDataFormat(); diff --git a/components/camel-google/camel-google-pubsub/src/main/docs/google-pubsub-component.adoc b/components/camel-google/camel-google-pubsub/src/main/docs/google-pubsub-component.adoc index 69fc8d3bb9903..6baad5b9b1f70 100644 --- a/components/camel-google/camel-google-pubsub/src/main/docs/google-pubsub-component.adoc +++ b/components/camel-google/camel-google-pubsub/src/main/docs/google-pubsub-component.adoc @@ -100,6 +100,7 @@ Without a dead-letter policy, the header will not be set. This allows routes to implement custom retry logic based on the delivery attempt count: +._Java-only: inline Processor with lambda expression accessing delivery attempt header_ [source,java] ---- from("google-pubsub:{{project.name}}:{{subscription.name}}") @@ -186,6 +187,7 @@ All Google components support https://cloud.google.com/iam/docs/workload-identit **With an explicit WIF configuration file:** Set `useWorkloadIdentityFederation=true` and provide the path to the WIF JSON config file via `workloadIdentityConfig`. This is the typical setup for GitHub Actions, AWS, and Azure workloads. +._Java-only: programmatic endpoint configuration for Workload Identity Federation_ [source,java] ---- // GKE with Workload Identity - ADC handles it automatically @@ -200,6 +202,7 @@ endpoint.setWorkloadIdentityConfig("/path/to/wif-config.json"); **With Service Account Impersonation:** Set `impersonatedServiceAccount` to a target service account email. The external credentials obtained via WIF will impersonate that service account, inheriting its permissions. +._Java-only: programmatic endpoint configuration with service account impersonation_ [source,java] ---- // WIF with service account impersonation @@ -220,6 +223,7 @@ By default, the PubSub consumer will acknowledge messages once the exchange has If the _ackMode_ option is set to `NONE`, the component will not acknowledge messages, and it is up to the route to do so. In this case, a `GooglePubsubAcknowledge` object is stored in the header `GooglePubsubConstants.GOOGLE_PUBSUB_ACKNOWLEDGE` and can be used to acknowledge messages: +._Java-only: inline Processor with lambda expression for manual acknowledgement_ [source,java] ---- from("google-pubsub:{{project.name}}:{{subscription.name}}?ackMode=NONE") diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-replicatedmap-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-replicatedmap-component.adoc index b22d87e6a53aa..b0f32dd6b904d 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-replicatedmap-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-replicatedmap-component.adoc @@ -130,6 +130,7 @@ Spring XML:: You can call them in your test class with: +._Java-only: uses ProducerTemplate API and Java constants_ [source,java] ------------------------------------------------------------------------------------------------------------ template.sendBodyAndHeader("direct:[put|get|delete|clear]", "my-foo", HazelcastConstants.OBJECT_ID, "4711"); @@ -142,6 +143,7 @@ variables as for the map cache consumer (except the update and enviction listener). The only difference is the *multimap* prefix inside the URI. Here is a sample: +._Java-only: uses Java constants, string formatting, and choice/when/otherwise_ [source,java] -------------------------------------------------------------------------------------------------- fromF("hazelcast-%sbar", HazelcastConstants.MULTIMAP_PREFIX) diff --git a/components/camel-infinispan/camel-infinispan-embedded/src/main/docs/infinispan-embedded-component.adoc b/components/camel-infinispan/camel-infinispan-embedded/src/main/docs/infinispan-embedded-component.adoc index 0e2430bb5806e..6558416eca3b6 100644 --- a/components/camel-infinispan/camel-infinispan-embedded/src/main/docs/infinispan-embedded-component.adoc +++ b/components/camel-infinispan/camel-infinispan-embedded/src/main/docs/infinispan-embedded-component.adoc @@ -220,6 +220,7 @@ Write methods like put(key, value) and remove(key) do not return the previous va * Put a key/value into a named cache: + +._Java-only: uses InfinispanConstants and InfinispanOperation Java constants_ [source,java] ---- from("direct:start") @@ -233,6 +234,7 @@ from("direct:start") + It is possible to configure the lifetime and/or the idle time before the entry expires and gets evicted from the cache, as example: + +._Java-only: uses InfinispanConstants Java constants and TimeUnit enum_ [source,java] ---- from("direct:start") @@ -247,6 +249,7 @@ from("direct:start") * Queries + +._Java-only: uses InfinispanQueryBuilder anonymous class and Java constants_ [source,java] ---- from("direct:start") @@ -263,11 +266,41 @@ from("direct:start") * Custom Listeners + +[tabs] +==== +Java:: ++ [source,java] ---- from("infinispan://?cacheContainer=#cacheManager&customListener=#myCustomListener") .to("mock:result"); ---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: "infinispan://" + parameters: + cacheContainer: "#cacheManager" + customListener: "#myCustomListener" + steps: + - to: + uri: mock:result +---- +==== + The instance of `myCustomListener` must exist and Camel should be able to look it up from the `Registry`. Users are encouraged to extend the `org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedCustomListener` class and annotate the resulting class with `@Listener` which can be found in the package `org.infinispan.notifications`. diff --git a/components/camel-jdbc/src/main/docs/jdbc-component.adoc b/components/camel-jdbc/src/main/docs/jdbc-component.adoc index 902ed5eef8075..a9fef5192cc89 100644 --- a/components/camel-jdbc/src/main/docs/jdbc-component.adoc +++ b/components/camel-jdbc/src/main/docs/jdbc-component.adoc @@ -149,6 +149,7 @@ map on the headers with the key `CamelJdbcParameters`. In the following example, we set up the DataSource that camel-jdbc requires. First we register our datasource in the Camel registry as `testdb`: +._Java-only: programmatic DataSource registration using EmbeddedDatabaseBuilder_ [source,java] ---- EmbeddedDatabase db = new EmbeddedDatabaseBuilder() @@ -199,6 +200,7 @@ We create an endpoint, add the SQL query to the body of the IN message, and then send the exchange. The result of the query is returned in the _OUT_ body: +._Java-only: using ProducerTemplate to send an exchange to the endpoint_ [source,java] ---- Endpoint endpoint = context.getEndpoint("direct:hello"); @@ -213,6 +215,10 @@ If you want to work on the rows one by one instead of the entire ResultSet at once, you need to use the Splitter EIP such as: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:hello") @@ -225,6 +231,42 @@ from("direct:hello") .to("mock:result"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:hello + steps: + - to: + uri: jdbc:testdb + parameters: + outputType: StreamList + - split: + expression: + body: {} + streaming: true + steps: + - to: + uri: mock:result +---- +==== + === Polling the database every minute If we want to poll a database using the JDBC component, we need to @@ -284,6 +326,7 @@ another data source (ETL operations). In the following example, we retrieve new customer records from the source table every hour, filter/transform them and move them to a destination table: +._Java-only: ETL route using inline Processor to filter and transform results_ [source,java] ---- from("timer://MoveNewCustomersEveryHour?period=3600000") diff --git a/components/camel-jetty/src/main/docs/jetty-component.adoc b/components/camel-jetty/src/main/docs/jetty-component.adoc index 3d593895ccb8b..d4d46c6ec7dd1 100644 --- a/components/camel-jetty/src/main/docs/jetty-component.adoc +++ b/components/camel-jetty/src/main/docs/jetty-component.adoc @@ -330,6 +330,7 @@ Spring `bean` element: Where the processor implementation can access the `HttpSession` as follows: +._Java-only: inline Processor accessing HttpSession_ [source,java] ---- public void process(Exchange exchange) throws Exception { @@ -353,6 +354,7 @@ to use the utility with the Jetty component. [[Jetty-Programmaticconfigurationofthecomponent]] Programmatic configuration of the component +._Java-only: programmatic SSL configuration with KeyStore and SSLContext parameters_ [source,java] ---- KeyStoreParameters ksp = new KeyStoreParameters(); @@ -475,6 +477,7 @@ the port number as entry). Jetty stores a reference to the certificate in the HttpServletRequest which you can access from code as follows: +._Java-only: accessing X509Certificate from HttpServletRequest_ [source,java] ---- HttpServletRequest req = exchange.getIn().getBody(HttpServletRequest.class); @@ -633,11 +636,39 @@ You can configure a list of Jetty handlers as follows: You can then define the endpoint as: +[tabs] +==== +Java:: ++ [source,java] ---- from("jetty:http://0.0.0.0:9080/myservice?handlers=securityHandler"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: jetty:http://0.0.0.0:9080/myservice + parameters: + handlers: securityHandler + steps: + # ... +---- +==== + If you need more handlers, set the `handlers` option equal to a comma-separated list of bean IDs. diff --git a/components/camel-jt400/src/main/docs/jt400-component.adoc b/components/camel-jt400/src/main/docs/jt400-component.adoc index 0e812d5b4be83..341525daa94c0 100644 --- a/components/camel-jt400/src/main/docs/jt400-component.adoc +++ b/components/camel-jt400/src/main/docs/jt400-component.adoc @@ -107,13 +107,14 @@ library `BEATLES` on a system named `LIVERPOOL`. + Another user connects to the same data queue to receive the information from the data queue and forward it to the `mock:ringo` endpoint. +._Java-only: RouteBuilder class definition_ [source,java] ------------------------------------------------------------------------------------------------------- public class Jt400RouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { - from("direct:george").to("jt400://GEORGE:EGROEG@LIVERPOOL/QSYS.LIB/BEATLES.LIB/PENNYLANE.DTAQ"); - from("jt400://RINGO:OGNIR@LIVERPOOL/QSYS.LIB/BEATLES.LIB/PENNYLANE.DTAQ").to("mock:ringo"); + from(“direct:george”).to(“jt400://GEORGE:EGROEG@LIVERPOOL/QSYS.LIB/BEATLES.LIB/PENNYLANE.DTAQ”); + from(“jt400://RINGO:OGNIR@LIVERPOOL/QSYS.LIB/BEATLES.LIB/PENNYLANE.DTAQ”).to(“mock:ringo”); } } ------------------------------------------------------------------------------------------------------- @@ -126,38 +127,40 @@ program “compute” in the library “assets”. This program will write the output values in the second and third parameters. All the parameters will be sent to the direct:play endpoint. +._Java-only: RouteBuilder class definition_ [source,java] --------------------------------------------------------------------------------------------------------------------------------------------------------- public class Jt400RouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { - from("direct:work").to("jt400://GRUPO:ATWORK@server/QSYS.LIB/assets.LIB/compute.PGM?fieldsLength=10,10,512&ouputFieldsIdx=2,3").to("direct:play"); + from(“direct:work”).to(“jt400://GRUPO:ATWORK@server/QSYS.LIB/assets.LIB/compute.PGM?fieldsLength=10,10,512&ouputFieldsIdx=2,3”).to(“direct:play”); } } --------------------------------------------------------------------------------------------------------------------------------------------------------- In this example, the camel route will call the QUSRTVUS API to retrieve -16 bytes from data area "MYUSRSPACE" in the "MYLIB" library. +16 bytes from data area “MYUSRSPACE” in the “MYLIB” library. +._Java-only: RouteBuilder class definition with lambda expression_ [source,java] --------------------------------------------------------------------------------------------------------------------------------------------------------- public class Jt400RouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { - from("timer://foo?period=60000") + from(“timer://foo?period=60000”) .process( exchange -> { - String usrSpc = "MYUSRSPACEMYLIB "; + String usrSpc = “MYUSRSPACEMYLIB “; Object[] parms = new Object[] { usrSpc, // Qualified user space name 1, // starting position 16, // length of data - "" // output + “” // output }; exchange.getIn().setBody(parms); }) - .to("jt400://*CURRENT:*CURRENt@localhost/qsys.lib/QUSRTVUS.PGM?fieldsLength=20,4,4,16&outputFieldsIdx=3") - .setBody(simple("${body[3]}")) - .to("direct:foo"); + .to(“jt400://*CURRENT:*CURRENt@localhost/qsys.lib/QUSRTVUS.PGM?fieldsLength=20,4,4,16&outputFieldsIdx=3”) + .setBody(simple(“${body[3]}”)) + .to(“direct:foo”); } } --------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -310,6 +313,7 @@ YAML:: === Replying to an inquiry message on a message queue +._Java-only: uses Java constants, lambda expression, and choice with header() predicate_ [source,java] ------------------------------------------------------------------------------------------------------- from("jt400://username:password@localhost/qsys.lib/qusrsys.lib/myq.msgq?sendingReply=true") diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc index e839726287e5a..be6bbafa70d6d 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc @@ -43,6 +43,7 @@ include::partial$component-endpoint-headers.adoc[] - `listPersistentVolumesClaims`: this operation lists the PVCs on a kubernetes cluster +._Java-only: uses `toF()` for URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). diff --git a/components/camel-lucene/src/main/docs/lucene-component.adoc b/components/camel-lucene/src/main/docs/lucene-component.adoc index 135b07572da43..e4c09e95869df 100644 --- a/components/camel-lucene/src/main/docs/lucene-component.adoc +++ b/components/camel-lucene/src/main/docs/lucene-component.adoc @@ -83,6 +83,7 @@ Lucene usage samples. === Example 1: Creating a Lucene index +._Java-only: RouteBuilder class definition_ [source,java] ------------------------------------------------------------------------------------ RouteBuilder builder = new RouteBuilder() { @@ -97,6 +98,7 @@ RouteBuilder builder = new RouteBuilder() { === Example 2: Loading properties into the JNDI registry in the Camel Context +._Java-only: programmatic CamelContext and registry configuration_ [source,java] ----------------------------------------------------------------- CamelContext context = new DefaultCamelContext(createRegistry()); @@ -108,6 +110,7 @@ registry.bind("whitespaceAnalyzer", new WhitespaceAnalyzer()); === Example 2: Performing searches using a Query Producer +._Java-only: RouteBuilder with inline Processor and Java constants_ [source,java] ---------------------------------------------------------------------------------------------------- RouteBuilder builder = new RouteBuilder() { @@ -117,7 +120,7 @@ RouteBuilder builder = new RouteBuilder() { to("lucene:searchIndex:query? analyzer=#whitespaceAnalyzer&indexDir=#whitespace&maxHits=20"). to("direct:next"); - + from("direct:next").process(new Processor() { public void process(Exchange exchange) throws Exception { Hits hits = exchange.getIn().getBody(Hits.class); @@ -139,10 +142,11 @@ RouteBuilder builder = new RouteBuilder() { === Example 3: Performing searches using a Query Processor +._Java-only: RouteBuilder with LuceneQueryProcessor and inline Processor_ [source,java] ------------------------------------------------------------------------------------------------------- RouteBuilder builder = new RouteBuilder() { - public void configure() { + public void configure() { try { from("direct:start"). setHeader(LuceneConstants.HEADER_QUERY, constant("Rodney Dangerfield")). @@ -151,13 +155,13 @@ RouteBuilder builder = new RouteBuilder() { } catch (Exception e) { e.printStackTrace(); } - + from("direct:next").process(new Processor() { public void process(Exchange exchange) throws Exception { Hits hits = exchange.getIn().getBody(Hits.class); printResults(hits); } - + private void printResults(Hits hits) { LOG.debug("Number of hits: " + hits.getNumberOfHits()); for (int i = 0; i < hits.getNumberOfHits(); i++) { diff --git a/components/camel-olingo2/camel-olingo2-component/src/main/docs/olingo2-component.adoc b/components/camel-olingo2/camel-olingo2-component/src/main/docs/olingo2-component.adoc index 7f4405010c6df..041843a686e42 100644 --- a/components/camel-olingo2/camel-olingo2-component/src/main/docs/olingo2-component.adoc +++ b/components/camel-olingo2/camel-olingo2-component/src/main/docs/olingo2-component.adoc @@ -124,8 +124,9 @@ the OData resource being queried, created or modified. == Examples The following route reads top 5 entries from the Manufacturer feed -ordered by ascending Name property. +ordered by ascending Name property. +._Java-only: uses setHeader with Java constant_ [source,java] ------------------------------------------------------------ from("direct:...") @@ -134,8 +135,9 @@ from("direct:...") ------------------------------------------------------------ The following route reads Manufacturer entry using the key property -value in incoming *id* header. +value in incoming *id* header. +._Java-only: uses setHeader with header() expression_ [source,java] ------------------------------------------------------------ from("direct:...") @@ -146,11 +148,38 @@ from("direct:...") The following route creates Manufacturer entry using the `java.util.Map` in the body message. +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------- +---- from("direct:...") .to("olingo2://create/Manufacturers"); ------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:... + steps: + - to: + uri: olingo2://create/Manufacturers +---- +==== The following route polls Manufacturer http://olingo.apache.org/doc/tutorials/deltaClient.html[delta @@ -158,13 +187,44 @@ feed] every 30 seconds. The bean *blah* updates the bean *paramsBean* to add an updated *!deltatoken* property with the value returned in the *ODataDeltaFeed* result. Since the initial delta token is not known, the consumer endpoint will produce an *ODataFeed* value the first time, and -*ODataDeltaFeed* on subsequent polls. +*ODataDeltaFeed* on subsequent polls. +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------------------------------------------------------------------- +---- from("olingo2://read/Manufacturers?queryParams=#paramsBean&timeUnit=SECONDS&delay=30") .to("bean:blah"); ---------------------------------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: olingo2://read/Manufacturers + parameters: + queryParams: "#paramsBean" + timeUnit: SECONDS + delay: 30 + steps: + - to: + uri: bean:blah +---- +==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc b/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc index ef7409d3576d1..420f227a95ba1 100644 --- a/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc +++ b/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc @@ -114,8 +114,9 @@ the OData resource being queried, created or modified. == Examples The following route reads top 5 entries from the People entity -ordered by ascending FirstName property. +ordered by ascending FirstName property. +._Java-only: uses setHeader with Java constant_ [source,java] ------------------------------------------------------------ from("direct:...") @@ -124,8 +125,9 @@ from("direct:...") ------------------------------------------------------------ The following route reads Airports entity using the key property -value in incoming *id* header. +value in incoming *id* header. +._Java-only: uses setHeader with header() expression_ [source,java] ------------------------------------------------------------ from("direct:...") @@ -134,22 +136,76 @@ from("direct:...") ------------------------------------------------------------ The following route creates People entity using the -*ClientEntity* in body message. +*ClientEntity* in body message. +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------- +---- from("direct:...") .to("olingo4://create/People"); ------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:... + steps: + - to: + uri: olingo4://create/People +---- +==== The following route calls an odata action using the *ClientEntity* in the body message. The body message may be null for actions that don't expect an input. +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------------------- +---- from("direct:...") .to("olingo4://action/People"); ------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:... + steps: + - to: + uri: olingo4://action/People +---- +==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-openapi-java/src/main/docs/openapi-java.adoc b/components/camel-openapi-java/src/main/docs/openapi-java.adoc index 38f30fb54fedb..61f08ca85c694 100644 --- a/components/camel-openapi-java/src/main/docs/openapi-java.adoc +++ b/components/camel-openapi-java/src/main/docs/openapi-java.adoc @@ -38,6 +38,7 @@ the REST components (without the need for servlet) You can enable the OpenApi api from the rest-dsl by configuring the `apiContextPath` dsl as shown below: +._Java-only: RouteBuilder with Rest DSL configuration and class literals_ [source,java] ---- public class UserRouteBuilder extends RouteBuilder { @@ -138,6 +139,7 @@ to the generated OpenAPI document and not to the actual REST services The Rest DSL now supports declaring OpenApi `securityDefinitions` in the generated API document. For example, as shown below: +._Java-only: Rest DSL security definitions builder API_ [source,java] ---- rest("/user").tag("dude").description("User rest service") @@ -157,6 +159,7 @@ Here we have set up two security definitions Then you need to specify on the rest operations which security to use by referring to their key (petstore_auth or api_key). +._Java-only: Rest DSL security on operations with class literals_ [source,java] ---- .get("/{id}/{date}").description("Find user by id and date").outType(User.class) @@ -188,6 +191,7 @@ By default, the value for these fields is determined by `X-Forwarded` headers, ` This can be overridden by specifying your own host, port & scheme on the REST configuration. +._Java-only: programmatic restConfiguration builder API_ [source,java] ---- restConfiguration().component("netty-http") diff --git a/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc b/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc index 1d612348ed25f..4a3afeaaf5473 100644 --- a/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc +++ b/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc @@ -47,6 +47,7 @@ To explicitly configure OpenTelemetry support, instantiate the `OpenTelemetryTra context. You can optionally specify a `Tracer`, or alternatively it can be implicitly discovered using the `Registry` +._Java-only: programmatic OpenTelemetryTracer configuration_ [source,java] -------------------------------------------------------------------------------------------------- OpenTelemetryTracer otelTracer = new OpenTelemetryTracer(); @@ -135,6 +136,7 @@ as they allow you to export your traces to various backends (e.g., Zipkin and Ja add `io.opentelemetry:opentelemetry-exporter-otlp` as a dependency to your project. To configure it, you can use the `management.otlp.tracing` properties or register a new `SpanExporter` bean yourself: +._Java-only: Spring bean definition for SpanExporter_ [source,java] -------------------------------------------------------------------------------------------------- @Bean @@ -148,6 +150,7 @@ Spring Boot's Actuator will take care of the wiring for you. Alternatively if you just want to log your traces in OTLP JSON format, add `io.opentelemetry:opentelemetry-exporter-logging-otlp` as a dependency to your project and also register a new `SpanExporter` bean: +._Java-only: Spring bean definition for logging SpanExporter_ [source,java] -------------------------------------------------------------------------------------------------- @Bean @@ -171,6 +174,7 @@ or bind it to the Camel registry, where it will be automatically resolved by the Note that care should be taken when configuring parents & links to avoid breaking the relationship between spans & traces. +._Java-only: SpanCustomizer class definition_ [source,java] ---- public class MySpanCustomizer implements SpanCustomizer { diff --git a/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc b/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc index 9cca85783e5be..7f1b1f4902961 100644 --- a/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc +++ b/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc @@ -43,6 +43,7 @@ To use this option, set contentTypeFormat value to `json` or call protobuf with If the default instance is not specified, always use the native protobuf format. The sample code shows below: +._Java-only: programmatic protobuf configuration with content type format_ [source,java] -------------------------------------------------------------------------------------------------- from("direct:marshal") @@ -78,7 +79,7 @@ This is defined in a .proto file as so: *addressbook.proto* -[source,java] +[source,protobuf] ------------------------------------------------------------ syntax = "proto2"; @@ -171,6 +172,7 @@ domain classes. You can use create the ProtobufDataFormat instance and pass it to Camel DataFormat marshal and unmarshal API like this. +._Java-only: programmatic ProtobufDataFormat instantiation_ [source,java] ---- ProtobufDataFormat format = new ProtobufDataFormat(Person.getDefaultInstance()); @@ -182,6 +184,7 @@ DataFormat marshal and unmarshal API like this. Or use the DSL `protobuf()` passing the unmarshal default instance or default instance class name like this. However, if you have input data as `Map` type, you will need to **specify** the ProtobufDataFormat otherwise it will throw an error. +._Java-only: DSL protobuf() with class name and default instance_ [source,java] ---- // You don't need to specify the default instance for protobuf marshaling, but you will need in case your input data is a Map type diff --git a/components/camel-ref/src/main/docs/ref-component.adoc b/components/camel-ref/src/main/docs/ref-component.adoc index 9d82e97bba561..97aadaf4f05e2 100644 --- a/components/camel-ref/src/main/docs/ref-component.adoc +++ b/components/camel-ref/src/main/docs/ref-component.adoc @@ -43,6 +43,7 @@ This component can be used when you need dynamic discovery of endpoints in the Registry where you can compute the URI at runtime. Then you can look up the endpoint using the following code: +._Java-only: programmatic endpoint lookup and producer usage_ [source,java] ---- // lookup the endpoint @@ -59,7 +60,7 @@ producer.process(exchange); With Spring XML, you could have a list of endpoints defined in the Registry such as: -[source,java] +[source,xml] ---- @@ -70,6 +71,8 @@ Registry such as: == Example Bind endpoints to the Camel registry: + +._Java-only: programmatic registry binding_ [source,java] ---- context.getRegistry().bind("endpoint1", context.getEndpoint("direct:start")); @@ -77,6 +80,8 @@ context.getRegistry().bind("endpoint2", context.getEndpoint("log:end")); ---- Use the `ref` URI scheme to refer to endpoint's bond to the Camel registry: + +._Java-only: RouteBuilder class definition_ [source,java] ---- public class MyRefRoutes extends RouteBuilder { diff --git a/components/camel-robotframework/src/main/docs/robotframework-component.adoc b/components/camel-robotframework/src/main/docs/robotframework-component.adoc index c21ddca5e5dba..a0983375f006d 100644 --- a/components/camel-robotframework/src/main/docs/robotframework-component.adoc +++ b/components/camel-robotframework/src/main/docs/robotframework-component.adoc @@ -96,6 +96,7 @@ and pass them to generate a custom report if such need happens It's possible to specify what template the component should use dynamically via a header, so for example: +._Java-only: Java constants for header names_ [source,java] ---- from("direct:in") @@ -108,6 +109,7 @@ with the similar approach how you would be able to pass values using Camel Simple Language. Components support passing values in three different ways. Exchange body, headers, and properties. +._Java-only: Java constants for header names_ [source,java] ---- from("direct:in") @@ -126,6 +128,7 @@ And the `template.robot` file: Should Be True ${myvar} == ${body} ---- +._Java-only: Java constants for header names_ [source,java] ---- from("direct:in") @@ -144,6 +147,7 @@ And the `template.robot` file: Should Be True ${myvar} == ${headers.testHeader} ---- +._Java-only: Java constants for header names_ [source,java] ---- from("direct:in") diff --git a/components/camel-rocketmq/src/main/docs/rocketmq-component.adoc b/components/camel-rocketmq/src/main/docs/rocketmq-component.adoc index 08e647117113b..d54c718804e78 100644 --- a/components/camel-rocketmq/src/main/docs/rocketmq-component.adoc +++ b/components/camel-rocketmq/src/main/docs/rocketmq-component.adoc @@ -66,6 +66,7 @@ When a message from `ReplyToTpic` contains the key, it means that the reply rece If `requestTimeoutMillis` elapsed and no reply received, an exception will be thrown. +._Java-only: uses ExchangePattern.InOut enum and string concatenation for the URI_ [source,java] ---- from("rocketmq:START_TOPIC?producerGroup=p1&consumerGroup=c1") @@ -126,6 +127,7 @@ YAML:: Setting specific headers can change routing behaviour. For example, if header `RocketMQConstants.OVERRIDE_TOPIC_NAME` was set, the message will be sent to `ACTUAL_TARGET` instead of `ORIGIN_TARGET`. +._Java-only: uses inline Processor lambda and RocketMQConstants Java constants_ [source,java] ---- from("rocketmq:FROM?consumerGroup=consumer") diff --git a/components/camel-sap-netweaver/src/main/docs/sap-netweaver-component.adoc b/components/camel-sap-netweaver/src/main/docs/sap-netweaver-component.adoc index 2b86836198749..63b7b7087cf36 100644 --- a/components/camel-sap-netweaver/src/main/docs/sap-netweaver-component.adoc +++ b/components/camel-sap-netweaver/src/main/docs/sap-netweaver-component.adoc @@ -72,10 +72,10 @@ https://sapes4.sapdevcenter.com/sap/opu/odata/IWFND/RMTSAMPLEFLIGHT And we want to execute the following command -[source,java] -------------------------------------------------------------------------------------------------------- +[source,text] +---- FlightCollection(carrid='AA',connid='0017',fldate=datetime'2016-04-20T00%3A00%3A00') -------------------------------------------------------------------------------------------------------- +---- To get flight details for the given flight. The command syntax is in http://msdn.microsoft.com/en-us/library/cc956153.aspx[MS ADO.Net Data @@ -83,24 +83,26 @@ Service] format. We have the following Camel route +._Java-only: route using Java constants and toF() string formatting_ [source,java] ------------------------------------------------------------------------------ +---- from("direct:start") .setHeader(NetWeaverConstants.COMMAND, constant(command)) .toF("sap-netweaver:%s?username=%s&password=%s", url, username, password) .to("log:response") .to("velocity:flight-info.vm") ------------------------------------------------------------------------------ +---- Where `url`, `username`, `password` and `command` are defined as: +._Java-only: Java field definitions_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------------- - private String username = "P1909969254"; - private String password = "TODO"; - private String url = "https://sapes4.sapdevcenter.com/sap/opu/odata/IWFND/RMTSAMPLEFLIGHT"; - private String command = "FlightCollection(carrid='AA',connid='0017',fldate=datetime'2016-04-20T00%3A00%3A00')"; ---------------------------------------------------------------------------------------------------------------------------------------- +---- +private String username = "P1909969254"; +private String password = "TODO"; +private String url = "https://sapes4.sapdevcenter.com/sap/opu/odata/IWFND/RMTSAMPLEFLIGHT"; +private String command = "FlightCollection(carrid='AA',connid='0017',fldate=datetime'2016-04-20T00%3A00%3A00')"; +---- The password is invalid. You would need to create an account at SAP first to run the demo. diff --git a/components/camel-saxon/src/main/docs/xquery-component.adoc b/components/camel-saxon/src/main/docs/xquery-component.adoc index cec88e3aa5dfd..3ae66af22d1f5 100644 --- a/components/camel-saxon/src/main/docs/xquery-component.adoc +++ b/components/camel-saxon/src/main/docs/xquery-component.adoc @@ -25,23 +25,58 @@ include::partial$component-endpoint-headers.adoc[] == Examples +[tabs] +==== +Java:: ++ [source,java] ---------------------------- +---- from("queue:foo") .filter().xquery("//foo") - .to("queue:bar") ---------------------------- + .to("queue:bar"); +---- + +XML:: ++ +[source,xml] +---- + + + + //foo + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: queue:foo + steps: + - filter: + xquery: + expression: //foo + steps: + - to: + uri: queue:bar +---- +==== You can also use functions inside your query, in which case you need an explicit type conversion (otherwise you will get a `org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR`), by passing the Class as a second argument to the *xquery()* method. +._Java-only: xquery() with class literal parameter_ [source,java] ------------------------------------------------------------------------------ +---- from("direct:start") .recipientList().xquery("concat('mock:foo.', /person/@city)", String.class); ------------------------------------------------------------------------------ +---- == Usage @@ -139,10 +174,11 @@ such as `"classpath:"`, `"file:"`, or `"http:"`. This is done using the following syntax: `"resource:scheme:location"`, e.g., to refer to a file on the classpath you can do: +._Java-only: setHeader with xquery() and class literal_ [source,java] ------------------------------------------------------------------------------- +---- .setHeader("myHeader").xquery("resource:classpath:myxquery.txt", String.class) ------------------------------------------------------------------------------- +---- === Learning XQuery diff --git a/components/camel-spring-parent/camel-spring/src/main/docs/spel-language.adoc b/components/camel-spring-parent/camel-spring/src/main/docs/spel-language.adoc index f77eeea84703a..a3f6c974c3cc4 100644 --- a/components/camel-spring-parent/camel-spring/src/main/docs/spel-language.adoc +++ b/components/camel-spring-parent/camel-spring/src/main/docs/spel-language.adoc @@ -106,6 +106,7 @@ template language. For example, if you construct the following route: +._Java-only: static method import for spel expression_ [source,java] ---- from("direct:example") @@ -119,6 +120,7 @@ use `spel` as an Expression passed in as a parameter to the `setBody` method. Though if we use the fluent API, we can do this instead: +._Java-only: fluent API for spel expression_ [source,java] ---- from("direct:example") @@ -132,6 +134,7 @@ this does not require us to statically import the `spel` method. Then we send a message with the string "World" in the body, and a header `dayOrNight` with value `day`: +._Java-only: ProducerTemplate usage_ [source,java] ---- template.sendBodyAndHeader("direct:example", "World", "dayOrNight", "day"); @@ -160,6 +163,7 @@ such as `"classpath:"`, `"file:"`, or `"http:"`. This is done using the following syntax: `"resource:scheme:location"`, e.g., to refer to a file on the classpath you can do: +._Java-only: fluent API for loading SpEL from resource_ [source,java] ---- .setHeader("myHeader").spel("resource:classpath:myspel.txt") diff --git a/components/camel-spring-parent/camel-spring/src/main/docs/spring-summary.adoc b/components/camel-spring-parent/camel-spring/src/main/docs/spring-summary.adoc index 9b4a9d251b0ff..4730b226a8977 100644 --- a/components/camel-spring-parent/camel-spring/src/main/docs/spring-summary.adoc +++ b/components/camel-spring-parent/camel-spring/src/main/docs/spring-summary.adoc @@ -198,8 +198,9 @@ the Spring `` feature and have Camel pickup any This allows you to just annotate your routes using the Spring `@Component` and have those routes included by Camel +._Java-only: Spring component-scanned RouteBuilder class definition_ [source,java] -------------------------------------------------- +---- @Component public class MyRoute extends SpringRouteBuilder { @@ -208,7 +209,7 @@ public class MyRoute extends SpringRouteBuilder { from("direct:start").to("mock:result"); } } -------------------------------------------------- +---- You can also use the ant style for inclusion and exclusion, as mentioned above in the `` documentation. @@ -311,15 +312,16 @@ to allow this. It provides two methods (`excludeRoute` and `excludeRoutes`) that may be overridden to exclude a single class or an array of classes. +._Java-only: test class with route exclusion_ [source,java] ----------------------------------------------------------------- +---- public class RouteAandRouteBOnlyTest extends SpringTestSupport { - @Override + @Override protected Class excludeRoute() { return RouteC.class; } } ----------------------------------------------------------------- +---- To hook into the camelContext initialization by spring to exclude the class `MyExcludedRouteBuilder`, we need to intercept the spring @@ -328,25 +330,27 @@ spring context, we call the `getRouteExcludingApplicationContext()` method to provide a special parent spring context that takes care of the exclusion. +._Java-only: overriding Spring application context for route exclusion_ [source,java] --------------------------------------------------------------------------------------------------------------------------- +---- @Override protected AbstractXmlApplicationContext createApplicationContext() { return new ClassPathXmlApplicationContext(new String[] {"routes-context.xml"}, getRouteExcludingApplicationContext()); } --------------------------------------------------------------------------------------------------------------------------- +---- `RouteC` will now be excluded from initialization. Similarly, in another test that is testing only `RouteC`, we could exclude RouteB and RouteA by overriding the method `excludeRoutes`. +._Java-only: excluding multiple route classes_ [source,java] ---------------------------------------------------- +---- @Override protected Class[] excludeRoutes() { return new Class[]{RouteA.class, RouteB.class}; } ---------------------------------------------------- +---- == Using Spring XML diff --git a/components/camel-telegram/src/main/docs/telegram-component.adoc b/components/camel-telegram/src/main/docs/telegram-component.adoc index 1aff4dedec349..30d5fe9b82eb8 100644 --- a/components/camel-telegram/src/main/docs/telegram-component.adoc +++ b/components/camel-telegram/src/main/docs/telegram-component.adoc @@ -186,6 +186,7 @@ YAML:: The `MyBean` is a simple bean that will receive the messages +._Java-only: bean class definition_ [source,java] --------------------------------------------------------- public class MyBean { @@ -265,6 +266,7 @@ YAML:: The `ChatBotLogic` is a simple bean that implements a generic String-to-String method. +._Java-only: bean class definition_ [source,java] --------------------------------------------------------- public class ChatBotLogic { @@ -383,6 +385,7 @@ Note that the corresponding URI parameter is simply `chatId`. You can customize the user keyboard instead of asking him to write an option. `OutgoingTextMessage` has the property `ReplyMarkup` which can be used for such a thing. +._Java-only: inline Processor with keyboard builder API_ [source,java] --------------------------------------------------------- from("telegram:bots?authorizationToken=123456789:insertYourAuthorizationTokenHere") @@ -417,6 +420,7 @@ from("telegram:bots?authorizationToken=123456789:insertYourAuthorizationTokenHer If you want to disable it, the next message must have the property `removeKeyboard` set on `ReplyKeyboardMarkup` object. +._Java-only: inline Processor with keyboard removal_ [source,java] --------------------------------------------------------- from("telegram:bots?authorizationToken=123456789:insertYourAuthorizationTokenHere") diff --git a/components/camel-thrift/src/main/docs/thrift-dataformat.adoc b/components/camel-thrift/src/main/docs/thrift-dataformat.adoc index 37022d9f657ea..56cf42304daeb 100644 --- a/components/camel-thrift/src/main/docs/thrift-dataformat.adoc +++ b/components/camel-thrift/src/main/docs/thrift-dataformat.adoc @@ -34,6 +34,10 @@ If the default instance is not specified, always use the native binary Thrift fo The simple JSON format is write-only (marshal) and produces a simple output format suitable for parsing by scripting languages. The sample code shows below: +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:marshal") @@ -42,6 +46,36 @@ from("direct:marshal") .to("mock:reverse"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:marshal + steps: + - unmarshal: + thrift: + instanceClass: org.apache.camel.dataformat.thrift.generated.Work + contentTypeFormat: json + - to: + uri: mock:reverse +---- +==== + == Thrift overview This quick overview of how to use Thrift. @@ -98,26 +132,28 @@ org.apache.thrift.TBase. You can use create the ThriftDataFormat instance and pass it to Camel DataFormat marshal and unmarshal API like this. +._Java-only: programmatic ThriftDataFormat instance_ [source,java] ---- - ThriftDataFormat format = new ThriftDataFormat(new Work()); +ThriftDataFormat format = new ThriftDataFormat(new Work()); - from("direct:in").marshal(format); - from("direct:back").unmarshal(format).to("mock:reverse"); +from("direct:in").marshal(format); +from("direct:back").unmarshal(format).to("mock:reverse"); ---- Or use the DSL thrift() passing the unmarshal default instance or default instance class name like this. +._Java-only: DSL thrift() with class name and instance parameters_ [source,java] ---- - // You don't need to specify the default instance for the thrift marshaling - from("direct:marshal").marshal().thrift(); - from("direct:unmarshalA").unmarshal() - .thrift("org.apache.camel.dataformat.thrift.generated.Work") - .to("mock:reverse"); +// You don't need to specify the default instance for the thrift marshaling +from("direct:marshal").marshal().thrift(); +from("direct:unmarshalA").unmarshal() + .thrift("org.apache.camel.dataformat.thrift.generated.Work") + .to("mock:reverse"); - from("direct:unmarshalB").unmarshal().thrift(new Work()).to("mock:reverse"); +from("direct:unmarshalB").unmarshal().thrift(new Work()).to("mock:reverse"); ---- The following example shows how to use Thrift to unmarshal: diff --git a/components/camel-xmlsecurity/src/main/docs/xmlsecurity-sign-component.adoc b/components/camel-xmlsecurity/src/main/docs/xmlsecurity-sign-component.adoc index e1792d6469caa..7b567610004a3 100644 --- a/components/camel-xmlsecurity/src/main/docs/xmlsecurity-sign-component.adoc +++ b/components/camel-xmlsecurity/src/main/docs/xmlsecurity-sign-component.adoc @@ -190,22 +190,46 @@ between different signer/verifier endpoints within the camel context. The following example shows the basic usage of the component. +[tabs] +==== +Java:: ++ [source,java] ---- -from("direct:enveloping").to("xmlsecurity-sign://enveloping?keyAccessor=#accessor", - "xmlsecurity-verify://enveloping?keySelector=#selector", - "mock:result") +from("direct:enveloping") + .to("xmlsecurity-sign://enveloping?keyAccessor=#accessor") + .to("xmlsecurity-verify://enveloping?keySelector=#selector") + .to("mock:result"); ---- -In Spring XML: - +XML:: ++ [source,xml] ---- - - - - + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:enveloping + steps: + - to: + uri: "xmlsecurity-sign://enveloping?keyAccessor=#accessor" + - to: + uri: "xmlsecurity-verify://enveloping?keySelector=#selector" + - to: + uri: mock:result ---- +==== For the signing process, a private key is necessary. You specify a key accessor bean which provides this private key. For the validation, the @@ -367,6 +391,10 @@ element `A`. *Java DSL Example* +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:detached") @@ -375,11 +403,39 @@ from("direct:detached") .to("mock:result"); ---- -*Spring Example* +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:detached + steps: + - to: + uri: "xmlsecurity-sign://detached?keyAccessor=#keyAccessorBean&xpathsToIdAttributes=#xpathsToIdAttributesBean&schemaResourceUri=Test.xsd" + - to: + uri: "xmlsecurity-verify://detached?keySelector=#keySelectorBean&schemaResourceUri=Test.xsd" + - to: + uri: mock:result +---- +==== + +*Spring Bean Configuration Example* [source,xml] ---- - @@ -397,13 +453,6 @@ from("direct:detached") -... - - - - ---- @@ -469,6 +518,7 @@ can just omit them. *XAdES-BES/EPES Example in Java DSL* +._Java-only: programmatic XAdES signature properties configuration_ [source,java] ---- Keystore keystore = ... // load a keystore diff --git a/components/camel-zookeeper-master/src/main/docs/zookeeper-master-component.adoc b/components/camel-zookeeper-master/src/main/docs/zookeeper-master-component.adoc index 3bfacad0f58b3..c78371e88feea 100644 --- a/components/camel-zookeeper-master/src/main/docs/zookeeper-master-component.adoc +++ b/components/camel-zookeeper-master/src/main/docs/zookeeper-master-component.adoc @@ -84,27 +84,52 @@ include::partial$component-endpoint-headers.adoc[] You can protect a clustered Camel application to only consume files from one active node. - +[tabs] +==== +Java:: ++ [source,java] ---- - // the file endpoint we want to consume from - String url = "file:target/inbox?delete=true"; +from("zookeeper-master:myGroup:file:target/inbox?delete=true") + .log(name + " - Received file: ${file:name}") + .delay(delay) + .log(name + " - Done file: ${file:name}") + .to("file:target/outbox"); +---- - // use the zookeeper master component in the clustered group named myGroup - // to run a master/slave mode in the following Camel url - from("zookeeper-master:myGroup:" + url) - .log(name + " - Received file: ${file:name}") - .delay(delay) - .log(name + " - Done file: ${file:name}") - .to("file:target/outbox"); +XML:: ++ +[source,xml] +---- + + + + + ---- +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: zookeeper-master:myGroup:file:target/inbox?delete=true + steps: + - log: + message: "${file:name}" + - to: + uri: file:target/outbox +---- +==== + ZooKeeper will by default connect to `localhost:2181`, but you can configure this on the component level. +._Java-only: programmatic component configuration_ [source,java] ---- - MasterComponent master = new MasterComponent(); - master.setZooKeeperUrl("myzookeeper:2181"); +MasterComponent master = new MasterComponent(); +master.setZooKeeperUrl("myzookeeper:2181"); ---- However, you can also configure the url of the ZooKeeper ensemble using environment variables. @@ -126,22 +151,23 @@ When doing so, you must configure the route policy with A little example +._Java-only: programmatic RoutePolicy configuration_ [source,java] ---- - MasterRoutePolicy master = new MasterRoutePolicy(); - master.setZooKeeperUrl("localhost:2181"); - master.setGroupName("myGroup"); - - // its import to set the route to not auto startup - // as we let the route policy start/stop the routes when it becomes a master/slave, etc. - from("file:target/inbox?delete=true").noAutoStartup() - // use the zookeeper master route policy in the clustered group - // to run this route in master/slave mode - .routePolicy(master) - .log(name + " - Received file: ${file:name}") - .delay(delay) - .log(name + " - Done file: ${file:name}") - .to("file:target/outbox"); +MasterRoutePolicy master = new MasterRoutePolicy(); +master.setZooKeeperUrl("localhost:2181"); +master.setGroupName("myGroup"); + +// its import to set the route to not auto startup +// as we let the route policy start/stop the routes when it becomes a master/slave, etc. +from("file:target/inbox?delete=true").noAutoStartup() + // use the zookeeper master route policy in the clustered group + // to run this route in master/slave mode + .routePolicy(master) + .log(name + " - Received file: ${file:name}") + .delay(delay) + .log(name + " - Done file: ${file:name}") + .to("file:target/outbox"); ---- From 636653c36d9220360af6d8eae5d87c6e58a446d1 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 10:31:28 +0200 Subject: [PATCH 82/87] CAMEL-23789: Make component docs multi-DSL friendly (Wave 1) - batch 5 Components: langchain4j-embeddingstore, arangodb, cassandraql, consul, ehcache, exec, flatpack-dataformat, jgroups-raft, jpa, quartz, rocketmq, rss, servlet, sjms2, smb, smpp, splunk-hec, velocity, weather, whatsapp, kubernetes-persistent-volumes-claims, kubernetes-persistent-volumes, kubernetes-resources-quota, kubernetes-service-accounts, openshift-build-configs, openshift-builds, aws2-kinesis-firehose, aws2-mq, aws2-timestream, aws2-translate, azure-files, camunda, github2, google-bigquery-sql, snakeyaml, thymeleaf, wasm, xmlsecurity-verify, zipDeflater, zookeeper, attachments, kamelet, leveldb, master, parquet-avro Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/attachments.adoc | 3 + .../docs/aws2-kinesis-firehose-component.adoc | 1 + .../src/main/docs/aws2-mq-component.adoc | 4 +- .../main/docs/aws2-timestream-component.adoc | 2 + .../main/docs/aws2-translate-component.adoc | 2 + .../src/main/docs/azure-files-component.adoc | 58 +++++++++++++++ .../src/main/docs/camunda-component.adoc | 2 + .../src/main/docs/cql-component.adoc | 2 + .../src/main/docs/consul-component.adoc | 2 + .../src/main/docs/ehcache-component.adoc | 4 +- .../src/main/docs/exec-component.adoc | 2 + .../src/main/docs/flatpack-dataformat.adoc | 2 + .../src/main/docs/github2-component.adoc | 32 +++++++++ .../docs/google-bigquery-sql-component.adoc | 2 + .../src/main/docs/jgroups-raft-component.adoc | 41 +++++++++-- .../src/main/docs/jpa-component.adoc | 2 + .../src/main/docs/kamelet-component.adoc | 2 + ...s-persistent-volumes-claims-component.adoc | 1 + ...bernetes-persistent-volumes-component.adoc | 2 + .../kubernetes-resources-quota-component.adoc | 2 + ...kubernetes-service-accounts-component.adoc | 2 + .../openshift-build-configs-component.adoc | 2 + .../main/docs/openshift-builds-component.adoc | 2 + .../camel-leveldb/src/main/docs/leveldb.adoc | 3 + .../src/main/docs/master-component.adoc | 3 +- .../src/main/docs/parquetAvro-dataformat.adoc | 2 + .../src/main/docs/quartz-component.adoc | 70 +++++++++++++++++-- .../src/main/docs/rss-component.adoc | 2 + .../src/main/docs/servlet-component.adoc | 30 ++++++++ .../src/main/docs/sjms2-component.adoc | 28 ++++++++ .../src/main/docs/smb-component.adoc | 2 + .../src/main/docs/smpp-component.adoc | 2 + .../src/main/docs/snakeYaml-dataformat.adoc | 6 +- .../src/main/docs/splunk-hec-component.adoc | 28 ++++++++ .../src/main/docs/thymeleaf-component.adoc | 2 + .../src/main/docs/velocity-component.adoc | 2 + .../src/main/docs/wasm-language.adoc | 3 +- .../src/main/docs/weather-component.adoc | 2 + .../src/main/docs/whatsapp-component.adoc | 4 +- .../docs/xmlsecurity-verify-component.adoc | 41 +++++++++++ .../src/main/docs/zipDeflater-dataformat.adoc | 4 +- .../src/main/docs/zookeeper-component.adoc | 2 + 42 files changed, 392 insertions(+), 18 deletions(-) diff --git a/components/camel-attachments/src/main/docs/attachments.adoc b/components/camel-attachments/src/main/docs/attachments.adoc index 5cd8c5cf15953..35938dec10259 100644 --- a/components/camel-attachments/src/main/docs/attachments.adoc +++ b/components/camel-attachments/src/main/docs/attachments.adoc @@ -16,6 +16,7 @@ The Attachments component is included automatically when using these components. The Attachments support is on Camel `Message` level, for example to get the `javax.activation.DataHandler` instance of the attachment, you can do as shown below: +._Java-only: retrieving an attachment via Exchange API_ [source,java] ---- AttachmentMessage attMsg = exchange.getIn(AttachmentMessage.class); @@ -24,6 +25,8 @@ DataHandler dh = attachment.getDataHandler(); ---- And if you want to add an attachment, to a Camel `Message` you can do as shown: + +._Java-only: adding an attachment via Exchange API_ [source,java] ---- AttachmentMessage attMsg = exchange.getIn(AttachmentMessage.class); diff --git a/components/camel-aws/camel-aws2-kinesis/src/main/docs/aws2-kinesis-firehose-component.adoc b/components/camel-aws/camel-aws2-kinesis/src/main/docs/aws2-kinesis-firehose-component.adoc index 3e10f5da78fa6..478ad322b8fe9 100644 --- a/components/camel-aws/camel-aws2-kinesis/src/main/docs/aws2-kinesis-firehose-component.adoc +++ b/components/camel-aws/camel-aws2-kinesis/src/main/docs/aws2-kinesis-firehose-component.adoc @@ -150,6 +150,7 @@ Camel-AWS s3 component provides the following operation on the producer side: You can send an iterable of Kinesis Record (as the following example shows), or you can send directly a PutRecordBatchRequest POJO instance in the body. +._Java-only: uses ProducerTemplate, inline Processor, and AWS SDK builders_ [source,java] -------------------------------------------------------------------------------------------------------------------- @Test diff --git a/components/camel-aws/camel-aws2-mq/src/main/docs/aws2-mq-component.adoc b/components/camel-aws/camel-aws2-mq/src/main/docs/aws2-mq-component.adoc index d2f3336184162..c23969573121c 100644 --- a/components/camel-aws/camel-aws2-mq/src/main/docs/aws2-mq-component.adoc +++ b/components/camel-aws/camel-aws2-mq/src/main/docs/aws2-mq-component.adoc @@ -123,6 +123,7 @@ YAML:: - createBroker: this operation will create an MQ Broker in AWS +._Java-only: uses inline Processor, Java constants, and AWS SDK builders_ [source,java] -------------------------------------------------------------------------------- from("direct:createBroker") @@ -141,7 +142,7 @@ from("direct:createBroker") user.password("camelpwd"); users.add(user.build()); exchange.getIn().setHeader(MQ2Constants.BROKER_USERS, users); - + } }) .to("aws2-mq://test?amazonMqClient=#amazonMqClient&operation=createBroker") @@ -242,6 +243,7 @@ YAML:: Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as the body. In AWS MQ, there are multiple operations you can submit, as an example for List brokers request, you can do something like: +._Java-only: uses AWS SDK POJO request builder as message body_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:aws2-mq") diff --git a/components/camel-aws/camel-aws2-timestream/src/main/docs/aws2-timestream-component.adoc b/components/camel-aws/camel-aws2-timestream/src/main/docs/aws2-timestream-component.adoc index 28d07a4e52244..18b9253d09d79 100644 --- a/components/camel-aws/camel-aws2-timestream/src/main/docs/aws2-timestream-component.adoc +++ b/components/camel-aws/camel-aws2-timestream/src/main/docs/aws2-timestream-component.adoc @@ -233,6 +233,7 @@ In AWS Timestream there are multiple operations you can submit, as an example fo * Write Operation ** createDatabase: this operation will create a timestream database +._Java-only: uses AWS SDK POJO request builder as message body_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") @@ -243,6 +244,7 @@ from("direct:start") * Query Operation ** query: this operation will execute a timestream query +._Java-only: uses AWS SDK POJO request builder as message body_ [source,java] -------------------------------------------------------------------------------- from("direct:query") diff --git a/components/camel-aws/camel-aws2-translate/src/main/docs/aws2-translate-component.adoc b/components/camel-aws/camel-aws2-translate/src/main/docs/aws2-translate-component.adoc index 5c6708d1f1b7b..c6bf8efe8f059 100644 --- a/components/camel-aws/camel-aws2-translate/src/main/docs/aws2-translate-component.adoc +++ b/components/camel-aws/camel-aws2-translate/src/main/docs/aws2-translate-component.adoc @@ -79,6 +79,7 @@ Camel-AWS Translate component provides the following operation on the producer s === Translate Text example +._Java-only: uses Java constants for header names and enum values_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") @@ -95,6 +96,7 @@ As a result, you'll get an exchange containing the translated text. Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as the body. In AWS Translate, the only operation available is TranslateText, so you can do something like: +._Java-only: uses AWS SDK POJO request builder as message body_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") diff --git a/components/camel-azure/camel-azure-files/src/main/docs/azure-files-component.adoc b/components/camel-azure/camel-azure-files/src/main/docs/azure-files-component.adoc index 1586c066aae09..a4cda73ff04d2 100644 --- a/components/camel-azure/camel-azure-files/src/main/docs/azure-files-component.adoc +++ b/components/camel-azure/camel-azure-files/src/main/docs/azure-files-component.adoc @@ -226,11 +226,40 @@ the local file is deleted. So if you want to download files from a remote files server and store it as local files, then you need to route to a file endpoint such as: +[tabs] +==== +Java:: ++ [source,java] ---- from("azure-files://...&localWorkDirectory=/tmp").to("file://inbox"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: azure-files://... + parameters: + localWorkDirectory: /tmp + steps: + - to: + uri: file://inbox +---- +==== + [TIP] ==== The route above is ultra efficient as it avoids reading the entire file content into memory. @@ -278,11 +307,40 @@ The file paths are matched with the following rules: The sample below demonstrates how to use it: +[tabs] +==== +Java:: ++ [source,java] ---- from("azure-files://...&antInclude=**/*.txt").to("..."); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: azure-files://... + parameters: + antInclude: "**/*.txt" + steps: + - to: + uri: "..." +---- +==== + === Using a Proxy Consult the https://learn.microsoft.com/en-us/azure/developer/java/sdk/proxying[underlying library] diff --git a/components/camel-camunda/src/main/docs/camunda-component.adoc b/components/camel-camunda/src/main/docs/camunda-component.adoc index f0ef14e42ae47..74a37192278a1 100644 --- a/components/camel-camunda/src/main/docs/camunda-component.adoc +++ b/components/camel-camunda/src/main/docs/camunda-component.adoc @@ -60,6 +60,7 @@ include::partial$component-endpoint-headers.adoc[] Set the `clusterId`, `clientId`, `clientSecret`, and `region` component options. +._Java-only: programmatic component configuration_ [source,java] ---------------------------------------------------------------------------------------------------------------------- CamundaComponent camunda = context.getComponent("camunda", CamundaComponent.class); @@ -74,6 +75,7 @@ camunda.setRegion("bru-2"); Set the `grpcAddress` and `restAddress` component options. For authenticated self-managed clusters, also set `clientId`, `clientSecret`, and `oAuthAPI`. +._Java-only: programmatic component configuration_ [source,java] ---------------------------------------------------------------------------------------------------------------------- CamundaComponent camunda = context.getComponent("camunda", CamundaComponent.class); diff --git a/components/camel-cassandraql/src/main/docs/cql-component.adoc b/components/camel-cassandraql/src/main/docs/cql-component.adoc index ca11c56eb85b0..2fc7536bc4056 100644 --- a/components/camel-cassandraql/src/main/docs/cql-component.adoc +++ b/components/camel-cassandraql/src/main/docs/cql-component.adoc @@ -186,6 +186,7 @@ This could be accomplished by changing the deserializationFilter field in the re To insert something on a table, you can use the following code: +._Java-only: route with CQL query string concatenation_ [source,java] --------------------------------------------------------- String CQL = "insert into camel_user(login, first_name, last_name) values (?, ?, ?)"; @@ -195,6 +196,7 @@ from("direct:input") At this point, you should be able to insert data by using a list as body +._Java-only: creating a parameter list for CQL binding_ [source,java] --------------------------------------------------------- Arrays.asList("davsclaus", "Claus", "Ibsen"); diff --git a/components/camel-consul/src/main/docs/consul-component.adoc b/components/camel-consul/src/main/docs/consul-component.adoc index 800fd70ad051d..65c6700a31b8f 100644 --- a/components/camel-consul/src/main/docs/consul-component.adoc +++ b/components/camel-consul/src/main/docs/consul-component.adoc @@ -78,6 +78,7 @@ Which producer action invoked by which consul api is defined by the respective p E.g., the `ConsulAgentProducer` maps `ConsulAgentActions.REGISTER` to an invocation of `AgentClient.register`. ==== +._Java-only: route using ImmutableRegistration builder and Java constants_ [source,java] ---- from("direct:registerFooService") @@ -101,6 +102,7 @@ consul:agent?action=REGISTER You can employ a `ServiceRegistrationRoutePolicy` to register Camel routes as services with Consul automatically. +._Java-only: route with programmatic routePolicy and Java constants_ [source,java] ---- from("jetty:http://0.0.0.0:8080/service/endpoint").routeId("foo-1") diff --git a/components/camel-ehcache/src/main/docs/ehcache-component.adoc b/components/camel-ehcache/src/main/docs/ehcache-component.adoc index 531f3f9a95a1c..c229772bddccb 100644 --- a/components/camel-ehcache/src/main/docs/ehcache-component.adoc +++ b/components/camel-ehcache/src/main/docs/ehcache-component.adoc @@ -49,11 +49,12 @@ include::partial$component-endpoint-headers.adoc[] === Ehcache based idempotent repository example: +._Java-only: programmatic CacheManager and idempotent repository configuration_ [source,java] ------------------------------------------------------------------------------------------------ CacheManager manager = CacheManagerBuilder.newCacheManager(new XmlConfiguration("ehcache.xml")); EhcacheIdempotentRepository repo = new EhcacheIdempotentRepository(manager, "idempotent-cache"); - + from("direct:in") .idempotentConsumer(header("messageId"), idempotentRepo) .to("mock:out"); @@ -63,6 +64,7 @@ from("direct:in") === Ehcache based aggregation repository example: +._Java-only: full test class with aggregation repository configuration_ [source,java] --------------------------------------------------------------------------------------------------------------------------------- public class EhcacheAggregationRepositoryRoutesTest extends CamelTestSupport { diff --git a/components/camel-exec/src/main/docs/exec-component.adoc b/components/camel-exec/src/main/docs/exec-component.adoc index 16e77db269af0..bbc66ac73ff0c 100644 --- a/components/camel-exec/src/main/docs/exec-component.adoc +++ b/components/camel-exec/src/main/docs/exec-component.adoc @@ -91,6 +91,7 @@ The example below executes `wc` (word count, Linux) to count the words in file `/usr/share/dict/words`. The word count (_output_) is written to the standard output stream of `wc`: +._Java-only: route with inline Processor to handle ExecResult_ [source,java] -------------------------------------------------------------------------------------- from("direct:exec") @@ -234,6 +235,7 @@ used as the _out file_ with `outFile=CamelExecOutFile.txt`. The example assumes that `ant.bat` is in the system path, and that `CamelExecBuildFile.xml` is in the current directory. +._Java-only: route with inline Processor to handle output file_ [source,java] ------------------------------------------------------------------------------------------------------- from("direct:exec") diff --git a/components/camel-flatpack/src/main/docs/flatpack-dataformat.adoc b/components/camel-flatpack/src/main/docs/flatpack-dataformat.adoc index 13285418b0a6c..086ca54a4ca8d 100644 --- a/components/camel-flatpack/src/main/docs/flatpack-dataformat.adoc +++ b/components/camel-flatpack/src/main/docs/flatpack-dataformat.adoc @@ -38,6 +38,7 @@ include::partial$dataformat-options.adoc[] To use the data format, instantiate an instance and invoke the marshal or unmarshal operation in the route builder: +._Java-only: programmatic FlatpackDataFormat configuration and unmarshal_ [source,java] --------------------------------------------------------------------------- FlatpackDataFormat fp = new FlatpackDataFormat(); @@ -51,6 +52,7 @@ unmarshal the input using the Flatpack configuration file `INVENTORY-Delimited.pzmap.xml` that configures the structure of the files. The result is a `DataSetList` object we store on the SEDA queue. +._Java-only: programmatic FlatpackDataFormat configuration and marshal_ [source,java] ----------------------------------------------------------------------------------- FlatpackDataFormat df = new FlatpackDataFormat(); diff --git a/components/camel-github2/src/main/docs/github2-component.adoc b/components/camel-github2/src/main/docs/github2-component.adoc index 10432ec10f96a..c6773159f9252 100644 --- a/components/camel-github2/src/main/docs/github2-component.adoc +++ b/components/camel-github2/src/main/docs/github2-component.adoc @@ -67,6 +67,7 @@ The GitHub2 component requires to be configured with an authentication token on For example, to set it on the component: +._Java-only: programmatic component configuration_ [source,java] ---- GitHub2Component ghc = context.getComponent("github2", GitHub2Component.class); @@ -77,12 +78,43 @@ ghc.setOauthToken("mytoken"); To use with GitHub Enterprise, set the `apiUrl` parameter to your GitHub Enterprise API endpoint: +[tabs] +==== +Java:: ++ [source,java] ---- from("github2:commit/main?repoOwner=myorg&repoName=myrepo&apiUrl=https://github.mycompany.com/api/v3") .to("log:commits"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: github2:commit/main + parameters: + repoOwner: myorg + repoName: myrepo + apiUrl: "https://github.mycompany.com/api/v3" + steps: + - to: + uri: log:commits +---- +==== + === Consumer Endpoints [width="100%",cols="20%,20%,60%",options="header",] diff --git a/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-sql-component.adoc b/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-sql-component.adoc index 72082b6227e36..15c7873f6f02f 100644 --- a/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-sql-component.adoc +++ b/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-sql-component.adoc @@ -51,6 +51,7 @@ https://developers.google.com/identity/protocols/application-default-credentials When you have the **service account key** you can provide authentication credentials to your application code. Google security credentials can be set through the component endpoint: +._Java-only: endpoint URI as Java string variable_ [source,java] -------------------------------------------------------- String endpoint = "google-bigquery-sql://project-id:query?serviceAccountKey=/home/user/Downloads/my-key.json"; @@ -58,6 +59,7 @@ String endpoint = "google-bigquery-sql://project-id:query?serviceAccountKey=/hom You can also use the base64 encoded content of the authentication credentials file if you don't want to set a file system path. +._Java-only: endpoint URI as Java string variable_ [source,java] -------------------------------------------------------- String endpoint = "google-bigquery-sql://project-id:query?serviceAccountKey=base64:"; diff --git a/components/camel-jgroups-raft/src/main/docs/jgroups-raft-component.adoc b/components/camel-jgroups-raft/src/main/docs/jgroups-raft-component.adoc index b32b9d8a96813..b59f204483233 100644 --- a/components/camel-jgroups-raft/src/main/docs/jgroups-raft-component.adoc +++ b/components/camel-jgroups-raft/src/main/docs/jgroups-raft-component.adoc @@ -131,12 +131,40 @@ The snippet below demonstrates how to create the consumer endpoint listening to the change role events. By default, this option is off. +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------------------------------- -... -from("jgroups-raft:clusterName?enableRoleChangeEvents=true").to(mock:mockEndpoint); -... ---------------------------------------------------------------------- +---- +from("jgroups-raft:clusterName?enableRoleChangeEvents=true") + .to("mock:mockEndpoint"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: jgroups-raft:clusterName + parameters: + enableRoleChangeEvents: true + steps: + - to: + uri: mock:mockEndpoint +---- +==== === Keeping singleton route within the cluster @@ -147,6 +175,7 @@ particular example, we want to keep singleton xref:jetty-component.adoc[jetty] instance listening for the requests on address` http://localhost:8080/orders`. +._Java-only: programmatic JGroupsRaftClusterService configuration_ [source,java] ----------------------------------------------------------------------------------------------------------------------------------------------------------------- JGroupsRaftClusterService service = new JGroupsRaftClusterService(); @@ -156,7 +185,7 @@ service.setJgroupsClusterName("clusterName"); ... context.addService(service); -from("master:mycluster:jetty:http://localhost:8080/orders").to("jms:orders"); +from("master:mycluster:jetty:http://localhost:8080/orders").to("jms:orders"); ----------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/components/camel-jpa/src/main/docs/jpa-component.adoc b/components/camel-jpa/src/main/docs/jpa-component.adoc index a7d82ad5b6381..e5b485af8ad84 100644 --- a/components/camel-jpa/src/main/docs/jpa-component.adoc +++ b/components/camel-jpa/src/main/docs/jpa-component.adoc @@ -158,6 +158,7 @@ For consuming only selected entities, you can use the `namedQuery` URI query option. First, you have to define the named query in the JPA Entity class: +._Java-only: JPA entity class definition with @NamedQuery annotation_ [source,java] ---------------------------------------------------------------------------------- @Entity @@ -295,6 +296,7 @@ For retrieving selected entities or execute bulk update/delete, you can use the `namedQuery` URI query option. First, you have to define the named query in the JPA Entity class: +._Java-only: JPA entity class definition with @NamedQuery annotation_ [source,java] ---------------------------------------------------------------------------------- @Entity diff --git a/components/camel-kamelet/src/main/docs/kamelet-component.adoc b/components/camel-kamelet/src/main/docs/kamelet-component.adoc index 8bc917089ecd5..69b39c7157e56 100644 --- a/components/camel-kamelet/src/main/docs/kamelet-component.adoc +++ b/components/camel-kamelet/src/main/docs/kamelet-component.adoc @@ -158,6 +158,7 @@ WARNING: beware of any potential circular reference you may introduce when using _Kamelets_ can be used as if they were standard Camel components. For example, suppose that we have created a Route Template as follows: +._Java-only: programmatic route template definition_ [source,java] ---- routeTemplate("setMyBody") @@ -216,6 +217,7 @@ Behind the scenes, the *Kamelet* component does the following things: If you had to do it programmatically, it would have been something like: +._Java-only: programmatic TemplatedRouteBuilder usage_ [source,java] ---- routeTemplate("setMyBody") diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc index be6bbafa70d6d..f3136fa3f60ae 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc @@ -55,6 +55,7 @@ This operation returns a list of PVC from your cluster - `listPersistentVolumesClaimsByLabels`: this operation lists the PVCs by labels on a kubernetes cluster +._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-component.adoc index a7a609dae0c44..512e7cacf2485 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-component.adoc @@ -40,6 +40,7 @@ include::partial$component-endpoint-headers.adoc[] - `listPersistentVolumes`: this operation lists the PVs on a kubernetes cluster +._Java-only: uses `toF()` for URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -51,6 +52,7 @@ This operation returns a list of PVs from your cluster - `listPersistentVolumesByLabels`: this operation lists the PVs by labels on a kubernetes cluster +._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-resources-quota-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-resources-quota-component.adoc index de6f292aaca3c..d02abadcb0681 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-resources-quota-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-resources-quota-component.adoc @@ -43,6 +43,7 @@ include::partial$component-endpoint-headers.adoc[] - `listResourcesQuota`: this operation lists the resource quotas on a kubernetes cluster +._Java-only: uses `toF()` for URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -54,6 +55,7 @@ This operation returns a list of resource quotas from your cluster - `listResourcesQuotaByLabels`: this operation lists the resource quotas by labels on a kubernetes cluster +._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-service-accounts-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-service-accounts-component.adoc index 0ba263946243e..8ada83af537ff 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-service-accounts-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-service-accounts-component.adoc @@ -43,6 +43,7 @@ include::partial$component-endpoint-headers.adoc[] - `listServiceAccounts`: this operation lists the SAs on a kubernetes cluster +._Java-only: uses `toF()` for URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -54,6 +55,7 @@ This operation returns a list of services from your cluster - `listServiceAccountsByLabels`: this operation lists the SAs by labels on a kubernetes cluster +._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { diff --git a/components/camel-kubernetes/src/main/docs/openshift-build-configs-component.adoc b/components/camel-kubernetes/src/main/docs/openshift-build-configs-component.adoc index fa7a79cf3e8dc..5fd0c74104349 100644 --- a/components/camel-kubernetes/src/main/docs/openshift-build-configs-component.adoc +++ b/components/camel-kubernetes/src/main/docs/openshift-build-configs-component.adoc @@ -40,6 +40,7 @@ include::partial$component-endpoint-headers.adoc[] - `listBuilds`: this operation lists the build configs on an Openshift cluster +._Java-only: uses `toF()` for URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -51,6 +52,7 @@ This operation returns a list of builds from your Openshift cluster - `listBuildsByLabels`: this operation lists the build configs by labels on an Openshift cluster +._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { diff --git a/components/camel-kubernetes/src/main/docs/openshift-builds-component.adoc b/components/camel-kubernetes/src/main/docs/openshift-builds-component.adoc index bd93b02533ffd..7b7db1603761e 100644 --- a/components/camel-kubernetes/src/main/docs/openshift-builds-component.adoc +++ b/components/camel-kubernetes/src/main/docs/openshift-builds-component.adoc @@ -40,6 +40,7 @@ include::partial$component-endpoint-headers.adoc[] - `listBuilds`: this operation lists the builds on an Openshift cluster +._Java-only: uses `toF()` for URI formatting_ [source,java] -------------------------------------------------------------------------------- from("direct:list"). @@ -51,6 +52,7 @@ This operation returns a List of Builds from your Openshift cluster - `listBuildsByLabels`: this operation lists the builds by labels on an Openshift cluster +._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] -------------------------------------------------------------------------------- from("direct:listByLabels").process(new Processor() { diff --git a/components/camel-leveldb/src/main/docs/leveldb.adoc b/components/camel-leveldb/src/main/docs/leveldb.adoc index 453d090ae593f..00620e8d93334 100644 --- a/components/camel-leveldb/src/main/docs/leveldb.adoc +++ b/components/camel-leveldb/src/main/docs/leveldb.adoc @@ -146,6 +146,8 @@ You can use serialization via Jackson (using json). Jackson's serialization brings better performance, but also several limitations. Example of jackson serialization: + +._Java-only: programmatic Jackson serializer configuration_ [source,java] ---------------------------------------- LevelDBAggregationRepository repo = ...; //initialization of repository @@ -158,6 +160,7 @@ Limitation of jackson serializer is caused by binary data: * If payload contains objects with binary fields. Those fields won't be serialized/deserialized correctly. Customized serializer can be used to solve this problem. Please use custom serializer with Jackson by providing own Module: +._Java-only: custom Jackson module with serializer and deserializer_ [source,java] ---------------------------------------- SimpleModule simpleModule = new SimpleModule(); diff --git a/components/camel-master/src/main/docs/master-component.adoc b/components/camel-master/src/main/docs/master-component.adoc index 2b95dbd58f193..f2567a64fffcd 100644 --- a/components/camel-master/src/main/docs/master-component.adoc +++ b/components/camel-master/src/main/docs/master-component.adoc @@ -89,7 +89,7 @@ TIP: Apache ActiveMQ 5.x has such a feature out of the box called https://active You can protect a clustered Camel application to only consume files from one active node. - +._Java-only: string concatenation to build the master endpoint URI_ [source,java] ---- // the file endpoint we want to consume from @@ -108,6 +108,7 @@ The master component leverages CamelClusterService you can configure using * *Java* + +._Java-only: programmatic ZooKeeperClusterService configuration_ [source,java] ---- ZooKeeperClusterService service = new ZooKeeperClusterService(); diff --git a/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc b/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc index 3e8113d6ccd11..9d74b3d3cf8a0 100644 --- a/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc +++ b/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc @@ -31,6 +31,7 @@ There are ways to unmarshal parquet files/structures, usually binary parquet fil In this first example we unmarshal file payload to OutputStream and send it to mock endpoint, then we will be able to get GenericRecord or POJO (it could be a list if that is coming through) +._Java-only: unmarshal with a local parquet data format variable_ [source,java] ----------------------------------------------------------------------- from("direct:unmarshal").unmarshal(parquet).to("mock:unmarshal"); @@ -40,6 +41,7 @@ from("direct:unmarshal").unmarshal(parquet).to("mock:unmarshal"); Marshalling is the reverse process of unmarshalling, so when you have your `GenericRecord` or POJO and marshal it, you will get the parquet-formatted output stream on your producer endpoint. +._Java-only: marshal with a local parquet data format variable_ [source,java] ----------------------------------------------------------------------- from("direct:marshal").marshal(parquet).to("mock:marshal"); diff --git a/components/camel-quartz/src/main/docs/quartz-component.adoc b/components/camel-quartz/src/main/docs/quartz-component.adoc index 85c1c65e47c01..65587643ff380 100644 --- a/components/camel-quartz/src/main/docs/quartz-component.adoc +++ b/components/camel-quartz/src/main/docs/quartz-component.adoc @@ -386,21 +386,83 @@ IMPORTANT: Remember that configuring these options from the endpoint URIs must be prefixed with `scheduler.`. For example, to configure the trigger id and group: +[tabs] +==== +Java:: ++ [source,java] ---- - from("file:inbox?scheduler=quartz&scheduler.cron=0/2+*+*+*+*+?&scheduler.triggerId=myId&scheduler.triggerGroup=myGroup") - .to("bean:process"); +from("file:inbox?scheduler=quartz&scheduler.cron=0/2+*+*+*+*+?&scheduler.triggerId=myId&scheduler.triggerGroup=myGroup") + .to("bean:process"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] ---- +- route: + from: + uri: file:inbox + parameters: + scheduler: quartz + scheduler.cron: "0/2 * * * * ?" + scheduler.triggerId: myId + scheduler.triggerGroup: myGroup + steps: + - to: + uri: bean:process +---- +==== There is also a CRON scheduler in Spring, so you can use the following as well: +[tabs] +==== +Java:: ++ [source,java] ---- - from("file:inbox?scheduler=spring&scheduler.cron=0/2+*+*+*+*+?") - .to("bean:process"); +from("file:inbox?scheduler=spring&scheduler.cron=0/2+*+*+*+*+?") + .to("bean:process"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file:inbox + parameters: + scheduler: spring + scheduler.cron: "0/2 * * * * ?" + steps: + - to: + uri: bean:process +---- +==== + === Cron Component Support The Quartz component can be used as implementation of the Camel Cron component. diff --git a/components/camel-rss/src/main/docs/rss-component.adoc b/components/camel-rss/src/main/docs/rss-component.adoc index 68e0c8093aa29..b2a3c1bff0c28 100644 --- a/components/camel-rss/src/main/docs/rss-component.adoc +++ b/components/camel-rss/src/main/docs/rss-component.adoc @@ -160,6 +160,7 @@ YAML:: The custom bean for this would be: +._Java-only: bean class definition with annotations and type casts_ [source,java] ---- public static class FilterBean { @@ -182,6 +183,7 @@ Instead of directly using `from("rss:...")`, you can configure an HTTP client wi Below is an example that sets up an HTTP client with a proxy (including authentication support) and uses it to retrieve and process an RSS feed: +._Java-only: programmatic proxy configuration with HttpClientConfigurer, registry binding, and RouteBuilder class_ [source,java] ---- protected RoutesBuilder createRouteBuilder() throws Exception { diff --git a/components/camel-servlet/src/main/docs/servlet-component.adoc b/components/camel-servlet/src/main/docs/servlet-component.adoc index 6e242ffb47894..50017e3726308 100644 --- a/components/camel-servlet/src/main/docs/servlet-component.adoc +++ b/components/camel-servlet/src/main/docs/servlet-component.adoc @@ -188,6 +188,7 @@ For example, to define a route that exposes an HTTP service under the path `/ser === Example route +._Java-only: inline Processor with Exchange API and string concatenation_ [source,java] ------------------------------------------------------------------------- from("servlet:hello").process(new Processor() { @@ -277,11 +278,40 @@ In this scenario, you *must* define a custom and unique servlet name in each of In your Camel servlet endpoints, include the servlet name: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------- from("servlet://foo?servletName=MyServlet") --------------------------------------------------- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: servlet://foo + parameters: + servletName: MyServlet + steps: + - to: + uri: direct:businessLogic +---- +==== + Camel detects duplicate Servlet names and will fail to start the application. You can control and ignore such duplicates by setting the servlet init parameter `ignoreDuplicateServletName` to `true` as diff --git a/components/camel-sjms2/src/main/docs/sjms2-component.adoc b/components/camel-sjms2/src/main/docs/sjms2-component.adoc index 5c9be045895ee..2a09e32ab51bf 100644 --- a/components/camel-sjms2/src/main/docs/sjms2-component.adoc +++ b/components/camel-sjms2/src/main/docs/sjms2-component.adoc @@ -150,6 +150,7 @@ part of the JMS endpoint URL, but it will be ignored in this example. In the `computeDestination` bean, specify the real destination by setting the `CamelJmsDestinationName` header as follows: +._Java-only: programmatic header manipulation with Exchange API_ [source,java] ------------------------------------------------------------------------- public void setJmsHeader(Exchange exchange) { @@ -178,12 +179,39 @@ For example, suppose you need to send messages to queues with order types, then using toD could, for example, be done as follows: .Example SJMS2 route with `toD` +[tabs] +==== +Java:: ++ [source,java] -------------------------------- from("direct:order") .toD("sjms2:order-${header.orderType}"); -------------------------------- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:order + steps: + - toD: + uri: "sjms2:order-${header.orderType}" +---- +==== + === Local transactions When using `transacted=true` then JMS Transacted Acknowledge Mode are in use. diff --git a/components/camel-smb/src/main/docs/smb-component.adoc b/components/camel-smb/src/main/docs/smb-component.adoc index 2bd6d888c48c1..78424bb9a02ee 100644 --- a/components/camel-smb/src/main/docs/smb-component.adoc +++ b/components/camel-smb/src/main/docs/smb-component.adoc @@ -49,6 +49,7 @@ For the SMB producer to operate correctly, the header `Exchange.FILE_NAME` has t For instance, polling all the files from an SMB file share and reading their contents would look like this: +._Java-only: uses fromF with string formatting and method reference Processor_ [source,java] ---- private void process(Exchange exchange) throws IOException { @@ -71,6 +72,7 @@ NOTE: you may also get the file contents as an InputStream using `exchange.getMe You can also get access to the file using the underlying `File` implementation provided by Camel. In that case, polling all the files from an SMB file share and reading their contents would look like this: +._Java-only: uses SmbFile class, type casts, fromF with string formatting, and method reference Processor_ [source,java] ---- private void process(Exchange exchange) throws IOException { diff --git a/components/camel-smpp/src/main/docs/smpp-component.adoc b/components/camel-smpp/src/main/docs/smpp-component.adoc index f4df332704099..ee1d117302826 100644 --- a/components/camel-smpp/src/main/docs/smpp-component.adoc +++ b/components/camel-smpp/src/main/docs/smpp-component.adoc @@ -199,6 +199,7 @@ code to the SMSC. This feature is useful to e.g., instruct the SMSC to resend the short message at a later time. This could be done with the following lines of code: +._Java-only: uses doTry/doCatch with Exception.class literal and ProcessRequestException constructor_ [source,java] -------------------------------------------------------------------------------------------------------------------------- from("smpp://smppclient@localhost:2775?password=password&enquireLinkTimer=3000&transactionTimer=5000&systemType=consumer") @@ -296,6 +297,7 @@ YAML:: An example of using transceiver (TRX) binding type: +._Java-only: multi-route definition with string concatenation and route id assignment_ [source,java] -------------------------------------------------------------------------------------------------------------------------- from("direct:start") diff --git a/components/camel-snakeyaml/src/main/docs/snakeYaml-dataformat.adoc b/components/camel-snakeyaml/src/main/docs/snakeYaml-dataformat.adoc index e34f0d111619e..190a38aabd86b 100644 --- a/components/camel-snakeyaml/src/main/docs/snakeYaml-dataformat.adoc +++ b/components/camel-snakeyaml/src/main/docs/snakeYaml-dataformat.adoc @@ -71,7 +71,8 @@ YAML DSL:: uri: mqseries:Another.Queue ---- ==== -+ + +._Java-only: selecting the SnakeYAML library explicitly_ [source,java] ------------------------------------------------------------ from("activemq:My.Queue") @@ -80,7 +81,8 @@ from("activemq:My.Queue") ------------------------------------------------------------ - Restrict classes to be loaded from YAML -+ + +._Java-only: programmatic type filter configuration_ [source,java] ------------------------------------------------------------ // Creat a SnakeYAMLDataFormat instance diff --git a/components/camel-splunk-hec/src/main/docs/splunk-hec-component.adoc b/components/camel-splunk-hec/src/main/docs/splunk-hec-component.adoc index 365e58a75feae..f142811160a86 100644 --- a/components/camel-splunk-hec/src/main/docs/splunk-hec-component.adoc +++ b/components/camel-splunk-hec/src/main/docs/splunk-hec-component.adoc @@ -100,6 +100,7 @@ If you are ingesting a large enough dataset with a big enough lag, then the time the event hits the server and when that event actually happened could be skewed. If you want to override the index time, you can do so. +._Java-only: uses SplunkHECConstants.INDEX_TIME Java constant_ [source,java] ------------------------------- from("kafka:logs") @@ -107,12 +108,39 @@ from("kafka:logs") .to("splunk-hec://localhost:8080?token=token"); ------------------------------- +[tabs] +==== +Java:: ++ [source,java] ------------------------------- from("kafka:logs") .toD("splunk-hec://localhost:8080?token=token&time=${headers[kafka.HEADERS].lastKey('TIME')}"); ------------------------------- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: kafka:logs + steps: + - toD: + uri: "splunk-hec://localhost:8080?token=token&time=${headers[kafka.HEADERS].lastKey('TIME')}" +---- +==== + include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc b/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc index 60297319c8cc2..293b7aafb6bd1 100644 --- a/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc +++ b/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc @@ -97,6 +97,7 @@ The `Exchange` is transferred as: You can set up a custom Thymeleaf Context yourself by setting property `allowTemplateFromHeader=true` and setting the message header `CamelThymeleafContext` like this +._Java-only: programmatic Thymeleaf context setup via Exchange API_ [source,java] ----------------------------------------------------------------------- EngineContext engineContext = new EngineContext(variableMap); @@ -403,6 +404,7 @@ Regards Camel Riders Bookstore And the java code (from a unit test): +._Java-only: unit test with Exchange creation and RouteBuilder_ [source,java] ---- private Exchange createLetter() { diff --git a/components/camel-velocity/src/main/docs/velocity-component.adoc b/components/camel-velocity/src/main/docs/velocity-component.adoc index 67bf614aa1f2c..27ba5f6b20f0f 100644 --- a/components/camel-velocity/src/main/docs/velocity-component.adoc +++ b/components/camel-velocity/src/main/docs/velocity-component.adoc @@ -100,6 +100,7 @@ The `Exchange` is transferred as: You can set up a custom Velocity Context yourself by setting property `allowTemplateFromHeader=true` and setting the message header `CamelVelocityContext` just like this +._Java-only: programmatic VelocityContext creation and header manipulation_ [source,java] ----------------------------------------------------------------------- VelocityContext velocityContext = new VelocityContext(variableMap); @@ -406,6 +407,7 @@ ${body} And the java code (from an unit test): +._Java-only: unit test with Exchange API, ProducerTemplate, MockEndpoint assertions, and RouteBuilder class_ [source,java] ---- private Exchange createLetter() { diff --git a/components/camel-wasm/src/main/docs/wasm-language.adoc b/components/camel-wasm/src/main/docs/wasm-language.adoc index 50325d6de10f7..15d33fcad99e5 100644 --- a/components/camel-wasm/src/main/docs/wasm-language.adoc +++ b/components/camel-wasm/src/main/docs/wasm-language.adoc @@ -61,6 +61,7 @@ data exchange leverages Wasm's memory that can be accessed by both the host and At this stage, the data structure that the component exchange with the Wasm function is a subset of the Apache Camel Message, containing headers the body encoded as a base64 string: +._Java-only: data wrapper class definition_ [source,java] ------------------------------------------------- public static class Wrapper { @@ -131,7 +132,7 @@ pub extern fn transform(ptr: u32, len: u32) -> u64 { Supposing we have compiled a Wasm module containing the function above, then it can be called in a Camel Route by its name and module resource location: - +._Java-only: programmatic CamelContext and FluentProducerTemplate usage_ [source,java] --------------------------------------- try (CamelContext cc = new DefaultCamelContext()) { diff --git a/components/camel-weather/src/main/docs/weather-component.adoc b/components/camel-weather/src/main/docs/weather-component.adoc index 64626110bcbe6..f2f002befaad4 100644 --- a/components/camel-weather/src/main/docs/weather-component.adoc +++ b/components/camel-weather/src/main/docs/weather-component.adoc @@ -183,6 +183,7 @@ YAML:: And we can send in a message with a header to get the weather for any location as shown: +._Java-only: ProducerTemplate API usage_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------- String json = template.requestBodyAndHeader("direct:start", "", "CamelWeatherLocation", "Paris,France&appid=APIKEY", String.class); @@ -190,6 +191,7 @@ String json = template.requestBodyAndHeader("direct:start", "", "CamelWeatherLoc And to get the weather at the current location, then: +._Java-only: ProducerTemplate API usage_ [source,java] -------------------------------------------------------------------------------------------------------------------------------- String json = template.requestBodyAndHeader("direct:start", "", "CamelWeatherLocation", "current&appid=APIKEY", String.class); diff --git a/components/camel-whatsapp/src/main/docs/whatsapp-component.adoc b/components/camel-whatsapp/src/main/docs/whatsapp-component.adoc index 4377ad4f1836b..84cc704438810 100644 --- a/components/camel-whatsapp/src/main/docs/whatsapp-component.adoc +++ b/components/camel-whatsapp/src/main/docs/whatsapp-component.adoc @@ -66,6 +66,7 @@ Business Cloud API. in Java DSL +._Java-only: inline Processor lambda with TextMessageRequest construction_ [source,java] --------------------------------------------------------- from("direct:start") @@ -74,7 +75,7 @@ from("direct:start") request.setTo(insertYourRecipientPhoneNumberHere); request.setText(new TextMessage()); request.getText().setBody("This is an auto-generated message from Camel \uD83D\uDC2B"); - + exchange.getIn().setBody(request); }) .to("whatsapp:123456789:insertYourPhoneNumberIdHere?authorizationToken=123456789:insertYourAuthorizationTokenHere"); @@ -100,6 +101,7 @@ Once done, you need to prepend the webhook URI to the whatsapp URI you want to u In Java DSL: +._Java-only: uses fromF with string formatting_ [source,java] --------------------------------------------------------- fromF("webhook:whatsapp:%s?authorizationToken=%s&webhookVerifyToken=%s", "", "", "").log("${body}") diff --git a/components/camel-xmlsecurity/src/main/docs/xmlsecurity-verify-component.adoc b/components/camel-xmlsecurity/src/main/docs/xmlsecurity-verify-component.adoc index 0887366d755a7..152b662d1b5c4 100644 --- a/components/camel-xmlsecurity/src/main/docs/xmlsecurity-verify-component.adoc +++ b/components/camel-xmlsecurity/src/main/docs/xmlsecurity-verify-component.adoc @@ -328,6 +328,10 @@ element `A`. *Java DSL Example* +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:detached") @@ -336,6 +340,42 @@ from("direct:detached") .to("mock:result"); ---- +XML:: ++ +[source,xml] +---- + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:detached + steps: + - to: + uri: xmlsecurity-sign://detached + parameters: + keyAccessor: "#keyAccessorBeant" + xpathsToIdAttributes: "#xpathsToIdAttributesBean" + schemaResourceUri: Test.xsd + - to: + uri: xmlsecurity-verify://detached + parameters: + keySelector: "#keySelectorBean" + schemaResourceUri: org/apache/camel/component/xmlsecurity/Test.xsd + - to: + uri: mock:result +---- +==== + *Spring Example* [source,xml] @@ -428,6 +468,7 @@ can just omit them. *XAdES-BES/EPES Example in Java DSL* +._Java-only: programmatic XAdES signature properties configuration_ [source,java] ---- Keystore keystore = ... // load a keystore diff --git a/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc b/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc index 58ef86317e1eb..2c8146744569a 100644 --- a/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc +++ b/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc @@ -38,6 +38,7 @@ In this example we marshal a regular text/XML payload to a compressed payload employing zip compression `Deflater.BEST_COMPRESSION` and send it an ActiveMQ queue called MY_QUEUE. +._Java-only: specifying compression level via Java constant_ [source,java] ---- from("direct:start").marshal().zipDeflater(Deflater.BEST_COMPRESSION).to("activemq:queue:MY_QUEUE"); @@ -89,9 +90,10 @@ the UnZippedMessageProcessor. Note that the compression Level employed during marshaling should be identical to the one employed during unmarshalling to avoid errors. +._Java-only: inline Processor instance_ [source,java] ---- -from("activemq:queue:MY_QUEUE").unmarshal().zipDeflater().process(new UnZippedMessageProcessor()); +from("activemq:queue:MY_QUEUE").unmarshal().zipDeflater().process(new UnZippedMessageProcessor()); ---- == Dependencies diff --git a/components/camel-zookeeper/src/main/docs/zookeeper-component.adoc b/components/camel-zookeeper/src/main/docs/zookeeper-component.adoc index 2fa4382a25c58..3a13a65720593 100644 --- a/components/camel-zookeeper/src/main/docs/zookeeper-component.adoc +++ b/components/camel-zookeeper/src/main/docs/zookeeper-component.adoc @@ -190,6 +190,7 @@ not to `/somepath/somenode` but to the path from the header WARNING: the `testPayload` must be convertible to `byte[]` as the data stored in ZooKeeper is byte-based. +._Java-only: ProducerTemplate with dynamic znode header_ [source,java] ---- Object testPayload = ... @@ -334,6 +335,7 @@ or using the header `CamelZookeeperCreateMode`. WARNING: the `testPayload` must be convertible to `byte[]` as the data stored in ZooKeeper is byte-based. +._Java-only: ProducerTemplate with create mode header_ [source,java] ---- Object testPayload = ... From bf58524e097016ffa55e10894752a985e64ec63e Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 10:39:28 +0200 Subject: [PATCH 83/87] CAMEL-23789: Make component docs multi-DSL friendly (Wave 1) - batch 6 Components: rest-openapi, pubnub, lpr, ocsf, nats, mail-microsoft-oauth, jasypt, jackson3, graphql, groovy, git, datasonnet, crypto-dataformat, pgp, azure-servicebus, azure-eventhubs, aws2-msk, a2a, wal, threadpoolfactory-vertx, paho, paho-mqtt5, openapi-validator, ognl, mvel, milo, microprofile-health, micrometer-observability, mdc, mimeMultipart, gzipDeflater, xslt-saxon, wordpress, web3j, vertx, thrift-component Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/a2a-component.adoc | 3 + .../src/main/docs/aws2-msk-component.adoc | 7 +- .../main/docs/azure-eventhubs-component.adoc | 3 + .../main/docs/azure-servicebus-component.adoc | 3 + .../src/main/docs/pgp-dataformat.adoc | 23 +-- .../src/main/docs/crypto-dataformat.adoc | 3 + .../src/main/docs/datasonnet-language.adoc | 4 +- .../src/main/docs/git-component.adoc | 33 +++- .../src/main/docs/graphql-component.adoc | 3 + .../src/main/docs/groovy-language.adoc | 3 + .../src/main/docs/jackson3-dataformat.adoc | 3 + .../camel-jasypt/src/main/docs/jasypt.adoc | 1 + .../src/main/docs/mail-microsoft-oauth.adoc | 3 + .../main/docs/mimeMultipart-dataformat.adoc | 2 + components/camel-mdc/src/main/docs/mdc.adoc | 2 + .../main/docs/micrometer-observability.adoc | 5 + .../src/main/docs/microprofile-health.adoc | 3 + .../src/main/docs/milo-client-component.adoc | 2 + .../src/main/docs/mvel-language.adoc | 2 + .../src/main/docs/nats-component.adoc | 3 + .../src/main/docs/ocsf-dataformat.adoc | 51 ++++++ .../src/main/docs/ognl-language.adoc | 2 + .../src/main/docs/openapi-validator.adoc | 2 + .../src/main/docs/paho-mqtt5-component.adoc | 2 + .../src/main/docs/paho-component.adoc | 2 + .../src/main/docs/lpr-component.adoc | 149 ++++++++++++++---- .../src/main/docs/pubnub-component.adoc | 5 +- .../src/main/docs/rest-openapi-component.adoc | 3 + .../main/docs/threadpoolfactory-vertx.adoc | 2 + .../src/main/docs/thrift-component.adoc | 1 + .../src/main/docs/vertx-component.adoc | 1 + components/camel-wal/src/main/docs/wal.adoc | 2 + .../src/main/docs/web3j-component.adoc | 40 ++++- .../src/main/docs/wordpress-component.adoc | 1 + .../src/main/docs/xslt-saxon-component.adoc | 1 + .../main/docs/gzipDeflater-dataformat.adoc | 1 + 36 files changed, 327 insertions(+), 49 deletions(-) diff --git a/components/camel-ai/camel-a2a/src/main/docs/a2a-component.adoc b/components/camel-ai/camel-a2a/src/main/docs/a2a-component.adoc index cd6d19a8a19ab..201b375ba3cf1 100644 --- a/components/camel-ai/camel-a2a/src/main/docs/a2a-component.adoc +++ b/components/camel-ai/camel-a2a/src/main/docs/a2a-component.adoc @@ -473,6 +473,7 @@ NOTE: Use `script` EIP (not `setBody`) for `${a2a:emit()}` calls — `script` ev For advanced use cases, `A2AProgress` also supports emitting structured artifacts and intermediate messages: +._Java-only: emitting structured artifacts and intermediate messages with A2AProgress_ [source,java] ---- // Emit a structured artifact (e.g., a generated file) @@ -1426,6 +1427,7 @@ Default handlers: Override or extend by registering a custom handler bean: +._Java-only: implementing a custom A2ASecuritySchemeHandler_ [source,java] ---- @BindToRegistry("myCustomAuth") @@ -1672,6 +1674,7 @@ To customize, register a bean implementing `A2ATaskStore` in the Camel registry. Custom subscribers can be registered on a task-store bean for audit logging, metrics, or custom delivery: +._Java-only: registering a custom A2ATaskStore with a global subscriber_ [source,java] ---- @BindToRegistry diff --git a/components/camel-aws/camel-aws2-msk/src/main/docs/aws2-msk-component.adoc b/components/camel-aws/camel-aws2-msk/src/main/docs/aws2-msk-component.adoc index 660f9373ec7ee..8513bc0d141ee 100644 --- a/components/camel-aws/camel-aws2-msk/src/main/docs/aws2-msk-component.adoc +++ b/components/camel-aws/camel-aws2-msk/src/main/docs/aws2-msk-component.adoc @@ -115,6 +115,7 @@ YAML:: - createCluster: this operation will create an MSK Cluster in AWS +._Java-only: creating an MSK Cluster with a Processor and MSK2Constants_ [source,java] -------------------------------------------------------------------------------- from("direct:createCluster") @@ -125,7 +126,7 @@ from("direct:createCluster") exchange.getIn().setHeader(MSK2Constants.CLUSTER_KAFKA_VERSION, "2.1.1"); exchange.getIn().setHeader(MSK2Constants.BROKER_NODES_NUMBER, 2); BrokerNodeGroupInfo groupInfo = BrokerNodeGroupInfo.builder().build(); - exchange.getIn().setHeader(MSK2Constants.BROKER_NODES_GROUP_INFO, groupInfo); + exchange.getIn().setHeader(MSK2Constants.BROKER_NODES_GROUP_INFO, groupInfo); } }) .to("aws2-msk://test?mskClient=#amazonMskClient&operation=createCluster") @@ -176,6 +177,7 @@ YAML:: ---- ==== +._Java-only: deleting an MSK Cluster with a Processor and MSK2Constants_ [source,java] -------------------------------------------------------------------------------- from("direct:createCluster") @@ -186,7 +188,7 @@ from("direct:createCluster") exchange.getIn().setHeader(MSK2Constants.CLUSTER_KAFKA_VERSION, "2.1.1"); exchange.getIn().setHeader(MSK2Constants.BROKER_NODES_NUMBER, 2); BrokerNodeGroupInfo groupInfo = BrokerNodeGroupInfo.builder().build(); - exchange.getIn().setHeader(MSK2Constants.BROKER_NODES_GROUP_INFO, groupInfo); + exchange.getIn().setHeader(MSK2Constants.BROKER_NODES_GROUP_INFO, groupInfo); } }) .to("aws2-msk://test?mskClient=#amazonMskClient&operation=deleteCluster") @@ -197,6 +199,7 @@ from("direct:createCluster") Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as the body. In AWS MSK, there are multiple operations you can submit, as an example for List clusters request, you can do something like: +._Java-only: using an AWS SDK POJO request as the message body_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:aws2-msk") diff --git a/components/camel-azure/camel-azure-eventhubs/src/main/docs/azure-eventhubs-component.adoc b/components/camel-azure/camel-azure-eventhubs/src/main/docs/azure-eventhubs-component.adoc index 9f38d4e18e106..dd207c7482b51 100644 --- a/components/camel-azure/camel-azure-eventhubs/src/main/docs/azure-eventhubs-component.adoc +++ b/components/camel-azure/camel-azure-eventhubs/src/main/docs/azure-eventhubs-component.adoc @@ -157,6 +157,7 @@ YAML:: To produce events: +._Java-only: producing events with a Processor and EventHubsConstants_ [source,java] ---- from("direct:start") @@ -169,6 +170,7 @@ from("direct:start") The azure-eventhubs producer supports sending sending events as an `Iterable` (E.g. as a `List`). For example: +._Java-only: producing batch events with an Iterable body_ [source,java] ---- from("direct:start") @@ -188,6 +190,7 @@ from("direct:start") The example below makes use of the Azure-AD authentication. See https://docs.microsoft.com/en-us/java/api/overview/azure/identity-readme?view=azure-java-stable#environment-variables[here] about what environment variables you need to set for this to work: +._Java-only: registering a TokenCredential bean and using Azure-AD authentication_ [source,java] ---- @BindToRegistry("myTokenCredential") diff --git a/components/camel-azure/camel-azure-servicebus/src/main/docs/azure-servicebus-component.adoc b/components/camel-azure/camel-azure-servicebus/src/main/docs/azure-servicebus-component.adoc index 4ff85e6589f0b..50efaa9d4c4b4 100644 --- a/components/camel-azure/camel-azure-servicebus/src/main/docs/azure-servicebus-component.adoc +++ b/components/camel-azure/camel-azure-servicebus/src/main/docs/azure-servicebus-component.adoc @@ -89,6 +89,7 @@ In the consumer, the returned message body will be of type `String`. - `sendMessages` +._Java-only: building a batch message list with a Processor_ [source,java] -------------------------------------------------------------------------------- from("direct:start") @@ -105,6 +106,7 @@ from("direct:start") .to("mock:result"); -------------------------------------------------------------------------------- +._Java-only: sending a batch message with a session ID_ [source,java] -------------------------------------------------------------------------------- from("direct:start") @@ -124,6 +126,7 @@ from("direct:start") - `scheduleMessages` +._Java-only: scheduling messages with a Processor and ServiceBusConstants_ [source,java] -------------------------------------------------------------------------------- from("direct:start") diff --git a/components/camel-crypto-pgp/src/main/docs/pgp-dataformat.adoc b/components/camel-crypto-pgp/src/main/docs/pgp-dataformat.adoc index d090e9b8fd56b..6d50e5be6cc80 100644 --- a/components/camel-crypto-pgp/src/main/docs/pgp-dataformat.adoc +++ b/components/camel-crypto-pgp/src/main/docs/pgp-dataformat.adoc @@ -195,6 +195,7 @@ Provide the corresponding private keys in the secret keyring, the corresponding public keys in the public keyring, and the passphrases in the passphrase accessor. +._Java-only: programmatic PGPDataFormat with passphrase accessor and multiple keyrings_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------ Map userId2Passphrase = new HashMap(2); @@ -210,11 +211,11 @@ pgpVerifyAndDecrypt.setEncryptionKeyRing(getSecKeyRing()); // alternatively, you // the method getPublicKeyRing() provides the public keyring as a byte array containing the public keys pgpVerifyAndDecrypt.setSignatureKeyRing((getPublicKeyRing()); // alternatively, you can use setSignatureKeyFileName(signatgureKeyfileName) // it is not necessary to specify the encryption or signer User Id - + from("direct:start") - ... + ... .unmarshal(pgpVerifyAndDecrypt) // can decrypt/verify messages encrypted/signed by different private/public keys - ... + ... ------------------------------------------------------------------------------------------------------------------------------------------ * The functionality is especially useful to support the key exchange. If @@ -240,23 +241,24 @@ which can be used for the verification of a signature. *Signature User IDs* +._Java-only: programmatic PGPDataFormat restricting signer identities for verification_ [source,java] --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // specify the User IDs of the expected signer identities List expectedSigUserIds = new ArrayList(); expectedSigUserIds.add("Trusted company1"); expectedSigUserIds.add("Trusted company2"); - + PGPDataFormat pgpVerifyWithSpecificKeysAndDecrypt = new PGPDataFormat(); pgpVerifyWithSpecificKeysAndDecrypt.setPassword("my password"); // for decrypting with private key pgpVerifyWithSpecificKeysAndDecrypt.setKeyFileName(keyfileName); pgpVerifyWithSpecificKeysAndDecrypt.setSignatureKeyFileName(signatgureKeyfileName); pgpVerifyWithSpecificKeysAndDecrypt.setSignatureKeyUserids(expectedSigUserIds); // if you have only one signer identity, then you can also use setSignatureKeyUserid("expected Signer") - + from("direct:start") - ... + ... .unmarshal(pgpVerifyWithSpecificKeysAndDecrypt) - ... + ... --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * If the PGP content has several signatures, the verification is @@ -274,6 +276,7 @@ User IDs which relate to several private keys in the secret keyring. *Several Signatures* +._Java-only: programmatic PGPDataFormat with multiple signer keys_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- PGPDataFormat pgpSignAndEncryptSeveralSignerKeys = new PGPDataFormat(); @@ -286,11 +289,11 @@ User IDs which relate to several private keys in the secret keyring. signerUserIds.add("company old key"); signerUserIds.add("company new key"); pgpSignAndEncryptSeveralSignerKeys.setSignatureKeyUserids(signerUserIds); - + from("direct:start") - ... + ... .marshal(pgpSignAndEncryptSeveralSignerKeys) - ... + ... ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- == Support for Sub-Keys and Key Flags in PGP Data Format Marshaller diff --git a/components/camel-crypto/src/main/docs/crypto-dataformat.adoc b/components/camel-crypto/src/main/docs/crypto-dataformat.adoc index 971062799c992..1e4853ed14c6b 100644 --- a/components/camel-crypto/src/main/docs/crypto-dataformat.adoc +++ b/components/camel-crypto/src/main/docs/crypto-dataformat.adoc @@ -33,6 +33,7 @@ If one or more instances of the Crypto data format are configured with this key, be used to encrypt the payload in one route (or part of one) and decrypted in another. For example, using the Java DSL as follows: +._Java-only: programmatic CryptoDataFormat configuration with KeyGenerator_ [source,java] ---------------------------------------------------------- KeyGenerator generator = KeyGenerator.getInstance("DES"); @@ -71,6 +72,7 @@ In Spring the dataformat is configured first and then used in routes Changing the algorithm is a matter of supplying the JCE algorithm name. If you change the algorithm, you will need to use a compatible key. +._Java-only: programmatic CryptoDataFormat with custom algorithm and HMAC_ [source,java] ---------------------------------------------------------- KeyGenerator generator = KeyGenerator.getInstance("DES"); @@ -95,6 +97,7 @@ Some crypto algorithms, particularly block algorithms, require configuration wit In the JCE this is passed as an AlgorithmParameterSpec when the Cipher is initialized. To use such a vector with the CryptoDataFormat, you can configure it with a byte[] containing the required data, e.g. +._Java-only: programmatic CryptoDataFormat with initialization vector_ [source,java] ---------------------------------------------------------- KeyGenerator generator = KeyGenerator.getInstance("DES"); diff --git a/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc b/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc index 5911f22ecc6fa..56764b7847c7a 100644 --- a/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc +++ b/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc @@ -22,6 +22,7 @@ xref:eips:recipientList-eip.adoc[Recipient List]. To use a DataSonnet expression, use the following Java code: +._Java-only: creating a DataSonnet expression_ [source,java] --------------------------------------- datasonnet("someDSExpression"); @@ -178,7 +179,7 @@ xref:ROOT:properties-component.adoc[Properties] component (property placeholders Camel ships a standard library of helper functions that can be imported in any DataSonnet script: -[source,java] +[source,datasonnet] ---- local c = import 'camel.libsonnet'; { @@ -301,6 +302,7 @@ such as `"classpath:"`, `"file:"`, or `"http:"`. + This is done using the following syntax: `"resource:scheme:location"`, e.g., to refer to a file on the classpath you can do: +._Java-only: loading a DataSonnet script from an external resource_ [source,java] ------------------------------------------------------------------- .setHeader("myHeader").datasonnet("resource:classpath:mydatasonnet.ds"); diff --git a/components/camel-git/src/main/docs/git-component.adoc b/components/camel-git/src/main/docs/git-component.adoc index 7f25307637c91..25e575099b7e1 100644 --- a/components/camel-git/src/main/docs/git-component.adoc +++ b/components/camel-git/src/main/docs/git-component.adoc @@ -53,6 +53,7 @@ Below is an example route of a producer that adds a file test.java to a local repository, commits it with a specific message on the `main` branch and then pushes it to remote repository. +._Java-only: setting headers with GitConstants and chaining multiple git operations_ [source,java] -------------------------------------------------------------------------------------------------------------------- from("direct:start") @@ -69,12 +70,41 @@ from("direct:start") Below is an example route of a consumer that consumes commit: +[tabs] +==== +Java:: ++ [source,java] --------------------------------------- from("git:///tmp/testRepo?type=commit") - .to(....) + .to("mock:result"); --------------------------------------- +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: git:///tmp/testRepo + parameters: + type: commit + steps: + - to: + uri: mock:result +---- +==== + === Shallow Clone Use the `depth` option to perform a shallow clone, fetching only a limited number of commits. This reduces clone time and disk usage for large repositories when full history is not needed. @@ -123,6 +153,7 @@ A `depth` of 1 fetches only the latest commit. The value must be a positive inte By default, camel-git will load ``.gitconfig`` file from user home folder. You can override this by providing your own ``.gitconfig`` file. +._Java-only: configuring custom gitConfigFile with different resource schemes_ [source,java] --------------------------------------- from("git:///tmp/testRepo?type=commit&gitConfigFile=file:/tmp/configfile") diff --git a/components/camel-graphql/src/main/docs/graphql-component.adoc b/components/camel-graphql/src/main/docs/graphql-component.adoc index 2c58e05e09c55..bfd5d2752c04b 100644 --- a/components/camel-graphql/src/main/docs/graphql-component.adoc +++ b/components/camel-graphql/src/main/docs/graphql-component.adoc @@ -267,6 +267,7 @@ query BookById($id: Int!) { } ---- +._Java-only: registering query variables and referencing them in the endpoint_ [source,java] ---- @BindToRegistry("bookByIdQueryVariables") @@ -282,6 +283,7 @@ from("direct:start") A query that accesses variables via the variablesHeader parameter: +._Java-only: setting variables via a header with a lambda supplier_ [source,java] ---- from("direct:start") @@ -311,6 +313,7 @@ mutation AddBook($bookInput: BookInput) { } ---- +._Java-only: registering mutation variables and referencing them in the endpoint_ [source,java] ---- @BindToRegistry("addBookMutationVariables") diff --git a/components/camel-groovy/src/main/docs/groovy-language.adoc b/components/camel-groovy/src/main/docs/groovy-language.adoc index 67d9170aa3e0b..5b0ed13e83d27 100644 --- a/components/camel-groovy/src/main/docs/groovy-language.adoc +++ b/components/camel-groovy/src/main/docs/groovy-language.adoc @@ -17,6 +17,7 @@ For example, you can use Groovy in a xref:manual::predicate.adoc[Predicate] with the xref:eips:filter-eip.adoc[Message Filter] EIP. +._Java-only: creating a Groovy expression_ [source,java] --------------------------------------- groovy("someGroovyExpression") @@ -86,6 +87,7 @@ Groovy expressions. To provide the custom `GroovyShell`, add an implementation of the `org.apache.camel.language.groovy.GroovyShellFactory` SPI interface to the Camel registry. +._Java-only: implementing a custom GroovyShellFactory_ [source,java] ---- public class CustomGroovyShellFactory implements GroovyShellFactory { @@ -111,6 +113,7 @@ such as `"classpath:"`, `"file:"`, or `"http:"`. This is done using the following syntax: `"resource:scheme:location"`, e.g., to refer to a file on the classpath you can do: +._Java-only: loading a Groovy script from an external resource_ [source,java] ------------------------------------------------------------------- .setHeader("myHeader").groovy("resource:classpath:mygroovy.groovy") diff --git a/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc b/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc index 9e9a5b0c12bbe..bd0062846daf4 100644 --- a/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc +++ b/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc @@ -65,6 +65,7 @@ include::partial$dataformat-options.adoc[] Jackson can also be used via the generic `json()` DSL method by specifying `JsonLibrary.Jackson`: +._Java-only: using the json() DSL method with JsonLibrary.Jackson_ [source,java] ------------------------------- from("activemq:My.Queue") @@ -74,6 +75,7 @@ from("activemq:My.Queue") This is equivalent to using `.jackson()` directly. The `json()` method also supports additional parameters: +._Java-only: json() DSL with pretty print and unmarshal type_ [source,java] ------------------------------- // Pretty print @@ -115,6 +117,7 @@ from `JsonNode` to `String` or vice versa. To enable POJO conversion support for `camel-jackson3` then this must be enabled, which is done by setting the following options on the `CamelContext` global options, as shown: +._Java-only: enabling Jackson 3 POJO type converter via CamelContext options_ [source,java] ---- // Enable Jackson 3 JSON type converter for more types. diff --git a/components/camel-jasypt/src/main/docs/jasypt.adoc b/components/camel-jasypt/src/main/docs/jasypt.adoc index 63a8b528946a6..7972e6d49aa99 100644 --- a/components/camel-jasypt/src/main/docs/jasypt.adoc +++ b/components/camel-jasypt/src/main/docs/jasypt.adoc @@ -143,6 +143,7 @@ password=sysenv:CAMEL_ENCRYPTION_PASSWORD Or if configuring `JasyptPropertiesParser` manually, you can set the password like this. +._Java-only: setting the master password on JasyptPropertiesParser_ [source,java] --------------------- jasyptPropertiesParser.setPassword("sysenv:CAMEL_ENCRYPTION_PASSWORD"); diff --git a/components/camel-mail-microsoft-oauth/src/main/docs/mail-microsoft-oauth.adoc b/components/camel-mail-microsoft-oauth/src/main/docs/mail-microsoft-oauth.adoc index 3f7aa52ffb7dd..fe8111bd17f56 100644 --- a/components/camel-mail-microsoft-oauth/src/main/docs/mail-microsoft-oauth.adoc +++ b/components/camel-mail-microsoft-oauth/src/main/docs/mail-microsoft-oauth.adoc @@ -48,6 +48,7 @@ For example, * in a Quarkus application: +._Java-only: registering the OAuth2 authenticator bean in Quarkus_ [source,java] ---- @jakarta.enterprise.inject.Produces @@ -60,6 +61,7 @@ public MicrosoftExchangeOnlineOAuth2MailAuthenticator exchangeAuthenticator() { * in a Spring Boot application: +._Java-only: registering the OAuth2 authenticator bean in Spring Boot_ [source,java] ---- @BindToRegistry("auth") @@ -70,6 +72,7 @@ public MicrosoftExchangeOnlineOAuth2MailAuthenticator exchangeAuthenticator(){ and then reference it in the Camel endpoint: +._Java-only: referencing the authenticator in the IMAP endpoint URI_ [source,java] ---- from("imaps://outlook.office365.com:993" diff --git a/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc b/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc index ad7a5c1fd0d10..cd1a48e537774 100644 --- a/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc +++ b/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc @@ -99,6 +99,7 @@ MIME multipart. The header is removed afterward == Examples +._Java-only: marshalling a message with attachments into MIME-Multipart format_ [source,java] ----------------------------------- from(...).marshal().mimeMultipart() @@ -137,6 +138,7 @@ AAECAwQFBgc= A message with the header Content-Type set to "text/plain" sent to the route +._Java-only: marshalling with custom MIME-Multipart options_ [source,java] ------------------------------------------------------------------------------------ from("...").marshal().mimeMultipart("related", true, true, "(included|x-.*)", true); diff --git a/components/camel-mdc/src/main/docs/mdc.adoc b/components/camel-mdc/src/main/docs/mdc.adoc index 753f4c424a1ca..da287245bc608 100644 --- a/components/camel-mdc/src/main/docs/mdc.adoc +++ b/components/camel-mdc/src/main/docs/mdc.adoc @@ -23,6 +23,7 @@ NOTE: don't set legacy MDC via `context.setUseMDCLogging(true)` on `CamelContext The goal of this component is to avoid to work on low level API in Java. In older MDC implementations you had to hack into the code to include MDC such as: +._Java-only: legacy approach to setting MDC values directly via SLF4J API_ [source,java] ---- org.slf4j.MDC.put("myCustomMDCKey", "myCustomKeyValue"); @@ -30,6 +31,7 @@ The goal of this component is to avoid to work on low level API in Java. In olde And later you had to make sure to provide MDC context propagation in async components (eg, `wiretap`) in order to make sure to have such context available in the new executing async thread. With this new service, the only thing to do is to add the value as a Camel Exchange header (or a property), for example: +._Java-only: setting an MDC value as a Camel Exchange header_ [source,java] ---- .setHeader("myCustomMDCKey", simple("myCustomKeyValue")) diff --git a/components/camel-micrometer-observability/src/main/docs/micrometer-observability.adoc b/components/camel-micrometer-observability/src/main/docs/micrometer-observability.adoc index 61c0609546019..c4eb8896a69a9 100644 --- a/components/camel-micrometer-observability/src/main/docs/micrometer-observability.adoc +++ b/components/camel-micrometer-observability/src/main/docs/micrometer-observability.adoc @@ -46,6 +46,7 @@ The starter is in charge to autoconfigure the component. Additionally you will n If you use `camel-main` as standalone Camel, add `camel-micrometer-observability` component in your POM, and setup the proper configuration. Mind that, since the component is a facade to a concrete implementation, you are in charge to provide the configuration programmatically. The minimum required for the component to start is the following snippet of code: +._Java-only: minimum setup for MicrometerObservabilityTracer in standalone Camel_ ```java import org.apache.camel.micrometer.observability.MicrometerObservabilityTracer; ... @@ -62,6 +63,7 @@ You can run this, for example, directly via Camel CLI using `camel run MyTest.ja If you need to setup the specific component parameters, you may do it directly on the tracer object, for example: +._Java-only: configuring tracer parameters programmatically_ ```java myTracer.setTraceProcessors(true); myTracer.setExcludePatterns("log*,to*"); @@ -77,6 +79,7 @@ The production configuration vary based on the concrete technology you use (like Here it follows an example to configure the component to work with Opentelemetry bridge. First of all, you need to include in your project the dependencies for `io.micrometer:micrometer-tracing-bridge-otel` and `io.opentelemetry:opentelemetry-sdk:x.y.z` (you need to explicitly set the version for the last dependency). +._Java-only: configuring the OpenTelemetry bridge with Micrometer tracing_ ```java import org.apache.camel.micrometer.observability.MicrometerObservabilityTracer; import io.micrometer.tracing.otel.bridge.OtelBaggageManager; @@ -153,6 +156,7 @@ As an alternative, you can add Mapped Diagnostic Context tracing information (ie When you're working at a very low level, you may need to tweak your metrics and add some in-process custom `span` in order to trace some specific measure of your application. If you need this advanced use case, you can create it during your process by configuring a Micrometer Tracer object and share it to your route. For example, in Java DSL: +._Java-only: creating a custom span within a Camel processor_ [source,java] ---- protected io.micrometer.tracing.Tracer tracer = new OtelTracer( @@ -176,6 +180,7 @@ public void process(Exchange exchange) throws Exception { `Baggage` is a way to attach key-value metadata to a request and carry it across service boundaries. In the context of telemetry technologies, baggage travels along with the context (like trace/span), but it's meant for custom data you define, not telemetry internals. Camel allows you to programmatically provide any `Baggage` information via Exchange property settings. Whenever the component finds a property defined as `CamelBaggage_xyz` it will consider it as a baggage variable named `xyz`. For example, in Java DSL: +._Java-only: setting baggage properties and retrieving them via Micrometer API_ [source,java] ---- from("direct:start") diff --git a/components/camel-microprofile/camel-microprofile-health/src/main/docs/microprofile-health.adoc b/components/camel-microprofile/camel-microprofile-health/src/main/docs/microprofile-health.adoc index e1b3bc354a602..9363477f98c8f 100644 --- a/components/camel-microprofile/camel-microprofile-health/src/main/docs/microprofile-health.adoc +++ b/components/camel-microprofile/camel-microprofile-health/src/main/docs/microprofile-health.adoc @@ -29,6 +29,8 @@ for this component: == Usage This component provides a custom `HealthCheckRegistry` implementation that needs to be registered on the `CamelContext`. + +._Java-only: registering the MicroProfile Health check registry on the CamelContext_ [source,java] ---- HealthCheckRegistry registry = new CamelMicroProfileHealthCheckRegistry(); @@ -40,6 +42,7 @@ be considered either a readiness or liveness check, you can extend `AbstractHeal For example, to have a check registered exclusively as a liveness check: +._Java-only: implementing a custom liveness health check_ [source,java] ---- public class MyHealthCheck extends AbstractHealthCheck { diff --git a/components/camel-milo/src/main/docs/milo-client-component.adoc b/components/camel-milo/src/main/docs/milo-client-component.adoc index 6bfd1319d01c6..5acacbf2ddbb0 100644 --- a/components/camel-milo/src/main/docs/milo-client-component.adoc +++ b/components/camel-milo/src/main/docs/milo-client-component.adoc @@ -132,6 +132,7 @@ The component provide a producer to read values from multiple opc-ua nodes. The Example: +._Java-only: reading values from OPC UA nodes using enrich with an AggregationStrategy_ [source,java] ---- from("direct:start") @@ -156,6 +157,7 @@ The component does not decode these values automatically, because it cannot reli applies. Instead, the active `OpcUaClient` is exposed through `MiloClientConnection.getOpcUaClient()`, so you can obtain its encoding contexts and perform the encode/decode yourself: +._Java-only: accessing the underlying OpcUaClient for custom data type encoding/decoding_ [source,java] ---- MiloClientEndpoint endpoint = context.getEndpoint("milo-client:opc.tcp://localhost:4334", MiloClientEndpoint.class); diff --git a/components/camel-mvel/src/main/docs/mvel-language.adoc b/components/camel-mvel/src/main/docs/mvel-language.adoc index 3187d57510a05..6852abe491525 100644 --- a/components/camel-mvel/src/main/docs/mvel-language.adoc +++ b/components/camel-mvel/src/main/docs/mvel-language.adoc @@ -31,6 +31,7 @@ request.body.familyName Or use similar syntax as in Java: +._Java-only: MVEL expression using Java method call syntax_ [source,java] ---- getRequest().getBody().getFamilyName() @@ -119,6 +120,7 @@ such as `"classpath:"`, `"file:"`, or `"http:"`. This is done using the following syntax: `"resource:scheme:location"`, e.g., to refer to a file on the classpath you can do: +._Java-only: loading a MVEL script from the classpath_ [source,java] ---- .setHeader("myHeader").mvel("resource:classpath:script.mvel") diff --git a/components/camel-nats/src/main/docs/nats-component.adoc b/components/camel-nats/src/main/docs/nats-component.adoc index d923e248bd8a3..92d3dbf29ca5a 100644 --- a/components/camel-nats/src/main/docs/nats-component.adoc +++ b/components/camel-nats/src/main/docs/nats-component.adoc @@ -52,6 +52,7 @@ You configure the NATS servers on either the component or the endpoint. For example, to configure this once on the component, you can do: +._Java-only: configuring NATS servers on the component_ [source,java] ---- NatsComponent nats = context.getComponent("nats", NatsComponent.class); @@ -103,6 +104,7 @@ The endpoint configuration will override any server configuration on the compone You can specify username and password for the servers in the server URLs, where its `username:password@url`, or `token@url` etc: +._Java-only: configuring NATS servers with credentials_ [source,java] ---- NatsComponent nats = context.getComponent("nats", NatsComponent.class); @@ -278,6 +280,7 @@ To take full control of acknowledgment, set `manualAck=true` on the consumer end This disables automatic acknowledgment and exposes a `NatsManualAck` object as the `CamelNatsManualAck` message header. +._Java-only: manual acknowledgment with NatsManualAck in a processor_ [source,java] ---- from("nats:mytopic?jetstreamEnabled=true&jetstreamName=mystream&durableName=myconsumer&pullSubscription=false&manualAck=true") diff --git a/components/camel-ocsf/src/main/docs/ocsf-dataformat.adoc b/components/camel-ocsf/src/main/docs/ocsf-dataformat.adoc index d60ac92731c57..7325150ee4e4b 100644 --- a/components/camel-ocsf/src/main/docs/ocsf-dataformat.adoc +++ b/components/camel-ocsf/src/main/docs/ocsf-dataformat.adoc @@ -176,6 +176,10 @@ YAML:: AWS Security Hub now outputs findings in OCSF format. You can use this data format to process those findings: +[tabs] +==== +Java:: ++ [source,java] ---- from("aws-securityhub:findings") @@ -187,6 +191,51 @@ from("aws-securityhub:findings") .to("direct:normal-severity"); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + ${body.severityId} >= 4 + + + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: aws-securityhub:findings + steps: + - unmarshal: + ocsf: + unmarshalType: org.apache.camel.dataformat.ocsf.model.DetectionFinding + - choice: + when: + - simple: "${body.severityId} >= 4" + steps: + - to: + uri: direct:high-severity + otherwise: + steps: + - to: + uri: direct:normal-severity +---- +==== + == OCSF Options // dataformat options: START @@ -212,6 +261,7 @@ OCSF defines the following event categories: == Example: Creating a Detection Finding +._Java-only: creating and marshalling a DetectionFinding POJO_ [source,java] ---- DetectionFinding finding = new DetectionFinding(); @@ -241,6 +291,7 @@ You can combine the OCSF DataFormat with the LangChain4j Chat component to use a === Java DSL Example +._Java-only: AI-powered security finding summarization with process and langchain4j_ [source,java] ---- from("kafka:security-events") diff --git a/components/camel-ognl/src/main/docs/ognl-language.adoc b/components/camel-ognl/src/main/docs/ognl-language.adoc index db3e1a5ff0146..0886866354f9a 100644 --- a/components/camel-ognl/src/main/docs/ognl-language.adoc +++ b/components/camel-ognl/src/main/docs/ognl-language.adoc @@ -31,6 +31,7 @@ request.body.familyName Or use similar syntax as in Java: +._Java-only: OGNL expression using Java method call syntax_ [source,java] ---- getRequest().getBody().getFamilyName() @@ -121,6 +122,7 @@ such as `"classpath:"`, `"file:"`, or `"http:"`. This is done using the following syntax: `"resource:scheme:location"`, e.g., to refer to a file on the classpath you can do: +._Java-only: loading an OGNL script from the classpath_ [source,java] ---- .setHeader("myHeader").ognl("resource:classpath:myognl.txt") diff --git a/components/camel-openapi-validator/src/main/docs/openapi-validator.adoc b/components/camel-openapi-validator/src/main/docs/openapi-validator.adoc index 8db451fc2dccc..67da988234ccd 100644 --- a/components/camel-openapi-validator/src/main/docs/openapi-validator.adoc +++ b/components/camel-openapi-validator/src/main/docs/openapi-validator.adoc @@ -35,6 +35,7 @@ No additional configuration is required. To enable request validation on incoming HTTP requests, use `clientRequestValidation(true)` in the REST DSL and load the OpenAPI specification with `openApi()`: +._Java-only: enabling client request validation with REST DSL and OpenAPI_ [source,java] ---- rest().clientRequestValidation(true) @@ -71,6 +72,7 @@ camel.rest.validation-levels[validation.response.body.missing] = WARN Or configure them in Java DSL: +._Java-only: configuring validation levels programmatically_ [source,java] ---- restConfiguration() diff --git a/components/camel-paho-mqtt5/src/main/docs/paho-mqtt5-component.adoc b/components/camel-paho-mqtt5/src/main/docs/paho-mqtt5-component.adoc index e478fe33fb0f1..5d66008db4a5d 100644 --- a/components/camel-paho-mqtt5/src/main/docs/paho-mqtt5-component.adoc +++ b/components/camel-paho-mqtt5/src/main/docs/paho-mqtt5-component.adoc @@ -54,6 +54,7 @@ include::partial$component-endpoint-headers.adoc[] By default, the Camel Paho component operates on the binary payloads extracted out of (or put into) the MQTT message: +._Java-only: receiving and sending binary payloads using the Paho MQTT5 component_ [source,java] ---- // Receive payload @@ -69,6 +70,7 @@ API] can perform the automatic data type transformations for you. In the example below Camel automatically converts binary payload into `String` (and conversely): +._Java-only: automatic type conversion of payloads_ [source,java] ---- // Receive payload diff --git a/components/camel-paho/src/main/docs/paho-component.adoc b/components/camel-paho/src/main/docs/paho-component.adoc index 573abdca693ce..896ca2d64f22d 100644 --- a/components/camel-paho/src/main/docs/paho-component.adoc +++ b/components/camel-paho/src/main/docs/paho-component.adoc @@ -56,6 +56,7 @@ include::partial$component-endpoint-headers.adoc[] By default, the Camel Paho component operates on the binary payloads extracted out of (or put into) the MQTT message: +._Java-only: receiving and sending binary payloads using the Paho component_ [source,java] ---- // Receive payload @@ -69,6 +70,7 @@ producerTemplate.sendBody("paho:topic", payload); Of course, Camel build-in xref:manual::type-converter.adoc[type conversion API] can perform the automatic data type transformations for you. In the example below Camel automatically converts binary payload into `String` (and conversely): +._Java-only: automatic type conversion of payloads_ [source,java] ---- // Receive payload diff --git a/components/camel-printer/src/main/docs/lpr-component.adoc b/components/camel-printer/src/main/docs/lpr-component.adoc index 2f18e5636156a..5693482be5ae0 100644 --- a/components/camel-printer/src/main/docs/lpr-component.adoc +++ b/components/camel-printer/src/main/docs/lpr-component.adoc @@ -72,49 +72,134 @@ Usage samples. === Printing text-based payloads .Printing text-based payloads on a Default printer using letter stationary and one-sided mode +[tabs] +==== +Java:: ++ [source,java] ------------------------------------------------ -RouteBuilder builder = new RouteBuilder() { - public void configure() { - from("file://inputdir/?delete=true") - .to("lpr://localhost/default?copies=2" + - "&flavor=DocFlavor.INPUT_STREAM&" + - "&mimeType=AUTOSENSE" + - "&mediaSize=NA_LETTER" + - "&sides=one-sided"); - }}; ------------------------------------------------ +---- +from("file://inputdir/?delete=true") + .to("lpr://localhost/default?copies=2&flavor=DocFlavor.INPUT_STREAM&mimeType=AUTOSENSE&mediaSize=NA_LETTER&sides=one-sided"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://inputdir/ + parameters: + delete: true + steps: + - to: + uri: lpr://localhost/default + parameters: + copies: 2 + flavor: DocFlavor.INPUT_STREAM + mimeType: AUTOSENSE + mediaSize: NA_LETTER + sides: one-sided +---- +==== === Printing GIF-based payloads .Printing GIF-based payloads on a remote printer using A4 stationary and one-sided mode +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------- -RouteBuilder builder = new RouteBuilder() { - public void configure() { - from("file://inputdir/?delete=true") - .to("lpr://remotehost/sales/salesprinter" + - "?copies=2&sides=one-sided" + - "&mimeType=GIF&mediaSize=ISO_A4" + - "&flavor=DocFlavor.INPUT_STREAM"); - }}; --------------------------------------------------- +---- +from("file://inputdir/?delete=true") + .to("lpr://remotehost/sales/salesprinter?copies=2&sides=one-sided&mimeType=GIF&mediaSize=ISO_A4&flavor=DocFlavor.INPUT_STREAM"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://inputdir/ + parameters: + delete: true + steps: + - to: + uri: lpr://remotehost/sales/salesprinter + parameters: + copies: 2 + sides: one-sided + mimeType: GIF + mediaSize: ISO_A4 + flavor: DocFlavor.INPUT_STREAM +---- +==== === Printing JPEG-based payloads .Printing JPEG-based payloads on a remote printer using Japanese Postcard stationary and one-sided mode +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------- -RouteBuilder builder = new RouteBuilder() { - public void configure() { - from("file://inputdir/?delete=true") - .to("lpr://remotehost/sales/salesprinter" + - "?copies=2&sides=one-sided" + - "&mimeType=JPEG" + - "&mediaSize=JAPANESE_POSTCARD" + - "&flavor=DocFlavor.INPUT_STREAM"); - }}; --------------------------------------------------- +---- +from("file://inputdir/?delete=true") + .to("lpr://remotehost/sales/salesprinter?copies=2&sides=one-sided&mimeType=JPEG&mediaSize=JAPANESE_POSTCARD&flavor=DocFlavor.INPUT_STREAM"); +---- + +XML:: ++ +[source,xml] +---- + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: file://inputdir/ + parameters: + delete: true + steps: + - to: + uri: lpr://remotehost/sales/salesprinter + parameters: + copies: 2 + sides: one-sided + mimeType: JPEG + mediaSize: JAPANESE_POSTCARD + flavor: DocFlavor.INPUT_STREAM +---- +==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-pubnub/src/main/docs/pubnub-component.adoc b/components/camel-pubnub/src/main/docs/pubnub-component.adoc index 57656a526867d..cbbaf9c484f70 100644 --- a/components/camel-pubnub/src/main/docs/pubnub-component.adoc +++ b/components/camel-pubnub/src/main/docs/pubnub-component.adoc @@ -75,6 +75,7 @@ When receiving the message body uses objects provided by the PubNub API. Default operation when producing. The following snippet publishes the event generated by PojoBean to the channel iot. +._Java-only: publishing events with a bean processor_ [source,java] ---- from("timer:mytimer") @@ -86,8 +87,9 @@ from("timer:mytimer") === Fire events aka BLOCKS Event Handlers See https://www.pubnub.com/blocks-catalog/[blocks catalog] for all kinds of serverless functions that can be invoked. -Example of geolocation lookup +Example of geolocation lookup +._Java-only: fire events with geolocation lookup_ [source,java] ---- from("timer:geotimer") @@ -235,6 +237,7 @@ YAML:: - `setstate`: used to set key/value pairs specific to a subscriber uuid: +._Java-only: setting state with a bean processor_ [source,java] ---- from("direct:control") diff --git a/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc b/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc index f1462d7e1ccd2..99230fdc6a5cf 100644 --- a/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc +++ b/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc @@ -113,6 +113,7 @@ delegate. To validate incoming `Authorization: Bearer` tokens from Rest DSL contract-first routes, pass the delegate endpoint option `oauthProfile` through the REST configuration endpoint properties. +._Java-only: configuring REST with OAuth profile_ [source,java] ---- restConfiguration() @@ -233,6 +234,7 @@ Here are our dependencies defined in Maven POM file: Start by defining a `RestOpenApiComponent` bean: +._Java-only: defining a RestOpenApiComponent bean for PetStore_ [source,java] ---- @Bean @@ -266,6 +268,7 @@ would use the named component from the Camel registry. Now in our application we can simply use the `ProducerTemplate` to invoke PetStore REST methods: +._Java-only: invoking PetStore REST methods with ProducerTemplate_ [source,java] ---- @Autowired diff --git a/components/camel-threadpoolfactory-vertx/src/main/docs/threadpoolfactory-vertx.adoc b/components/camel-threadpoolfactory-vertx/src/main/docs/threadpoolfactory-vertx.adoc index 4c455dcc18e98..852334e740fd3 100644 --- a/components/camel-threadpoolfactory-vertx/src/main/docs/threadpoolfactory-vertx.adoc +++ b/components/camel-threadpoolfactory-vertx/src/main/docs/threadpoolfactory-vertx.adoc @@ -21,6 +21,7 @@ This implementation has been designed to use VertX worker threads for EIPs where However, this is limited to only apply when the EIP is not configured with a specific thread pool. For example, the first example below will use VertX worker threads, and the 2nd below will not: +._Java-only: split with parallel processing using VertX worker threads_ [source,java] ---- from("direct:start") @@ -34,6 +35,7 @@ from("direct:start") The following Split EIP will refer to a custom thread pool, and therefore VertX is not in use, and Camel will use the custom thread pool: +._Java-only: split with a custom thread pool profile (not using VertX)_ [source,java] ---- // register a custom thread pool profile with id myLowPool diff --git a/components/camel-thrift/src/main/docs/thrift-component.adoc b/components/camel-thrift/src/main/docs/thrift-component.adoc index 5e0ba2fb1bd4c..a315e5a769925 100644 --- a/components/camel-thrift/src/main/docs/thrift-component.adoc +++ b/components/camel-thrift/src/main/docs/thrift-component.adoc @@ -50,6 +50,7 @@ Parameters in the called procedure must be passed as a list of objects inside th To correctly find the corresponding method, all types must be transmitted regardless of the values. Please see an example below, how to pass different parameters to the method with the Camel body: +._Java-only: passing different parameter types in the Thrift method request body_ [source,java] ------------------------------------------------------------------------------- List requestBody = new ArrayList(); diff --git a/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc b/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc index fa70e7f910dbe..1922fa4b7d260 100644 --- a/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc +++ b/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc @@ -53,6 +53,7 @@ include::partial$component-endpoint-headers.adoc[] If you would like to connect to the Vert.x instance already existing in your JVM, you can set the instance on the component level: +._Java-only: connecting to an existing Vert.x instance_ [source,java] ----------------------------------------------------- Vertx vertx = ...; diff --git a/components/camel-wal/src/main/docs/wal.adoc b/components/camel-wal/src/main/docs/wal.adoc index aadfd9b3e4f55..8bc89c292c564 100644 --- a/components/camel-wal/src/main/docs/wal.adoc +++ b/components/camel-wal/src/main/docs/wal.adoc @@ -23,6 +23,7 @@ Thus guaranteeing that records can be recovered in case that system crashes. Because this strategy wraps another one, then the other one should be created first and then passed as an argument to this strategy when creating it. +._Java-only: creating a WriteAheadResumeStrategy wrapping another strategy_ [source,java] ---- SomeOtherResumeStrategy resumeStrategy = new SomeOtherResumeStrategy(); @@ -33,6 +34,7 @@ WriteAheadResumeStrategy writeAheadResumeStrategy = new WriteAheadResumeStrategy Subsequently, this strategy should be registered to the registry instead +._Java-only: registering the strategy and using it in a route_ [source,java] ---- getCamelContext().getRegistry().bind(ResumeStrategy.DEFAULT_NAME, writeAheadResumeStrategy); diff --git a/components/camel-web3j/src/main/docs/web3j-component.adoc b/components/camel-web3j/src/main/docs/web3j-component.adoc index 9122c75654214..657540d9c12ff 100644 --- a/components/camel-web3j/src/main/docs/web3j-component.adoc +++ b/components/camel-web3j/src/main/docs/web3j-component.adoc @@ -93,12 +93,48 @@ YAML:: Use the block hash code to retrieve the block and full transaction details: +[tabs] +==== +Java:: ++ [source,java] ---------------------------------------------------------- +---- from("jms:queue:blocks") .setHeader(BLOCK_HASH, body()) .to("web3j://http://127.0.0.1:7545?operation=ETH_GET_BLOCK_BY_HASH&fullTransactionObjects=true"); ---------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + ${body} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: jms:queue:blocks + steps: + - setHeader: + name: BLOCK_HASH + simple: "${body}" + - to: + uri: "web3j://http://127.0.0.1:7545" + parameters: + operation: ETH_GET_BLOCK_BY_HASH + fullTransactionObjects: true +---- +==== Read the balance of an address at a specific block number: diff --git a/components/camel-wordpress/src/main/docs/wordpress-component.adoc b/components/camel-wordpress/src/main/docs/wordpress-component.adoc index 81ed0df01942c..c68cf6e4da88e 100644 --- a/components/camel-wordpress/src/main/docs/wordpress-component.adoc +++ b/components/camel-wordpress/src/main/docs/wordpress-component.adoc @@ -42,6 +42,7 @@ wordpress:post?criteria.perPage=10&criteria.orderBy=author&criteria.categories=c The `WordpressConfiguration` class can be used to set initial properties configuration to the component instead of passing it as query parameter. The following listing shows how to set the component to be used in your routes. +._Java-only: configuring the WordPress component programmatically_ [source,java] ---- public void configure() { diff --git a/components/camel-xslt-saxon/src/main/docs/xslt-saxon-component.adoc b/components/camel-xslt-saxon/src/main/docs/xslt-saxon-component.adoc index d63b4195ed5b7..d32066727b2da 100644 --- a/components/camel-xslt-saxon/src/main/docs/xslt-saxon-component.adoc +++ b/components/camel-xslt-saxon/src/main/docs/xslt-saxon-component.adoc @@ -221,6 +221,7 @@ Since Saxon 9.2, writing extension functions has been supplemented by a new mechanism, referred to as https://www.saxonica.com/html/documentation12/extensibility/extension-functions.html[extension functions] you can now easily use camel as shown in the below example: +._Java-only: registering Saxon extension functions and using them in a route_ [source,java] ---- SimpleRegistry registry = new SimpleRegistry(); diff --git a/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc b/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc index 5fb29212783b0..759a12252106b 100644 --- a/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc +++ b/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc @@ -80,6 +80,7 @@ In this example we unmarshal a gzipped payload from an ActiveMQ queue called MY_QUEUE to its original format, and forward it for processing to the `UnGZippedMessageProcessor`. +._Java-only: unmarshalling a gzipped payload and forwarding to a custom processor_ [source,java] ---- from("activemq:queue:MY_QUEUE").unmarshal().gzipDeflater().process(new UnGZippedMessageProcessor()); From ee40ff3fd977294e7c8ab33f3cb8601f0cda287b Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 10:59:27 +0200 Subject: [PATCH 84/87] CAMEL-23789: Make component docs multi-DSL friendly (Wave 1) - batch 7 Final sweep: process all remaining single-block component doc files. Covers 62 files including AI components (djl, huggingface, langchain4j-chat/embeddings, pgvector), AWS components (ses, ecs, eks, kms, redshift, rekognition, step-functions, sts, cw), Debezium components (db2, mongodb, mysql, oracle, postgres, sqlserver), Jackson data formats (jackson2/3, avro, protobuf variants), and miscellaneous components (browse, clickup, coap, freemarker, geocoder, ical, iso8583, jq, jte, kubernetes-config-maps, language, ldif, log, lzf, mapstruct, microprofile-config, milo-browse, mybatis-bean, observation, platform-http, scp, servicenow, shell, sjms, slack, solr, splunk, spring-ai-embeddings, spring-batch, spring-cloud-config, spring-security, string-template, test-junit6, wasm-component). Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/djl-component.adoc | 2 +- .../src/main/docs/huggingface-component.adoc | 2 + .../main/docs/langchain4j-chat-component.adoc | 1 + .../langchain4j-embeddings-component.adoc | 1 + .../src/main/docs/pgvector-component.adoc | 1 + .../src/main/docs/avro-component.adoc | 1 + .../src/main/docs/avro-dataformat.adoc | 1 + .../src/main/docs/aws2-cw-component.adoc | 1 + .../src/main/docs/aws2-ecs-component.adoc | 1 + .../src/main/docs/aws2-eks-component.adoc | 1 + .../src/main/docs/aws2-kms-component.adoc | 1 + .../docs/aws2-redshift-data-component.adoc | 1 + .../main/docs/aws2-rekognition-component.adoc | 1 + .../src/main/docs/aws2-ses-component.adoc | 51 ++++++++++++++- .../docs/aws2-step-functions-component.adoc | 1 + .../src/main/docs/aws2-sts-component.adoc | 1 + .../src/main/docs/browse-component.adoc | 1 + .../src/main/docs/clickup-component.adoc | 1 + .../src/main/docs/coap-component.adoc | 1 + .../src/main/docs/debezium-db2-component.adoc | 1 + .../main/docs/debezium-mongodb-component.adoc | 64 +++++++++++++++++++ .../main/docs/debezium-mysql-component.adoc | 1 + .../main/docs/debezium-oracle-component.adoc | 1 + .../docs/debezium-postgres-component.adoc | 1 + .../docs/debezium-sqlserver-component.adoc | 1 + .../src/main/docs/freemarker-component.adoc | 1 + .../src/main/docs/geocoder-component.adoc | 1 + .../src/main/docs/ical-dataformat.adoc | 1 + .../src/main/docs/iso8583-dataformat.adoc | 1 + .../main/docs/avroJackson2-dataformat.adoc | 41 ++++++++++-- .../docs/protobufJackson2-dataformat.adoc | 41 ++++++++++-- .../src/main/docs/jackson2-dataformat.adoc | 1 + .../main/docs/avroJackson3-dataformat.adoc | 41 ++++++++++-- .../docs/protobufJackson3-dataformat.adoc | 41 ++++++++++-- .../camel-jq/src/main/docs/jq-language.adoc | 6 ++ .../src/main/docs/scp-component.adoc | 1 + .../src/main/docs/jsonata-component.adoc | 1 + .../src/main/docs/jte-component.adoc | 1 + .../kubernetes-config-maps-component.adoc | 1 + .../src/main/docs/language-component.adoc | 1 + .../src/main/docs/ldif-component.adoc | 1 + .../src/main/docs/log-component.adoc | 2 + .../src/main/docs/lzf-dataformat.adoc | 34 +++++++++- .../src/main/docs/mapstruct-component.adoc | 1 + .../src/main/docs/microprofile-config.adoc | 1 + .../src/main/docs/milo-browse-component.adoc | 1 + .../src/main/docs/mybatis-bean-component.adoc | 1 + .../src/main/docs/observation.adoc | 1 + .../main/docs/platform-http-component.adoc | 1 + .../src/main/docs/servicenow-component.adoc | 3 +- .../src/main/docs/shell-component.adoc | 1 + .../src/main/docs/sjms-component.adoc | 1 + .../src/main/docs/slack-component.adoc | 1 + .../src/main/docs/solr-component.adoc | 1 + .../src/main/docs/splunk-component.adoc | 1 + .../docs/spring-ai-embeddings-component.adoc | 35 ++++++++++ .../src/main/docs/spring-batch-component.adoc | 1 + .../src/main/docs/spring-cloud-config.adoc | 33 ++++++++++ .../src/main/docs/spring-security.adoc | 1 + .../main/docs/string-template-component.adoc | 1 + .../src/main/docs/test-junit6.adoc | 1 + .../src/main/docs/wasm-component.adoc | 1 + 62 files changed, 418 insertions(+), 26 deletions(-) diff --git a/components/camel-ai/camel-djl/src/main/docs/djl-component.adoc b/components/camel-ai/camel-djl/src/main/docs/djl-component.adoc index 0b7cbe5096509..fd66016c8d8bb 100644 --- a/components/camel-ai/camel-djl/src/main/docs/djl-component.adoc +++ b/components/camel-ai/camel-djl/src/main/docs/djl-component.adoc @@ -551,7 +551,7 @@ YAML:: ---- ==== -.Custom deep learning model +._Java-only: creating a custom DJL model with translator and binding to the registry_ [source,java] ---- // create a deep learning model diff --git a/components/camel-ai/camel-huggingface/src/main/docs/huggingface-component.adoc b/components/camel-ai/camel-huggingface/src/main/docs/huggingface-component.adoc index b7cbe04141ad4..8eaa37c5b9b08 100644 --- a/components/camel-ai/camel-huggingface/src/main/docs/huggingface-component.adoc +++ b/components/camel-ai/camel-huggingface/src/main/docs/huggingface-component.adoc @@ -267,6 +267,8 @@ Send multiple messages to "direct:start-chat" — history is maintained automati .Custom Task For a custom task (e.g., _translation_): Define a custom predictor bean in your application or test: + +._Java-only: defining a custom predictor bean_ [source,java] ---- public class TranslationPredictor extends AbstractTaskPredictor { diff --git a/components/camel-ai/camel-langchain4j-chat/src/main/docs/langchain4j-chat-component.adoc b/components/camel-ai/camel-langchain4j-chat/src/main/docs/langchain4j-chat-component.adoc index af2e3d3c41a81..c302224fc6428 100644 --- a/components/camel-ai/camel-langchain4j-chat/src/main/docs/langchain4j-chat-component.adoc +++ b/components/camel-ai/camel-langchain4j-chat/src/main/docs/langchain4j-chat-component.adoc @@ -169,6 +169,7 @@ Add the dependency for LangChain4j OpenAI support: Initialize the OpenAI Chat Model, and add it to the Camel Registry: +._Java-only: programmatic ChatModel initialization and registry binding_ [source,java] ---- ChatModel model = OpenAiChatModel.builder() diff --git a/components/camel-ai/camel-langchain4j-embeddings/src/main/docs/langchain4j-embeddings-component.adoc b/components/camel-ai/camel-langchain4j-embeddings/src/main/docs/langchain4j-embeddings-component.adoc index 41b1eed50b572..eaf49cfa0520d 100644 --- a/components/camel-ai/camel-langchain4j-embeddings/src/main/docs/langchain4j-embeddings-component.adoc +++ b/components/camel-ai/camel-langchain4j-embeddings/src/main/docs/langchain4j-embeddings-component.adoc @@ -147,6 +147,7 @@ Add the dependency for LangChain4j OpenAI support: Initialize the OpenAI Embedding Model: +._Java-only: programmatic EmbeddingModel initialization and registry binding_ [source,java] ---- EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder() diff --git a/components/camel-ai/camel-pgvector/src/main/docs/pgvector-component.adoc b/components/camel-ai/camel-pgvector/src/main/docs/pgvector-component.adoc index a0b3f9f0dc93f..271a96c12ec76 100644 --- a/components/camel-ai/camel-pgvector/src/main/docs/pgvector-component.adoc +++ b/components/camel-ai/camel-pgvector/src/main/docs/pgvector-component.adoc @@ -53,6 +53,7 @@ When using the `SIMILARITY_SEARCH` action, you can filter results using a SQL WH `CamelPgVectorFilter` header. For safe handling of dynamic values, use parameterized queries with `?` placeholders and provide values via the `CamelPgVectorFilterParams` header: +._Java-only: setting parameterized filter headers programmatically_ [source,java] ---- from("direct:search") diff --git a/components/camel-avro-rpc/camel-avro-rpc-component/src/main/docs/avro-component.adoc b/components/camel-avro-rpc/camel-avro-rpc-component/src/main/docs/avro-component.adoc index 47896977e3e9f..b636f60e442ba 100644 --- a/components/camel-avro-rpc/camel-avro-rpc-component/src/main/docs/avro-component.adoc +++ b/components/camel-avro-rpc/camel-avro-rpc-component/src/main/docs/avro-component.adoc @@ -85,6 +85,7 @@ You should use interface for the protocol itself and POJO beans or primitive/Str and result types. Here is an example of the class that corresponds to the schema above: +._Java-only: protocol interface and POJO class definition for Avro RPC_ [source,java] -------------------------------------------------------------- package org.apache.camel.avro.reflection; diff --git a/components/camel-avro/src/main/docs/avro-dataformat.adoc b/components/camel-avro/src/main/docs/avro-dataformat.adoc index 0214d90ee41d8..f01d4a81ecf36 100644 --- a/components/camel-avro/src/main/docs/avro-dataformat.adoc +++ b/components/camel-avro/src/main/docs/avro-dataformat.adoc @@ -49,6 +49,7 @@ include::partial$dataformat-options.adoc[] Using the avro data format is as easy as specifying that the class that you want to marshal or unmarshal in your route. +._Java-only: programmatic AvroDataFormat with schema_ [source,java] -------------------------------------------------------------------------------- AvroDataFormat format = new AvroDataFormat(Value.SCHEMA$); diff --git a/components/camel-aws/camel-aws2-cw/src/main/docs/aws2-cw-component.adoc b/components/camel-aws/camel-aws2-cw/src/main/docs/aws2-cw-component.adoc index 4e1886b60f8aa..975804e68ce18 100644 --- a/components/camel-aws/camel-aws2-cw/src/main/docs/aws2-cw-component.adoc +++ b/components/camel-aws/camel-aws2-cw/src/main/docs/aws2-cw-component.adoc @@ -170,6 +170,7 @@ YAML:: and sends something like +._Java-only: setting CloudWatch metric headers programmatically_ [source,java] ------------------------------- exchange.getIn().setHeader(Cw2Constants.METRIC_NAME, "ExchangesCompleted"); diff --git a/components/camel-aws/camel-aws2-ecs/src/main/docs/aws2-ecs-component.adoc b/components/camel-aws/camel-aws2-ecs/src/main/docs/aws2-ecs-component.adoc index e2907e8a28793..2138511d90762 100644 --- a/components/camel-aws/camel-aws2-ecs/src/main/docs/aws2-ecs-component.adoc +++ b/components/camel-aws/camel-aws2-ecs/src/main/docs/aws2-ecs-component.adoc @@ -122,6 +122,7 @@ YAML:: Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as a body. In AWS ECS there are multiple operations you can submit, as an example for List cluster request, you can do something like: +._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") diff --git a/components/camel-aws/camel-aws2-eks/src/main/docs/aws2-eks-component.adoc b/components/camel-aws/camel-aws2-eks/src/main/docs/aws2-eks-component.adoc index 36f51cbfc82c3..c69aad1de07fa 100644 --- a/components/camel-aws/camel-aws2-eks/src/main/docs/aws2-eks-component.adoc +++ b/components/camel-aws/camel-aws2-eks/src/main/docs/aws2-eks-component.adoc @@ -126,6 +126,7 @@ YAML:: Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as a body. In AWS EKS there are multiple operations you can submit, as an example for List cluster request, you can do something like: +._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") diff --git a/components/camel-aws/camel-aws2-kms/src/main/docs/aws2-kms-component.adoc b/components/camel-aws/camel-aws2-kms/src/main/docs/aws2-kms-component.adoc index 650fbd2d35288..4a552b90e4a91 100644 --- a/components/camel-aws/camel-aws2-kms/src/main/docs/aws2-kms-component.adoc +++ b/components/camel-aws/camel-aws2-kms/src/main/docs/aws2-kms-component.adoc @@ -254,6 +254,7 @@ Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as the body. In AWS KMS there are multiple operations you can submit, as an example for List keys request, you can do something like: +._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:createUser") diff --git a/components/camel-aws/camel-aws2-redshift/src/main/docs/aws2-redshift-data-component.adoc b/components/camel-aws/camel-aws2-redshift/src/main/docs/aws2-redshift-data-component.adoc index 32854918cdd8c..af40fa2de11b9 100644 --- a/components/camel-aws/camel-aws2-redshift/src/main/docs/aws2-redshift-data-component.adoc +++ b/components/camel-aws/camel-aws2-redshift/src/main/docs/aws2-redshift-data-component.adoc @@ -135,6 +135,7 @@ Sometimes building an AWS Request can be complex because of multiple options. We In AWS Redshift Data there are multiple operations you can submit, as an example for List Databases request, you can do something like: +._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") diff --git a/components/camel-aws/camel-aws2-rekognition/src/main/docs/aws2-rekognition-component.adoc b/components/camel-aws/camel-aws2-rekognition/src/main/docs/aws2-rekognition-component.adoc index 4afda31b00339..c885cfaf226f8 100644 --- a/components/camel-aws/camel-aws2-rekognition/src/main/docs/aws2-rekognition-component.adoc +++ b/components/camel-aws/camel-aws2-rekognition/src/main/docs/aws2-rekognition-component.adoc @@ -153,6 +153,7 @@ Sometimes building an AWS Request can be complex because of multiple options. We In AWS Rekognition, there are multiple operations you can submit, as an example for Create Collection request, you can do something like: +._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") diff --git a/components/camel-aws/camel-aws2-ses/src/main/docs/aws2-ses-component.adoc b/components/camel-aws/camel-aws2-ses/src/main/docs/aws2-ses-component.adoc index c9662ec1d1e2e..dd32bc4dae5ce 100644 --- a/components/camel-aws/camel-aws2-ses/src/main/docs/aws2-ses-component.adoc +++ b/components/camel-aws/camel-aws2-ses/src/main/docs/aws2-ses-component.adoc @@ -114,14 +114,61 @@ The `#client` refers to a `SesClient` in the Registry. === Producer Examples +[tabs] +==== +Java:: ++ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .setHeader(SesConstants.SUBJECT, constant("This is my subject")) .setHeader(SesConstants.TO, constant(Collections.singletonList("to@example.com")) .setBody(constant("This is my message text.")) .to("aws2-ses://from@example.com?accessKey=xxx&secretKey=yyy"); --------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + This is my subject + + + to@example.com + + + This is my message text. + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:start + steps: + - setHeader: + name: CamelAwsSesSubject + constant: "This is my subject" + - setHeader: + name: CamelAwsSesTo + constant: "to@example.com" + - setBody: + constant: "This is my message text." + - to: + uri: aws2-ses://from@example.com + parameters: + accessKey: xxx + secretKey: yyy +---- +==== == Dependencies diff --git a/components/camel-aws/camel-aws2-step-functions/src/main/docs/aws2-step-functions-component.adoc b/components/camel-aws/camel-aws2-step-functions/src/main/docs/aws2-step-functions-component.adoc index 8c0d52b9088ff..fac57ecca0ca8 100644 --- a/components/camel-aws/camel-aws2-step-functions/src/main/docs/aws2-step-functions-component.adoc +++ b/components/camel-aws/camel-aws2-step-functions/src/main/docs/aws2-step-functions-component.adoc @@ -145,6 +145,7 @@ Sometimes building an AWS Request can be complex because of multiple options. We In AWS Step Functions, there are multiple operations you can submit, as an example for Create state machine request, you can do something like: +._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:start") diff --git a/components/camel-aws/camel-aws2-sts/src/main/docs/aws2-sts-component.adoc b/components/camel-aws/camel-aws2-sts/src/main/docs/aws2-sts-component.adoc index 81f66349c4eec..41738bba7330e 100644 --- a/components/camel-aws/camel-aws2-sts/src/main/docs/aws2-sts-component.adoc +++ b/components/camel-aws/camel-aws2-sts/src/main/docs/aws2-sts-component.adoc @@ -226,6 +226,7 @@ YAML:: Sometimes building an AWS Request can be complex because of multiple options. We introduce the possibility to use a POJO as the body. In AWS STS, as an example for Assume Role request, you can do something like: +._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------ from("direct:createUser") diff --git a/components/camel-browse/src/main/docs/browse-component.adoc b/components/camel-browse/src/main/docs/browse-component.adoc index c18d78449d2fc..df6c3fbd0a9d1 100644 --- a/components/camel-browse/src/main/docs/browse-component.adoc +++ b/components/camel-browse/src/main/docs/browse-component.adoc @@ -76,6 +76,7 @@ YAML:: We can now inspect the received exchanges from within the Java code: +._Java-only: inspecting received exchanges using the BrowsableEndpoint API_ [source,java] ---- private CamelContext context; diff --git a/components/camel-clickup/src/main/docs/clickup-component.adoc b/components/camel-clickup/src/main/docs/clickup-component.adoc index b397b08e484f8..a956de8c54406 100644 --- a/components/camel-clickup/src/main/docs/clickup-component.adoc +++ b/components/camel-clickup/src/main/docs/clickup-component.adoc @@ -58,6 +58,7 @@ Maven users, for example, can add *netty-http* to their `pom.xml` file: In Java DSL: +._Java-only: processing ClickUp webhook events with Java types and lambdas_ [source,java] --------------------------------------------------------- from("webhook:clickup:?&authorizationToken=&events=taskTimeTrackedUpdated") diff --git a/components/camel-coap/src/main/docs/coap-component.adoc b/components/camel-coap/src/main/docs/coap-component.adoc index c017a03958956..cf287f90de7bc 100644 --- a/components/camel-coap/src/main/docs/coap-component.adoc +++ b/components/camel-coap/src/main/docs/coap-component.adoc @@ -76,6 +76,7 @@ include::spring-boot:partial$starter.adoc[] The COAP server has many configuration options, and this can be configured from a properties file such as `Californium3.properties`. You can specfiy the location of this configuration file on the Camel CoAPComponent, such as: +._Java-only: configuring the CoAP component programmatically_ [source,java] ---- CoAPComponent coap = context.getComponent("coap", CoAPComponent.class); diff --git a/components/camel-debezium/camel-debezium-db2/src/main/docs/debezium-db2-component.adoc b/components/camel-debezium/camel-debezium-db2/src/main/docs/debezium-db2-component.adoc index d20536546c098..24624ce8aed9e 100644 --- a/components/camel-debezium/camel-debezium-db2/src/main/docs/debezium-db2-component.adoc +++ b/components/camel-debezium/camel-debezium-db2/src/main/docs/debezium-db2-component.adoc @@ -153,6 +153,7 @@ To use it, you can either add `Map.class` type when you access the message (e.g. We mentioned above the schema, which can be used in case you need to perform advance data transformation and the schema is needed for that. If you choose not to convert your body to `Map`, you can obtain the schema information as https://kafka.apache.org/22/javadoc/org/apache/kafka/connect/data/Schema.html[`Schema`] type from `Struct` like this: +._Java-only: accessing Kafka Connect Struct schema information_ [source,java] ---- from("debezium-db2:[name]?[options]]) diff --git a/components/camel-debezium/camel-debezium-mongodb/src/main/docs/debezium-mongodb-component.adoc b/components/camel-debezium/camel-debezium-mongodb/src/main/docs/debezium-mongodb-component.adoc index 5ea0e19e61afa..32ec4d56132dd 100644 --- a/components/camel-debezium/camel-debezium-mongodb/src/main/docs/debezium-mongodb-component.adoc +++ b/components/camel-debezium/camel-debezium-mongodb/src/main/docs/debezium-mongodb-component.adoc @@ -84,6 +84,10 @@ See below for more details. Here is a basic route that you can use to listen to Debezium events from MongoDB connector: +[tabs] +==== +Java:: ++ [source,java] ---- from("debezium-mongodb:dbz-test-1?offsetStorageFileName=/usr/offset-file-1.dat&mongodbHosts=rs0/localhost:27017&mongodbUser=debezium&mongodbPassword=dbz&mongodbName=dbserver1&databaseHistoryFileFilename=/usr/history-file-1.dat") @@ -101,6 +105,66 @@ from("debezium-mongodb:dbz-test-1?offsetStorageFileName=/usr/offset-file-1.dat&m .end(); ---- +XML:: ++ +[source,xml] +---- + + + + + + + + + + + ${headers.CamelDebeziumSourceOperation} in 'c,u,r' + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: debezium-mongodb:dbz-test-1 + parameters: + offsetStorageFileName: /usr/offset-file-1.dat + mongodbHosts: rs0/localhost:27017 + mongodbUser: debezium + mongodbPassword: dbz + mongodbName: dbserver1 + databaseHistoryFileFilename: /usr/history-file-1.dat + steps: + - log: + message: "Event received from Debezium : ${body}" + - log: + message: " with this identifier ${headers.CamelDebeziumIdentifier}" + - log: + message: " with these source metadata ${headers.CamelDebeziumSourceMetadata}" + - log: + message: " the event occurred upon this operation '${headers.CamelDebeziumSourceOperation}'" + - log: + message: " on this database '${headers.CamelDebeziumSourceMetadata[db]}' and this table '${headers.CamelDebeziumSourceMetadata[table]}'" + - log: + message: " with the key ${headers.CamelDebeziumKey}" + - choice: + when: + - simple: "${headers.CamelDebeziumSourceOperation} in 'c,u,r'" + steps: + - unmarshal: + json: {} + - log: + message: "Event received from Debezium : ${body}" +---- +==== + By default, the component will emit the events in the body String JSON format in case of `u`, `c` or `r` operations. This can be easily converted to JSON using Camel JSON Data Format e.g.: `.unmarshal().json()` like the above example. In case of operation `d`, the body will be `null`. diff --git a/components/camel-debezium/camel-debezium-mysql/src/main/docs/debezium-mysql-component.adoc b/components/camel-debezium/camel-debezium-mysql/src/main/docs/debezium-mysql-component.adoc index 7dcf6e77bf456..73a5648041afc 100644 --- a/components/camel-debezium/camel-debezium-mysql/src/main/docs/debezium-mysql-component.adoc +++ b/components/camel-debezium/camel-debezium-mysql/src/main/docs/debezium-mysql-component.adoc @@ -169,6 +169,7 @@ To use it, you can either add `Map.class` type when you access the message (e.g. We mentioned above the schema, which can be used in case you need to perform advance data transformation and the schema is needed for that. If you choose not to convert your body to `Map`, you can obtain the schema information as https://kafka.apache.org/22/javadoc/org/apache/kafka/connect/data/Schema.html[`Schema`] type from `Struct` like this: +._Java-only: accessing the Struct schema from a processor_ [source,java] ---- from("debezium-mysql:[name]?[options]]) diff --git a/components/camel-debezium/camel-debezium-oracle/src/main/docs/debezium-oracle-component.adoc b/components/camel-debezium/camel-debezium-oracle/src/main/docs/debezium-oracle-component.adoc index 5108af3c516db..12aa007901141 100644 --- a/components/camel-debezium/camel-debezium-oracle/src/main/docs/debezium-oracle-component.adoc +++ b/components/camel-debezium/camel-debezium-oracle/src/main/docs/debezium-oracle-component.adoc @@ -151,6 +151,7 @@ To use it, you can either add `Map.class` type when you access the message (e.g. We mentioned above the schema, which can be used in case you need to perform advance data transformation and the schema is needed for that. If you choose not to convert your body to `Map`, you can obtain the schema information as https://kafka.apache.org/22/javadoc/org/apache/kafka/connect/data/Schema.html[`Schema`] type from `Struct` like this: +._Java-only: accessing the Struct schema from a processor_ [source,java] ---- from("debezium-oracle:[name]?[options]]) diff --git a/components/camel-debezium/camel-debezium-postgres/src/main/docs/debezium-postgres-component.adoc b/components/camel-debezium/camel-debezium-postgres/src/main/docs/debezium-postgres-component.adoc index c8929c947ccd7..2bc1d50858093 100644 --- a/components/camel-debezium/camel-debezium-postgres/src/main/docs/debezium-postgres-component.adoc +++ b/components/camel-debezium/camel-debezium-postgres/src/main/docs/debezium-postgres-component.adoc @@ -151,6 +151,7 @@ To use it, you can either add `Map.class` type when you access the message (e.g. We mentioned above the schema, which can be used in case you need to perform advance data transformation and the schema is needed for that. If you choose not to convert your body to `Map`, you can obtain the schema information as https://kafka.apache.org/22/javadoc/org/apache/kafka/connect/data/Schema.html[`Schema`] type from `Struct` like this: +._Java-only: accessing the Struct schema from a processor_ [source,java] ---- from("debezium-postgres:[name]?[options]]) diff --git a/components/camel-debezium/camel-debezium-sqlserver/src/main/docs/debezium-sqlserver-component.adoc b/components/camel-debezium/camel-debezium-sqlserver/src/main/docs/debezium-sqlserver-component.adoc index 46b17fbf529bd..93881f673cfb9 100644 --- a/components/camel-debezium/camel-debezium-sqlserver/src/main/docs/debezium-sqlserver-component.adoc +++ b/components/camel-debezium/camel-debezium-sqlserver/src/main/docs/debezium-sqlserver-component.adoc @@ -149,6 +149,7 @@ To use it, you can either add `Map.class` type when you access the message (e.g. We mentioned above the schema, which can be used in case you need to perform advance data transformation and the schema is needed for that. If you choose not to convert your body to `Map`, you can obtain the schema information as https://kafka.apache.org/22/javadoc/org/apache/kafka/connect/data/Schema.html[`Schema`] type from `Struct` like this: +._Java-only: accessing the Struct schema from a processor_ [source,java] ---- from("debezium-sqlserver:[name]?[options]]) diff --git a/components/camel-freemarker/src/main/docs/freemarker-component.adoc b/components/camel-freemarker/src/main/docs/freemarker-component.adoc index 4c5f5353b537f..1f8d19ea5e971 100644 --- a/components/camel-freemarker/src/main/docs/freemarker-component.adoc +++ b/components/camel-freemarker/src/main/docs/freemarker-component.adoc @@ -93,6 +93,7 @@ a `Map`). The `Exchange` is transferred as: You can set up your custom FreeMarker context in the message header with the key "*CamelFreemarkerDataModel*" just like this +._Java-only: setting a custom FreeMarker data model via headers_ [source,java] -------------------------------------------------------------------- Map variableMap = new HashMap(); diff --git a/components/camel-geocoder/src/main/docs/geocoder-component.adoc b/components/camel-geocoder/src/main/docs/geocoder-component.adoc index 8650c576c4fd0..6286e5846bbd7 100644 --- a/components/camel-geocoder/src/main/docs/geocoder-component.adoc +++ b/components/camel-geocoder/src/main/docs/geocoder-component.adoc @@ -111,6 +111,7 @@ If you provide a header with the `CamelGeoCoderAddress` then that overrides the endpoint configuration, so to get the location of Copenhagen, Denmark we can send a message with a headers as shown: +._Java-only: overriding the address via a message header_ [source,java] ------------------------------------------------------------------------------------------------------ template.sendBodyAndHeader("direct:start", "Hello", GeoCoderConstants.ADDRESS, "Copenhagen, Denmark"); diff --git a/components/camel-ical/src/main/docs/ical-dataformat.adoc b/components/camel-ical/src/main/docs/ical-dataformat.adoc index 9316ae9430817..02286206359ce 100644 --- a/components/camel-ical/src/main/docs/ical-dataformat.adoc +++ b/components/camel-ical/src/main/docs/ical-dataformat.adoc @@ -16,6 +16,7 @@ http://en.wikipedia.org/wiki/ICalendar[iCalendar] messages. A typical iCalendar message looks like: +._Java-only: example of an iCalendar message format_ [source,java] ---------------------------------------------------------------------- BEGIN:VCALENDAR diff --git a/components/camel-iso8583/src/main/docs/iso8583-dataformat.adoc b/components/camel-iso8583/src/main/docs/iso8583-dataformat.adoc index 192d0e364ebe6..9b5841579a2bc 100644 --- a/components/camel-iso8583/src/main/docs/iso8583-dataformat.adoc +++ b/components/camel-iso8583/src/main/docs/iso8583-dataformat.adoc @@ -175,6 +175,7 @@ YAML:: Instead of simple language you can also use Groovy which has a special support in J8583 library: +._Java-only: using Groovy language for ISO-8583 field extraction_ [source,java] ---- from("jms:payment:response") diff --git a/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc b/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc index 7e3143ace3abd..47e770dd032e2 100644 --- a/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc +++ b/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc @@ -23,12 +23,43 @@ same way as its JSON counterpart, and thus can be used with classes annotated for JSON serialization/deserialization. ==== +[tabs] +==== +Java:: ++ [source,java] -------------------------------- -from("kafka:topic"). - unmarshal().avro(JsonNode.class). - to("log:info"); -------------------------------- +---- +from("kafka:topic") + .unmarshal().avro(JsonNode.class) + .to("log:info"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: kafka:topic + steps: + - unmarshal: + avro: + library: Jackson + - to: + uri: log:info +---- +==== == Avro Jackson Options diff --git a/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc b/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc index 82f1183fcecb3..b4aa2c73e7ab5 100644 --- a/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc +++ b/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc @@ -23,12 +23,43 @@ same way as its JSON counterpart, and thus can be used with classes annotated for JSON serialization/deserialization. ==== +[tabs] +==== +Java:: ++ [source,java] -------------------------------- -from("kafka:topic"). - unmarshal().protobuf(ProtobufLibrary.Jackson, JsonNode.class). - to("log:info"); -------------------------------- +---- +from("kafka:topic") + .unmarshal().protobuf(ProtobufLibrary.Jackson, JsonNode.class) + .to("log:info"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: kafka:topic + steps: + - unmarshal: + protobuf: + library: Jackson + - to: + uri: log:info +---- +==== == Protobuf Jackson Options diff --git a/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc b/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc index 9fae12ab3a387..b4844ac952faf 100644 --- a/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc +++ b/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc @@ -90,6 +90,7 @@ from `JSonNode` to `String` or vice versa. To enable POJO conversion support for `camel-jackson` then this must be enabled, which is done by setting the following options on the `CamelContext` global options, as shown: +._Java-only: enabling Jackson POJO type conversion on the CamelContext_ [source,java] ---- // Enable Jackson JSON type converter for more types. diff --git a/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc b/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc index ad27efe00c7b7..722a413ce9ec1 100644 --- a/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc +++ b/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc @@ -23,12 +23,43 @@ same way as its JSON counterpart, and thus can be used with classes annotated for JSON serialization/deserialization. ==== +[tabs] +==== +Java:: ++ [source,java] -------------------------------- -from("kafka:topic"). - unmarshal().avro(JsonNode.class). - to("log:info"); -------------------------------- +---- +from("kafka:topic") + .unmarshal().avro(JsonNode.class) + .to("log:info"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: kafka:topic + steps: + - unmarshal: + avro: + library: Jackson + - to: + uri: log:info +---- +==== == Avro Jackson Options diff --git a/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc b/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc index 29afb5d69baec..abb80cf58719d 100644 --- a/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc +++ b/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc @@ -23,12 +23,43 @@ same way as its JSON counterpart, and thus can be used with classes annotated for JSON serialization/deserialization. ==== +[tabs] +==== +Java:: ++ [source,java] -------------------------------- -from("kafka:topic"). - unmarshal().protobuf(ProtobufLibrary.Jackson, JsonNode.class). - to("log:info"); -------------------------------- +---- +from("kafka:topic") + .unmarshal().protobuf(ProtobufLibrary.Jackson, JsonNode.class) + .to("log:info"); +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: kafka:topic + steps: + - unmarshal: + protobuf: + library: Jackson + - to: + uri: log:info +---- +==== == Protobuf Jackson Options diff --git a/components/camel-jq/src/main/docs/jq-language.adoc b/components/camel-jq/src/main/docs/jq-language.adoc index 1bb4cc47d2845..b0742d1289b2a 100644 --- a/components/camel-jq/src/main/docs/jq-language.adoc +++ b/components/camel-jq/src/main/docs/jq-language.adoc @@ -33,6 +33,7 @@ By default, JQ uses the message body as the input source. However, you can also For example, to count the number of books from a JSON document that was stored in a header named `books` you can do: +._Java-only: using header as JQ input source_ [source,java] ---- from("direct:start") @@ -55,6 +56,7 @@ The camel-jq adds the following functions: For example, to set the property foo with the value from the Message header `MyHeader': +._Java-only: using the header function_ [source, java] ---- from("direct:start") @@ -65,6 +67,7 @@ from("direct:start") Or from the exchange property: +._Java-only: using the property function_ [source, java] ---- from("direct:start") @@ -75,6 +78,7 @@ from("direct:start") And using a constant value +._Java-only: using the constant function_ [source, java] ---- from("direct:start") @@ -85,6 +89,7 @@ from("direct:start") Or using an exchange variable: +._Java-only: using the variable function_ [source, java] ---- from("direct:start") @@ -96,6 +101,7 @@ from("direct:start") The `header`, `property` and `variable` functions also support returning a default value in case the key does not exist, as shown in the following: +._Java-only: using the header function with a default value_ [source, java] ---- from("direct:start") diff --git a/components/camel-jsch/src/main/docs/scp-component.adoc b/components/camel-jsch/src/main/docs/scp-component.adoc index 9ca76ef54dd5d..12f5625ba1789 100644 --- a/components/camel-jsch/src/main/docs/scp-component.adoc +++ b/components/camel-jsch/src/main/docs/scp-component.adoc @@ -55,6 +55,7 @@ include::partial$component-endpoint-headers.adoc[] Camel supports OpenSSH certificate-based authentication for SCP connections, where a user's public key is signed by a Certificate Authority (CA). This is configured using the `certFile`, `certUri`, or `certBytes` parameters alongside the private key: +._Java-only: configuring certificate-based authentication_ [source,java] ---- to("scp://host/path?username=myuser" diff --git a/components/camel-jsonata/src/main/docs/jsonata-component.adoc b/components/camel-jsonata/src/main/docs/jsonata-component.adoc index 4ab628de36938..ddce4b8416255 100644 --- a/components/camel-jsonata/src/main/docs/jsonata-component.adoc +++ b/components/camel-jsonata/src/main/docs/jsonata-component.adoc @@ -176,6 +176,7 @@ YAML:: A custom binding might look like the following: +._Java-only: implementing a custom JsonataFrameBinding_ [source,java] --------------------------------------------------------------- @NoArgsConstructor diff --git a/components/camel-jte/src/main/docs/jte-component.adoc b/components/camel-jte/src/main/docs/jte-component.adoc index b8cae77371b59..27e18a93f2519 100644 --- a/components/camel-jte/src/main/docs/jte-component.adoc +++ b/components/camel-jte/src/main/docs/jte-component.adoc @@ -125,6 +125,7 @@ YAML:: To use a JTE template to formulate a response to the REST get call: +._Java-only: example JTE template file content_ [source,java] ---- @import org.apache.camel.component.jte.Model diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-config-maps-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-config-maps-component.adoc index 8929d5feac0ac..c5ea3e27deee9 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-config-maps-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-config-maps-component.adoc @@ -139,6 +139,7 @@ This operation returns a List of ConfigMaps from your cluster, using a label sel === Kubernetes ConfigMaps Consumer Example +._Java-only: consuming ConfigMap events with a custom processor_ [source,java] -------------------------------------------------------------------------------- fromF("kubernetes-config-maps://%s?oauthToken=%s", host, authToken) diff --git a/components/camel-language/src/main/docs/language-component.adoc b/components/camel-language/src/main/docs/language-component.adoc index 5c42a092c9c84..5854114712a12 100644 --- a/components/camel-language/src/main/docs/language-component.adoc +++ b/components/camel-language/src/main/docs/language-component.adoc @@ -163,6 +163,7 @@ You can also provide the script as a header as shown below. Here we use xref:languages:xpath-language.adoc[XPath] language to extract the text from the `` tag. +._Java-only: providing the script as a message header_ [source,java] ---- Object out = producer.requestBodyAndHeader("language:xpath", "Hello World", Exchange.LANGUAGE_SCRIPT, "/foo/text()"); diff --git a/components/camel-ldif/src/main/docs/ldif-component.adoc b/components/camel-ldif/src/main/docs/ldif-component.adoc index 4630d703ee303..2f37cb772a9a0 100644 --- a/components/camel-ldif/src/main/docs/ldif-component.adoc +++ b/components/camel-ldif/src/main/docs/ldif-component.adoc @@ -113,6 +113,7 @@ Following on from the Spring configuration above, the code sample below sends an LDAP request to filter search a group for a member. The Common Name is then extracted from the response. +._Java-only: sending LDIF content using the ProducerTemplate_ [source,java] ---- ProducerTemplate template = exchange.getContext().createProducerTemplate(); diff --git a/components/camel-log/src/main/docs/log-component.adoc b/components/camel-log/src/main/docs/log-component.adoc index d777da7e44a98..660231cd3803c 100644 --- a/components/camel-log/src/main/docs/log-component.adoc +++ b/components/camel-log/src/main/docs/log-component.adoc @@ -266,6 +266,8 @@ You can enable security masking for logging by setting `logMask` flag to `true`. Note that this option also affects Log EIP. To enable mask in Java DSL at CamelContext level: + +._Java-only: enabling log masking on CamelContext_ [source,java] ---- camelContext.setLogMask(true); diff --git a/components/camel-lzf/src/main/docs/lzf-dataformat.adoc b/components/camel-lzf/src/main/docs/lzf-dataformat.adoc index 6a64d0e3f3bda..4b89b72db80d3 100644 --- a/components/camel-lzf/src/main/docs/lzf-dataformat.adoc +++ b/components/camel-lzf/src/main/docs/lzf-dataformat.adoc @@ -73,10 +73,40 @@ In this example we unmarshal a LZF payload from an ActiveMQ queue called MY_QUEUE to its original format, and forward it for processing to the `UnGZippedMessageProcessor`. +[tabs] +==== +Java:: ++ [source,java] ----------------------------------------------------------------------------------------------- +---- from("activemq:queue:MY_QUEUE").unmarshal().lzf().process(new UnCompressedMessageProcessor()); ----------------------------------------------------------------------------------------------- +---- + +XML:: ++ +[source,xml] +---- + + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: activemq:queue:MY_QUEUE + steps: + - unmarshal: + lzf: {} + - process: + ref: unCompressedMessageProcessor +---- +==== == Dependencies diff --git a/components/camel-mapstruct/src/main/docs/mapstruct-component.adoc b/components/camel-mapstruct/src/main/docs/mapstruct-component.adoc index f6f9e0af8c560..14d1aa77cacc2 100644 --- a/components/camel-mapstruct/src/main/docs/mapstruct-component.adoc +++ b/components/camel-mapstruct/src/main/docs/mapstruct-component.adoc @@ -40,6 +40,7 @@ This is necessary because the _Mapper_ classes are to be used for converting POJ For example, to set up two packages, you can do the following: +._Java-only: configuring MapStruct mapper packages programmatically_ [source,java] ---- MapstructComponent mc = context.getComponent("mapstruct", MapstructComponent.class); diff --git a/components/camel-microprofile/camel-microprofile-config/src/main/docs/microprofile-config.adoc b/components/camel-microprofile/camel-microprofile-config/src/main/docs/microprofile-config.adoc index 7fef520d120ff..92df3c0f1cd08 100644 --- a/components/camel-microprofile/camel-microprofile-config/src/main/docs/microprofile-config.adoc +++ b/components/camel-microprofile/camel-microprofile-config/src/main/docs/microprofile-config.adoc @@ -20,6 +20,7 @@ To enable this, add this component to the classpath and Camel should auto-detect You can also register the microprofile-config component manually with the Apache Camel Properties Component as shown below: +._Java-only: registering MicroProfile Config properties source_ [source,java] ---- PropertiesComponent pc = (PropertiesComponent) camelContext.getPropertiesComponent(); diff --git a/components/camel-milo/src/main/docs/milo-browse-component.adoc b/components/camel-milo/src/main/docs/milo-browse-component.adoc index e1d0e997b38c4..525d2b395772f 100644 --- a/components/camel-milo/src/main/docs/milo-browse-component.adoc +++ b/components/camel-milo/src/main/docs/milo-browse-component.adoc @@ -67,6 +67,7 @@ the node tree of the OPC-UA server, e.g. to avoid hard-coding a significant numb Camel routes. The component is designed to work in conjunction with the Camel Milo Client component as illustrated in the following example: +._Java-only: browsing OPC UA nodes and enriching with client values_ [source,java] ---- from("direct:start") diff --git a/components/camel-mybatis/src/main/docs/mybatis-bean-component.adoc b/components/camel-mybatis/src/main/docs/mybatis-bean-component.adoc index e1c9d9a1bb6ea..9012b69229653 100644 --- a/components/camel-mybatis/src/main/docs/mybatis-bean-component.adoc +++ b/components/camel-mybatis/src/main/docs/mybatis-bean-component.adoc @@ -111,6 +111,7 @@ bean annotations. You can configure type alias in the SqlMapConfig file: On the `AccountService` bean you can declare the MyBatis mappins using annotations as shown: +._Java-only: MyBatis bean annotation mappings_ [source,java] ---- public interface AccountService { diff --git a/components/camel-observation/src/main/docs/observation.adoc b/components/camel-observation/src/main/docs/observation.adoc index f67deeb341dbc..8a3758c1859e3 100644 --- a/components/camel-observation/src/main/docs/observation.adoc +++ b/components/camel-observation/src/main/docs/observation.adoc @@ -47,6 +47,7 @@ To explicitly configure OpenTelemetry support, instantiate the `OpenTelemetryTra context. You can optionally specify a `Tracer`, or alternatively it can be implicitly discovered using the `Registry` +._Java-only: configuring MicrometerObservationTracer with metrics and tracing_ [source,java] -------------------------------------------------------------------------------------------------- ObservationRegistry observationRegistry = ObservationRegistry.create(); diff --git a/components/camel-platform-http/src/main/docs/platform-http-component.adoc b/components/camel-platform-http/src/main/docs/platform-http-component.adoc index 4012562bc57c1..d4f3b31b0e568 100644 --- a/components/camel-platform-http/src/main/docs/platform-http-component.adoc +++ b/components/camel-platform-http/src/main/docs/platform-http-component.adoc @@ -176,6 +176,7 @@ For valid tokens, the token validation result is stored on the exchange as the principal name, token scopes, and immutable token attributes/claims. The raw `Authorization` header is removed before the route is invoked and from OAuth rejection responses. +._Java-only: accessing OAuth token validation result in a processor_ [source,java] ---- import org.apache.camel.component.platform.http.PlatformHttpConstants; diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc b/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc index 5910a05210710..b84824bfb1a55 100644 --- a/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc +++ b/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc @@ -132,6 +132,7 @@ https://docs.servicenow.com/bundle/helsinki-servicenow-platform/page/integrate/i == Examples: +._Java-only: retrieving 10 Incidents with FluentProducerTemplate_ [source,java] .Retrieve 10 Incidents ------------------------------------------------------------------------------------------------------------------- @@ -145,7 +146,7 @@ context.addRoutes(new RouteBuilder() { + "&oauthClientSecret={{env:SERVICENOW_OAUTH2_CLIENT_SECRET}}" .to("mock:servicenow"); } -}); +}); FluentProducerTemplate.on(context) .withHeader(ServiceNowConstants.RESOURCE, "table") diff --git a/components/camel-shell/src/main/docs/shell-component.adoc b/components/camel-shell/src/main/docs/shell-component.adoc index 6986fb3a0a4b8..d372188301a9f 100644 --- a/components/camel-shell/src/main/docs/shell-component.adoc +++ b/components/camel-shell/src/main/docs/shell-component.adoc @@ -137,6 +137,7 @@ YAML:: === Route to JMS (fire-and-forget) +._Java-only: using ExchangePattern.InOnly with shell consumer_ [source,java] ---- from("shell:myapp") diff --git a/components/camel-sjms/src/main/docs/sjms-component.adoc b/components/camel-sjms/src/main/docs/sjms-component.adoc index b3cc1d0df2058..a2204e18c47f4 100644 --- a/components/camel-sjms/src/main/docs/sjms-component.adoc +++ b/components/camel-sjms/src/main/docs/sjms-component.adoc @@ -146,6 +146,7 @@ part of the JMS endpoint URL, but it will be ignored in this example. In the `computeDestination` bean, specify the real destination by setting the `CamelJmsDestinationName` header as follows: +._Java-only: setting JMS destination header dynamically_ [source,java] ------------------------------------------------------------------------- public void setJmsHeader(Exchange exchange) { diff --git a/components/camel-slack/src/main/docs/slack-component.adoc b/components/camel-slack/src/main/docs/slack-component.adoc index 9eda292877af7..8a119909c2d27 100644 --- a/components/camel-slack/src/main/docs/slack-component.adoc +++ b/components/camel-slack/src/main/docs/slack-component.adoc @@ -114,6 +114,7 @@ YAML:: You can now use the Slack API model to create blocks. You can read more about it here https://api.slack.com/block-kit +._Java-only: creating Slack Block Kit messages with the API model_ [source,java] --------------------------------------------------------------------------------------------------------------------------- public void testSlackAPIModelMessage() { diff --git a/components/camel-solr/src/main/docs/solr-component.adoc b/components/camel-solr/src/main/docs/solr-component.adoc index 19d7e3f0e0031..0bab1731087aa 100644 --- a/components/camel-solr/src/main/docs/solr-component.adoc +++ b/components/camel-solr/src/main/docs/solr-component.adoc @@ -176,6 +176,7 @@ YAML:: A client would simply need to pass a body message to the insert or delete routes and then call the commit route. +._Java-only: sending messages to Solr routes using ProducerTemplate_ [source,java] ----------------------------------------------- template.sendBodyAndHeader("direct:insert", "1234", "CamelSolrParam.commit", true); diff --git a/components/camel-splunk/src/main/docs/splunk-component.adoc b/components/camel-splunk/src/main/docs/splunk-component.adoc index dd58f136b36e6..172dd82e9637f 100644 --- a/components/camel-splunk/src/main/docs/splunk-component.adoc +++ b/components/camel-splunk/src/main/docs/splunk-component.adoc @@ -251,6 +251,7 @@ YAML:: To convert a Tweet to a `SplunkEvent`, you could use a converter like: +._Java-only: custom type converter from Tweet to SplunkEvent_ [source,java] ---------------------------------------------------------------------------------- @Converter diff --git a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/docs/spring-ai-embeddings-component.adoc b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/docs/spring-ai-embeddings-component.adoc index fc919524d1ea3..33c489dadd3a3 100644 --- a/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/docs/spring-ai-embeddings-component.adoc +++ b/components/camel-spring-parent/camel-spring-ai/camel-spring-ai-embeddings/src/main/docs/spring-ai-embeddings-component.adoc @@ -103,6 +103,10 @@ When processing a single String, the component returns: === Batch Processing Example +[tabs] +==== +Java:: ++ [source,java] ---- from("direct:batch") @@ -111,6 +115,37 @@ from("direct:batch") .log("Number of embeddings: ${body.size()}"); ---- +XML:: ++ +[source,xml] +---- + + + + ["text 1", "text 2", "text 3"] + + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct:batch + steps: + - setBody: + constant: '["text 1", "text 2", "text 3"]' + - to: + uri: spring-ai-embeddings:myEmbedding + - log: + message: "Number of embeddings: ${body.size()}" +---- +==== + When processing a List, the component returns: * **Message Body**: List of embedding vectors as `List` diff --git a/components/camel-spring-parent/camel-spring-batch/src/main/docs/spring-batch-component.adoc b/components/camel-spring-parent/camel-spring-batch/src/main/docs/spring-batch-component.adoc index fb1e1134eb41a..024468e1a8f26 100644 --- a/components/camel-spring-parent/camel-spring-batch/src/main/docs/spring-batch-component.adoc +++ b/components/camel-spring-parent/camel-spring-batch/src/main/docs/spring-batch-component.adoc @@ -158,6 +158,7 @@ A `JobExecution` instance returned by the message. You can use the `JobExecution` instance to perform some operations using the Spring Batch API directly. +._Java-only: accessing JobExecution from MockEndpoint_ [source,java] --------------------------------------------------------------------------------------------------- from("direct:startBatch").to("spring-batch:myJob").to("mock:JobExecutions"); diff --git a/components/camel-spring-parent/camel-spring-cloud-config/src/main/docs/spring-cloud-config.adoc b/components/camel-spring-parent/camel-spring-cloud-config/src/main/docs/spring-cloud-config.adoc index 47af7ab8117f5..0d6241f663232 100644 --- a/components/camel-spring-parent/camel-spring-cloud-config/src/main/docs/spring-cloud-config.adoc +++ b/components/camel-spring-parent/camel-spring-cloud-config/src/main/docs/spring-cloud-config.adoc @@ -80,6 +80,10 @@ camel.vault.spring-config.password=configPass camel.vault.spring-config.label=latest ---- +[tabs] +==== +Java:: ++ [source,java] ---- from("direct") @@ -87,6 +91,35 @@ from("direct") .to("log"); ---- +XML:: ++ +[source,xml] +---- + + + + {{spring-config:custom.property}} + + + +---- + +YAML:: ++ +[source,yaml] +---- +- route: + from: + uri: direct + steps: + - setHeader: + name: MyHeader + simple: "{{spring-config:custom.property}}" + - to: + uri: log +---- +==== + == Automatic Configuration Reload The component includes a periodic task that monitors Spring Cloud Config properties for changes and triggers a Camel context reload when property values have changed. diff --git a/components/camel-spring-parent/camel-spring-security/src/main/docs/spring-security.adoc b/components/camel-spring-parent/camel-spring-security/src/main/docs/spring-security.adoc index 35f58d12da51c..ba8149ab54d10 100644 --- a/components/camel-spring-parent/camel-spring-security/src/main/docs/spring-security.adoc +++ b/components/camel-spring-parent/camel-spring-security/src/main/docs/spring-security.adoc @@ -151,6 +151,7 @@ are collected, they need to be placed in the In message or the `SecurityContextHolder` so the Camel xref:spring-security.adoc[Spring Security] component can access them: +._Java-only: extracting credentials from HTTP header and creating a Subject_ [source,java] ---- import javax.security.auth.Subject; diff --git a/components/camel-stringtemplate/src/main/docs/string-template-component.adoc b/components/camel-stringtemplate/src/main/docs/string-template-component.adoc index a2e4d1dca76bb..79bcc955491d8 100644 --- a/components/camel-stringtemplate/src/main/docs/string-template-component.adoc +++ b/components/camel-stringtemplate/src/main/docs/string-template-component.adoc @@ -104,6 +104,7 @@ You can define the custom context map by setting the message header "*CamelStringTemplateVariableMap*" just like the below code. +._Java-only: setting up a custom StringTemplate variable map_ [source,java] -------------------------------------------------------------------------- Map variableMap = new HashMap(); diff --git a/components/camel-test/camel-test-junit6/src/main/docs/test-junit6.adoc b/components/camel-test/camel-test-junit6/src/main/docs/test-junit6.adoc index ba3f78bfe8719..34ff1201b1047 100644 --- a/components/camel-test/camel-test-junit6/src/main/docs/test-junit6.adoc +++ b/components/camel-test/camel-test-junit6/src/main/docs/test-junit6.adoc @@ -21,6 +21,7 @@ for build the routes to be tested. Then the methods with `@Test` annotations are will be executed. The base class `CamelTestSupport` has a number of helper methods to configure testing, see more at the Javadoc of this class. +._Java-only: CamelTestSupport unit test example_ [source,java] ---- import org.apache.camel.RoutesBuilder; diff --git a/components/camel-wasm/src/main/docs/wasm-component.adoc b/components/camel-wasm/src/main/docs/wasm-component.adoc index fdd35e275845a..f940ef6526c92 100644 --- a/components/camel-wasm/src/main/docs/wasm-component.adoc +++ b/components/camel-wasm/src/main/docs/wasm-component.adoc @@ -86,6 +86,7 @@ data exchange leverages Wasm's memory that can be accessed by both the host and At this stage, the data structure that the component exchange with the Wasm function is a subset of the Apache Camel Message, containing headers the body encoded as a base64 string: +._Java-only: data exchange wrapper class for Wasm module communication_ [source,java] ------------------------------------------------- public static class Wrapper { From c39733036a13e872026a65ad41d6215bb193d616 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 11:01:32 +0200 Subject: [PATCH 85/87] CAMEL-23789: Normalize AsciiDoc code block delimiters to 4 dashes Standardize all long dash delimiters (e.g. ----------------) to the standard 4-dash format (----) across all component docs modified in this branch. Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../src/main/docs/arangodb-component.adoc | 16 +-- .../src/main/docs/asn1-dataformat.adoc | 16 +-- .../src/main/docs/atom-component.adoc | 8 +- .../src/main/docs/avro-component.adoc | 36 ++--- .../src/main/docs/avro-dataformat.adoc | 16 +-- .../src/main/docs/aws-bedrock-component.adoc | 132 +++++++++--------- .../main/docs/aws-security-hub-component.adoc | 24 ++-- .../src/main/docs/aws2-athena-component.adoc | 8 +- .../main/docs/aws2-comprehend-component.adoc | 24 ++-- .../src/main/docs/aws2-cw-component.adoc | 12 +- .../src/main/docs/aws2-ddb-component.adoc | 48 +++---- .../src/main/docs/aws2-ec2-component.adoc | 36 ++--- .../src/main/docs/aws2-ecs-component.adoc | 12 +- .../src/main/docs/aws2-eks-component.adoc | 12 +- .../main/docs/aws2-eventbridge-component.adoc | 8 +- .../src/main/docs/aws2-iam-component.adoc | 12 +- .../docs/aws2-kinesis-firehose-component.adoc | 12 +- .../src/main/docs/aws2-kms-component.adoc | 12 +- .../src/main/docs/aws2-lambda-component.adoc | 12 +- .../src/main/docs/aws2-mq-component.adoc | 16 +-- .../src/main/docs/aws2-msk-component.adoc | 20 +-- .../src/main/docs/aws2-polly-component.adoc | 24 ++-- .../docs/aws2-redshift-data-component.adoc | 12 +- .../main/docs/aws2-rekognition-component.adoc | 12 +- .../src/main/docs/aws2-s3-component.adoc | 8 +- .../src/main/docs/aws2-ses-component.adoc | 8 +- .../src/main/docs/aws2-sns-component.adoc | 16 +-- .../src/main/docs/aws2-sqs-component.adoc | 16 +-- .../docs/aws2-step-functions-component.adoc | 12 +- .../src/main/docs/aws2-sts-component.adoc | 12 +- .../main/docs/aws2-timestream-component.adoc | 16 +-- .../main/docs/aws2-translate-component.adoc | 16 +-- .../main/docs/azure-cosmosdb-component.adoc | 8 +- .../main/docs/azure-eventhubs-component.adoc | 8 +- .../main/docs/azure-functions-component.adoc | 4 +- .../main/docs/azure-key-vault-component.adoc | 8 +- .../main/docs/azure-servicebus-component.adoc | 16 +-- .../docs/azure-storage-blob-component.adoc | 24 ++-- .../azure-storage-datalake-component.adoc | 4 +- .../docs/azure-storage-queue-component.adoc | 12 +- .../src/main/docs/barcode-dataformat.adoc | 24 ++-- .../main/docs/bean-validator-component.adoc | 48 +++---- .../src/main/docs/bean-component.adoc | 12 +- .../src/main/docs/bindy-dataformat.adoc | 4 +- .../src/main/docs/browse-component.adoc | 4 +- .../src/main/docs/camunda-component.adoc | 16 +-- .../src/main/docs/cql-component.adoc | 16 +-- .../src/main/docs/clickup-component.adoc | 16 +-- .../src/main/docs/coap-component.adoc | 4 +- .../src/main/docs/consul-component.adoc | 8 +- .../src/main/docs/couchbase-component.adoc | 8 +- .../src/main/docs/couchdb-component.adoc | 8 +- .../src/main/docs/pgp-dataformat.adoc | 32 ++--- .../src/main/docs/crypto-component.adoc | 8 +- .../src/main/docs/crypto-dataformat.adoc | 56 ++++---- .../src/main/docs/csv-dataformat.adoc | 80 +++++------ .../src/main/docs/cxfrs-component.adoc | 32 ++--- .../src/main/docs/cxf-transport.adoc | 20 +-- .../main/docs/cyberark-vault-component.adoc | 4 +- .../src/main/docs/datasonnet-language.adoc | 36 ++--- .../src/main/docs/debezium-db2-component.adoc | 4 +- .../main/docs/debezium-mongodb-component.adoc | 4 +- .../main/docs/debezium-mysql-component.adoc | 4 +- .../main/docs/debezium-oracle-component.adoc | 4 +- .../docs/debezium-postgres-component.adoc | 4 +- .../docs/debezium-sqlserver-component.adoc | 4 +- .../src/main/docs/disruptor-component.adoc | 36 ++--- .../src/main/docs/ehcache-component.adoc | 16 +-- .../src/main/docs/exec-component.adoc | 16 +-- .../src/main/docs/file-component.adoc | 4 +- .../src/main/docs/flatpack-component.adoc | 36 ++--- .../src/main/docs/flatpack-dataformat.adoc | 12 +- .../src/main/docs/flink-component.adoc | 8 +- .../src/main/docs/freemarker-component.adoc | 20 +-- .../src/main/docs/sftp-component.adoc | 4 +- .../src/main/docs/geocoder-component.adoc | 16 +-- .../src/main/docs/git-component.adoc | 20 +-- .../src/main/docs/github2-component.adoc | 8 +- .../main/docs/google-bigquery-component.adoc | 24 ++-- .../docs/google-bigquery-sql-component.adoc | 28 ++-- .../main/docs/google-firestore-component.adoc | 32 ++--- .../main/docs/google-functions-component.adoc | 16 +-- .../main/docs/google-pubsub-component.adoc | 4 +- .../docs/google-secret-manager-component.adoc | 16 +-- .../docs/google-speech-to-text-component.adoc | 16 +-- .../main/docs/google-storage-component.adoc | 16 +-- .../docs/google-text-to-speech-component.adoc | 16 +-- .../main/docs/google-vision-component.adoc | 16 +-- .../src/main/docs/graphql-component.adoc | 4 +- .../src/main/docs/groovy-language.adoc | 20 +-- .../src/main/docs/grpc-component.adoc | 16 +-- .../main/docs/hazelcast-map-component.adoc | 56 ++++---- .../docs/hazelcast-multimap-component.adoc | 36 ++--- .../hazelcast-replicatedmap-component.adoc | 32 ++--- .../docs/hazelcast-ringbuffer-component.adoc | 8 +- .../src/main/docs/http-component.adoc | 68 ++++----- .../src/main/docs/hwcloud-smn-component.adoc | 8 +- .../src/main/docs/ibm-cos-component.adoc | 8 +- .../docs/ibm-secrets-manager-component.adoc | 4 +- .../ibm-watson-speech-to-text-component.adoc | 20 +-- .../ibm-watson-text-to-speech-component.adoc | 20 +-- .../main/docs/ibm-watsonx-ai-component.adoc | 56 ++++---- .../src/main/docs/ical-dataformat.adoc | 8 +- .../docs/infinispan-embedded-component.adoc | 8 +- .../src/main/docs/infinispan-component.adoc | 8 +- .../src/main/docs/irc-component.adoc | 28 ++-- .../src/main/docs/iso8583-dataformat.adoc | 4 +- .../main/docs/avroJackson2-dataformat.adoc | 4 +- .../docs/protobufJackson2-dataformat.adoc | 4 +- .../src/main/docs/jackson2-dataformat.adoc | 4 +- .../main/docs/avroJackson3-dataformat.adoc | 4 +- .../docs/protobufJackson3-dataformat.adoc | 4 +- .../src/main/docs/jackson3-dataformat.adoc | 12 +- .../src/main/docs/jacksonXml3-dataformat.adoc | 88 ++++++------ .../src/main/docs/jacksonXml2-dataformat.adoc | 88 ++++++------ .../camel-jasypt/src/main/docs/jasypt.adoc | 64 ++++----- .../src/main/docs/jaxb-dataformat.adoc | 52 +++---- .../src/main/docs/jcache-component.adoc | 40 +++--- .../src/main/docs/jgroups-raft-component.adoc | 12 +- .../src/main/docs/jgroups-component.adoc | 28 ++-- .../src/main/docs/jms-component.adoc | 92 ++++++------ .../src/main/docs/jpa-component.adoc | 36 ++--- .../camel-jq/src/main/docs/jq-language.adoc | 4 +- .../src/main/docs/scp-component.adoc | 8 +- .../src/main/docs/jsonata-component.adoc | 12 +- .../src/main/docs/jt400-component.adoc | 32 ++--- .../src/main/docs/jte-component.adoc | 8 +- .../src/main/docs/kafka-component.adoc | 8 +- .../src/main/docs/keycloak-component.adoc | 4 +- .../src/main/docs/knative-component.adoc | 12 +- .../src/main/docs/knative-http-component.adoc | 4 +- .../kubernetes-config-maps-component.adoc | 4 +- .../kubernetes-deployments-component.adoc | 12 +- .../docs/kubernetes-events-component.adoc | 20 +-- .../main/docs/kubernetes-hpa-component.adoc | 12 +- .../main/docs/kubernetes-job-component.adoc | 12 +- .../docs/kubernetes-namespaces-component.adoc | 12 +- .../main/docs/kubernetes-nodes-component.adoc | 12 +- ...s-persistent-volumes-claims-component.adoc | 8 +- ...bernetes-persistent-volumes-component.adoc | 8 +- .../main/docs/kubernetes-pods-component.adoc | 12 +- ...tes-replication-controllers-component.adoc | 12 +- .../kubernetes-resources-quota-component.adoc | 8 +- ...kubernetes-service-accounts-component.adoc | 8 +- .../docs/kubernetes-services-component.adoc | 12 +- .../openshift-build-configs-component.adoc | 8 +- .../main/docs/openshift-builds-component.adoc | 8 +- ...openshift-deploymentconfigs-component.adoc | 12 +- .../src/main/docs/ldap-component.adoc | 32 ++--- .../camel-leveldb/src/main/docs/leveldb.adoc | 12 +- .../src/main/docs/log-component.adoc | 8 +- .../src/main/docs/lucene-component.adoc | 24 ++-- .../src/main/docs/lzf-dataformat.adoc | 4 +- .../src/main/docs/mail-component.adoc | 88 ++++++------ .../main/docs/mimeMultipart-dataformat.adoc | 28 ++-- .../src/main/docs/milo-browse-component.adoc | 8 +- .../src/main/docs/milo-client-component.adoc | 16 +-- .../src/main/docs/mina-component.adoc | 36 ++--- .../src/main/docs/minio-component.adoc | 12 +- .../main/docs/mongodb-gridfs-component.adoc | 40 +++--- .../src/main/docs/mongodb-component.adoc | 60 ++++---- .../src/main/docs/nats-component.adoc | 8 +- .../src/main/docs/netty-http-component.adoc | 28 ++-- .../src/main/docs/observation.adoc | 4 +- .../src/main/docs/ognl-language.adoc | 4 +- .../src/main/docs/olingo2-component.adoc | 16 +-- .../src/main/docs/olingo4-component.adoc | 8 +- .../src/main/docs/opentelemetry.adoc | 12 +- .../src/main/docs/parquetAvro-dataformat.adoc | 12 +- .../src/main/docs/lpr-component.adoc | 8 +- .../src/main/docs/protobuf-dataformat.adoc | 22 +-- .../src/main/docs/pubnub-component.adoc | 8 +- .../src/main/docs/quartz-component.adoc | 4 +- .../main/docs/reactive-streams-component.adoc | 8 +- .../src/main/docs/rest-openapi-component.adoc | 8 +- .../src/main/docs/rss-component.adoc | 8 +- .../main/docs/sap-netweaver-component.adoc | 20 +-- .../src/main/docs/xquery-component.adoc | 16 +-- .../src/main/docs/xquery-language.adoc | 12 +- .../src/main/docs/servicenow-component.adoc | 12 +- .../src/main/docs/servlet-component.adoc | 32 ++--- .../camel-shiro/src/main/docs/shiro.adoc | 36 ++--- .../src/main/docs/sjms-component.adoc | 4 +- .../src/main/docs/sjms2-component.adoc | 8 +- .../src/main/docs/slack-component.adoc | 20 +-- .../src/main/docs/smpp-component.adoc | 20 +-- .../src/main/docs/snakeYaml-dataformat.adoc | 20 +-- .../src/main/docs/soap-dataformat.adoc | 36 ++--- .../src/main/docs/solr-component.adoc | 12 +- .../src/main/docs/splunk-hec-component.adoc | 16 +-- .../src/main/docs/splunk-component.adoc | 12 +- .../src/main/docs/spring-batch-component.adoc | 28 ++-- .../src/main/docs/spring-ws-component.adoc | 36 ++--- .../src/main/docs/spring-summary.adoc | 8 +- .../src/main/docs/sql-component.adoc | 4 +- .../src/main/docs/stax-component.adoc | 40 +++--- .../src/main/docs/stitch-component.adoc | 28 ++-- .../main/docs/string-template-component.adoc | 16 +-- .../src/main/docs/tarFile-dataformat.adoc | 24 ++-- .../src/main/docs/telegram-component.adoc | 28 ++-- .../src/main/docs/thrift-component.adoc | 12 +- .../src/main/docs/thymeleaf-component.adoc | 20 +-- .../src/main/docs/velocity-component.adoc | 20 +-- .../src/main/docs/vertx-http-component.adoc | 12 +- .../main/docs/vertx-websocket-component.adoc | 8 +- .../src/main/docs/vertx-component.adoc | 12 +- .../src/main/docs/wasm-component.adoc | 24 ++-- .../src/main/docs/wasm-language.adoc | 24 ++-- .../src/main/docs/weather-component.adoc | 16 +-- .../src/main/docs/web3j-component.adoc | 4 +- .../src/main/docs/whatsapp-component.adoc | 20 +-- .../src/main/docs/xmlSecurity-dataformat.adoc | 28 ++-- .../src/main/docs/xpath-language.adoc | 4 +- .../src/main/docs/zeebe-component.adoc | 60 ++++---- .../main/docs/gzipDeflater-dataformat.adoc | 4 +- .../src/main/docs/zipDeflater-dataformat.adoc | 4 +- 216 files changed, 2035 insertions(+), 2035 deletions(-) diff --git a/components/camel-arangodb/src/main/docs/arangodb-component.adoc b/components/camel-arangodb/src/main/docs/arangodb-component.adoc index 0b67f07631716..43abeee79063b 100644 --- a/components/camel-arangodb/src/main/docs/arangodb-component.adoc +++ b/components/camel-arangodb/src/main/docs/arangodb-component.adoc @@ -20,22 +20,22 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-arangodb x.x.x ------------------------------------------------------------- +---- == URI format [source,java] ---------------------------- +---- arangodb:database[?options] ---------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -87,11 +87,11 @@ YAML:: And you can set as body a BaseDocument class --------------------------------------------------------------------------------- +---- BaseDocument myObject = new BaseDocument(); myObject.addAttribute("a", "Foo"); myObject.addAttribute("b", 42); --------------------------------------------------------------------------------- +---- ==== Query a collection @@ -134,7 +134,7 @@ And you can invoke an AQL Query in this way ._Java-only: ProducerTemplate with AQL query parameters and string concatenation_ [source,java] --------------------------------------------------------------------------------- +---- String query = "FOR t IN " + COLLECTION_NAME + " FILTER t.value == @value"; Map bindVars = new MapBuilder().put("value", "hello") .get(); @@ -143,7 +143,7 @@ Exchange result = template.request("direct:query", exchange -> { exchange.getMessage().setHeader(AQL_QUERY, query); exchange.getMessage().setHeader(AQL_QUERY_BIND_PARAMETERS, bindVars); }); --------------------------------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-asn1/src/main/docs/asn1-dataformat.adoc b/components/camel-asn1/src/main/docs/asn1-dataformat.adoc index 122cc733c2164..fedbab652b4df 100644 --- a/components/camel-asn1/src/main/docs/asn1-dataformat.adoc +++ b/components/camel-asn1/src/main/docs/asn1-dataformat.adoc @@ -29,9 +29,9 @@ In this first example, we unmarshal BER file payload to OutputStream and send it ._Java-only: uses the asn1 data format object directly_ [source,java] ------------------------------------------------------------------------ +---- from("direct:unmarshal").unmarshal(asn1).to("mock:unmarshal"); ------------------------------------------------------------------------ +---- In the second example, we unmarshal BER file payload to a byte array using Split EIP. The reason for applying Split EIP is that usually each BER file or (ASN.1 structured file) contains multiple records to process and Split EIP helps us to get each record in a file as byte arrays which is actually ASN1Primitive's instance (by the use of Bouncy Castle's ASN.1 support in bcprov-jdk18on library) @@ -40,12 +40,12 @@ In such example, note that you need to set `usingIterator=true` ._Java-only: uses the asn1 data format object and Split EIP with bodyAs_ [source,java] ------------------------------------------------------------------------ +---- from("direct:unmarshal") .unmarshal(asn1) .split(bodyAs(Iterator.class)).streaming() .to("mock:unmarshal"); ------------------------------------------------------------------------ +---- In the last example, we unmarshalled a BER file payload to plain old Java Objects using Split EIP. The reason for applying Split EIP is already mentioned in the previous example. Please note and keep in mind that reason. In such example we also need to set the fully qualified name of the class or .class reference through data format. The important thing to note here is that your object should have been generated by jasn1 compiler, which is a nice tool to generate java object representations of your ASN.1 structure. @@ -55,13 +55,13 @@ The nice thing about this example, you will get POJO instance at the mock endpoi ._Java-only: uses unmarshal with class name and Split EIP with bodyAs_ [source,java] ------------------------------------------------------------------------ +---- from("direct:unmarshaldsl") .unmarshal() .asn1("org.apache.camel.dataformat.asn1.model.testsmscbercdr.SmsCdr") .split(bodyAs(Iterator.class)).streaming() .to("mock:unmarshaldsl"); ------------------------------------------------------------------------ +---- == Dependencies @@ -73,14 +73,14 @@ substituting the version number for the latest & greatest release (see the download page for the latest versions). [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-asn1 x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-atom/src/main/docs/atom-component.adoc b/components/camel-atom/src/main/docs/atom-component.adoc index 2f2a22bfaa4aa..3006e73068bd5 100644 --- a/components/camel-atom/src/main/docs/atom-component.adoc +++ b/components/camel-atom/src/main/docs/atom-component.adoc @@ -24,20 +24,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-atom x.x.x ------------------------------------------------------------- +---- == URI format ------------------------- +---- atom://atomUri[?options] ------------------------- +---- Where *atomUri* is the URI to the Atom feed to poll. diff --git a/components/camel-avro-rpc/camel-avro-rpc-component/src/main/docs/avro-component.adoc b/components/camel-avro-rpc/camel-avro-rpc-component/src/main/docs/avro-component.adoc index b636f60e442ba..81bf7cb3591ff 100644 --- a/components/camel-avro-rpc/camel-avro-rpc-component/src/main/docs/avro-component.adoc +++ b/components/camel-avro-rpc/camel-avro-rpc-component/src/main/docs/avro-component.adoc @@ -22,14 +22,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-avro-rpc x.x.x ------------------------------------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -44,7 +44,7 @@ format and then generate java code for the specified types and messages. An example of how a schema looks like is below. [source,json] ------------------------------------------------------------------------------------------- +---- {"namespace": "org.apache.camel.avro.generated", "protocol": "KeyValueProtocol", @@ -72,7 +72,7 @@ An example of how a schema looks like is below. } } } ------------------------------------------------------------------------------------------- +---- You can easily generate classes from a schema, using maven, ant etc. More details can be found at the @@ -87,7 +87,7 @@ the schema above: ._Java-only: protocol interface and POJO class definition for Avro RPC_ [source,java] --------------------------------------------------------------- +---- package org.apache.camel.avro.reflection; public interface KeyValueProtocol { @@ -100,7 +100,7 @@ class Value { public String getValue() { return value; } public void setValue(String value) { this.value = value; } } --------------------------------------------------------------- +---- _Note: Existing classes can be used only for RPC (see below), not in data format._ @@ -113,9 +113,9 @@ As mentioned above, Avro also provides RPC support over multiple transports such as http and netty. Camel provides consumers and producers for these two transports. ----------------------------------------- +---- avro:[transport]:[host]:[port][?options] ----------------------------------------- +---- The supported transport values are currently http or netty. @@ -123,9 +123,9 @@ The supported transport values are currently http or netty. ==== You can specify the message name right in the URI: ------------------------------------------------------- +---- avro:[transport]:[host]:[port][/messageName][?options] ------------------------------------------------------- +---- ==== For consumers, this allows you to have multiple routes attached to the @@ -152,31 +152,31 @@ wrapping. An example of using camel avro producers via http: [source,xml] ---------------------------------------------------------------------------------------------------------------------------- +---- ---------------------------------------------------------------------------------------------------------------------------- +---- In the example above you need to fill `CamelAvroMessageName` header. You can use the following syntax to call constant messages: [source,xml] -------------------------------------------------------------------------------------------------------------------------------- +---- -------------------------------------------------------------------------------------------------------------------------------- +---- An example of consuming messages using camel avro consumers via netty: [source,xml] ------------------------------------------------------------------------------------------------------------------------------- +---- @@ -190,12 +190,12 @@ An example of consuming messages using camel avro consumers via netty: ------------------------------------------------------------------------------------------------------------------------------- +---- You can set up two distinct routes to perform the same task: [source,xml] -------------------------------------------------------------------------------------------------------------------------------------------------------- +---- @@ -204,7 +204,7 @@ You can set up two distinct routes to perform the same task: -------------------------------------------------------------------------------------------------------------------------------------------------------- +---- In the example above, get takes only one parameter, so `singleParameter` is used and `getProcessor` will receive Value class directly in body, diff --git a/components/camel-avro/src/main/docs/avro-dataformat.adoc b/components/camel-avro/src/main/docs/avro-dataformat.adoc index f01d4a81ecf36..77d5995ace6aa 100644 --- a/components/camel-avro/src/main/docs/avro-dataformat.adoc +++ b/components/camel-avro/src/main/docs/avro-dataformat.adoc @@ -21,14 +21,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-avro x.x.x ------------------------------------------------------------- +---- You can easily generate classes from a schema, using maven, ant etc. @@ -51,19 +51,19 @@ you want to marshal or unmarshal in your route. ._Java-only: programmatic AvroDataFormat with schema_ [source,java] --------------------------------------------------------------------------------- +---- AvroDataFormat format = new AvroDataFormat(Value.SCHEMA$); from("direct:in").marshal(format).to("direct:marshal"); from("direct:back").unmarshal(format).to("direct:unmarshal"); --------------------------------------------------------------------------------- +---- Where Value is an Avro Maven Plugin Generated class. or in XML [source,xml] --------------------------------------------------------------------------------- +---- @@ -73,13 +73,13 @@ or in XML --------------------------------------------------------------------------------- +---- An alternative can be to specify the dataformat inside the context and reference it from your route. [source,xml] --------------------------------------------------------------------------------------- +---- @@ -90,7 +90,7 @@ reference it from your route. --------------------------------------------------------------------------------------- +---- In the same manner, you can unmarshal using the avro data format. diff --git a/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc b/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc index 345947b52ba02..4f117bbfb436b 100644 --- a/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc +++ b/components/camel-aws/camel-aws-bedrock/src/main/docs/aws-bedrock-component.adoc @@ -27,9 +27,9 @@ https://aws.amazon.com/bedrock/[Amazon Bedrock]. == URI Format -------------------------- +---- aws-bedrock://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -78,7 +78,7 @@ Express is a large language model for text generation. It is useful for a wide r Json schema for request [source,json] --------------------------------------------------------------------------------- +---- { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -120,7 +120,7 @@ Json schema for request "textGenerationConfig" ] } --------------------------------------------------------------------------------- +---- - Titan Text Lite V1 with id `amazon.titan-text-lite-v1` Lite is a light weight efficient model, ideal for fine-tuning of English-language tasks. @@ -128,7 +128,7 @@ Lite is a light weight efficient model, ideal for fine-tuning of English-languag Json schema for request [source,json] --------------------------------------------------------------------------------- +---- { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -170,7 +170,7 @@ Json schema for request "textGenerationConfig" ] } --------------------------------------------------------------------------------- +---- - Titan Image Generator G1 with id `amazon.titan-image-generator-v1` It generates images from text, and allows users to upload and edit an existing image. Users can edit an image with a text prompt (without a mask) or parts of an image with an image mask. You can extend the boundaries of an image with outpainting, and fill in an image with inpainting. @@ -178,7 +178,7 @@ It generates images from text, and allows users to upload and edit an existing i Json schema for request [source,json] --------------------------------------------------------------------------------- +---- { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -239,7 +239,7 @@ Json schema for request "imageGenerationConfig" ] } --------------------------------------------------------------------------------- +---- - Titan Embeddings G1 with id `amazon.titan-embed-text-v1` The Amazon Titan Embeddings G1 - Text – Text v1.2 can intake up to 8k tokens and outputs a vector of 1,536 dimensions. The model also works in 25+ different language @@ -247,7 +247,7 @@ The Amazon Titan Embeddings G1 - Text – Text v1.2 can intake up to 8k tokens a Json schema for request [source,json] --------------------------------------------------------------------------------- +---- { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -260,7 +260,7 @@ Json schema for request "inputText" ] } --------------------------------------------------------------------------------- +---- - Jurassic2-Ultra with id `ai21.j2-ultra-v1` Jurassic-2 Ultra is AI21’s most powerful model for complex tasks that require advanced text generation and comprehension. @@ -268,7 +268,7 @@ Jurassic-2 Ultra is AI21’s most powerful model for complex tasks that require Json schema for request [source,json] --------------------------------------------------------------------------------- +---- { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -326,7 +326,7 @@ Json schema for request "frequencyPenalty" ] } --------------------------------------------------------------------------------- +---- - Jurassic2-Mid with id `ai21.j2-mid-v1` Jurassic-2 Mid is less powerful than Ultra, yet carefully designed to strike the right balance between exceptional quality and affordability. @@ -334,7 +334,7 @@ Jurassic-2 Mid is less powerful than Ultra, yet carefully designed to strike the Json schema for request [source,json] --------------------------------------------------------------------------------- +---- { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -392,7 +392,7 @@ Json schema for request "frequencyPenalty" ] } --------------------------------------------------------------------------------- +---- - Claude Instant V1.2 with id `anthropic.claude-instant-v1` A fast, affordable yet still very capable model, which can handle a range of tasks including casual dialogue, text analysis, summarization, and document question-answering. @@ -400,7 +400,7 @@ A fast, affordable yet still very capable model, which can handle a range of tas Json schema for request [source,json] --------------------------------------------------------------------------------- +---- { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -442,7 +442,7 @@ Json schema for request "anthropic_version" ] } --------------------------------------------------------------------------------- +---- - Claude 2 with id `anthropic.claude-v2` Anthropic's highly capable model across a wide range of tasks from sophisticated dialogue and creative content generation to detailed instruction following. @@ -450,7 +450,7 @@ Anthropic's highly capable model across a wide range of tasks from sophisticated Json schema for request [source,json] --------------------------------------------------------------------------------- +---- { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -492,7 +492,7 @@ Json schema for request "anthropic_version" ] } --------------------------------------------------------------------------------- +---- - Claude 2.1 with id `anthropic.claude-v2:1` An update to Claude 2 that features double the context window, plus improvements across reliability, hallucination rates, and evidence-based accuracy in long document and RAG contexts. @@ -500,7 +500,7 @@ An update to Claude 2 that features double the context window, plus improvements Json schema for request [source,json] --------------------------------------------------------------------------------- +---- { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -542,7 +542,7 @@ Json schema for request "anthropic_version" ] } --------------------------------------------------------------------------------- +---- - Claude 3 Sonnet with id `anthropic.claude-3-sonnet-20240229-v1:0` Claude 3 Sonnet by Anthropic strikes the ideal balance between intelligence and speed—particularly for enterprise workloads. @@ -550,7 +550,7 @@ Claude 3 Sonnet by Anthropic strikes the ideal balance between intelligence and Json schema for request [source,json] --------------------------------------------------------------------------------- +---- { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -605,7 +605,7 @@ Json schema for request "anthropic_version" ] } --------------------------------------------------------------------------------- +---- - Claude 3 Haiku with id `anthropic.claude-3-haiku-20240307-v1:0` Claude 3 Haiku is Anthropic's fastest, most compact model for near-instant responsiveness. It answers simple queries and requests with speed. @@ -613,7 +613,7 @@ Claude 3 Haiku is Anthropic's fastest, most compact model for near-instant respo Json schema for request [source,json] --------------------------------------------------------------------------------- +---- { "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", @@ -668,7 +668,7 @@ Json schema for request "anthropic_version" ] } --------------------------------------------------------------------------------- +---- === Bedrock Producer operations @@ -736,15 +736,15 @@ Two operations are provided: *converse*: Standard request-response conversation [source] --------------------------------------------------------------------------------- +---- aws-bedrock://label?operation=converse&modelId=anthropic.claude-3-sonnet-20240229-v1:0 --------------------------------------------------------------------------------- +---- *converseStream*: Streaming conversation with real-time chunk delivery [source] --------------------------------------------------------------------------------- +---- aws-bedrock://label?operation=converseStream&modelId=anthropic.claude-3-sonnet-20240229-v1:0 --------------------------------------------------------------------------------- +---- ==== Converse Configuration Options @@ -812,26 +812,26 @@ The Camel AWS Bedrock component provides comprehensive support for guardrails th *converse with Guardrails*: Apply guardrails to conversational model invocations [source] --------------------------------------------------------------------------------- +---- aws-bedrock://label?operation=converse&modelId=anthropic.claude-3-sonnet-20240229-v1:0 &guardrailIdentifier=abc123xyz&guardrailVersion=DRAFT&guardrailTrace=true --------------------------------------------------------------------------------- +---- *converseStream with Guardrails*: Apply guardrails to streaming conversations [source] --------------------------------------------------------------------------------- +---- aws-bedrock://label?operation=converseStream&modelId=anthropic.claude-3-sonnet-20240229-v1:0 &guardrailIdentifier=abc123xyz&guardrailVersion=DRAFT --------------------------------------------------------------------------------- +---- *applyGuardrail*: Standalone operation to validate content against a guardrail without invoking a model [source] --------------------------------------------------------------------------------- +---- aws-bedrock://label?operation=applyGuardrail&guardrailIdentifier=abc123xyz &guardrailVersion=DRAFT --------------------------------------------------------------------------------- +---- ==== Guardrails Response Headers @@ -913,7 +913,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with complex JSON construction_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:invoke", exchange -> { ObjectMapper mapper = new ObjectMapper(); ObjectNode rootNode = mapper.createObjectNode(); @@ -932,7 +932,7 @@ and you can then send to the direct endpoint something like exchange.getMessage().setHeader("CamelAwsBedrockContentType", "application/json"); exchange.getMessage().setHeader("CamelAwsBedrockAcceptContentType", "application/json"); }); --------------------------------------------------------------------------------- +---- where template is a ProducerTemplate. @@ -940,20 +940,20 @@ where template is a ProducerTemplate. ._Java-only: uses `unmarshal().base64()` method chain and `simple()` expression builder_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:invoke") .to("aws-bedrock://test?bedrockRuntimeClient=#amazonBedrockRuntimeClient&operation=invokeImageModel&modelId=amazon.titan-image-generator-v1") .split(body()) .unmarshal().base64() .setHeader("CamelFileName", simple("image-${random(128)}.png")) .to("file:target/generated_images"); --------------------------------------------------------------------------------- +---- and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with complex JSON construction_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:send_titan_image", exchange -> { ObjectMapper mapper = new ObjectMapper(); ObjectNode rootNode = mapper.createObjectNode(); @@ -976,7 +976,7 @@ and you can then send to the direct endpoint something like exchange.getMessage().setHeader("CamelAwsBedrockContentType", "application/json"); exchange.getMessage().setHeader("CamelAwsBedrockAcceptContentType", "application/json"); }); --------------------------------------------------------------------------------- +---- where template is a ProducerTemplate. @@ -1028,7 +1028,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with complex JSON construction_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:send_titan_embeddings", exchange -> { ObjectMapper mapper = new ObjectMapper(); ObjectNode rootNode = mapper.createObjectNode(); @@ -1039,7 +1039,7 @@ and you can then send to the direct endpoint something like exchange.getMessage().setHeader("CamelAwsBedrockContentType", "application/json"); exchange.getMessage().setHeader("CamelAwsBedrockAcceptContentType", "*/*"); }); --------------------------------------------------------------------------------- +---- where template is a ProducerTemplate. @@ -1092,7 +1092,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with complex JSON construction_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:stream_complete", exchange -> { ObjectMapper mapper = new ObjectMapper(); ObjectNode rootNode = mapper.createObjectNode(); @@ -1118,7 +1118,7 @@ and you can then send to the direct endpoint something like Integer tokenCount = result.getMessage().getHeader("CamelAwsBedrockTokenCount", Integer.class); String completionReason = result.getMessage().getHeader("CamelAwsBedrockCompletionReason", String.class); Integer chunkCount = result.getMessage().getHeader("CamelAwsBedrockChunkCount", Integer.class); --------------------------------------------------------------------------------- +---- - invokeTextModelStreaming (Chunks Mode): this operation will invoke a model from Bedrock with streaming, emitting individual chunks. @@ -1177,7 +1177,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with complex JSON construction_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:stream_chunks", exchange -> { ObjectMapper mapper = new ObjectMapper(); ObjectNode rootNode = mapper.createObjectNode(); @@ -1211,7 +1211,7 @@ and you can then send to the direct endpoint something like for (String chunk : chunks) { System.out.println("Chunk: " + chunk); } --------------------------------------------------------------------------------- +---- - converse: this operation uses the unified Converse API for model-agnostic conversations. @@ -1261,7 +1261,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with AWS SDK objects_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:converse", exchange -> { // Create a conversation message List messages = new ArrayList<>(); @@ -1301,7 +1301,7 @@ and you can then send to the direct endpoint something like System.out.println("Stop reason: " + stopReason); System.out.println("Input tokens: " + usage.inputTokens()); System.out.println("Output tokens: " + usage.outputTokens()); --------------------------------------------------------------------------------- +---- - converseStream (Complete Mode): this operation uses the Converse API with streaming, accumulating the complete response. @@ -1351,7 +1351,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with AWS SDK objects_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:converse_stream", exchange -> { // Create a conversation message List messages = new ArrayList<>(); @@ -1379,7 +1379,7 @@ and you can then send to the direct endpoint something like System.out.println("Response: " + response); System.out.println("Received " + chunkCount + " chunks"); --------------------------------------------------------------------------------- +---- - converseStream (Chunks Mode): this operation uses the Converse API with streaming, emitting individual chunks. @@ -1437,7 +1437,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with AWS SDK objects_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:converse_stream_chunks", exchange -> { // Create a conversation message List messages = new ArrayList<>(); @@ -1458,7 +1458,7 @@ and you can then send to the direct endpoint something like for (String chunk : chunks) { System.out.println("Chunk: " + chunk); } --------------------------------------------------------------------------------- +---- - Multi-turn Conversation with Converse API: demonstrates maintaining conversation history. @@ -1508,7 +1508,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with multi-turn conversation history_ [source,java] --------------------------------------------------------------------------------- +---- // Maintain conversation history List conversationHistory = new ArrayList<>(); @@ -1544,7 +1544,7 @@ and you can then send to the direct endpoint something like String followUpResponse = result2.getMessage().getBody(String.class); System.out.println("Follow-up response: " + followUpResponse); --------------------------------------------------------------------------------- +---- === Guardrails Examples @@ -1599,7 +1599,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with AWS SDK objects_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:converse_with_guardrails", exchange -> { // Create a conversation message List messages = new ArrayList<>(); @@ -1631,7 +1631,7 @@ and you can then send to the direct endpoint something like if (trace != null) { System.out.println("Guardrail evaluation: " + trace); } --------------------------------------------------------------------------------- +---- - Converse with Guardrails (Header Configuration): Apply guardrails configured per-message via headers. @@ -1681,7 +1681,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with AWS SDK `GuardrailConfiguration` objects_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:converse_dynamic_guardrails", exchange -> { // Create a conversation message List messages = new ArrayList<>(); @@ -1705,7 +1705,7 @@ and you can then send to the direct endpoint something like String response = result.getMessage().getBody(String.class); System.out.println("Protected response: " + response); --------------------------------------------------------------------------------- +---- - Converse Stream with Guardrails: Apply guardrails to streaming conversations. @@ -1757,7 +1757,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with AWS SDK objects_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:stream_with_guardrails", exchange -> { List messages = new ArrayList<>(); messages.add(software.amazon.awssdk.services.bedrockruntime.model.Message.builder() @@ -1772,7 +1772,7 @@ and you can then send to the direct endpoint something like String streamedResponse = result.getMessage().getBody(String.class); System.out.println("Guardrail-protected stream response: " + streamedResponse); --------------------------------------------------------------------------------- +---- - Apply Guardrail: Validate content against a guardrail without invoking a model. @@ -1823,7 +1823,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with AWS SDK `GuardrailContentBlock` objects_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:validate_content", exchange -> { // Create content blocks to check List content @@ -1854,7 +1854,7 @@ and you can then send to the direct endpoint something like } else { System.out.println("Content passed guardrail validation"); } --------------------------------------------------------------------------------- +---- - Apply Guardrail with POJO Request: Use the SDK request object directly for maximum control. @@ -1904,7 +1904,7 @@ and you can then send to the direct endpoint something like ._Java-only: uses `ProducerTemplate` test API with AWS SDK `ApplyGuardrailRequest` POJO_ [source,java] --------------------------------------------------------------------------------- +---- final Exchange result = template.send("direct:validate_pojo", exchange -> { // Create content blocks List content @@ -1929,7 +1929,7 @@ and you can then send to the direct endpoint something like String action = result.getMessage().getBody(String.class); System.out.println("Validation result: " + action); --------------------------------------------------------------------------------- +---- - Content Moderation Pipeline: Combine guardrails with model invocation in a pipeline. @@ -2019,13 +2019,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws-bedrock ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws-security-hub/src/main/docs/aws-security-hub-component.adoc b/components/camel-aws/camel-aws-security-hub/src/main/docs/aws-security-hub-component.adoc index 96d8a398a2c93..e5825cbe92b84 100644 --- a/components/camel-aws/camel-aws-security-hub/src/main/docs/aws-security-hub-component.adoc +++ b/components/camel-aws/camel-aws-security-hub/src/main/docs/aws-security-hub-component.adoc @@ -28,9 +28,9 @@ https://aws.amazon.com/security-hub/[Amazon Security Hub]. == URI Format -------------------------- +---- aws-security-hub://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -81,7 +81,7 @@ Import security findings into Security Hub. This is the primary way to send find ._Java-only: uses inline Processor with AWS SDK builder API_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:importFindings") .process(exchange -> { AwsSecurityFinding finding = AwsSecurityFinding.builder() @@ -105,7 +105,7 @@ from("direct:importFindings") }) .to("aws-security-hub://findings?operation=batchImportFindings") .to("mock:result"); --------------------------------------------------------------------------------- +---- ==== GetFindings @@ -113,7 +113,7 @@ Retrieve security findings from Security Hub with optional filtering. ._Java-only: uses inline Processor with AWS SDK builder API_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:getFindings") .process(exchange -> { AwsSecurityFindingFilters filters = AwsSecurityFindingFilters.builder() @@ -127,7 +127,7 @@ from("direct:getFindings") }) .to("aws-security-hub://findings?operation=getFindings") .to("mock:result"); --------------------------------------------------------------------------------- +---- ==== BatchUpdateFindings @@ -135,7 +135,7 @@ Update security findings with notes, severity changes, workflow status, etc. ._Java-only: uses inline Processor with AWS SDK builder API and Java constants_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:updateFindings") .process(exchange -> { List identifiers = List.of( @@ -159,7 +159,7 @@ from("direct:updateFindings") }) .to("aws-security-hub://findings?operation=batchUpdateFindings") .to("mock:result"); --------------------------------------------------------------------------------- +---- ==== DescribeHub @@ -210,7 +210,7 @@ AWS Security Hub uses the https://schema.ocsf.io/[Open Cybersecurity Schema Fram ._Java-only: uses inline Processor with class literal and method reference_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:ocsfToSecurityHub") .unmarshal().ocsf(DetectionFinding.class) .process(exchange -> { @@ -220,7 +220,7 @@ from("direct:ocsfToSecurityHub") exchange.getIn().setBody(List.of(finding)); }) .to("aws-security-hub://findings?operation=batchImportFindings"); --------------------------------------------------------------------------------- +---- == Dependencies @@ -229,12 +229,12 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws-security-hub ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-athena/src/main/docs/aws2-athena-component.adoc b/components/camel-aws/camel-aws2-athena/src/main/docs/aws2-athena-component.adoc index 80f4d66d56f02..7ea3f59b0fd24 100644 --- a/components/camel-aws/camel-aws2-athena/src/main/docs/aws2-athena-component.adoc +++ b/components/camel-aws/camel-aws2-athena/src/main/docs/aws2-athena-component.adoc @@ -25,9 +25,9 @@ https://aws.amazon.com/athena/[AWS Athena]. == URI Format ------------------------------- +---- aws2-athena://label[?options] ------------------------------- +---- You can append query options to the URI in the following format: `?options=value&option2=value&...` @@ -964,13 +964,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-athena ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-comprehend/src/main/docs/aws2-comprehend-component.adoc b/components/camel-aws/camel-aws2-comprehend/src/main/docs/aws2-comprehend-component.adoc index b2e8f40db1c2d..9d241448ed50e 100644 --- a/components/camel-aws/camel-aws2-comprehend/src/main/docs/aws2-comprehend-component.adoc +++ b/components/camel-aws/camel-aws2-comprehend/src/main/docs/aws2-comprehend-component.adoc @@ -35,9 +35,9 @@ https://aws.amazon.com/comprehend/[Amazon Comprehend]. == URI Format -------------------------- +---- aws2-comprehend://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -530,7 +530,7 @@ For more control, you can pass AWS SDK request objects directly by setting `pojo ._Java-only: uses lambda expression and AWS SDK request builder API_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:pojoRequest") .setBody(exchange -> DetectSentimentRequest.builder() .text("I am very happy with this service!") @@ -538,7 +538,7 @@ from("direct:pojoRequest") .build()) .to("aws2-comprehend://test?operation=detectSentiment&pojoRequest=true&useDefaultCredentialsProvider=true®ion=us-east-1") .log("Sentiment: ${header.CamelAwsComprehendDetectedSentiment}"); ------------------------------------------------------------------------------------------------------- +---- === Setting Operation and Language via Headers @@ -546,14 +546,14 @@ You can dynamically set the operation and language code using message headers: ._Java-only: uses Java enum constant for operation header value_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:dynamicOperation") .setHeader("CamelAwsComprehendOperation", constant(Comprehend2Operations.detectEntities)) .setHeader("CamelAwsComprehendLanguageCode", constant("en")) .setBody(constant("Apple Inc. is headquartered in Cupertino, California.")) .to("aws2-comprehend://test?useDefaultCredentialsProvider=true®ion=us-east-1") .log("Detected entities: ${body}"); ------------------------------------------------------------------------------------------------------- +---- === Using with Static Credentials @@ -613,7 +613,7 @@ A practical example combining multiple Comprehend operations for content moderat ._Java-only: uses choice/when/otherwise with inline comments_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:moderateContent") .setHeader("originalText", simple("${body}")) // First, detect the language @@ -631,7 +631,7 @@ from("direct:moderateContent") .otherwise() .log("Content is safe") .to("direct:approveContent"); ------------------------------------------------------------------------------------------------------- +---- === Customer Feedback Analysis Example @@ -639,7 +639,7 @@ Analyze customer feedback for sentiment and key topics: ._Java-only: uses body() method reference and choice/when/otherwise with inline comments_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("kafka:customer-feedback") .log("Processing feedback: ${body}") // Analyze sentiment @@ -657,7 +657,7 @@ from("kafka:customer-feedback") .to("direct:handlePositiveFeedback") .otherwise() .to("direct:handleNeutralFeedback"); ------------------------------------------------------------------------------------------------------- +---- == Dependencies @@ -666,13 +666,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-comprehend ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-cw/src/main/docs/aws2-cw-component.adoc b/components/camel-aws/camel-aws2-cw/src/main/docs/aws2-cw-component.adoc index 975804e68ce18..89d9e5331fff1 100644 --- a/components/camel-aws/camel-aws2-cw/src/main/docs/aws2-cw-component.adoc +++ b/components/camel-aws/camel-aws2-cw/src/main/docs/aws2-cw-component.adoc @@ -28,9 +28,9 @@ https://aws.amazon.com/cloudwatch/[Amazon CloudWatch]. == URI Format ----------------------------- +---- aws2-cw://namespace[?options] ----------------------------- +---- The metrics will be created if they don't already exist. @@ -121,13 +121,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-cw ${camel-version} ---------------------------------------- +---- where `${camel-version`} must be replaced by the actual version of Camel. @@ -172,11 +172,11 @@ and sends something like ._Java-only: setting CloudWatch metric headers programmatically_ [source,java] -------------------------------- +---- exchange.getIn().setHeader(Cw2Constants.METRIC_NAME, "ExchangesCompleted"); exchange.getIn().setHeader(Cw2Constants.METRIC_VALUE, "2.0"); exchange.getIn().setHeader(Cw2Constants.METRIC_UNIT, "Count"); -------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-aws/camel-aws2-ddb/src/main/docs/aws2-ddb-component.adoc b/components/camel-aws/camel-aws2-ddb/src/main/docs/aws2-ddb-component.adoc index b2dcdb187a48e..873563420a16d 100644 --- a/components/camel-aws/camel-aws2-ddb/src/main/docs/aws2-ddb-component.adoc +++ b/components/camel-aws/camel-aws2-ddb/src/main/docs/aws2-ddb-component.adoc @@ -27,9 +27,9 @@ https://aws.amazon.com/dynamodb[Amazon DynamoDB]. == URI Format ------------------------------- +---- aws2-ddb://domainName[?options] ------------------------------- +---- You can append query options to the URI in the following format: @@ -77,7 +77,7 @@ URI: ._Java-only: programmatic `DynamoDbClient` configuration and registry binding_ [source,java] ----------------------------------------------------- +---- public class MyRouteBuilder extends RouteBuilder { private String accessKey = "myaccessKey"; @@ -97,7 +97,7 @@ public class MyRouteBuilder extends RouteBuilder { .to("aws2-ddb://domainName?amazonDDBClient=#client"); } } ----------------------------------------------------- +---- The `#client` refers to a `DynamoDbClient` in the Registry. @@ -127,13 +127,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-ddb ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. @@ -145,7 +145,7 @@ where `$\{camel-version}` must be replaced by the actual version of Camel. ._Java-only: uses AWS SDK `AttributeValue` builders and variable table name_ [source,java] --------------------------------------------------------------------------------- +---- Map attributeMap = new HashMap<>(); attributeMap.put("partitionKey", AttributeValue.builder().s("3000").build()); attributeMap.put("id", AttributeValue.builder().s("1001").build()); @@ -158,13 +158,13 @@ from("direct:start") .setHeader("CamelAwsDdbItem", constant(attributeMap)) .setHeader("CamelAwsDdbAttributeNames", constant(attributeMap.keySet())) .to("aws2-ddb://" + tableName + "?amazonDDBClient=#client"); --------------------------------------------------------------------------------- +---- - UpdateItem: this operation will update an entry into DynamoDB ._Java-only: uses AWS SDK `AttributeValue` and `AttributeValueUpdate` builders_ [source,java] --------------------------------------------------------------------------------- +---- Map attributeMap = new HashMap<>(); attributeMap.put("partitionKey", AttributeValueUpdate.builder().value(AttributeValue.builder().s("3000").build()).build()); attributeMap.put("sortKey", AttributeValueUpdate.builder().value(AttributeValue.builder().s("1001").build()).build()); @@ -179,13 +179,13 @@ from("direct:start") .setHeader("CamelAwsDdbUpdateValues", constant(attributeMap)) .setHeader("CamelAwsDdbKey", constant(keyMap)) .to("aws2-ddb://" + tableName + "?amazonDDBClient=#client"); --------------------------------------------------------------------------------- +---- - GetItem: this operation will retrieve an entry from DynamoDB ._Java-only: uses `Processor` with AWS SDK `AttributeValue` builders_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:get") .process(exchange -> { final Map keyMap = new HashMap<>(); @@ -196,13 +196,13 @@ from("direct:get") exchange.getIn().setHeader("CamelAwsDdbKey", keyMap); }) .toF("aws2-ddb://%s?amazonDDBClient=#client&consistentRead=true", tableName); --------------------------------------------------------------------------------- +---- - DeleteItem: this operation will delete an entry from DynamoDB ._Java-only: uses `Processor` with AWS SDK `AttributeValue` builders_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:delete") .process(exchange -> { final Map keyMap = new HashMap<>(); @@ -212,14 +212,14 @@ from("direct:delete") exchange.getIn().setHeader("CamelAwsDdbKey", keyMap); }) .toF("aws2-ddb://%s?amazonDDBClient=#client&consistentRead=true", tableName); --------------------------------------------------------------------------------- +---- - ExecuteStatement (PartiQL): this operation runs a PartiQL statement against DynamoDB ._Java-only: uses `Processor` with AWS SDK `AttributeValue` builders_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:partiql") .process(exchange -> { exchange.getIn().setHeader("CamelAwsDdbOperation", "ExecuteStatement"); @@ -230,13 +230,13 @@ from("direct:partiql") exchange.getIn().setHeader("CamelAwsDdbConsistentRead", true); }) .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName); --------------------------------------------------------------------------------- +---- - BatchExecuteStatement (PartiQL batch): this operation runs multiple PartiQL statements in a batch ._Java-only: uses `Processor` with AWS SDK `BatchStatementRequest` builders_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:batchPartiql") .process(exchange -> { exchange.getIn().setHeader("CamelAwsDdbOperation", "BatchExecuteStatement"); @@ -249,13 +249,13 @@ from("direct:batchPartiql") .build())); }) .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName); --------------------------------------------------------------------------------- +---- - TransactWriteItems: this operation performs a transactional write across one or more tables ._Java-only: uses `Processor` with AWS SDK `TransactWriteItem` builders_ [source,java] --------------------------------------------------------------------------------- +---- Map item = new HashMap<>(); item.put("key", AttributeValue.builder().s("txKey").build()); item.put("data", AttributeValue.builder().s("txValue").build()); @@ -269,13 +269,13 @@ from("direct:transactWrite") .build())); }) .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName); --------------------------------------------------------------------------------- +---- - TransactGetItems: this operation performs a transactional read across one or more tables ._Java-only: uses `Processor` with AWS SDK `TransactGetItem` builders_ [source,java] --------------------------------------------------------------------------------- +---- Map key = new HashMap<>(); key.put("key", AttributeValue.builder().s("txKey").build()); @@ -288,13 +288,13 @@ from("direct:transactGet") .build())); }) .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName); --------------------------------------------------------------------------------- +---- - BatchWriteItems: this operation puts or deletes multiple items in one or more tables in a single batch ._Java-only: uses AWS SDK `WriteRequest` and `PutRequest` builders_ [source,java] --------------------------------------------------------------------------------- +---- Map item1 = new HashMap<>(); item1.put("key", AttributeValue.builder().s("bk1").build()); item1.put("data", AttributeValue.builder().s("bv1").build()); @@ -311,7 +311,7 @@ from("direct:batchWrite") exchange.getIn().setHeader("CamelAwsDdbBatchWriteItems", requestItems); }) .toF("aws2-ddb://%s?amazonDDBClient=#client", tableName); --------------------------------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-aws/camel-aws2-ec2/src/main/docs/aws2-ec2-component.adoc b/components/camel-aws/camel-aws2-ec2/src/main/docs/aws2-ec2-component.adoc index 05e6fc1869148..063d41ee45ece 100644 --- a/components/camel-aws/camel-aws2-ec2/src/main/docs/aws2-ec2-component.adoc +++ b/components/camel-aws/camel-aws2-ec2/src/main/docs/aws2-ec2-component.adoc @@ -27,9 +27,9 @@ https://aws.amazon.com/ec2/[Amazon EC2]. == URI Format -------------------------- +---- aws2-ec2://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -94,19 +94,19 @@ For more information about this you can look at https://docs.aws.amazon.com/sdk- Java:: + [source,java] --------------------------------------------------------------------------------- +---- from("direct:createAndRun") .setHeader(EC2Constants.IMAGE_ID, constant("ami-fd65ba94")) .setHeader(EC2Constants.INSTANCE_TYPE, constant(InstanceType.T2_MICRO)) .setHeader(EC2Constants.INSTANCE_MIN_COUNT, constant("1")) .setHeader(EC2Constants.INSTANCE_MAX_COUNT, constant("1")) .to("aws2-ec2://TestDomain?accessKey=xxxx&secretKey=xxxx&operation=createAndRunInstances"); --------------------------------------------------------------------------------- +---- XML:: + [source,xml] --------------------------------------------------------------------------------- +---- @@ -123,12 +123,12 @@ XML:: --------------------------------------------------------------------------------- +---- YAML:: + [source,yaml] --------------------------------------------------------------------------------- +---- - route: from: uri: direct:createAndRun @@ -151,14 +151,14 @@ YAML:: accessKey: xxxx secretKey: xxxx operation: createAndRunInstances --------------------------------------------------------------------------------- +---- ==== - startInstances: this operation will start a list of EC2 instances ._Java-only: using a Processor to set the instance IDs collection_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .process(new Processor() { @Override @@ -169,13 +169,13 @@ from("direct:start") } }) .to("aws2-ec2://TestDomain?accessKey=xxxx&secretKey=xxxx&operation=startInstances"); --------------------------------------------------------------------------------- +---- - stopInstances: this operation will stop a list of EC2 instances ._Java-only: using a Processor to set the instance IDs collection_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:stop") .process(new Processor() { @Override @@ -186,13 +186,13 @@ from("direct:stop") } }) .to("aws2-ec2://TestDomain?accessKey=xxxx&secretKey=xxxx&operation=stopInstances"); --------------------------------------------------------------------------------- +---- - terminateInstances: this operation will terminate a list of EC2 instances ._Java-only: using a Processor to set the instance IDs collection_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:stop") .process(new Processor() { @Override @@ -203,7 +203,7 @@ from("direct:stop") } }) .to("aws2-ec2://TestDomain?accessKey=xxxx&secretKey=xxxx&operation=terminateInstances"); --------------------------------------------------------------------------------- +---- === Using a POJO as body @@ -212,11 +212,11 @@ In AWS EC2 there are multiple operations you can submit, as an example for Creat ._Java-only: using AWS SDK RunInstancesRequest as POJO body_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setBody(RunInstancesRequest.builder().imageId("test-1").instanceType(InstanceType.T2_MICRO).build()) .to("aws2-ec2://TestDomain?accessKey=xxxx&secretKey=xxxx&operation=createAndRunInstances&pojoRequest=true"); ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -227,13 +227,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-ec2 ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-ecs/src/main/docs/aws2-ecs-component.adoc b/components/camel-aws/camel-aws2-ecs/src/main/docs/aws2-ecs-component.adoc index 2138511d90762..ea960026caed1 100644 --- a/components/camel-aws/camel-aws2-ecs/src/main/docs/aws2-ecs-component.adoc +++ b/components/camel-aws/camel-aws2-ecs/src/main/docs/aws2-ecs-component.adoc @@ -26,9 +26,9 @@ https://aws.amazon.com/ecs/[Amazon ECS]. == URI Format -------------------------- +---- aws2-ecs://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -124,11 +124,11 @@ In AWS ECS there are multiple operations you can submit, as an example for List ._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setBody(ListClustersRequest.builder().maxResults(10).build()) .to("aws2-ecs://test?ecsClient=#amazonEcsClient&operation=listClusters&pojoRequest=true") ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -139,13 +139,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-ecs ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-eks/src/main/docs/aws2-eks-component.adoc b/components/camel-aws/camel-aws2-eks/src/main/docs/aws2-eks-component.adoc index c69aad1de07fa..2d07c6ac2a321 100644 --- a/components/camel-aws/camel-aws2-eks/src/main/docs/aws2-eks-component.adoc +++ b/components/camel-aws/camel-aws2-eks/src/main/docs/aws2-eks-component.adoc @@ -27,9 +27,9 @@ https://aws.amazon.com/eks/[Amazon EKS]. == URI Format -------------------------- +---- aws2-eks://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -128,11 +128,11 @@ In AWS EKS there are multiple operations you can submit, as an example for List ._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setBody(ListClustersRequest.builder().maxResults(12).build()) .to("aws2-eks://test?eksClient=#amazonEksClient&operation=listClusters&pojoRequest=true") ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -143,13 +143,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-eks ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-eventbridge/src/main/docs/aws2-eventbridge-component.adoc b/components/camel-aws/camel-aws2-eventbridge/src/main/docs/aws2-eventbridge-component.adoc index 40ff529f810af..12d97f21917d2 100644 --- a/components/camel-aws/camel-aws2-eventbridge/src/main/docs/aws2-eventbridge-component.adoc +++ b/components/camel-aws/camel-aws2-eventbridge/src/main/docs/aws2-eventbridge-component.adoc @@ -31,9 +31,9 @@ To create a rule that triggers on an action by an AWS service that does not emit == URI Format -------------------------- +---- aws2-eventbridge://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -829,13 +829,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-eventbridge ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-iam/src/main/docs/aws2-iam-component.adoc b/components/camel-aws/camel-aws2-iam/src/main/docs/aws2-iam-component.adoc index df03b40732b77..5c2cab8ddbb78 100644 --- a/components/camel-aws/camel-aws2-iam/src/main/docs/aws2-iam-component.adoc +++ b/components/camel-aws/camel-aws2-iam/src/main/docs/aws2-iam-component.adoc @@ -27,9 +27,9 @@ https://aws.amazon.com/iam/[Amazon IAM]. == URI Format -------------------------- +---- aws2-iam://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -1338,11 +1338,11 @@ In AWS IAM, there are multiple operations you can submit, as an example for Crea ._Java-only: requires AWS SDK builder_ [source,java] --------------------------- +---- from("direct:createUser") .setBody(CreateUserRequest.builder().userName("camel").build()) .to("aws2-iam://test?iamClient=#amazonIAMClient&operation=createUser&pojoRequest=true") --------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -1353,13 +1353,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-iam ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-kinesis/src/main/docs/aws2-kinesis-firehose-component.adoc b/components/camel-aws/camel-aws2-kinesis/src/main/docs/aws2-kinesis-firehose-component.adoc index 478ad322b8fe9..9e7802fdeb283 100644 --- a/components/camel-aws/camel-aws2-kinesis/src/main/docs/aws2-kinesis-firehose-component.adoc +++ b/components/camel-aws/camel-aws2-kinesis/src/main/docs/aws2-kinesis-firehose-component.adoc @@ -26,9 +26,9 @@ at https://aws.amazon.com/kinesis/firehose/[AWS Kinesis Firehose] == URI Format [source,java] ------------------------------------ +---- aws2-kinesis-firehose://delivery-stream-name[?options] ------------------------------------ +---- The stream needs to be created prior to it being used. @@ -152,7 +152,7 @@ You can send an iterable of Kinesis Record (as the following example shows), or ._Java-only: uses ProducerTemplate, inline Processor, and AWS SDK builders_ [source,java] --------------------------------------------------------------------------------------------------------------------- +---- @Test public void testFirehoseBatchRouting() throws Exception { Exchange exchange = template.send("direct:start", ExchangePattern.InOnly, new Processor() { @@ -169,7 +169,7 @@ You can send an iterable of Kinesis Record (as the following example shows), or } from("direct:start").to("aws2-kinesis-firehose://cc?amazonKinesisFirehoseClient=#FirehoseClient&operation=sendBatchRecord"); --------------------------------------------------------------------------------------------------------------------- +---- In the deliveryStream you'll find "Test1Test2". @@ -180,13 +180,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-kinesis ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-kms/src/main/docs/aws2-kms-component.adoc b/components/camel-aws/camel-aws2-kms/src/main/docs/aws2-kms-component.adoc index 4a552b90e4a91..d91e7efe07b25 100644 --- a/components/camel-aws/camel-aws2-kms/src/main/docs/aws2-kms-component.adoc +++ b/components/camel-aws/camel-aws2-kms/src/main/docs/aws2-kms-component.adoc @@ -26,9 +26,9 @@ https://aws.amazon.com/kms/[Amazon KMS]. == URI Format -------------------------- +---- aws2-kms://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -256,11 +256,11 @@ In AWS KMS there are multiple operations you can submit, as an example for List ._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:createUser") .setBody(ListKeysRequest.builder().limit(10).build()) .to("aws2-kms://test?kmsClient=#amazonKmsClient&operation=listKeys&pojoRequest=true") ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -271,13 +271,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-kms ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-lambda/src/main/docs/aws2-lambda-component.adoc b/components/camel-aws/camel-aws2-lambda/src/main/docs/aws2-lambda-component.adoc index 781235f2e1236..026d897d5ebf4 100644 --- a/components/camel-aws/camel-aws2-lambda/src/main/docs/aws2-lambda-component.adoc +++ b/components/camel-aws/camel-aws2-lambda/src/main/docs/aws2-lambda-component.adoc @@ -28,9 +28,9 @@ When creating a Lambda function, you need to specify an IAM role which has at le == URI Format -------------------------- +---- aws2-lambda://functionName[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -836,11 +836,11 @@ In AWS Lambda there are multiple operations you can submit, as an example for Ge ._Java-only: requires AWS SDK builder_ [source,java] --------------------------- +---- from("direct:getFunction") .setBody(GetFunctionRequest.builder().functionName("test").build()) .to("aws2-lambda://GetHelloWithName?awsLambdaClient=#awsLambdaClient&operation=getFunction&pojoRequest=true") --------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -852,13 +852,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-lambda ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-mq/src/main/docs/aws2-mq-component.adoc b/components/camel-aws/camel-aws2-mq/src/main/docs/aws2-mq-component.adoc index c23969573121c..705f44c56652c 100644 --- a/components/camel-aws/camel-aws2-mq/src/main/docs/aws2-mq-component.adoc +++ b/components/camel-aws/camel-aws2-mq/src/main/docs/aws2-mq-component.adoc @@ -26,9 +26,9 @@ https://aws.amazon.com/amazon-mq/[Amazon MQ]. == URI Format -------------------------- +---- aws2-mq://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -125,7 +125,7 @@ YAML:: ._Java-only: uses inline Processor, Java constants, and AWS SDK builders_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:createBroker") .process(new Processor() { @Override @@ -146,7 +146,7 @@ from("direct:createBroker") } }) .to("aws2-mq://test?amazonMqClient=#amazonMqClient&operation=createBroker") --------------------------------------------------------------------------------- +---- - deleteBroker: this operation will delete an MQ Broker in AWS @@ -245,11 +245,11 @@ In AWS MQ, there are multiple operations you can submit, as an example for List ._Java-only: uses AWS SDK POJO request builder as message body_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:aws2-mq") .setBody(ListBrokersRequest.builder().maxResults(10).build()) .to("aws2-mq://test?amazonMqClient=#amazonMqClient&operation=listBrokers&pojoRequest=true") ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -260,13 +260,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-mq ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-msk/src/main/docs/aws2-msk-component.adoc b/components/camel-aws/camel-aws2-msk/src/main/docs/aws2-msk-component.adoc index 8513bc0d141ee..a173de31a6cdc 100644 --- a/components/camel-aws/camel-aws2-msk/src/main/docs/aws2-msk-component.adoc +++ b/components/camel-aws/camel-aws2-msk/src/main/docs/aws2-msk-component.adoc @@ -26,9 +26,9 @@ https://aws.amazon.com/msk/[Amazon MSK]. == URI Format -------------------------- +---- aws2-msk://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -117,7 +117,7 @@ YAML:: ._Java-only: creating an MSK Cluster with a Processor and MSK2Constants_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:createCluster") .process(new Processor() { @Override @@ -130,7 +130,7 @@ from("direct:createCluster") } }) .to("aws2-msk://test?mskClient=#amazonMskClient&operation=createCluster") --------------------------------------------------------------------------------- +---- - deleteCluster: this operation will delete an MSK Cluster in AWS @@ -179,7 +179,7 @@ YAML:: ._Java-only: deleting an MSK Cluster with a Processor and MSK2Constants_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:createCluster") .process(new Processor() { @Override @@ -192,7 +192,7 @@ from("direct:createCluster") } }) .to("aws2-msk://test?mskClient=#amazonMskClient&operation=deleteCluster") --------------------------------------------------------------------------------- +---- === Using a POJO as body @@ -201,11 +201,11 @@ In AWS MSK, there are multiple operations you can submit, as an example for List ._Java-only: using an AWS SDK POJO request as the message body_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:aws2-msk") .setBody(ListClustersRequest.builder().maxResults(10).build()) .to("aws2-msk://test?mskClient=#amazonMskClient&operation=listClusters&pojoRequest=true") ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -216,13 +216,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-msk ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-polly/src/main/docs/aws2-polly-component.adoc b/components/camel-aws/camel-aws2-polly/src/main/docs/aws2-polly-component.adoc index 7838c38b0a541..750c635f91c43 100644 --- a/components/camel-aws/camel-aws2-polly/src/main/docs/aws2-polly-component.adoc +++ b/components/camel-aws/camel-aws2-polly/src/main/docs/aws2-polly-component.adoc @@ -26,9 +26,9 @@ https://aws.amazon.com/polly/[Amazon Polly]. == URI Format -------------------------- +---- aws2-polly://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -89,13 +89,13 @@ Camel-AWS Polly component provides the following operations on the producer side ._Java-only: uses AWS SDK enum constants for header values_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setHeader(Polly2Constants.VOICE_ID, constant(VoiceId.JOANNA)) .setBody(constant("Hello, this is a test of Amazon Polly text to speech synthesis.")) .to("aws2-polly://test?operation=synthesizeSpeech") .to("file:output?fileName=speech.mp3"); ------------------------------------------------------------------------------------------------------- +---- As a result, you'll get an exchange containing the audio stream (InputStream) with the synthesized speech. @@ -103,13 +103,13 @@ As a result, you'll get an exchange containing the audio stream (InputStream) wi ._Java-only: uses AWS SDK enum constants for header values_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setHeader(Polly2Constants.VOICE_ID, constant(VoiceId.MATTHEW)) .setHeader(Polly2Constants.ENGINE, constant(Engine.NEURAL)) .setBody(constant("This is synthesized using a neural voice.")) .to("aws2-polly://test?operation=synthesizeSpeech&outputFormat=MP3"); ------------------------------------------------------------------------------------------------------- +---- === Describe Voices example @@ -158,14 +158,14 @@ For long text, you can use asynchronous synthesis which stores the result in S3: ._Java-only: uses Java constants for header names_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setHeader(Polly2Constants.VOICE_ID, constant(VoiceId.JOANNA)) .setHeader(Polly2Constants.S3_BUCKET, constant("my-audio-bucket")) .setHeader(Polly2Constants.S3_KEY_PREFIX, constant("audio/")) .setBody(constant("This is a very long text that will be synthesized asynchronously...")) .to("aws2-polly://test?operation=startSpeechSynthesisTask"); ------------------------------------------------------------------------------------------------------- +---- === Using a POJO as body @@ -174,7 +174,7 @@ In AWS Polly, you can do something like: ._Java-only: uses AWS SDK request builder API_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setBody(SynthesizeSpeechRequest.builder() .voiceId(VoiceId.JOANNA) @@ -182,7 +182,7 @@ from("direct:start") .text("Hello from Camel!") .build()) .to("aws2-polly://test?operation=synthesizeSpeech&pojoRequest=true"); ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -193,13 +193,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-polly ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-redshift/src/main/docs/aws2-redshift-data-component.adoc b/components/camel-aws/camel-aws2-redshift/src/main/docs/aws2-redshift-data-component.adoc index af40fa2de11b9..8b9243fff08e7 100644 --- a/components/camel-aws/camel-aws2-redshift/src/main/docs/aws2-redshift-data-component.adoc +++ b/components/camel-aws/camel-aws2-redshift/src/main/docs/aws2-redshift-data-component.adoc @@ -29,9 +29,9 @@ https://aws.amazon.com/redshift/[AWS Redshift]. == URI Format -------------------------- +---- aws2-redshift-data://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -137,11 +137,11 @@ In AWS Redshift Data there are multiple operations you can submit, as an example ._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setBody(ListDatabases.builder().database("database1").build()) .to("aws2-redshift-data://test?awsRedshiftDataClient=#awsRedshiftDataClient&operation=listDatabases&pojoRequest=true") ------------------------------------------------------------------------------------------------------- +---- In this way you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -152,13 +152,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-redshift-data ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-rekognition/src/main/docs/aws2-rekognition-component.adoc b/components/camel-aws/camel-aws2-rekognition/src/main/docs/aws2-rekognition-component.adoc index c885cfaf226f8..2e8bce7288533 100644 --- a/components/camel-aws/camel-aws2-rekognition/src/main/docs/aws2-rekognition-component.adoc +++ b/components/camel-aws/camel-aws2-rekognition/src/main/docs/aws2-rekognition-component.adoc @@ -30,9 +30,9 @@ https://aws.amazon.com/rekognition/[AWS Rekognition]. == URI Format -------------------------- +---- aws2-rekognition://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -155,11 +155,11 @@ In AWS Rekognition, there are multiple operations you can submit, as an example ._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setBody(CreateCollectionRequest.builder().collectionId("test-collection").build()) .to("aws2-rekognition://test?awsRekognitionClient=#awsRekognitionClient&operation=createCollection&pojoRequest=true") ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -170,12 +170,12 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-rekognition ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc index 6b2a2c3ab60c1..385b4961c08fe 100644 --- a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc +++ b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc @@ -26,9 +26,9 @@ https://aws.amazon.com/s3[Amazon S3]. == URI Format ------------------------------- +---- aws2-s3://bucketNameOrArn[?options] ------------------------------- +---- The bucket will be created if it doesn't already exist. @@ -2502,13 +2502,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-s3 ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-ses/src/main/docs/aws2-ses-component.adoc b/components/camel-aws/camel-aws2-ses/src/main/docs/aws2-ses-component.adoc index dd32bc4dae5ce..35bac62591a83 100644 --- a/components/camel-aws/camel-aws2-ses/src/main/docs/aws2-ses-component.adoc +++ b/components/camel-aws/camel-aws2-ses/src/main/docs/aws2-ses-component.adoc @@ -26,9 +26,9 @@ https://aws.amazon.com/ses[Amazon SES]. == URI Format ------------------------- +---- aws2-ses://from[?options] ------------------------- +---- You can append query options to the URI in the following format: @@ -177,13 +177,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-ses ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc b/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc index 22519f1503055..3b8b642f1aac4 100644 --- a/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc +++ b/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc @@ -28,9 +28,9 @@ https://aws.amazon.com/sns[Amazon SNS]. == URI Format ------------------------------ +---- aws2-sns://topicNameOrArn[?options] ------------------------------ +---- The topic will be created if they don't already exist. @@ -217,7 +217,7 @@ Suppose you created an SNS FIFO Topic called `Order.fifo` and an SQS Queue calle In the access Policy of the `QueueSub.fifo` you should submit something like this [source,json] -------------------------------------------------- +---- { "Version": "2008-10-17", "Id": "__default_policy_ID", @@ -246,7 +246,7 @@ In the access Policy of the `QueueSub.fifo` you should submit something like thi } ] } -------------------------------------------------- +---- This is a critical step to make the subscription work correctly. @@ -308,7 +308,7 @@ Sending batch to a topic ._Java-only: requires constructing `PublishBatchRequestEntry` objects programmatically_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { List pubList = List.of( @@ -319,7 +319,7 @@ from("direct:start") exchange.getIn().setBody(pubList); }) .to("aws2-sns://camel-topic?subject=The+subject+message&autoCreateTopic=true&batchEnabled=true"); --------------------------------------------------------------------------------- +---- == Dependencies @@ -328,13 +328,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-sns ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-sqs/src/main/docs/aws2-sqs-component.adoc b/components/camel-aws/camel-aws2-sqs/src/main/docs/aws2-sqs-component.adoc index c9002977271f0..8a6d7fc2b38d6 100644 --- a/components/camel-aws/camel-aws2-sqs/src/main/docs/aws2-sqs-component.adoc +++ b/components/camel-aws/camel-aws2-sqs/src/main/docs/aws2-sqs-component.adoc @@ -26,9 +26,9 @@ https://aws.amazon.com/sqs[Amazon SQS]. == URI Format ------------------------------- +---- aws2-sqs://queueNameOrArn[?options] ------------------------------- +---- The queue will be created if they don't already exist. @@ -91,7 +91,7 @@ In the example below, we use _myClient_ as the bean id: ._Java-only: programmatic `SqsClient` creation and registry binding_ [source,java] ---------------------------------------------------------------------------------- +---- // create my own instance of SqsClient SqsClient sqs = ... @@ -101,7 +101,7 @@ camelContext.getRegistry().bind("myClient", sqs); // refer to the custom client via myClient as the bean id from("aws2-sqs://MyQueue?amazonSQSClient=#myClient&delay=5000&maxMessagesPerPoll=5") .to("mock:result"); ---------------------------------------------------------------------------------- +---- === DelayQueue VS Delay for Single message @@ -252,7 +252,7 @@ You can set a `SendMessageBatchRequest` or an `Iterable` ._Java-only: requires constructing a `List` body programmatically for batch messages_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setHeader("CamelAwsSqsOperation", constant("sendBatchMessage")) .process(exchange -> { @@ -264,7 +264,7 @@ from("direct:start") exchange.getIn().setBody(c); }) .to("aws2-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)®ion=eu-west-1"); ------------------------------------------------------------------------------------------------------- +---- As result, you'll get an exchange containing a `SendMessageBatchResponse` instance, that you can examine to check what messages were successful and what not. The id set on each message of the batch will be a Random UUID. @@ -449,13 +449,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-sqs ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-step-functions/src/main/docs/aws2-step-functions-component.adoc b/components/camel-aws/camel-aws2-step-functions/src/main/docs/aws2-step-functions-component.adoc index fac57ecca0ca8..4cd1cfd8e96c0 100644 --- a/components/camel-aws/camel-aws2-step-functions/src/main/docs/aws2-step-functions-component.adoc +++ b/components/camel-aws/camel-aws2-step-functions/src/main/docs/aws2-step-functions-component.adoc @@ -33,9 +33,9 @@ https://aws.amazon.com/step-functions/[AWS Step Functions]. == URI Format -------------------------- +---- aws2-step-functions://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -147,11 +147,11 @@ In AWS Step Functions, there are multiple operations you can submit, as an examp ._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setBody(CreateStateMachineRequest.builder().name("state-machine").build()) .to("aws2-step-functions://test?awsSfnClient=#awsSfnClient&operation=createStateMachine&pojoRequest=true") ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -162,13 +162,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-step-functions ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-sts/src/main/docs/aws2-sts-component.adoc b/components/camel-aws/camel-aws2-sts/src/main/docs/aws2-sts-component.adoc index 41738bba7330e..d4cf3c6864649 100644 --- a/components/camel-aws/camel-aws2-sts/src/main/docs/aws2-sts-component.adoc +++ b/components/camel-aws/camel-aws2-sts/src/main/docs/aws2-sts-component.adoc @@ -31,9 +31,9 @@ The AWS2 STS component works on the aws-global region, and it has aws-global as == URI Format -------------------------- +---- aws2-sts://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -228,11 +228,11 @@ In AWS STS, as an example for Assume Role request, you can do something like: ._Java-only: using a POJO request body with the AWS SDK builder_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:createUser") .setBody(AssumeRoleRequest.builder().roleArn("arn:123").roleSessionName("groot").build()) .to("aws2-sts://test?stsClient=#amazonSTSClient&operation=assumeRole&pojoRequest=true") ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -243,13 +243,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-sts ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-timestream/src/main/docs/aws2-timestream-component.adoc b/components/camel-aws/camel-aws2-timestream/src/main/docs/aws2-timestream-component.adoc index 18b9253d09d79..ee1c0ac95834d 100644 --- a/components/camel-aws/camel-aws2-timestream/src/main/docs/aws2-timestream-component.adoc +++ b/components/camel-aws/camel-aws2-timestream/src/main/docs/aws2-timestream-component.adoc @@ -40,9 +40,9 @@ https://aws.amazon.com/timestream/[AWS Timestream]. == URI Format -------------------------- +---- aws2-timestream://clientType:label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -235,22 +235,22 @@ In AWS Timestream there are multiple operations you can submit, as an example fo ._Java-only: uses AWS SDK POJO request builder as message body_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setBody(CreateDatabaseRequest.builder().database(Database.builder().databaseName("testDb").kmsKeyId("testKmsKey").build()).build()) .to("aws2-timestream://write:test?awsTimestreamWriteClient=#awsTimestreamWriteClient&operation=createDatabase&pojoRequest=true") ------------------------------------------------------------------------------------------------------- +---- * Query Operation ** query: this operation will execute a timestream query ._Java-only: uses AWS SDK POJO request builder as message body_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:query") .setBody(QueryRequest.builder().queryString("SELECT * FROM testDb.testTable ORDER BY time DESC LIMIT 10").build()) .to("aws2-timestream://query:test?awsTimestreamQueryClient=#awsTimestreamQueryClient&operation=query&pojoRequest=true") --------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -261,13 +261,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-timestream ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-aws/camel-aws2-translate/src/main/docs/aws2-translate-component.adoc b/components/camel-aws/camel-aws2-translate/src/main/docs/aws2-translate-component.adoc index c6bf8efe8f059..618e1ccc6ad3e 100644 --- a/components/camel-aws/camel-aws2-translate/src/main/docs/aws2-translate-component.adoc +++ b/components/camel-aws/camel-aws2-translate/src/main/docs/aws2-translate-component.adoc @@ -26,9 +26,9 @@ https://aws.amazon.com/translate/[Amazon Translate]. == URI Format -------------------------- +---- aws2-translate://label[?options] -------------------------- +---- You can append query options to the URI in the following format: @@ -81,13 +81,13 @@ Camel-AWS Translate component provides the following operation on the producer s ._Java-only: uses Java constants for header names and enum values_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setHeader(TranslateConstants.SOURCE_LANGUAGE, TranslateLanguageEnum.ITALIAN) .setHeader(TranslateConstants.TARGET_LANGUAGE, TranslateLanguageEnum.GERMAN) .setBody("Ciao") .to("aws2-translate://test?translateClient=#amazonTranslateClient&operation=translateText"); ------------------------------------------------------------------------------------------------------- +---- As a result, you'll get an exchange containing the translated text. @@ -98,12 +98,12 @@ In AWS Translate, the only operation available is TranslateText, so you can do s ._Java-only: uses AWS SDK POJO request builder as message body_ [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setBody(TranslateTextRequest.builder().sourceLanguageCode(Translate2LanguageEnum.ITALIAN.toString()) .targetLanguageCode(Translate2LanguageEnum.GERMAN.toString()).text("Ciao").build()) .to("aws2-translate://test?translateClient=#amazonTranslateClient&operation=translateText&pojoRequest=true"); ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -114,13 +114,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-aws2-translate ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc b/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc index fecc61681b104..c4b7af0de367e 100644 --- a/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc +++ b/components/camel-azure/camel-azure-cosmosdb/src/main/docs/azure-cosmosdb-component.adoc @@ -27,22 +27,22 @@ https://docs.microsoft.com/azure/[Azure Documentation Portal]. [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-azure-cosmosdb x.x.x ------------------------------------------------------------- +---- == URI Format [source,text] ------------------------------- +---- azure-cosmosdb://[databaseName][/containerName][?options] ------------------------------- +---- In case of the consumer, `databaseName`, `containerName` are required, In case of the producer, it depends on the operation that being requested, for example if operation is on a database level, e.b: deleteDatabase, only `databaseName` is required, but in case diff --git a/components/camel-azure/camel-azure-eventhubs/src/main/docs/azure-eventhubs-component.adoc b/components/camel-azure/camel-azure-eventhubs/src/main/docs/azure-eventhubs-component.adoc index dd207c7482b51..f24b71702ebe0 100644 --- a/components/camel-azure/camel-azure-eventhubs/src/main/docs/azure-eventhubs-component.adoc +++ b/components/camel-azure/camel-azure-eventhubs/src/main/docs/azure-eventhubs-component.adoc @@ -27,21 +27,21 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-azure-eventhubs x.x.x ------------------------------------------------------------- +---- == URI Format [source,text] ------------------------------- +---- azure-eventhubs://[namespace/eventHubName][?options] ------------------------------- +---- When providing a `connectionString`, the `namespace` and `eventHubName` options are not required as they are already included in the `connectionString` diff --git a/components/camel-azure/camel-azure-functions/src/main/docs/azure-functions-component.adoc b/components/camel-azure/camel-azure-functions/src/main/docs/azure-functions-component.adoc index 7c748cfc20c11..a2b55664769b2 100644 --- a/components/camel-azure/camel-azure-functions/src/main/docs/azure-functions-component.adoc +++ b/components/camel-azure/camel-azure-functions/src/main/docs/azure-functions-component.adoc @@ -30,13 +30,13 @@ You must have a valid Azure subscription. More information is available at https://docs.microsoft.com/azure/[Azure Documentation Portal]. [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-azure-functions ${camel-version} ------------------------------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-azure/camel-azure-key-vault/src/main/docs/azure-key-vault-component.adoc b/components/camel-azure/camel-azure-key-vault/src/main/docs/azure-key-vault-component.adoc index 75e3d7ee62c97..ee52d80041ac0 100644 --- a/components/camel-azure/camel-azure-key-vault/src/main/docs/azure-key-vault-component.adoc +++ b/components/camel-azure/camel-azure-key-vault/src/main/docs/azure-key-vault-component.adoc @@ -26,21 +26,21 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-azure-key-vault x.x.x ------------------------------------------------------------- +---- == URI Format [source,text] ------------------------------- +---- azure-key-vault://vaultName[?options] ------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] diff --git a/components/camel-azure/camel-azure-servicebus/src/main/docs/azure-servicebus-component.adoc b/components/camel-azure/camel-azure-servicebus/src/main/docs/azure-servicebus-component.adoc index 50efaa9d4c4b4..617b9b6c24df5 100644 --- a/components/camel-azure/camel-azure-servicebus/src/main/docs/azure-servicebus-component.adoc +++ b/components/camel-azure/camel-azure-servicebus/src/main/docs/azure-servicebus-component.adoc @@ -25,14 +25,14 @@ You must have a valid Windows Azure Storage account. More information is availab https://docs.microsoft.com/azure/[Azure Documentation Portal]. [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-azure-servicebus x.x.x ------------------------------------------------------------- +---- // component options: START @@ -91,7 +91,7 @@ In the consumer, the returned message body will be of type `String`. ._Java-only: building a batch message list with a Processor_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { final List inputBatch = new LinkedList<>(); @@ -104,11 +104,11 @@ from("direct:start") }) .to("azure-servicebus:test//?connectionString=test") .to("mock:result"); --------------------------------------------------------------------------------- +---- ._Java-only: sending a batch message with a session ID_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { final List inputBatch = new LinkedList<>(); @@ -121,14 +121,14 @@ from("direct:start") }) .to("azure-servicebus:test//?connectionString=test&sessionId=123") .to("mock:result"); --------------------------------------------------------------------------------- +---- - `scheduleMessages` ._Java-only: scheduling messages with a Processor and ServiceBusConstants_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { final List inputBatch = new LinkedList<>(); @@ -142,7 +142,7 @@ from("direct:start") }) .to("azure-servicebus:test//?connectionString=test&producerOperation=scheduleMessages") .to("mock:result"); --------------------------------------------------------------------------------- +---- - `receiveMessages` diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc b/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc index b60d916313d9e..9381b594509fb 100644 --- a/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc +++ b/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc @@ -27,22 +27,22 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-azure-storage-blob x.x.x ------------------------------------------------------------- +---- == URI Format [source,text] ------------------------------- +---- azure-storage-blob://accountName[/containerName][?options] ------------------------------- +---- In the case of a consumer, `accountName`, `containerName` are required. @@ -120,7 +120,7 @@ create your own instance: ._Java-only: programmatic BlobServiceClient setup_ [source,java] ------------------------------------------------------------------------ +---- StorageSharedKeyCredential credential = new StorageSharedKeyCredential("yourAccountName", "yourAccessKey"); String uri = String.format("https://%s.blob.core.windows.net", "yourAccountName"); @@ -130,7 +130,7 @@ BlobServiceClient client = new BlobServiceClientBuilder() .buildClient(); // This is camel context context.getRegistry().bind("client", client); ------------------------------------------------------------------------ +---- Then refer to this instance in your Camel `azure-storage-blob` component configuration: @@ -139,25 +139,25 @@ Then refer to this instance in your Camel `azure-storage-blob` component configu Java:: + [source,java] ------------------------------------------------------------------------ +---- from("azure-storage-blob://cameldev/container1?blobName=myblob&serviceClient=#client") .to("mock:result"); ------------------------------------------------------------------------ +---- XML:: + [source,xml] ------------------------------------------------------------------------ +---- ------------------------------------------------------------------------ +---- YAML:: + [source,yaml] ------------------------------------------------------------------------ +---- - route: from: uri: azure-storage-blob://cameldev/container1 @@ -167,7 +167,7 @@ YAML:: steps: - to: uri: mock:result ------------------------------------------------------------------------ +---- ==== === Automatic detection of BlobServiceClient client in registry diff --git a/components/camel-azure/camel-azure-storage-datalake/src/main/docs/azure-storage-datalake-component.adoc b/components/camel-azure/camel-azure-storage-datalake/src/main/docs/azure-storage-datalake-component.adoc index 8227487f1e33d..57d6a6db63794 100644 --- a/components/camel-azure/camel-azure-storage-datalake/src/main/docs/azure-storage-datalake-component.adoc +++ b/components/camel-azure/camel-azure-storage-datalake/src/main/docs/azure-storage-datalake-component.adoc @@ -24,14 +24,14 @@ You need to have a valid Azure account with Azure storage set up. More informati Maven users will need to add the following dependency to their `pom.xml` for this component. [source,xml] ---------------- +---- org.apache.camel camel-azure-storage-datalake x.x.x ---------------- +---- == Uri Format diff --git a/components/camel-azure/camel-azure-storage-queue/src/main/docs/azure-storage-queue-component.adoc b/components/camel-azure/camel-azure-storage-queue/src/main/docs/azure-storage-queue-component.adoc index 94a5e7a38293f..310d4d12a954d 100644 --- a/components/camel-azure/camel-azure-storage-queue/src/main/docs/azure-storage-queue-component.adoc +++ b/components/camel-azure/camel-azure-storage-queue/src/main/docs/azure-storage-queue-component.adoc @@ -28,21 +28,21 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-azure-storage-queue x.x.x ------------------------------------------------------------- +---- == URI Format [source,text] ------------------------------- +---- azure-storage-queue://accountName[/queueName][?options] ------------------------------- +---- In the case of consumer, `accountName` and `queueName` are required. @@ -117,7 +117,7 @@ have more control over the `QueueServiceClient` instance configuration, you can create your own instance: [source,java] ------------------------------------------------------------------------ +---- StorageSharedKeyCredential credential = new StorageSharedKeyCredential("yourAccountName", "yourAccessKey"); String uri = String.format("https://%s.queue.core.windows.net", "yourAccountName"); @@ -127,7 +127,7 @@ QueueServiceClient client = new QueueServiceClientBuilder() .buildClient(); // This is camel context context.getRegistry().bind("client", client); ------------------------------------------------------------------------ +---- Then refer to this instance in your Camel `azure-storage-queue` component configuration: diff --git a/components/camel-barcode/src/main/docs/barcode-dataformat.adoc b/components/camel-barcode/src/main/docs/barcode-dataformat.adoc index bacbd5a0d8d54..6305dbed2bf1d 100644 --- a/components/camel-barcode/src/main/docs/barcode-dataformat.adoc +++ b/components/camel-barcode/src/main/docs/barcode-dataformat.adoc @@ -27,13 +27,13 @@ substituting the version number for the latest & greatest release (see the download page for the latest versions). [source,java] ----------------------------------------- +---- org.apache.camel camel-barcode x.x.x ----------------------------------------- +---- == Barcode Options @@ -63,19 +63,19 @@ The default values are: ._Java-only: Java programmatic data format instantiation_ [source,java] ------------------------------------------- +---- // QR-Code default DataFormat code = new BarcodeDataFormat(); ------------------------------------------- +---- If you want to use zxing hints, you can use the 'addToHintMap' method of your BarcodeDataFormat instance: ._Java-only: Java data format configuration API_ [source,java] ------------------------------------------------------------ +---- code.addToHintMap(DecodeHintType.TRY_HARDER, Boolean.true); ------------------------------------------------------------ +---- For possible hints, please consult the xzing documentation. @@ -83,19 +83,19 @@ For possible hints, please consult the xzing documentation. ._Java-only: route using Java data format variable_ [source,java] ----------------------------- +---- from("direct://code") .marshal(code) .to("file://barcode_out"); ----------------------------- +---- You can call the route from a test class with: ._Java-only: Java test API (ProducerTemplate)_ [source,java] -------------------------------------------------------------- +---- template.sendBody("direct://code", "This is a testmessage!"); -------------------------------------------------------------- +---- You should find inside the 'barcode_out' folder this image: @@ -109,11 +109,11 @@ If you've two instances, one for (generating) QR-Code and one for PDF417, it doe ._Java-only: route using Java data format variable_ [source,java] --------------------------------------------------------------------- +---- from("file://barcode_in?noop=true") .unmarshal(code) // for unmarshalling, the instance doesn't matter .to("mock:out"); --------------------------------------------------------------------- +---- If you'll paste the QR-Code image above into the 'barcode_in' folder, you should find _`This is a testmessage!`_ inside the mock. diff --git a/components/camel-bean-validator/src/main/docs/bean-validator-component.adoc b/components/camel-bean-validator/src/main/docs/bean-validator-component.adoc index 1b1e050b93a3d..835d97e23a8f9 100644 --- a/components/camel-bean-validator/src/main/docs/bean-validator-component.adoc +++ b/components/camel-bean-validator/src/main/docs/bean-validator-component.adoc @@ -25,20 +25,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-bean-validator x.y.z ------------------------------------------------------------- +---- == URI format ------------------------------- +---- bean-validator:label[?options] ------------------------------- +---- Where *label* is an arbitrary text value describing the endpoint. You can append query options to the URI in the following format: `?option=value&option=value&...` @@ -57,17 +57,17 @@ include::partial$component-endpoint-headers.adoc[] Java:: + [source,java] --------------------------------------------------------------------------------------------------------------------------------- +---- from("direct:test"). to("bean-validator://ValidationProviderResolverTest?validationProviderResolver=#myValidationProviderResolver"); --------------------------------------------------------------------------------------------------------------------------------- +---- XML:: + [source,xml] --------------------------------------------------------------------------------------------------------------------------------- +---- --------------------------------------------------------------------------------------------------------------------------------- +---- ==== == Example @@ -78,7 +78,7 @@ Assumed we have a java bean with the following annotations ._Java-only: Java Bean with validation annotations_ [source,java] ------------------------------------------------------------ +---- public class Car { @NotNull @@ -90,7 +90,7 @@ public class Car { // getter and setter } ------------------------------------------------------------ +---- and an interface definition for our custom validation group @@ -98,10 +98,10 @@ and an interface definition for our custom validation group ._Java-only: custom validation group interface_ [source,java] ---------------------------------- +---- public interface OptionalChecks { } ---------------------------------- +---- with the following Camel route, only the *@NotNull* constraints on the attributes `manufacturer` and `licensePlate` will be validated (Camel uses @@ -193,11 +193,11 @@ define a new interface first: ._Java-only: combined validation group interface using @GroupSequence_ [source,java] ------------------------------------------------------ +---- @GroupSequence({Default.class, OptionalChecks.class}) public interface AllChecks { } ------------------------------------------------------ +---- And then your route definition should look like this: @@ -249,20 +249,20 @@ like this: Java:: + [source,xml] ------------------------------------------------------------------------------------------------------- +---- ------------------------------------------------------------------------------------------------------- +---- XML:: + [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:start") .to("bean-validator://x?group=AllChecks&messageInterpolator=#myMessageInterpolator &traversableResolver=#myTraversableResolver&constraintValidatorFactory=#myConstraintValidatorFactory") .to("mock:end") ------------------------------------------------------------------------------------------------------- +---- ==== It's also possible to describe your constraints as XML and not as Java @@ -274,7 +274,7 @@ In this case, you have to provide the files `META-INF/validation.xml` and `const validation.xml:: + [source,xml] ------------------------------------------------------------------------------------------------------------------------------- +---- /constraints-car.xml ------------------------------------------------------------------------------------------------------------------------------- +---- constraints-car.xml:: + [source,xml] ----------------------------------------------------------------------------------------------------- +---- ----------------------------------------------------------------------------------------------------- +---- ==== Here is the XML syntax for the example route definition where **OrderedChecks** can be https://github.com/apache/camel/blob/main/components/camel-bean-validator/src/test/java/org/apache/camel/component/bean/validator/OrderedChecks.java @@ -329,7 +329,7 @@ Here is the XML syntax for the example route definition where **OrderedChecks** Note that the body should include an instance of a class to validate. [source,xml] ----------------------------------------------------------------------------------------------------- +---- "")) ---------------------------------------------------------------- +---- == Bean Binding diff --git a/components/camel-bindy/src/main/docs/bindy-dataformat.adoc b/components/camel-bindy/src/main/docs/bindy-dataformat.adoc index 5d1f9ec6f0256..6a67f8cd2d981 100644 --- a/components/camel-bindy/src/main/docs/bindy-dataformat.adoc +++ b/components/camel-bindy/src/main/docs/bindy-dataformat.adoc @@ -2044,13 +2044,13 @@ substituting the version number for the latest & greatest release (see the download page for the latest versions). [source,xml] --------------------------------------- +---- org.apache.camel camel-bindy x.x.x --------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-browse/src/main/docs/browse-component.adoc b/components/camel-browse/src/main/docs/browse-component.adoc index df6c3fbd0a9d1..a5ae9318afe6d 100644 --- a/components/camel-browse/src/main/docs/browse-component.adoc +++ b/components/camel-browse/src/main/docs/browse-component.adoc @@ -20,9 +20,9 @@ The exchanges sent to the endpoint are all available to be browsed. == URI format -------------------------- +---- browse:someId[?options] -------------------------- +---- Where _someId_ can be any string to uniquely identify the endpoint. diff --git a/components/camel-camunda/src/main/docs/camunda-component.adoc b/components/camel-camunda/src/main/docs/camunda-component.adoc index 74a37192278a1..f480138c5b356 100644 --- a/components/camel-camunda/src/main/docs/camunda-component.adoc +++ b/components/camel-camunda/src/main/docs/camunda-component.adoc @@ -33,19 +33,19 @@ To use the Camunda component, Maven users will need to add the following dependency to their `pom.xml`: [source,xml] ------------------------------------------------ +---- org.apache.camel camel-camunda ${camel-version} ------------------------------------------------ +---- == URI format -------------------------------- +---- camunda://[endpoint]?[options] -------------------------------- +---- // component options: START @@ -62,13 +62,13 @@ Set the `clusterId`, `clientId`, `clientSecret`, and `region` component options. ._Java-only: programmatic component configuration_ [source,java] ----------------------------------------------------------------------------------------------------------------------- +---- CamundaComponent camunda = context.getComponent("camunda", CamundaComponent.class); camunda.setClusterId("your-cluster-id"); camunda.setClientId("your-client-id"); camunda.setClientSecret("your-client-secret"); camunda.setRegion("bru-2"); ----------------------------------------------------------------------------------------------------------------------- +---- === Self-Managed @@ -77,11 +77,11 @@ also set `clientId`, `clientSecret`, and `oAuthAPI`. ._Java-only: programmatic component configuration_ [source,java] ----------------------------------------------------------------------------------------------------------------------- +---- CamundaComponent camunda = context.getComponent("camunda", CamundaComponent.class); camunda.setGrpcAddress("http://localhost:26500"); camunda.setRestAddress("http://localhost:8080"); ----------------------------------------------------------------------------------------------------------------------- +---- == Usage diff --git a/components/camel-cassandraql/src/main/docs/cql-component.adoc b/components/camel-cassandraql/src/main/docs/cql-component.adoc index 2fc7536bc4056..fab61151f431b 100644 --- a/components/camel-cassandraql/src/main/docs/cql-component.adoc +++ b/components/camel-cassandraql/src/main/docs/cql-component.adoc @@ -99,14 +99,14 @@ Cassandra table like this: *CAMEL_IDEMPOTENT.cql* [source,sql] ---------------------------------------------------------- +---- CREATE TABLE CAMEL_IDEMPOTENT ( NAME varchar, -- Repository name KEY varchar, -- Message key PRIMARY KEY (NAME, KEY) ) WITH compaction = {'class':'LeveledCompactionStrategy'} AND gc_grace_seconds = 86400; ---------------------------------------------------------- +---- This repository implementation uses lightweight transactions, (also known as Compare and Set) and requires Cassandra 2.0.7+. @@ -141,7 +141,7 @@ correlation key in a Cassandra table like this: *CAMEL_AGGREGATION.cql* [source,sql] ---------------------------------------------------------- +---- CREATE TABLE CAMEL_AGGREGATION ( NAME varchar, -- Repository name KEY varchar, -- Correlation id @@ -150,7 +150,7 @@ CREATE TABLE CAMEL_AGGREGATION ( PRIMARY KEY (NAME, KEY) ) WITH compaction = {'class':'LeveledCompactionStrategy'} AND gc_grace_seconds = 86400; ---------------------------------------------------------- +---- Alternatively, the `CassandraAggregationRepository` does not have a `NAME` column and can be extended to use a different data model. @@ -188,19 +188,19 @@ To insert something on a table, you can use the following code: ._Java-only: route with CQL query string concatenation_ [source,java] ---------------------------------------------------------- +---- String CQL = "insert into camel_user(login, first_name, last_name) values (?, ?, ?)"; from("direct:input") .to("cql://localhost/camel_ks?cql=" + CQL); ---------------------------------------------------------- +---- At this point, you should be able to insert data by using a list as body ._Java-only: creating a parameter list for CQL binding_ [source,java] ---------------------------------------------------------- +---- Arrays.asList("davsclaus", "Claus", "Ibsen"); ---------------------------------------------------------- +---- The same approach can be used for updating or querying the table. diff --git a/components/camel-clickup/src/main/docs/clickup-component.adoc b/components/camel-clickup/src/main/docs/clickup-component.adoc index a956de8c54406..070a8d17b4690 100644 --- a/components/camel-clickup/src/main/docs/clickup-component.adoc +++ b/components/camel-clickup/src/main/docs/clickup-component.adoc @@ -20,20 +20,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component. [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-clickup x.x.x ------------------------------------------------------------- +---- == URI format ----------------------------------------------------- +---- clickup:workspaceId[?options] ----------------------------------------------------- +---- == Usage @@ -49,18 +49,18 @@ To enable webhook mode, users need first to add a REST implementation to their a Maven users, for example, can add *netty-http* to their `pom.xml` file: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-netty-http ------------------------------------------------------------- +---- In Java DSL: ._Java-only: processing ClickUp webhook events with Java types and lambdas_ [source,java] ---------------------------------------------------------- +---- from("webhook:clickup:?&authorizationToken=&events=taskTimeTrackedUpdated") .choice() .when(exchange -> exchange.getIn().getBody() instanceof TaskTimeTrackedUpdatedEvent) @@ -73,7 +73,7 @@ from("webhook:clickup:?&authorizationToken=&eve .log("Unknown Event: ${body}") .end(); ---------------------------------------------------------- +---- You can follow the https://clickup.com/api/developer-portal/webhooks[set-up webhooks guide] diff --git a/components/camel-coap/src/main/docs/coap-component.adoc b/components/camel-coap/src/main/docs/coap-component.adoc index cf287f90de7bc..23d9220121d58 100644 --- a/components/camel-coap/src/main/docs/coap-component.adoc +++ b/components/camel-coap/src/main/docs/coap-component.adoc @@ -23,14 +23,14 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ---------------------------------------------------------- +---- org.apache.camel camel-coap x.x.x ---------------------------------------------------------- +---- // component options: START diff --git a/components/camel-consul/src/main/docs/consul-component.adoc b/components/camel-consul/src/main/docs/consul-component.adoc index 65c6700a31b8f..b6b7806340ba3 100644 --- a/components/camel-consul/src/main/docs/consul-component.adoc +++ b/components/camel-consul/src/main/docs/consul-component.adoc @@ -20,19 +20,19 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] -------------------------------------------------- +---- org.apache.camel camel-consul ${camel-version} -------------------------------------------------- +---- == URI format ---------------------------------------- +---- consul://domain?[options] ---------------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] diff --git a/components/camel-couchbase/src/main/docs/couchbase-component.adoc b/components/camel-couchbase/src/main/docs/couchbase-component.adoc index d233060ea01ba..f1b175da9cdc7 100644 --- a/components/camel-couchbase/src/main/docs/couchbase-component.adoc +++ b/components/camel-couchbase/src/main/docs/couchbase-component.adoc @@ -22,20 +22,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-couchbase x.x.x ------------------------------------------------------------- +---- == URI format -------------------------------------------------- +---- couchbase:url -------------------------------------------------- +---- // component options: START diff --git a/components/camel-couchdb/src/main/docs/couchdb-component.adoc b/components/camel-couchdb/src/main/docs/couchdb-component.adoc index d0fbd32455b36..0c575f9e7e7cf 100644 --- a/components/camel-couchdb/src/main/docs/couchdb-component.adoc +++ b/components/camel-couchdb/src/main/docs/couchdb-component.adoc @@ -39,20 +39,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-couchdb x.x.x ------------------------------------------------------------- +---- == URI format -------------------------------------------------- +---- couchdb:http://hostname[:port]/database?[options] -------------------------------------------------- +---- Where *hostname* is the hostname of the running couchdb instance. Port is optional and if not specified, then defaults to 5984. diff --git a/components/camel-crypto-pgp/src/main/docs/pgp-dataformat.adoc b/components/camel-crypto-pgp/src/main/docs/pgp-dataformat.adoc index 6d50e5be6cc80..8269c7c0967f3 100644 --- a/components/camel-crypto-pgp/src/main/docs/pgp-dataformat.adoc +++ b/components/camel-crypto-pgp/src/main/docs/pgp-dataformat.adoc @@ -152,27 +152,27 @@ if you would prefer to do it that way. Install the command line utilities on linux [source,bash] ---------------------- +---- apt-get install gnupg ---------------------- +---- Create your keyring, entering a secure password [source,bash] -------------- +---- gpg --gen-key -------------- +---- If you need to import someone else's public key so that you can encrypt a file for them. [source,bash] --------------------------- +---- gpg --import userId2Passphrase = new HashMap(2); // add passphrases of several private keys whose corresponding public keys have been used to encrypt the messages userId2Passphrase.put("UserIdOfKey1","passphrase1"); // you must specify the exact User ID! @@ -216,7 +216,7 @@ from("direct:start") ... .unmarshal(pgpVerifyAndDecrypt) // can decrypt/verify messages encrypted/signed by different private/public keys ... ------------------------------------------------------------------------------------------------------------------------------------------- +---- * The functionality is especially useful to support the key exchange. If you want to exchange the private key for decrypting, you can accept for a @@ -243,7 +243,7 @@ which can be used for the verification of a signature. ._Java-only: programmatic PGPDataFormat restricting signer identities for verification_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- // specify the User IDs of the expected signer identities List expectedSigUserIds = new ArrayList(); expectedSigUserIds.add("Trusted company1"); @@ -259,7 +259,7 @@ from("direct:start") ... .unmarshal(pgpVerifyWithSpecificKeysAndDecrypt) ... ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- * If the PGP content has several signatures, the verification is successful as soon as one signature can be verified. @@ -278,7 +278,7 @@ User IDs which relate to several private keys in the secret keyring. ._Java-only: programmatic PGPDataFormat with multiple signer keys_ [source,java] -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- PGPDataFormat pgpSignAndEncryptSeveralSignerKeys = new PGPDataFormat(); pgpSignAndEncryptSeveralSignerKeys.setKeyUserid(keyUserid); // for encrypting, you can also use setKeyUserids if you want to encrypt with several keys pgpSignAndEncryptSeveralSignerKeys.setKeyFileName(keyfileName); @@ -294,7 +294,7 @@ from("direct:start") ... .marshal(pgpSignAndEncryptSeveralSignerKeys) ... -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- == Support for Sub-Keys and Key Flags in PGP Data Format Marshaller @@ -339,14 +339,14 @@ To use the PGP dataformat in your camel routes you need to add the following dependency to your pom. [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-crypto x.x.x ----------------------------------------------------------- +---- diff --git a/components/camel-crypto/src/main/docs/crypto-component.adoc b/components/camel-crypto/src/main/docs/crypto-component.adoc index f4173c4532c2e..5cecd3be53df6 100644 --- a/components/camel-crypto/src/main/docs/crypto-component.adoc +++ b/components/camel-crypto/src/main/docs/crypto-component.adoc @@ -24,14 +24,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-crypto x.x.x ------------------------------------------------------------- +---- == Introduction @@ -64,10 +64,10 @@ http://en.wikipedia.org/wiki/Digital_signature[Digital_signatures] As mentioned, Camel provides a pair of crypto endpoints to create and verify signatures ----------------------------- +---- crypto:sign:name[?options] crypto:verify:name[?options] ----------------------------- +---- * `crypto:sign` creates the signature and stores it in the Header keyed by the constant diff --git a/components/camel-crypto/src/main/docs/crypto-dataformat.adoc b/components/camel-crypto/src/main/docs/crypto-dataformat.adoc index 1e4853ed14c6b..498eacf72cf2b 100644 --- a/components/camel-crypto/src/main/docs/crypto-dataformat.adoc +++ b/components/camel-crypto/src/main/docs/crypto-dataformat.adoc @@ -35,7 +35,7 @@ For example, using the Java DSL as follows: ._Java-only: programmatic CryptoDataFormat configuration with KeyGenerator_ [source,java] ----------------------------------------------------------- +---- KeyGenerator generator = KeyGenerator.getInstance("DES"); CryptoDataFormat cryptoFormat = new CryptoDataFormat("DES", generator.generateKey()); @@ -45,13 +45,13 @@ from("direct:basic-encryption") .to("mock:encrypted") .unmarshal(cryptoFormat) .to("mock:unencrypted"); ----------------------------------------------------------- +---- In Spring the dataformat is configured first and then used in routes [source,xml] ----------------------------------------------------------- +---- @@ -65,7 +65,7 @@ In Spring the dataformat is configured first and then used in routes ----------------------------------------------------------- +---- == Specifying the Encryption Algorithm @@ -74,7 +74,7 @@ Changing the algorithm is a matter of supplying the JCE algorithm name. If you c ._Java-only: programmatic CryptoDataFormat with custom algorithm and HMAC_ [source,java] ----------------------------------------------------------- +---- KeyGenerator generator = KeyGenerator.getInstance("DES"); CryptoDataFormat cryptoFormat = new CryptoDataFormat("DES", generator.generateKey()); @@ -86,7 +86,7 @@ from("direct:hmac-algorithm") .to("mock:encrypted") .unmarshal(cryptoFormat) .to("mock:unencrypted"); ----------------------------------------------------------- +---- A list of the available algorithms in Java 17 is available via the https://docs.oracle.com/en/java/javase/17/docs/specs/security/standard-names.html[Java Security Standard Algorithm Names] documentation. @@ -99,7 +99,7 @@ To use such a vector with the CryptoDataFormat, you can configure it with a byte ._Java-only: programmatic CryptoDataFormat with initialization vector_ [source,java] ----------------------------------------------------------- +---- KeyGenerator generator = KeyGenerator.getInstance("DES"); byte[] initializationVector = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; @@ -111,14 +111,14 @@ from("direct:init-vector") .to("mock:encrypted") .unmarshal(cryptoFormat) .to("mock:unencrypted"); ----------------------------------------------------------- +---- or with spring, suppling a reference to a byte[] [source,xml] ----------------------------------------------------------- +---- ----------------------------------------------------------- +---- The same vector is required in both the encryption and decryption phases. As it is not necessary to keep the IV a secret, the DataFormat allows for it to be inlined into the encrypted data and subsequently read out in the decryption phase to initialize the Cipher. To inline the IV set the `Inline` flag. @@ -128,7 +128,7 @@ The same vector is required in both the encryption and decryption phases. As it Java:: + [source,java] ----------------------------------------------------------- +---- KeyGenerator generator = KeyGenerator.getInstance("DES"); byte[] initializationVector = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; SecretKey key = generator.generateKey(); @@ -144,16 +144,16 @@ from("direct:inline") .to("mock:encrypted") .unmarshal(decryptFormat) .to("mock:unencrypted"); ----------------------------------------------------------- +---- Spring XML:: + [source,xml] ----------------------------------------------------------- +---- ----------------------------------------------------------- +---- ==== @@ -172,7 +172,7 @@ To avoid attacks against the encrypted data while it is in transit, the CryptoDa Java:: + [source,java] ----------------------------------------------------------- +---- KeyGenerator generator = KeyGenerator.getInstance("DES"); CryptoDataFormat cryptoFormat = new CryptoDataFormat("DES", generator.generateKey()); @@ -183,14 +183,14 @@ from("direct:hmac") .to("mock:encrypted") .unmarshal(cryptoFormat) .to("mock:unencrypted"); ----------------------------------------------------------- +---- Spring XML:: + [source,xml] ----------------------------------------------------------- +---- ----------------------------------------------------------- +---- ==== @@ -201,7 +201,7 @@ By default, the HMAC is calculated using the HmacSHA1 mac algorithm, though this Java:: + [source,java] ----------------------------------------------------------- +---- KeyGenerator generator = KeyGenerator.getInstance("DES"); CryptoDataFormat cryptoFormat = new CryptoDataFormat("DES", generator.generateKey()); @@ -213,14 +213,14 @@ from("direct:hmac-algorithm") .to("mock:encrypted") .unmarshal(cryptoFormat) .to("mock:unencrypted"); ----------------------------------------------------------- +---- Spring XML:: + [source,xml] ----------------------------------------------------------- +---- ----------------------------------------------------------- +---- ==== @@ -239,7 +239,7 @@ dynamically via the message headers below Java:: + [source,java] ----------------------------------------------------------- +---- CryptoDataFormat cryptoFormat = new CryptoDataFormat("DES", null); /** * Note: the header containing the key should be cleared after @@ -259,14 +259,14 @@ from("direct:key-in-header-decrypt").unmarshal(cryptoFormat).process(new Process exchange.getMessage().copyFrom(exchange.getIn()); } }).to("mock:unencrypted"); ----------------------------------------------------------- +---- Spring XML:: + [source,xml] ----------------------------------------------------------- +---- ----------------------------------------------------------- +---- ==== @@ -276,14 +276,14 @@ To use the xref:ROOT:crypto-component.adoc[Crypto] dataformat in your camel rout need to add the following dependency to your pom. [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-crypto x.x.x ----------------------------------------------------------- +---- diff --git a/components/camel-csv/src/main/docs/csv-dataformat.adoc b/components/camel-csv/src/main/docs/csv-dataformat.adoc index ee6493c1c478a..4c875d026fcba 100644 --- a/components/camel-csv/src/main/docs/csv-dataformat.adoc +++ b/components/camel-csv/src/main/docs/csv-dataformat.adoc @@ -49,11 +49,11 @@ Considering the following body: ._Java-only: Java collection API_ [source,java] -------------------------------------------------------- +---- Map body = new LinkedHashMap<>(); body.put("foo", "abc"); body.put("bar", 123); -------------------------------------------------------- +---- and this route definition: @@ -62,16 +62,16 @@ and this route definition: Java:: + [source,java] -------------------------------------------------------- +---- from("direct:start") .marshal().csv() .to("mock:result"); -------------------------------------------------------- +---- XML:: + [source,xml] -------------------------------------------------------- +---- @@ -79,7 +79,7 @@ XML:: -------------------------------------------------------- +---- YAML:: + @@ -112,13 +112,13 @@ An example: we have a CSV file with names of persons, their IQ and their current activity. [source,text] ------------------------------------------------------ +---- Jack Dalton, 115, mad at Averell Joe Dalton, 105, calming Joe William Dalton, 105, keeping Joe from killing Averell Averell Dalton, 80, playing with Rantanplan Lucky Luke, 120, capturing the Daltons ------------------------------------------------------ +---- We can now use the CSV component to unmarshal this file: @@ -168,12 +168,12 @@ The resulting message will contain a `List>` like... ._Java-only: Java collection API_ [source,java] --------------------------------------------------------------------------------------------------------------- +---- List> data = (List>) exchange.getIn().getBody(); for (List line : data) { LOG.debug(String.format("%s has an IQ of %s and is currently %s", line.get(0), line.get(1), line.get(2))); } --------------------------------------------------------------------------------------------------------------- +---- === Marshalling a List to CSV @@ -192,36 +192,36 @@ Given a bean which can handle the incoming data... ._Java-only: Java handler class_ [source,java] -------------------------------------------------------- +---- // Some comments here public void doHandleCsvData(List> csvData) { // do magic here } -------------------------------------------------------- +---- ... your route then looks as follows [source,xml] ------------------------------------------------------------------------------------------------- +---- ------------------------------------------------------------------------------------------------- +---- === Marshaling with a pipe as delimiter Considering the following body: ._Java-only: Java collection API_ [source,java] -------------------------------------------------------- +---- Map body = new LinkedHashMap<>(); body.put("foo", "abc"); body.put("bar", 123); -------------------------------------------------------- +---- And this Java route definition: @@ -231,7 +231,7 @@ And this Java route definition: Java:: + [source,java] -------------------------------------------------------- +---- from("direct:start") .marshal(new CsvDataFormat().setDelimiter('|')) .to("mock:result") @@ -240,7 +240,7 @@ from("direct:start") XML:: + [source,xml] -------------------------------------------------------- +---- @@ -248,7 +248,7 @@ XML:: -------------------------------------------------------- +---- YAML:: + @@ -269,7 +269,7 @@ YAML:: Then it will produce: -------------------------------------------------------- +---- abc|123 ------------------------------------------------------- @@ -285,7 +285,7 @@ value of the `autogenColumns` option is true. The following example should illustrate this customization. [source,xml] ------------------------------------------------------------------------------------------------------------------------------ +---- @@ -312,7 +312,7 @@ should illustrate this customization. ------------------------------------------------------------------------------------------------------------------------------ +---- === Collecting header record @@ -321,14 +321,14 @@ a message header called CamelCsvHeaderRecord. ._Java-only: Java programmatic data format configuration_ [source,java] --------------------------------------------- +---- CsvDataFormat csv = new CsvDataFormat(); csv.setCaptureHeaderRecord(true); from("direct:start") .unmarshal(csv) .log("${header[CamelCsvHeaderRecord]}"); --------------------------------------------- +---- === Using skipFirstLine or skipHeaderRecord option while unmarshaling @@ -338,7 +338,7 @@ The instruction for CSV Data format to skip headers or first line is the followi Usign the Spring/XML DSL: [source,xml] ---------------------------------------------------- +---- @@ -346,7 +346,7 @@ Usign the Spring/XML DSL: ---------------------------------------------------- +---- *Since Camel 2.10 and deleted for Camel 2.15* @@ -358,19 +358,19 @@ first line which contains the CSV headers. Using the Spring/XML DSL: Java:: + [source,java] --------------------------------------------- +---- CsvDataFormat csv = new CsvDataFormat(); csv.setSkipFirstLine(true); from("direct:start") .unmarshal(csv) .to("bean:myCsvHandler?method=doHandleCsv"); --------------------------------------------- +---- XML:: + [source,xml] ---------------------------------------------------- +---- @@ -378,7 +378,7 @@ XML:: ---------------------------------------------------- +---- YAML:: + @@ -409,7 +409,7 @@ YAML:: Java:: + [source,java] ----------------------------------------------------- +---- CsvDataFormat csv = new CsvDataFormat(); CSVStrategy strategy = CSVStrategy.DEFAULT_STRATEGY; strategy.setDelimiter('|'); @@ -418,24 +418,24 @@ csv.setStrategy(strategy); from("direct:start") .unmarshal(csv) .to("bean:myCsvHandler?method=doHandleCsv"); ----------------------------------------------------- +---- + Or, possibly: + [source,java] ----------------------------------------------- +---- CsvDataFormat csv = new CsvDataFormat(); csv.setDelimiter("|"); from("direct:start") .unmarshal(csv) .to("bean:myCsvHandler?method=doHandleCsv"); ----------------------------------------------- +---- XML:: + [source,xml] ---------------------------------------------------- +---- @@ -443,7 +443,7 @@ XML:: ---------------------------------------------------- +---- YAML:: + @@ -471,10 +471,10 @@ It looks like that ._Java-only: Java programmatic configuration_ [source,java] --------------------------------------- +---- CSVConfig csvConfig = new CSVConfig(); csvConfig.setDelimiter(';'); --------------------------------------- +---- This doesn't work. You have to set the delimiter as a String! @@ -488,13 +488,13 @@ substituting the version number for the latest and greatest release (see the download page for the latest versions). [source,xml] -------------------------------------- +---- org.apache.camel camel-csv x.x.x -------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-cxf/camel-cxf-rest/src/main/docs/cxfrs-component.adoc b/components/camel-cxf/camel-cxf-rest/src/main/docs/cxfrs-component.adoc index de84604988d3b..66f18fd290d42 100644 --- a/components/camel-cxf/camel-cxf-rest/src/main/docs/cxfrs-component.adoc +++ b/components/camel-cxf/camel-cxf-rest/src/main/docs/cxfrs-component.adoc @@ -20,34 +20,34 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] -------------------------------------------------------------------------------------- +---- org.apache.camel camel-cxf-rest x.x.x -------------------------------------------------------------------------------------- +---- == URI format ------------------------ +---- cxfrs://address?options ------------------------ +---- Where *address* represents the CXF endpoint's address ---------------------- +---- cxfrs:bean:rsEndpoint ---------------------- +---- Where *rsEndpoint* represents the spring bean's name, which presents the CXFRS client or server For either style above, you can append options to the URI as follows: ------------------------------------------------------------------- +---- cxfrs:bean:cxfEndpoint?resourceClasses=org.apache.camel.rs.Example ------------------------------------------------------------------- +---- // component options: START @@ -90,10 +90,10 @@ The `camel-cxfrs` producer supports overriding the service address by setting th ._Java-only: inline exchange header manipulation_ [source,java] ----------------------------------------------------------------------------------------------- +---- // set up the service address from the message header to override the setting of CXF endpoint exchange.getIn().setHeader(Exchange.DESTINATION_OVERRIDE_URL, constant(getServiceAddress())); ----------------------------------------------------------------------------------------------- +---- === Consuming a REST Request - Simple Binding Style @@ -196,12 +196,12 @@ Given a JAX-RS resource class with this method: ._Java-only: Java JAX-RS annotation_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------------- +---- @POST @Path("/customers/{type}") public Response newCustomer(Customer customer, @PathParam("type") String type, @QueryParam("active") @DefaultValue("true") boolean active) { return null; } ------------------------------------------------------------------------------------------------------------------------------------------------- +---- Serviced by the following route: @@ -255,7 +255,7 @@ YAML:: The following HTTP request with XML payload (given that the Customer DTO is JAXB-annotated): -------------------------------------- +---- POST /customers/gold?active=true Payload: @@ -264,13 +264,13 @@ Payload: Spain Apache Camel -------------------------------------- +---- Will print the message: ----------------------------------------------------------------------------------- +---- Request: type=gold, active=true, customerData= ----------------------------------------------------------------------------------- +---- [NOTE] ==== diff --git a/components/camel-cxf/camel-cxf-transport/src/main/docs/cxf-transport.adoc b/components/camel-cxf/camel-cxf-transport/src/main/docs/cxf-transport.adoc index c50991636fe5e..f41ea15f1a607 100644 --- a/components/camel-cxf/camel-cxf-transport/src/main/docs/cxf-transport.adoc +++ b/components/camel-cxf/camel-cxf-transport/src/main/docs/cxf-transport.adoc @@ -46,7 +46,7 @@ soon as you include the camel-cxf-transport.jar in your app, cxf will scan the jar and load a CamelTransportFactory for you. [source,xml] --------------------------------------------------------------------------------------------------------- +---- @@ -63,7 +63,7 @@ jar and load a CamelTransportFactory for you. --------------------------------------------------------------------------------------------------------- +---- [[CamelTransportforCXF-IntegratingtheCamelTransportinaprogrammaticway]] === Integrating the Camel Transport in a programmatic way @@ -75,7 +75,7 @@ a full example for you. ._Java-only: programmatic CXF bus and transport factory setup_ [source,java] ------------------------------------------------------------------------------------------------------------------- +---- import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.transport.ConduitInitiatorManager; @@ -99,7 +99,7 @@ DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class dfm.registerDestinationFactory(CamelTransportFactory.TRANSPORT_ID, camelTransportFactory); // set or bus as the default bus for cxf BusFactory.setDefaultBus(bus); ------------------------------------------------------------------------------------------------------------------- +---- [[CamelTransportforCXF-ConfigurethedestinationandconduitwithSpring]] == Configure the destination and conduit with Spring @@ -118,7 +118,7 @@ the `xsi:schemaLocation` attribute. *Adding the Configuration Namespace* [source,xml] ---------------------------------------------------------------------- +---- @@ -158,7 +158,7 @@ endpoint's target namespace was `\http://widgets.widgetvendor.net`. ... ---------------------------------------------------------------------------------------------------------------------------- +---- The `camel:destination` element for Spring has a number of child elements that specify configuration information. They are described @@ -192,7 +192,7 @@ endpoint's target namespace was `\http://widgets.widgetvendor.net`. *http-conf:conduit Element* [source,xml] -------------------------------------------------------------------------------------------------------------------------- +---- ... @@ -209,7 +209,7 @@ endpoint's target namespace was `\http://widgets.widgetvendor.net`. ... ... -------------------------------------------------------------------------------------------------------------------------- +---- The `camel:conduit` element has a number of child elements that specify configuration information. They are described below. diff --git a/components/camel-cyberark-vault/src/main/docs/cyberark-vault-component.adoc b/components/camel-cyberark-vault/src/main/docs/cyberark-vault-component.adoc index 5d4a921db8a74..c063cf7d8e65d 100644 --- a/components/camel-cyberark-vault/src/main/docs/cyberark-vault-component.adoc +++ b/components/camel-cyberark-vault/src/main/docs/cyberark-vault-component.adoc @@ -23,9 +23,9 @@ You must have access to a CyberArk Conjur instance and have the necessary creden == URI Format -------------------------- +---- cyberark-vault:label[?options] -------------------------- +---- Where `label` is a logical name for the endpoint. diff --git a/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc b/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc index 56764b7847c7a..37610afb1bde8 100644 --- a/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc +++ b/components/camel-datasonnet/src/main/docs/datasonnet-language.adoc @@ -24,9 +24,9 @@ To use a DataSonnet expression, use the following Java code: ._Java-only: creating a DataSonnet expression_ [source,java] ---------------------------------------- +---- datasonnet("someDSExpression"); ---------------------------------------- +---- == DataSonnet Options @@ -258,16 +258,16 @@ Here's an example showing some of these functions in use: Java:: + [source,java] ------------------------------------------------------------------------------------------------- +---- from("direct:in") .setBody(datasonnet("'hello, ' + cml.properties('toGreet')", String.class)) .to("mock:camel"); ------------------------------------------------------------------------------------------------- +---- XML:: + [source,xml] ------------------------------------------------------------------------------ +---- @@ -275,7 +275,7 @@ XML:: ------------------------------------------------------------------------------ +---- YAML:: + @@ -304,9 +304,9 @@ e.g., to refer to a file on the classpath you can do: ._Java-only: loading a DataSonnet script from an external resource_ [source,java] -------------------------------------------------------------------- +---- .setHeader("myHeader").datasonnet("resource:classpath:mydatasonnet.ds"); -------------------------------------------------------------------- +---- == Examples @@ -317,17 +317,17 @@ Here is a simple example using a DataSonnet expression as a predicate in a Messa Java:: + [source,java] ------------------------------------------------------------------------------------------------- +---- // let's route if a line item is over $100 from("queue:foo") .filter(datasonnet("ds.arrays.firstWith(body.lineItems, function(item) item > 100) != null")) .to("queue:bar"); ------------------------------------------------------------------------------------------------- +---- XML:: + [source,xml] ------------------------------------------------------------------------------ +---- @@ -335,7 +335,7 @@ XML:: ------------------------------------------------------------------------------ +---- YAML:: + @@ -364,16 +364,16 @@ Here is an example of a simple DataSonnet expression as a transformation EIP. Th Java:: + [source,java] ------------------------------------------------------------------------------------------------- +---- from("queue:foo") .transform(datasonnet("ds.filter(body.lineItems, function(item) item > 100)", String.class, "application/xml", "application/json")) .to("queue:bar"); ------------------------------------------------------------------------------------------------- +---- XML:: + [source,xml] ------------------------------------------------------------------------------ +---- @@ -383,7 +383,7 @@ XML:: ------------------------------------------------------------------------------ +---- YAML:: + @@ -446,13 +446,13 @@ substituting the version number for the latest and greatest release (see the download page for the latest versions). [source,xml] ---------------------------------------- +---- org.apache.camel camel-datasonnet x.x.x ---------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-debezium/camel-debezium-db2/src/main/docs/debezium-db2-component.adoc b/components/camel-debezium/camel-debezium-db2/src/main/docs/debezium-db2-component.adoc index 24624ce8aed9e..7973ca5223477 100644 --- a/components/camel-debezium/camel-debezium-db2/src/main/docs/debezium-db2-component.adoc +++ b/components/camel-debezium/camel-debezium-db2/src/main/docs/debezium-db2-component.adoc @@ -47,9 +47,9 @@ for this component. == URI format ---------------------------- +---- debezium-db2:name[?options] ---------------------------- +---- // component options: START diff --git a/components/camel-debezium/camel-debezium-mongodb/src/main/docs/debezium-mongodb-component.adoc b/components/camel-debezium/camel-debezium-mongodb/src/main/docs/debezium-mongodb-component.adoc index 32ec4d56132dd..a8a465e38e7bd 100644 --- a/components/camel-debezium/camel-debezium-mongodb/src/main/docs/debezium-mongodb-component.adoc +++ b/components/camel-debezium/camel-debezium-mongodb/src/main/docs/debezium-mongodb-component.adoc @@ -51,9 +51,9 @@ for this component. == URI format ---------------------------- +---- debezium-mongodb:name[?options] ---------------------------- +---- // component options: START diff --git a/components/camel-debezium/camel-debezium-mysql/src/main/docs/debezium-mysql-component.adoc b/components/camel-debezium/camel-debezium-mysql/src/main/docs/debezium-mysql-component.adoc index 73a5648041afc..a15b4c087e92f 100644 --- a/components/camel-debezium/camel-debezium-mysql/src/main/docs/debezium-mysql-component.adoc +++ b/components/camel-debezium/camel-debezium-mysql/src/main/docs/debezium-mysql-component.adoc @@ -45,9 +45,9 @@ for this component. == URI format ---------------------------- +---- debezium-mysql:name[?options] ---------------------------- +---- [NOTE] ==== diff --git a/components/camel-debezium/camel-debezium-oracle/src/main/docs/debezium-oracle-component.adoc b/components/camel-debezium/camel-debezium-oracle/src/main/docs/debezium-oracle-component.adoc index 12aa007901141..e2bc6227c168b 100644 --- a/components/camel-debezium/camel-debezium-oracle/src/main/docs/debezium-oracle-component.adoc +++ b/components/camel-debezium/camel-debezium-oracle/src/main/docs/debezium-oracle-component.adoc @@ -45,9 +45,9 @@ Maven users will need to add the following dependency to their `pom.xml` for thi == URI format ---------------------------- +---- debezium-oracle:name[?options] ---------------------------- +---- // component options: START diff --git a/components/camel-debezium/camel-debezium-postgres/src/main/docs/debezium-postgres-component.adoc b/components/camel-debezium/camel-debezium-postgres/src/main/docs/debezium-postgres-component.adoc index 2bc1d50858093..9d0044bfc7aba 100644 --- a/components/camel-debezium/camel-debezium-postgres/src/main/docs/debezium-postgres-component.adoc +++ b/components/camel-debezium/camel-debezium-postgres/src/main/docs/debezium-postgres-component.adoc @@ -45,9 +45,9 @@ Maven users will need to add the following dependency to their `pom.xml` for thi == URI format ---------------------------- +---- debezium-postgres:name[?options] ---------------------------- +---- // component options: START diff --git a/components/camel-debezium/camel-debezium-sqlserver/src/main/docs/debezium-sqlserver-component.adoc b/components/camel-debezium/camel-debezium-sqlserver/src/main/docs/debezium-sqlserver-component.adoc index 93881f673cfb9..5e9337ba183da 100644 --- a/components/camel-debezium/camel-debezium-sqlserver/src/main/docs/debezium-sqlserver-component.adoc +++ b/components/camel-debezium/camel-debezium-sqlserver/src/main/docs/debezium-sqlserver-component.adoc @@ -45,9 +45,9 @@ for this component. == URI format ---------------------------- +---- debezium-sqlserver:name[?options] ---------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] diff --git a/components/camel-disruptor/src/main/docs/disruptor-component.adoc b/components/camel-disruptor/src/main/docs/disruptor-component.adoc index 2e12a1ee25c59..accd87cef9cb4 100644 --- a/components/camel-disruptor/src/main/docs/disruptor-component.adoc +++ b/components/camel-disruptor/src/main/docs/disruptor-component.adoc @@ -55,20 +55,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-disruptor x.x.x ------------------------------------------------------------- +---- == URI format ------------------------------ +---- disruptor:someId[?options] ------------------------------ +---- Where _someId_ can be any string that uniquely identifies the endpoint within the current CamelContext. @@ -181,9 +181,9 @@ thread pools, you can use: ._Java-only: concurrent consumers example (incomplete route)_ [source,java] --------------------------------------------------------------- +---- from("disruptor:stageName?concurrentConsumers=5").process(...) --------------------------------------------------------------- +---- As for the difference between the two, note that a thread pool can increase/shrink dynamically at runtime depending on load. Whereas the @@ -197,9 +197,9 @@ something like: ._Java-only: incomplete route (thread pool example)_ [source,java] --------------------------------------------------- +---- from("disruptor:stageName").thread(5).process(...) --------------------------------------------------- +---- Can wind up with adding a normal http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html[BlockingQueue] @@ -220,7 +220,7 @@ to the original caller. ._Java-only: Java RouteBuilder with multiple routes_ [source,java] -------------------------------------------------- +---- public void configure() { from("direct:start") // send it to the disruptor that is async @@ -230,16 +230,16 @@ public void configure() { from("disruptor:next").to("mock:result"); } -------------------------------------------------- +---- Here we send a _Hello World_ message and expect the reply to be _OK_. ._Java-only: Java test API (ProducerTemplate)_ [source,java] ------------------------------------------------------------------ +---- Object out = template.requestBody("direct:start", "Hello World"); assertEquals("OK", out); ------------------------------------------------------------------ +---- The "Hello World" message will be consumed from the Disruptor from another thread for further processing. Since this is from a unit test, @@ -252,7 +252,7 @@ In this example, we have defined two consumers and registered them as spring beans. [source,xml] -------------------------------------------------------------------------------------------- +---- @@ -262,7 +262,7 @@ spring beans. -------------------------------------------------------------------------------------------- +---- Since we have specified multipleConsumers=true on the Disruptor foo endpoint, we can have those two or more consumers receive their own copy @@ -272,7 +272,7 @@ but notice how we can use _@Consume_ to consume from the Disruptor. ._Java-only: Java annotation-based consumer class_ [source,java] -------------------------------------------- +---- public class FooEventConsumer { @EndpointInject("mock:result") @@ -284,7 +284,7 @@ public class FooEventConsumer { } } -------------------------------------------- +---- === Extracting disruptor information @@ -293,10 +293,10 @@ using JMX in this fashion: ._Java-only: Java endpoint API_ [source,java] --------------------------------------------------------------------- +---- DisruptorEndpoint disruptor = context.getEndpoint("disruptor:xxxx"); int size = disruptor.getBufferSize(); --------------------------------------------------------------------- +---- // shared with disruptor-vm diff --git a/components/camel-ehcache/src/main/docs/ehcache-component.adoc b/components/camel-ehcache/src/main/docs/ehcache-component.adoc index c229772bddccb..d61d5ae5e4e41 100644 --- a/components/camel-ehcache/src/main/docs/ehcache-component.adoc +++ b/components/camel-ehcache/src/main/docs/ehcache-component.adoc @@ -24,20 +24,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-ehcache x.x.x ------------------------------------------------------------- +---- == URI format ------------------------------ +---- ehcache://cacheName[?options] ------------------------------ +---- // component options: START include::partial$component-configure-options.adoc[] @@ -51,14 +51,14 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: programmatic CacheManager and idempotent repository configuration_ [source,java] ------------------------------------------------------------------------------------------------- +---- CacheManager manager = CacheManagerBuilder.newCacheManager(new XmlConfiguration("ehcache.xml")); EhcacheIdempotentRepository repo = new EhcacheIdempotentRepository(manager, "idempotent-cache"); from("direct:in") .idempotentConsumer(header("messageId"), idempotentRepo) .to("mock:out"); ------------------------------------------------------------------------------------------------- +---- @@ -66,7 +66,7 @@ from("direct:in") ._Java-only: full test class with aggregation repository configuration_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------- +---- public class EhcacheAggregationRepositoryRoutesTest extends CamelTestSupport { private static final String ENDPOINT_MOCK = "mock:result"; private static final String ENDPOINT_DIRECT = "direct:one"; @@ -134,7 +134,7 @@ public class EhcacheAggregationRepositoryRoutesTest extends CamelTestSupport { return repository; } } ---------------------------------------------------------------------------------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-exec/src/main/docs/exec-component.adoc b/components/camel-exec/src/main/docs/exec-component.adoc index bbc66ac73ff0c..7c851c4a77b21 100644 --- a/components/camel-exec/src/main/docs/exec-component.adoc +++ b/components/camel-exec/src/main/docs/exec-component.adoc @@ -22,21 +22,21 @@ The Exec component can be used to execute system commands. Maven users need to add the following dependency to their `pom.xml` [source,xml] -------------------------------------- +---- org.apache.camel camel-exec ${camel-version} -------------------------------------- +---- Where `${camel-version`} must be replaced by the actual version of Camel. == URI format ---------------------------- +---- exec://executable[?options] ---------------------------- +---- Where `executable` is the name, or file path, of the system command that will be executed. If executable name is used (e.g. `exec:java`), the @@ -93,7 +93,7 @@ the standard output stream of `wc`: ._Java-only: route with inline Processor to handle ExecResult_ [source,java] --------------------------------------------------------------------------------------- +---- from("direct:exec") .to("exec:wc?args=--words /usr/share/dict/words") .process(new Processor() { @@ -106,7 +106,7 @@ from("direct:exec") // do something with the word count } }); --------------------------------------------------------------------------------------- +---- === Executing `java` @@ -237,7 +237,7 @@ assumes that `ant.bat` is in the system path, and that ._Java-only: route with inline Processor to handle output file_ [source,java] -------------------------------------------------------------------------------------------------------- +---- from("direct:exec") .to("exec:ant.bat?args=-f CamelExecBuildFile.xml -l CamelExecOutFile.txt&outFile=CamelExecOutFile.txt") .process(new Processor() { @@ -247,7 +247,7 @@ from("direct:exec") // do something with the out file here } }); -------------------------------------------------------------------------------------------------------- +---- === Executing `echo` (Windows) diff --git a/components/camel-file/src/main/docs/file-component.adoc b/components/camel-file/src/main/docs/file-component.adoc index 4de277efdac76..415fcc325482b 100644 --- a/components/camel-file/src/main/docs/file-component.adoc +++ b/components/camel-file/src/main/docs/file-component.adoc @@ -566,10 +566,10 @@ YAML:: And the logs: ----------------------------------------------------------------------------------------------------------------------------------------------- +---- DEBUG GenericFileConverter - Read file /Users/davsclaus/workspace/camel/camel-core/target/charset/input/input.txt with charset utf-8 DEBUG FileOperations - Using Reader to write file: target/charset/output.txt with charset: iso-8859-1 ----------------------------------------------------------------------------------------------------------------------------------------------- +---- === Common gotchas with folder and filenames diff --git a/components/camel-flatpack/src/main/docs/flatpack-component.adoc b/components/camel-flatpack/src/main/docs/flatpack-component.adoc index ae4792946d592..999533232fa41 100644 --- a/components/camel-flatpack/src/main/docs/flatpack-component.adoc +++ b/components/camel-flatpack/src/main/docs/flatpack-component.adoc @@ -23,15 +23,15 @@ format. == URI format ---------------------------------------------------------- +---- flatpack:[delim|fixed]:flatPackConfig.pzmap.xml[?options] ---------------------------------------------------------- +---- Or for a delimited file handler with no configuration file just use ---------------------------- +---- flatpack:someName[?options] ---------------------------- +---- // component options: START @@ -65,21 +65,21 @@ For example, to get the firstname from the sample below: ._Java-only: accessing row data from the exchange body_ [source,java] ------------------------------------------------- +---- Map row = exchange.getIn().getBody(Map.class); String firstName = row.get("FIRSTNAME"); ------------------------------------------------- +---- However, you can also always get it as a `List` (even for `splitRows=true`). The same example: ._Java-only: accessing row data as a List from the exchange body_ [source,java] ---------------------------------------------------- +---- List data = exchange.getIn().getBody(List.class); Map row = (Map)data.get(0); String firstName = row.get("FIRSTNAME"); ---------------------------------------------------- +---- === Header and Trailer records @@ -93,7 +93,7 @@ The example below illustrates this fact that we have a header and a trailer. You can omit one or both of them if not needed. [source,xml] ---------------------------------------------------------------------------- +---- @@ -110,7 +110,7 @@ trailer. You can omit one or both of them if not needed. ---------------------------------------------------------------------------- +---- === Using as an Endpoint @@ -118,7 +118,7 @@ A common use case is sending a file to this endpoint for further processing in a separate route. For example: [source,xml] ------------------------------------------------------------------------ +---- @@ -130,7 +130,7 @@ processing in a separate route. For example: ... ------------------------------------------------------------------------ +---- You can also convert the payload of each message created to a `Map` for easy Bean Integration @@ -189,12 +189,12 @@ marshal or unmarshal operation in the route builder: ._Java-only: programmatic FlatpackDataFormat configuration and unmarshal_ [source,java] ---------------------------------------------------------------------------- +---- FlatpackDataFormat fp = new FlatpackDataFormat(); fp.setDefinition(new ClassPathResource("INVENTORY-Delimited.pzmap.xml")); ... from("file:order/in").unmarshal(df).to("seda:queue:neworder"); ---------------------------------------------------------------------------- +---- The sample above will read files from the `order/in` folder and unmarshal the input using the Flatpack configuration file @@ -203,14 +203,14 @@ files. The result is a `DataSetList` object we store on the SEDA queue. ._Java-only: programmatic FlatpackDataFormat configuration and marshal_ [source,java] ------------------------------------------------------------------------------------ +---- FlatpackDataFormat df = new FlatpackDataFormat(); df.setDefinition(new ClassPathResource("PEOPLE-FixedLength.pzmap.xml")); df.setFixed(true); df.setIgnoreFirstRecord(false); from("seda:people").marshal(df).convertBodyTo(String.class).to("jms:queue:people"); ------------------------------------------------------------------------------------ +---- In the code above we marshal the data from an Object representation as a `List` of rows as `Maps`. The rows as `Map` contains the column name as @@ -228,13 +228,13 @@ If you use maven, you could add the following to your `pom.xml`, substituting the version number for the latest release. [source,xml] ------------------------------------------ +---- org.apache.camel camel-flatpack x.x.x ------------------------------------------ +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-flatpack/src/main/docs/flatpack-dataformat.adoc b/components/camel-flatpack/src/main/docs/flatpack-dataformat.adoc index 086ca54a4ca8d..b8f57e21da8c5 100644 --- a/components/camel-flatpack/src/main/docs/flatpack-dataformat.adoc +++ b/components/camel-flatpack/src/main/docs/flatpack-dataformat.adoc @@ -40,12 +40,12 @@ marshal or unmarshal operation in the route builder: ._Java-only: programmatic FlatpackDataFormat configuration and unmarshal_ [source,java] ---------------------------------------------------------------------------- +---- FlatpackDataFormat fp = new FlatpackDataFormat(); fp.setDefinition(new ClassPathResource("INVENTORY-Delimited.pzmap.xml")); ... from("file:order/in").unmarshal(df).to("seda:queue:neworder"); ---------------------------------------------------------------------------- +---- The sample above will read files from the `order/in` folder and unmarshal the input using the Flatpack configuration file @@ -54,14 +54,14 @@ files. The result is a `DataSetList` object we store on the SEDA queue. ._Java-only: programmatic FlatpackDataFormat configuration and marshal_ [source,java] ------------------------------------------------------------------------------------ +---- FlatpackDataFormat df = new FlatpackDataFormat(); df.setDefinition(new ClassPathResource("PEOPLE-FixedLength.pzmap.xml")); df.setFixed(true); df.setIgnoreFirstRecord(false); from("seda:people").marshal(df).convertBodyTo(String.class).to("jms:queue:people"); ------------------------------------------------------------------------------------ +---- In the code above we marshal the data from an Object representation as a `List` of rows as `Maps`. The rows as `Map` contains the column name as @@ -79,13 +79,13 @@ If you use maven, you could add the following to your `pom.xml`, substituting the version number for the latest release. [source,xml] ------------------------------------------ +---- org.apache.camel camel-flatpack x.x.x ------------------------------------------ +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-flink/src/main/docs/flink-component.adoc b/components/camel-flink/src/main/docs/flink-component.adoc index 90d08646a0664..c98e62ab220fe 100644 --- a/components/camel-flink/src/main/docs/flink-component.adoc +++ b/components/camel-flink/src/main/docs/flink-component.adoc @@ -26,23 +26,23 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-flink x.x.x ------------------------------------------------------------- +---- == URI Format Currently, the Flink Component supports only Producers. One can create DataSet, DataStream jobs. -------------------------------------------------- +---- flink:dataset?dataset=#myDataSet&dataSetCallback=#dataSetCallback flink:datastream?datastream=#myDataStream&dataStreamCallback=#dataStreamCallback -------------------------------------------------- +---- IMPORTANT: The DataSet API has been deprecated by Apache Flink since version 1.12. It is recommended to migrate to the DataStream API with bounded streams for batch processing. diff --git a/components/camel-freemarker/src/main/docs/freemarker-component.adoc b/components/camel-freemarker/src/main/docs/freemarker-component.adoc index 1f8d19ea5e971..cc0473d12113d 100644 --- a/components/camel-freemarker/src/main/docs/freemarker-component.adoc +++ b/components/camel-freemarker/src/main/docs/freemarker-component.adoc @@ -23,19 +23,19 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] -------------------------------------------------------------------------------------- +---- org.apache.camel camel-freemarker x.x.x -------------------------------------------------------------------------------------- +---- == URI format ---------------------------------- +---- freemarker:templateName[?options] ---------------------------------- +---- Where *templateName* is the classpath-local URI of the template to invoke; or the complete URL of the remote template (e.g.: @@ -56,9 +56,9 @@ component to return values to the Message. For example, set the header value of `fruit` in the FreeMarker template: --------------------------------------- +---- ${request.setHeader('fruit', 'Apple')} --------------------------------------- +---- The header, `fruit`, is now accessible from the `message.out.headers`. @@ -95,13 +95,13 @@ message header with the key "*CamelFreemarkerDataModel*" just like this ._Java-only: setting a custom FreeMarker data model via headers_ [source,java] --------------------------------------------------------------------- +---- Map variableMap = new HashMap(); variableMap.put("headers", headersMap); variableMap.put("body", "Monday"); variableMap.put("exchange", exchange); exchange.getIn().setHeader("CamelFreemarkerDataModel", variableMap); --------------------------------------------------------------------- +---- === Hot reloading @@ -332,14 +332,14 @@ YAML:: In this sample, we want to use FreeMarker templating for an order confirmation email. The email template is laid out in FreeMarker as: ----------------------------------------------- +---- Dear ${headers.lastName}, ${headers.firstName} Thanks for the order of ${headers.item}. Regards Camel Riders Bookstore ${body} ----------------------------------------------- +---- diff --git a/components/camel-ftp/src/main/docs/sftp-component.adoc b/components/camel-ftp/src/main/docs/sftp-component.adoc index 74ad967b1f3c5..32dd424fad36e 100644 --- a/components/camel-ftp/src/main/docs/sftp-component.adoc +++ b/components/camel-ftp/src/main/docs/sftp-component.adoc @@ -20,14 +20,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------------------ +---- org.apache.camel camel-ftp x.x.x ------------------------------------------------------------------------ +---- // component options: START include::partial$component-configure-options.adoc[] diff --git a/components/camel-geocoder/src/main/docs/geocoder-component.adoc b/components/camel-geocoder/src/main/docs/geocoder-component.adoc index 6286e5846bbd7..dcd0c09cd5a72 100644 --- a/components/camel-geocoder/src/main/docs/geocoder-component.adoc +++ b/components/camel-geocoder/src/main/docs/geocoder-component.adoc @@ -24,21 +24,21 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-geocoder x.x.x ------------------------------------------------------------- +---- == URI format --------------------------------------------- +---- geocoder:address:name[?options] geocoder:latlng:latitude,longitude[?options] --------------------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -113,9 +113,9 @@ Copenhagen, Denmark we can send a message with a headers as shown: ._Java-only: overriding the address via a message header_ [source,java] ------------------------------------------------------------------------------------------------------- +---- template.sendBodyAndHeader("direct:start", "Hello", GeoCoderConstants.ADDRESS, "Copenhagen, Denmark"); ------------------------------------------------------------------------------------------------------- +---- To get the address for a latitude and longitude we can do: @@ -158,9 +158,9 @@ YAML:: Which will log --------------------------------------------------------------------------------------------------------------- +---- Location 285 Bedford Avenue, Brooklyn, NY 11211, USA is at lat/lng: 40.71412890,-73.96140740 and in country US --------------------------------------------------------------------------------------------------------------- +---- To get the current location using the Google GeoCoder, you can use "current" as the address as shown: diff --git a/components/camel-git/src/main/docs/git-component.adoc b/components/camel-git/src/main/docs/git-component.adoc index 25e575099b7e1..4dcaf1731ceac 100644 --- a/components/camel-git/src/main/docs/git-component.adoc +++ b/components/camel-git/src/main/docs/git-component.adoc @@ -17,20 +17,20 @@ The Git component allows you to work with a generic Git repository. [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-git x.x.x ------------------------------------------------------------- +---- *URI Format* ------------------------------------ +---- git://localRepositoryPath[?options] ------------------------------------ +---- == URI Options @@ -55,7 +55,7 @@ then pushes it to remote repository. ._Java-only: setting headers with GitConstants and chaining multiple git operations_ [source,java] --------------------------------------------------------------------------------------------------------------------- +---- from("direct:start") .setHeader(GitConstants.GIT_FILE_NAME, constant("test.java")) .to("git:///tmp/testRepo?operation=add") @@ -64,7 +64,7 @@ from("direct:start") .to("git:///tmp/testRepo?operation=push&remotePath=https://foo.com/test/test.git&username=xxx&password=xxx") .to("git:///tmp/testRepo?operation=createTag&tagName=myTag") .to("git:///tmp/testRepo?operation=pushTag&tagName=myTag&remoteName=origin"); --------------------------------------------------------------------------------------------------------------------- +---- === Consumer Example @@ -75,10 +75,10 @@ Below is an example route of a consumer that consumes commit: Java:: + [source,java] ---------------------------------------- +---- from("git:///tmp/testRepo?type=commit") .to("mock:result"); ---------------------------------------- +---- XML:: + @@ -155,7 +155,7 @@ You can override this by providing your own ``.gitconfig`` file. ._Java-only: configuring custom gitConfigFile with different resource schemes_ [source,java] ---------------------------------------- +---- from("git:///tmp/testRepo?type=commit&gitConfigFile=file:/tmp/configfile") .to(....); // will load from os dirs @@ -164,6 +164,6 @@ from("git:///tmp/testRepo?type=commit&gitConfigFile=classpath:configfile") from("git:///tmp/testRepo?type=commit&gitConfigFile=http://somedomain.xyz/gitconfigfile") .to(....); // will load from http. You could also use https ---------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-github2/src/main/docs/github2-component.adoc b/components/camel-github2/src/main/docs/github2-component.adoc index c6773159f9252..e665f0898a9c8 100644 --- a/components/camel-github2/src/main/docs/github2-component.adoc +++ b/components/camel-github2/src/main/docs/github2-component.adoc @@ -38,19 +38,19 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ------------------------------------------ +---- org.apache.camel camel-github2 ${camel-version} ------------------------------------------ +---- == URI format ---------------------------- +---- github2://endpoint[?options] ---------------------------- +---- // component-configure options: START diff --git a/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-component.adoc b/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-component.adoc index dfb099b3b174a..c8a9f2a0226ee 100644 --- a/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-component.adoc +++ b/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-component.adoc @@ -27,7 +27,7 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ------------------------------------------------------- +---- org.apache.camel camel-google-bigquery @@ -35,7 +35,7 @@ for this component: x.x.x ------------------------------------------------------- +---- [[GoogleBigQuery-AuthenticationConfiguration]] @@ -54,29 +54,29 @@ Google security credentials can be set through the component endpoint: ._Java-only: constructing the endpoint URI as a Java string_ [source,java] --------------------------------------------------------- +---- String endpoint = "google-bigquery://project-id:datasetId[:tableId]?serviceAccountKey=/home/user/Downloads/my-key.json"; --------------------------------------------------------- +---- You can also use the base64 encoded content of the authentication credentials file if you don't want to set a file system path. ._Java-only: constructing the endpoint URI with base64 credentials_ [source,java] --------------------------------------------------------- +---- String endpoint = "google-bigquery://project-id:datasetId[:tableId]?serviceAccountKey=base64:"; --------------------------------------------------------- +---- Or by setting the environment variable `GOOGLE_APPLICATION_CREDENTIALS` : --------------------------------------------------------- +---- export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json" --------------------------------------------------------- +---- == URI Format --------------------------------------------------------- +---- google-bigquery://project-id:datasetId[:tableId]?[options] --------------------------------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -108,11 +108,11 @@ I.e. the following route will create tables and insert records sharded on a per- ._Java-only: uses GoogleBigQueryConstants to set the table suffix header_ [source,java] ------------------------------------------------------- +---- from("direct:start") .header(GoogleBigQueryConstants.TABLE_SUFFIX, "_${date:now:yyyyMMdd}") .to("google-bigquery:sampleDataset:sampleTable") ------------------------------------------------------- +---- Note it is recommended to use partitioning for this use case. === Partitioning diff --git a/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-sql-component.adoc b/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-sql-component.adoc index 15c7873f6f02f..042c39a36ea3d 100644 --- a/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-sql-component.adoc +++ b/components/camel-google/camel-google-bigquery/src/main/docs/google-bigquery-sql-component.adoc @@ -26,7 +26,7 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ------------------------------------------------------- +---- org.apache.camel camel-google-bigquery @@ -34,7 +34,7 @@ for this component: x.x.x ------------------------------------------------------- +---- [[GoogleBigQuery-AuthenticationConfiguration]] @@ -53,36 +53,36 @@ Google security credentials can be set through the component endpoint: ._Java-only: endpoint URI as Java string variable_ [source,java] --------------------------------------------------------- +---- String endpoint = "google-bigquery-sql://project-id:query?serviceAccountKey=/home/user/Downloads/my-key.json"; --------------------------------------------------------- +---- You can also use the base64 encoded content of the authentication credentials file if you don't want to set a file system path. ._Java-only: endpoint URI as Java string variable_ [source,java] --------------------------------------------------------- +---- String endpoint = "google-bigquery-sql://project-id:query?serviceAccountKey=base64:"; --------------------------------------------------------- +---- Or by setting the environment variable `GOOGLE_APPLICATION_CREDENTIALS` : --------------------------------------------------------- +---- export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json" --------------------------------------------------------- +---- == URI Format --------------------------------------------------------- +---- google-bigquery-sql://project-id:query?[options] --------------------------------------------------------- +---- Examples: --------------------------------------------------------- +---- google-bigquery-sql://project-17248459:delete * from test.table where id=@myId google-bigquery-sql://project-17248459:delete * from ${datasetId}.${tableId} where id=@myId --------------------------------------------------------- +---- where * parameters in form $\{name} are extracted from message headers and formed the translated query. @@ -90,9 +90,9 @@ where You can externalize your SQL queries to files in the classpath or file system as shown: --------------------------------------------------------- +---- google-bigquery-sql://project-17248459::classpath:delete.sql --------------------------------------------------------- +---- // component options: START diff --git a/components/camel-google/camel-google-firestore/src/main/docs/google-firestore-component.adoc b/components/camel-google/camel-google-firestore/src/main/docs/google-firestore-component.adoc index 4af72ee8ea77a..39c4f7c542b09 100644 --- a/components/camel-google/camel-google-firestore/src/main/docs/google-firestore-component.adoc +++ b/components/camel-google/camel-google-firestore/src/main/docs/google-firestore-component.adoc @@ -24,14 +24,14 @@ It keeps your data in sync across client apps through realtime listeners and off Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ------------------------------------------------------- +---- org.apache.camel camel-google-firestore x.x.x ------------------------------------------------------- +---- [[GoogleFirestore-AuthenticationConfiguration]] @@ -44,24 +44,24 @@ When you have the **service account key**, you can provide authentication creden Google security credentials can be set through the component endpoint: [source,java] --------------------------------------------------------- +---- String endpoint = "google-firestore://myCollection?serviceAccountKey=/home/user/Downloads/my-key.json&projectId=my-project"; --------------------------------------------------------- +---- Or by providing the path to the GCP credentials file location: Provide authentication credentials to your application code by setting the environment variable `GOOGLE_APPLICATION_CREDENTIALS`: --------------------------------------------------------- +---- export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json" --------------------------------------------------------- +---- == URI Format --------------------------------------------------------- +---- google-firestore://collectionName?[options] --------------------------------------------------------- +---- You can append query options to the URI in the following format: `?options=value&option2=value&...` @@ -951,7 +951,7 @@ For write operations (`setDocument`, `createDocument`, `updateDocument`), the co You can send a JSON string directly as the message body. The component will automatically parse it: [source,java] --------------------------------------------------------------------------------- +---- // Simple JSON from("direct:start") .setBody(constant("{\"name\": \"John\", \"age\": 30}")) @@ -977,28 +977,28 @@ String json = """ from("direct:start") .setBody(constant(json)) .to("google-firestore://users?operation=createDocument"); --------------------------------------------------------------------------------- +---- ==== Reading JSON from Files [source,java] --------------------------------------------------------------------------------- +---- // Read JSON files and store in Firestore from("file:data/users?noop=true&include=.*\\.json") .setHeader("CamelGoogleFirestoreDocumentId", simple("${file:name.noext}")) .to("google-firestore://users?operation=setDocument") .log("Imported: ${file:name}"); --------------------------------------------------------------------------------- +---- ==== REST API Integration [source,java] --------------------------------------------------------------------------------- +---- // Receive JSON from REST endpoint and store in Firestore from("rest:post:/api/users") .to("google-firestore://users?operation=createDocument") .setBody(simple("{\"id\": \"${header.CamelGoogleFirestoreResponseDocumentId}\"}")); --------------------------------------------------------------------------------- +---- === Supported Firestore Data Types @@ -1058,10 +1058,10 @@ For `listCollections`, the response body is: If the input body cannot be converted to a Map (e.g., invalid JSON), an `InvalidPayloadException` is thrown: [source,text] --------------------------------------------------------------------------------- +---- org.apache.camel.InvalidPayloadException: No body available of type: java.util.Map ...Caused by: Unexpected character ('x' (code 120)): was expecting... --------------------------------------------------------------------------------- +---- == Message Headers diff --git a/components/camel-google/camel-google-functions/src/main/docs/google-functions-component.adoc b/components/camel-google/camel-google-functions/src/main/docs/google-functions-component.adoc index 4c07401cb24c1..c9c5cb5f9dc7b 100644 --- a/components/camel-google/camel-google-functions/src/main/docs/google-functions-component.adoc +++ b/components/camel-google/camel-google-functions/src/main/docs/google-functions-component.adoc @@ -22,7 +22,7 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ------------------------------------------------------- +---- org.apache.camel camel-google-functions @@ -30,7 +30,7 @@ for this component: x.x.x ------------------------------------------------------- +---- [[GoogleFunctions-AuthenticationConfiguration]] @@ -43,22 +43,22 @@ When you have the **service account key**, you can provide authentication creden Google security credentials can be set through the component endpoint: [source,java] --------------------------------------------------------- +---- String endpoint = "google-functions://myCamelFunction?serviceAccountKey=/home/user/Downloads/my-key.json"; --------------------------------------------------------- +---- Or by setting the environment variable `GOOGLE_APPLICATION_CREDENTIALS` : --------------------------------------------------------- +---- export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json" --------------------------------------------------------- +---- == URI Format --------------------------------------------------------- +---- google-functions://functionName[?options] --------------------------------------------------------- +---- You can append query options to the URI in the following format, `?options=value&option2=value&...` diff --git a/components/camel-google/camel-google-pubsub/src/main/docs/google-pubsub-component.adoc b/components/camel-google/camel-google-pubsub/src/main/docs/google-pubsub-component.adoc index 6baad5b9b1f70..c366706547b7f 100644 --- a/components/camel-google/camel-google-pubsub/src/main/docs/google-pubsub-component.adoc +++ b/components/camel-google/camel-google-pubsub/src/main/docs/google-pubsub-component.adoc @@ -23,14 +23,14 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ------------------------------------------------------- +---- org.apache.camel camel-google-pubsub x.x.x ------------------------------------------------------- +---- == URI Format diff --git a/components/camel-google/camel-google-secret-manager/src/main/docs/google-secret-manager-component.adoc b/components/camel-google/camel-google-secret-manager/src/main/docs/google-secret-manager-component.adoc index f753095b923c7..dbacf480eb786 100644 --- a/components/camel-google/camel-google-secret-manager/src/main/docs/google-secret-manager-component.adoc +++ b/components/camel-google/camel-google-secret-manager/src/main/docs/google-secret-manager-component.adoc @@ -21,7 +21,7 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ------------------------------------------------------- +---- org.apache.camel camel-google-secret-manager @@ -29,7 +29,7 @@ for this component: x.x.x ------------------------------------------------------- +---- [[GoogleSecretManager-AuthenticationConfiguration]] @@ -43,22 +43,22 @@ Google security credentials can be set through the component endpoint: ._Java-only: setting the endpoint URI with service account key_ [source,java] --------------------------------------------------------- +---- String endpoint = "google-secret-manager://myCamelFunction?serviceAccountKey=/home/user/Downloads/my-key.json"; --------------------------------------------------------- +---- Or by setting the environment variable `GOOGLE_APPLICATION_CREDENTIALS` : --------------------------------------------------------- +---- export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json" --------------------------------------------------------- +---- == URI Format --------------------------------------------------------- +---- google-secret-manager://functionName[?options] --------------------------------------------------------- +---- You can append query options to the URI in the following format, `?options=value&option2=value&...` diff --git a/components/camel-google/camel-google-speech-to-text/src/main/docs/google-speech-to-text-component.adoc b/components/camel-google/camel-google-speech-to-text/src/main/docs/google-speech-to-text-component.adoc index 400e5f1581e2d..a42ce8b8ac2c5 100644 --- a/components/camel-google/camel-google-speech-to-text/src/main/docs/google-speech-to-text-component.adoc +++ b/components/camel-google/camel-google-speech-to-text/src/main/docs/google-speech-to-text-component.adoc @@ -22,14 +22,14 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ------------------------------------------------------- +---- org.apache.camel camel-google-speech-to-text x.x.x ------------------------------------------------------- +---- [[GoogleSpeechToText-AuthenticationConfiguration]] @@ -42,22 +42,22 @@ When you have the **service account key**, you can provide authentication creden Google security credentials can be set through the component endpoint: [source,java] --------------------------------------------------------- +---- String endpoint = "google-speech-to-text://recognize?serviceAccountKey=/home/user/Downloads/my-key.json"; --------------------------------------------------------- +---- Or by setting the environment variable `GOOGLE_APPLICATION_CREDENTIALS` : --------------------------------------------------------- +---- export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json" --------------------------------------------------------- +---- == URI Format --------------------------------------------------------- +---- google-speech-to-text://operation[?options] --------------------------------------------------------- +---- You can append query options to the URI in the following format, `?options=value&option2=value&...` diff --git a/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc b/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc index 66b1038c6f572..dd0e96351cd48 100644 --- a/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc +++ b/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc @@ -22,14 +22,14 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ------------------------------------------------------- +---- org.apache.camel camel-google-storage x.x.x ------------------------------------------------------- +---- [[GoogleStorage-AuthenticationConfiguration]] @@ -42,24 +42,24 @@ When you have the **service account key**, you can provide authentication creden Google security credentials can be set through the component endpoint: [source,java] --------------------------------------------------------- +---- String endpoint = "google-storage://myCamelBucket?serviceAccountKey=/home/user/Downloads/my-key.json"; --------------------------------------------------------- +---- Or by providing the path to the GCP credentials file location: Provide authentication credentials to your application code by setting the environment variable `GOOGLE_APPLICATION_CREDENTIALS` : --------------------------------------------------------- +---- export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json" --------------------------------------------------------- +---- == URI Format --------------------------------------------------------- +---- google-storage://bucketNameOrArn?[options] --------------------------------------------------------- +---- By default, the bucket will be created if it doesn't already exist. You can append query options to the URI in the following format: `?options=value&option2=value&...` diff --git a/components/camel-google/camel-google-text-to-speech/src/main/docs/google-text-to-speech-component.adoc b/components/camel-google/camel-google-text-to-speech/src/main/docs/google-text-to-speech-component.adoc index 2ff794b0a6130..cec136eb76d5b 100644 --- a/components/camel-google/camel-google-text-to-speech/src/main/docs/google-text-to-speech-component.adoc +++ b/components/camel-google/camel-google-text-to-speech/src/main/docs/google-text-to-speech-component.adoc @@ -22,14 +22,14 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ------------------------------------------------------- +---- org.apache.camel camel-google-text-to-speech x.x.x ------------------------------------------------------- +---- [[GoogleTextToSpeech-AuthenticationConfiguration]] @@ -42,22 +42,22 @@ When you have the **service account key**, you can provide authentication creden Google security credentials can be set through the component endpoint: [source,java] --------------------------------------------------------- +---- String endpoint = "google-text-to-speech://synthesize?serviceAccountKey=/home/user/Downloads/my-key.json"; --------------------------------------------------------- +---- Or by setting the environment variable `GOOGLE_APPLICATION_CREDENTIALS` : --------------------------------------------------------- +---- export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json" --------------------------------------------------------- +---- == URI Format --------------------------------------------------------- +---- google-text-to-speech://operation[?options] --------------------------------------------------------- +---- You can append query options to the URI in the following format, `?options=value&option2=value&...` diff --git a/components/camel-google/camel-google-vision/src/main/docs/google-vision-component.adoc b/components/camel-google/camel-google-vision/src/main/docs/google-vision-component.adoc index f94cec2785d34..8b4a167fb7629 100644 --- a/components/camel-google/camel-google-vision/src/main/docs/google-vision-component.adoc +++ b/components/camel-google/camel-google-vision/src/main/docs/google-vision-component.adoc @@ -22,14 +22,14 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ------------------------------------------------------- +---- org.apache.camel camel-google-vision x.x.x ------------------------------------------------------- +---- [[GoogleVision-AuthenticationConfiguration]] @@ -42,22 +42,22 @@ When you have the **service account key**, you can provide authentication creden Google security credentials can be set through the component endpoint: [source,java] --------------------------------------------------------- +---- String endpoint = "google-vision://labelDetection?serviceAccountKey=/home/user/Downloads/my-key.json"; --------------------------------------------------------- +---- Or by setting the environment variable `GOOGLE_APPLICATION_CREDENTIALS` : --------------------------------------------------------- +---- export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/my-key.json" --------------------------------------------------------- +---- == URI Format --------------------------------------------------------- +---- google-vision://operation[?options] --------------------------------------------------------- +---- You can append query options to the URI in the following format, `?options=value&option2=value&...` diff --git a/components/camel-graphql/src/main/docs/graphql-component.adoc b/components/camel-graphql/src/main/docs/graphql-component.adoc index bfd5d2752c04b..92742b7e508bf 100644 --- a/components/camel-graphql/src/main/docs/graphql-component.adoc +++ b/components/camel-graphql/src/main/docs/graphql-component.adoc @@ -20,14 +20,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-graphql x.x.x ------------------------------------------------------------- +---- // component options: START diff --git a/components/camel-groovy/src/main/docs/groovy-language.adoc b/components/camel-groovy/src/main/docs/groovy-language.adoc index 5b0ed13e83d27..c28f71f4c1aac 100644 --- a/components/camel-groovy/src/main/docs/groovy-language.adoc +++ b/components/camel-groovy/src/main/docs/groovy-language.adoc @@ -19,9 +19,9 @@ Filter] EIP. ._Java-only: creating a Groovy expression_ [source,java] ---------------------------------------- +---- groovy("someGroovyExpression") ---------------------------------------- +---- == Groovy Options @@ -73,12 +73,12 @@ statements scripts, you need to make sure you set the value of result variable as the script return value. [source,groovy] -------------------------------------------------------------- +---- bar = "baz" // some other statements ... // camel take the result value as the script evaluation result result = body * 2 + 1 -------------------------------------------------------------- +---- === Customizing Groovy Shell @@ -115,9 +115,9 @@ e.g., to refer to a file on the classpath you can do: ._Java-only: loading a Groovy script from an external resource_ [source,java] -------------------------------------------------------------------- +---- .setHeader("myHeader").groovy("resource:classpath:mygroovy.groovy") -------------------------------------------------------------------- +---- === Dependencies @@ -129,13 +129,13 @@ substituting the version number for the latest and greatest release (see the download page for the latest versions). [source,xml] ---------------------------------------- +---- org.apache.camel camel-groovy x.x.x ---------------------------------------- +---- == Examples @@ -148,11 +148,11 @@ to determine if any line items are over $100: Java:: + [source,java] ------------------------------------------------------------------------------------------------- +---- from("queue:foo") .filter(groovy("body.lineItems.any { i -> i.value > 100 }")) .to("queue:bar") ------------------------------------------------------------------------------------------------- +---- XML DSL:: + diff --git a/components/camel-grpc/src/main/docs/grpc-component.adoc b/components/camel-grpc/src/main/docs/grpc-component.adoc index 6c363e9c0c50f..7042363e08adc 100644 --- a/components/camel-grpc/src/main/docs/grpc-component.adoc +++ b/components/camel-grpc/src/main/docs/grpc-component.adoc @@ -22,20 +22,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-grpc x.x.x ------------------------------------------------------------- +---- == URI format -------------------------------------- +---- grpc:host:port/service[?options] -------------------------------------- +---- // component options: START @@ -534,7 +534,7 @@ The following steps are required: Insert operating system and CPU architecture detection extension inside **** tag of the project `pom.xml` or set `${os.detected.classifier}` parameter manually [source,xml] -------------------------------------------------------------------------- +---- kr.motd.maven @@ -542,12 +542,12 @@ Insert operating system and CPU architecture detection extension inside **1.7.1 -------------------------------------------------------------------------- +---- Insert the gRPC and protobuf Java code generator plugins into the **** tag of the project pom.xml [source,xml] -------------------------------------------------------------------------- +---- org.xolstice.maven.plugins protobuf-maven-plugin @@ -568,7 +568,7 @@ Insert the gRPC and protobuf Java code generator plugins into the **** -------------------------------------------------------------------------- +---- == More information diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-map-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-map-component.adoc index 7658013ac5906..b6cb45ca2aadb 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-map-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-map-component.adoc @@ -51,9 +51,9 @@ The map cache producer provides follow operations specified by *CamelHazelcastOp You can call the samples with: [source,java] -------------------------------------------------------------------------------------------------------------------- +---- template.sendBodyAndHeader("direct:[put|get|update|delete|query|evict]", "my-foo", HazelcastConstants.OBJECT_ID, "4711"); -------------------------------------------------------------------------------------------------------------------- +---- === Example for *put*: @@ -63,16 +63,16 @@ template.sendBodyAndHeader("direct:[put|get|update|delete|query|evict]", "my-foo Java DSL:: + [source,java] ------------------------------------------------------------------------------------- +---- from("direct:put") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.PUT)) .toF("hazelcast-%sfoo", HazelcastConstants.MAP_PREFIX); ------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -80,7 +80,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== @@ -93,18 +93,18 @@ Java DSL:: + [source,java] ------------------------------------------------------------------------------------- +---- from("direct:put") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.PUT)) .setHeader(HazelcastConstants.TTL_VALUE, constant(Long.valueOf(1))) .setHeader(HazelcastConstants.TTL_UNIT, constant(TimeUnit.MINUTES)) .toF("hazelcast-%sfoo", HazelcastConstants.MAP_PREFIX); ------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -118,7 +118,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== @@ -130,17 +130,17 @@ Spring XML:: Java DSL:: + [source,java] ------------------------------------------------------------------------------------- +---- from("direct:get") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.GET)) .toF("hazelcast-%sfoo", HazelcastConstants.MAP_PREFIX) .to("seda:out"); ------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -149,7 +149,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== @@ -161,16 +161,16 @@ Spring XML:: Java DSL:: + [source,java] ---------------------------------------------------------------------------------------- +---- from("direct:update") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.UPDATE)) .toF("hazelcast-%sfoo", HazelcastConstants.MAP_PREFIX); ---------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -178,7 +178,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== @@ -191,16 +191,16 @@ Java DSL:: + [source,java] ---------------------------------------------------------------------------------------- +---- from("direct:delete") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.DELETE)) .toF("hazelcast-%sfoo", HazelcastConstants.MAP_PREFIX); ---------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -208,7 +208,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== @@ -220,17 +220,17 @@ Spring XML:: Java DSL:: + [source,java] --------------------------------------------------------------------------------------- +---- from("direct:query") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.QUERY)) .toF("hazelcast-%sfoo", HazelcastConstants.MAP_PREFIX) .to("seda:out"); --------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -239,7 +239,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== @@ -247,10 +247,10 @@ For the query operation Hazelcast offers an SQL like syntax to query your distributed map. [source,java] -------------------------------------------------------------------------------- +---- String q1 = "bar > 1000"; template.sendBodyAndHeader("direct:query", null, HazelcastConstants.QUERY, q1); -------------------------------------------------------------------------------- +---- == Map cache consumer - from("hazelcast-map:foo") diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-multimap-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-multimap-component.adoc index 41944d4903e0c..52a1daf524985 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-multimap-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-multimap-component.adoc @@ -50,16 +50,16 @@ The multimap producer provides eight operations: Java DSL:: + [source,java] ------------------------------------------------------------------------------------- +---- from("direct:put") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.PUT)) .to(String.format("hazelcast-%sbar", HazelcastConstants.MULTIMAP_PREFIX)); ------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -68,7 +68,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== @@ -81,16 +81,16 @@ Java DSL:: + [source,java] --------------------------------------------------------------------------------------------- +---- from("direct:removevalue") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.REMOVE_VALUE)) .toF("hazelcast-%sbar", HazelcastConstants.MULTIMAP_PREFIX); --------------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -99,7 +99,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== @@ -116,17 +116,17 @@ inside the message body to remove the `my-foo` value. Java DSL:: + [source,java] ------------------------------------------------------------------------------------- +---- from("direct:get") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.GET)) .toF("hazelcast-%sbar", HazelcastConstants.MULTIMAP_PREFIX) .to("seda:out"); ------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -136,7 +136,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== @@ -148,16 +148,16 @@ Spring XML:: Java DSL:: + [source,java] ---------------------------------------------------------------------------------------- +---- from("direct:delete") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.DELETE)) .toF("hazelcast-%sbar", HazelcastConstants.MULTIMAP_PREFIX); ---------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -166,16 +166,16 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== You can call them in your test class with: [source,java] ------------------------------------------------------------------------------------------------------------------- +---- template.sendBodyAndHeader("direct:[put|get|removevalue|delete]", "my-foo", HazelcastConstants.OBJECT_ID, "4711"); ------------------------------------------------------------------------------------------------------------------- +---- == multimap cache consumer - from("hazelcast-multimap:foo") diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-replicatedmap-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-replicatedmap-component.adoc index b0f32dd6b904d..70736f3b62e82 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-replicatedmap-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-replicatedmap-component.adoc @@ -45,16 +45,16 @@ The replicatedmap producer provides 6 operations: Java DSL:: + [source,java] ------------------------------------------------------------------------------------- +---- from("direct:put") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.PUT)) .to(String.format("hazelcast-%sbar", HazelcastConstants.REPLICATEDMAP_PREFIX)); ------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -63,7 +63,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== @@ -75,17 +75,17 @@ Spring XML:: Java DSL:: + [source,java] ------------------------------------------------------------------------------------- +---- from("direct:get") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.GET)) .toF("hazelcast-%sbar", HazelcastConstants.REPLICATEDMAP_PREFIX) .to("seda:out"); ------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -95,7 +95,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== @@ -107,16 +107,16 @@ Spring XML:: Java DSL:: + [source,java] ---------------------------------------------------------------------------------------- +---- from("direct:delete") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.DELETE)) .toF("hazelcast-%sbar", HazelcastConstants.REPLICATEDMAP_PREFIX); ---------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -125,16 +125,16 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== You can call them in your test class with: ._Java-only: uses ProducerTemplate API and Java constants_ [source,java] ------------------------------------------------------------------------------------------------------------- +---- template.sendBodyAndHeader("direct:[put|get|delete|clear]", "my-foo", HazelcastConstants.OBJECT_ID, "4711"); ------------------------------------------------------------------------------------------------------------- +---- == replicatedmap cache consumer @@ -145,7 +145,7 @@ Here is a sample: ._Java-only: uses Java constants, string formatting, and choice/when/otherwise_ [source,java] --------------------------------------------------------------------------------------------------- +---- fromF("hazelcast-%sbar", HazelcastConstants.MULTIMAP_PREFIX) .log("object...") .choice() @@ -160,7 +160,7 @@ fromF("hazelcast-%sbar", HazelcastConstants.MULTIMAP_PREFIX) .to("mock:removed") .otherwise() .log("fail!"); --------------------------------------------------------------------------------------------------- +---- Header Variables inside the response message: diff --git a/components/camel-hazelcast/src/main/docs/hazelcast-ringbuffer-component.adoc b/components/camel-hazelcast/src/main/docs/hazelcast-ringbuffer-component.adoc index ea5feaec835d7..58e191553375c 100644 --- a/components/camel-hazelcast/src/main/docs/hazelcast-ringbuffer-component.adoc +++ b/components/camel-hazelcast/src/main/docs/hazelcast-ringbuffer-component.adoc @@ -44,16 +44,16 @@ The ringbuffer producer provides 5 operations: Java DSL:: + [source,java] ------------------------------------------------------------------------------------- +---- from("direct:put") .setHeader(HazelcastConstants.OPERATION, constant(HazelcastOperation.ADD)) .to(String.format("hazelcast-%sbar", HazelcastConstants.RINGBUFFER_PREFIX)); ------------------------------------------------------------------------------------- +---- Spring XML:: + [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -62,7 +62,7 @@ Spring XML:: ------------------------------------------------------------------------------------------------ +---- ==== diff --git a/components/camel-http/src/main/docs/http-component.adoc b/components/camel-http/src/main/docs/http-component.adoc index 26fa4c6229550..6418c26ccf4ab 100644 --- a/components/camel-http/src/main/docs/http-component.adoc +++ b/components/camel-http/src/main/docs/http-component.adoc @@ -22,20 +22,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-http x.x.x ------------------------------------------------------------- +---- == URI format ---------------------------------------------- +---- http:hostname[:port][/resourceUri][?options] ---------------------------------------------- +---- Will by default use port 80 for HTTP and 443 for HTTPS. @@ -422,22 +422,22 @@ only from the CamelContext or URI. + ._Java-only: programmatic `CamelContext` global options configuration (deprecated)_ [source,java] ---------------------------------------------------------------- +---- context.getGlobalOptions().put("http.proxyHost", "172.168.18.9"); context.getGlobalOptions().put("http.proxyPort", "8080"); ---------------------------------------------------------------- +---- Spring XML [source,xml] ----------------------------------------------------------------- +---- ----------------------------------------------------------------- +---- Camel will first set the settings from Java System or CamelContext Properties and then the endpoint proxy options if provided. @@ -455,9 +455,9 @@ using the `Exchange` property: ._Java-only: setting exchange property programmatically_ [source,java] ----------------------------------------------------------- +---- exchange.setProperty(Exchange.CHARSET_NAME, "ISO-8859-1"); ----------------------------------------------------------- +---- ==== Example with scheduled poll @@ -521,21 +521,21 @@ web browser. Camel does no tricks here. ._Java-only: uses `ProducerTemplate` test API_ [source,java] ------------------------------------------------------------------ +---- // we query for Camel at the Google page template.sendBody("http://www.google.com/search?q=Camel", null); ------------------------------------------------------------------ +---- ==== URI Parameters from the Message ._Java-only: uses `ProducerTemplate` test API with headers_ [source,java] ------------------------------------------------------------------- +---- Map headers = new HashMap(); headers.put(Exchange.HTTP_QUERY, "q=Camel&lr=lang_en"); // we query for Camel and English language at Google template.sendBody("http://www.google.com/search", null, headers); ------------------------------------------------------------------- +---- In the header value above notice that it should *not* be prefixed with `?` and you can separate parameters as usual with the `&` char. @@ -548,13 +548,13 @@ the value from the Out message header with ._Java-only: uses `ProducerTemplate` and `Processor` to inspect response code_ [source,java] ------------------------------------------------------------------------------------- +---- Exchange exchange = template.send("http://www.google.com/search", e -> { e.getIn().setHeader("CamelHttpQuery", "hl=en&q=activemq"); }); Message out = exchange.getMessage(); int responseCode = out.getHeader("CamelHttpResponseCode", Integer.class); ------------------------------------------------------------------------------------- +---- === Defining specific properties of Apache HTTP client via Camel parameters @@ -702,7 +702,7 @@ Programmatic configuration of the component ._Java-only: programmatic `SSLContextParameters` setup_ [source,java] ---------------------------------------------------------------------------------------- +---- KeyStoreParameters ksp = new KeyStoreParameters(); ksp.setResource("file:/users/home/server/keystore.jks"); ksp.setPassword("keystorePassword"); @@ -716,14 +716,14 @@ scp.setKeyManagers(kmp); HttpComponent httpComponent = getContext().getComponent("https", HttpComponent.class); httpComponent.setSslContextParameters(scp); ---------------------------------------------------------------------------------------- +---- [[HTTP-SpringDSLbasedconfigurationofendpoint]] Spring DSL based configuration of endpoint [source,xml] --------------------------------------------------------------------------------------- +---- --------------------------------------------------------------------------------------- +---- [[HTTP-ConfiguringApacheHTTPClientDirectly]] Configuring Apache HTTP Client Directly @@ -756,13 +756,13 @@ can do this with Apache HTTP `HttpClientConfigurer`, for example: ._Java-only: programmatic `KeyStore` and `SchemeRegistry` setup_ [source,java] ------------------------------------------------------------------------------------------------------- +---- KeyStore keystore = ...; KeyStore truststore = ...; SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("https", 443, new SSLSocketFactory(keystore, "mypassword", truststore))); ------------------------------------------------------------------------------------------------------- +---- And then you need to create a class that implements `HttpClientConfigurer`, and registers https protocol providing a @@ -771,22 +771,22 @@ builder class, you can hook it up like so: ._Java-only: programmatic `HttpClientConfigurer` setup_ [source,java] --------------------------------------------------------------------------------------- +---- HttpComponent httpComponent = getContext().getComponent("http", HttpComponent.class); httpComponent.setHttpClientConfigurer(new MyHttpClientConfigurer()); --------------------------------------------------------------------------------------- +---- If you are doing this using the Spring DSL, you can specify your `HttpClientConfigurer` using the URI. For example: [source,xml] ------------------------------------------------------------------------------------------ +---- ------------------------------------------------------------------------------------------ +---- As long as you implement the `HttpClientConfigurer` and configure your keystore and truststore as described above, it will work fine. @@ -802,7 +802,7 @@ The problem was eventually resolved by providing a custom configured ._Java-only: custom `HttpContext` factory for preemptive basic authentication_ [source,java] ------------------------------------------------------------------- +---- public class HttpContextFactory { private String httpHost = "localhost"; @@ -830,21 +830,21 @@ public class HttpContextFactory { // getter and setter } ------------------------------------------------------------------- +---- * 2. Declare an` HttpContext` in the Spring application context file: [source,xml] ---------------------------------------------------------------------------------------- +---- ---------------------------------------------------------------------------------------- +---- * 3. Reference the context in the http URL: [source,xml] ------------------------------------------------------------------------ +---- ------------------------------------------------------------------------ +---- [[HTTP-UsingdifferentSSLContextParameters]] Using different SSLContextParameters @@ -857,7 +857,7 @@ two components, each using their own instance of `sslContextParameters` property. [source,xml] ----------------------------------------------------------------------------- +---- @@ -867,7 +867,7 @@ property. ----------------------------------------------------------------------------- +---- == Removing http protocol headers in the Camel Message diff --git a/components/camel-huawei/camel-huaweicloud-smn/src/main/docs/hwcloud-smn-component.adoc b/components/camel-huawei/camel-huaweicloud-smn/src/main/docs/hwcloud-smn-component.adoc index c064517492297..22cae758fd428 100644 --- a/components/camel-huawei/camel-huaweicloud-smn/src/main/docs/hwcloud-smn-component.adoc +++ b/components/camel-huawei/camel-huaweicloud-smn/src/main/docs/hwcloud-smn-component.adoc @@ -21,22 +21,22 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-huaweicloud-smn x.x.x ------------------------------------------------------------- +---- == URI format To send a notification. ------------------------- +---- hwcloud-smn:service[?options] ------------------------- +---- // component options: START diff --git a/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc b/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc index 9c0be3c728833..1d285b9f30942 100644 --- a/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc +++ b/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc @@ -25,9 +25,9 @@ More information is available at https://www.ibm.com/cloud/object-storage[IBM Cl == URI Format ------------------------------- +---- ibm-cos://bucketName[?options] ------------------------------- +---- The bucket will be created if it doesn't already exist. @@ -989,14 +989,14 @@ Maven users will need to add the following dependency to their `pom.xml`. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-ibm-cos x.x.x ---------------------------------------- +---- where `x.x.x` is the version number of Camel. diff --git a/components/camel-ibm/camel-ibm-secrets-manager/src/main/docs/ibm-secrets-manager-component.adoc b/components/camel-ibm/camel-ibm-secrets-manager/src/main/docs/ibm-secrets-manager-component.adoc index 5cd5290dae22d..35b7f7fbb1cac 100644 --- a/components/camel-ibm/camel-ibm-secrets-manager/src/main/docs/ibm-secrets-manager-component.adoc +++ b/components/camel-ibm/camel-ibm-secrets-manager/src/main/docs/ibm-secrets-manager-component.adoc @@ -21,14 +21,14 @@ The ibm-secrets-manager component that integrates https://www.ibm.com/products/s == URI Format [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-ibm-secrets-manager x.x.x ------------------------------------------------------------- +---- // component options: START diff --git a/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/docs/ibm-watson-speech-to-text-component.adoc b/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/docs/ibm-watson-speech-to-text-component.adoc index c571de13be826..00112122f65db 100644 --- a/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/docs/ibm-watson-speech-to-text-component.adoc +++ b/components/camel-ibm/camel-ibm-watson-speech-to-text/src/main/docs/ibm-watson-speech-to-text-component.adoc @@ -25,9 +25,9 @@ More information is available at https://cloud.ibm.com/catalog/services/speech-t == URI Format ------------------------------- +---- ibm-watson-speech-to-text:label[?options] ------------------------------- +---- You can append query options to the URI in the following format: @@ -479,23 +479,23 @@ To get your credentials: Integration tests are executed with the `verify` goal and require system properties: [source,bash] --------------------------------------------------------------------------------- +---- mvn verify \ -Dcamel.ibm.watson.stt.apiKey=YOUR_API_KEY \ -Dcamel.ibm.watson.stt.serviceUrl=YOUR_SERVICE_URL --------------------------------------------------------------------------------- +---- Alternatively, using environment variables: [source,bash] --------------------------------------------------------------------------------- +---- export CAMEL_IBM_WATSON_STT_API_KEY=YOUR_API_KEY export CAMEL_IBM_WATSON_STT_SERVICE_URL=YOUR_SERVICE_URL mvn verify \ -Dcamel.ibm.watson.stt.apiKey=${CAMEL_IBM_WATSON_STT_API_KEY} \ -Dcamel.ibm.watson.stt.serviceUrl=${CAMEL_IBM_WATSON_STT_SERVICE_URL} --------------------------------------------------------------------------------- +---- === Integration Test Coverage @@ -564,7 +564,7 @@ These files can be reviewed to verify transcription accuracy and examine the det === Example Output [source] --------------------------------------------------------------------------------- +---- [INFO] Running org.apache.camel.component.ibm.watson.stt.integration.WatsonSpeechToTextIT Created input directory: target/audio-input Created output directory: target/transcription-output @@ -585,7 +585,7 @@ Created transcript file: transcript-file2.txt (size: 156 bytes) Created transcript file: transcript-file3.txt (size: 156 bytes) Successfully transcribed and saved 3 audio files [INFO] Tests run: 12, Failures: 0, Errors: 0, Skipped: 0 --------------------------------------------------------------------------------- +---- == Dependencies @@ -594,14 +594,14 @@ Maven users will need to add the following dependency to their `pom.xml`. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-ibm-watson-speech-to-text x.x.x ---------------------------------------- +---- where `x.x.x` is the version number of Camel. diff --git a/components/camel-ibm/camel-ibm-watson-text-to-speech/src/main/docs/ibm-watson-text-to-speech-component.adoc b/components/camel-ibm/camel-ibm-watson-text-to-speech/src/main/docs/ibm-watson-text-to-speech-component.adoc index 11d6f5af0dc83..b35e625d44e62 100644 --- a/components/camel-ibm/camel-ibm-watson-text-to-speech/src/main/docs/ibm-watson-text-to-speech-component.adoc +++ b/components/camel-ibm/camel-ibm-watson-text-to-speech/src/main/docs/ibm-watson-text-to-speech-component.adoc @@ -25,9 +25,9 @@ More information is available at https://cloud.ibm.com/catalog/services/text-to- == URI Format ------------------------------- +---- ibm-watson-text-to-speech:label[?options] ------------------------------- +---- You can append query options to the URI in the following format: @@ -472,23 +472,23 @@ To get your credentials: Integration tests are executed with the `verify` goal and require system properties: [source,bash] --------------------------------------------------------------------------------- +---- mvn verify \ -Dcamel.ibm.watson.tts.apiKey=YOUR_API_KEY \ -Dcamel.ibm.watson.tts.serviceUrl=YOUR_SERVICE_URL --------------------------------------------------------------------------------- +---- Alternatively, using environment variables: [source,bash] --------------------------------------------------------------------------------- +---- export CAMEL_IBM_WATSON_TTS_API_KEY=YOUR_API_KEY export CAMEL_IBM_WATSON_TTS_SERVICE_URL=YOUR_SERVICE_URL mvn verify \ -Dcamel.ibm.watson.tts.apiKey=${CAMEL_IBM_WATSON_TTS_API_KEY} \ -Dcamel.ibm.watson.tts.serviceUrl=${CAMEL_IBM_WATSON_TTS_SERVICE_URL} --------------------------------------------------------------------------------- +---- === Integration Test Coverage @@ -540,7 +540,7 @@ These files can be played with any media player to verify audio quality and comp === Example Output [source] --------------------------------------------------------------------------------- +---- [INFO] Running org.apache.camel.component.ibm.watson.tts.integration.WatsonTextToSpeechIT Created output directory: target/audio-output Successfully synthesized text with default voice. Bytes read: 44032 @@ -550,7 +550,7 @@ Found 28 voices Successfully saved MP3 file: target/audio-output/test-output.mp3 (size: 51234 bytes) Successfully created audio files in 4 different languages [INFO] Tests run: 12, Failures: 0, Errors: 0, Skipped: 0 --------------------------------------------------------------------------------- +---- == Dependencies @@ -559,14 +559,14 @@ Maven users will need to add the following dependency to their `pom.xml`. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-ibm-watson-text-to-speech x.x.x ---------------------------------------- +---- where `x.x.x` is the version number of Camel. diff --git a/components/camel-ibm/camel-ibm-watsonx-ai/src/main/docs/ibm-watsonx-ai-component.adoc b/components/camel-ibm/camel-ibm-watsonx-ai/src/main/docs/ibm-watsonx-ai-component.adoc index 73bd6d887e4e1..8b372c87eab63 100644 --- a/components/camel-ibm/camel-ibm-watsonx-ai/src/main/docs/ibm-watsonx-ai-component.adoc +++ b/components/camel-ibm/camel-ibm-watsonx-ai/src/main/docs/ibm-watsonx-ai-component.adoc @@ -36,9 +36,9 @@ To use this component, you need: == URI Format ------------------------------- +---- ibm-watsonx-ai:label[?options] ------------------------------- +---- You can append query options to the URI in the following format: @@ -373,7 +373,7 @@ Stream chat responses with a callback consumer: ._Java-only: uses `Consumer` callback and `UserMessage` SDK type_ [source,java] --------------------------------------------------------------------------------- +---- import com.ibm.watsonx.ai.chat.model.UserMessage; from("direct:streamChat") @@ -393,7 +393,7 @@ from("direct:streamChat") "&modelId=ibm/granite-4-h-small" + "&operation=chatStreaming") .log("Full response: ${body}"); --------------------------------------------------------------------------------- +---- === Streaming Chat with WebSocket @@ -574,7 +574,7 @@ Generate embeddings for semantic search and similarity: ._Java-only: uses `List.of()` for batch input and `process` lambda for typed result handling_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:embed") .setBody(constant(List.of( "Apache Camel is an integration framework", @@ -590,7 +590,7 @@ from("direct:embed") System.out.println("Generated " + embeddings.size() + " embeddings"); System.out.println("Embedding dimensions: " + embeddings.get(0).size()); }); --------------------------------------------------------------------------------- +---- === Single Text Embedding @@ -651,7 +651,7 @@ Generate an embedding and store it in a Qdrant vector database for semantic sear ._Java-only: uses Qdrant SDK types (`Points.PointStruct`, `VectorsFactory`, etc.) for vector construction_ [source,java] --------------------------------------------------------------------------------- +---- import org.apache.camel.component.qdrant.QdrantHeaders; import org.apache.camel.component.qdrant.QdrantAction; import io.qdrant.client.PointIdFactory; @@ -679,7 +679,7 @@ from("direct:embedAndStore") }) .to("qdrant:embeddings?host=localhost&port=6334") .log("Embedding stored with ID: ${header.CamelQdrantOperationID}"); --------------------------------------------------------------------------------- +---- NOTE: This example requires the `camel-qdrant` dependency. See the xref:qdrant-component.adoc[Qdrant component documentation] for more details. @@ -689,7 +689,7 @@ Rerank documents by relevance to a query: ._Java-only: uses `process` lambda with `List.of()` for document input_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:rerank") .process(exchange -> { // Set the query to rank against @@ -712,7 +712,7 @@ from("direct:rerank") List results = exchange.getMessage().getBody(List.class); System.out.println("Reranked results: " + results); }); --------------------------------------------------------------------------------- +---- === Rerank with Top N @@ -720,7 +720,7 @@ Return only the top N most relevant documents: ._Java-only: uses `List.of()` for document input_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:rerankTopN") .setHeader("CamelIBMWatsonxAiRerankQuery", constant("Cloud computing platform")) .setHeader("CamelIBMWatsonxAiRerankTopN", constant(3)) @@ -737,7 +737,7 @@ from("direct:rerankTopN") "&modelId=cross-encoder/ms-marco-minilm-l-12-v2" + "&operation=rerank") .log("Top 3 results: ${body}"); --------------------------------------------------------------------------------- +---- === Tokenization @@ -955,7 +955,7 @@ Provide custom detectors via header: ._Java-only: uses watsonx.ai SDK detector types (`Pii`, `Hap`)_ [source,java] --------------------------------------------------------------------------------- +---- import com.ibm.watsonx.ai.detection.detector.Pii; import com.ibm.watsonx.ai.detection.detector.Hap; @@ -972,7 +972,7 @@ from("direct:detectCustom") "&projectId=yourProjectId" + "&operation=detect") .log("Detections: ${body}"); --------------------------------------------------------------------------------- +---- === Text Extraction from Cloud Object Storage @@ -1166,7 +1166,7 @@ The text extraction operations integrate seamlessly with Camel file components: ._Java-only: illustrative snippets showing various file source integrations_ [source,java] --------------------------------------------------------------------------------- +---- // From local file system from("file:/documents/incoming?noop=true") .to("ibm-watsonx-ai:extract?operation=textExtractionUploadAndFetch...") @@ -1186,7 +1186,7 @@ from("aws2-s3://my-bucket?region=us-east-1&prefix=docs/") from("azure-storage-blob://mycontainer?prefix=documents/") .to("ibm-watsonx-ai:extract?operation=textExtractionUploadAndFetch...") .log("Extracted text from blob"); --------------------------------------------------------------------------------- +---- === Document Classification @@ -1318,7 +1318,7 @@ For more control, use the async flow with `textClassificationUpload` and `textCl ._Java-only: complex async polling pattern with `loopDoWhile`, `delay`, `exchangeProperty`, and `choice`_ [source,java] --------------------------------------------------------------------------------- +---- // Start classification and poll until complete from("direct:startClassification") .to("ibm-watsonx-ai:classify?operation=textClassificationUpload" + @@ -1349,7 +1349,7 @@ from("direct:startClassification") .otherwise() .log("Classification failed: ${header.CamelIBMWatsonxAiErrorMessage}") .end(); --------------------------------------------------------------------------------- +---- ==== Classification with File Components @@ -1357,7 +1357,7 @@ The classification operations integrate seamlessly with Camel file components: ._Java-only: illustrative snippets showing various file source integrations_ [source,java] --------------------------------------------------------------------------------- +---- // From local file system from("file:/documents/incoming?noop=true") .to("ibm-watsonx-ai:classify?operation=textClassificationUploadAndFetch...") @@ -1377,7 +1377,7 @@ from("aws2-s3://my-bucket?region=us-east-1&prefix=docs/") from("azure-storage-blob://mycontainer?prefix=documents/") .to("ibm-watsonx-ai:classify?operation=textClassificationUploadAndFetch...") .log("Classified blob: ${header.CamelIBMWatsonxAiClassificationResult}"); --------------------------------------------------------------------------------- +---- ==== Delete Classification Request @@ -1580,7 +1580,7 @@ Generate time series forecasts: ._Java-only: uses watsonx.ai SDK types (`InputSchema`, `ForecastData`) for time series data construction_ [source,java] --------------------------------------------------------------------------------- +---- import com.ibm.watsonx.ai.timeseries.InputSchema; import com.ibm.watsonx.ai.timeseries.ForecastData; @@ -1607,7 +1607,7 @@ from("direct:forecast") "&modelId=ibm/granite-ttm-1536-96-r2" + "&operation=forecast") .log("Forecast results: ${body}"); --------------------------------------------------------------------------------- +---- === List Available Models @@ -1757,7 +1757,7 @@ Use watsonx.ai utility tools (experimental): ._Java-only: uses `process` lambda with `Map.of()` for tool input and config_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:runTool") .process(exchange -> { // Set tool name @@ -1771,7 +1771,7 @@ from("direct:runTool") "&baseUrl=https://us-south.ml.cloud.ibm.com" + "&operation=runTool") .log("Tool result: ${body}"); --------------------------------------------------------------------------------- +---- === List Available Tools @@ -1825,7 +1825,7 @@ When using Spring Boot or Camel Main, you can configure the component in `applic NOTE: This configuration approach works with both Spring Boot (`camel-ibm-watsonx-ai-starter`) and Camel Main runtimes. [source,properties] --------------------------------------------------------------------------------- +---- # watsonx.ai configuration camel.component.ibm-watsonx-ai.configuration.api-key=${IBM_WATSONX_API_KEY} camel.component.ibm-watsonx-ai.configuration.base-url=https://us-south.ml.cloud.ibm.com @@ -1833,7 +1833,7 @@ camel.component.ibm-watsonx-ai.configuration.project-id=${IBM_WATSONX_PROJECT_ID camel.component.ibm-watsonx-ai.configuration.model-id=ibm/granite-13b-instruct-v2 camel.component.ibm-watsonx-ai.configuration.temperature=0.7 camel.component.ibm-watsonx-ai.configuration.max-new-tokens=200 --------------------------------------------------------------------------------- +---- Then use the component in routes without repeating configuration: @@ -1947,14 +1947,14 @@ Maven users will need to add the following dependency to their `pom.xml`. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-ibm-watsonx-ai x.x.x ---------------------------------------- +---- where `x.x.x` is the version number of Camel. diff --git a/components/camel-ical/src/main/docs/ical-dataformat.adoc b/components/camel-ical/src/main/docs/ical-dataformat.adoc index 02286206359ce..6eb75a6e12530 100644 --- a/components/camel-ical/src/main/docs/ical-dataformat.adoc +++ b/components/camel-ical/src/main/docs/ical-dataformat.adoc @@ -18,7 +18,7 @@ A typical iCalendar message looks like: ._Java-only: example of an iCalendar message format_ [source,java] ----------------------------------------------------------------------- +---- BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Events Calendar//iCal4j 1.0//EN @@ -34,7 +34,7 @@ ATTENDEE;ROLE=REQ-PARTICIPANT;CN=Developer 1:mailto:dev1@mycompany.com ATTENDEE;ROLE=OPT-PARTICIPANT;CN=Developer 2:mailto:dev2@mycompany.com END:VEVENT END:VCALENDAR ----------------------------------------------------------------------- +---- == Options @@ -96,14 +96,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-ical x.x.x ------------------------------------------------------------- +---- diff --git a/components/camel-infinispan/camel-infinispan-embedded/src/main/docs/infinispan-embedded-component.adoc b/components/camel-infinispan/camel-infinispan-embedded/src/main/docs/infinispan-embedded-component.adoc index 6558416eca3b6..0727d2ae52658 100644 --- a/components/camel-infinispan/camel-infinispan-embedded/src/main/docs/infinispan-embedded-component.adoc +++ b/components/camel-infinispan/camel-infinispan-embedded/src/main/docs/infinispan-embedded-component.adoc @@ -33,20 +33,20 @@ The events are processed asynchronously. If you use Maven, you must add the following dependency to your `pom.xml`: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-infinispan-embedded x.x.x ------------------------------------------------------------- +---- == URI format -------------------------------- +---- infinispan-embedded://cacheName?[options] -------------------------------- +---- The producer allows sending messages to a local infinispan cache. The consumer allows listening for events from local infinispan cache. diff --git a/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc b/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc index 473402d4a121f..0a52bb1e978f6 100644 --- a/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc +++ b/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc @@ -20,20 +20,20 @@ Infinispan is an extremely scalable, highly available key/value data store and d If you use Maven, you must add the following dependency to your `pom.xml`: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-infinispan x.x.x ------------------------------------------------------------- +---- == URI format -------------------------------- +---- infinispan://cacheName?[options] -------------------------------- +---- The producer allows sending messages to a remote cache using the HotRod protocol. The consumer allows listening for events from a remote cache using the HotRod protocol. diff --git a/components/camel-irc/src/main/docs/irc-component.adoc b/components/camel-irc/src/main/docs/irc-component.adoc index 5c39da2c7572e..4b2892ed32449 100644 --- a/components/camel-irc/src/main/docs/irc-component.adoc +++ b/components/camel-irc/src/main/docs/irc-component.adoc @@ -23,14 +23,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-irc x.x.x ------------------------------------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -58,7 +58,7 @@ Programmatic configuration of the endpoint ._Java-only: Java programmatic SSL configuration_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------ +---- KeyStoreParameters ksp = new KeyStoreParameters(); ksp.setResource("/users/home/server/truststore.jks"); ksp.setPassword("keystorePassword"); @@ -76,13 +76,13 @@ registry.bind("sslContextParameters", scp); from(...) .to("ircs://camel-prd-user@server:6669/#camel-test?nickname=camel-prd&password=password&sslContextParameters=#sslContextParameters"); ------------------------------------------------------------------------------------------------------------------------------------------ +---- [[IRC-SpringDSLbasedconfigurationofendpoint]] Spring DSL based configuration of endpoint [source,xml] ----------------------------------------------------------------------------------------------------------------------------------------------- +---- ... @@ -94,7 +94,7 @@ Spring DSL based configuration of endpoint ... ... ... ----------------------------------------------------------------------------------------------------------------------------------------------- +---- === Using the legacy basic configuration options @@ -102,9 +102,9 @@ You can also connect to an SSL enabled IRC server, as follows: ._Java-only: endpoint URI syntax_ [source,java] --------------------------------------------------- +---- ircs:host[:port]/#room?username=user&password=pass --------------------------------------------------- +---- By default, the IRC transport uses http://moepii.sourceforge.net/irclib/javadoc/org/schwering/irc/lib/ssl/SSLDefaultTrustManager.html[SSLDefaultTrustManager]. @@ -113,9 +113,9 @@ If you need to provide your own custom trust manager, use the ._Java-only: endpoint URI syntax with trustManager_ [source,java] ----------------------------------------------------------------------------------------------- +---- ircs:host[:port]/#room?username=user&password=pass&trustManager=#referenceToMyTrustManagerBean ----------------------------------------------------------------------------------------------- +---- == Examples @@ -128,9 +128,9 @@ For example, we join three channels whereas only channel 1 and 3 use a key. ._Java-only: endpoint URI syntax with channel keys_ [source,java] ------------------------------------------------------------------------------ +---- irc:nick@irc.server.org?channels=#chan1,#chan2,#chan3&keys=chan1Key,,chan3key ------------------------------------------------------------------------------ +---- === Getting a list of channel users @@ -142,13 +142,13 @@ For example, we want to get all exchanges that contain the usernames of the chan ._Java-only: Java DSL with choice and filter EIPs_ [source,java] ------------------------------------------------------------------------------ +---- from("ircs:nick@myserver:1234/#mychannelname?namesOnJoin=true&onReply=true") .choice() .when(header("CamelIrcMessageType").isEqualToIgnoreCase("REPLY")) .filter(header("CamelIrcNum").isEqualTo("353")) .to("mock:result").stop(); ------------------------------------------------------------------------------ +---- === Sending to a different channel or a person diff --git a/components/camel-iso8583/src/main/docs/iso8583-dataformat.adoc b/components/camel-iso8583/src/main/docs/iso8583-dataformat.adoc index 9b5841579a2bc..b6106f10fbc49 100644 --- a/components/camel-iso8583/src/main/docs/iso8583-dataformat.adoc +++ b/components/camel-iso8583/src/main/docs/iso8583-dataformat.adoc @@ -208,14 +208,14 @@ If you use maven, you could add the following to your `pom.xml`, substituting the version number for the latest and greatest release. [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-iso8583 x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc b/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc index 47e770dd032e2..19f9806448343 100644 --- a/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc +++ b/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc @@ -92,13 +92,13 @@ If you use Maven, you could add the following to your pom.xml, substituting the version number for the latest & greatest release. [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-jackson-avro x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc b/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc index b4aa2c73e7ab5..eaf197270d5cf 100644 --- a/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc +++ b/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc @@ -92,13 +92,13 @@ If you use Maven, you could add the following to your pom.xml, substituting the version number for the latest & greatest release. [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-jackson-protobuf x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc b/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc index b4844ac952faf..6cef121a3074b 100644 --- a/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc +++ b/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc @@ -113,14 +113,14 @@ If you use Maven, you could add the following to your `pom.xml`, substituting the version number for the latest & greatest release: [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-jackson x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc b/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc index 722a413ce9ec1..e9a976b01d088 100644 --- a/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc +++ b/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc @@ -92,13 +92,13 @@ If you use Maven, you could add the following to your pom.xml, substituting the version number for the latest & greatest release. [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-jackson3-avro x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc b/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc index abb80cf58719d..e0074b0ff64c9 100644 --- a/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc +++ b/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc @@ -92,13 +92,13 @@ If you use Maven, you could add the following to your pom.xml, substituting the version number for the latest & greatest release. [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-jackson3-protobuf x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc b/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc index bd0062846daf4..196810b661b12 100644 --- a/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc +++ b/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc @@ -67,17 +67,17 @@ Jackson can also be used via the generic `json()` DSL method by specifying `Json ._Java-only: using the json() DSL method with JsonLibrary.Jackson_ [source,java] -------------------------------- +---- from("activemq:My.Queue") .marshal().json(JsonLibrary.Jackson) .to("mqseries:Another.Queue"); -------------------------------- +---- This is equivalent to using `.jackson()` directly. The `json()` method also supports additional parameters: ._Java-only: json() DSL with pretty print and unmarshal type_ [source,java] -------------------------------- +---- // Pretty print from("activemq:My.Queue") .marshal().json(JsonLibrary.Jackson, true) @@ -87,7 +87,7 @@ from("activemq:My.Queue") from("activemq:My.Queue") .unmarshal().json(JsonLibrary.Jackson, MyPojo.class) .to("mqseries:Another.Queue"); -------------------------------- +---- === 2 and 4 bytes characters @@ -140,14 +140,14 @@ If you use Maven, you could add the following to your `pom.xml`, substituting the version number for the latest & greatest release: [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-jackson3 x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc b/components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc index 69144c7f6b959..14dccb6586c3f 100644 --- a/components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc +++ b/components/camel-jackson3xml/src/main/docs/jacksonXml3-dataformat.adoc @@ -87,24 +87,24 @@ When using Data Format in Spring DSL, you need to declare the data formats first. This is done in the `dataFormats` XML tag: [source,xml] ------------------------------------------------------------------------------------------------------------------------------ +---- ------------------------------------------------------------------------------------------------------------------------------ +---- And then you can refer to this id in the route: [source,xml] -------------------------------------- +---- -------------------------------------- +---- === Excluding POJO fields from marshalling @@ -122,9 +122,9 @@ to XML. Note that the weight field is missing in the resulting XML: [source,xml] ----------------------------- +---- ----------------------------- +---- === Include/Exclude fields using the `jsonView` attribute with ``JacksonXML``DataFormat @@ -132,34 +132,34 @@ As an example of using this attribute, you can instead of: ._Java-only: Java programmatic data format with class literal_ [source,java] ---------------------------------------------------------------------------------------------------- +---- JacksonXMLDataFormat ageViewFormat = new JacksonXMLDataFormat(TestPojoView.class, Views.Age.class); from("direct:inPojoAgeView") .marshal(ageViewFormat); ---------------------------------------------------------------------------------------------------- +---- Directly specify your https://github.com/FasterXML/jackson-annotations/blob/master/src/main/java/tools/jackson/annotation/JsonView.java[JSON view] inside the Java DSL as: ._Java-only: Java DSL with class literal parameters_ [source,java] ------------------------------------------------------------- +---- from("direct:inPojoAgeView") .marshal().jacksonXml(TestPojoView.class, Views.Age.class); ------------------------------------------------------------- +---- And the same in XML DSL: [source,xml] ---------------------------------------------------------------------------------------------------------------------------------------------------- +---- ---------------------------------------------------------------------------------------------------------------------------------------------------- +---- === Setting serialization include option @@ -169,12 +169,12 @@ set either an annotation on the POJO: ._Java-only: Java annotation_ [source,java] ------------------------------- +---- @JsonInclude(Include.NON_NULL) public class MyPojo { ... } ------------------------------- +---- But this requires you to include that annotation in your POJO source code. You can also configure the Camel JacksonXMLDataFormat to set the @@ -182,19 +182,19 @@ code. You can also configure the Camel JacksonXMLDataFormat to set the ._Java-only: Java programmatic data format configuration_ [source,java] ---------------------------------------------------------- +---- JacksonXMLDataFormat format = new JacksonXMLDataFormat(); format.setInclude("NON_NULL"); ---------------------------------------------------------- +---- Or from XML DSL you configure this as [source,xml] ------------------------------------------------------- +---- ------------------------------------------------------- +---- === Unmarshalling from XML to POJO with dynamic class name @@ -210,19 +210,19 @@ turn that on, on the Jackson data format as shown: ._Java-only: Java programmatic data format configuration_ [source,java] ---------------------------------------------------- +---- JacksonDataFormat format = new JacksonDataFormat(); format.setAllowJmsType(true); ---------------------------------------------------- +---- Or from XML DSL you configure this as: [source,xml] -------------------------------------------------------- +---- -------------------------------------------------------- +---- === Unmarshalling from XML to `List` or `List` @@ -233,33 +233,33 @@ For example, with Java, you can do as shown below: ._Java-only: Java programmatic data format configuration_ [source,java] -------------------------------------------------------------- +---- JacksonXMLDataFormat format = new ListJacksonXMLDataFormat(); // or JacksonXMLDataFormat format = new JacksonXMLDataFormat(); format.useList(); // and you can specify the POJO class type also format.setUnmarshalType(MyPojo.class); -------------------------------------------------------------- +---- And if you use XML DSL then you configure to use a list using `useList` attribute as shown below: [source,xml] --------------------------------------------- +---- --------------------------------------------- +---- And you can specify the POJO type also [source,xml] -------------------------------------------------------------------------------- +---- -------------------------------------------------------------------------------- +---- === Using custom Jackson modules @@ -267,11 +267,11 @@ You can use custom Jackson modules by specifying the class names of those using the moduleClassNames option as shown below. [source,xml] ------------------------------------------------------------------------------------------------------------------------------------------ +---- ------------------------------------------------------------------------------------------------------------------------------------------ +---- When using `moduleClassNames` then the custom Jackson modules are not configured, by created using default constructor and used as-is. If a @@ -280,7 +280,7 @@ module can be created and configured, and then use modulesRefs to refer to the module as shown below: [source,xml] ------------------------------------------------------------------------------------------------------------------- +---- ... // configure the module as you want @@ -288,7 +288,7 @@ to the module as shown below: ------------------------------------------------------------------------------------------------------------------- +---- Multiple modules can be specified separated by comma, such as `moduleRefs="myJacksonModule,myOtherModule"`. @@ -300,11 +300,11 @@ For example, to disable failing on unknown properties when marshalling, you can configure this using the disableFeatures: [source,xml] -------------------------------------------------------------------------------------------------------------------- +---- -------------------------------------------------------------------------------------------------------------------- +---- You can disable multiple features by separating the values using comma. The values for the features must be the name of the enums from Jackson @@ -322,11 +322,11 @@ module: ._Java-only: Java programmatic data format configuration_ [source,java] ----------------------------------------------------------------------- +---- JacksonDataFormat df = new JacksonDataFormat(MyPojo.class); df.disableFeature(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); df.disableFeature(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES); ----------------------------------------------------------------------- +---- === Converting Maps to POJO using Jackson @@ -337,14 +337,14 @@ non-Number objects. ._Java-only: Java collection API (ProducerTemplate)_ [source,java] ----------------------------------------------------------------- +---- Map invoiceData = new HashMap(); invoiceData.put("netValue", 500); producerTemplate.sendBody("direct:mapToInvoice", invoiceData); ... // Later in the processor Invoice invoice = exchange.getIn().getBody(Invoice.class); ----------------------------------------------------------------- +---- If there is a single `XmlMapper` instance available in the Camel registry, it will be used by the converter to perform the conversion. @@ -356,19 +356,19 @@ Using the `prettyPrint` option one can output a well-formatted XML while marshalling: [source,xml] ------------------------------------------------- +---- ------------------------------------------------- +---- And in Java DSL: ._Java-only: Java DSL shorthand_ [source,java] ---------------------------------------------------- +---- from("direct:inPretty").marshal().jacksonXml(true); ---------------------------------------------------- +---- Please note that there are 5 different overloaded `jacksonXml()` DSL methods which support the `prettyPrint` option in combination with other @@ -383,14 +383,14 @@ If you use Maven, you could add the following to your `pom.xml`, substituting the version number for the latest & greatest release. [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-jackson3xml x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc b/components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc index 0c28b7145391b..f0b85cba490c8 100644 --- a/components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc +++ b/components/camel-jacksonxml/src/main/docs/jacksonXml2-dataformat.adoc @@ -87,24 +87,24 @@ When using Data Format in Spring DSL, you need to declare the data formats first. This is done in the `dataFormats` XML tag: [source,xml] ------------------------------------------------------------------------------------------------------------------------------ +---- ------------------------------------------------------------------------------------------------------------------------------ +---- And then you can refer to this id in the route: [source,xml] -------------------------------------- +---- -------------------------------------- +---- === Excluding POJO fields from marshalling @@ -122,9 +122,9 @@ to XML. Note that the weight field is missing in the resulting XML: [source,xml] ----------------------------- +---- ----------------------------- +---- === Include/Exclude fields using the `jsonView` attribute with ``JacksonXML``DataFormat @@ -132,34 +132,34 @@ As an example of using this attribute, you can instead of: ._Java-only: Java programmatic data format with class literal_ [source,java] ---------------------------------------------------------------------------------------------------- +---- JacksonXMLDataFormat ageViewFormat = new JacksonXMLDataFormat(TestPojoView.class, Views.Age.class); from("direct:inPojoAgeView") .marshal(ageViewFormat); ---------------------------------------------------------------------------------------------------- +---- Directly specify your https://github.com/FasterXML/jackson-annotations/blob/master/src/main/java/com/fasterxml/jackson/annotation/JsonView.java[JSON view] inside the Java DSL as: ._Java-only: Java DSL with class literal parameters_ [source,java] ------------------------------------------------------------- +---- from("direct:inPojoAgeView") .marshal().jacksonXml(TestPojoView.class, Views.Age.class); ------------------------------------------------------------- +---- And the same in XML DSL: [source,xml] ---------------------------------------------------------------------------------------------------------------------------------------------------- +---- ---------------------------------------------------------------------------------------------------------------------------------------------------- +---- === Setting serialization include option @@ -169,12 +169,12 @@ set either an annotation on the POJO: ._Java-only: Java annotation_ [source,java] ------------------------------- +---- @JsonInclude(Include.NON_NULL) public class MyPojo { ... } ------------------------------- +---- But this requires you to include that annotation in your POJO source code. You can also configure the Camel JacksonXMLDataFormat to set the @@ -182,19 +182,19 @@ code. You can also configure the Camel JacksonXMLDataFormat to set the ._Java-only: Java programmatic data format configuration_ [source,java] ---------------------------------------------------------- +---- JacksonXMLDataFormat format = new JacksonXMLDataFormat(); format.setInclude("NON_NULL"); ---------------------------------------------------------- +---- Or from XML DSL you configure this as [source,xml] ------------------------------------------------------- +---- ------------------------------------------------------- +---- === Unmarshalling from XML to POJO with dynamic class name @@ -210,19 +210,19 @@ turn that on, on the Jackson data format as shown: ._Java-only: Java programmatic data format configuration_ [source,java] ---------------------------------------------------- +---- JacksonDataFormat format = new JacksonDataFormat(); format.setAllowJmsType(true); ---------------------------------------------------- +---- Or from XML DSL you configure this as: [source,xml] -------------------------------------------------------- +---- -------------------------------------------------------- +---- === Unmarshalling from XML to `List` or `List` @@ -233,33 +233,33 @@ For example, with Java, you can do as shown below: ._Java-only: Java programmatic data format configuration_ [source,java] -------------------------------------------------------------- +---- JacksonXMLDataFormat format = new ListJacksonXMLDataFormat(); // or JacksonXMLDataFormat format = new JacksonXMLDataFormat(); format.useList(); // and you can specify the POJO class type also format.setUnmarshalType(MyPojo.class); -------------------------------------------------------------- +---- And if you use XML DSL then you configure to use a list using `useList` attribute as shown below: [source,xml] --------------------------------------------- +---- --------------------------------------------- +---- And you can specify the POJO type also [source,xml] -------------------------------------------------------------------------------- +---- -------------------------------------------------------------------------------- +---- === Using custom Jackson modules @@ -267,11 +267,11 @@ You can use custom Jackson modules by specifying the class names of those using the moduleClassNames option as shown below. [source,xml] ------------------------------------------------------------------------------------------------------------------------------------------ +---- ------------------------------------------------------------------------------------------------------------------------------------------ +---- When using `moduleClassNames` then the custom Jackson modules are not configured, by created using default constructor and used as-is. If a @@ -280,7 +280,7 @@ module can be created and configured, and then use modulesRefs to refer to the module as shown below: [source,xml] ------------------------------------------------------------------------------------------------------------------- +---- ... // configure the module as you want @@ -288,7 +288,7 @@ to the module as shown below: ------------------------------------------------------------------------------------------------------------------- +---- Multiple modules can be specified separated by comma, such as `moduleRefs="myJacksonModule,myOtherModule"`. @@ -300,11 +300,11 @@ For example, to disable failing on unknown properties when marshalling, you can configure this using the disableFeatures: [source,xml] -------------------------------------------------------------------------------------------------------------------- +---- -------------------------------------------------------------------------------------------------------------------- +---- You can disable multiple features by separating the values using comma. The values for the features must be the name of the enums from Jackson @@ -322,11 +322,11 @@ module: ._Java-only: Java programmatic data format configuration_ [source,java] ----------------------------------------------------------------------- +---- JacksonDataFormat df = new JacksonDataFormat(MyPojo.class); df.disableFeature(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); df.disableFeature(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES); ----------------------------------------------------------------------- +---- === Converting Maps to POJO using Jackson @@ -337,14 +337,14 @@ non-Number objects. ._Java-only: Java collection API (ProducerTemplate)_ [source,java] ----------------------------------------------------------------- +---- Map invoiceData = new HashMap(); invoiceData.put("netValue", 500); producerTemplate.sendBody("direct:mapToInvoice", invoiceData); ... // Later in the processor Invoice invoice = exchange.getIn().getBody(Invoice.class); ----------------------------------------------------------------- +---- If there is a single `XmlMapper` instance available in the Camel registry, it will be used by the converter to perform the conversion. @@ -356,19 +356,19 @@ Using the `prettyPrint` option one can output a well-formatted XML while marshalling: [source,xml] ------------------------------------------------- +---- ------------------------------------------------- +---- And in Java DSL: ._Java-only: Java DSL shorthand_ [source,java] ---------------------------------------------------- +---- from("direct:inPretty").marshal().jacksonXml(true); ---------------------------------------------------- +---- Please note that there are 5 different overloaded `jacksonXml()` DSL methods which support the `prettyPrint` option in combination with other @@ -383,14 +383,14 @@ If you use Maven, you could add the following to your `pom.xml`, substituting the version number for the latest & greatest release. [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-jacksonxml x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jasypt/src/main/docs/jasypt.adoc b/components/camel-jasypt/src/main/docs/jasypt.adoc index 7972e6d49aa99..ec5ed3cdaa3b3 100644 --- a/components/camel-jasypt/src/main/docs/jasypt.adoc +++ b/components/camel-jasypt/src/main/docs/jasypt.adoc @@ -23,14 +23,14 @@ If you are using Maven, you need to add the following dependency to your `pom.xm for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-jasypt x.x.x ------------------------------------------------------------- +---- == Tooling @@ -47,7 +47,7 @@ The Jasypt component is a runnable JAR that provides a command line utility to e The usage documentation can be output to the console to describe the syntax and options it provides: [source,text] --------------------------------------------------------------- +---- Apache Camel Jasypt takes the following options -h or -help = Displays the help screen @@ -57,23 +57,23 @@ Apache Camel Jasypt takes the following options -a or -algorithm = Optional algorithm to use -rsga or -algorithm = Optional random salt generator algorithm to use -riga or -algorithm = Optional random iv generator algorithm to use --------------------------------------------------------------- +---- A simple way of running the tool is with https://www.jbang.dev/[JBang]. For example, to encrypt the value `tiger`, you can use the following parameters. Make sure to specify the version of camel-jasypt that you want to use. [source,bash] ----------------------------------------------------------------- +---- $ jbang org.apache.camel:camel-jasypt: -c encrypt -p secret -i tiger ----------------------------------------------------------------- +---- Which outputs the following result [source,text] ----------------------------------------- +---- Encrypted text: qaEEacuW7BUti8LcMgyjKw== ----------------------------------------- +---- This means the encrypted representation `qaEEacuW7BUti8LcMgyjKw==` can be decrypted back to `tiger` if you know the _master_ password which was @@ -86,24 +86,24 @@ You can test decrypting the value by running the tooling using the following parameters: [source,bash] ------------------------------------------------------------------------------------ +---- $ jbang org.apache.camel:camel-jasypt: -c decrypt -p secret -i qaEEacuW7BUti8LcMgyjKw== ------------------------------------------------------------------------------------ +---- Which outputs the following result: [source,text] ---------------------- +---- Decrypted text: tiger ---------------------- +---- The idea is to then use the encrypted values in your xref:ROOT:properties-component.adoc[Properties] files. For example. [source,text] ---------------------- +---- # Encrypted value for 'tiger' my.secret = ENC(qaEEacuW7BUti8LcMgyjKw==) ---------------------- +---- == Protecting the master password @@ -121,33 +121,33 @@ For example, you could provide the password before you start the application [source,bash] ------------------------------------------ +---- $ export CAMEL_ENCRYPTION_PASSWORD=secret ------------------------------------------ +---- Then start the application, such as running the start script. When the application is up and running, you can unset the environment [source,bash] ---------------------------------- +---- $ unset CAMEL_ENCRYPTION_PASSWORD ---------------------------------- +---- On runtimes like Spring Boot and Quarkus, you can configure a password property in `application.properties` as follows. [source,text] ---------------------- +---- password=sysenv:CAMEL_ENCRYPTION_PASSWORD ---------------------- +---- Or if configuring `JasyptPropertiesParser` manually, you can set the password like this. ._Java-only: setting the master password on JasyptPropertiesParser_ [source,java] ---------------------- +---- jasyptPropertiesParser.setPassword("sysenv:CAMEL_ENCRYPTION_PASSWORD"); ---------------------- +---- == Example configuration @@ -160,7 +160,7 @@ On the Spring Boot and Quarkus runtimes, Camel Jasypt can be configured via conf Else, in Java DSL you need to configure Jasypt as a `JasyptPropertiesParser` instance and set it on the xref:ROOT:properties-component.adoc[Properties] component as shown below: + [source,java] ---------------------- +---- // create the jasypt properties parser JasyptPropertiesParser jasypt = new JasyptPropertiesParser(); // set the master password (see above for how to do this in a secure way) @@ -176,27 +176,27 @@ pc.setNestedPlaceholder(true); // add properties component to camel context context.setPropertiesComponent(pc); ---------------------- +---- + It is possible to configure custom algorithms on the JasyptPropertiesParser like this. + [source,java] ------------------------------------------------------------------------------------------------------------ +---- JasyptPropertiesParser jasyptPropertiesParser = new JasyptPropertiesParser(); jasyptPropertiesParser.setAlgorithm("PBEWithHmacSHA256AndAES_256"); jasyptPropertiesParser.setRandomSaltGeneratorAlgorithm("PKCS11"); jasyptPropertiesParser.setRandomIvGeneratorAlgorithm("PKCS11"); ------------------------------------------------------------------------------------------------------------ +---- + The properties file `secret.properties` will contain your encrypted configuration values, such as shown below. Notice how the password value is encrypted and is surrounded like `ENC(value here)`. + [source,text] ---------------------- +---- my.secret.password=ENC(bsW9uV37gQ0QHFu7KO03Ww==) ---------------------- +---- XML (Spring):: + @@ -207,7 +207,7 @@ Jasypt has its chance to decrypt values looked up in the properties file. + [source,xml] ------------------------------------------------------------------------------------------------------------ +---- @@ -222,7 +222,7 @@ the properties file. ------------------------------------------------------------------------------------------------------------ +---- + The xref:ROOT:properties-component.adoc[Properties] component can also be inlined inside the `` tag which is shown below. Notice how we use @@ -230,7 +230,7 @@ the `propertiesParserRef` attribute to refer to Jasypt. + [source,xml] --------------------------------------------------------------------------------------------------------------- +---- ------------------------------------------------------------------------ +---- To use this in JAXB or SOAP data formats, you refer to this map, using the `namespacePrefixRef` attribute as shown below. Then @@ -212,11 +212,11 @@ Camel will look up in the Registry a `java.util.Map` with the id `myMap`, which was what we defined above. [source,xml] ----------------------------------------------------------------------------------------- +---- ----------------------------------------------------------------------------------------- +---- === Schema validation @@ -232,22 +232,22 @@ Using the Java DSL, you can configure it in the following way: ._Java-only: Java programmatic data format configuration_ [source,java] ------------------------------------------------------------------------ +---- JaxbDataFormat jaxbDataFormat = new JaxbDataFormat(); jaxbDataFormat.setContextPath(Person.class.getPackage().getName()); jaxbDataFormat.setSchema("classpath:person.xsd,classpath:address.xsd"); jaxbDataFormat.setAccessExternalSchemaProtocols("file"); ------------------------------------------------------------------------ +---- You can do the same using the XML DSL: [source,xml] -------------------------------------------------------------------------- +---- -------------------------------------------------------------------------- +---- === Schema Location @@ -257,20 +257,20 @@ Using the Java DSL, you can configure it in the following way: ._Java-only: Java programmatic data format configuration_ [source,java] -------------------------------------------------------------------- +---- JaxbDataFormat jaxbDataFormat = new JaxbDataFormat(); jaxbDataFormat.setContextPath(Person.class.getPackage().getName()); jaxbDataFormat.setSchemaLocation("schema/person.xsd"); -------------------------------------------------------------------- +---- You can do the same using the XML DSL: [source,xml] --------------------------------------------------------- +---- --------------------------------------------------------- +---- === Marshal data that is already XML @@ -292,13 +292,13 @@ If you use Maven, you could add the following to your `pom.xml`, substituting the version number for the latest & greatest release. [source,xml] -------------------------------------- +---- org.apache.camel camel-jaxb x.x.x -------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jcache/src/main/docs/jcache-component.adoc b/components/camel-jcache/src/main/docs/jcache-component.adoc index fbba3462b6ebe..268bae562d963 100644 --- a/components/camel-jcache/src/main/docs/jcache-component.adoc +++ b/components/camel-jcache/src/main/docs/jcache-component.adoc @@ -18,9 +18,9 @@ The JCache component enables you to perform caching operations using JSR107/JCac == URI Format ----------------------------- +---- jcache:cacheName[?options] ----------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -76,7 +76,7 @@ and used here. Or it's possible to use the standard Caching API as below: ._Java-only: Java programmatic cache configuration with JCachePolicy_ [source,java] ----------------------------- +---- MutableConfiguration configuration = new MutableConfiguration<>(); configuration.setTypes(String.class, Object.class); configuration.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.MINUTES, 60))); @@ -90,7 +90,7 @@ from("direct:get-orders") .policy(jcachePolicy) .log("Getting order with id: ${body}") .bean(OrderService.class,"findOrderById(${body})"); ----------------------------- +---- === Set cacheManager @@ -100,7 +100,7 @@ If the cache does not exist, it will create a new one using the `cacheConfigurat ._Java-only: Java programmatic CacheManager configuration_ [source,java] ----------------------------- +---- //In a Spring environment, for example, the CacheManager may already exist as a bean @Autowire CacheManager cacheManager; @@ -110,7 +110,7 @@ CacheManager cacheManager; JCachePolicy jcachePolicy = new JCachePolicy(); jcachePolicy.setCacheManager(cacheManager); jcachePolicy.setCacheName("items") ----------------------------- +---- === Find cacheManager @@ -121,13 +121,13 @@ If `cacheManager` (and the `cache`) is not set, the policy will try to find a JC ._Java-only: Java DSL with JCachePolicy_ [source,java] ----------------------------- +---- //A Cache "getorders" will be used (or created) from the found CacheManager from("direct:get-orders").routeId("getorders") .policy(new JCachePolicy()) .log("Getting order with id: ${body}") .bean(OrderService.class,"findOrderById(${body})"); ----------------------------- +---- === Partially wrapped route @@ -136,7 +136,7 @@ A policy can be used to wrap only a segment of the route instead of all processo ._Java-only: Java DSL with partial JCachePolicy wrapping_ [source,java] ----------------------------- +---- from("direct:get-orders") .log("Order requested: ${body}") .policy(new JCachePolicy()) @@ -144,7 +144,7 @@ from("direct:get-orders") .bean(OrderService.class,"findOrderById(${body})") .end() .log("Order found: ${body}"); ----------------------------- +---- The `.log()` at the beginning and at the end of the route is always called, but the section inside `.policy()` and `.end()` is executed based on the cache. @@ -160,7 +160,7 @@ this _key_ is used to store the _value_ in cache at the end of the route. ._Java-only: Java programmatic JCachePolicy with keyExpression_ [source,java] ----------------------------- +---- MutableConfiguration configuration = new MutableConfiguration<>(); configuration.setTypes(String.class, Order.class); configuration.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.MINUTES, 10))); @@ -175,7 +175,7 @@ from("direct:get-orders") .policy(jcachePolicy) .log("Getting order with id: ${header.orderId}") .bean(OrderService.class,"findOrderById(${header.orderId})"); ----------------------------- +---- === BypassExpression @@ -191,7 +191,7 @@ In Camel XML DSL, we need a named reference to the JCachePolicy instance (regist We have to wrap the route between `...` tags after ``. [source,xml] ----------------------------- +---- @@ -202,12 +202,12 @@ We have to wrap the route between `...` tags after ``. ----------------------------- +---- See this example when only a part of the route is wrapped: [source,xml] ----------------------------- +---- @@ -221,7 +221,7 @@ See this example when only a part of the route is wrapped: ----------------------------- +---- === Define CachePolicy in Spring @@ -230,7 +230,7 @@ It's more convenient to create a JCachePolicy in Java, especially within a Route but see this example to define it in a Spring XML: [source,xml] ----------------------------- +---- @@ -239,7 +239,7 @@ but see this example to define it in a Spring XML: ----------------------------- +---- === Create Cache from XML @@ -247,7 +247,7 @@ It's not strictly speaking related to Camel XML DSL, but JCache providers usuall For example with Hazelcast, you can add a `hazelcast.xml` to classpath to configure the cache "spring" used in the example above. [source,xml] ----------------------------- +---- @@ -261,7 +261,7 @@ For example with Hazelcast, you can add a `hazelcast.xml` to classpath to config ----------------------------- +---- === Special scenarios and error handling diff --git a/components/camel-jgroups-raft/src/main/docs/jgroups-raft-component.adoc b/components/camel-jgroups-raft/src/main/docs/jgroups-raft-component.adoc index b59f204483233..dcb285b75b50d 100644 --- a/components/camel-jgroups-raft/src/main/docs/jgroups-raft-component.adoc +++ b/components/camel-jgroups-raft/src/main/docs/jgroups-raft-component.adoc @@ -21,20 +21,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component. [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-jgroups-raft x.y.z ------------------------------------------------------------- +---- == URI format ------------------------------ +---- jgroups-raft:clusterName[?options] ------------------------------ +---- Where *clusterName* represents the name of the JGroups-raft cluster, the component should connect to. @@ -177,7 +177,7 @@ address` http://localhost:8080/orders`. ._Java-only: programmatic JGroupsRaftClusterService configuration_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------------------------------ +---- JGroupsRaftClusterService service = new JGroupsRaftClusterService(); service.setId("raftId"); service.setRaftId("raftId"); @@ -186,7 +186,7 @@ service.setJgroupsClusterName("clusterName"); context.addService(service); from("master:mycluster:jetty:http://localhost:8080/orders").to("jms:orders"); ------------------------------------------------------------------------------------------------------------------------------------------------------------------ +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jgroups/src/main/docs/jgroups-component.adoc b/components/camel-jgroups/src/main/docs/jgroups-component.adoc index 03a1b99a3bec9..9514ce67cf965 100644 --- a/components/camel-jgroups/src/main/docs/jgroups-component.adoc +++ b/components/camel-jgroups/src/main/docs/jgroups-component.adoc @@ -22,20 +22,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component. [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-jgroups x.y.z ------------------------------------------------------------- +---- == URI format ------------------------------ +---- jgroups:clusterName[?options] ------------------------------ +---- Where *clusterName* represents the name of the JGroups cluster, the component should connect to. @@ -138,13 +138,13 @@ node. ._Java-only: Java static import and filter EIP_ [source,java] ----------------------------------------------------------------------------------------- +---- import static org.apache.camel.component.jgroups.JGroupsFilters.dropNonCoordinatorViews; ... from("jgroups:clusterName?enableViewMessages=true"). filter(dropNonCoordinatorViews()). to("seda:masterNodeEventsQueue"); ----------------------------------------------------------------------------------------- +---- === Predefined expressions @@ -171,7 +171,7 @@ cluster. ._Java-only: Java static imports with conditional delay expression_ [source,java] ------------------------------------------------------------------------------------------------------------------------------------------------------------------ +---- import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.camel.component.jgroups.JGroupsExpressions.delayIfContextNotStarted; import static org.apache.camel.component.jgroups.JGroupsFilters.dropNonCoordinatorViews; @@ -182,7 +182,7 @@ from("jgroups:clusterName?enableViewMessages=true"). to("controlbus:route?routeId=masterRoute&action=start&async=true"); from("timer://master?repeatCount=1").routeId("masterRoute").autoStartup(false).to(masterMockUri); ------------------------------------------------------------------------------------------------------------------------------------------------------------------ +---- == Examples @@ -193,11 +193,11 @@ just as demonstrated in the snippet below. ._Java-only: Java test API (ProducerTemplate)_ [source,java] ------------------------------------------------- +---- from("direct:start").to("jgroups:myCluster"); ... producerTemplate.sendBody("direct:start", "msg") ------------------------------------------------- +---- To receive the message from the snippet above (on the same, or the other physical machine), listen to the messages coming from the given cluster, @@ -205,14 +205,14 @@ just as demonstrated on the code fragment below. ._Java-only: Java test API (MockEndpoint assertions)_ [source,java] ------------------------------------------------------------- +---- mockEndpoint.setExpectedMessageCount(1); mockEndpoint.message(0).body().isEqualTo("msg"); ... from("jgroups:myCluster").to("mock:messagesFromTheCluster"); ... mockEndpoint.assertIsSatisfied(); ------------------------------------------------------------- +---- === Receive cluster view change notifications @@ -222,11 +222,11 @@ default, the endpoint consumes only regular messages. ._Java-only: Java test API (MockEndpoint assertions)_ [source,java] ---------------------------------------------------------------------- +---- mockEndpoint.setExpectedMessageCount(1); mockEndpoint.message(0).body().isInstanceOf(org.jgroups.View.class); ... from("jgroups:clusterName?enableViewMessages=true").to(mockEndpoint); ... mockEndpoint.assertIsSatisfied(); ---------------------------------------------------------------------- +---- diff --git a/components/camel-jms/src/main/docs/jms-component.adoc b/components/camel-jms/src/main/docs/jms-component.adoc index 9fb1cc18c6fae..a9cfcff983d5d 100644 --- a/components/camel-jms/src/main/docs/jms-component.adoc +++ b/components/camel-jms/src/main/docs/jms-component.adoc @@ -24,14 +24,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-jms x.x.x ------------------------------------------------------------- +---- [TIP] ==== @@ -64,31 +64,31 @@ environments. == URI format --------------------------------------------- +---- jms:[queue:|topic:]destinationName[?options] --------------------------------------------- +---- Where `destinationName` is a JMS queue or topic name. By default, the `destinationName` is interpreted as a queue name. For example, to connect to the queue, `FOO.BAR` use: ------------ +---- jms:FOO.BAR ------------ +---- You can include the optional `queue:` prefix, if you prefer: ------------------ +---- jms:queue:FOO.BAR ------------------ +---- To connect to a topic, you _must_ include the `topic:` prefix. For example, to + connect to the topic, `Stocks.Prices`, use: ------------------------ +---- jms:topic:Stocks.Prices ------------------------ +---- You append query options to the URI by using the following format, `?option=value&option=value&...` @@ -369,10 +369,10 @@ demo below illustrates this: ._Java-only: `errorHandler` configuration is Java DSL specific_ [source,java] ------------------------------------------------------------------------- +---- // setup error handler to use JMS as queue and store the entire Exchange errorHandler(deadLetterChannel("jms:queue:dead?transferExchange=true")); ------------------------------------------------------------------------- +---- Then you can consume from the JMS queue and analyze the problem: @@ -412,12 +412,12 @@ And in the `myErrorAnalyzer` bean: ._Java-only: programmatic access to exchange properties and exception_ [source,java] ------------------------------------------------------------------------------------ +---- String body = exchange.getIn().getBody(); Exception cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class); // the cause message is String problem = cause.getMessage(); ------------------------------------------------------------------------------------ +---- === Using JMS as a Dead Letter Channel storing error only @@ -429,13 +429,13 @@ xref:jms-component.adoc[JMS] dead letter queue: ._Java-only: `errorHandler` and `exceptionMessage()` are Java DSL specific_ [source,java] --------------------------------------------------------------------------------------------------- +---- // we sent it to a seda dead queue first errorHandler(deadLetterChannel("seda:dead")); // and on the seda dead queue we can do the custom transformation before its sent to the JMS queue from("seda:dead").transform(exceptionMessage()).to("jms:queue:dead"); --------------------------------------------------------------------------------------------------- +---- Here we only store the original cause error message in the transform. You can, however, use any Expression to send @@ -590,9 +590,9 @@ the header with the key `CamelJmsMessageType`. For example: ._Java-only: uses the `JmsMessageType` enum which requires Java code_ [source,java] ---------------------------------------------------------------------------------------------------------- +---- from("file://inbox/order").setHeader("CamelJmsMessageType", JmsMessageType.Text).to("jms:queue:order"); ---------------------------------------------------------------------------------------------------------- +---- The possible values are defined in the `enum` class, `org.apache.camel.jms.JmsMessageType`. @@ -629,10 +629,10 @@ For the `exchange.in.header`, the following rules apply for the header Camel will log with category `org.apache.camel.component.jms.JmsBinding` at *DEBUG* level if it drops a given header value. For example: ----------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- 2008-07-09 06:43:04,046 [main ] DEBUG JmsBinding - Ignoring non primitive header: order of class: org.apache.camel.component.jms.issues.DummyOrder with value: DummyOrder{orderId=333, itemId=4444, quantity=2} ----------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- === Message format when receiving @@ -854,12 +854,12 @@ setting the `CamelJmsDestinationName` header as follows: ._Java-only: bean method that sets the destination header programmatically_ [source,java] -------------------------------------------------------------------------- +---- public void setJmsHeader(Exchange exchange) { String id = .... exchange.getIn().setHeader("CamelJmsDestinationName", "order:" + id); } -------------------------------------------------------------------------- +---- Then Camel will read this header and use it as the destination instead of the one configured on the endpoint. So, in this example Camel sends @@ -902,13 +902,13 @@ mechanism in Spring. You can do this using Spring's factory bean or the new Spring XML namespace. For example: [source,xml] ------------------------------------------------------------------------------ +---- ------------------------------------------------------------------------------ +---- See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/xsd-config.html#xsd-config-body-schemas-jee[The @@ -1090,12 +1090,12 @@ this in Camel as shown below: ._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] -------------------------------------------------------- +---- from(xxx) .inOut().to("activemq:queue:foo?concurrentConsumers=5") .to(yyy) .to(zzz); -------------------------------------------------------- +---- In this route, we instruct Camel to route replies asynchronously using a thread pool with five threads. @@ -1108,11 +1108,11 @@ below, then pay attention. ._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] ---------------------------------------------- +---- from(xxx) .inOut().to("activemq:queue:foo?replyTo=bar") .to(yyy) ---------------------------------------------- +---- In this example, the fixed reply queue named "bar" is used. By default, Camel assumes the queue is shared when using fixed reply queues, and @@ -1126,11 +1126,11 @@ as shown: ._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] ----------------------------------------------------------------- +---- from(xxx) .inOut().to("activemq:queue:foo?replyTo=bar&receiveTimeout=250") .to(yyy) ----------------------------------------------------------------- +---- Notice this will cause the Camel to send pull requests to the message broker more frequently, and thus require more network traffic. + @@ -1154,11 +1154,11 @@ below: ._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] -------------------------------------------------------------------- +---- from(xxx) .inOut().to("activemq:queue:foo?replyTo=bar&replyToType=Exclusive") .to(yyy) -------------------------------------------------------------------- +---- Mind that the queue must be exclusive to each and every endpoint. So if you have two routes, then they each need a unique reply queue as shown @@ -1166,7 +1166,7 @@ in the next example: ._Java-only: uses `inOut()` Java DSL method for request-reply pattern_ [source,java] ------------------------------------------------------------------------------ +---- from(xxx) .inOut().to("activemq:queue:foo?replyTo=bar&replyToType=Exclusive") .to(yyy) @@ -1174,7 +1174,7 @@ from(xxx) from(aaa) .inOut().to("activemq:queue:order?replyTo=order.reply&replyToType=Exclusive") .to(bbb) ------------------------------------------------------------------------------ +---- The same applies if you run in a clustered environment. Then each node in the cluster must use a unique reply queue name. As otherwise, each @@ -1392,20 +1392,20 @@ the value of the ReplyTo `javax.jms.Destination` object, having the key ._Java-only: uses JMS `Destination` object and Camel Java API_ [source,java] ------------------------------------------------------------------------------------------------------------------ +---- Destination replyDestination = exchange.getIn().getHeader("JMSReplyTo", Destination.class); ------------------------------------------------------------------------------------------------------------------ +---- And then later use it to send a reply using regular JMS or Camel. ._Java-only: uses `JmsEndpoint` and `ProducerTemplate` Java API_ [source,java] ----------------------------------------------------------------------------------------- +---- // we need to pass in the JMS component, and in this sample we use ActiveMQ JmsEndpoint endpoint = JmsEndpoint.newInstance(replyDestination, activeMQComponent); // now we have the endpoint we can use regular Camel API to send a message to it template.sendBody(endpoint, "Here is the late reply."); ----------------------------------------------------------------------------------------- +---- A different solution to sending a reply is to provide the `replyDestination` object in the same Exchange property when sending. @@ -1415,14 +1415,14 @@ For example: ._Java-only: uses `ProducerTemplate` and `Processor` to set the JMS destination object programmatically_ [source,java] ----------------------------------------------------------------------------------------------------------------------------------------- +---- // we pretend to send it to some non-existing dummy queue template.send("activemq:queue:dummy", exchange -> { // and here we override the destination with the ReplyTo destination object so the message is sent to there instead of dummy exchange.getIn().setHeader("CamelJmsDestination", replyDestination); exchange.getIn().setBody("Here is the late reply."); }); ----------------------------------------------------------------------------------------------------------------------------------------- +---- === Using a request timeout @@ -1445,12 +1445,12 @@ For example, to send an `InOnly` message to the foo queue, but with a ._Java-only: uses `ProducerTemplate` test API to send with custom JMS headers_ [source,java] -------------------------------------------------------------------------------------- +---- template.send("activemq:queue:foo?preserveMessageQos=true", exchange -> { exchange.getIn().setBody("World"); exchange.getIn().setHeader("JMSReplyTo", "bar"); }); -------------------------------------------------------------------------------------- +---- Notice we use `preserveMessageQos=true` to instruct Camel to keep the `JMSReplyTo` header. @@ -1503,24 +1503,24 @@ YAML:: Some versions of WMQ won't accept this option on the destination name, and you will get an exception like: ----------------------------------------------------------------------------------------------------------------------------------- +---- com.ibm.msg.client.jms.DetailedJMSException: JMSCC0005: The specified value 'MY_QUEUE?targetClient=1' is not allowed for 'XMSC_DESTINATION_NAME' ----------------------------------------------------------------------------------------------------------------------------------- +---- A workaround is to use a custom DestinationResolver: ._Java-only: programmatic JMS component configuration with custom `DestinationResolver`_ [source,java] ----------------------------------------------------------------------------------------------------------------------------------- +---- JmsComponent wmq = new JmsComponent(connectionFactory); wmq.setDestinationResolver((session, destinationName, pubSubDomain) -> { MQQueueSession wmqSession = (MQQueueSession) session; return wmqSession.createQueue("queue:///" + destinationName + "?targetClient=1"); }); ----------------------------------------------------------------------------------------------------------------------------------- +---- diff --git a/components/camel-jpa/src/main/docs/jpa-component.adoc b/components/camel-jpa/src/main/docs/jpa-component.adoc index e5b485af8ad84..51df757c9ae30 100644 --- a/components/camel-jpa/src/main/docs/jpa-component.adoc +++ b/components/camel-jpa/src/main/docs/jpa-component.adoc @@ -23,20 +23,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-jpa x.x.x ------------------------------------------------------------- +---- == URI format ------------------------------ +---- jpa:entityClassName[?options] ------------------------------ +---- For sending to the endpoint, the _entityClassName_ is optional. If specified, it helps the http://camel.apache.org/type-converter.html[Type Converter] to @@ -112,11 +112,11 @@ For example, you can instantiate a JPA component that references the `myEMFactory` entity manager factory, as follows: [source,xml] -------------------------------------------------------------------- +---- -------------------------------------------------------------------- +---- The `JpaComponent` looks up automatically the `EntityManagerFactory` from the Registry which means @@ -145,12 +145,12 @@ explicitly configure a JPA component that references the `myTransactionManager` transaction manager, as follows: [source,xml] -------------------------------------------------------------------- +---- -------------------------------------------------------------------- +---- === Using a consumer with a named query @@ -160,13 +160,13 @@ named query in the JPA Entity class: ._Java-only: JPA entity class definition with @NamedQuery annotation_ [source,java] ----------------------------------------------------------------------------------- +---- @Entity @NamedQuery(name = "step1", query = "select x from MultiSteps x where x.step = 1") public class MultiSteps { ... } ----------------------------------------------------------------------------------- +---- After that, you can define a consumer uri like this one: @@ -298,13 +298,13 @@ named query in the JPA Entity class: ._Java-only: JPA entity class definition with @NamedQuery annotation_ [source,java] ----------------------------------------------------------------------------------- +---- @Entity @NamedQuery(name = "step1", query = "select x from MultiSteps x where x.step = 1") public class MultiSteps { ... } ----------------------------------------------------------------------------------- +---- After that, you can define a producer uri like this one: @@ -454,7 +454,7 @@ Index: 20, Size: 20 . Create the JPA idempotent repository in the Spring XML file: [source,xml] ---------------------------------------------------------------- +---- @@ -464,7 +464,7 @@ Index: 20, Size: 20 ---------------------------------------------------------------- +---- == Important Development Notes @@ -472,7 +472,7 @@ If you run the https://github.com/apache/camel/tree/main/components/camel-jpa/src/test[tests of this component] directly inside your IDE, and not through Maven, then you could see exceptions like these: --------------------------------------------------------------------------------------------------------------------------------------------------------- +---- org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is org.apache.openjpa.persistence.ArgumentException: This configuration disallows runtime optimization, but the following listed types were not enhanced at build time or at class load time with a javaagent: "org.apache.camel.examples.SendEmail". @@ -483,7 +483,7 @@ but the following listed types were not enhanced at build time or at class load at org.apache.camel.processor.jpa.JpaRouteTest.createCamelContext(JpaRouteTest.java:67) at org.apache.camel.test.junit6.CamelTestSupport.doSetUp(CamelTestSupport.java:238) at org.apache.camel.test.junit6.CamelTestSupport.setUp(CamelTestSupport.java:208) --------------------------------------------------------------------------------------------------------------------------------------------------------- +---- The problem here is that the source has been compiled or recompiled through your IDE and not through Maven, which would @@ -495,9 +495,9 @@ OpenJPA version being used in Camel is 2.2.1, to run the tests inside your IDE, you would need to pass the following argument to the JVM: -------------------------------------------------------------------------------------------- +---- -javaagent:/org/apache/openjpa/openjpa/2.2.1/openjpa-2.2.1.jar -------------------------------------------------------------------------------------------- +---- diff --git a/components/camel-jq/src/main/docs/jq-language.adoc b/components/camel-jq/src/main/docs/jq-language.adoc index b0742d1289b2a..3f7568c884ba3 100644 --- a/components/camel-jq/src/main/docs/jq-language.adoc +++ b/components/camel-jq/src/main/docs/jq-language.adoc @@ -214,12 +214,12 @@ YAML:: If you use Maven you could just add the following to your `pom.xml`, substituting the version number for the latest and greatest release (see the download page for the latest versions). [source,xml] ---------------------------------------- +---- org.apache.camel camel-jq x.x.x ---------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jsch/src/main/docs/scp-component.adoc b/components/camel-jsch/src/main/docs/scp-component.adoc index 12f5625ba1789..f162d5f11fa1c 100644 --- a/components/camel-jsch/src/main/docs/scp-component.adoc +++ b/components/camel-jsch/src/main/docs/scp-component.adoc @@ -24,20 +24,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-jsch x.x.x ------------------------------------------------------------- +---- == URI format ---------------------------------------- +---- scp://host[:port]/destination[?options] ---------------------------------------- +---- The file name can be specified either in the part of the URI or as a "CamelFileName" header on the message (`Exchange.FILE_NAME` if used diff --git a/components/camel-jsonata/src/main/docs/jsonata-component.adoc b/components/camel-jsonata/src/main/docs/jsonata-component.adoc index ddce4b8416255..2d3f0327b4d5b 100644 --- a/components/camel-jsonata/src/main/docs/jsonata-component.adoc +++ b/components/camel-jsonata/src/main/docs/jsonata-component.adoc @@ -22,21 +22,21 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-jsonata x.x.x ------------------------------------------------------------- +---- == URI format ------------------------ +---- jsonata:specName[?options] ------------------------ +---- Where *specName* is the classpath-local URI of the specification to invoke; or the complete URL of the remote specification @@ -178,7 +178,7 @@ A custom binding might look like the following: ._Java-only: implementing a custom JsonataFrameBinding_ [source,java] ---------------------------------------------------------------- +---- @NoArgsConstructor public class CustomJsonataFrameBinding implements JsonataFrameBinding { @Override @@ -186,6 +186,6 @@ public class CustomJsonataFrameBinding implements JsonataFrameBinding { frame.bind("env", (String s) -> System.getenv(s)); } } ---------------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-jt400/src/main/docs/jt400-component.adoc b/components/camel-jt400/src/main/docs/jt400-component.adoc index 341525daa94c0..014b03b823c59 100644 --- a/components/camel-jt400/src/main/docs/jt400-component.adoc +++ b/components/camel-jt400/src/main/docs/jt400-component.adoc @@ -22,34 +22,34 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-jt400 x.x.x ------------------------------------------------------------- +---- == URI format To send or receive data from a data queue ----------------------------------------------------------------------- +---- jt400://user:password/system/QSYS.LIB/library.LIB/queue.DTAQ[?options] ----------------------------------------------------------------------- +---- To send or receive messages from a message queue ----------------------------------------------------------------------- +---- jt400://user:password/system/QSYS.LIB/library.LIB/queue.MSGQ[?options] ----------------------------------------------------------------------- +---- To call program ------------------------------------------------------------------------ +---- jt400://user:password/system/QSYS.LIB/library.LIB/program.PGM[?options] ------------------------------------------------------------------------ +---- // component options: START @@ -109,7 +109,7 @@ from the data queue and forward it to the `mock:ringo` endpoint. ._Java-only: RouteBuilder class definition_ [source,java] -------------------------------------------------------------------------------------------------------- +---- public class Jt400RouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { @@ -117,7 +117,7 @@ public class Jt400RouteBuilder extends RouteBuilder { from(“jt400://RINGO:OGNIR@LIVERPOOL/QSYS.LIB/BEATLES.LIB/PENNYLANE.DTAQ”).to(“mock:ringo”); } } -------------------------------------------------------------------------------------------------------- +---- === Program call examples @@ -129,21 +129,21 @@ sent to the direct:play endpoint. ._Java-only: RouteBuilder class definition_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------------------------------- +---- public class Jt400RouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { from(“direct:work”).to(“jt400://GRUPO:ATWORK@server/QSYS.LIB/assets.LIB/compute.PGM?fieldsLength=10,10,512&ouputFieldsIdx=2,3”).to(“direct:play”); } } ---------------------------------------------------------------------------------------------------------------------------------------------------------- +---- In this example, the camel route will call the QUSRTVUS API to retrieve 16 bytes from data area “MYUSRSPACE” in the “MYLIB” library. ._Java-only: RouteBuilder class definition with lambda expression_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------------------------------- +---- public class Jt400RouteBuilder extends RouteBuilder { @Override public void configure() throws Exception { @@ -163,7 +163,7 @@ public class Jt400RouteBuilder extends RouteBuilder { .to(“direct:foo”); } } ---------------------------------------------------------------------------------------------------------------------------------------------------------- +---- === Writing to keyed data queues @@ -315,7 +315,7 @@ YAML:: ._Java-only: uses Java constants, lambda expression, and choice with header() predicate_ [source,java] -------------------------------------------------------------------------------------------------------- +---- from("jt400://username:password@localhost/qsys.lib/qusrsys.lib/myq.msgq?sendingReply=true") .choice() .when(header(Jt400Constants.MESSAGE_TYPE).isEqualTo(AS400Message.INQUIRY)) @@ -324,7 +324,7 @@ from("jt400://username:password@localhost/qsys.lib/qusrsys.lib/myq.msgq?sendingR exchange.getIn().setBody(reply); }) .to("jt400://username:password@localhost/qsys.lib/qusrsys.lib/myq.msgq"); -------------------------------------------------------------------------------------------------------- +---- diff --git a/components/camel-jte/src/main/docs/jte-component.adoc b/components/camel-jte/src/main/docs/jte-component.adoc index 27e18a93f2519..f5f92e798d01b 100644 --- a/components/camel-jte/src/main/docs/jte-component.adoc +++ b/components/camel-jte/src/main/docs/jte-component.adoc @@ -26,19 +26,19 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] -------------------------------------------------------------------------------------- +---- org.apache.camel camel-jte x.x.x -------------------------------------------------------------------------------------- +---- == URI format ---------------------------------- +---- jte:templateName[?options] ---------------------------------- +---- Where *templateName* is the classpath-local URI of the template to invoke; or the complete URL of the remote template (e.g.: diff --git a/components/camel-kafka/src/main/docs/kafka-component.adoc b/components/camel-kafka/src/main/docs/kafka-component.adoc index e4a2d1e3e3a54..6d0cb71013ccf 100644 --- a/components/camel-kafka/src/main/docs/kafka-component.adoc +++ b/components/camel-kafka/src/main/docs/kafka-component.adoc @@ -21,21 +21,21 @@ Maven users will need to add the following dependency to their `pom.xml` for this component. [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-kafka x.x.x ------------------------------------------------------------- +---- == URI format ---------------------------- +---- kafka:topic[?options] ---------------------------- +---- // component options: START diff --git a/components/camel-keycloak/src/main/docs/keycloak-component.adoc b/components/camel-keycloak/src/main/docs/keycloak-component.adoc index 208e418271cf4..7311095a1e25a 100644 --- a/components/camel-keycloak/src/main/docs/keycloak-component.adoc +++ b/components/camel-keycloak/src/main/docs/keycloak-component.adoc @@ -26,9 +26,9 @@ The Keycloak component provides two main functionalities: == URI Format -------------------------- +---- keycloak://label[?options] -------------------------- +---- You can append query options to the URI in the following format: diff --git a/components/camel-knative/camel-knative-component/src/main/docs/knative-component.adoc b/components/camel-knative/camel-knative-component/src/main/docs/knative-component.adoc index 527f5db1a77f1..8d4e51076d5c3 100644 --- a/components/camel-knative/camel-knative-component/src/main/docs/knative-component.adoc +++ b/components/camel-knative/camel-knative-component/src/main/docs/knative-component.adoc @@ -20,14 +20,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component. [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-knative x.x.x ------------------------------------------------------------- +---- == URI format @@ -39,9 +39,9 @@ knative:type/name[?options] You can append query options to the URI in the following format: [source,text] ------------------------------------------------------------- +---- ?option=value&option=value&... ------------------------------------------------------------- +---- == Options @@ -68,7 +68,7 @@ To do so, the component needs a so called `Knative Environment`, which is essenc .Example [source,json] ------------------------------------------------------------- +---- { "services": [ { @@ -84,7 +84,7 @@ To do so, the component needs a so called `Knative Environment`, which is essenc } ] } ------------------------------------------------------------- +---- <1> the type of the Knative resource <2> the name of the resource <3> the url of the service to invoke (for producer only) diff --git a/components/camel-knative/camel-knative-http/src/main/docs/knative-http-component.adoc b/components/camel-knative/camel-knative-http/src/main/docs/knative-http-component.adoc index 81b008bb9e785..6c47bf7e6f672 100644 --- a/components/camel-knative/camel-knative-http/src/main/docs/knative-http-component.adoc +++ b/components/camel-knative/camel-knative-http/src/main/docs/knative-http-component.adoc @@ -20,14 +20,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component. [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-knative-http x.x.x ------------------------------------------------------------- +---- == Knative Http producer factory diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-config-maps-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-config-maps-component.adoc index c5ea3e27deee9..9bba8f56431b2 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-config-maps-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-config-maps-component.adoc @@ -141,7 +141,7 @@ This operation returns a List of ConfigMaps from your cluster, using a label sel ._Java-only: consuming ConfigMap events with a custom processor_ [source,java] --------------------------------------------------------------------------------- +---- fromF("kubernetes-config-maps://%s?oauthToken=%s", host, authToken) .process(new KubernetesProcessor()).to("mock:result"); @@ -153,7 +153,7 @@ fromF("kubernetes-config-maps://%s?oauthToken=%s", host, authToken) log.info("Got event with configmap name: " + cm.getMetadata().getName() + " and action " + in.getHeader(KubernetesConstants.KUBERNETES_EVENT_ACTION)); } } --------------------------------------------------------------------------------- +---- This consumer returns a message per event received for all ConfigMaps from all namespaces in the cluster. diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-deployments-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-deployments-component.adoc index 2e0dc494859e4..ff1e167376cc4 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-deployments-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-deployments-component.adoc @@ -44,11 +44,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses toF() for endpoint URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-deployments:///?kubernetesClient=#kubernetesClient&operation=listDeployments"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a List of Deployment from your cluster @@ -56,7 +56,7 @@ This operation returns a List of Deployment from your cluster ._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -68,7 +68,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-deployments:///?kubernetesClient=#kubernetesClient&operation=listDeploymentsByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a List of Deployments from your cluster, using a label selector (with key1 and key2, with value value1 and value2) @@ -76,7 +76,7 @@ This operation returns a List of Deployments from your cluster, using a label se ._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] --------------------------------------------------------------------------------- +---- fromF("kubernetes-deployments://%s?oauthToken=%s", host, authToken) .process(new KubernetesProcessor()).to("mock:result"); @@ -88,7 +88,7 @@ fromF("kubernetes-deployments://%s?oauthToken=%s", host, authToken) log.info("Got event with deployment name: " + dp.getMetadata().getName() + " and action " + in.getHeader(KubernetesConstants.KUBERNETES_EVENT_ACTION)); } } --------------------------------------------------------------------------------- +---- This consumer returns a message per event received for all Deployments from all namespaces in the cluster. diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-events-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-events-component.adoc index b03273a6a22b0..94506c6d1e43a 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-events-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-events-component.adoc @@ -90,7 +90,7 @@ To indicate from which namespace, the events are expected, it is possible to set ._Java-only: using a Processor to set label headers on the exchange_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override @@ -103,7 +103,7 @@ from("direct:listByLabels").process(new Processor() { }); to("kubernetes-events:///?kubernetesClient=#kubernetesClient&operation=listEventsByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of events from your cluster that occurred in any namespaces, using a label selector (in the example above only expect events which have the label "key1" set to "value1" and the label "key2" set to "value2"). The type of the events is `io.fabric8.kubernetes.api.model.events.v1.Event`. @@ -113,7 +113,7 @@ This operation expects the message header `CamelKubernetesEventsLabels` to be se ._Java-only: using a Processor to set namespace and event name headers_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:get").process(new Processor() { @Override @@ -124,7 +124,7 @@ from("direct:get").process(new Processor() { }); to("kubernetes-events:///?kubernetesClient=#kubernetesClient&operation=getEvent"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns the event matching the criteria from your cluster. The type of the event is `io.fabric8.kubernetes.api.model.events.v1.Event`. @@ -136,7 +136,7 @@ If no matching event could be found, `null` is returned. ._Java-only: using a Processor to set event headers for creation_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:get").process(new Processor() { @Override @@ -155,7 +155,7 @@ from("direct:get").process(new Processor() { }); to("kubernetes-events:///?kubernetesClient=#kubernetesClient&operation=createEvent"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation publishes a new event in your cluster. An event can be created in two ways either from message headers or directly from an `io.fabric8.kubernetes.api.model.events.v1.EventBuilder`. @@ -176,7 +176,7 @@ The behavior is exactly the same as `createEvent`, only the name of the operatio ._Java-only: using a Processor to set namespace and event name headers_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:get").process(new Processor() { @Override @@ -187,7 +187,7 @@ from("direct:get").process(new Processor() { }); to("kubernetes-events:///?kubernetesClient=#kubernetesClient&operation=deleteEvent"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation removes an existing event from your cluster. It returns a `boolean` to indicate whether the operation was successful or not. @@ -197,7 +197,7 @@ This operation expects two message headers which are `CamelKubernetesNamespaceNa ._Java-only: using fromF with parameters and a custom Processor to handle Event objects_ [source,java] --------------------------------------------------------------------------------- +---- fromF("kubernetes-events://%s?oauthToken=%s", host, authToken) .process(new KubernetesProcessor()).to("mock:result"); @@ -209,7 +209,7 @@ fromF("kubernetes-events://%s?oauthToken=%s", host, authToken) log.info("Got event with event name: " + e.getMetadata().getName() + " and action " + in.getHeader(KubernetesConstants.KUBERNETES_EVENT_ACTION)); } } --------------------------------------------------------------------------------- +---- This consumer returns a message per event received in the whole cluster. It also set the action (`io.fabric8.kubernetes.client.Watcher.Action`) in the message header `CamelKubernetesEventAction` and the timestamp (`long`) in the message header `CamelKubernetesEventTimestamp`. diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-hpa-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-hpa-component.adoc index 6953f2b36573a..81b4797d73c26 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-hpa-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-hpa-component.adoc @@ -43,11 +43,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses toF() for endpoint URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-hpa:///?kubernetesClient=#kubernetesClient&operation=listHPA"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of HPAs from your cluster @@ -55,7 +55,7 @@ This operation returns a list of HPAs from your cluster ._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -67,7 +67,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-hpa:///?kubernetesClient=#kubernetesClient&operation=listHPAByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a List of HPAs from your cluster using a label selector (with key1 and key2, with value value1 and value2) @@ -75,7 +75,7 @@ This operation returns a List of HPAs from your cluster using a label selector ( ._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] --------------------------------------------------------------------------------- +---- fromF("kubernetes-hpa://%s?oauthToken=%s", host, authToken) .process(new KubernetesProcessor()).to("mock:result"); @@ -87,7 +87,7 @@ fromF("kubernetes-hpa://%s?oauthToken=%s", host, authToken) log.info("Got event with hpa name: " + hpa.getMetadata().getName() + " and action " + in.getHeader(KubernetesConstants.KUBERNETES_EVENT_ACTION)); } } --------------------------------------------------------------------------------- +---- This consumer returns a message per event received for all HorizontalPodAutoscalers from all namespaces in the cluster. diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-job-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-job-component.adoc index e5c1e6da8baaa..8ae94b6e750fb 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-job-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-job-component.adoc @@ -44,11 +44,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses toF() for endpoint URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-job:///?kubernetesClient=#kubernetesClient&operation=listJob"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of jobs from your cluster @@ -56,7 +56,7 @@ This operation returns a list of jobs from your cluster ._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -68,7 +68,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-job:///?kubernetesClient=#kubernetesClient&operation=listJobByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of jobs from your cluster, using a label selector (with key1 and key2, with value value1 and value2) @@ -78,7 +78,7 @@ We have a wonderful example of this operation thanks to https://github.com/Emmer ._Java-only: full RouteBuilder class with KubernetesConstants, lambda Processors, and programmatic JobSpec construction_ [source,java] --------------------------------------------------------------------------------- +---- import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -172,7 +172,7 @@ public class KubernetesCreateJob extends RouteBuilder { return containers; } } --------------------------------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-namespaces-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-namespaces-component.adoc index 8cdbc7ddf54e9..48a67e3b6e289 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-namespaces-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-namespaces-component.adoc @@ -44,11 +44,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses toF() for endpoint URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-namespaces:///?kubernetesClient=#kubernetesClient&operation=listNamespaces"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of namespaces from your cluster @@ -56,7 +56,7 @@ This operation returns a list of namespaces from your cluster ._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -68,7 +68,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-namespaces:///?kubernetesClient=#kubernetesClient&operation=listNamespacesByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of namespaces from your cluster, using a label selector (with key1 and key2, with value value1 and value2) @@ -76,7 +76,7 @@ This operation returns a list of namespaces from your cluster, using a label sel ._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] --------------------------------------------------------------------------------- +---- fromF("kubernetes-namespaces://%s?oauthToken=%s", host, authToken) .process(new KubernetesProcessor()).to("mock:result"); @@ -88,7 +88,7 @@ fromF("kubernetes-namespaces://%s?oauthToken=%s", host, authToken) log.info("Got event with namespace name: " + ns.getMetadata().getName() + " and action " + in.getHeader(KubernetesConstants.KUBERNETES_EVENT_ACTION)); } } --------------------------------------------------------------------------------- +---- This consumer returns a message per event received for all Namespaces in the cluster. diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-nodes-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-nodes-component.adoc index ea6728dc2fde8..5881a9bd891f8 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-nodes-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-nodes-component.adoc @@ -45,11 +45,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses toF() for endpoint URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-nodes:///?kubernetesClient=#kubernetesClient&operation=listNodes"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a List of Nodes from your cluster @@ -57,7 +57,7 @@ This operation returns a List of Nodes from your cluster ._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -69,7 +69,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-deployments:///?kubernetesClient=#kubernetesClient&operation=listNodesByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of nodes from your cluster, using a label selector (with key1 and key2, with value value1 and value2) @@ -77,7 +77,7 @@ This operation returns a list of nodes from your cluster, using a label selector ._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] --------------------------------------------------------------------------------- +---- fromF("kubernetes-nodes://%s?oauthToken=%s", host, authToken) .process(new KubernetesProcessor()).to("mock:result"); @@ -89,7 +89,7 @@ fromF("kubernetes-nodes://%s?oauthToken=%s", host, authToken) log.info("Got event with node name: " + node.getMetadata().getName() + " and action " + in.getHeader(KubernetesConstants.KUBERNETES_EVENT_ACTION)); } } --------------------------------------------------------------------------------- +---- This consumer returns a message per event received for all Nodes in the cluster. diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc index f3136fa3f60ae..18addab658f8b 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-claims-component.adoc @@ -45,11 +45,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses `toF()` for URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-persistent-volumes-claims:///?kubernetesClient=#kubernetesClient&operation=listPersistentVolumesClaims"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of PVC from your cluster @@ -57,7 +57,7 @@ This operation returns a list of PVC from your cluster ._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -69,7 +69,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-persistent-volumes-claims:///?kubernetesClient=#kubernetesClient&operation=listPersistentVolumesClaimsByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of PVCs from your cluster using a label selector (with key1 and key2, with value value1 and value2) diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-component.adoc index 512e7cacf2485..c7fecfd3f5506 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-persistent-volumes-component.adoc @@ -42,11 +42,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses `toF()` for URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-persistent-volumes:///?kubernetesClient=#kubernetesClient&operation=listPersistentVolumes"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of PVs from your cluster @@ -54,7 +54,7 @@ This operation returns a list of PVs from your cluster ._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -66,7 +66,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-persistent-volumes:///?kubernetesClient=#kubernetesClient&operation=listPersistentVolumesByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of PVs from your cluster using a label selector (with key1 and key2, with value value1 and value2) diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-pods-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-pods-component.adoc index 979f8da521fdd..9190c205a3ee1 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-pods-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-pods-component.adoc @@ -45,11 +45,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses toF() for endpoint URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-pods:///?kubernetesClient=#kubernetesClient&operation=listPods"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of pods from your cluster @@ -57,7 +57,7 @@ This operation returns a list of pods from your cluster ._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -69,7 +69,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-pods:///?kubernetesClient=#kubernetesClient&operation=listPodsByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of pods from your cluster using a label selector (with key1 and key2, with value value1 and value2) @@ -77,7 +77,7 @@ This operation returns a list of pods from your cluster using a label selector ( ._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] --------------------------------------------------------------------------------- +---- fromF("kubernetes-pods://%s?oauthToken=%s", host, authToken) .process(new KubernetesProcessor()).to("mock:result"); public class KubernetesProcessor implements Processor { @@ -88,7 +88,7 @@ fromF("kubernetes-pods://%s?oauthToken=%s", host, authToken) log.info("Got event with pod name: " + pod.getMetadata().getName() + " and action " + in.getHeader(KubernetesConstants.KUBERNETES_EVENT_ACTION)); } } --------------------------------------------------------------------------------- +---- This consumer returns a message per event received for all Pods from all namespaces in the cluster. diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-replication-controllers-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-replication-controllers-component.adoc index 4bc5d7f421fb6..89c5e41e0c1cf 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-replication-controllers-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-replication-controllers-component.adoc @@ -47,11 +47,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses toF() for endpoint URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-replication-controllers:///?kubernetesClient=#kubernetesClient&operation=listReplicationControllers"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of RCs from your cluster @@ -59,7 +59,7 @@ This operation returns a list of RCs from your cluster ._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -71,7 +71,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-replication-controllers:///?kubernetesClient=#kubernetesClient&operation=listReplicationControllersByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of RCs from your cluster using a label selector (with key1 and key2, with value value1 and value2) @@ -79,7 +79,7 @@ This operation returns a list of RCs from your cluster using a label selector (w ._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] --------------------------------------------------------------------------------- +---- fromF("kubernetes-replication-controllers://%s?oauthToken=%s", host, authToken) .process(new KubernetesProcessor()).to("mock:result"); @@ -91,7 +91,7 @@ fromF("kubernetes-replication-controllers://%s?oauthToken=%s", host, authToken) log.info("Got event with replication controller name: " + rc.getMetadata().getName() + " and action " + in.getHeader(KubernetesConstants.KUBERNETES_EVENT_ACTION)); } } --------------------------------------------------------------------------------- +---- This consumer returns a message per event received for all ReplicationControllers from all namespaces in the cluster. diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-resources-quota-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-resources-quota-component.adoc index d02abadcb0681..a419fe25e1a1b 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-resources-quota-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-resources-quota-component.adoc @@ -45,11 +45,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses `toF()` for URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-resources-quota:///?kubernetesClient=#kubernetesClient&operation=listResourcesQuota"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of resource quotas from your cluster @@ -57,7 +57,7 @@ This operation returns a list of resource quotas from your cluster ._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -69,7 +69,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-resources-quota:///?kubernetesClient=#kubernetesClient&operation=listResourcesQuotaByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of resource quotas from your cluster using a label selector (with key1 and key2, with value value1 and value2) diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-service-accounts-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-service-accounts-component.adoc index 8ada83af537ff..c895c61b46c20 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-service-accounts-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-service-accounts-component.adoc @@ -45,11 +45,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses `toF()` for URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-service-accounts:///?kubernetesClient=#kubernetesClient&operation=listServiceAccounts"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of services from your cluster @@ -57,7 +57,7 @@ This operation returns a list of services from your cluster ._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -69,7 +69,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-service-accounts:///?kubernetesClient=#kubernetesClient&operation=listServiceAccountsByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of services from your cluster using a label selector (with key1 and key2, with value value1 and value2) diff --git a/components/camel-kubernetes/src/main/docs/kubernetes-services-component.adoc b/components/camel-kubernetes/src/main/docs/kubernetes-services-component.adoc index 2917956e5e7a5..c27964e59bb3f 100644 --- a/components/camel-kubernetes/src/main/docs/kubernetes-services-component.adoc +++ b/components/camel-kubernetes/src/main/docs/kubernetes-services-component.adoc @@ -44,11 +44,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses toF() for endpoint URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("kubernetes-services:///?kubernetesClient=#kubernetesClient&operation=listServices"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a List of services from your cluster @@ -56,7 +56,7 @@ This operation returns a List of services from your cluster ._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -68,7 +68,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("kubernetes-services:///?kubernetesClient=#kubernetesClient&operation=listServicesByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of services from your cluster using a label selector (with key1 and key2, with value value1 and value2) @@ -76,7 +76,7 @@ This operation returns a list of services from your cluster using a label select ._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] --------------------------------------------------------------------------------- +---- fromF("kubernetes-services://%s?oauthToken=%s", host, authToken) .process(new KubernetesProcessor()).to("mock:result"); @@ -88,7 +88,7 @@ fromF("kubernetes-services://%s?oauthToken=%s", host, authToken) log.info("Got event with service name: " + sv.getMetadata().getName() + " and action " + in.getHeader(KubernetesConstants.KUBERNETES_EVENT_ACTION)); } } --------------------------------------------------------------------------------- +---- This consumer returns a message per event received for all Services from all namespaces in the cluster. diff --git a/components/camel-kubernetes/src/main/docs/openshift-build-configs-component.adoc b/components/camel-kubernetes/src/main/docs/openshift-build-configs-component.adoc index 5fd0c74104349..e90a6f7b5c23d 100644 --- a/components/camel-kubernetes/src/main/docs/openshift-build-configs-component.adoc +++ b/components/camel-kubernetes/src/main/docs/openshift-build-configs-component.adoc @@ -42,11 +42,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses `toF()` for URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("openshift-build-configs:///?kubernetesClient=#kubernetesClient&operation=listBuildConfigs"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of builds from your Openshift cluster @@ -54,7 +54,7 @@ This operation returns a list of builds from your Openshift cluster ._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -66,7 +66,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("openshift-build-configs:///?kubernetesClient=#kubernetesClient&operation=listBuildConfigsByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of build configs from your cluster using a label selector (with key1 and key2, with value value1 and value2) diff --git a/components/camel-kubernetes/src/main/docs/openshift-builds-component.adoc b/components/camel-kubernetes/src/main/docs/openshift-builds-component.adoc index 7b7db1603761e..ea37d4d6cb27e 100644 --- a/components/camel-kubernetes/src/main/docs/openshift-builds-component.adoc +++ b/components/camel-kubernetes/src/main/docs/openshift-builds-component.adoc @@ -42,11 +42,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses `toF()` for URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("openshift-builds:///?kubernetesClient=#kubernetesClient&operation=listBuilds"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a List of Builds from your Openshift cluster @@ -54,7 +54,7 @@ This operation returns a List of Builds from your Openshift cluster ._Java-only: uses inline Processor, Java constants, and `toF()`_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -66,7 +66,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("openshift-builds:///?kubernetesClient=#kubernetesClient&operation=listBuildsByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of builds from your cluster using a label selector (with key1 and key2, with value value1 and value2) diff --git a/components/camel-kubernetes/src/main/docs/openshift-deploymentconfigs-component.adoc b/components/camel-kubernetes/src/main/docs/openshift-deploymentconfigs-component.adoc index bf5d2e6143402..0f4185d348b29 100644 --- a/components/camel-kubernetes/src/main/docs/openshift-deploymentconfigs-component.adoc +++ b/components/camel-kubernetes/src/main/docs/openshift-deploymentconfigs-component.adoc @@ -44,11 +44,11 @@ include::partial$component-endpoint-headers.adoc[] ._Java-only: uses toF() for endpoint URI formatting_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:list"). toF("openshift-deploymentconfigs:///?kubernetesClient=#kubernetesClient&operation=listDeploymentConfigs"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of deployment configs from your cluster @@ -56,7 +56,7 @@ This operation returns a list of deployment configs from your cluster ._Java-only: uses inline Processor with KubernetesConstants and HashMap_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:listByLabels").process(new Processor() { @Override public void process(Exchange exchange) throws Exception { @@ -68,7 +68,7 @@ from("direct:listByLabels").process(new Processor() { }); toF("openshift-deploymentconfigs:///?kubernetesClient=#kubernetesClient&operation=listDeploymentConfigsByLabels"). to("mock:result"); --------------------------------------------------------------------------------- +---- This operation returns a list of deployment configs from your cluster using a label selector (with key1 and key2, with value value1 and value2) @@ -76,7 +76,7 @@ This operation returns a list of deployment configs from your cluster using a la ._Java-only: uses fromF(), inline Processor class, KubernetesConstants, and string concatenation_ [source,java] --------------------------------------------------------------------------------- +---- fromF("openshift-deploymentconfigs://%s?oauthToken=%s", host, authToken) .process(new OpenshiftProcessor()).to("mock:result"); @@ -88,7 +88,7 @@ fromF("openshift-deploymentconfigs://%s?oauthToken=%s", host, authToken) log.info("Got event with deployment config name: " + dp.getMetadata().getName() + " and action " + in.getHeader(KubernetesConstants.KUBERNETES_EVENT_ACTION)); } } --------------------------------------------------------------------------------- +---- This consumer returns a message per event received for all DeploymentConfigs from all namespaces in the cluster. diff --git a/components/camel-ldap/src/main/docs/ldap-component.adoc b/components/camel-ldap/src/main/docs/ldap-component.adoc index db54a2cc7a3f5..fe08778461f2e 100644 --- a/components/camel-ldap/src/main/docs/ldap-component.adoc +++ b/components/camel-ldap/src/main/docs/ldap-component.adoc @@ -23,20 +23,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-ldap x.x.x ------------------------------------------------------------- +---- == URI format ------------------------------ +---- ldap:ldapServerBean[?options] ------------------------------ +---- The _ldapServerBean_ portion of the URI refers to a https://docs.oracle.com/en/java/javase/17/docs/api/java.naming/javax/naming/directory/DirContext.html[DirContext] @@ -87,7 +87,7 @@ public class LdapServerProducer { XML (Spring):: + [source,xml] ------------------------------------------------------------------------------------------ +---- @@ -97,7 +97,7 @@ XML (Spring):: ------------------------------------------------------------------------------------------ +---- ==== The preceding example declares a regular Sun-based LDAP `DirContext` @@ -128,7 +128,7 @@ Name is then extracted from the response. ._Java-only: Java test API (ProducerTemplate)_ [source,java] ----------------------------------------------------------- +---- ProducerTemplate template = exchange.getContext().createProducerTemplate(); Collection results = template.requestBody( @@ -145,15 +145,15 @@ if (results.size() > 0) { String deviceCN = (String) deviceCNAttr.get(); // ... } ----------------------------------------------------------- +---- If no specific filter is required (for example, you need to look up a single entry), specify a wildcard filter expression. If the LDAP entry has a Common Name, use a filter expression like: ------- +---- (cn=*) ------- +---- === Binding using credentials @@ -162,7 +162,7 @@ server using credentials. ._Java-only: Java programmatic CamelContext and LDAP context setup_ [source,java] ---------------------------------------------------------------------------------------- +---- Properties props = new Properties(); props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); props.setProperty(Context.PROVIDER_URL, "ldap://localhost:389"); @@ -200,7 +200,7 @@ assert !data.isEmpty(); System.out.println(out.getMessage().getBody()); context.stop(); ---------------------------------------------------------------------------------------- +---- == Configuring SSL @@ -236,7 +236,7 @@ public class LdapServerProducer { XML (Spring):: + [source,xml] ----------------------------------------------------------------------------------------------------------------------------------- +---- ----------------------------------------------------------------------------------------------------------------------------------- +---- ==== *Custom Socket Factory* @@ -370,7 +370,7 @@ ldap.trustStorePassword=secret XML (Spring):: + [source,java] ------------------------------------------------------------------------------------------------------ +---- package com.example.ldap; import java.io.IOException; @@ -456,7 +456,7 @@ public class CustomSocketFactory extends SSLSocketFactory { return socketFactory.createSocket(ia, i, ia1, i1); } } ------------------------------------------------------------------------------------------------------ +---- ==== include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-leveldb/src/main/docs/leveldb.adoc b/components/camel-leveldb/src/main/docs/leveldb.adoc index 00620e8d93334..abd714e2d69d5 100644 --- a/components/camel-leveldb/src/main/docs/leveldb.adoc +++ b/components/camel-leveldb/src/main/docs/leveldb.adoc @@ -149,10 +149,10 @@ Example of jackson serialization: ._Java-only: programmatic Jackson serializer configuration_ [source,java] ----------------------------------------- +---- LevelDBAggregationRepository repo = ...; //initialization of repository repo.setSerializer(new JacksonLevelDBSerializer()); ----------------------------------------- +---- Limitation of jackson serializer is caused by binary data: @@ -162,13 +162,13 @@ can be used to solve this problem. Please use custom serializer with Jackson by ._Java-only: custom Jackson module with serializer and deserializer_ [source,java] ----------------------------------------- +---- SimpleModule simpleModule = new SimpleModule(); simpleModule.addSerializer(ObjectWithBinaryField.class, new ObjectWithBinaryFieldSerializer()); //custom serializer simpleModule.addDeserializer(ObjectWithBinaryField.class, new ObjectWithBinaryFieldDeserializer()); //custom deserializer repo.setSerializer(new JacksonLevelDBSerializer(simpleModule)); ----------------------------------------- +---- [[LevelDB-UsingLevelDBAggregationRepositoryinJavaDSL]] == Using LevelDBAggregationRepository in Java DSL @@ -190,12 +190,12 @@ If you use Maven, you could add the following to your pom.xml, substituting the version number for the latest & greatest release. [source,xml] ----------------------------------------- +---- org.apache.camel camel-leveldb x.y.z ----------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-log/src/main/docs/log-component.adoc b/components/camel-log/src/main/docs/log-component.adoc index 660231cd3803c..eb80c5a5bbfdd 100644 --- a/components/camel-log/src/main/docs/log-component.adoc +++ b/components/camel-log/src/main/docs/log-component.adoc @@ -369,9 +369,9 @@ Simply by registering a bean with the name `logFormatter`; the Log Component is intelligent enough to pick it up automatically. [source,xml] ------ +---- ------ +---- [NOTE] ==== @@ -397,11 +397,11 @@ And then we can have Camel routes using the log uri with different options: [source,xml] ---------------------------------------------- +---- ---------------------------------------------- +---- diff --git a/components/camel-lucene/src/main/docs/lucene-component.adoc b/components/camel-lucene/src/main/docs/lucene-component.adoc index e4c09e95869df..d31ec8d120c69 100644 --- a/components/camel-lucene/src/main/docs/lucene-component.adoc +++ b/components/camel-lucene/src/main/docs/lucene-component.adoc @@ -34,21 +34,21 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-lucene x.x.x ------------------------------------------------------------- +---- == URI format ------------------------------------- +---- lucene:searcherName:insert[?options] lucene:searcherName:query[?options] ------------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -85,7 +85,7 @@ Lucene usage samples. ._Java-only: RouteBuilder class definition_ [source,java] ------------------------------------------------------------------------------------- +---- RouteBuilder builder = new RouteBuilder() { public void configure() { from("direct:start"). @@ -94,25 +94,25 @@ RouteBuilder builder = new RouteBuilder() { to("mock:result"); } }; ------------------------------------------------------------------------------------- +---- === Example 2: Loading properties into the JNDI registry in the Camel Context ._Java-only: programmatic CamelContext and registry configuration_ [source,java] ------------------------------------------------------------------ +---- CamelContext context = new DefaultCamelContext(createRegistry()); Registry registry = context.getRegistry(); registry.bind("whitespace", new File("./whitespaceIndexDir")); registry.bind("load_dir", new File("src/test/resources/sources")); registry.bind("whitespaceAnalyzer", new WhitespaceAnalyzer()); ------------------------------------------------------------------ +---- === Example 2: Performing searches using a Query Producer ._Java-only: RouteBuilder with inline Processor and Java constants_ [source,java] ----------------------------------------------------------------------------------------------------- +---- RouteBuilder builder = new RouteBuilder() { public void configure() { from("direct:start"). @@ -138,13 +138,13 @@ RouteBuilder builder = new RouteBuilder() { }).to("mock:searchResult"); } }; ----------------------------------------------------------------------------------------------------- +---- === Example 3: Performing searches using a Query Processor ._Java-only: RouteBuilder with LuceneQueryProcessor and inline Processor_ [source,java] -------------------------------------------------------------------------------------------------------- +---- RouteBuilder builder = new RouteBuilder() { public void configure() { try { @@ -173,7 +173,7 @@ RouteBuilder builder = new RouteBuilder() { }).to("mock:searchResult"); } }; -------------------------------------------------------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-lzf/src/main/docs/lzf-dataformat.adoc b/components/camel-lzf/src/main/docs/lzf-dataformat.adoc index 4b89b72db80d3..6641c7e37d794 100644 --- a/components/camel-lzf/src/main/docs/lzf-dataformat.adoc +++ b/components/camel-lzf/src/main/docs/lzf-dataformat.adoc @@ -117,14 +117,14 @@ If you use Maven you can add the following to your `pom.xml`, substituting the version number for the latest release. [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-lzf x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-mail/src/main/docs/mail-component.adoc b/components/camel-mail/src/main/docs/mail-component.adoc index 409f02651533b..4f40cf9642547 100644 --- a/components/camel-mail/src/main/docs/mail-component.adoc +++ b/components/camel-mail/src/main/docs/mail-component.adoc @@ -21,14 +21,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-mail x.x.x ------------------------------------------------------------- +---- [TIP] @@ -56,21 +56,21 @@ will kick in and avoid sending the mails. Mail endpoints can have one of the following URI formats (for the protocols, SMTP, POP3, or IMAP, respectively): ---------------------------------------- +---- smtp://[username@]host[:port][?options] pop3://[username@]host[:port][?options] imap://[username@]host[:port][?options] ---------------------------------------- +---- The mail component also supports secure variants of these protocols (layered over SSL). You can enable the secure protocols by adding `s` to the scheme: ----------------------------------------- +---- smtps://[username@]host[:port][?options] pop3s://[username@]host[:port][?options] imaps://[username@]host[:port][?options] ----------------------------------------- +---- // component options: START @@ -85,22 +85,22 @@ include::partial$component-endpoint-headers.adoc[] Typically, you specify a URI with login credentials as follows: .SMTP endpoint example ------------------------------------------------- +---- smtp://[username@]host[:port][?password=somepwd] ------------------------------------------------- +---- Alternatively, it is possible to specify both the username and the password as query options: ------------------------------------------------------ +---- smtp://host[:port]?password=somepwd&username=someuser ------------------------------------------------------ +---- For example: ------------------------------------------------------------- +---- smtp://mycompany.mailserver:30?password=tiger&username=scott ------------------------------------------------------------- +---- === Component alias names @@ -149,7 +149,7 @@ Programmatic configuration of the endpoint ._Java-only: programmatic `SSLContextParameters` configuration and registry binding_ [source,java] ----------------------------------------------------------------------------------------------------------------------------------- +---- KeyStoreParameters ksp = new KeyStoreParameters(); ksp.setResource("/users/home/server/truststore.jks"); ksp.setPassword("keystorePassword"); @@ -162,13 +162,13 @@ registry.bind("sslContextParameters", scp); ... from(...) .to("smtps://smtp.google.com?username=user@gmail.com&password=password&sslContextParameters=#sslContextParameters"); ----------------------------------------------------------------------------------------------------------------------------------- +---- [[Mail-SpringDSLbasedconfigurationofendpoint]] Spring DSL based configuration of endpoint [source,xml] ---------------------------------------------------------------------------------------------------------------------------- +---- ... @@ -177,7 +177,7 @@ Spring DSL based configuration of endpoint ... ... ... ---------------------------------------------------------------------------------------------------------------------------- +---- ==== Configuring JavaMail Directly @@ -245,7 +245,7 @@ you can use a header property as `To`: ._Java-only: ProducerTemplate API with mail headers_ [source,java] ------------------------------------------------------------------------------------------------------------- +---- Map headers = new HashMap(); headers.put("To", "davsclaus@apache.org"); headers.put("From", "jstrachan@apache.org"); @@ -255,7 +255,7 @@ headers.put("org.apache.camel.test", "value"); String body = "Hello Claus.\nYes it does.\n\nRegards James."; template.sendBodyAndHeaders("smtp://davsclaus@apache.org", body, headers); ------------------------------------------------------------------------------------------------------------- +---- When using the MailProducer to send the mail to server, you should be able to get the message id of the @@ -367,7 +367,7 @@ For example, you define the following headers on the message: ._Java-only: programmatic header map construction_ [source,java] ---------------------------------------------------------- +---- Map headers = new HashMap(); map.put("Subject", "Camel is cool"); map.put("From", "James Strachan "); @@ -375,7 +375,7 @@ map.put("To", "Claus Ibsen "); map.put("Cc", "An Other "); map.put("Bcc", "An Other "); map.put("Reply-To", "An Other "); ---------------------------------------------------------- +---- === JavaMail API (ex SUN JavaMail) @@ -501,7 +501,7 @@ attachment. ._Java-only: programmatic `Exchange` and attachment manipulation via Camel API_ [source,java] -------------------------------------------------------- +---- // create an exchange with a normal body and attachment to be produced as email Endpoint endpoint = context.getEndpoint("smtp://james@mymailserver.com?password=secret"); @@ -519,7 +519,7 @@ Producer producer = endpoint.createProducer(); producer.start(); // and let it go (processes the exchange by sending the email) producer.process(exchange); -------------------------------------------------------- +---- === SSL example @@ -575,13 +575,13 @@ Running the sample with `DEBUG` logging enabled, we can monitor the progress in the logs: [source,text] ------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- 2008-05-08 06:32:09,640 DEBUG MailConsumer - Connecting to MailStore imaps//imap.gmail.com:993 (SSL enabled), folder=INBOX 2008-05-08 06:32:11,203 DEBUG MailConsumer - Polling mailfolder: imaps//imap.gmail.com:993 (SSL enabled), folder=INBOX 2008-05-08 06:32:11,640 DEBUG MailConsumer - Fetching 1 messages. Total 1 messages. 2008-05-08 06:32:12,171 DEBUG MailConsumer - Processing message: messageNumber=[332], from=[James Bond <007@mi5.co.uk>], to=YOUR_USERNAME@gmail.com], subject=[... 2008-05-08 06:32:12,187 INFO newmail - Exchange[MailMessage: messageNumber=[332], from=[James Bond <007@mi5.co.uk>], to=YOUR_USERNAME@gmail.com], subject=[... ------------------------------------------------------------------------------------------------------------------------------------------------------------------- +---- === Consuming mails with attachment @@ -592,17 +592,17 @@ SSL sample: ._Java-only: uses custom `Processor` to handle mail attachments_ [source,java] ---------------------------------------------------------------------------------------- +---- from("imaps://imap.gmail.com?username=YOUR_USERNAME@gmail.com&password=YOUR_PASSWORD&delete=false&unseen=true&delay=60000") .process(new MyMailProcessor()); ---------------------------------------------------------------------------------------- +---- Instead of logging the mail, we use a processor where we can process the mail from java code: ._Java-only: custom `Processor` for extracting and saving attachments_ [source,java] ---------------------------------------------------------------------------------- +---- public void process(Exchange exchange) throws Exception { // the API is a bit clunky, so we need to loop AttachmentMessage attachmentMessage = exchange.getMessage(AttachmentMessage.class); @@ -625,7 +625,7 @@ public void process(Exchange exchange) throws Exception { } } } ---------------------------------------------------------------------------------- +---- As you can see the API to handle attachments is a bit clunky, but it's there, so you can get the `javax.activation.DataHandler` so you can @@ -656,12 +656,12 @@ If you use XML DSL, then you need to declare a method call expression in the Splitter as shown below [source,xml] ---------------------------------------------------------------------------------- +---- ---------------------------------------------------------------------------------- +---- You can also split the attachments as byte[] to be stored as the message body. This is done by creating the expression @@ -669,9 +669,9 @@ with boolean true ._Java-only: programmatic `SplitAttachmentsExpression` configuration_ [source,java] --------------------------------------------------------------------- +---- SplitAttachmentsExpression split = SplitAttachmentsExpression(true); --------------------------------------------------------------------- +---- And then use the expression with the splitter EIP. @@ -684,12 +684,12 @@ For example, to filter mails to contain Camel in either Subject or Text, you can do as follows: [source,xml] -------------------------------------------------------------------------------------------------- +---- -------------------------------------------------------------------------------------------------- +---- Notice we use the `"searchTerm.subjectOrBody"` as a parameter key to indicate that we want to search on mail subject or body, to contain the @@ -701,12 +701,12 @@ Or to get the new unseen emails going 24 hours back in time, you can do. Notice the "now-24h" syntax. See the table below for more details. [source,xml] --------------------------------------------------------------------------------------------------- +---- --------------------------------------------------------------------------------------------------- +---- You can have multiple searchTerm in the endpoint uri configuration. They would then be combined using the `AND` operator, e.g., so both @@ -714,35 +714,35 @@ conditions must match. For example, to get the last unseen emails going back 24 hours which has Camel in the mail subject you can do: [source,xml] ---------------------------------------------------------------------------------------------------------------------------- +---- ---------------------------------------------------------------------------------------------------------------------------- +---- The `SimpleSearchTerm` is designed to be easily configurable from a POJO, so you can also configure it using a style in XML [source,xml] ---------------------------------------------------------------------------------- +---- ---------------------------------------------------------------------------------- +---- You can then refer to this bean, using #beanId in your Camel route as shown: [source,xml] -------------------------------------------------------------------------------------------- +---- -------------------------------------------------------------------------------------------- +---- In Java there is a builder class to build compound `SearchTerms` using the `org.apache.camel.component.mail.SearchTermBuilder` @@ -750,7 +750,7 @@ class. This allows you to build complex terms such as: ._Java-only: programmatic `SearchTermBuilder` for complex mail filters_ [source,java] --------------------------------------------------------------- +---- // we just want the unseen mails that are not spam SearchTermBuilder builder = new SearchTermBuilder(); @@ -760,7 +760,7 @@ builder.unseen().body(Op.not, "Spam").subject(Op.not, "Spam") // ... and we could continue building the terms SearchTerm term = builder.build(); --------------------------------------------------------------- +---- === Using headers with additional Java Mail Sender properties diff --git a/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc b/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc index cd1a48e537774..7d867721a56c5 100644 --- a/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc +++ b/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc @@ -101,28 +101,28 @@ MIME multipart. The header is removed afterward ._Java-only: marshalling a message with attachments into MIME-Multipart format_ [source,java] ------------------------------------ +---- from(...).marshal().mimeMultipart() ------------------------------------ +---- With a message where no Content-Type header is set, will create a Message with the following message Camel headers: *Camel Message Headers* -------------------------------------------------------------------------------- +---- Content-Type=multipart/mixed; \n boundary="----=_Part_0_14180567.1447658227051" Message-Id=<...> MIME-Version=1.0 -------------------------------------------------------------------------------- +---- -------------------------- +---- The message body will be: -------------------------- +---- *Camel Message Body* ----------------------------------------------------------------- +---- ------=_Part_0_14180567.1447658227051 Content-Type: application/octet-stream Content-Transfer-Encoding: base64 @@ -133,16 +133,16 @@ Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="Attachment File Name" AAECAwQFBgc= ------=_Part_0_14180567.1447658227051-- ----------------------------------------------------------------- +---- A message with the header Content-Type set to "text/plain" sent to the route ._Java-only: marshalling with custom MIME-Multipart options_ [source,java] ------------------------------------------------------------------------------------- +---- from("...").marshal().mimeMultipart("related", true, true, "(included|x-.*)", true); ------------------------------------------------------------------------------------- +---- will create a message without any specific MIME headers set as Camel headers (the Content-Type header is removed from the Camel message) and @@ -151,7 +151,7 @@ original message starting with "x-" and the header with name "included": *Camel Message Body* ----------------------------------------------------------------- +---- Message-ID: <...> MIME-Version: 1.0 Content-Type: multipart/related; @@ -172,7 +172,7 @@ Content-Disposition: attachment; filename="Attachment File Name" [binary content] ------=_Part_0_1134128170.1447659361365 ----------------------------------------------------------------- +---- == Dependencies @@ -182,13 +182,13 @@ on *camel-mail*, which implements this data format. If you use Maven, you can add the following to your pom.xml: [source,xml] ------------------------------------------------------------------------------------ +---- org.apache.camel camel-mail x.x.x ------------------------------------------------------------------------------------ +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-milo/src/main/docs/milo-browse-component.adoc b/components/camel-milo/src/main/docs/milo-browse-component.adoc index 525d2b395772f..c8487f1e7d2ad 100644 --- a/components/camel-milo/src/main/docs/milo-browse-component.adoc +++ b/components/camel-milo/src/main/docs/milo-browse-component.adoc @@ -26,23 +26,23 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-milo x.x.x ------------------------------------------------------------- +---- == URI format The URI syntax of the endpoint is: ------------------------- +---- milo-browse:opc.tcp://[user:password@]host:port/path/to/service?node=RAW(nsu=urn:foo:bar;s=item-1) ------------------------- +---- Please refer to the xref:milo-client-component.adoc[Milo Client] component for further details about the construction of the URI. diff --git a/components/camel-milo/src/main/docs/milo-client-component.adoc b/components/camel-milo/src/main/docs/milo-client-component.adoc index 5acacbf2ddbb0..b893209e49a9e 100644 --- a/components/camel-milo/src/main/docs/milo-client-component.adoc +++ b/components/camel-milo/src/main/docs/milo-client-component.adoc @@ -26,29 +26,29 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-milo x.x.x ------------------------------------------------------------- +---- == URI format The URI syntax of the endpoint is: ------------------------- +---- milo-client:opc.tcp://[user:password@]host:port/path/to/service?node=RAW(nsu=urn:foo:bar;s=item-1) ------------------------- +---- If the server does not use a path, then it is possible to simply omit it: ------------------------- +---- milo-client:opc.tcp://[user:password@]host:port?node=RAW(nsu=urn:foo:bar;s=item-1) ------------------------- +---- If no user credentials are provided the client will switch to anonymous mode. @@ -110,9 +110,9 @@ Exactly one namespace and one node id key must be used. See the following table As the values generated by the syntax cannot be transparently encoded into a URI parameter value, it is necessary to escape them. However Camel allows to wrap the actual value inside `RAW(…)`, which makes escaping unnecessary. For example: ------------------------- +---- milo-client:opc.tcp://user:password@localhost:12345?node=RAW(nsu=http://foo.bar;s=foo/bar) ------------------------- +---- === Method ID diff --git a/components/camel-mina/src/main/docs/mina-component.adoc b/components/camel-mina/src/main/docs/mina-component.adoc index 9fad0d73efee5..68df1e764cecc 100644 --- a/components/camel-mina/src/main/docs/mina-component.adoc +++ b/components/camel-mina/src/main/docs/mina-component.adoc @@ -30,22 +30,22 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-mina x.x.x ------------------------------------------------------------- +---- == URI format -------------------------------------- +---- mina:tcp://hostname[:port][?options] mina:udp://hostname[:port][?options] mina:vm://hostname[:port][?options] -------------------------------------- +---- You can specify a codec in the Registry using the *codec* option. If you are using TCP and no codec is specified then the @@ -108,23 +108,23 @@ on port 6200. We use the *textline* codec. In our route, we create a Mina consumer endpoint that listens to on port 6200: ._Java-only: Java string concatenation with port variable_ [source,java] ---------------------------------------------------------------------------------------- +---- from("mina:tcp://localhost:" + port1 + "?textline=true&sync=false").to("mock:result"); ---------------------------------------------------------------------------------------- +---- As the sample is part of a unit test, we test it by sending some data to it on port 6200. ._Java-only: Java test API (MockEndpoint and ProducerTemplate)_ [source,java] -------------------------------------------------------------------------------------------------- +---- MockEndpoint mock = getMockEndpoint("mock:result"); mock.expectedBodiesReceived("Hello World"); template.sendBody("mina:tcp://localhost:" + port1 + "?textline=true&sync=false", "Hello World"); MockEndpoint.assertIsSatisfied(context); -------------------------------------------------------------------------------------------------- +---- === Example with sync=true @@ -135,14 +135,14 @@ consumer. ._Java-only: inline Processor class_ [source,java] ---------------------------------------------------------------------------------------------- +---- fromF("mina:tcp://localhost:%d?textline=true&sync=true", port2).process(new Processor() { public void process(Exchange exchange) throws Exception { String body = exchange.getIn().getBody(String.class); exchange.getOut().setBody("Bye " + body); } }); ---------------------------------------------------------------------------------------------- +---- Then we test the sample by sending some data and retrieving the response using the `template.requestBody()` method. As we know the response is a @@ -151,10 +151,10 @@ fact, something we have dynamically set in our processor code logic. ._Java-only: Java test API (ProducerTemplate)_ [source,java] ------------------------------------------------------------------------------------------------------------------------ +---- String response = (String)template.requestBody("mina:tcp://localhost:" + port2 + "?textline=true&sync=true", "World"); assertEquals("Bye World", response); ------------------------------------------------------------------------------------------------------------------------ +---- === Example with Spring DSL @@ -162,12 +162,12 @@ Spring DSL can also be used for xref:mina-component.adoc[MINA]. In the sample below, we expose a TCP server on port 5555: [source,xml] ------------------------------------------------------------ +---- ------------------------------------------------------------ +---- In the route above, we expose a TCP server on port 5555 using the textline codec. We let the Spring bean with ID, `myTCPOrderHandler`, @@ -176,12 +176,12 @@ could be implemented as follows: ._Java-only: Java handler class_ [source,java] ------------------------------------------------ +---- public String handleOrder(String payload) { ... return "Order: OK" } ------------------------------------------------ +---- == Closing Session When Complete @@ -195,7 +195,7 @@ written the `bye` message back to the client: ._Java-only: inline Processor class_ [source,java] ---------------------------------------------------------------------------------------------------- +---- from("mina:tcp://localhost:8080?sync=true&textline=true").process(new Processor() { public void process(Exchange exchange) throws Exception { String body = exchange.getIn().getBody(String.class); @@ -203,7 +203,7 @@ written the `bye` message back to the client: exchange.getOut().setHeader(MinaConstants.MINA_CLOSE_SESSION_WHEN_COMPLETE, true); } }); ---------------------------------------------------------------------------------------------------- +---- diff --git a/components/camel-minio/src/main/docs/minio-component.adoc b/components/camel-minio/src/main/docs/minio-component.adoc index 6ab1149a7e34b..987429c054415 100644 --- a/components/camel-minio/src/main/docs/minio-component.adoc +++ b/components/camel-minio/src/main/docs/minio-component.adoc @@ -24,9 +24,9 @@ https://min.io/[Minio]. == URI Format ------------------------------- +---- minio://bucketName[?options] ------------------------------- +---- The bucket will be created if it doesn't already exist. + You can append query options to the URI in the following format: `?options=value&option2=value&...` @@ -696,13 +696,13 @@ We introduce the possibility to use a POJO as the body. In Minio, there are multiple operations you can submit, as an example for List brokers request, you can do something like: [source,java] ------------------------------------------------------------------------------------------------------- +---- from("direct:minio") .setBody(ListObjectsArgs.builder() .bucket(bucketName) .recursive(getConfiguration().isRecursive())) .to("minio://test?minioClient=#minioClient&operation=listObjects&pojoRequest=true"); ------------------------------------------------------------------------------------------------------- +---- In this way, you'll pass the request directly without the need of passing headers and options specifically related to this operation. @@ -713,13 +713,13 @@ Maven users will need to add the following dependency to their `pom.xml`. *pom.xml* [source,xml] ---------------------------------------- +---- org.apache.camel camel-minio ${camel-version} ---------------------------------------- +---- where `$\{camel-version}` must be replaced by the actual version of Camel. diff --git a/components/camel-mongodb-gridfs/src/main/docs/mongodb-gridfs-component.adoc b/components/camel-mongodb-gridfs/src/main/docs/mongodb-gridfs-component.adoc index 9f4e2f9110dad..4c5c75c17b966 100644 --- a/components/camel-mongodb-gridfs/src/main/docs/mongodb-gridfs-component.adoc +++ b/components/camel-mongodb-gridfs/src/main/docs/mongodb-gridfs-component.adoc @@ -18,20 +18,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-mongodb-gridfs x.y.z ------------------------------------------------------------- +---- == URI format ------------------------------------------------------------------------------- +---- mongodb-gridfs:connectionBean?database=databaseName&bucket=bucketName[&moreOptions...] ------------------------------------------------------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -51,35 +51,35 @@ as the OUT message body. ._Java-only: using ProducerTemplate to invoke the count operation_ [source,java] ---------------------------------------------------------------------------------- +---- // from("direct:count").to("mongodb-gridfs?database=tickets&operation=count"); Integer result = template.requestBodyAndHeader("direct:count", "irrelevantBody"); assertTrue("Result is not of type Long", result instanceof Integer); ---------------------------------------------------------------------------------- +---- You can provide a filename header to provide a count of files matching that filename. ._Java-only: using ProducerTemplate with filename header_ [source,java] -------------------------------------------------------------------------------- +---- Map headers = new HashMap(); headers.put(Exchange.FILE_NAME, "filename.txt"); Integer count = template.requestBodyAndHeaders("direct:count", query, headers); -------------------------------------------------------------------------------- +---- ==== listAll Returns a Reader that lists all the filenames and their IDs in a tab separated stream. ----------------------------------------------------------------------------------- +---- // from("direct:listAll").to("mongodb-gridfs?database=tickets&operation=listAll"); Reader result = template.requestBodyAndHeader("direct:listAll", "irrelevantBody"); filename1.txt 1252314321 filename2.txt 2897651254 ----------------------------------------------------------------------------------- +---- ==== findOne @@ -89,12 +89,12 @@ the content. Also provides the metadata has headers. It uses ._Java-only: using ProducerTemplate to find a file by name_ [source,java] -------------------------------------------------------------------------------------------------- +---- // from("direct:findOne").to("mongodb-gridfs?database=tickets&operation=findOne"); Map headers = new HashMap(); headers.put(Exchange.FILE_NAME, "filename.txt"); InputStream result = template.requestBodyAndHeaders("direct:findOne", "irrelevantBody", headers); -------------------------------------------------------------------------------------------------- +---- ==== create @@ -104,13 +104,13 @@ contents (as an InputStream) as the content. ._Java-only: using ProducerTemplate to create a file_ [source,java] ------------------------------------------------------------------------- +---- // from("direct:create").to("mongodb-gridfs?database=tickets&operation=create"); Map headers = new HashMap(); headers.put(Exchange.FILE_NAME, "filename.txt"); InputStream stream = ... the data for the file ... template.requestBodyAndHeaders("direct:create", stream, headers); ------------------------------------------------------------------------- +---- ==== remove @@ -118,12 +118,12 @@ Removes a file from the GridFS database. ._Java-only: using ProducerTemplate to remove a file_ [source,java] ------------------------------------------------------------------------- +---- // from("direct:remove").to("mongodb-gridfs?database=tickets&operation=remove"); Map headers = new HashMap(); headers.put(Exchange.FILE_NAME, "filename.txt"); template.requestBodyAndHeaders("direct:remove", "", headers); ------------------------------------------------------------------------- +---- == Examples @@ -135,14 +135,14 @@ xref:mongodb-gridfs-component.adoc[*findOne*] on a collection. *Get a file from GridFS* [source,xml] ----------------------------------------------------------------------------------- +---- ----------------------------------------------------------------------------------- +---- === Configuration of a database in Spring XML @@ -150,7 +150,7 @@ The following Spring XML creates a bean defining the connection to a MongoDB instance. [source,xml] ----------------------------------------------------------------------------------------------------------------------------------- +---- @@ -159,7 +159,7 @@ MongoDB instance. ----------------------------------------------------------------------------------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-mongodb/src/main/docs/mongodb-component.adoc b/components/camel-mongodb/src/main/docs/mongodb-component.adoc index fd8ae66808634..0645e590de8b1 100644 --- a/components/camel-mongodb/src/main/docs/mongodb-component.adoc +++ b/components/camel-mongodb/src/main/docs/mongodb-component.adoc @@ -48,21 +48,21 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-mongodb x.y.z ------------------------------------------------------------- +---- == URI formats ---------------------------------------------------------------------------------------------------------------- +---- mongodb:connectionBean?database=databaseName&collection=collectionName&operation=operationName[&moreOptions...] mongodb:dummy?hosts=hostnames&database=databaseName&collection=collectionName&operation=operationName[&moreOptions...] ---------------------------------------------------------------------------------------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -84,7 +84,7 @@ Since mongo java driver 3, the WriteConcern and readPreference options have not They are defined in the mongoClient object: [source,xml] ----------------------------------------------------------------------------------------------------------------------------------- +---- ----------------------------------------------------------------------------------------------------------------------------------- +---- === MongoDB operations - producer endpoints @@ -159,12 +159,12 @@ YAML:: Please note that the default _id is treated by Mongo as and `ObjectId` type, so you may need to convert it properly. [source,java] ------------------------------------------------------------------------------- +---- from("direct:findById") .convertBodyTo(ObjectId.class) .to("mongodb:myDb?database=flights&collection=tickets&operation=findById") .to("mock:resultFindById"); ------------------------------------------------------------------------------- +---- [TIP] ==== @@ -805,7 +805,7 @@ Equivalent of running the `db.stats()` command in the MongoDB shell, which displays useful statistic figures about the database. + For example: -------------------------------------- +---- > db.stats(); { "db" : "test", @@ -821,16 +821,16 @@ which displays useful statistic figures about the database. + "nsSizeMB" : 16, "ok" : 1 } -------------------------------------- +---- Usage example: [source,java] ---------------------------------------------------------------------------------------------------------- +---- // from("direct:getDbStats").to("mongodb:myDb?database=flights&collection=tickets&operation=getDbStats"); Object result = template.requestBody("direct:getDbStats", "irrelevantBody"); assertTrue("Result is not of type Document", result instanceof Document); ---------------------------------------------------------------------------------------------------------- +---- The operation will return a data structure similar to the one displayed in the shell, in the form of a `Document` in the OUT message body. @@ -841,7 +841,7 @@ Equivalent of running the `db.collection.stats()` command in the MongoDB shell, which displays useful statistic figures about the collection. + For example: ------------------------------ +---- > db.camelTest.stats(); { "ns" : "test.camelTest", @@ -860,16 +860,16 @@ shell, which displays useful statistic figures about the collection. + }, "ok" : 1 } ------------------------------ +---- Usage example: [source,java] ------------------------------------------------------------------------------------------------------------ +---- // from("direct:getColStats").to("mongodb:myDb?database=flights&collection=tickets&operation=getColStats"); Object result = template.requestBody("direct:getColStats", "irrelevantBody"); assertTrue("Result is not of type Document", result instanceof Document); ------------------------------------------------------------------------------------------------------------ +---- The operation will return a data structure similar to the one displayed in the shell, in the form of a `Document` in the OUT message body. @@ -882,11 +882,11 @@ getting host information, replication or sharding status. Collection parameter is not used for this operation. [source,java] --------------------------------------------------------------------------------- +---- // route: from("command").to("mongodb:myDb?database=science&operation=command"); DBObject commandBody = new BasicDBObject("hostInfo", "1"); Object result = template.requestBody("direct:command", commandBody); --------------------------------------------------------------------------------- +---- ==== Dynamic operations @@ -974,12 +974,12 @@ value of 1000ms.), which you can modify to suit your needs. An example: [source,java] ------------------------------------------------------------------------------------------------------ +---- from("mongodb:myDb?database=flights&collection=cancellations&tailTrackIncreasingField=departureTime") .id("tailableCursorConsumer1") .autoStartup(false) .to("mock:test"); ------------------------------------------------------------------------------------------------------ +---- The above route will consume from the `flights.cancellations` capped collection, using `departureTime` as the increasing field, with a @@ -1028,13 +1028,13 @@ the last processed value under the "lastTrackingValue" field (`camelTailTracking` and `lastTrackingValue` are defaults). [source,java] ------------------------------------------------------------------------------------------------------------------------------------ +---- from("mongodb:myDb?database=flights&collection=cancellations&tailTrackIncreasingField=departureTime&persistentTailTracking=true" + "&persistentId=cancellationsTracker") .id("tailableCursorConsumer2") .autoStartup(false) .to("mock:test"); ------------------------------------------------------------------------------------------------------------------------------------ +---- Below is another example identical to the one above, but where the persistent tail tracking runtime information will be stored under the @@ -1042,14 +1042,14 @@ persistent tail tracking runtime information will be stored under the field: [source,java] ------------------------------------------------------------------------------------------------------------------------------------ +---- from("mongodb:myDb?database=flights&collection=cancellations&tailTrackIncreasingField=departureTime&persistentTailTracking=true" + "&persistentId=cancellationsTracker&tailTrackDb=trackers&tailTrackCollection=camelTrackers" + "&tailTrackField=lastProcessedDepartureTime") .id("tailableCursorConsumer3") .autoStartup(false) .to("mock:test"); ------------------------------------------------------------------------------------------------------------------------------------ +---- ==== Change Streams Consumer @@ -1064,19 +1064,19 @@ That JSON property is standard MongoDB `$match` aggregation. It could be easily specified using XML DSL configuration: [source,xml] -------------- +---- -------------- +---- Java configuration: [source,java] -------------- +---- from("mongodb:myDb?consumerType=changeStreams&database=flights&collection=tickets&streamFilter={ '$match':{'$or':[{'fullDocument.stringValue': 'specificValue'}]} }") .to("mock:test"); -------------- +---- TIP: You can externalize the streamFilter value into a property placeholder which allows the endpoint URI parameters to be _cleaner_ and easier to read. @@ -1111,14 +1111,14 @@ The following route defined in Spring XML executes the operation *Get DB stats for specified collection* [source,xml] ---------------------------------------------------------------------------------------------------------------------------- +---- ---------------------------------------------------------------------------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-nats/src/main/docs/nats-component.adoc b/components/camel-nats/src/main/docs/nats-component.adoc index 92d3dbf29ca5a..1685037a82de0 100644 --- a/components/camel-nats/src/main/docs/nats-component.adoc +++ b/components/camel-nats/src/main/docs/nats-component.adoc @@ -20,20 +20,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component. [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-nats x.y.z ------------------------------------------------------------- +---- == URI format ----------------------- +---- nats:topic[?options] ----------------------- +---- Where *topic* is the topic name diff --git a/components/camel-netty-http/src/main/docs/netty-http-component.adoc b/components/camel-netty-http/src/main/docs/netty-http-component.adoc index dcce4ce17271c..aebe0102be502 100644 --- a/components/camel-netty-http/src/main/docs/netty-http-component.adoc +++ b/components/camel-netty-http/src/main/docs/netty-http-component.adoc @@ -39,22 +39,22 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-netty-http x.x.x ------------------------------------------------------------- +---- == URI format The URI scheme for a netty component is as follows -------------------------------------------- +---- netty-http:http://0.0.0.0:8080[?options] -------------------------------------------- +---- [NOTE] ==== @@ -223,7 +223,7 @@ For example, as shown below in the XML DSL, we define the constraint bean: [source,xml] -------------------------------------------------------------------------------------------------- +---- @@ -241,7 +241,7 @@ bean: -------------------------------------------------------------------------------------------------- +---- The constraint above is defined so that @@ -256,12 +256,12 @@ To use this constraint, we just need to refer to the bean id as shown below: [source,xml] ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +---- ... ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +---- == Examples @@ -520,7 +520,7 @@ This will cause Camel to fail on startup. and will fail on starting* [source,java] --------------------------------------------------------------------------------------- +---- from("netty-http:http://0.0.0.0:{{port}}/foo") .to("mock:foo") .transform().constant("Bye World"); @@ -529,7 +529,7 @@ from("netty-http:http://0.0.0.0:{{port}}/foo") from("netty-http:http://0.0.0.0:{{port}}/bar?ssl=true") .to("mock:bar") .transform().constant("Bye Camel"); --------------------------------------------------------------------------------------- +---- === Reusing the same server bootstrap configuration with multiple routes @@ -540,18 +540,18 @@ type, we can use the `bootstrapConfiguration` option on the Netty HTTP consumers to refer and reuse the same options across all consumers. [source,xml] ------------------------------------------------------------------------------------------------------------------ +---- ------------------------------------------------------------------------------------------------------------------ +---- And in the routes you refer to this option as shown below [source,xml] ----------------------------------------------------------------------------------------------------------- +---- ... @@ -566,7 +566,7 @@ And in the routes you refer to this option as shown below ... ----------------------------------------------------------------------------------------------------------- +---- === Implementing a reverse proxy diff --git a/components/camel-observation/src/main/docs/observation.adoc b/components/camel-observation/src/main/docs/observation.adoc index 8a3758c1859e3..7e9bf1655dcce 100644 --- a/components/camel-observation/src/main/docs/observation.adoc +++ b/components/camel-observation/src/main/docs/observation.adoc @@ -49,7 +49,7 @@ context. You can optionally specify a `Tracer`, or alternatively it can be impli ._Java-only: configuring MicrometerObservationTracer with metrics and tracing_ [source,java] --------------------------------------------------------------------------------------------------- +---- ObservationRegistry observationRegistry = ObservationRegistry.create(); MicrometerObservationTracer micrometerObservationTracer = new MicrometerObservationTracer(); @@ -73,7 +73,7 @@ micrometerObservationTracer.setTracer(otelTracer); // Initialize the MicrometerObservationTracer micrometerObservationTracer.init(context); --------------------------------------------------------------------------------------------------- +---- == Spring Boot diff --git a/components/camel-ognl/src/main/docs/ognl-language.adoc b/components/camel-ognl/src/main/docs/ognl-language.adoc index 0886866354f9a..06b006a71abd2 100644 --- a/components/camel-ognl/src/main/docs/ognl-language.adoc +++ b/components/camel-ognl/src/main/docs/ognl-language.adoc @@ -137,13 +137,13 @@ If you use Maven, you could add the following to your `pom.xml`, substituting the version number for the latest & greatest release. [source,xml] -------------------------------------- +---- org.apache.camel camel-ognl x.x.x -------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-olingo2/camel-olingo2-component/src/main/docs/olingo2-component.adoc b/components/camel-olingo2/camel-olingo2-component/src/main/docs/olingo2-component.adoc index 041843a686e42..75c8d47eaaa4b 100644 --- a/components/camel-olingo2/camel-olingo2-component/src/main/docs/olingo2-component.adoc +++ b/components/camel-olingo2/camel-olingo2-component/src/main/docs/olingo2-component.adoc @@ -47,19 +47,19 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ----------------------------------------------- +---- org.apache.camel camel-olingo2 ${camel-version} ----------------------------------------------- +---- == URI format ------------------------------------------------- +---- olingo2://endpoint/?[options] ------------------------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -128,22 +128,22 @@ ordered by ascending Name property. ._Java-only: uses setHeader with Java constant_ [source,java] ------------------------------------------------------------- +---- from("direct:...") .setHeader("CamelOlingo2.$top", "5"); .to("olingo2://read/Manufacturers?orderBy=Name%20asc"); ------------------------------------------------------------- +---- The following route reads Manufacturer entry using the key property value in incoming *id* header. ._Java-only: uses setHeader with header() expression_ [source,java] ------------------------------------------------------------- +---- from("direct:...") .setHeader("CamelOlingo2.keyPredicate", header("id")) .to("olingo2://read/Manufacturers"); ------------------------------------------------------------- +---- The following route creates Manufacturer entry using the `java.util.Map` in the body message. diff --git a/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc b/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc index 420f227a95ba1..41f6dd83364a8 100644 --- a/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc +++ b/components/camel-olingo4/camel-olingo4-component/src/main/docs/olingo4-component.adoc @@ -118,22 +118,22 @@ ordered by ascending FirstName property. ._Java-only: uses setHeader with Java constant_ [source,java] ------------------------------------------------------------- +---- from("direct:...") .setHeader("CamelOlingo4.$top", "5"); .to("olingo4://read/People?orderBy=FirstName%20asc"); ------------------------------------------------------------- +---- The following route reads Airports entity using the key property value in incoming *id* header. ._Java-only: uses setHeader with header() expression_ [source,java] ------------------------------------------------------------- +---- from("direct:...") .setHeader("CamelOlingo4.keyPredicate", header("id")) .to("olingo4://read/Airports"); ------------------------------------------------------------- +---- The following route creates People entity using the *ClientEntity* in body message. diff --git a/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc b/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc index 4a3afeaaf5473..77b1859856b8c 100644 --- a/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc +++ b/components/camel-opentelemetry/src/main/docs/opentelemetry.adoc @@ -49,13 +49,13 @@ context. You can optionally specify a `Tracer`, or alternatively it can be impli ._Java-only: programmatic OpenTelemetryTracer configuration_ [source,java] --------------------------------------------------------------------------------------------------- +---- OpenTelemetryTracer otelTracer = new OpenTelemetryTracer(); // By default, it uses the DefaultTracer, but you can override it with a specific OpenTelemetry Tracer implementation. otelTracer.setTracer(...); // And then initialize the context otelTracer.init(camelContext); --------------------------------------------------------------------------------------------------- +---- NOTE: You would still need OpenTelemetry to instrument your code, which can be done via a <>. @@ -138,12 +138,12 @@ use the `management.otlp.tracing` properties or register a new `SpanExporter` be ._Java-only: Spring bean definition for SpanExporter_ [source,java] --------------------------------------------------------------------------------------------------- +---- @Bean public SpanExporter OtlpGrpcSpanExporter(@Value("${tracing.url}") String url) { return OtlpGrpcSpanExporter.builder().setEndpoint(url).build(); } --------------------------------------------------------------------------------------------------- +---- Spring Boot's Actuator will take care of the wiring for you. @@ -152,12 +152,12 @@ add `io.opentelemetry:opentelemetry-exporter-logging-otlp` as a dependency to yo ._Java-only: Spring bean definition for logging SpanExporter_ [source,java] --------------------------------------------------------------------------------------------------- +---- @Bean public SpanExporter logTraces() { return OtlpJsonLoggingSpanExporter.create(); } --------------------------------------------------------------------------------------------------- +---- Multiple `SpanExporters` can be used at the same time. diff --git a/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc b/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc index 9d74b3d3cf8a0..95a460c69ab0f 100644 --- a/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc +++ b/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc @@ -33,9 +33,9 @@ In this first example we unmarshal file payload to OutputStream and send it to m ._Java-only: unmarshal with a local parquet data format variable_ [source,java] ------------------------------------------------------------------------ +---- from("direct:unmarshal").unmarshal(parquet).to("mock:unmarshal"); ------------------------------------------------------------------------ +---- == Marshal @@ -43,9 +43,9 @@ Marshalling is the reverse process of unmarshalling, so when you have your `Gene ._Java-only: marshal with a local parquet data format variable_ [source,java] ------------------------------------------------------------------------ +---- from("direct:marshal").marshal(parquet).to("mock:marshal"); ------------------------------------------------------------------------ +---- == Dependencies @@ -56,14 +56,14 @@ If you use Maven you can add the following to your `pom.xml`, substituting the version number for the latest & greatest release. [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-parquet-avro x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-printer/src/main/docs/lpr-component.adoc b/components/camel-printer/src/main/docs/lpr-component.adoc index 5693482be5ae0..bf54c6124539e 100644 --- a/components/camel-printer/src/main/docs/lpr-component.adoc +++ b/components/camel-printer/src/main/docs/lpr-component.adoc @@ -28,14 +28,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-printer x.x.x ------------------------------------------------------------- +---- == URI format @@ -43,10 +43,10 @@ Since the URI scheme for a printer has not been standardized (the nearest thing to a standard being the IETF print standard), and therefore not uniformly applied by vendors, we have chosen *"lpr"* as the scheme. ------------------------------------------------ +---- lpr://localhost/default[?options] lpr://remotehost:port/path/to/printer[?options] ------------------------------------------------ +---- // component options: START include::partial$component-configure-options.adoc[] diff --git a/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc b/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc index 7f1b1f4902961..06ec4cd0a3e72 100644 --- a/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc +++ b/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc @@ -12,7 +12,7 @@ *Since Camel {since}* Protobuf - Protocol Buffers ---------------------------- +---- "Protocol Buffers - Google's data interchange format" @@ -45,12 +45,12 @@ The sample code shows below: ._Java-only: programmatic protobuf configuration with content type format_ [source,java] --------------------------------------------------------------------------------------------------- +---- from("direct:marshal") .unmarshal() .protobuf("org.apache.camel.dataformat.protobuf.generated.AddressBookProtos$Person", "json") .to("mock:reverse"); --------------------------------------------------------------------------------------------------- +---- == Input data type @@ -80,7 +80,7 @@ This is defined in a .proto file as so: *addressbook.proto* [source,protobuf] ------------------------------------------------------------- +---- syntax = "proto2"; package org.apache.camel.component.protobuf; @@ -110,7 +110,7 @@ message Person { message AddressBook { repeated Person person = 1; } ------------------------------------------------------------- +---- == Generating Java classes @@ -121,7 +121,7 @@ you can automate protobuf Java code generating by adding the following configura Insert operating system and CPU architecture detection extension inside `` tag of the project `pom.xml` or set `${os.detected.classifier}` parameter manually [source,xml] -------------------------------------------------------------------------- +---- kr.motd.maven @@ -129,10 +129,10 @@ Insert operating system and CPU architecture detection extension inside ` 1.4.1.Final -------------------------------------------------------------------------- +---- Insert gRPC and protobuf Java code generator plugin **** tag of the project `pom.xml` [source,xml] -------------------------------------------------------------------------- +---- org.xolstice.maven.plugins protobuf-maven-plugin @@ -150,7 +150,7 @@ Insert gRPC and protobuf Java code generator plugin **** tag of the pro -------------------------------------------------------------------------- +---- You can also run the compiler for any additional supported languages you require manually. @@ -245,14 +245,14 @@ To use Protobuf in your Camel routes, you need to add the dependency on .Example pom.xml for `camel-protobuf` [source,xml] ------------------------------------------ +---- org.apache.camel camel-protobuf x.x.x ------------------------------------------ +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-pubnub/src/main/docs/pubnub-component.adoc b/components/camel-pubnub/src/main/docs/pubnub-component.adoc index cbbaf9c484f70..3b623c66c128d 100644 --- a/components/camel-pubnub/src/main/docs/pubnub-component.adoc +++ b/components/camel-pubnub/src/main/docs/pubnub-component.adoc @@ -30,20 +30,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-pubnub x.x.x ------------------------------------------------------------- +---- == URI format ------------------------- +---- pubnub:channel[?options] ------------------------- +---- Where *channel* is the PubNub channel to publish or subscribe to. diff --git a/components/camel-quartz/src/main/docs/quartz-component.adoc b/components/camel-quartz/src/main/docs/quartz-component.adoc index 65587643ff380..86974a71f1226 100644 --- a/components/camel-quartz/src/main/docs/quartz-component.adoc +++ b/components/camel-quartz/src/main/docs/quartz-component.adoc @@ -21,14 +21,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-quartz x.x.x ------------------------------------------------------------- +---- == URI format diff --git a/components/camel-reactive-streams/src/main/docs/reactive-streams-component.adoc b/components/camel-reactive-streams/src/main/docs/reactive-streams-component.adoc index 8c05f4d7d7b9c..6d2df02a00267 100644 --- a/components/camel-reactive-streams/src/main/docs/reactive-streams-component.adoc +++ b/components/camel-reactive-streams/src/main/docs/reactive-streams-component.adoc @@ -33,20 +33,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-reactive-streams x.x.x ------------------------------------------------------------- +---- == URI format -------------------------------------------------- +---- reactive-streams://stream?[options] -------------------------------------------------- +---- Where *stream* is a logical stream name used to bind Camel routes to the external stream processing systems. diff --git a/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc b/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc index 99230fdc6a5cf..d77a5eda25338 100644 --- a/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc +++ b/components/camel-rest-openapi/src/main/docs/rest-openapi-component.adoc @@ -31,20 +31,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-rest-openapi x.x.x ------------------------------------------------------------- +---- == URI format -------------------------------------------------------- +---- rest-openapi:[specificationPath#]operationId -------------------------------------------------------- +---- Where `operationId` is the ID of the operation in the OpenApi specification, and `specificationPath` is the path to the diff --git a/components/camel-rss/src/main/docs/rss-component.adoc b/components/camel-rss/src/main/docs/rss-component.adoc index b2a3c1bff0c28..0ba653f53d6c0 100644 --- a/components/camel-rss/src/main/docs/rss-component.adoc +++ b/components/camel-rss/src/main/docs/rss-component.adoc @@ -21,22 +21,22 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-rss x.x.x ------------------------------------------------------------- +---- NOTE: The component currently only supports consuming feeds. == URI format ----------- +---- rss:rssUri ----------- +---- Where `rssUri` is the URI to the RSS feed to poll. diff --git a/components/camel-sap-netweaver/src/main/docs/sap-netweaver-component.adoc b/components/camel-sap-netweaver/src/main/docs/sap-netweaver-component.adoc index 63b7b7087cf36..1f410b3ee3507 100644 --- a/components/camel-sap-netweaver/src/main/docs/sap-netweaver-component.adoc +++ b/components/camel-sap-netweaver/src/main/docs/sap-netweaver-component.adoc @@ -24,22 +24,22 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-sap-netweaver x.x.x ------------------------------------------------------------- +---- == URI format The URI scheme for a sap netweaver gateway component is as follows ------------------------------------------------------------------ +---- sap-netweaver:https://host:8080/path?username=foo&password=secret ------------------------------------------------------------------ +---- == Prerequisites @@ -66,9 +66,9 @@ http://scn.sap.com/docs/DOC-31221[here]. In the route below we request the SAP NetWeaver demo server using the following url ----------------------------------------------------------------------- +---- https://sapes4.sapdevcenter.com/sap/opu/odata/IWFND/RMTSAMPLEFLIGHT ----------------------------------------------------------------------- +---- And we want to execute the following command @@ -111,7 +111,7 @@ The velocity template is used for formatting the response to a basic HTML page [source,xml] ------------------------------------------------------------------------- +---- Flight information: @@ -126,11 +126,11 @@ HTML page ------------------------------------------------------------------------- +---- When running the application, you get sample output: -------------------------------- +---- Flight information: Airline ID: AA Aircraft Type: 747-400 @@ -138,7 +138,7 @@ Departure city: new york Departure airport: JFK Destination city: SAN FRANCISCO Destination airport: SFO -------------------------------- +---- diff --git a/components/camel-saxon/src/main/docs/xquery-component.adoc b/components/camel-saxon/src/main/docs/xquery-component.adoc index 3ae66af22d1f5..512ed28559fc7 100644 --- a/components/camel-saxon/src/main/docs/xquery-component.adoc +++ b/components/camel-saxon/src/main/docs/xquery-component.adoc @@ -113,7 +113,7 @@ If you prefer to configure your routes in your Spring XML file, then you can use XPath expressions as follows [source,xml] ---------------------------------------------------------------------------------------------------------------- +---- ---------------------------------------------------------------------------------------------------------------- +---- Notice how we can reuse the namespace prefixes, *foo* in this case, in the XPath expression for easier namespace-based XQuery expressions! @@ -141,9 +141,9 @@ type conversion which is done in the xml configuration via the *@type* attribute: [source,xml] -------------------------------------------------------------------------------- +---- concat('mock:foo.', /person/@city) -------------------------------------------------------------------------------- +---- === Using XQuery as an endpoint @@ -157,7 +157,7 @@ The following example shows how to take a message of an ActiveMQ queue (MyQueue) and transform it using XQuery and send it to MQSeries. [source,xml] -------------------------------------------------------------------------- +---- @@ -165,7 +165,7 @@ The following example shows how to take a message of an ActiveMQ queue -------------------------------------------------------------------------- +---- === Loading script from external resource @@ -198,13 +198,13 @@ If you use Maven, you could add the following to your `pom.xml`, substituting the version number for the latest release. [source,xml] --------------------------------------- +---- org.apache.camel camel-saxon x.x.x --------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-saxon/src/main/docs/xquery-language.adoc b/components/camel-saxon/src/main/docs/xquery-language.adoc index a1bb3c2dcb676..07961544189d9 100644 --- a/components/camel-saxon/src/main/docs/xquery-language.adoc +++ b/components/camel-saxon/src/main/docs/xquery-language.adoc @@ -177,7 +177,7 @@ In the XML example below we use Spring XML where the namespace is declared in th in the line with `xmlns:foo="http://example.com/person"`: [source,xml] ---------------------------------------------------------------------------------------------------------------- +---- ---------------------------------------------------------------------------------------------------------------- +---- This namespace uses `foo` as prefix, so the `` expression uses `foo:` to use this namespace. @@ -256,14 +256,14 @@ If you want to use Camel variables like headers, you have to explicitly declare them in the XQuery expression. [source,xml] -------------------------------------------------------------- +---- declare variable $in.headers.foo external; element item {$in.headers.foo} -------------------------------------------------------------- +---- == Loading script from external resource @@ -295,13 +295,13 @@ If you use Maven you could add the following to your `pom.xml`, substituting the version number for the latest & greatest release. [source,xml] --------------------------------------- +---- org.apache.camel camel-saxon x.x.x --------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc b/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc index b84824bfb1a55..ba0fc87054545 100644 --- a/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc +++ b/components/camel-servicenow/camel-servicenow-component/src/main/docs/servicenow-component.adoc @@ -22,19 +22,19 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] -------------------------------------------------- +---- org.apache.camel camel-servicenow ${camel-version} -------------------------------------------------- +---- == URI format ---------------------------------------- +---- servicenow://instanceName?[options] ---------------------------------------- +---- @@ -135,7 +135,7 @@ https://docs.servicenow.com/bundle/helsinki-servicenow-platform/page/integrate/i ._Java-only: retrieving 10 Incidents with FluentProducerTemplate_ [source,java] .Retrieve 10 Incidents -------------------------------------------------------------------------------------------------------------------- +---- context.addRoutes(new RouteBuilder() { public void configure() { from("direct:servicenow") @@ -156,7 +156,7 @@ FluentProducerTemplate.on(context) .withHeader(ServiceNowConstants.MODEL, Incident.class) .to("direct:servicenow") .send(); -------------------------------------------------------------------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-servlet/src/main/docs/servlet-component.adoc b/components/camel-servlet/src/main/docs/servlet-component.adoc index 50017e3726308..864174a700702 100644 --- a/components/camel-servlet/src/main/docs/servlet-component.adoc +++ b/components/camel-servlet/src/main/docs/servlet-component.adoc @@ -22,14 +22,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ---------------------------------------------------------------- +---- org.apache.camel camel-servlet x.x.x ---------------------------------------------------------------- +---- [NOTE] @@ -47,9 +47,9 @@ a `String` which is safe to be read multiple times. == URI format ---------------------------------- +---- servlet://relative_path[?options] ---------------------------------- +---- // component options: START @@ -172,7 +172,7 @@ If you're running Camel standalone on a Servlet container or application server, For example, to define a route that exposes an HTTP service under the path `/services`. [source,xml] -------------------------------------------------------------------------- +---- CamelServlet @@ -184,13 +184,13 @@ For example, to define a route that exposes an HTTP service under the path `/ser /services/* -------------------------------------------------------------------------- +---- === Example route ._Java-only: inline Processor with Exchange API and string concatenation_ [source,java] -------------------------------------------------------------------------- +---- from("servlet:hello").process(new Processor() { public void process(Exchange exchange) throws Exception { // Access HTTP headers sent by the client @@ -202,7 +202,7 @@ from("servlet:hello").process(new Processor() { message.setBody("Got Content-Type: " + contentType = ", URI: " + httpUri + ""); } }); -------------------------------------------------------------------------- +---- === Camel Servlet HTTP endpoint path @@ -229,7 +229,7 @@ On the Camel Quarkus runtime, these init parameters can be set via configuration On other runtimes you can configure these parameters in `web.xml` as follows. [source,xml] ------------------------------------------------------------------------------------------------ +---- CamelServlet @@ -249,7 +249,7 @@ On other runtimes you can configure these parameters in `web.xml` as follows. /services/* ------------------------------------------------------------------------------------------------ +---- === Camel JARs on an application server boot classpath @@ -261,7 +261,7 @@ WARNING: Having Camel JARs on the boot classpath of the application server is no In this scenario, you *must* define a custom and unique servlet name in each of your Camel applications. For example, in `web.xml`: [source,xml] ---------------------------------------------------------------------------------------------- +---- MyServlet @@ -274,7 +274,7 @@ In this scenario, you *must* define a custom and unique servlet name in each of /* ---------------------------------------------------------------------------------------------- +---- In your Camel servlet endpoints, include the servlet name: @@ -283,9 +283,9 @@ In your Camel servlet endpoints, include the servlet name: Java:: + [source,java] ---------------------------------------------------- +---- from("servlet://foo?servletName=MyServlet") ---------------------------------------------------- +---- XML:: + @@ -318,7 +318,7 @@ setting the servlet init parameter `ignoreDuplicateServletName` to `true` as follows: [source,xml] ------------------------------------------------------------------------------------------------ +---- CamelServlet Camel Http Transport Servlet @@ -328,7 +328,7 @@ follows: true ------------------------------------------------------------------------------------------------ +---- But it is *strongly advised* to use unique `servlet-name` for each Camel application to avoid this duplication clash, as well any unforeseen diff --git a/components/camel-shiro/src/main/docs/shiro.adoc b/components/camel-shiro/src/main/docs/shiro.adoc index 414684c02b996..53ae4b3916457 100644 --- a/components/camel-shiro/src/main/docs/shiro.adoc +++ b/components/camel-shiro/src/main/docs/shiro.adoc @@ -25,14 +25,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-shiro x.x.x ------------------------------------------------------------- +---- == Usage @@ -63,7 +63,7 @@ Ini file (properties file) or an Ini object. The Ini file is a standard Shiro configuration file containing user/role details as shown below [source,properties] ------------------------------------------------------------------- +---- [users] # user 'ringo' with password 'starr' and the 'sec-level1' role ringo = starr, sec-level1 @@ -83,7 +83,7 @@ sec-level2 = zone1:* # The 'sec-level1' role can do anything with access of permission # readonly sec-level1 = zone1:readonly:* ------------------------------------------------------------------- +---- [[ShiroSecurity-InstantiatingaShiroSecurityPolicyObject]] === Instantiating a ShiroSecurityPolicy Object @@ -92,7 +92,7 @@ A ShiroSecurityPolicy object is instantiated as follows ._Java-only: Java class instantiation and configuration_ [source,java] ----------------------------------------------------------------------------------------- +---- private final String iniResourcePath = "classpath:shiro.ini"; private final byte[] passPhrase = { (byte) 0x08, (byte) 0x09, (byte) 0x0A, (byte) 0x0B, @@ -105,7 +105,7 @@ A ShiroSecurityPolicy object is instantiated as follows final ShiroSecurityPolicy securityPolicy = new ShiroSecurityPolicy(iniResourcePath, passPhrase, true, permissionsList); ----------------------------------------------------------------------------------------- +---- [[ShiroSecurity-ShiroSecurityPolicyOptions]] === ShiroSecurityPolicy Options @@ -167,7 +167,7 @@ the user is a valid user. ._Java-only: Java RouteBuilder with security policy_ [source,java] ------------------------------------------------------------------------ +---- protected RouteBuilder createRouteBuilder() throws Exception { final ShiroSecurityPolicy securityPolicy = new ShiroSecurityPolicy("classpath:shiro.ini", passPhrase); @@ -190,7 +190,7 @@ the user is a valid user. } }; } ------------------------------------------------------------------------ +---- [[ShiroSecurity-ApplyingShiroAuthorizationonaCamelRoute]] ==== Applying Shiro Authorization on a Camel Route @@ -203,7 +203,7 @@ permission set, the request is not authorized to continue any further. ._Java-only: Java RouteBuilder with security policy_ [source,java] -------------------------------------------------------------------------------------------- +---- protected RouteBuilder createRouteBuilder() throws Exception { final ShiroSecurityPolicy securityPolicy = new ShiroSecurityPolicy("./src/test/resources/securityconfig.ini", passPhrase); @@ -226,7 +226,7 @@ permission set, the request is not authorized to continue any further. } }; } -------------------------------------------------------------------------------------------- +---- [[ShiroSecurity-CreatingaShiroSecurityTokenandinjectingitintoaMessageExchange]] === Creating a ShiroSecurityToken and injecting it into a Message Exchange @@ -238,7 +238,7 @@ ShiroSecurityTokenInjector in the client is shown below ._Java-only: Java security token injection_ [source,java] -------------------------------------------------------------------------------------- +---- ShiroSecurityToken shiroSecurityToken = new ShiroSecurityToken("ringo", "starr"); ShiroSecurityTokenInjector shiroSecurityTokenInjector = new ShiroSecurityTokenInjector(shiroSecurityToken, passPhrase); @@ -246,7 +246,7 @@ ShiroSecurityTokenInjector in the client is shown below from("direct:client"). process(shiroSecurityTokenInjector). to("direct:secureEndpoint"); -------------------------------------------------------------------------------------- +---- [[ShiroSecurity-SendingMessagestoroutessecuredbyaShiroSecurityPolicy]] === Sending Messages to routes secured by a ShiroSecurityPolicy @@ -262,7 +262,7 @@ ProducerTemplate in Camel along with a SecurityToken ._Java-only: Java test method (ProducerTemplate)_ [source,java] -------------------------------------------------------------------------------------------------- +---- @Test public void testSuccessfulShiroAuthenticationWithNoAuthorization() throws Exception { @@ -281,7 +281,7 @@ ProducerTemplate in Camel along with a SecurityToken successEndpoint.assertIsSatisfied(); failureEndpoint.assertIsSatisfied(); } -------------------------------------------------------------------------------------------------- +---- [[ShiroSecurity-UsingShiroSecurityToken]] === Using ShiroSecurityToken @@ -293,23 +293,23 @@ contains the username and password. For example: ._Java-only: Java test API (ProducerTemplate)_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------------------- +---- ShiroSecurityToken shiroSecurityToken = new ShiroSecurityToken("ringo", "starr"); template.sendBodyAndHeader("direct:secureEndpoint", "Beatle Mania", ShiroSecurityConstants.SHIRO_SECURITY_TOKEN, shiroSecurityToken); ---------------------------------------------------------------------------------------------------------------------------------------------- +---- You can also provide the username and password in two different headers as shown below: ._Java-only: Java test API (ProducerTemplate)_ [source,java] --------------------------------------------------------------------------------------- +---- Map headers = new HashMap(); headers.put(ShiroSecurityConstants.SHIRO_SECURITY_USERNAME, "ringo"); headers.put(ShiroSecurityConstants.SHIRO_SECURITY_PASSWORD, "starr"); template.sendBodyAndHeaders("direct:secureEndpoint", "Beatle Mania", headers); --------------------------------------------------------------------------------------- +---- When you use the username and password headers, then the ShiroSecurityPolicy in the Camel route will automatically transform those diff --git a/components/camel-sjms/src/main/docs/sjms-component.adoc b/components/camel-sjms/src/main/docs/sjms-component.adoc index a2204e18c47f4..4a9e8343a9a5f 100644 --- a/components/camel-sjms/src/main/docs/sjms-component.adoc +++ b/components/camel-sjms/src/main/docs/sjms-component.adoc @@ -148,12 +148,12 @@ setting the `CamelJmsDestinationName` header as follows: ._Java-only: setting JMS destination header dynamically_ [source,java] -------------------------------------------------------------------------- +---- public void setJmsHeader(Exchange exchange) { String id = .... exchange.getIn().setHeader("CamelJmsDestinationName", "order:" + id"); } -------------------------------------------------------------------------- +---- Then Camel will read this header and use it as the destination instead of the one configured on the endpoint. So, in this example Camel sends diff --git a/components/camel-sjms2/src/main/docs/sjms2-component.adoc b/components/camel-sjms2/src/main/docs/sjms2-component.adoc index 2a09e32ab51bf..1d711ad1e3601 100644 --- a/components/camel-sjms2/src/main/docs/sjms2-component.adoc +++ b/components/camel-sjms2/src/main/docs/sjms2-component.adoc @@ -152,12 +152,12 @@ setting the `CamelJmsDestinationName` header as follows: ._Java-only: programmatic header manipulation with Exchange API_ [source,java] -------------------------------------------------------------------------- +---- public void setJmsHeader(Exchange exchange) { String id = .... exchange.getIn().setHeader("CamelJmsDestinationName", "order:" + id"); } -------------------------------------------------------------------------- +---- Then Camel will read this header and use it as the destination instead of the one configured on the endpoint. So, in this example Camel sends @@ -184,10 +184,10 @@ then using toD could, for example, be done as follows: Java:: + [source,java] --------------------------------- +---- from("direct:order") .toD("sjms2:order-${header.orderType}"); --------------------------------- +---- XML:: + diff --git a/components/camel-slack/src/main/docs/slack-component.adoc b/components/camel-slack/src/main/docs/slack-component.adoc index 8a119909c2d27..7930ffcfa3678 100644 --- a/components/camel-slack/src/main/docs/slack-component.adoc +++ b/components/camel-slack/src/main/docs/slack-component.adoc @@ -21,28 +21,28 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-slack x.x.x ------------------------------------------------------------- +---- == URI format To send a message to a channel. ------------------------- +---- slack:#channel[?options] ------------------------- +---- To send a direct message to a Slack user. -------------------------- +---- slack:@userID[?options] -------------------------- +---- @@ -64,12 +64,12 @@ The SlackComponent with XML must be configured as a Spring bean that contains th parameter. [source,xml] ------------------------------------------------------------------------------------------------------------------------ +---- ------------------------------------------------------------------------------------------------------------------------ +---- NOTE: for Java, you can configure this using Java code. @@ -116,7 +116,7 @@ You can now use the Slack API model to create blocks. You can read more about it ._Java-only: creating Slack Block Kit messages with the API model_ [source,java] ---------------------------------------------------------------------------------------------------------------------------- +---- public void testSlackAPIModelMessage() { Message message = new Message(); message.setBlocks(Collections.singletonList(SectionBlock @@ -129,7 +129,7 @@ You can now use the Slack API model to create blocks. You can read more about it template.sendBody(test, message); } ---------------------------------------------------------------------------------------------------------------------------- +---- You'll need to create a Slack app and use it in your workspace. diff --git a/components/camel-smpp/src/main/docs/smpp-component.adoc b/components/camel-smpp/src/main/docs/smpp-component.adoc index ee1d117302826..e23aa78857b50 100644 --- a/components/camel-smpp/src/main/docs/smpp-component.adoc +++ b/components/camel-smpp/src/main/docs/smpp-component.adoc @@ -32,14 +32,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-smpp x.x.x ------------------------------------------------------------- +---- [TIP] ==== @@ -159,10 +159,10 @@ throttling messages in the SMPP route before handing them to the SMSC. == URI format --------------------------------------------- +---- smpp://[username@]hostname[:port][?options] smpps://[username@]hostname[:port][?options] --------------------------------------------- +---- If no *username* is provided, then Camel will provide the default value `smppclient`. + @@ -201,14 +201,14 @@ following lines of code: ._Java-only: uses doTry/doCatch with Exception.class literal and ProcessRequestException constructor_ [source,java] --------------------------------------------------------------------------------------------------------------------------- +---- from("smpp://smppclient@localhost:2775?password=password&enquireLinkTimer=3000&transactionTimer=5000&systemType=consumer") .doTry() .to("bean:dao?method=updateSmsState") .doCatch(Exception.class) .throwException(new ProcessRequestException("update of sms state failed", 100)) .end(); --------------------------------------------------------------------------------------------------------------------------- +---- Please refer to the http://smsforum.net/SMPP_v3_4_Issue1_2.zip[SMPP specification] for the complete list of error codes and their meanings. @@ -299,14 +299,14 @@ An example of using transceiver (TRX) binding type: ._Java-only: multi-route definition with string concatenation and route id assignment_ [source,java] --------------------------------------------------------------------------------------------------------------------------- +---- from("direct:start") .to("smpp://j@localhost:8056?password=jpwd&systemType=producer" + "&messageReceiverRouteId=sampleMessageReceiverRouteId"); from("direct:messageReceiver").id("sampleMessageReceiverRouteId") .to("bean:foo"); --------------------------------------------------------------------------------------------------------------------------- +---- Please note that with TRX binding type, you wouldn't define a corresponding redundant SMPP consumer. Camel will use the specified route by `messageReceiverRouteId` as the corresponding consumer. Internally, it uses one and same SmppSession @@ -331,9 +331,9 @@ problems. If you use log4j, you can add the following line to your configuration: [source,properties] --------------------------------------------------- +---- log4j.logger.org.apache.camel.component.smpp=DEBUG --------------------------------------------------- +---- diff --git a/components/camel-snakeyaml/src/main/docs/snakeYaml-dataformat.adoc b/components/camel-snakeyaml/src/main/docs/snakeYaml-dataformat.adoc index 190a38aabd86b..26d517ec75f01 100644 --- a/components/camel-snakeyaml/src/main/docs/snakeYaml-dataformat.adoc +++ b/components/camel-snakeyaml/src/main/docs/snakeYaml-dataformat.adoc @@ -74,17 +74,17 @@ YAML DSL:: ._Java-only: selecting the SnakeYAML library explicitly_ [source,java] ------------------------------------------------------------- +---- from("activemq:My.Queue") .marshal().yaml(YAMLLibrary.SnakeYAML) .to("mqseries:Another.Queue"); ------------------------------------------------------------- +---- - Restrict classes to be loaded from YAML ._Java-only: programmatic type filter configuration_ [source,java] ------------------------------------------------------------- +---- // Creat a SnakeYAMLDataFormat instance SnakeYAMLDataFormat yaml = new SnakeYAMLDataFormat(); @@ -94,7 +94,7 @@ yaml.addTypeFilters(TypeFilters.types(MyPojo.class, MyOtherPojo.class)); from("activemq:My.Queue") .unmarshal(yaml) .to("mqseries:Another.Queue"); ------------------------------------------------------------- +---- == Using YAML in Spring DSL @@ -103,7 +103,7 @@ declare the data formats first. This is done in the *DataFormats* XML tag. [source,xml] --------------------------------------------------------------------------------- +---- ------------------------------------------------------------------------------------------------------ +---- And in the Camel route [source,xml] ---------------------------------------------------------------------------------------------------------------- +---- @@ -128,7 +128,7 @@ And in the Camel route ---------------------------------------------------------------------------------------------------------------- +---- == Multi-part Messages @@ -150,10 +150,10 @@ request parameters or response parameters. ._Java-only: Java class instantiation_ [source,java] -------------------------------------------------------------------------------------------------------------------------------------------- +---- ServiceInterfaceStrategy strat = new ServiceInterfaceStrategy(com.example.customerservice.multipart.MultiPartCustomerService.class, true); SoapDataFormat soapDataFormat = new SoapDataFormat("com.example.customerservice.multipart", strat); -------------------------------------------------------------------------------------------------------------------------------------------- +---- === Holder Object mapping @@ -173,7 +173,7 @@ response or fault. ._Java-only: Java programmatic data format with exception handling_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------------- +---- String WS_URI = "cxf://http://myserver/customerservice?serviceClass=com.example.customerservice&dataFormat=RAW"; SoapDataFormat soapDF = new SoapDataFormat("com.example.customerservice", new ServiceInterfaceStrategy(CustomerService.class)); from("direct:customerServiceClient") @@ -184,14 +184,14 @@ from("direct:customerServiceClient") .marshal(soapDF) .to(WS_URI) .unmarshal(soapDF); ---------------------------------------------------------------------------------------------------------------------------------------- +---- The below snippet creates a proxy for the service interface and makes a SOAP call to the above route. ._Java-only: Java proxy API_ [source,java] ---------------------------------------------------------------------------------------------------- +---- import org.apache.camel.Endpoint; import org.apache.camel.component.bean.ProxyHelper; ... @@ -201,7 +201,7 @@ ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); // CustomerService below is the service endpoint interface, *not* the javax.xml.ws.Service subclass CustomerService proxy = ProxyHelper.createProxy(startEndpoint, classLoader, CustomerService.class); GetCustomersByNameResponse response = proxy.getCustomersByName(new GetCustomersByName()); ---------------------------------------------------------------------------------------------------- +---- === Webservice Server @@ -213,7 +213,7 @@ server class it could be defined in a spring context as a regular bean. ._Java-only: Java programmatic data format with bean processing_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------------- +---- SoapDataFormat soapDF = new SoapDataFormat("com.example.customerservice", new ServiceInterfaceStrategy(CustomerService.class)); CustomerService serverBean = new CustomerServiceImpl(); from("jms://queue:customerServiceQueue") @@ -224,7 +224,7 @@ from("jms://queue:customerServiceQueue") .unmarshal(soapDF) .bean(serverBean) .marshal(soapDF); ---------------------------------------------------------------------------------------------------------------------------------------- +---- == Dependencies @@ -232,13 +232,13 @@ To use the SOAP dataformat in your Camel routes, you need to add the following dependency to your `pom.xml`. [source,xml] -------------------------------------- +---- org.apache.camel camel-soap x.y.z -------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-solr/src/main/docs/solr-component.adoc b/components/camel-solr/src/main/docs/solr-component.adoc index 0bab1731087aa..2d37a94485329 100644 --- a/components/camel-solr/src/main/docs/solr-component.adoc +++ b/components/camel-solr/src/main/docs/solr-component.adoc @@ -21,20 +21,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-solr x.x.x ------------------------------------------------------------- +---- == URI format --------------------------------------- +---- solr://host[:port]?[options] --------------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -178,11 +178,11 @@ delete routes and then call the commit route. ._Java-only: sending messages to Solr routes using ProducerTemplate_ [source,java] ------------------------------------------------ +---- template.sendBodyAndHeader("direct:insert", "1234", "CamelSolrParam.commit", true); template.sendBodyAndHeader("direct:delete", "1234", "CamelSolrParam.commit", true); template.sendBody("direct:search", "id:1234"); ------------------------------------------------ +---- For more information: diff --git a/components/camel-splunk-hec/src/main/docs/splunk-hec-component.adoc b/components/camel-splunk-hec/src/main/docs/splunk-hec-component.adoc index f142811160a86..20a82cb54365e 100644 --- a/components/camel-splunk-hec/src/main/docs/splunk-hec-component.adoc +++ b/components/camel-splunk-hec/src/main/docs/splunk-hec-component.adoc @@ -21,19 +21,19 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ---------------------------------------------- +---- org.apache.camel camel-splunk-hec ${camel-version} ---------------------------------------------- +---- == URI format -------------------------------- +---- splunk-hec:[splunkURL]?[options] -------------------------------- +---- @@ -102,21 +102,21 @@ you want to override the index time, you can do so. ._Java-only: uses SplunkHECConstants.INDEX_TIME Java constant_ [source,java] -------------------------------- +---- from("kafka:logs") .setHeader(SplunkHECConstants.INDEX_TIME, simple("${headers[kafka.HEADERS].lastKey('TIME')}")) .to("splunk-hec://localhost:8080?token=token"); -------------------------------- +---- [tabs] ==== Java:: + [source,java] -------------------------------- +---- from("kafka:logs") .toD("splunk-hec://localhost:8080?token=token&time=${headers[kafka.HEADERS].lastKey('TIME')}"); -------------------------------- +---- XML:: + diff --git a/components/camel-splunk/src/main/docs/splunk-component.adoc b/components/camel-splunk/src/main/docs/splunk-component.adoc index 172dd82e9637f..ca18e278bf91d 100644 --- a/components/camel-splunk/src/main/docs/splunk-component.adoc +++ b/components/camel-splunk/src/main/docs/splunk-component.adoc @@ -32,19 +32,19 @@ Maven users will need to add the following dependency to their pom.xml for this component: [source,xml] ---------------------------------------------- +---- org.apache.camel camel-splunk ${camel-version} ---------------------------------------------- +---- == URI format -------------------------------- +---- splunk://[endpoint]?[options] -------------------------------- +---- @@ -253,7 +253,7 @@ To convert a Tweet to a `SplunkEvent`, you could use a converter like: ._Java-only: custom type converter from Tweet to SplunkEvent_ [source,java] ----------------------------------------------------------------------------------- +---- @Converter public class Tweet2SplunkEvent { @Converter @@ -278,7 +278,7 @@ public class Tweet2SplunkEvent { return data; } } ----------------------------------------------------------------------------------- +---- Search Splunk for tweets: diff --git a/components/camel-spring-parent/camel-spring-batch/src/main/docs/spring-batch-component.adoc b/components/camel-spring-parent/camel-spring-batch/src/main/docs/spring-batch-component.adoc index 024468e1a8f26..ce48248a45cf9 100644 --- a/components/camel-spring-parent/camel-spring-batch/src/main/docs/spring-batch-component.adoc +++ b/components/camel-spring-parent/camel-spring-batch/src/main/docs/spring-batch-component.adoc @@ -23,20 +23,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-spring-batch x.x.x ------------------------------------------------------------- +---- == URI format ------------------------------- +---- spring-batch:jobName[?options] ------------------------------- +---- Where *jobName* represents the name of the Spring Batch job located in the Camel registry. @@ -160,13 +160,13 @@ operations using the Spring Batch API directly. ._Java-only: accessing JobExecution from MockEndpoint_ [source,java] ---------------------------------------------------------------------------------------------------- +---- from("direct:startBatch").to("spring-batch:myJob").to("mock:JobExecutions"); ... MockEndpoint mockEndpoint = ...; JobExecution jobExecution = mockEndpoint.getExchanges().get(0).getIn().getBody(JobExecution.class); BatchStatus currentJobStatus = jobExecution.getStatus(); ---------------------------------------------------------------------------------------------------- +---- === Support classes @@ -182,7 +182,7 @@ For example, the snippet below is configuring Spring Batch to read data from JMS queue. [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -195,7 +195,7 @@ JMS queue. ------------------------------------------------------------------------------------------------ +---- ==== CamelItemWriter @@ -206,7 +206,7 @@ For example, the snippet below is configuring Spring Batch to read data from JMS queue. [source,xml] ------------------------------------------------------------------------------------------------ +---- @@ -219,7 +219,7 @@ JMS queue. ------------------------------------------------------------------------------------------------ +---- ==== CamelItemProcessor @@ -236,7 +236,7 @@ item using the http://camel.apache.org/direct.html[Direct endpoint] and the http://camel.apache.org/simple.html[Simple expression language]. [source,xml] -------------------------------------------------------------------------------------------------------------- +---- @@ -259,7 +259,7 @@ the http://camel.apache.org/simple.html[Simple expression language]. -------------------------------------------------------------------------------------------------------------- +---- ==== CamelJobExecutionListener @@ -276,7 +276,7 @@ The example snippet below sends Spring Batch job execution events to the JMS queue. [source,xml] ------------------------------------------------------------------------------------------------------------------------ +---- @@ -292,7 +292,7 @@ JMS queue. ------------------------------------------------------------------------------------------------------------------------ +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-spring-parent/camel-spring-ws/src/main/docs/spring-ws-component.adoc b/components/camel-spring-parent/camel-spring-ws/src/main/docs/spring-ws-component.adoc index eeff42f4a5fd5..46e0a77ed7a9d 100644 --- a/components/camel-spring-parent/camel-spring-ws/src/main/docs/spring-ws-component.adoc +++ b/components/camel-spring-parent/camel-spring-ws/src/main/docs/spring-ws-component.adoc @@ -25,14 +25,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-spring-ws x.x.x ------------------------------------------------------------- +---- *Be aware* Spring WS version 4.x does not support Axiom anymore (because Axiom does not support Jakarta JEE 9) @@ -40,9 +40,9 @@ for this component: The URI scheme for this component is as follows ------------------------------------------- +---- spring-ws:[mapping-type:]address[?options] ------------------------------------------- +---- To expose a web service *mapping-type* needs to be set to any of the following: @@ -244,20 +244,20 @@ can be used to transform the soap header for a soap request. If you want to use the header transformation filter, see the below example: [source,xml] ------------------------------------------------------------------- +---- ------------------------------------------------------------------- +---- Use the bead defined above in the camel endpoint [source,xml] ------------------------------------------------------------------- +---- ------------------------------------------------------------------- +---- === The custom header and attachment filtering @@ -275,9 +275,9 @@ follows: all Spring-WS endpoints [source,xml] --------------------------------------------------------------------------------- +---- --------------------------------------------------------------------------------- +---- - the local messageFilter directly on the endpoint as follows: @@ -349,7 +349,7 @@ YAML:: Spring configuration: [source,xml] ---------------------------------------------------------------------------------------------------------------------- +---- @@ -359,7 +359,7 @@ Spring configuration: ---------------------------------------------------------------------------------------------------------------------- +---- === Exposing web services @@ -379,7 +379,7 @@ your routes. _web.xml_ [source,xml] ------------------------------------------------------------------------------------------------------ +---- spring-ws @@ -391,12 +391,12 @@ _web.xml_ /* ------------------------------------------------------------------------------------------------------ +---- _spring-ws-servlet.xml_ [source,xml] ----------------------------------------------------------------------------------------------------- +---- @@ -409,7 +409,7 @@ _spring-ws-servlet.xml_ ----------------------------------------------------------------------------------------------------- +---- More information on setting up Spring-WS can be found in https://docs.spring.io/spring-ws/docs/4.0.x/reference/html/#tutorial[Writing @@ -487,7 +487,7 @@ of annotations. An example of a route using `beanname`: [source,xml] ------------------------------------------------------------------------------------------------------------------------- +---- @@ -506,7 +506,7 @@ An example of a route using `beanname`: ------------------------------------------------------------------------------------------------------------------------- +---- === POJO (un)marshalling diff --git a/components/camel-spring-parent/camel-spring/src/main/docs/spring-summary.adoc b/components/camel-spring-parent/camel-spring/src/main/docs/spring-summary.adoc index 4730b226a8977..3f99511c3c961 100644 --- a/components/camel-spring-parent/camel-spring/src/main/docs/spring-summary.adoc +++ b/components/camel-spring-parent/camel-spring/src/main/docs/spring-summary.adoc @@ -145,7 +145,7 @@ one or more 'includes' or 'excludes' elements specifying patterns to be applied to the fully qualified names of the discovered classes. e.g. [source,xml] --------------------------------------------------------------- +---- org.example.routes @@ -153,7 +153,7 @@ applied to the fully qualified names of the discovered classes. e.g. **.* --------------------------------------------------------------- +---- Exclude patterns are applied before the include patterns. If no include or exclude patterns are defined, then all the Route classes discovered in @@ -421,14 +421,14 @@ The `camel-spring` module can be used as implementation of the Camel Cron compon Maven users will need to add the following additional dependency to their `pom.xml`: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-cron x.x.x ------------------------------------------------------------- +---- Users can then use the cron component inside routes of their Spring or Spring Boot application: diff --git a/components/camel-sql/src/main/docs/sql-component.adoc b/components/camel-sql/src/main/docs/sql-component.adoc index d0ca70c5298db..52be8b127012e 100644 --- a/components/camel-sql/src/main/docs/sql-component.adoc +++ b/components/camel-sql/src/main/docs/sql-component.adoc @@ -810,7 +810,7 @@ Here is the SQL query used to create the tables. Replace `"aggregation"` with your aggregator repository name. [source,sql] ------ +---- CREATE TABLE aggregation ( id varchar(255) NOT NULL, exchange blob NOT NULL, @@ -823,7 +823,7 @@ CREATE TABLE aggregation_completed ( version BIGINT NOT NULL, constraint aggregation_completed_pk PRIMARY KEY (id) ); ------ +---- === Storing body and headers as text diff --git a/components/camel-stax/src/main/docs/stax-component.adoc b/components/camel-stax/src/main/docs/stax-component.adoc index 4ea503605a860..7cab64744ef28 100644 --- a/components/camel-stax/src/main/docs/stax-component.adoc +++ b/components/camel-stax/src/main/docs/stax-component.adoc @@ -23,33 +23,33 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-stax x.x.x ------------------------------------------------------------- +---- == URI format --------------------------- +---- stax:content-handler-class --------------------------- +---- example: ------------------------------------ +---- stax:org.superbiz.FooContentHandler ------------------------------------ +---- You can look up a `org.xml.sax.ContentHandler` bean from the Registry using the # syntax as shown: ---------------- +---- stax:#myHandler ---------------- +---- @@ -69,7 +69,7 @@ Here is an example: ._Java-only: inline Processor class_ [source,java] --------------------------------------------------------------------------------------------------------- +---- from("file:target/in") .to("stax:org.superbiz.handler.CountingHandler") // CountingHandler implements org.xml.sax.ContentHandler or extends org.xml.sax.helpers.DefaultHandler @@ -80,7 +80,7 @@ from("file:target/in") // do some great work with the handler } }); --------------------------------------------------------------------------------------------------------- +---- === Iterate over a collection using JAXB and StAX @@ -90,7 +90,7 @@ For instance, a list of records in a wrapper object: ._Java-only: Java JAXB annotated class_ [source,java] -------------------------------------------------- +---- import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; @@ -111,13 +111,13 @@ public class Records { return record; } } -------------------------------------------------- +---- and ._Java-only: Java JAXB annotated class_ [source,java] ---------------------------------------------------------- +---- import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; @@ -148,12 +148,12 @@ public class Record { this.value = value; } } ---------------------------------------------------------- +---- Then you get an XML file to process: [source,xml] -------------------------------------------------------- +---- @@ -163,18 +163,18 @@ Then you get an XML file to process: -------------------------------------------------------- +---- The StAX component provides an `StAXBuilder` which can be used when iterating XML elements with the Camel Splitter ._Java-only: Java static method with class literal_ [source,java] ------------------------------------------- +---- from("file:target/in") .split(stax(Record.class)).streaming() .to("mock:records"); ------------------------------------------- +---- Where `stax` is a static method on `org.apache.camel.component.stax.StAXBuilder` which you can have static @@ -184,11 +184,11 @@ off by setting the boolean parameter to false, as shown below: ._Java-only: Java static method with class literal_ [source,java] -------------------------------------------------- +---- from("file:target/in") .split(stax(Record.class, false)).streaming() .to("mock:records"); -------------------------------------------------- +---- Alternatively, the example above could be implemented as follows in Spring XML diff --git a/components/camel-stitch/src/main/docs/stitch-component.adoc b/components/camel-stitch/src/main/docs/stitch-component.adoc index 1aba630e8a5fa..006e96997e2f0 100644 --- a/components/camel-stitch/src/main/docs/stitch-component.adoc +++ b/components/camel-stitch/src/main/docs/stitch-component.adoc @@ -25,21 +25,21 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-stitch x.x.x ------------------------------------------------------------- +---- == URI format ------------------------------- +---- stitch:[tableName]//[?options] ------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -65,7 +65,7 @@ This allows camel route to consume and produce events asynchronously without blo ._Java-only: Java lambda Processor with Stitch SDK builders_ .Example showing how to produce data to Stitch from a custom processor: [source,java] --------------------------------------------------------------------------------- +---- from("direct:sendStitch") .process(exchange -> { final StitchMessage stitchMessage = StitchMessage.builder() @@ -82,7 +82,7 @@ from("direct:sendStitch") exchange.getMessage().setBody(stitchRequestBody); }) .to("stitch:table_1?token=RAW({{token}})"); --------------------------------------------------------------------------------- +---- === Message body type @@ -108,7 +108,7 @@ Here is list of examples showing data that can be proceeded to Stitch: ==== Input body type `org.apache.camel.component.stitch.client.models.StitchRequestBody`: ._Java-only: Java lambda Processor with Stitch SDK builders_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:sendStitch") .process(exchange -> { final StitchMessage stitchMessage = StitchMessage.builder() @@ -125,14 +125,14 @@ from("direct:sendStitch") exchange.getMessage().setBody(stitchRequestBody); }) .to("stitch:table_1?token=RAW({{token}})"); --------------------------------------------------------------------------------- +---- ==== Input body type `org.apache.camel.component.stitch.client.models.StitchMessage`: ._Java-only: Java lambda Processor with Stitch SDK API_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:sendStitch") .process(exchange -> { exchange.getMessage().setHeader(StitchConstants.SCHEMA, StitchSchema.builder().addKeyword("field_1", "string").build()); @@ -146,13 +146,13 @@ from("direct:sendStitch") exchange.getMessage().setBody(stitchMessage); }) .to("stitch:table_1?token=RAW({{token}})"); --------------------------------------------------------------------------------- +---- ==== Input body type `Map`: ._Java-only: Java lambda Processor with Map construction_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:sendStitch") .process(exchange -> { final Map properties = new LinkedHashMap<>(); @@ -171,12 +171,12 @@ from("direct:sendStitch") exchange.getMessage().setBody(data); }) .to("stitch:table_1?token=RAW({{token}})"); --------------------------------------------------------------------------------- +---- ==== Input body type `Iterable`: ._Java-only: Java lambda Processor with Iterable construction_ [source,java] --------------------------------------------------------------------------------- +---- from("direct:sendStitch") .process(exchange -> { exchange.getMessage().setHeader(StitchConstants.SCHEMA, StitchSchema.builder().addKeyword("field_1", "string").build()); @@ -225,7 +225,7 @@ from("direct:sendStitch") exchange.getMessage().setBody(inputMessages); }) .to("stitch:table_1?token=RAW({{token}})"); --------------------------------------------------------------------------------- +---- == Development Notes (Important) diff --git a/components/camel-stringtemplate/src/main/docs/string-template-component.adoc b/components/camel-stringtemplate/src/main/docs/string-template-component.adoc index 79bcc955491d8..2da8c76305b39 100644 --- a/components/camel-stringtemplate/src/main/docs/string-template-component.adoc +++ b/components/camel-stringtemplate/src/main/docs/string-template-component.adoc @@ -23,20 +23,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-stringtemplate x.x.x ------------------------------------------------------------- +---- == URI format --------------------------------------- +---- string-template:templateName[?options] --------------------------------------- +---- Where *templateName* is the classpath-local URI of the template to invoke; or the complete URL of the remote template. @@ -106,7 +106,7 @@ code. ._Java-only: setting up a custom StringTemplate variable map_ [source,java] --------------------------------------------------------------------------- +---- Map variableMap = new HashMap(); Map headersMap = new HashMap(); headersMap.put("name", "Willem"); @@ -114,7 +114,7 @@ variableMap.put("headers", headersMap); variableMap.put("body", "Monday"); variableMap.put("exchange", exchange); exchange.getIn().setHeader("CamelStringTemplateVariableMap", variableMap); --------------------------------------------------------------------------- +---- == Examples @@ -160,13 +160,13 @@ In this sample, we want to use a string template to send an order confirmation email. The email template is laid out in `StringTemplate` as: --------------------------------------------- +---- Dear , Thanks for the order of . Regards Camel Riders Bookstore --------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc b/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc index 27e2ba63d8fd9..d26be90d31d66 100644 --- a/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc +++ b/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc @@ -187,9 +187,9 @@ the `UnTarpedMessageProcessor`. ._Java-only: inline Processor class_ [source,java] ------------------------------------------------------------------------------------------------ +---- from("activemq:queue:MY_QUEUE").unmarshal().tarFile().process(new UnTarpedMessageProcessor()); ------------------------------------------------------------------------------------------------ +---- If the Tar File has more than one entry, the usingIterator option of TarFileDataFormat to be true, and you can use splitter to do the further @@ -197,7 +197,7 @@ work. ._Java-only: Java programmatic data format configuration_ [source,java] ----------------------------------------------------------------------------------------------------- +---- TarFileDataFormat tarFile = new TarFileDataFormat(); tarFile.setUsingIterator(true); from("file:src/test/resources/org/apache/camel/dataformat/tarfile/?delay=1000&noop=true") @@ -206,20 +206,20 @@ work. .streaming() .process(new UnTarpedMessageProcessor()) .end(); ----------------------------------------------------------------------------------------------------- +---- Or you can use the TarSplitter as an expression for splitter directly like this ._Java-only: Java TarSplitter class_ [source,java] ----------------------------------------------------------------------------------------------------- +---- from("file:src/test/resources/org/apache/camel/dataformat/tarfile?delay=1000&noop=true") .split(new TarSplitter()) .streaming() .process(new UnTarpedMessageProcessor()) .end(); ----------------------------------------------------------------------------------------------------- +---- IMPORTANT: You cannot use TarSplitter in _parallel_ mode with the splitter. @@ -237,14 +237,14 @@ into a single Tar File that is stored in the output directory. ._Java-only: Java TarAggregationStrategy class_ [source,java] -------------------------------------------------- +---- from("file:input/directory?antInclude=*/.txt") .aggregate(new TarAggregationStrategy()) .constant(true) .completionFromBatchConsumer() .eagerCheckCompletion() .to("file:output/directory"); -------------------------------------------------- +---- The outgoing `CamelFileName` message header is created using java.io.File.createTempFile, with the ".tar" suffix. If you want to @@ -253,7 +253,7 @@ the `CamelFileName` header explicitly in your route: ._Java-only: Java TarAggregationStrategy class_ [source,java] ------------------------------------------------------------- +---- from("file:input/directory?antInclude=*/.txt") .aggregate(new TarAggregationStrategy()) .constant(true) @@ -261,7 +261,7 @@ the `CamelFileName` header explicitly in your route: .eagerCheckCompletion() .setHeader(Exchange.FILE_NAME, constant("reports.tar")) .to("file:output/directory"); ------------------------------------------------------------- +---- == Dependencies @@ -273,14 +273,14 @@ substituting the version number for the latest & greatest release (see the download page for the latest versions). [source,xml] ----------------------------------------------------------- +---- org.apache.camel camel-tarfile x.x.x ----------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-telegram/src/main/docs/telegram-component.adoc b/components/camel-telegram/src/main/docs/telegram-component.adoc index 30d5fe9b82eb8..00f9a570e7893 100644 --- a/components/camel-telegram/src/main/docs/telegram-component.adoc +++ b/components/camel-telegram/src/main/docs/telegram-component.adoc @@ -36,20 +36,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-telegram x.x.x ------------------------------------------------------------- +---- == URI format ----------------------------------------------------- +---- telegram:type[?options] ----------------------------------------------------- +---- @@ -188,7 +188,7 @@ The `MyBean` is a simple bean that will receive the messages ._Java-only: bean class definition_ [source,java] ---------------------------------------------------------- +---- public class MyBean { public void process(String message) { @@ -198,7 +198,7 @@ public class MyBean { } } ---------------------------------------------------------- +---- Supported types for incoming messages are @@ -268,7 +268,7 @@ The `ChatBotLogic` is a simple bean that implements a generic String-to-String m ._Java-only: bean class definition_ [source,java] ---------------------------------------------------------- +---- public class ChatBotLogic { public String chatBotProcess(String message) { @@ -280,7 +280,7 @@ public class ChatBotLogic { } } ---------------------------------------------------------- +---- Every non-null string returned by the `chatBotProcess` method is automatically routed to the @@ -387,7 +387,7 @@ You can customize the user keyboard instead of asking him to write an option. ._Java-only: inline Processor with keyboard builder API_ [source,java] ---------------------------------------------------------- +---- from("telegram:bots?authorizationToken=123456789:insertYourAuthorizationTokenHere") .process(exchange -> { @@ -416,13 +416,13 @@ from("telegram:bots?authorizationToken=123456789:insertYourAuthorizationTokenHer exchange.getIn().setBody(msg); }) .to("telegram:bots?authorizationToken=123456789:insertYourAuthorizationTokenHere"); ---------------------------------------------------------- +---- If you want to disable it, the next message must have the property `removeKeyboard` set on `ReplyKeyboardMarkup` object. ._Java-only: inline Processor with keyboard removal_ [source,java] ---------------------------------------------------------- +---- from("telegram:bots?authorizationToken=123456789:insertYourAuthorizationTokenHere") .process(exchange -> { @@ -438,7 +438,7 @@ from("telegram:bots?authorizationToken=123456789:insertYourAuthorizationTokenHer exchange.getIn().setBody(msg); }) .to("telegram:bots?authorizationToken=123456789:insertYourAuthorizationTokenHere"); ---------------------------------------------------------- +---- === Webhook Mode @@ -449,14 +449,14 @@ To enable webhook mode, users need first to add a REST implementation to their a Maven users, for example, can add *netty-http* to their `pom.xml` file: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-netty-http x.x.x ------------------------------------------------------------- +---- Once done, you need to prepend the webhook URI to the telegram URI you want to use. diff --git a/components/camel-thrift/src/main/docs/thrift-component.adoc b/components/camel-thrift/src/main/docs/thrift-component.adoc index a315e5a769925..dc72b108dc176 100644 --- a/components/camel-thrift/src/main/docs/thrift-component.adoc +++ b/components/camel-thrift/src/main/docs/thrift-component.adoc @@ -21,20 +21,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-thrift x.x.x ------------------------------------------------------------- +---- == URI format -------------------------------------- +---- thrift://service[?options] -------------------------------------- +---- @@ -52,7 +52,7 @@ different parameters to the method with the Camel body: ._Java-only: passing different parameter types in the Thrift method request body_ [source,java] -------------------------------------------------------------------------------- +---- List requestBody = new ArrayList(); requestBody.add((boolean)true); @@ -69,7 +69,7 @@ requestBody.add(new HashSet()); // set parameter requestBody.add(new HashMap()); // map parameter Object responseBody = template.requestBody("direct:thrift-alltypes", requestBody); -------------------------------------------------------------------------------- +---- Incoming parameters in the service consumer will also be passed to the message body as a list of objects. diff --git a/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc b/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc index 293b7aafb6bd1..6e434dc84e7d1 100644 --- a/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc +++ b/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc @@ -22,20 +22,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-thymeleaf x.x.x ------------------------------------------------------------- +---- == URI format -------------------------------- +---- thymeleaf:templateName[?options] -------------------------------- +---- Where *templateName* is the classpath-local URI of the template to invoke; or the complete URL of the remote template (e.g.: @@ -57,9 +57,9 @@ Thymeleaf to the Message. For example, to set the header value of `fruit` in the Thymeleaf template `fruit-template.html`: -------------------------------- +---- $in.setHeader("fruit", "Apple") -------------------------------- +---- The `fruit` header is now accessible from the `message.out.headers`. @@ -99,10 +99,10 @@ setting property `allowTemplateFromHeader=true` and setting the message header ` ._Java-only: programmatic Thymeleaf context setup via Exchange API_ [source,java] ------------------------------------------------------------------------ +---- EngineContext engineContext = new EngineContext(variableMap); exchange.getIn().setHeader("CamelThymeleafContext", engineContext); ------------------------------------------------------------------------ +---- === Hot reloading @@ -393,14 +393,14 @@ confirmation email. The email template is laid out in Thymeleaf as: .letter.html [source,text] ----------------------------------------------- +---- Dear [(${headers.lastName})], [(${headers.firstName})] Thanks for the order of [(${headers.item})]. Regards Camel Riders Bookstore [(${body})] ----------------------------------------------- +---- And the java code (from a unit test): diff --git a/components/camel-velocity/src/main/docs/velocity-component.adoc b/components/camel-velocity/src/main/docs/velocity-component.adoc index 27ba5f6b20f0f..a46fff12c752e 100644 --- a/components/camel-velocity/src/main/docs/velocity-component.adoc +++ b/components/camel-velocity/src/main/docs/velocity-component.adoc @@ -23,20 +23,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-velocity x.x.x ------------------------------------------------------------- +---- == URI format -------------------------------- +---- velocity:templateName[?options] -------------------------------- +---- Where *templateName* is the classpath-local URI of the template to invoke; or the complete URL of the remote template (e.g.: @@ -58,9 +58,9 @@ Velocity to the Message. For example, to set the header value of `fruit` in the Velocity template `.tm`: -------------------------------- +---- $in.setHeader("fruit", "Apple") -------------------------------- +---- The `fruit` header is now accessible from the `message.out.headers`. @@ -102,10 +102,10 @@ setting property `allowTemplateFromHeader=true` and setting the message header ` ._Java-only: programmatic VelocityContext creation and header manipulation_ [source,java] ------------------------------------------------------------------------ +---- VelocityContext velocityContext = new VelocityContext(variableMap); exchange.getIn().setHeader("CamelVelocityContext", velocityContext); ------------------------------------------------------------------------ +---- === Hot reloading @@ -396,14 +396,14 @@ confirmation email. The email template is laid out in Velocity as: .letter.vm [source,text] ----------------------------------------------- +---- Dear ${headers.lastName}, ${headers.firstName} Thanks for the order of ${headers.item}. Regards Camel Riders Bookstore ${body} ----------------------------------------------- +---- And the java code (from an unit test): diff --git a/components/camel-vertx/camel-vertx-http/src/main/docs/vertx-http-component.adoc b/components/camel-vertx/camel-vertx-http/src/main/docs/vertx-http-component.adoc index 70aebf6502c02..0b1dde615de7a 100644 --- a/components/camel-vertx/camel-vertx-http/src/main/docs/vertx-http-component.adoc +++ b/components/camel-vertx/camel-vertx-http/src/main/docs/vertx-http-component.adoc @@ -20,20 +20,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-vertx-http x.x.x ------------------------------------------------------------- +---- == URI format ---------------------------- +---- vertx-http:hostname[:port][/resourceUri][?options] ---------------------------- +---- @@ -147,13 +147,13 @@ instance to the registry. ._Java-only: programmatic `WebClientOptions` configuration and registry binding_ [source,java] ---------------------------- +---- WebClientOptions options = new WebClientOptions().setMaxRedirects(5) .setIdleTimeout(10) .setConnectTimeout(3); camelContext.getRegistry.bind("clientOptions", options); ---------------------------- +---- Then reference the options on the `vertx-http` producer. diff --git a/components/camel-vertx/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc b/components/camel-vertx/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc index df3eada8d9c15..bec57f54c8103 100644 --- a/components/camel-vertx/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc +++ b/components/camel-vertx/camel-vertx-websocket/src/main/docs/vertx-websocket-component.adoc @@ -20,20 +20,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-vertx-websocket x.x.x ------------------------------------------------------------- +---- == URI format ---------------------------- +---- vertx-websocket://hostname[:port][/resourceUri][?options] ---------------------------- +---- diff --git a/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc b/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc index 1922fa4b7d260..4420c88df103e 100644 --- a/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc +++ b/components/camel-vertx/camel-vertx/src/main/docs/vertx-component.adoc @@ -24,20 +24,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-vertx x.x.x ------------------------------------------------------------- +---- == URI format ---------------------------- +---- vertx:channelName[?options] ---------------------------- +---- @@ -55,12 +55,12 @@ your JVM, you can set the instance on the component level: ._Java-only: connecting to an existing Vert.x instance_ [source,java] ------------------------------------------------------ +---- Vertx vertx = ...; VertxComponent vertxComponent = new VertxComponent(); vertxComponent.setVertx(vertx); camelContext.addComponent("vertx", vertxComponent); ------------------------------------------------------ +---- diff --git a/components/camel-wasm/src/main/docs/wasm-component.adoc b/components/camel-wasm/src/main/docs/wasm-component.adoc index f940ef6526c92..41e73a9f4aac8 100644 --- a/components/camel-wasm/src/main/docs/wasm-component.adoc +++ b/components/camel-wasm/src/main/docs/wasm-component.adoc @@ -23,19 +23,19 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] -------------------------------------------------- +---- org.apache.camel camel-wasm ${camel-version} -------------------------------------------------- +---- == URI format ---------------------------------------- +---- wasm://functionName?[options] ---------------------------------------- +---- // component options: START include::partial$component-configure-options.adoc[] @@ -62,7 +62,7 @@ The module hosting the function *must* provide the functions to allocate/dealloc Here's an example of the mentioned functions implemented in https://www.rust-lang.org[Rust]: [source,rust] ---------------------------------------- +---- pub extern "C" fn alloc(size: u32) -> *mut u8 { let mut buf = Vec::with_capacity(size as usize); let ptr = buf.as_mut_ptr(); @@ -77,7 +77,7 @@ pub unsafe extern "C" fn dealloc(ptr: &mut u8, len: i32) { // Retakes the pointer which allows its memory to be freed. let _ = Vec::from_raw_parts(ptr, 0, len as usize); } ---------------------------------------- +---- ==== Data shapes @@ -88,7 +88,7 @@ containing headers the body encoded as a base64 string: ._Java-only: data exchange wrapper class for Wasm module communication_ [source,java] -------------------------------------------------- +---- public static class Wrapper { @JsonProperty public Map headers = new HashMap<>(); @@ -96,16 +96,16 @@ public static class Wrapper { @JsonProperty public byte[] body; } -------------------------------------------------- +---- ==== Data processing The component expects the processing function to have the following signature: [source,rust] ---------------------------------------- +---- fn function(ptr: u32, len: u32) -> u64 ---------------------------------------- +---- * it accepts two 32bit unsigned integers arguments ** a pointer to the memory location when the input data has been written (`ptr`) @@ -118,7 +118,7 @@ fn function(ptr: u32, len: u32) -> u64 Here's an example of a complete function: [source,rust] ---------------------------------------- +---- #[derive(Serialize, Deserialize)] struct Message { headers: HashMap, @@ -153,7 +153,7 @@ pub extern fn process(ptr: u32, len: u32) -> u64 { return ((out_ptr as u64) << 32) | out_len as u64; } ---------------------------------------- +---- == Examples diff --git a/components/camel-wasm/src/main/docs/wasm-language.adoc b/components/camel-wasm/src/main/docs/wasm-language.adoc index 15d33fcad99e5..b4c6fe8d38b47 100644 --- a/components/camel-wasm/src/main/docs/wasm-language.adoc +++ b/components/camel-wasm/src/main/docs/wasm-language.adoc @@ -37,7 +37,7 @@ The module hosting the function *must* provide the functions to allocate/dealloc Here's an example of the mentioned functions implemented in https://www.rust-lang.org[Rust]: [source,rust] ---------------------------------------- +---- pub extern "C" fn alloc(size: u32) -> *mut u8 { let mut buf = Vec::with_capacity(size as usize); let ptr = buf.as_mut_ptr(); @@ -52,7 +52,7 @@ pub unsafe extern "C" fn dealloc(ptr: &mut u8, len: i32) { // Retakes the pointer which allows its memory to be freed. let _ = Vec::from_raw_parts(ptr, 0, len as usize); } ---------------------------------------- +---- === Data shapes @@ -63,7 +63,7 @@ containing headers the body encoded as a base64 string: ._Java-only: data wrapper class definition_ [source,java] -------------------------------------------------- +---- public static class Wrapper { @JsonProperty public Map headers = new HashMap<>(); @@ -71,16 +71,16 @@ public static class Wrapper { @JsonProperty public byte[] body; } -------------------------------------------------- +---- === Data processing The component expects the processing function to have the following signature: [source,rust] ---------------------------------------- +---- fn function(ptr: u32, len: u32) -> u64 ---------------------------------------- +---- * it accepts two 32bit unsigned integers arguments ** a pointer to the memory location when the input data has been written (`ptr`) @@ -93,7 +93,7 @@ fn function(ptr: u32, len: u32) -> u64 Here's an example of a complete function: [source,rust] ---------------------------------------- +---- #[derive(Serialize, Deserialize)] struct Message { headers: HashMap, @@ -126,7 +126,7 @@ pub extern fn transform(ptr: u32, len: u32) -> u64 { return ((out_ptr as u64) << 32) | out_len as u64; } ---------------------------------------- +---- == Examples @@ -134,7 +134,7 @@ Supposing we have compiled a Wasm module containing the function above, then it ._Java-only: programmatic CamelContext and FluentProducerTemplate usage_ [source,java] ---------------------------------------- +---- try (CamelContext cc = new DefaultCamelContext()) { FluentProducerTemplate pt = cc.createFluentProducerTemplate(); @@ -158,7 +158,7 @@ Supposing we have compiled a Wasm module containing the function above, then it assertThat(out.getMessage().getBody(String.class)) .isEqualTo("HELLO"); } ---------------------------------------- +---- @@ -168,12 +168,12 @@ If you use Maven you could add the following to your `pom.xml`, substituting the version number for the latest and greatest release. [source,xml] ---------------------------------------- +---- org.apache.camel camel-wasm x.x.x ---------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-weather/src/main/docs/weather-component.adoc b/components/camel-weather/src/main/docs/weather-component.adoc index f2f002befaad4..d4d628176a07c 100644 --- a/components/camel-weather/src/main/docs/weather-component.adoc +++ b/components/camel-weather/src/main/docs/weather-component.adoc @@ -27,20 +27,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-weather x.x.x ------------------------------------------------------------- +---- == URI format ---------------------------------- +---- weather://[?options] ---------------------------------- +---- @@ -185,17 +185,17 @@ location as shown: ._Java-only: ProducerTemplate API usage_ [source,java] -------------------------------------------------------------------------------------------------------------------------------------- +---- String json = template.requestBodyAndHeader("direct:start", "", "CamelWeatherLocation", "Paris,France&appid=APIKEY", String.class); -------------------------------------------------------------------------------------------------------------------------------------- +---- And to get the weather at the current location, then: ._Java-only: ProducerTemplate API usage_ [source,java] --------------------------------------------------------------------------------------------------------------------------------- +---- String json = template.requestBodyAndHeader("direct:start", "", "CamelWeatherLocation", "current&appid=APIKEY", String.class); --------------------------------------------------------------------------------------------------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-web3j/src/main/docs/web3j-component.adoc b/components/camel-web3j/src/main/docs/web3j-component.adoc index 657540d9c12ff..59e908f997045 100644 --- a/components/camel-web3j/src/main/docs/web3j-component.adoc +++ b/components/camel-web3j/src/main/docs/web3j-component.adoc @@ -27,14 +27,14 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-web3j x.x.x ------------------------------------------------------------- +---- == URI Format diff --git a/components/camel-whatsapp/src/main/docs/whatsapp-component.adoc b/components/camel-whatsapp/src/main/docs/whatsapp-component.adoc index 84cc704438810..b9426513b8ee7 100644 --- a/components/camel-whatsapp/src/main/docs/whatsapp-component.adoc +++ b/components/camel-whatsapp/src/main/docs/whatsapp-component.adoc @@ -29,20 +29,20 @@ Maven users will need to add the following dependency to their `pom.xml` for this component: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-whatsapp x.x.x ------------------------------------------------------------- +---- == URI format ----------------------------------------------------- +---- whatsapp:type[?options] ----------------------------------------------------- +---- @@ -68,7 +68,7 @@ in Java DSL ._Java-only: inline Processor lambda with TextMessageRequest construction_ [source,java] ---------------------------------------------------------- +---- from("direct:start") .process(exchange -> { TextMessageRequest request = new TextMessageRequest(); @@ -79,7 +79,7 @@ from("direct:start") exchange.getIn().setBody(request); }) .to("whatsapp:123456789:insertYourPhoneNumberIdHere?authorizationToken=123456789:insertYourAuthorizationTokenHere"); ---------------------------------------------------------- +---- For more information you can refer to https://developers.facebook.com/docs/whatsapp/cloud-api/reference[Cloud API Reference], Supported API are: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages[Messages] and https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media[Media] === Webhook Mode @@ -90,12 +90,12 @@ To enable webhook mode, users need first to add a REST implementation to their a Maven users, for example, can add *netty-http* to their `pom.xml` file: [source,xml] ------------------------------------------------------------- +---- org.apache.camel camel-netty-http ------------------------------------------------------------- +---- Once done, you need to prepend the webhook URI to the whatsapp URI you want to use. @@ -103,9 +103,9 @@ In Java DSL: ._Java-only: uses fromF with string formatting_ [source,java] ---------------------------------------------------------- +---- fromF("webhook:whatsapp:%s?authorizationToken=%s&webhookVerifyToken=%s", "", "", "").log("${body}") ---------------------------------------------------------- +---- You can follow the https://developers.facebook.com/docs/whatsapp/cloud-api/guides/set-up-webhooks[set up webhooks guide] diff --git a/components/camel-xmlsecurity/src/main/docs/xmlSecurity-dataformat.adoc b/components/camel-xmlsecurity/src/main/docs/xmlSecurity-dataformat.adoc index 95c12a890a624..ffe83ea79ce1c 100644 --- a/components/camel-xmlsecurity/src/main/docs/xmlSecurity-dataformat.adoc +++ b/components/camel-xmlsecurity/src/main/docs/xmlSecurity-dataformat.adoc @@ -84,7 +84,7 @@ at the Document, Element, and Content levels. ._Java-only: full payload encryption using generated AES key_ [source,java] ----------------------------- +---- KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(256); Key key = keyGenerator.generateKey(); @@ -93,13 +93,13 @@ from("direct:start") .marshal().xmlSecurity(key.getEncoded()) .unmarshal().xmlSecurity(key.getEncoded() .to("direct:end"); ----------------------------- +---- === Partial Payload Content Only encryption/decryption with choice of passPhrase(password) ._Java-only: partial payload encryption with passPhrase_ [source,java] ------------------------------------------------------------------- +---- String tagXPATH = "//cheesesites/italy/cheese"; boolean secureTagContent = true; ... @@ -108,13 +108,13 @@ from("direct:start") .marshal().xmlSecurity(tagXPATH, secureTagContent, passPhrase) .unmarshal().xmlSecurity(tagXPATH, secureTagContent, passPhrase) .to("direct:end"); ------------------------------------------------------------------- +---- === Partial Payload Content Only encryption/decryption with passPhrase(password) and Algorithm ._Java-only: partial payload encryption with passPhrase and algorithm_ [source,java] ------------------------------------------------------------------------------ +---- import org.apache.xml.security.encryption.XMLCipher; .... String tagXPATH = "//cheesesites/italy/cheese"; @@ -125,7 +125,7 @@ from("direct:start") .marshal().xmlSecurity(tagXPATH, secureTagContent, passPhrase, algorithm) .unmarshal().xmlSecurity(tagXPATH, secureTagContent, passPhrase, algorithm) .to("direct:end"); ------------------------------------------------------------------------------ +---- === Partial Payload Content with Namespace support @@ -134,7 +134,7 @@ Java DSL ._Java-only: namespace-aware encryption with asymmetric key and KeyStore_ [source,java] ------------------------------------------------------------------------------------------- +---- final Map namespaces = new HashMap(); namespaces.put("cust", "http://cheese.xmlsecurity.camel.apache.org/"); @@ -150,7 +150,7 @@ context.addRoutes(new RouteBuilder() { .to("mock:encrypted"); } } ------------------------------------------------------------------------------------------- +---- [[XMLSecurityDataFormat-SpringXML]] Spring XML @@ -160,7 +160,7 @@ definition can be re-used in context within the data format `secureTag` attribute of the `xmlSecurity` element. [source,xml] ---------------------------------------------------------------------------------- +---- @@ -171,7 +171,7 @@ attribute of the `xmlSecurity` element. secureTagContents="true"/> ... ---------------------------------------------------------------------------------- +---- === Asymmetric Key Encryption @@ -179,7 +179,7 @@ attribute of the `xmlSecurity` element. Spring XML Sender [source,xml] --------------------------------------------------------------------------------------------------- +---- @@ -197,13 +197,13 @@ Spring XML Sender keyOrTrustStoreParametersRef="trustStoreParams"/> ... --------------------------------------------------------------------------------------------------- +---- [[XMLSecurityDataFormat-SpringXMLRecipient]] Spring XML Recipient [source,xml] ----------------------------------------------------------------------------------------------- +---- @@ -223,7 +223,7 @@ Spring XML Recipient keyPassword="privateKeyPassword" /> ... ----------------------------------------------------------------------------------------------- +---- == Dependencies diff --git a/components/camel-xpath/src/main/docs/xpath-language.adoc b/components/camel-xpath/src/main/docs/xpath-language.adoc index 6d0ef9fe63c71..0f5a4aed38ee0 100644 --- a/components/camel-xpath/src/main/docs/xpath-language.adoc +++ b/components/camel-xpath/src/main/docs/xpath-language.adoc @@ -793,13 +793,13 @@ If you use Maven, you could add the following to your `pom.xml`, substituting the version number for the latest & greatest release. [source,xml] --------------------------------------- +---- org.apache.camel camel-xpath x.x.x --------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-zeebe/src/main/docs/zeebe-component.adoc b/components/camel-zeebe/src/main/docs/zeebe-component.adoc index 8fe804763a166..31066b027f249 100644 --- a/components/camel-zeebe/src/main/docs/zeebe-component.adoc +++ b/components/camel-zeebe/src/main/docs/zeebe-component.adoc @@ -38,9 +38,9 @@ https://camunda.com/platform/zeebe/[Camunda Zeebe]. == URI format -------------------------------- +---- zeebe://[endpoint]?[options] -------------------------------- +---- // component options: START @@ -83,7 +83,7 @@ The endpoints accept either Java request objects as shown in the examples below ._Java-only: inline Processor with Zeebe SDK types_ [source,java] ----------------------------------------------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { ProcessRequest request = new ProcessRequest(); @@ -99,22 +99,22 @@ The endpoints accept either Java request objects as shown in the examples below long processInstanceKey = body.getProcessInstanceKey(); } }); ----------------------------------------------------------------------------------------------------------------------- +---- *JSON Request Example* [source,json] ----------------------------------------------------------------------------------------------------------------------- +---- { "process_id" : "Process_0e3ldfm", "variables" : { "v1": "a", "v2": 10 } } ----------------------------------------------------------------------------------------------------------------------- +---- *JSON Response Example* [source,json] ----------------------------------------------------------------------------------------------------------------------- +---- { "success": true, "process_id": "Process_0e3ldfm", @@ -122,13 +122,13 @@ The endpoints accept either Java request objects as shown in the examples below "process_version": 4, "process_key": 2251799813685906 } ----------------------------------------------------------------------------------------------------------------------- +---- * cancelProcess ._Java-only: inline Processor with Zeebe SDK types_ [source,java] ----------------------------------------------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { ProcessRequest request = new ProcessRequest(); @@ -142,13 +142,13 @@ The endpoints accept either Java request objects as shown in the examples below bool success = body.getSuccess(); } }); ----------------------------------------------------------------------------------------------------------------------- +---- * publishMessage ._Java-only: inline Processor with Zeebe SDK types_ [source,java] ----------------------------------------------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { MessageRequest request = new MessageRequest(); @@ -166,36 +166,36 @@ The endpoints accept either Java request objects as shown in the examples below String messageKey = body.getMessageKey(); } }); ----------------------------------------------------------------------------------------------------------------------- +---- *JSON Request Example* [source,json] ----------------------------------------------------------------------------------------------------------------------- +---- { "correlation_key" : "messageKey", "time-to-live" : 100, "variables" : { "v1": "a", "v2": 10 }, "name" : "MessageName" } ----------------------------------------------------------------------------------------------------------------------- +---- *JSON Response Example* [source,json] ----------------------------------------------------------------------------------------------------------------------- +---- { "success": true, "correlation_key": "messageKey", "message_key": 2251799813688336 } ----------------------------------------------------------------------------------------------------------------------- +---- * completeJob ._Java-only: inline Processor with Zeebe SDK types_ [source,java] ----------------------------------------------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { JobRequest request = new JobRequest(); @@ -210,13 +210,13 @@ The endpoints accept either Java request objects as shown in the examples below bool success = body.getSuccess(); } }); ----------------------------------------------------------------------------------------------------------------------- +---- * failJob ._Java-only: inline Processor with Zeebe SDK types_ [source,java] ----------------------------------------------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { JobRequest request = new JobRequest(); @@ -232,13 +232,13 @@ The endpoints accept either Java request objects as shown in the examples below bool success = body.getSuccess(); } }); ----------------------------------------------------------------------------------------------------------------------- +---- * updateJobRetries ._Java-only: inline Processor with Zeebe SDK types_ [source,java] ----------------------------------------------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { JobRequest request = new JobRequest(); @@ -253,13 +253,13 @@ The endpoints accept either Java request objects as shown in the examples below bool success = body.getSuccess(); } }); ----------------------------------------------------------------------------------------------------------------------- +---- * throwError ._Java-only: inline Processor with Zeebe SDK types_ [source,java] ----------------------------------------------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { JobRequest request = new JobRequest(); @@ -275,13 +275,13 @@ The endpoints accept either Java request objects as shown in the examples below bool success = body.getSuccess(); } }); ----------------------------------------------------------------------------------------------------------------------- +---- * deployResource ._Java-only: inline Processor with Zeebe SDK types_ [source,java] ----------------------------------------------------------------------------------------------------------------------- +---- from("direct:start") .process(exchange -> { DeploymentRequest request = new DeploymentRequest(); @@ -300,7 +300,7 @@ The endpoints accept either Java request objects as shown in the examples below String resourceName = body.getResourceName(); } }); ----------------------------------------------------------------------------------------------------------------------- +---- === Consumer Endpoints: @@ -316,7 +316,7 @@ The endpoints accept either Java request objects as shown in the examples below ._Java-only: inline Processor with Zeebe SDK types_ [source,java] ---------------------------------------------------------------------------------------------------------------------------------------------- +---- from("zeebe://worker?jobKey=job1&timeout=20") .process(exchange -> { JobWorkerMessage body = exchange.getIn().getBody(JobWorkerMessage.class); @@ -336,7 +336,7 @@ The endpoints accept either Java request objects as shown in the examples below Map variables = body.getVariables(); } }) ---------------------------------------------------------------------------------------------------------------------------------------------- +---- camel-zeebe creates a route exchange per job type with a job in the body. @@ -347,13 +347,13 @@ Maven users will need to add the following dependency to their pom.xml. *pom.xml* [source,xml] ------------------------------------------------ +---- org.apache.camel camel-zeebe ${camel-version} ------------------------------------------------ +---- where `${camel-version`} must be replaced by the actual version of Camel. diff --git a/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc b/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc index 759a12252106b..3eec770a10e74 100644 --- a/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc +++ b/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc @@ -91,12 +91,12 @@ from("activemq:queue:MY_QUEUE").unmarshal().gzipDeflater().process(new UnGZipped If you use Maven you could add the following to your `pom.xml`, substituting the version number for the latest and greatest release (see the download page for the latest versions). [source,xml] ---------------------------------------- +---- org.apache.camel camel-zip-deflater x.x.x ---------------------------------------- +---- include::spring-boot:partial$starter.adoc[] diff --git a/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc b/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc index 2c8146744569a..cf7814c789466 100644 --- a/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc +++ b/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc @@ -101,12 +101,12 @@ from("activemq:queue:MY_QUEUE").unmarshal().zipDeflater().process(new UnZippedMe If you use Maven you could add the following to your `pom.xml`, substituting the version number for the latest and greatest release (see the download page for the latest versions). [source,xml] ---------------------------------------- +---- org.apache.camel camel-zip-deflater x.x.x ---------------------------------------- +---- include::spring-boot:partial$starter.adoc[] From a104743445cf2fc7a921f32b4ced5ad6361969d9 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 11:04:49 +0200 Subject: [PATCH 86/87] CAMEL-23789: Add missing XML tab to OpenAI MCP OAuth example Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- .../camel-openai/src/main/docs/openai-component.adoc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc b/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc index f545bd2d8653f..313dcf2a1de28 100644 --- a/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc +++ b/components/camel-ai/camel-openai/src/main/docs/openai-component.adoc @@ -131,6 +131,16 @@ from("direct:chat") + "&mcpServer.tools.oauthProfile=keycloak"); ---- +XML:: ++ +[source,xml] +---- + + + + +---- + YAML:: + [source,yaml] From 49ef4cb68c3800d957fa8ac95b6b9535aef6a031 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 18 Jun 2026 11:14:51 +0200 Subject: [PATCH 87/87] CAMEL-23789: Fix unterminated listing blocks in csv and protobuf docs Co-Authored-By: Claude Signed-off-by: Claus Ibsen --- components/camel-csv/src/main/docs/csv-dataformat.adoc | 4 ++-- .../camel-protobuf/src/main/docs/protobuf-dataformat.adoc | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/components/camel-csv/src/main/docs/csv-dataformat.adoc b/components/camel-csv/src/main/docs/csv-dataformat.adoc index 4c875d026fcba..3ee3b6950e74b 100644 --- a/components/camel-csv/src/main/docs/csv-dataformat.adoc +++ b/components/camel-csv/src/main/docs/csv-dataformat.adoc @@ -235,7 +235,7 @@ Java:: from("direct:start") .marshal(new CsvDataFormat().setDelimiter('|')) .to("mock:result") -------------------------------------------------------- +---- XML:: + @@ -271,7 +271,7 @@ Then it will produce: ---- abc|123 -------------------------------------------------------- +---- [[CSV-UsingautogenColumns,configRefandstrategyRefattributesinsideXMLDSL]] Using autogenColumns, configRef and strategyRef attributes inside XML diff --git a/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc b/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc index 06ec4cd0a3e72..d57e6307f4f49 100644 --- a/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc +++ b/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc @@ -12,7 +12,6 @@ *Since Camel {since}* Protobuf - Protocol Buffers ----- "Protocol Buffers - Google's data interchange format"