From 3e02dc3d948dc32af5ce710cf442db2d15f0844b Mon Sep 17 00:00:00 2001
From: Claus Ibsen
Date: Fri, 23 Oct 2026 20:09:01 +0200
Subject: [PATCH 1/5] CAMEL-25924: kafka, ftp, dns, as2, graphql, vertx-http,
github2, pdf, tika, infinispan, snmp, jdbc, jsch, micrometer - bug fixes
CAMEL-25924 kafka: only a JSON array is split, for Jackson 2 and 3
CAMEL-25938 ftp, ftps, sftp, mina-sftp, azure-files, smb: the default of download is true in the catalog
CAMEL-25977 dns: dig defaults to type A and needs a name; wikipedia is deprecated
CAMEL-26052 as2: client/send sends bytes and files, fails on an HTTP error, requestUri default, ediMessageType deprecated, quoted-printable, logging
CAMEL-26053 graphql: the request headers of the producer win and do not stay on the message; Map bodies
CAMEL-26058 vertx-http: Path and Reader bodies, decoded urlencoded forms
CAMEL-25983 github2: getCommitFile reads the file of the commit
CAMEL-26054 pdf: pageSize values, extractText after create, line ends, no body, Path files to merge
CAMEL-26057 tika: a body that is not a stream fails clearly; the charset of the output
CAMEL-25976 infinispan-embedded: the configurationUri reads files and placeholders
CAMEL-26055 snmp: GET without type, trap body, SnmpMessage to String, the poll consumer
CAMEL-26056 jdbc: outputClass not found, generated keys, no body, docs
CAMEL-26059 jsch: scp without a known hosts file; the remote directory must exist
CAMEL-26061 micrometer: the docs say a failure fails the exchange
Co-Authored-By: Claude Opus 5.5 (1M context)
Signed-off-by: Claus Ibsen
---
.../apache/camel/catalog/components/as2.json | 4 +-
.../camel/catalog/components/azure-files.json | 2 +-
.../apache/camel/catalog/components/dns.json | 8 +-
.../apache/camel/catalog/components/ftp.json | 2 +-
.../apache/camel/catalog/components/ftps.json | 2 +-
.../camel/catalog/components/github2.json | 9 +-
.../camel/catalog/components/graphql.json | 4 +-
.../components/infinispan-embedded.json | 12 +-
.../apache/camel/catalog/components/jdbc.json | 6 +-
.../camel/catalog/components/kafka.json | 4 +-
.../camel/catalog/components/micrometer.json | 4 +-
.../camel/catalog/components/mina-sftp.json | 2 +-
.../apache/camel/catalog/components/pdf.json | 4 +-
.../apache/camel/catalog/components/sftp.json | 2 +-
.../apache/camel/catalog/components/smb.json | 2 +-
.../apache/camel/catalog/components/snmp.json | 2 +-
.../apache/camel/catalog/components/tika.json | 4 +-
.../camel/catalog/docs/as2-component.adoc | 25 +-
.../camel/catalog/docs/dns-component.adoc | 6 +-
.../camel/catalog/docs/github2-component.adoc | 6 +-
.../camel/catalog/docs/graphql-component.adoc | 20 +-
.../docs/infinispan-embedded-component.adoc | 30 ++-
.../camel/catalog/docs/jdbc-component.adoc | 15 +-
.../catalog/docs/micrometer-component.adoc | 22 +-
.../camel/catalog/docs/pdf-component.adoc | 20 ++
.../camel/catalog/docs/scp-component.adoc | 8 +
.../camel/catalog/docs/snmp-component.adoc | 15 +-
.../camel/catalog/docs/tika-component.adoc | 6 +
.../catalog/docs/vertx-http-component.adoc | 15 +-
.../as2/api/AS2AsyncMDNServerConnection.java | 4 +
.../component/as2/api/AS2ClientManager.java | 7 +-
.../as2/api/AS2ServerConnection.java | 7 +-
.../component/as2/api/util/EntityUtils.java | 47 +++-
.../api/AS2AsyncMDNServerConnectionTest.java | 29 +-
.../as2/api/AS2UnencryptedMessageTest.java | 18 ++
.../camel/component/as2/api/LogCapture.java | 70 +++++
.../as2/api/util/EntityUtilsTest.java | 33 +++
...AS2ClientManagerEndpointConfiguration.java | 2 +-
.../org/apache/camel/component/as2/as2.json | 4 +-
.../src/main/docs/as2-component.adoc | 25 +-
.../camel/component/as2/AS2Configuration.java | 6 +-
.../camel/component/as2/AS2Endpoint.java | 32 ++-
.../camel/component/as2/AS2Producer.java | 42 +++
.../component/as2/AS2ClientSendTest.java | 251 ++++++++++++++++++
.../component/file/azure/azure-files.json | 2 +-
.../org/apache/camel/component/dns/dns.json | 8 +-
.../src/main/docs/dns-component.adoc | 6 +-
.../camel/component/dns/DnsComponent.java | 3 +-
.../camel/component/dns/DnsConstants.java | 15 +-
.../camel/component/dns/DnsDigProducer.java | 24 +-
.../camel/component/dns/DnsEndpoint.java | 4 +-
.../apache/camel/component/dns/DnsType.java | 4 +
.../component/dns/DnsWikipediaProducer.java | 3 +
.../component/dns/DnsDigProducerTest.java | 88 ++++++
.../file/remote/RemoteFileEndpoint.java | 9 +-
.../camel/component/file/remote/ftp.json | 2 +-
.../camel/component/file/remote/ftps.json | 2 +-
.../camel/component/file/remote/sftp.json | 2 +-
.../camel/component/github2/github2.json | 9 +-
.../src/main/docs/github2-component.adoc | 6 +-
.../component/github2/GitHub2Constants.java | 9 +-
.../component/github2/GitHub2Endpoint.java | 2 +-
.../producer/GetCommitFileProducer.java | 75 ++++--
.../producer/GetCommitFileProducerTest.java | 161 +++++++++++
.../camel/component/graphql/graphql.json | 4 +-
.../src/main/docs/graphql-component.adoc | 20 +-
.../component/graphql/GraphqlEndpoint.java | 5 +-
.../component/graphql/GraphqlProducer.java | 75 +++++-
.../graphql/GraphqlProducerHeadersTest.java | 178 +++++++++++++
.../graphql/server/GraphqlServer.java | 15 ++
.../embedded/infinispan-embedded.json | 12 +-
.../docs/infinispan-embedded-component.adoc | 30 ++-
.../embedded/InfinispanEmbeddedComponent.java | 3 +-
.../InfinispanEmbeddedConfiguration.java | 9 +
.../embedded/InfinispanEmbeddedManager.java | 25 +-
.../InfinispanEmbeddedClusterView.java | 1 +
...EmbeddedComponentConfigurationUriTest.java | 92 +++++++
.../org/apache/camel/component/jdbc/jdbc.json | 6 +-
.../src/main/docs/jdbc-component.adoc | 15 +-
.../camel/component/jdbc/JdbcConstants.java | 4 +-
.../camel/component/jdbc/JdbcEndpoint.java | 10 +-
.../camel/component/jdbc/JdbcHelper.java | 4 +
.../camel/component/jdbc/JdbcProducer.java | 10 +-
.../JdbcGeneratedKeysOutputClassTest.java | 69 +++++
.../camel/component/jdbc/JdbcNoBodyTest.java | 62 +++++
.../jdbc/JdbcOutputClassNotFoundTest.java | 55 ++++
.../src/main/docs/scp-component.adoc | 8 +
.../camel/component/scp/ScpOperations.java | 3 +-
.../component/scp/ScpNoKnownHostsTest.java | 72 +++++
components/camel-kafka/pom.xml | 6 +
.../apache/camel/component/kafka/kafka.json | 4 +-
.../component/kafka/KafkaConfiguration.java | 3 +-
.../camel/component/kafka/KafkaProducer.java | 27 +-
.../component/kafka/KafkaProducerTest.java | 75 ++++++
.../MicrometerEndpointUriFactory.java | 2 +-
.../component/micrometer/micrometer.json | 4 +-
.../src/main/docs/micrometer-component.adoc | 22 +-
.../micrometer/MicrometerConstants.java | 2 +-
.../micrometer/MicrometerEndpoint.java | 3 +-
.../component/file/remote/mina/mina-sftp.json | 2 +-
.../pdf/converter/PdfConverterLoader.java | 16 ++
.../org/apache/camel/component/pdf/pdf.json | 4 +-
.../src/main/docs/pdf-component.adoc | 20 ++
.../camel/component/pdf/PdfConfiguration.java | 56 ++--
.../component/pdf/PdfHeaderConstants.java | 5 +-
.../component/pdf/PdfPageSizeConstant.java | 1 +
.../camel/component/pdf/PdfProducer.java | 32 ++-
.../component/pdf/converter/PdfConverter.java | 16 ++
.../LineTerminationWriterAbstractFactory.java | 39 ++-
.../camel/component/pdf/PdfAppendTest.java | 6 +-
.../camel/component/pdf/PdfConverterTest.java | 29 +-
.../camel/component/pdf/PdfCreationTest.java | 142 +++++++---
.../camel/component/pdf/PdfMergeTest.java | 64 +++--
.../component/pdf/PdfTextExtractionTest.java | 113 +++++---
.../org/apache/camel/component/smb/smb.json | 2 +-
.../camel/component/smb/SmbConfiguration.java | 9 +-
.../component/snmp/SnmpConvertersLoader.java | 8 +
.../org/apache/camel/component/snmp/snmp.json | 2 +-
.../src/main/docs/snmp-component.adoc | 15 +-
.../camel/component/snmp/SnmpConverters.java | 13 +
.../camel/component/snmp/SnmpEndpoint.java | 14 +-
.../camel/component/snmp/SnmpOIDPoller.java | 45 +---
.../camel/component/snmp/SnmpProducer.java | 4 +-
.../component/snmp/SnmpTrapProducer.java | 2 +-
.../camel/component/snmp/PollOIDIdleTest.java | 58 ++++
.../snmp/ProducerWithoutTypeTest.java | 73 +++++
.../component/snmp/TrapProducerBodyTest.java | 61 +++++
.../component/snmp/UriConfigurationTest.java | 36 +++
.../org/apache/camel/component/tika/tika.json | 4 +-
.../src/main/docs/tika-component.adoc | 6 +
.../component/tika/TikaConfiguration.java | 9 +-
.../camel/component/tika/TikaProducer.java | 13 +-
.../camel/component/tika/TikaDetectTest.java | 19 ++
.../camel/component/tika/TikaParseTest.java | 72 ++++-
.../src/main/docs/vertx-http-component.adoc | 15 +-
.../vertx/http/VertxHttpProducer.java | 47 +++-
.../http/VertxHttpRequestBodyTypesTest.java | 98 +++++++
.../pages/camel-4x-upgrade-guide-4_24.adoc | 94 +++++++
...nispanEmbeddedComponentBuilderFactory.java | 12 +-
.../dsl/KafkaComponentBuilderFactory.java | 4 +-
.../endpoint/StaticEndpointBuilders.java | 12 +-
.../dsl/AS2EndpointBuilderFactory.java | 9 +
.../dsl/DnsEndpointBuilderFactory.java | 15 +-
.../dsl/FilesEndpointBuilderFactory.java | 4 +-
.../dsl/FtpEndpointBuilderFactory.java | 4 +-
.../dsl/FtpsEndpointBuilderFactory.java | 4 +-
.../dsl/GitHub2EndpointBuilderFactory.java | 21 +-
.../dsl/GraphqlEndpointBuilderFactory.java | 7 +-
...inispanEmbeddedEndpointBuilderFactory.java | 60 +++--
.../dsl/JdbcEndpointBuilderFactory.java | 26 +-
.../dsl/KafkaEndpointBuilderFactory.java | 8 +-
.../dsl/MicrometerEndpointBuilderFactory.java | 8 +-
.../dsl/MinaSftpEndpointBuilderFactory.java | 4 +-
.../dsl/PdfEndpointBuilderFactory.java | 8 +-
.../dsl/SftpEndpointBuilderFactory.java | 4 +-
.../dsl/SmbEndpointBuilderFactory.java | 4 +-
.../dsl/SnmpEndpointBuilderFactory.java | 36 ++-
.../dsl/TikaEndpointBuilderFactory.java | 11 +-
158 files changed, 3202 insertions(+), 530 deletions(-)
create mode 100644 components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/LogCapture.java
create mode 100644 components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ClientSendTest.java
create mode 100644 components/camel-dns/src/test/java/org/apache/camel/component/dns/DnsDigProducerTest.java
create mode 100644 components/camel-github2/src/test/java/org/apache/camel/component/github2/producer/GetCommitFileProducerTest.java
create mode 100644 components/camel-graphql/src/test/java/org/apache/camel/component/graphql/GraphqlProducerHeadersTest.java
create mode 100644 components/camel-infinispan/camel-infinispan-embedded/src/test/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedComponentConfigurationUriTest.java
create mode 100644 components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcGeneratedKeysOutputClassTest.java
create mode 100644 components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcNoBodyTest.java
create mode 100644 components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcOutputClassNotFoundTest.java
create mode 100644 components/camel-jsch/src/test/java/org/apache/camel/component/scp/ScpNoKnownHostsTest.java
create mode 100644 components/camel-snmp/src/test/java/org/apache/camel/component/snmp/PollOIDIdleTest.java
create mode 100644 components/camel-snmp/src/test/java/org/apache/camel/component/snmp/ProducerWithoutTypeTest.java
create mode 100644 components/camel-snmp/src/test/java/org/apache/camel/component/snmp/TrapProducerBodyTest.java
create mode 100644 components/camel-vertx/camel-vertx-http/src/test/java/org/apache/camel/component/vertx/http/VertxHttpRequestBodyTypesTest.java
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/as2.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/as2.json
index 989fb9a25f74f..ee51bd92337cf 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/as2.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/as2.json
@@ -46,7 +46,7 @@
"dispositionNotificationTo": { "index": 10, "kind": "parameter", "displayName": "Disposition Notification To", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The value of the Disposition-Notification-To header. Assigning a value to this parameter requests a message disposition notification (MDN) for the AS2 message." },
"ediMessageCharset": { "index": 11, "kind": "parameter", "displayName": "Edi Message Charset", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "us-ascii", "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The charset of the content type of EDI message." },
"ediMessageTransferEncoding": { "index": 12, "kind": "parameter", "displayName": "Edi Message Transfer Encoding", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The transfer encoding of EDI message." },
- "ediMessageType": { "index": 13, "kind": "parameter", "displayName": "Edi Message Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "application\/edifact", "application\/edi-x12", "application\/edi-consent", "application\/xml" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The content type of EDI message. One of application\/edifact, application\/edi-x12, application\/edi-consent, application\/xml" },
+ "ediMessageType": { "index": 13, "kind": "parameter", "displayName": "Edi Message Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "application\/edifact", "application\/edi-x12", "application\/edi-consent", "application\/xml" ], "deprecated": true, "deprecationNote": "Use ediMessageContentType instead", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The content type of EDI message. One of application\/edifact, application\/edi-x12, application\/edi-consent, application\/xml. client\/send uses this value only when ediMessageContentType is not set. Deprecation note: Use ediMessageContentType instead" },
"from": { "index": 14, "kind": "parameter", "displayName": "From", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The value of the From header of AS2 message." },
"httpConnectionPoolSize": { "index": 15, "kind": "parameter", "displayName": "Http Connection Pool Size", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 5, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The maximum size of the connection pool for http connections (client only)" },
"httpConnectionPoolTtl": { "index": 16, "kind": "parameter", "displayName": "Http Connection Pool Ttl", "group": "common", "label": "", "required": false, "type": "duration", "javaType": "java.time.Duration", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "15m", "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The time to live for connections in the connection pool (client only)" },
@@ -92,7 +92,7 @@
"server": { "consumerOnly": true, "producerOnly": false, "description": "Receives EDI Messages over HTTP", "methods": { "listen": { "description": "", "signatures": [ "void listen(String requestUriPattern, org.apache.hc.core5.http.io.HttpRequestHandler handler)" ] } } }
},
"apiProperties": {
- "client": { "methods": { "send": { "properties": { "accessToken": { "index": 0, "kind": "parameter", "displayName": "Access Token", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The access token that is used by the client for bearer authentication", "optional": true }, "as2From": { "index": 1, "kind": "parameter", "displayName": "As2 From", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "AS2 name of sender", "optional": false }, "as2MessageStructure": { "index": 2, "kind": "parameter", "displayName": "As2 Message Structure", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2MessageStructure", "enum": [ "PLAIN", "SIGNED", "ENCRYPTED", "SIGNED_ENCRYPTED", "PLAIN_COMPRESSED", "COMPRESSED_SIGNED", "SIGNED_COMPRESSED", "ENCRYPTED_COMPRESSED", "ENCRYPTED_COMPRESSED_SIGNED", "ENCRYPTED_SIGNED_COMPRESSED" ], "deprecated": false, "autowired": false, "secret": false, "description": "The structure of AS2 to send; see AS2MessageStructure", "optional": false }, "as2To": { "index": 3, "kind": "parameter", "displayName": "As2 To", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "AS2 name of recipient", "optional": false }, "attachedFileName": { "index": 4, "kind": "parameter", "displayName": "Attached File Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the attached file or null if user doesn't want to specify it", "optional": true }, "compressionAlgorithm": { "index": 5, "kind": "parameter", "displayName": "Compression Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2CompressionAlgorithm", "enum": [ "ZLIB" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to compress the message or null if sending EDI message uncompressed", "optional": true }, "dispositionNotificationTo": { "index": 6, "kind": "parameter", "displayName": "Disposition Notification To", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "An RFC2822 address to request a receipt or null if no receipt requested", "optional": true }, "ediMessage": { "index": 7, "kind": "parameter", "displayName": "Edi Message", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "description": "EDI message to transport", "optional": false }, "ediMessageCharset": { "index": 8, "kind": "parameter", "displayName": "Edi Message Charset", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The charset of the EDI message", "optional": true }, "ediMessageContentType": { "index": 9, "kind": "parameter", "displayName": "Edi Message Content Type", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type of EDI message", "optional": false }, "ediMessageTransferEncoding": { "index": 10, "kind": "parameter", "displayName": "Edi Message Transfer Encoding", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The transfer encoding used to transport EDI message", "optional": true }, "encryptingAlgorithm": { "index": 11, "kind": "parameter", "displayName": "Encrypting Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2EncryptionAlgorithm", "enum": [ "AES128_CBC", "AES192_CBC", "AES256_CBC", "AES128_CCM", "AES192_CCM", "AES256_CCM", "AES128_GCM", "AES192_GCM", "AES256_GCM", "CAMELLIA128_CBC", "CAMELLIA192_CBC", "CAMELLIA256_CBC", "CAST5_CBC", "DES_CBC", "DES_EDE3_CBC", "GOST28147_GCFB", "IDEA_CBC", "RC2_CBC", "RC4", "SEED_CBC" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to encrypt the message or null if sending EDI message unencrypted", "optional": true }, "encryptingCertificateChain": { "index": 12, "kind": "parameter", "displayName": "Encrypting Certificate Chain", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.cert.Certificate[]", "deprecated": false, "autowired": false, "secret": false, "description": "The chain of certificates used to encrypt the message or null if sending EDI message unencrypted", "optional": true }, "from": { "index": 13, "kind": "parameter", "displayName": "From", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "RFC2822 address of sender", "optional": false }, "password": { "index": 14, "kind": "parameter", "displayName": "Password", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The password that is used by the client for basic authentication", "optional": true }, "receiptDeliveryOption": { "index": 15, "kind": "parameter", "displayName": "Receipt Delivery Option", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The return URL that the message receiver should send an asynchronous MDN to", "optional": true }, "requestUri": { "index": 16, "kind": "parameter", "displayName": "Request Uri", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Resource location to deliver message", "optional": false }, "signedReceiptMicAlgorithms": { "index": 17, "kind": "parameter", "displayName": "Signed Receipt Mic Algorithms", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The senders list of signing algorithms for signing receipt, in preferred order, or null if requesting an unsigned receipt.", "optional": true }, "signingAlgorithm": { "index": 18, "kind": "parameter", "displayName": "Signing Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2SignatureAlgorithm", "enum": [ "SHA3_224WITHRSA", "SHA3_256WITHRSA", "SHA3_384withRSA", "SHA3_512WITHRSA", "MD5WITHRSA", "SHA1WITHRSA", "MD2WITHRSA", "SHA224WITHRSA", "SHA256WITHRSA", "SHA384WITHRSA", "SHA512WITHRSA", "RIPEMD128WITHRSA", "RIPEMD160WITHRSA", "RIPEMD256WITHRSA", "SHA224WITHDSA", "SHA256WITHDSA", "SHA384WITHDSA", "SHA512WITHDSA", "SHA3_224WITHDSA", "SHA3_256WITHDSA", "SHA3_384WITHDSA", "SHA3_512WITHDSA", "SHA1WITHDSA", "SHA3_224WITHECDSA", "SHA3_256WITHECDSA", "SHA3_384WITHECDSA", "SHA3_512WITHECDSA", "SHA1WITHECDSA", "SHA224WITHECDSA", "SHA256WITHECDSA", "SHA384WITHECDSA", "SHA512WITHECDSA", "SHA1WITHPLAIN_ECDSA", "SHA224WITHPLAIN_ECDSA", "SHA256WITHPLAIN_ECDSA", "SHA384WITHPLAIN_ECDSA", "SHA512WITHPLAIN_ECDSA", "RIPEMD160WITHPLAIN_ECDSA", "SHA1WITHRSAANDMGF1", "SHA224WITHRSAANDMGF1", "SHA256WITHRSAANDMGF1", "SHA384WITHRSAANDMGF1", "SHA512WITHRSAANDMGF1", "SHA3_224WITHRSAANDMGF1", "SHA3_256WITHRSAANDMGF1", "SHA3_384WITHRSAANDMGF1", "SHA3_512WITHRSAANDMGF1" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to sign the message or null if sending EDI message unsigned", "optional": true }, "signingCertificateChain": { "index": 19, "kind": "parameter", "displayName": "Signing Certificate Chain", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.cert.Certificate[]", "deprecated": false, "autowired": false, "secret": false, "description": "The chain of certificates used to sign the message or null if sending EDI message unsigned", "optional": true }, "signingPrivateKey": { "index": 20, "kind": "parameter", "displayName": "Signing Private Key", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.PrivateKey", "deprecated": false, "autowired": false, "secret": false, "description": "The private key used to sign EDI message", "optional": true }, "subject": { "index": 21, "kind": "parameter", "displayName": "Subject", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Message subject", "optional": false }, "userName": { "index": 22, "kind": "parameter", "displayName": "User Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The user-name that is used for basic authentication", "optional": true } } } } },
+ "client": { "methods": { "send": { "properties": { "accessToken": { "index": 0, "kind": "parameter", "displayName": "Access Token", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The access token that is used by the client for bearer authentication", "optional": true }, "as2From": { "index": 1, "kind": "parameter", "displayName": "As2 From", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "AS2 name of sender", "optional": false }, "as2MessageStructure": { "index": 2, "kind": "parameter", "displayName": "As2 Message Structure", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2MessageStructure", "enum": [ "PLAIN", "SIGNED", "ENCRYPTED", "SIGNED_ENCRYPTED", "PLAIN_COMPRESSED", "COMPRESSED_SIGNED", "SIGNED_COMPRESSED", "ENCRYPTED_COMPRESSED", "ENCRYPTED_COMPRESSED_SIGNED", "ENCRYPTED_SIGNED_COMPRESSED" ], "deprecated": false, "autowired": false, "secret": false, "description": "The structure of AS2 to send; see AS2MessageStructure", "optional": false }, "as2To": { "index": 3, "kind": "parameter", "displayName": "As2 To", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "AS2 name of recipient", "optional": false }, "attachedFileName": { "index": 4, "kind": "parameter", "displayName": "Attached File Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the attached file or null if user doesn't want to specify it", "optional": true }, "compressionAlgorithm": { "index": 5, "kind": "parameter", "displayName": "Compression Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2CompressionAlgorithm", "enum": [ "ZLIB" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to compress the message or null if sending EDI message uncompressed", "optional": true }, "dispositionNotificationTo": { "index": 6, "kind": "parameter", "displayName": "Disposition Notification To", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "An RFC2822 address to request a receipt or null if no receipt requested", "optional": true }, "ediMessage": { "index": 7, "kind": "parameter", "displayName": "Edi Message", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "description": "EDI message to transport: a String, an InputStream or a byte array", "optional": false }, "ediMessageCharset": { "index": 8, "kind": "parameter", "displayName": "Edi Message Charset", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The charset of the EDI message", "optional": true }, "ediMessageContentType": { "index": 9, "kind": "parameter", "displayName": "Edi Message Content Type", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type of EDI message", "optional": false }, "ediMessageTransferEncoding": { "index": 10, "kind": "parameter", "displayName": "Edi Message Transfer Encoding", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The transfer encoding used to transport EDI message", "optional": true }, "encryptingAlgorithm": { "index": 11, "kind": "parameter", "displayName": "Encrypting Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2EncryptionAlgorithm", "enum": [ "AES128_CBC", "AES192_CBC", "AES256_CBC", "AES128_CCM", "AES192_CCM", "AES256_CCM", "AES128_GCM", "AES192_GCM", "AES256_GCM", "CAMELLIA128_CBC", "CAMELLIA192_CBC", "CAMELLIA256_CBC", "CAST5_CBC", "DES_CBC", "DES_EDE3_CBC", "GOST28147_GCFB", "IDEA_CBC", "RC2_CBC", "RC4", "SEED_CBC" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to encrypt the message or null if sending EDI message unencrypted", "optional": true }, "encryptingCertificateChain": { "index": 12, "kind": "parameter", "displayName": "Encrypting Certificate Chain", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.cert.Certificate[]", "deprecated": false, "autowired": false, "secret": false, "description": "The chain of certificates used to encrypt the message or null if sending EDI message unencrypted", "optional": true }, "from": { "index": 13, "kind": "parameter", "displayName": "From", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "RFC2822 address of sender", "optional": false }, "password": { "index": 14, "kind": "parameter", "displayName": "Password", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The password that is used by the client for basic authentication", "optional": true }, "receiptDeliveryOption": { "index": 15, "kind": "parameter", "displayName": "Receipt Delivery Option", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The return URL that the message receiver should send an asynchronous MDN to", "optional": true }, "requestUri": { "index": 16, "kind": "parameter", "displayName": "Request Uri", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Resource location to deliver message", "optional": false }, "signedReceiptMicAlgorithms": { "index": 17, "kind": "parameter", "displayName": "Signed Receipt Mic Algorithms", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The senders list of signing algorithms for signing receipt, in preferred order, or null if requesting an unsigned receipt.", "optional": true }, "signingAlgorithm": { "index": 18, "kind": "parameter", "displayName": "Signing Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2SignatureAlgorithm", "enum": [ "SHA3_224WITHRSA", "SHA3_256WITHRSA", "SHA3_384withRSA", "SHA3_512WITHRSA", "MD5WITHRSA", "SHA1WITHRSA", "MD2WITHRSA", "SHA224WITHRSA", "SHA256WITHRSA", "SHA384WITHRSA", "SHA512WITHRSA", "RIPEMD128WITHRSA", "RIPEMD160WITHRSA", "RIPEMD256WITHRSA", "SHA224WITHDSA", "SHA256WITHDSA", "SHA384WITHDSA", "SHA512WITHDSA", "SHA3_224WITHDSA", "SHA3_256WITHDSA", "SHA3_384WITHDSA", "SHA3_512WITHDSA", "SHA1WITHDSA", "SHA3_224WITHECDSA", "SHA3_256WITHECDSA", "SHA3_384WITHECDSA", "SHA3_512WITHECDSA", "SHA1WITHECDSA", "SHA224WITHECDSA", "SHA256WITHECDSA", "SHA384WITHECDSA", "SHA512WITHECDSA", "SHA1WITHPLAIN_ECDSA", "SHA224WITHPLAIN_ECDSA", "SHA256WITHPLAIN_ECDSA", "SHA384WITHPLAIN_ECDSA", "SHA512WITHPLAIN_ECDSA", "RIPEMD160WITHPLAIN_ECDSA", "SHA1WITHRSAANDMGF1", "SHA224WITHRSAANDMGF1", "SHA256WITHRSAANDMGF1", "SHA384WITHRSAANDMGF1", "SHA512WITHRSAANDMGF1", "SHA3_224WITHRSAANDMGF1", "SHA3_256WITHRSAANDMGF1", "SHA3_384WITHRSAANDMGF1", "SHA3_512WITHRSAANDMGF1" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to sign the message or null if sending EDI message unsigned", "optional": true }, "signingCertificateChain": { "index": 19, "kind": "parameter", "displayName": "Signing Certificate Chain", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.cert.Certificate[]", "deprecated": false, "autowired": false, "secret": false, "description": "The chain of certificates used to sign the message or null if sending EDI message unsigned", "optional": true }, "signingPrivateKey": { "index": 20, "kind": "parameter", "displayName": "Signing Private Key", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.PrivateKey", "deprecated": false, "autowired": false, "secret": false, "description": "The private key used to sign EDI message", "optional": true }, "subject": { "index": 21, "kind": "parameter", "displayName": "Subject", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Message subject", "optional": false }, "userName": { "index": 22, "kind": "parameter", "displayName": "User Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The user-name that is used for basic authentication", "optional": true } } } } },
"receipt": { "methods": { "receive": { "properties": { "requestUriPattern": { "index": 0, "kind": "parameter", "displayName": "Request Uri Pattern", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "", "optional": false } } } } },
"server": { "methods": { "listen": { "properties": { "requestUriPattern": { "index": 0, "kind": "parameter", "displayName": "Request Uri Pattern", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "", "optional": false } } } } }
}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-files.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-files.json
index 231fb1308104c..65fd7e2caa373 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-files.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-files.json
@@ -68,7 +68,7 @@
"sendEmptyMessageWhenIdle": { "index": 17, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
"streamDownload": { "index": 18, "kind": "parameter", "displayName": "Stream Download", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.azure.FilesConfiguration", "configurationField": "configuration", "description": "Sets the download method to use when not using a local working directory. If set to true, the remote files are streamed to the route as they are read. When set to false, the remote files are loaded into memory before being sent into the route. If enabling this option then you must set stepwise=false as both cannot be enabled at the same time." },
"bridgeErrorHandler": { "index": 19, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
- "download": { "index": 20, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
+ "download": { "index": 20, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
"exceptionHandler": { "index": 21, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 22, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"inProgressRepository": { "index": 23, "kind": "parameter", "displayName": "In Progress Repository", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.IdempotentRepository", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable in-progress repository org.apache.camel.spi.IdempotentRepository. The in-progress repository is used to account the current in progress files being consumed. By default a memory based repository is used." },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dns.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dns.json
index 9bd010f45fe95..f6182c1142c32 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dns.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dns.json
@@ -29,14 +29,14 @@
},
"headers": {
"CamelDnsClass": { "index": 0, "kind": "header", "displayName": "", "group": "lookup dig", "label": "lookup dig", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The DNS class of the lookup. Should match the values of org.xbill.dns.DClass. Optional.", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_CLASS" },
- "CamelDnsName": { "index": 1, "kind": "header", "displayName": "", "group": "lookup", "label": "lookup", "required": true, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name to lookup", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_NAME" },
+ "CamelDnsName": { "index": 1, "kind": "header", "displayName": "", "group": "lookup dig", "label": "lookup dig", "required": true, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name to lookup", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_NAME" },
"CamelDnsDomain": { "index": 2, "kind": "header", "displayName": "", "group": "ip", "label": "ip", "required": true, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The domain name.", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_DOMAIN" },
"CamelDnsServer": { "index": 3, "kind": "header", "displayName": "", "group": "dig", "label": "dig", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The server in particular for the query. If none is given, the default one specified by the OS will be used. Optional.", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_SERVER" },
- "CamelDnsType": { "index": 4, "kind": "header", "displayName": "", "group": "lookup dig", "label": "lookup dig", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of the lookup. Should match the values of org.xbill.dns.Type. Optional.", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_TYPE" },
- "CamelDnsTerm": { "index": 5, "kind": "header", "displayName": "", "group": "wikipedia", "label": "wikipedia", "required": true, "javaType": "", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The term", "constantName": "org.apache.camel.component.dns.DnsConstants#TERM" }
+ "CamelDnsType": { "index": 4, "kind": "header", "displayName": "", "group": "lookup dig", "label": "lookup dig", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of the lookup. Should match the values of org.xbill.dns.Type. Optional. The dig operation uses A when none or an unknown type is given.", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_TYPE" },
+ "CamelDnsTerm": { "index": 5, "kind": "header", "displayName": "", "group": "wikipedia", "label": "wikipedia", "required": true, "javaType": "", "deprecated": true, "deprecationNote": "The Wikipedia over DNS service is no longer available", "autowired": false, "secret": false, "description": "The term. Deprecation note: The Wikipedia over DNS service is no longer available", "constantName": "org.apache.camel.component.dns.DnsConstants#TERM" }
},
"properties": {
- "dnsType": { "index": 0, "kind": "path", "displayName": "Dns Type", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.dns.DnsType", "enum": [ "dig", "ip", "lookup", "wikipedia" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of the lookup." },
+ "dnsType": { "index": 0, "kind": "path", "displayName": "Dns Type", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.dns.DnsType", "enum": [ "dig", "ip", "lookup", "wikipedia" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of the lookup. The wikipedia type is deprecated, as the Wikipedia over DNS service it queries is no longer available." },
"lazyStartProducer": { "index": 1, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }
}
}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ftp.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ftp.json
index 8d0a3be6738aa..691f642b84592 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ftp.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ftp.json
@@ -82,7 +82,7 @@
"sendEmptyMessageWhenIdle": { "index": 23, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
"streamDownload": { "index": 24, "kind": "parameter", "displayName": "Stream Download", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.FtpConfiguration", "configurationField": "configuration", "description": "Sets the download method to use when not using a local working directory. If set to true, the remote files are streamed to the route as they are read. When set to false, the remote files are loaded into memory before being sent into the route. If enabling this option then you must set stepwise=false as both cannot be enabled at the same time." },
"bridgeErrorHandler": { "index": 25, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
- "download": { "index": 26, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
+ "download": { "index": 26, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
"exceptionHandler": { "index": 27, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 28, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"handleDirectoryParserAbsoluteResult": { "index": 29, "kind": "parameter", "displayName": "Handle Directory Parser Absolute Result", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.FtpConfiguration", "configurationField": "configuration", "description": "Allows you to set how the consumer will handle subfolders and files in the path if the directory parser results in with absolute paths. The reason for this is that some FTP servers may return file names with absolute paths, and if so, then the FTP component needs to handle this by converting the returned path into a relative path." },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ftps.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ftps.json
index ba1fade434f6b..1d2a9a2cc22ad 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ftps.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ftps.json
@@ -83,7 +83,7 @@
"sendEmptyMessageWhenIdle": { "index": 23, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
"streamDownload": { "index": 24, "kind": "parameter", "displayName": "Stream Download", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.FtpsConfiguration", "configurationField": "configuration", "description": "Sets the download method to use when not using a local working directory. If set to true, the remote files are streamed to the route as they are read. When set to false, the remote files are loaded into memory before being sent into the route. If enabling this option then you must set stepwise=false as both cannot be enabled at the same time." },
"bridgeErrorHandler": { "index": 25, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
- "download": { "index": 26, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
+ "download": { "index": 26, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
"exceptionHandler": { "index": 27, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 28, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"handleDirectoryParserAbsoluteResult": { "index": 29, "kind": "parameter", "displayName": "Handle Directory Parser Absolute Result", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.FtpsConfiguration", "configurationField": "configuration", "description": "Allows you to set how the consumer will handle subfolders and files in the path if the directory parser results in with absolute paths. The reason for this is that some FTP servers may return file names with absolute paths, and if so, then the FTP component needs to handle this by converting the returned path into a relative path." },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/github2.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/github2.json
index e956fb8a2d632..de592a3659697 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/github2.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/github2.json
@@ -39,9 +39,10 @@
"CamelGitHubIssueTitle": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The title of the issue", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_ISSUE_TITLE" },
"CamelGitHubCommitAuthor": { "index": 4, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The commit author", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_AUTHOR" },
"CamelGitHubCommitCommitter": { "index": 5, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The committer name", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_COMMITTER" },
- "CamelGitHubCommitSha": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The commit sha", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_SHA" },
- "CamelGitHubCommitUrl": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The commit URL", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_URL" },
- "CamelGitHubEventPayload": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "org.kohsuke.github.GHEventPayload", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The event payload", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_EVENT_PAYLOAD" }
+ "CamelGitHubCommitSha": { "index": 6, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The commit sha. The getCommitFile producer reads the file at this commit (a commit id of 40 hexadecimal characters).", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_SHA" },
+ "CamelGitHubFilePath": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The path of the file in the repository for the getCommitFile producer. If not set, the body is the path.", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_FILE_PATH" },
+ "CamelGitHubCommitUrl": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The commit URL", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_URL" },
+ "CamelGitHubEventPayload": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "org.kohsuke.github.GHEventPayload", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The event payload", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_EVENT_PAYLOAD" }
},
"properties": {
"type": { "index": 0, "kind": "path", "displayName": "Type", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.github2.GitHub2Type", "enum": [ "CLOSEPULLREQUEST", "PULLREQUESTCOMMENT", "COMMIT", "PULLREQUEST", "TAG", "PULLREQUESTSTATE", "PULLREQUESTFILES", "GETCOMMITFILE", "CREATEISSUE", "EVENT" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "What git operation to execute" },
@@ -56,7 +57,7 @@
"exceptionHandler": { "index": 9, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 10, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"pollStrategy": { "index": 11, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." },
- "encoding": { "index": 12, "kind": "parameter", "displayName": "Encoding", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use the given encoding when getting a git commit file" },
+ "encoding": { "index": 12, "kind": "parameter", "displayName": "Encoding", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The charset of the content of the file for the getCommitFile producer (the default charset of the JVM if not set)" },
"state": { "index": 13, "kind": "parameter", "displayName": "State", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "error", "failure", "pending", "success" ], "deprecated": false, "autowired": false, "secret": false, "description": "To set git commit status state" },
"targetUrl": { "index": 14, "kind": "parameter", "displayName": "Target Url", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To set git commit status target url" },
"lazyStartProducer": { "index": 15, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/graphql.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/graphql.json
index 73ef1d1a19f3c..c1a6f8bca5d22 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/graphql.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/graphql.json
@@ -37,10 +37,10 @@
"proxyHost": { "index": 3, "kind": "parameter", "displayName": "Proxy Host", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The proxy host in the format hostname:port." },
"query": { "index": 4, "kind": "parameter", "displayName": "Query", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The query text." },
"queryFile": { "index": 5, "kind": "parameter", "displayName": "Query File", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The query file name located in the classpath (or use file: to load from file system)." },
- "queryHeader": { "index": 6, "kind": "parameter", "displayName": "Query Header", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of a header containing the GraphQL query." },
+ "queryHeader": { "index": 6, "kind": "parameter", "displayName": "Query Header", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of a header containing the GraphQL query. The header is not sent as an HTTP header." },
"throwExceptionOnFailure": { "index": 7, "kind": "parameter", "displayName": "Throw Exception On Failure", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Option to disable throwing the HttpOperationFailedException in case of failed responses from the remote server. This allows you to get all responses regardless of the HTTP status code." },
"variables": { "index": 8, "kind": "parameter", "displayName": "Variables", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.util.json.JsonObject", "deprecated": false, "autowired": false, "secret": false, "description": "The JsonObject instance containing the operation variables." },
- "variablesHeader": { "index": 9, "kind": "parameter", "displayName": "Variables Header", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of a header containing a JsonObject instance containing the operation variables." },
+ "variablesHeader": { "index": 9, "kind": "parameter", "displayName": "Variables Header", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of a header containing the operation variables, as a JsonObject or a Map. The header is not sent as an HTTP header." },
"lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
"httpClient": { "index": 11, "kind": "parameter", "displayName": "Http Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.hc.client5.http.classic.HttpClient", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom pre-existing Http Client. Beware that when using this, then other configurations such as proxy, access token, is not applied and all this must be pre-configured on the Http Client." },
"accessToken": { "index": 12, "kind": "parameter", "displayName": "Access Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "The access token sent in the Authorization header." },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/infinispan-embedded.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/infinispan-embedded.json
index b884448a4a183..31fe69ab05719 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/infinispan-embedded.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/infinispan-embedded.json
@@ -38,10 +38,10 @@
"operation": { "index": 11, "kind": "property", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.infinispan.InfinispanOperation", "enum": [ "PUT", "PUTASYNC", "PUTALL", "PUTALLASYNC", "PUTIFABSENT", "PUTIFABSENTASYNC", "GET", "GETORDEFAULT", "CONTAINSKEY", "CONTAINSVALUE", "REMOVE", "REMOVEASYNC", "REPLACE", "REPLACEASYNC", "SIZE", "CLEAR", "CLEARASYNC", "QUERY", "STATS", "COMPUTE", "COMPUTEASYNC" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "PUT", "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The operation to perform" },
"value": { "index": 12, "kind": "property", "displayName": "Value", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Set a specific value for producer operations" },
"autowiredEnabled": { "index": 13, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." },
- "cacheContainer": { "index": 14, "kind": "property", "displayName": "Cache Container", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.manager.EmbeddedCacheManager", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Specifies the cache Container to connect" },
- "cacheContainerConfiguration": { "index": 15, "kind": "property", "displayName": "Cache Container Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.configuration.cache.Configuration", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The CacheContainer configuration. Used if the cacheContainer is not defined." },
+ "cacheContainer": { "index": 14, "kind": "property", "displayName": "Cache Container", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.manager.EmbeddedCacheManager", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Specifies the cache Container to connect Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
+ "cacheContainerConfiguration": { "index": 15, "kind": "property", "displayName": "Cache Container Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.configuration.cache.Configuration", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The CacheContainer configuration. Used if the cacheContainer is not defined. Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
"configurationUri": { "index": 16, "kind": "property", "displayName": "Configuration Uri", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "An implementation specific URI for the CacheManager" },
- "flags": { "index": 17, "kind": "property", "displayName": "Flags", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "A comma separated list of org.infinispan.context.Flag to be applied by default on each cache invocation" },
+ "flags": { "index": 17, "kind": "property", "displayName": "Flags", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "A comma separated list of org.infinispan.context.Flag to be applied by default on each cache invocation Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
"remappingFunction": { "index": 18, "kind": "property", "displayName": "Remapping Function", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.function.BiFunction", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Set a specific remappingFunction to use in a compute operation." },
"resultHeader": { "index": 19, "kind": "property", "displayName": "Result Header", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Store the operation result in a header instead of the message body. By default, resultHeader == null and the query result is stored in the message body, any existing content in the message body is discarded. If resultHeader is set, the value is used as the name of the header to store the query result and the original message body is preserved. This value can be overridden by an in message header named: CamelInfinispanOperationResultHeader" }
},
@@ -85,10 +85,10 @@
"operation": { "index": 12, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.infinispan.InfinispanOperation", "enum": [ "PUT", "PUTASYNC", "PUTALL", "PUTALLASYNC", "PUTIFABSENT", "PUTIFABSENTASYNC", "GET", "GETORDEFAULT", "CONTAINSKEY", "CONTAINSVALUE", "REMOVE", "REMOVEASYNC", "REPLACE", "REPLACEASYNC", "SIZE", "CLEAR", "CLEARASYNC", "QUERY", "STATS", "COMPUTE", "COMPUTEASYNC" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "PUT", "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The operation to perform" },
"value": { "index": 13, "kind": "parameter", "displayName": "Value", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Set a specific value for producer operations" },
"lazyStartProducer": { "index": 14, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
- "cacheContainer": { "index": 15, "kind": "parameter", "displayName": "Cache Container", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.manager.EmbeddedCacheManager", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Specifies the cache Container to connect" },
- "cacheContainerConfiguration": { "index": 16, "kind": "parameter", "displayName": "Cache Container Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.configuration.cache.Configuration", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The CacheContainer configuration. Used if the cacheContainer is not defined." },
+ "cacheContainer": { "index": 15, "kind": "parameter", "displayName": "Cache Container", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.manager.EmbeddedCacheManager", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Specifies the cache Container to connect Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
+ "cacheContainerConfiguration": { "index": 16, "kind": "parameter", "displayName": "Cache Container Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.configuration.cache.Configuration", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The CacheContainer configuration. Used if the cacheContainer is not defined. Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
"configurationUri": { "index": 17, "kind": "parameter", "displayName": "Configuration Uri", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "An implementation specific URI for the CacheManager" },
- "flags": { "index": 18, "kind": "parameter", "displayName": "Flags", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "A comma separated list of org.infinispan.context.Flag to be applied by default on each cache invocation" },
+ "flags": { "index": 18, "kind": "parameter", "displayName": "Flags", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "A comma separated list of org.infinispan.context.Flag to be applied by default on each cache invocation Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
"remappingFunction": { "index": 19, "kind": "parameter", "displayName": "Remapping Function", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.function.BiFunction", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Set a specific remappingFunction to use in a compute operation." },
"resultHeader": { "index": 20, "kind": "parameter", "displayName": "Result Header", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Store the operation result in a header instead of the message body. By default, resultHeader == null and the query result is stored in the message body, any existing content in the message body is discarded. If resultHeader is set, the value is used as the name of the header to store the query result and the original message body is preserved. This value can be overridden by an in message header named: CamelInfinispanOperationResultHeader" }
}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jdbc.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jdbc.json
index 5109e64326886..039f9e6ad647f 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jdbc.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jdbc.json
@@ -31,7 +31,7 @@
},
"headers": {
"CamelJdbcUpdateCount": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "If the query is an UPDATE, query the update count is returned in this OUT header.", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_UPDATE_COUNT" },
- "CamelJdbcRowCount": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "If the query is a SELECT, query the row count is returned in this OUT header.", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_ROW_COUNT" },
+ "CamelJdbcRowCount": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "If the query is a SELECT and the outputType is SelectList, the row count is returned in this OUT header.", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_ROW_COUNT" },
"CamelJdbcColumnNames": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Set", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The column names from the ResultSet as a java.util.Set type.", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_COLUMN_NAMES" },
"CamelJdbcParameters": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A java.util.Map which has the headers to be used if useHeadersAsParameters has been enabled.", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_PARAMETERS" },
"CamelRetrieveGeneratedKeys": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "false", "description": "Set its value to true to retrieve generated keys", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_RETRIEVE_GENERATED_KEYS" },
@@ -47,8 +47,8 @@
"parameters": { "index": 4, "kind": "parameter", "displayName": "Parameters", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "statement.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Optional parameters to the java.sql.Statement. For example to set maxRows, fetchSize etc. This is a multi-value option with prefix: statement." },
"readSize": { "index": 5, "kind": "parameter", "displayName": "Read Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The default maximum number of rows that can be read by a polling query. The default value is 0." },
"resetAutoCommit": { "index": 6, "kind": "parameter", "displayName": "Reset Auto Commit", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Camel will set the autoCommit on the JDBC connection to be false, commit the change after executed the statement and reset the autoCommit flag of the connection at the end, if the resetAutoCommit is true. If the JDBC connection doesn't support to reset the autoCommit flag, you can set the resetAutoCommit flag to be false, and Camel will not try to reset the autoCommit flag. When used with XA transactions you most likely need to set it to false so that the transaction manager is in charge of committing this tx." },
- "transacted": { "index": 7, "kind": "parameter", "displayName": "Transacted", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether transactions are in use." },
- "useGetBytesForBlob": { "index": 8, "kind": "parameter", "displayName": "Use Get Bytes For Blob", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "To read BLOB columns as bytes instead of string data. This may be needed for certain databases such as Oracle where you must read BLOB columns as bytes." },
+ "transacted": { "index": 7, "kind": "parameter", "displayName": "Transacted", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": true, "deprecationNote": "Not used: the producer does not read this option", "autowired": false, "secret": false, "defaultValue": false, "description": "Whether transactions are in use. Deprecation note: Not used: the producer does not read this option" },
+ "useGetBytesForBlob": { "index": 8, "kind": "parameter", "displayName": "Use Get Bytes For Blob", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "To read BLOB columns as bytes (a byte) instead of a java.sql.Blob, which cannot be read after the producer has closed the connection. This may be needed for certain databases such as Oracle where you must read BLOB columns as bytes." },
"useHeadersAsParameters": { "index": 9, "kind": "parameter", "displayName": "Use Headers As Parameters", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Set this option to true to use the prepareStatementStrategy with named parameters. This allows to define queries with named placeholders, and use headers with the dynamic values for the query placeholders." },
"useJDBC4ColumnNameAndLabelSemantics": { "index": 10, "kind": "parameter", "displayName": "Use JDBC4 Column Name And Label Semantics", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Sets whether to use JDBC 4 or JDBC 3.0 or older semantic when retrieving column name. JDBC 4.0 uses columnLabel to get the column name where as JDBC 3.0 uses both columnName or columnLabel. Unfortunately JDBC drivers behave differently so you can use this option to work out issues around your JDBC driver if you get problem using this component This option is default true." },
"lazyStartProducer": { "index": 11, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kafka.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kafka.json
index d1dafe51f2f12..dd09c9c37ec32 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kafka.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kafka.json
@@ -107,7 +107,7 @@
"retries": { "index": 80, "kind": "property", "displayName": "Retries", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Setting a value greater than zero will cause the client to resend any record that has failed to be sent due to a potentially transient error. Note that this retry is no different from if the client re-sending the record upon receiving the error. Produce requests will be failed before the number of retries has been exhausted if the timeout configured by delivery.timeout.ms expires first before successful acknowledgement. Users should generally prefer to leave this config unset and instead use delivery.timeout.ms to control retry behavior. Enabling idempotence requires this config value to be greater than 0. If conflicting configurations are set and idempotence is not explicitly enabled, idempotence is disabled. Allowing retries while setting enable.idempotence to false and max.in.flight.requests.per.connection to 1 will potentially change the ordering of records, because if two batches are sent to a single partition, and the first fails and is retried but the second succeeds; then the records in the second batch may appear first." },
"transacted": { "index": 81, "kind": "property", "displayName": "Transacted", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Indicates to create a transactional.id kafka property by using the endpoint id and route id. This property is ignored in case there is transactional.id kafka property or the transactionalId parameter." },
"transactionalId": { "index": 82, "kind": "property", "displayName": "Transactional Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Enable the kafka producer to be a transactional one by setting the transactional.id property. In case this property is used, the transacted parameter is ignored." },
- "useIterator": { "index": 83, "kind": "property", "displayName": "Use Iterator", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Sets whether sending to kafka should send the message body as a single record, or use a java.util.Iterator to send multiple records to kafka (if the message body can be iterated)." },
+ "useIterator": { "index": 83, "kind": "property", "displayName": "Use Iterator", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Sets whether sending to kafka should send the message body as a single record, or use a java.util.Iterator to send multiple records to kafka (if the message body can be iterated). A Jackson JSON array node is sent as one record per element, and any other JSON node (such as an object) as one record." },
"valueSerializer": { "index": 84, "kind": "property", "displayName": "Value Serializer", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "org.apache.kafka.common.serialization.StringSerializer", "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "The serializer class for messages." },
"workerPool": { "index": 85, "kind": "property", "displayName": "Worker Pool", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "java.util.concurrent.ExecutorService", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "To use a custom worker pool for continue routing Exchange after kafka server has acknowledged the message that was sent to it from KafkaProducer using asynchronous non-blocking processing. If using this option, then you must handle the lifecycle of the thread pool to shut the pool down when no longer needed." },
"workerPoolCoreSize": { "index": 86, "kind": "property", "displayName": "Worker Pool Core Size", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 10, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Number of core threads for the worker pool for continue routing Exchange after kafka server has acknowledged the message that was sent to it from KafkaProducer using asynchronous non-blocking processing." },
@@ -253,7 +253,7 @@
"retries": { "index": 75, "kind": "parameter", "displayName": "Retries", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Setting a value greater than zero will cause the client to resend any record that has failed to be sent due to a potentially transient error. Note that this retry is no different from if the client re-sending the record upon receiving the error. Produce requests will be failed before the number of retries has been exhausted if the timeout configured by delivery.timeout.ms expires first before successful acknowledgement. Users should generally prefer to leave this config unset and instead use delivery.timeout.ms to control retry behavior. Enabling idempotence requires this config value to be greater than 0. If conflicting configurations are set and idempotence is not explicitly enabled, idempotence is disabled. Allowing retries while setting enable.idempotence to false and max.in.flight.requests.per.connection to 1 will potentially change the ordering of records, because if two batches are sent to a single partition, and the first fails and is retried but the second succeeds; then the records in the second batch may appear first." },
"transacted": { "index": 76, "kind": "parameter", "displayName": "Transacted", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Indicates to create a transactional.id kafka property by using the endpoint id and route id. This property is ignored in case there is transactional.id kafka property or the transactionalId parameter." },
"transactionalId": { "index": 77, "kind": "parameter", "displayName": "Transactional Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Enable the kafka producer to be a transactional one by setting the transactional.id property. In case this property is used, the transacted parameter is ignored." },
- "useIterator": { "index": 78, "kind": "parameter", "displayName": "Use Iterator", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Sets whether sending to kafka should send the message body as a single record, or use a java.util.Iterator to send multiple records to kafka (if the message body can be iterated)." },
+ "useIterator": { "index": 78, "kind": "parameter", "displayName": "Use Iterator", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Sets whether sending to kafka should send the message body as a single record, or use a java.util.Iterator to send multiple records to kafka (if the message body can be iterated). A Jackson JSON array node is sent as one record per element, and any other JSON node (such as an object) as one record." },
"valueSerializer": { "index": 79, "kind": "parameter", "displayName": "Value Serializer", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "org.apache.kafka.common.serialization.StringSerializer", "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "The serializer class for messages." },
"workerPool": { "index": 80, "kind": "parameter", "displayName": "Worker Pool", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "java.util.concurrent.ExecutorService", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "To use a custom worker pool for continue routing Exchange after kafka server has acknowledged the message that was sent to it from KafkaProducer using asynchronous non-blocking processing. If using this option, then you must handle the lifecycle of the thread pool to shut the pool down when no longer needed." },
"workerPoolCoreSize": { "index": 81, "kind": "parameter", "displayName": "Worker Pool Core Size", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 10, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Number of core threads for the worker pool for continue routing Exchange after kafka server has acknowledged the message that was sent to it from KafkaProducer using asynchronous non-blocking processing." },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/micrometer.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/micrometer.json
index f7e9210de8972..89c539d9e0b37 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/micrometer.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/micrometer.json
@@ -30,7 +30,7 @@
},
"headers": {
"CamelMetricsTimerAction": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.apache.camel.component.micrometer.MicrometerTimerAction", "enum": [ "start", "stop" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override timer action in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_TIMER_ACTION" },
- "CamelMetricsHistogramValue": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override histogram value in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_HISTOGRAM_VALUE" },
+ "CamelMetricsHistogramValue": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override histogram value in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_HISTOGRAM_VALUE" },
"CamelMetricsCounterDecrement": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override decrement value in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_COUNTER_DECREMENT" },
"CamelMetricsCounterIncrement": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override increment value in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_COUNTER_INCREMENT" },
"CamelMetricsName": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Override name value in URI", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_METRIC_NAME" },
@@ -38,7 +38,7 @@
"CamelMetricsTags": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.lang.Iterable", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To augment meter tags defined as URI parameters", "constantName": "org.apache.camel.component.micrometer.MicrometerConstants#HEADER_METRIC_TAGS" }
},
"properties": {
- "metricsType": { "index": 0, "kind": "path", "displayName": "Metrics Type", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "io.micrometer.core.instrument.Meter.Type", "enum": [ "counter", "summary", "timer" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Type of metrics" },
+ "metricsType": { "index": 0, "kind": "path", "displayName": "Metrics Type", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "io.micrometer.core.instrument.Meter.Type", "enum": [ "counter", "summary", "timer" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "counter", "description": "Type of metrics" },
"metricsName": { "index": 1, "kind": "path", "displayName": "Metrics Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportSimpleExpression": true, "description": "Name of metrics" },
"action": { "index": 2, "kind": "parameter", "displayName": "Action", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "start", "stop" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportSimpleExpression": true, "description": "Action expression when using timer type" },
"decrement": { "index": 3, "kind": "parameter", "displayName": "Decrement", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportSimpleExpression": true, "description": "Decrement value expression when using counter type" },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mina-sftp.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mina-sftp.json
index 6cae8c76d1cb1..14c37f8a89144 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mina-sftp.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mina-sftp.json
@@ -72,7 +72,7 @@
"sendEmptyMessageWhenIdle": { "index": 19, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
"streamDownload": { "index": 20, "kind": "parameter", "displayName": "Stream Download", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.mina.MinaSftpConfiguration", "configurationField": "configuration", "description": "Sets the download method to use when not using a local working directory. If set to true, the remote files are streamed to the route as they are read. When set to false, the remote files are loaded into memory before being sent into the route. If enabling this option then you must set stepwise=false as both cannot be enabled at the same time." },
"bridgeErrorHandler": { "index": 21, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
- "download": { "index": 22, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
+ "download": { "index": 22, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
"exceptionHandler": { "index": 23, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 24, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"ignoreFileNotFoundOrPermissionError": { "index": 25, "kind": "parameter", "displayName": "Ignore File Not Found Or Permission Error", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.mina.MinaSftpConfiguration", "configurationField": "configuration", "description": "Whether to ignore when (trying to list files in directories or when downloading a file), which does not exist or due to permission error. By default when a directory or file does not exist or insufficient permission, then an exception is thrown. Setting this option to true allows to ignore that instead." },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pdf.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pdf.json
index f2edff0482dd4..333577f9981ec 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pdf.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pdf.json
@@ -31,7 +31,7 @@
"CamelPdfProtectionPolicy": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Expected type is https:\/\/pdfbox.apache.org\/docs\/2.0.13\/javadocs\/org\/apache\/pdfbox\/pdmodel\/encryption\/ProtectionPolicy.htmlProtectionPolicy. If specified then PDF document will be encrypted with it.", "constantName": "org.apache.camel.component.pdf.PdfHeaderConstants#PROTECTION_POLICY_HEADER_NAME" },
"CamelPdfDocument": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.apache.pdfbox.pdmodel.PDDocument", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Mandatory header for append operation and ignored in all other operations. Expected type is https:\/\/pdfbox.apache.org\/docs\/2.0.13\/javadocs\/org\/apache\/pdfbox\/pdmodel\/PDDocument.htmlPDDocument. Stores PDF document which will be used for append operation.", "constantName": "org.apache.camel.component.pdf.PdfHeaderConstants#PDF_DOCUMENT_HEADER_NAME" },
"CamelPdfDecryptionMaterial": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.apache.pdfbox.pdmodel.encryption.DecryptionMaterial", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Expected type is https:\/\/pdfbox.apache.org\/docs\/2.0.13\/javadocs\/org\/apache\/pdfbox\/pdmodel\/encryption\/DecryptionMaterial.htmlDecryptionMaterial. Mandatory header if PDF document is encrypted.", "constantName": "org.apache.camel.component.pdf.PdfHeaderConstants#DECRYPTION_MATERIAL_HEADER_NAME" },
- "CamelPdfFilesToMerge": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.util.List", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Mandatory header for merge operation and ignored in all other operations. The array of pdf files that will be merged.", "constantName": "org.apache.camel.component.pdf.PdfHeaderConstants#FILES_TO_MERGE_HEADER_NAME" }
+ "CamelPdfFilesToMerge": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "java.util.List", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Mandatory header for merge operation and ignored in all other operations. The list of pdf files that will be merged, each given as a java.io.File or a java.nio.file.Path.", "constantName": "org.apache.camel.component.pdf.PdfHeaderConstants#FILES_TO_MERGE_HEADER_NAME" }
},
"properties": {
"operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.pdf.PdfOperation", "enum": [ "create", "append", "extractText", "merge" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pdf.PdfConfiguration", "configurationField": "pdfConfiguration", "description": "Operation type" },
@@ -41,7 +41,7 @@
"marginLeft": { "index": 4, "kind": "parameter", "displayName": "Margin Left", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 20, "configurationClass": "org.apache.camel.component.pdf.PdfConfiguration", "configurationField": "pdfConfiguration", "description": "Margin left in pixels" },
"marginRight": { "index": 5, "kind": "parameter", "displayName": "Margin Right", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 40, "configurationClass": "org.apache.camel.component.pdf.PdfConfiguration", "configurationField": "pdfConfiguration", "description": "Margin right in pixels" },
"marginTop": { "index": 6, "kind": "parameter", "displayName": "Margin Top", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 20, "configurationClass": "org.apache.camel.component.pdf.PdfConfiguration", "configurationField": "pdfConfiguration", "description": "Margin top in pixels" },
- "pageSize": { "index": 7, "kind": "parameter", "displayName": "Page Size", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "LETTER", "LEGAL", "A0", "A1", "A2", "A3", "A4", "A5", "A6" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "A4", "configurationClass": "org.apache.camel.component.pdf.PdfConfiguration", "configurationField": "pdfConfiguration", "description": "Page size" },
+ "pageSize": { "index": 7, "kind": "parameter", "displayName": "Page Size", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "LETTER", "LEGAL", "A0", "A1", "A2", "A3", "A4", "A5", "A6" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "A4", "configurationClass": "org.apache.camel.component.pdf.PdfConfiguration", "configurationField": "pdfConfiguration", "description": "Page size: LETTER, LEGAL or A0 to A6. The older names PAGE_SIZE_A0 to PAGE_SIZE_A6 and PAGE_SIZE_LETTER are also accepted." },
"textProcessingFactory": { "index": 8, "kind": "parameter", "displayName": "Text Processing Factory", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.pdf.TextProcessingFactory", "enum": [ "autoFormatting", "lineTermination" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "lineTermination", "configurationClass": "org.apache.camel.component.pdf.PdfConfiguration", "configurationField": "pdfConfiguration", "description": "Text processing to use. autoFormatting: Text is getting sliced by words, then max amount of words that fits in the line will be written into pdf document. With this strategy all words that doesn't fit in the line will be moved to the new line. lineTermination: Builds set of classes for line-termination writing strategy. Text getting sliced by line termination symbol and then it will be written regardless it fits in the line or not." },
"lazyStartProducer": { "index": 9, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }
}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sftp.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sftp.json
index a0471a76cb2f0..aff91a1d61774 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sftp.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sftp.json
@@ -84,7 +84,7 @@
"sendEmptyMessageWhenIdle": { "index": 20, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
"streamDownload": { "index": 21, "kind": "parameter", "displayName": "Stream Download", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.SftpConfiguration", "configurationField": "configuration", "description": "Sets the download method to use when not using a local working directory. If set to true, the remote files are streamed to the route as they are read. When set to false, the remote files are loaded into memory before being sent into the route. If enabling this option then you must set stepwise=false as both cannot be enabled at the same time." },
"bridgeErrorHandler": { "index": 22, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
- "download": { "index": 23, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
+ "download": { "index": 23, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
"exceptionHandler": { "index": 24, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 25, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"ignoreFileNotFoundOrPermissionError": { "index": 26, "kind": "parameter", "displayName": "Ignore File Not Found Or Permission Error", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.SftpConfiguration", "configurationField": "configuration", "description": "Whether to ignore when (trying to list files in directories or when downloading a file), which does not exist or due to permission error. By default when a directory or file does not exist or insufficient permission, then an exception is thrown. Setting this option to true allows to ignore that instead." },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smb.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smb.json
index 89a91c6824397..1de0619cbabe2 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smb.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smb.json
@@ -69,7 +69,7 @@
"sendEmptyMessageWhenIdle": { "index": 16, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
"streamDownload": { "index": 17, "kind": "parameter", "displayName": "Stream Download", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.smb.SmbConfiguration", "configurationField": "configuration", "description": "Sets the download method to use when not using a local working directory. If set to true, the remote files are streamed to the route as they are read. When set to false, the remote files are loaded into memory before being sent into the route." },
"bridgeErrorHandler": { "index": 18, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
- "download": { "index": 19, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.smb.SmbConfiguration", "configurationField": "configuration", "description": "Whether the SMB consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
+ "download": { "index": 19, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.smb.SmbConfiguration", "configurationField": "configuration", "description": "Whether the SMB consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
"exceptionHandler": { "index": 20, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 21, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"inProgressRepository": { "index": 22, "kind": "parameter", "displayName": "In Progress Repository", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.IdempotentRepository", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable in-progress repository org.apache.camel.spi.IdempotentRepository. The in-progress repository is used to account the current in progress files being consumed. By default a memory based repository is used." },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/snmp.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/snmp.json
index 4dc8c5a836cd3..d2da3dc0f0c90 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/snmp.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/snmp.json
@@ -41,7 +41,7 @@
"snmpContextName": { "index": 7, "kind": "parameter", "displayName": "Snmp Context Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the context name field of this scoped PDU." },
"snmpVersion": { "index": 8, "kind": "parameter", "displayName": "Snmp Version", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "int", "enum": [ "0", "1", "3" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Sets the snmp version for the request. The value 0 means SNMPv1, 1 means SNMPv2c, and the value 3 means SNMPv3" },
"timeout": { "index": 9, "kind": "parameter", "displayName": "Timeout", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1500, "description": "Sets the timeout value for the request in millis." },
- "type": { "index": 10, "kind": "parameter", "displayName": "Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.snmp.SnmpActionType", "enum": [ "TRAP", "POLL", "GET_NEXT" ], "deprecated": false, "autowired": false, "secret": false, "description": "Which operation to perform such as poll, trap, etc." },
+ "type": { "index": 10, "kind": "parameter", "displayName": "Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.snmp.SnmpActionType", "enum": [ "TRAP", "POLL", "GET_NEXT" ], "deprecated": false, "autowired": false, "secret": false, "description": "Which operation to perform such as poll, trap, etc. The consumer supports TRAP (receive traps) and POLL (poll the oids). The producer supports TRAP (send the PDU of the body as a trap), POLL (a GET of the oids, also done when no type is set) and GET_NEXT (a walk of the oids, for the producer only)." },
"delay": { "index": 11, "kind": "parameter", "displayName": "Delay", "group": "consumer", "label": "consumer", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "60000", "description": "Milliseconds before the next poll." },
"sendEmptyMessageWhenIdle": { "index": 12, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
"treeList": { "index": 13, "kind": "parameter", "displayName": "Tree List", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets the flag whether the scoped PDU will be displayed as the list if it has child elements in its tree" },
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/tika.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/tika.json
index ddc7c899b1b78..80a2cf26249d9 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/tika.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/tika.json
@@ -29,8 +29,8 @@
},
"properties": {
"operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.tika.TikaOperation", "enum": [ "parse", "detect" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.tika.TikaConfiguration", "configurationField": "tikaConfiguration", "description": "Operation type" },
- "tikaParseOutputEncoding": { "index": 1, "kind": "parameter", "displayName": "Tika Parse Output Encoding", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.tika.TikaConfiguration", "configurationField": "tikaConfiguration", "description": "Tika Parse Output Encoding" },
- "tikaParseOutputFormat": { "index": 2, "kind": "parameter", "displayName": "Tika Parse Output Format", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.tika.TikaParseOutputFormat", "enum": [ "xml", "html", "text" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "xml", "configurationClass": "org.apache.camel.component.tika.TikaConfiguration", "configurationField": "tikaConfiguration", "description": "Tika Output Format. Supported output formats. xml: Returns Parsed Content as XML. html: Returns Parsed Content as HTML. text: Returns Parsed Content as Text. textMain: Uses the boilerpipe library to automatically extract the main content from a web page." },
+ "tikaParseOutputEncoding": { "index": 1, "kind": "parameter", "displayName": "Tika Parse Output Encoding", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.tika.TikaConfiguration", "configurationField": "tikaConfiguration", "description": "The character encoding of the parsed output. Defaults to the default charset of the JVM. The parse operation sets this encoding as the charset of the exchange, so converting the output to text decodes it with this encoding." },
+ "tikaParseOutputFormat": { "index": 2, "kind": "parameter", "displayName": "Tika Parse Output Format", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.tika.TikaParseOutputFormat", "enum": [ "xml", "html", "text" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "xml", "configurationClass": "org.apache.camel.component.tika.TikaConfiguration", "configurationField": "tikaConfiguration", "description": "Tika Output Format. Supported output formats. xml: Returns Parsed Content as XML. html: Returns Parsed Content as HTML. text: Returns Parsed Content as Text." },
"lazyStartProducer": { "index": 3, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
"tikaConfigFile": { "index": 4, "kind": "parameter", "displayName": "Tika Config File", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.tika.TikaConfiguration", "configurationField": "tikaConfiguration", "description": "Path to a Tika JSON configuration file" },
"tikaLoader": { "index": 5, "kind": "parameter", "displayName": "Tika Loader", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.tika.config.loader.TikaLoader", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.tika.TikaConfiguration", "configurationField": "tikaConfiguration", "description": "Tika loader used to configure parsers and detectors" }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/as2-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/as2-component.adoc
index 8b3988308f017..22692a23e9e30 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/as2-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/as2-component.adoc
@@ -36,8 +36,10 @@ as2://apiName/methodName
apiName can be one of:
-* client
-* server
+* client: `client/send` sends an EDI message to a trading partner
+* server: `server/listen` receives EDI messages
+* receipt: `receipt/receive` receives the asynchronous MDNs (receipts) that a `client/send` asked for with
+ `receiptDeliveryOption`
// component options: START
@@ -100,6 +102,25 @@ An `as2://server/listen` consumer receives AS2 messages on `serverPortNumber`, f
A `SIGNED`, `ENCRYPTED` or `SIGNED_ENCRYPTED` message structure also needs the keys and certificates of the signing
and encrypting options.
+=== Sending with client/send
+
+The EDI message (`inBody: ediMessage`) can be text, a stream, a `byte[]` or a file, such as the `java.io.File` or the
+file of a `file` consumer, so a route can send the files of a folder without converting them first. Text is encoded
+with `ediMessageCharset` (US-ASCII when it is not set); the other types are sent as their bytes. Any other body that
+the type converters can turn into bytes is sent as those bytes, and a body that cannot be converted fails the
+exchange with a message that names its type.
+
+`requestUri` defaults to `/`. The content type of the message is set with `ediMessageContentType`; the older
+`ediMessageType` option is deprecated, and it is used only when `ediMessageContentType` is not set.
+
+`ediMessageTransferEncoding` can be `7bit`, `8bit`, `binary`, `base64` or `quoted-printable`.
+
+When the trading partner answers with an HTTP status outside 2xx, such as a 500 when the route of an AS2 server fails,
+the exchange fails with an exception that names the status code and reason. The exchange property
+`CamelAs2.interchange` still holds the `HttpCoreContext` with the request and the response. A 2xx answer sets the body
+to the receipt (MDN) when the partner returned one, and to `null` when there is none, such as a send without
+`dispositionNotificationTo` or with an asynchronous receipt.
+
Several `as2://server/listen` consumers can share a `serverPortNumber`, each with its own `requestUriPattern`. Each
consumer applies its own keys and certificates and its own asynchronous MDN settings (`mdnUserName`, `mdnPassword`,
`mdnAccessToken` and `asyncMdnAllowedHosts`) to the messages received on its own pattern.
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dns-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dns-component.adoc
index 63f273f75cf5e..3d51e1e7d14f1 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dns-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dns-component.adoc
@@ -20,6 +20,7 @@ The component offers the following operations:
* `ip`: to resolve a domain by its ip
* `lookup`: to lookup information about the domain
* `dig`: to run DNS queries
+* `wikipedia` (deprecated): to query the Wikipedia over DNS service, which is no longer available
[NOTE]
====
@@ -177,7 +178,10 @@ YAML::
----
====
-The query must be provided in the header with key `"CamelDnsName"`.
+The query must be provided in the header with key `"CamelDnsName"`; without it the
+exchange fails with an `IllegalArgumentException`. The `"CamelDnsType"` header sets the type of
+the query, such as `MX`, and defaults to `A` when it is not set or not a known type. The
+`"CamelDnsClass"` header sets the DNS class, and defaults to `IN`.
=== Dns Activation Policy
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/github2-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/github2-component.adoc
index 446143a8382c9..b2d070e78eac2 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/github2-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/github2-component.adoc
@@ -153,9 +153,9 @@ Sets the commit status on a pull request.
|pullRequestFiles |none | - `CamelGitHubPullRequest` (integer) (REQUIRED): Pull request number.
Returns the list of files changed in a pull request.
-|getCommitFile |none | - `CamelGitHubCommitSha` (String) (REQUIRED): Commit SHA.
-- `CamelGitHubFilePath` (String) (REQUIRED): File path.
-Returns the content of a file at a specific commit.
+|getCommitFile |String (the path of the file, if the `CamelGitHubFilePath` header is not set) | - `CamelGitHubCommitSha` (String) (REQUIRED): The commit id (40 hexadecimal characters; a branch or tag name is not accepted).
+- `CamelGitHubFilePath` (String): The path of the file in the repository, such as `docs/README.md`. If not set, the body is the path.
+Returns the content of the file in the tree of that commit, as a `String` (decoded with the `encoding` option, or the default charset of the JVM).
|=======================================================================
=== Example: Consuming commits
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/graphql-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/graphql-component.adoc
index 3ec1d0083d546..f53906a8cfc8a 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/graphql-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/graphql-component.adoc
@@ -12,7 +12,7 @@
*{component-header}*
-The GraphQL component is a GraphQL client that communicates over HTTP and supports queries and mutations, but not subscriptions. It uses the https://hc.apache.org/httpcomponents-client-4.5.x/index.html[Apache HttpClient] library.
+The GraphQL component is a GraphQL client that communicates over HTTP and supports queries and mutations, but not subscriptions. It sends the requests with the xref:http-component.adoc[HTTP] component, which uses the Apache HttpClient 5 library.
Maven users will need to add the following dependency to their `pom.xml`
for this component:
@@ -37,9 +37,21 @@ include::partial$component-endpoint-headers.adoc[]
== Message Body
-If the `variables` and `variablesHeader` parameters are not set and the IN body is a JsonObject instance, Camel will use it for the operation's variables. If the `query` and `queryFile` parameters are not set and the IN body is a String, Camel will use it as the query. Camel will store the GraphQL response from the external server on the OUT message body.
-All headers from the IN message will be copied to the OUT message, so headers are preserved during routing.
-Additionally, Camel will add the HTTP response headers as well to the OUT message headers.
+If the `query`, `queryFile` and `queryHeader` parameters are not set, the body is the query: it must be text, bytes, a stream or a file, and another body (such as a `Map`) fails with an `InvalidPayloadException`.
+Otherwise, if the `variables` and `variablesHeader` parameters are not set and the body is a `Map` (such as a `JsonObject`), Camel will use it for the operation's variables.
+Camel will store the GraphQL response from the external server on the message body.
+
+== HTTP Headers
+
+The headers of the message are sent as HTTP request headers (filtered by the `headerFilterStrategy`), except:
+
+* the headers named by the `queryHeader` and `variablesHeader` parameters, as the query and the variables are sent in the JSON body of the request;
+* a `Content-Encoding` header, as the request is not compressed.
+
+The producer always sends the request with `Content-Type: application/json`, `Accept: application/json` and `Accept-Encoding: gzip`, whatever the headers of the message are.
+
+After the call, the message keeps its own headers, and Camel adds the HTTP response headers (such as `CamelHttpResponseCode` and the `Content-Type` of the response).
+The headers the producer set for the request (`CamelHttpMethod`, `Accept` and `Accept-Encoding`) do not stay on the message: a header of the message with the same name keeps its value.
== Examples
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/infinispan-embedded-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/infinispan-embedded-component.adoc
index 3221910ea61bc..ebf9cd695d851 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/infinispan-embedded-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/infinispan-embedded-component.adoc
@@ -51,6 +51,21 @@ The consumer allows listening for events from local infinispan cache.
If no cache configuration is provided, embedded cacheContainer is created directly in the component.
+=== Options read on the component only
+
+All the endpoints of the component share one cache manager, which the component creates when it starts. So the
+options that configure the cache manager are read on the component only: `configurationUri`, `cacheContainer`,
+`cacheContainerConfiguration` and `flags`. Set on an endpoint, these options are not used. Configure them on the
+component instead, for example in `application.properties`:
+
+[source,properties]
+----
+camel.component.infinispan-embedded.configuration-uri = file:/etc/infinispan/infinispan.xml
+----
+
+The `configurationUri` is read with the resource loader of Camel, so it can be a name on the class path, a
+`classpath:` or `file:` uri, or an absolute path, and it can use property placeholders.
+
// component options: START
include::partial$component-configure-options.adoc[]
include::partial$component-endpoint-options.adoc[]
@@ -244,11 +259,11 @@ from("infinispan-embedded:source")
from("direct:start")
.setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUT) // <1>
.setHeader(InfinispanConstants.KEY).constant("123") // <2>
- .to("infinispan-embedded:myCacheName?cacheContainer=#cacheContainer"); // <3>
+ .to("infinispan-embedded:myCacheName"); // <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`
+<3> Put an element to the cache named `myCacheName` of the cache manager of the component
--
+
It is possible to configure the lifetime and/or the idle time before the entry expires and gets evicted from the cache, as example:
@@ -281,7 +296,7 @@ from("direct:start")
return qf.from(User.class).having("name").like("%abc%").build();
}
})
- .to("infinispan-embedded:myCacheName?cacheContainer=#cacheManager") ;
+ .to("infinispan-embedded:myCacheName");
----
+
@@ -293,7 +308,7 @@ Java::
+
[source,java]
----
-from("infinispan-embedded:myCacheName?cacheContainer=#cacheManager&customListener=#myCustomListener")
+from("infinispan-embedded:myCacheName?customListener=#myCustomListener")
.to("mock:result");
----
@@ -302,7 +317,7 @@ XML::
[source,xml]
----
-
+
----
@@ -315,7 +330,6 @@ YAML::
from:
uri: infinispan-embedded:myCacheName
parameters:
- cacheContainer: "#cacheManager"
customListener: "#myCustomListener"
steps:
- to:
@@ -366,7 +380,7 @@ XML::
-
+
@@ -429,7 +443,7 @@ XML::
-
+
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jdbc-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jdbc-component.adoc
index 04943660e73f2..d5f4442e8cf16 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jdbc-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jdbc-component.adoc
@@ -63,6 +63,18 @@ the result.
*Note:* This component fetches `ResultSetMetaData` to be able to return
the column name as the key in the `Map`.
+With `outputType=SelectList` the header `CamelJdbcRowCount` holds the number of rows of the result.
+
+A `BLOB` or `CLOB` value of a row is a `java.sql.Blob` or `java.sql.Clob`, which can be read only while the connection is
+open, and the producer closes the connection before the route continues (except with `outputType=StreamList`,
+which closes it when the exchange is done). So read such a value inside the producer: set `useGetBytesForBlob=true`
+to get a `BLOB` as a `byte[]`, or convert a `CLOB` to text in the SQL query with a function of the database.
+
+The `SQL` of the message body is mandatory: a message without a body fails with an `InvalidPayloadException`.
+
+The `transacted` option is not used (and deprecated). To take part in a Spring transaction, use the
+xref:spring-jdbc-component.adoc[Spring JDBC Component].
+
=== Generated keys
If you insert data using SQL INSERT, then the RDBMS may support auto
@@ -72,7 +84,8 @@ return the generated keys in headers. +
generated keys will be provided as headers with the keys listed in the
table above.
-Using generated keys does not work together with named parameters.
+The generated keys in the header `CamelGeneratedKeysRows` are a `List` of `Map` objects with the key columns,
+whatever the `outputClass` and `readSize` of the endpoint.
=== Using named parameters
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/micrometer-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/micrometer-component.adoc
index d63172bfad4fb..c2464b67c616b 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/micrometer-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/micrometer-component.adoc
@@ -148,8 +148,10 @@ from("direct:in")
will update a counter with name `new.name` instead of `name.not.used` using the
tag `dynamic-key` with value `dynamic-value` in addition to the tag `key` with value `value`.
-All Metrics specific headers are removed from the message once the Micrometer endpoint finishes processing of exchange. While processing exchange
-Micrometer endpoint will catch all exceptions and write log entry using level `warn`.
+All Metrics specific headers are removed from the message once the Micrometer endpoint finishes processing of exchange.
+If the Micrometer endpoint cannot update the meter, then the exchange fails with the exception, which the
+error handler of the route handles as any other failure. For example, a `value`, `increment` or `decrement` that is
+not a number, or a timer `action` that is not `start` or `stop`, fails the exchange with a `TypeConversionException`.
[[MicrometerComponent-counter]]
@@ -412,8 +414,9 @@ micrometer:summary:metricname[?options]
|value |- |Value to use in histogram
|===================================
-If no `value` is not set, nothing is added to histogram and warning is
-logged.
+If `value` is not set, and there is no `CamelMetricsHistogramValue` header, then nothing is added to the
+distribution summary, and nothing is logged. A value that is not a number fails the exchange with a
+`TypeConversionException`.
[tabs]
====
@@ -461,7 +464,7 @@ Java::
+
[source,java]
----
-// nothing is added to simple.histogram; warning is logged
+// nothing is added to simple.histogram
from("direct:in")
.to("micrometer:summary:simple.histogram")
.to("direct:out");
@@ -543,7 +546,7 @@ the Micrometer endpoint URI.
[width="100%",cols="10%,80%,10%",options="header",]
|=================================================================
|Name |Description |Expected type
-|CamelMetricsHistogramValue |Override histogram value in URI |Long
+|CamelMetricsHistogramValue |Override histogram value in URI |Double
|=================================================================
[tabs]
@@ -609,10 +612,9 @@ micrometer:timer:metricname[?options]
|action |- |start or stop
|==========================
-If no `action` or invalid value is provided then warning is logged
-without any timer update. If action `start` is called on an already running
-timer or `stop` is called on an unknown timer, nothing is updated
-and warning is logged.
+If no `action` is provided, then the timer is not updated, and nothing is logged. An `action` that is not
+`start` or `stop` fails the exchange with a `TypeConversionException`. If action `start` is called on an
+already running timer or `stop` is called on an unknown timer, nothing is updated, and nothing is logged.
[tabs]
====
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/pdf-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/pdf-component.adoc
index e2e9dcebcb9ab..913cf95edc278 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/pdf-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/pdf-component.adoc
@@ -95,5 +95,25 @@ YAML::
It is now possible to get the body as a PD Document by using `PDDocument doc = exchange.getIn().getBody(PDDocument.class);`,
which saves the trouble of converting the byte-array to a document.
+The type converter reads a PDF from a `byte[]`, a `ByteArrayOutputStream`, an `InputStream`, a `java.io.File` or a
+`java.nio.file.Path`. The `create`, `append` and `merge` operations leave the PDF in a `ByteArrayOutputStream`, so
+`pdf:create` can be followed by `pdf:extractText` directly. The `extractText` operation fails with an
+`InvalidPayloadException` naming the type of the body when the body is missing or is not one of these types.
+
NOTE: this only works for unprotected PDF files. For password-protected, the files still need to be converted
manually.
+
+=== Creating a PDF from text
+
+The `create` operation needs a body with the text to write; without a body it fails with an `InvalidPayloadException`.
+
+With the default `textProcessingFactory=lineTermination`, the text is written line by line: a line ends at `\r\n`,
+`\r` or `\n`. A tab is written as four spaces, and other control characters, which the fonts cannot show, are left out.
+
+The `pageSize` option takes `LETTER`, `LEGAL` or `A0` to `A6` (default `A4`). The older names `PAGE_SIZE_A0` to
+`PAGE_SIZE_A6` and `PAGE_SIZE_LETTER` are still accepted. An unknown value fails when the endpoint is created.
+
+=== Merging PDF files
+
+The `merge` operation reads the files to merge from the `CamelPdfFilesToMerge` header: a list of at least two
+elements, each a `java.io.File` or a `java.nio.file.Path`.
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/scp-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/scp-component.adoc
index 95fd93cdb3cba..5ce99b38b2951 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/scp-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/scp-component.adoc
@@ -70,6 +70,14 @@ The host key is checked against a known hosts file:
strictHostKeyChecking: "yes"
----
+The directory of the endpoint (`/upload` above) must exist on the remote host, as scp does not create it:
+when it does not exist, each file is written to a file named like the directory, and the last one wins.
+The sub directories in the `CamelFileName` header (such as `mysub/hello.txt`) are created in that directory.
+
+Without a known hosts file (`useUserKnownHostsFile=false` and no `knownHostsFile`), no host is known,
+so the option `strictHostKeyChecking` decides: with `yes` the connection fails, with `no` (the default)
+the host key is not checked.
+
== OpenSSH Certificate Authentication
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/snmp-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/snmp-component.adoc
index 2f0eda76b8e8a..e08d2731e2f8e 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/snmp-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/snmp-component.adoc
@@ -39,9 +39,15 @@ and receiving traps.
== Snmp Producer
-It can also be used to request information using GET method.
+It can also be used to request information using GET method: the producer with `type=POLL`, or without a `type`,
+sends a GET request of the `oids` of the endpoint. With `type=GET_NEXT` the producer walks the `oids`
+(a GET_NEXT request is for the producer only, the consumer supports the types `TRAP` and `POLL`).
+With `type=TRAP` the producer sends the `org.snmp4j.PDU` of the message body as a trap.
-The response body type is `org.apache.camel.component.snmp.SnmpMessage`.
+The response body type is `org.apache.camel.component.snmp.SnmpMessage` (a list of them for `GET_NEXT`), and it converts
+to `String` as the XML text shown in "The result of a poll" below.
+
+Without a port in the endpoint, the default port is 162 for `type=TRAP` and 161 otherwise.
// component options: START
@@ -108,7 +114,7 @@ Be prepared.
-------------------------
As you may notice, default `snmpVersion` is 0, which means `version1` in the endpoint if it is not set explicitly.
Make sure you explicitly set `snmpVersion` which is not default value, in a case of where you are able to query SNMP tables with different versions.
-Other possible values are `version2c` and `version3`.
+Other possible values are 1, which means `version2c`, and 3, which means `version3`.
== Examples
@@ -125,7 +131,8 @@ snmp:127.0.0.1:162?protocol=udp&type=TRAP
-----------------------------------------
You can get the community of SNMP TRAP with message
-header `securityName`, peer address of the SNMP TRAP with message header `peerAddress`.
+header `securityName` (an `org.snmp4j.smi.OctetString`), peer address of the SNMP TRAP with message header `peerAddress`
+(an `org.snmp4j.smi.Address`).
Routing example in Java: (converts the SNMP PDU to XML String)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/tika-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/tika-component.adoc
index 52c7916bdd820..5c60e4eea4c56 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/tika-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/tika-component.adoc
@@ -82,6 +82,12 @@ YAML::
The file should be placed in the Body.
+The body of `detect` and `parse` must convert to an `InputStream`, such as a `java.io.File`, a `byte[]`, a `String` or
+a stream. A missing body or a body that does not convert, such as a `Map`, fails with an `InvalidPayloadException`.
+
+The `parse` operation writes its output in the `tikaParseOutputEncoding` and sets that encoding as the charset of the
+exchange (the `CamelCharsetName` exchange property), so converting the output to a `String` decodes it right.
+
[tabs]
====
Java::
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-http-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-http-component.adoc
index 87f57ffb4064c..89760b5a9bf0e 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-http-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/vertx-http-component.adoc
@@ -89,7 +89,7 @@ URI, or as a header with the key `Exchange.HTTP_QUERY` on the message.
Camel will handle, according to the HTTP response code:
-* Response code is in the range 100..299, Camel regards it as a success
+* Response code is in the range of the `okStatusCodeRange` option (200-299 by default), Camel regards it as a success
response.
* Response code is in the range 300..399, Camel regards it as a
redirection response and will throw a `HttpOperationFailedException`
@@ -123,12 +123,23 @@ The following algorithm determines the HTTP method to be used: +
5. `POST` if there is data to send (body is not `null`). +
6. `GET` otherwise.
+=== Request body
+
+The producer sends the message body as the request body:
+
+* a `java.io.File`, a `java.nio.file.Path` or a file of a file based component (such as `file` or `ftp`) is sent
+as the content of the file (or as a multipart upload with the `multipartUpload` option);
+* a `String`, or a `java.io.Reader`, is sent as its text;
+* a Vert.x `Buffer`, `MultiMap` (a form), `MultipartForm` or `ReadStream` is sent as is;
+* another body must convert to a Vert.x `Buffer`, such as a `byte[]` or an `InputStream`.
+
=== HTTP form parameters
You can send HTTP form parameters in one of two ways.
1. Set the `Exchange.CONTENT_TYPE` header to the value `application/x-www-form-urlencoded` and ensure the message
-body is a `String` formatted as form variables. For example `param1=value1¶m2=value2`.
+body is a `String` formatted as form variables. For example `param1=value1¶m2=value2`. The names and values are
+URL decoded (such as `a%26b` for `a&b`) and encoded again when sent, and a repeated name sends all its values.
2. Set the message body as a https://vertx.io/docs/apidocs/io/vertx/core/MultiMap.html[MultiMap] which allows you to
configure form parameter names and values.
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2AsyncMDNServerConnection.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2AsyncMDNServerConnection.java
index dee0ffb7f4780..adc55beb99710 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2AsyncMDNServerConnection.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2AsyncMDNServerConnection.java
@@ -33,6 +33,7 @@
import org.apache.camel.component.as2.api.io.AS2BHttpServerConnection;
import org.apache.camel.util.ObjectHelper;
import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ConnectionClosedException;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.config.Http1Config;
import org.apache.hc.core5.http.impl.io.HttpService;
@@ -211,6 +212,9 @@ public void run() {
}
this.httpService.handleRequest(this.serverConnection, context);
}
+ } catch (final ConnectionClosedException ex) {
+ // the sender closed the connection after its receipt was delivered
+ LOG.debug("I/O exception: {}", ex.getMessage());
} catch (final IOException ex) {
LOG.error("I/O exception: {}", ex.getMessage(), ex);
} catch (final HttpException ex) {
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ClientManager.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ClientManager.java
index 155b4b354f3ea..922ec625585d3 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ClientManager.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ClientManager.java
@@ -185,7 +185,7 @@ public AS2ClientManager(AS2ClientConnection as2ClientConnection) {
/**
* Send ediMessage to trading partner.
*
- * @param ediMessage - EDI message to transport
+ * @param ediMessage - EDI message to transport: a String, an InputStream or a byte array
* @param requestUri - resource location to deliver message
* @param subject - message subject
* @param from - RFC2822 address of sender
@@ -290,9 +290,12 @@ public HttpCoreContext send(
} else if (ediMessage instanceof String strMsg) {
msgBytes = strMsg.getBytes(ct.getCharset() == null
? StandardCharsets.US_ASCII : ct.getCharset());
+ } else if (ediMessage instanceof byte[] bytesMsg) {
+ msgBytes = bytesMsg;
} else {
throw new IllegalArgumentException(
- "Message type not supported. Must be InputStream or String");
+ "Message type " + ediMessage.getClass().getName()
+ + " not supported. Must be InputStream, String or byte[]");
}
applicationEntity
= EntityUtils.createEDIEntity(msgBytes, ct, ediMessageTransferEncoding, false,
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java
index 57459d9279b22..c85167630fdc3 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/AS2ServerConnection.java
@@ -359,9 +359,10 @@ private AS2ConsumerConfiguration setupConfigurationForRequest(ClassicHttpRequest
Object checkKey = context.getAttribute(AS2_DECRYPTING_PRIVATE_KEY);
if (checkKey == null) {
- LOG.error(
- "FATAL: Decrypting Private Key failed to be read back from HttpContext immediately after injection for path: {}",
- requestUriPath);
+ if (config.getDecryptingPrivateKey() != null) {
+ LOG.error("The decrypting private key could not be read back from the HttpContext for path: {}",
+ requestUriPath);
+ }
} else if (!(checkKey instanceof PrivateKey)) {
LOG.error("FATAL: Key in HttpContext is not a PrivateKey object! Found type: {}", checkKey.getClass().getName());
} else {
diff --git a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/EntityUtils.java b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/EntityUtils.java
index 3bd4404ff917e..2c83e7825f839 100644
--- a/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/EntityUtils.java
+++ b/components/camel-as2/camel-as2-api/src/main/java/org/apache/camel/component/as2/api/util/EntityUtils.java
@@ -16,7 +16,9 @@
*/
package org.apache.camel.component.as2.api.util;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -98,8 +100,7 @@ public static byte[] encode(byte[] data, String encoding) throws CamelException
case "base64":
return Base64.encode(data);
case "quoted-printable":
- // TODO: implement QuotedPrintableOutputStream
- return QuotedPrintableCodec.encodeQuotedPrintable(null, data);
+ return QuotedPrintableCodec.encodeQuotedPrintable(null, data, true);
case "binary":
case "7bit":
case "8bit":
@@ -121,9 +122,7 @@ public static OutputStream encode(OutputStream os, String encoding) throws Camel
case "base64":
return Base64OutputStream.builder().setOutputStream(os).setEncode(true).get();
case "quoted-printable":
- // TODO: implement QuotedPrintableOutputStream
- return Base64OutputStream.builder().setOutputStream(os).setEncode(true).get();
- // return new Base64OutputStream(os, true);
+ return new QuotedPrintableOutputStream(os);
case "binary":
case "7bit":
case "8bit":
@@ -172,8 +171,11 @@ public static InputStream decode(InputStream is, String encoding) throws CamelEx
case "base64":
return Base64InputStream.builder().setInputStream(is).setEncode(false).get();
case "quoted-printable":
- // TODO: implement QuotedPrintableInputStream
- return Base64InputStream.builder().setInputStream(is).setEncode(false).get();
+ try {
+ return new ByteArrayInputStream(QuotedPrintableCodec.decodeQuotedPrintable(is.readAllBytes()));
+ } catch (IOException | DecoderException e) {
+ throw new CamelException("Failed to decode quoted-printable content", e);
+ }
case "binary":
case "7bit":
case "8bit":
@@ -287,4 +289,35 @@ public static String printEntity(HttpEntity entity) throws IOException {
}
}
+ /**
+ * Encodes what is written to it as quoted-printable (RFC 2045, with soft line breaks) when it is closed.
+ */
+ private static final class QuotedPrintableOutputStream extends FilterOutputStream {
+
+ private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ private boolean closed;
+
+ QuotedPrintableOutputStream(OutputStream os) {
+ super(os);
+ }
+
+ @Override
+ public void write(int b) {
+ buffer.write(b);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) {
+ buffer.write(b, off, len);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (!closed) {
+ closed = true;
+ out.write(QuotedPrintableCodec.encodeQuotedPrintable(null, buffer.toByteArray(), true));
+ super.close();
+ }
+ }
+ }
}
diff --git a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2AsyncMDNServerConnectionTest.java b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2AsyncMDNServerConnectionTest.java
index f8c7eb5dddddb..3994b51995720 100644
--- a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2AsyncMDNServerConnectionTest.java
+++ b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2AsyncMDNServerConnectionTest.java
@@ -18,16 +18,20 @@
import java.net.HttpURLConnection;
import java.net.URL;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.io.HttpRequestHandler;
import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.logging.log4j.Level;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.*;
class AS2AsyncMDNServerConnectionTest {
@@ -61,9 +65,7 @@ public void handle(ClassicHttpRequest request, ClassicHttpResponse response, Htt
}
});
- // Wait for server to be ready
- Thread.sleep(200);
-
+ // the server socket is bound when the connection is created, so the server is ready
// Send a request with a Host header that doesn't match the server's hostname
// This previously caused HTTP 421 due to RequestValidateHost
HttpURLConnection conn
@@ -80,4 +82,25 @@ public void handle(ClassicHttpRequest request, ClassicHttpResponse response, Htt
// Should NOT get 421 (Misdirected Request) anymore
assertNotEquals(421, responseCode, "Should not reject requests with non-matching Host header");
}
+
+ @Test
+ void closedConnectionAfterAReceiptIsNotLoggedAsError() throws Exception {
+ connection.receive("/test-mdn", (request, response, context) -> response.setCode(200));
+
+ try (LogCapture log = new LogCapture(AS2AsyncMDNServerConnection.class)) {
+ HttpURLConnection conn
+ = (HttpURLConnection) new URL("http://localhost:" + port + "/test-mdn").openConnection();
+ conn.setRequestMethod("POST");
+ conn.setRequestProperty("Connection", "close");
+ conn.setDoOutput(true);
+ conn.getOutputStream().write("receipt".getBytes());
+ assertEquals(200, conn.getResponseCode());
+ conn.disconnect();
+
+ // the request handler thread ends when the sender closes the connection
+ await().atMost(10, TimeUnit.SECONDS).until(() -> log.hasMessageContaining("Connection is closed"));
+ assertEquals(List.of(), log.events(Level.ERROR), "a closed connection is not an error");
+ assertTrue(log.eventsContaining("Connection is closed").stream().allMatch(e -> e.getLevel() == Level.DEBUG));
+ }
+ }
}
diff --git a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2UnencryptedMessageTest.java b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2UnencryptedMessageTest.java
index 51901d5622a5f..028bfcb95b796 100644
--- a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2UnencryptedMessageTest.java
+++ b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/AS2UnencryptedMessageTest.java
@@ -19,6 +19,7 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.cert.Certificate;
+import java.util.List;
import org.apache.camel.component.as2.api.entity.*;
import org.apache.camel.component.as2.api.util.HttpMessageUtils;
@@ -36,6 +37,7 @@
import org.apache.hc.core5.http.io.HttpRequestHandler;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.protocol.HttpCoreContext;
+import org.apache.logging.log4j.Level;
import org.bouncycastle.cms.jcajce.ZlibExpanderProvider;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -166,6 +168,22 @@ public void compressedMessageRequestTest() throws Exception {
}
+ @Test
+ public void unencryptedMessageToAServerWithoutDecryptingKeyLogsNoError() throws Exception {
+ AS2ClientManager clientManager = createDefaultClientManager();
+
+ try (LogCapture log = new LogCapture(AS2ServerConnection.class)) {
+ HttpCoreContext httpContext = clientManager.send(EDI_MESSAGE, REQUEST_URI, SUBJECT, FROM, AS2_NAME, AS2_NAME,
+ AS2MessageStructure.PLAIN, AS2MediaType.APPLICATION_EDIFACT, null,
+ null, null, null, null, null,
+ DISPOSITION_NOTIFICATION_TO, SIGNED_RECEIPT_MIC_ALGORITHMS, null, null,
+ "file.txt", null, null, null, null);
+
+ assertEquals(HttpStatus.SC_OK, httpContext.getResponse().getCode());
+ assertEquals(List.of(), log.events(Level.ERROR), "the server has no decrypting key, as it needs none");
+ }
+ }
+
@Test
public void mdnMessageTest() throws Exception {
AS2ClientManager clientManager = createDefaultClientManager();
diff --git a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/LogCapture.java b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/LogCapture.java
new file mode 100644
index 0000000000000..14528224a54a5
--- /dev/null
+++ b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/LogCapture.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.as2.api;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.config.Property;
+
+/**
+ * Captures the log events of one logger, down to DEBUG, while it is open.
+ */
+final class LogCapture extends AbstractAppender implements AutoCloseable {
+
+ private final List events = new CopyOnWriteArrayList<>();
+ private final Logger logger;
+ private final Level previousLevel;
+
+ LogCapture(Class> loggerClass) {
+ super("LogCapture-" + loggerClass.getSimpleName(), null, null, true, Property.EMPTY_ARRAY);
+ this.logger = (Logger) LogManager.getLogger(loggerClass);
+ this.previousLevel = logger.getLevel();
+ start();
+ logger.addAppender(this);
+ logger.setLevel(Level.DEBUG);
+ }
+
+ @Override
+ public void append(LogEvent event) {
+ events.add(event.toImmutable());
+ }
+
+ List events(Level level) {
+ return events.stream().filter(e -> e.getLevel() == level).toList();
+ }
+
+ boolean hasMessageContaining(String text) {
+ return events.stream().anyMatch(e -> e.getMessage().getFormattedMessage().contains(text));
+ }
+
+ List eventsContaining(String text) {
+ return events.stream().filter(e -> e.getMessage().getFormattedMessage().contains(text)).toList();
+ }
+
+ @Override
+ public void close() {
+ logger.removeAppender(this);
+ logger.setLevel(previousLevel);
+ stop();
+ }
+}
diff --git a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/util/EntityUtilsTest.java b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/util/EntityUtilsTest.java
index f35e3c11470f9..14d65762a0b87 100644
--- a/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/util/EntityUtilsTest.java
+++ b/components/camel-as2/camel-as2-api/src/test/java/org/apache/camel/component/as2/api/util/EntityUtilsTest.java
@@ -16,6 +16,10 @@
*/
package org.apache.camel.component.as2.api.util;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import org.apache.camel.component.as2.api.AS2Header;
@@ -70,4 +74,33 @@ public void testCreateEDIEntityContentTypeWithoutContentDisposition() throws Exc
Header[] actualContentDisposition = applicationEntity.getHeaders(AS2Header.CONTENT_DISPOSITION);
Assertions.assertEquals(0, actualContentDisposition.length, "no Content-Disposition headers found");
}
+
+ @Test
+ public void testQuotedPrintableOutputStreamEncodesQuotedPrintable() throws Exception {
+ byte[] message = ("UNB+UNOA:1+005435656:1+006415160:1+060515:1434+00000000000778'\r\n"
+ + "FTX+AAI+++Prix = 12 \u20ac, Gr\u00fc\u00dfe, a line longer than seventy-six characters'")
+ .getBytes(StandardCharsets.UTF_8);
+
+ ByteArrayOutputStream encoded = new ByteArrayOutputStream();
+ try (OutputStream os = EntityUtils.encode(encoded, "quoted-printable")) {
+ os.write(message);
+ }
+
+ String text = encoded.toString(StandardCharsets.US_ASCII);
+ Assertions.assertTrue(text.contains("Prix =3D 12 =E2=82=AC"), text);
+ for (String line : text.split("\r\n")) {
+ Assertions.assertTrue(line.length() <= 76, "line longer than 76 characters: " + line);
+ }
+ Assertions.assertArrayEquals(message, EntityUtils.decode(encoded.toByteArray(), "quoted-printable"));
+ }
+
+ @Test
+ public void testQuotedPrintableInputStreamDecodesQuotedPrintable() throws Exception {
+ byte[] message = "FTX+AAI+++Prix = 12 \u20ac'".getBytes(StandardCharsets.UTF_8);
+ byte[] encoded = EntityUtils.encode(message, "quoted-printable");
+
+ try (InputStream is = EntityUtils.decode(new ByteArrayInputStream(encoded), "quoted-printable")) {
+ Assertions.assertArrayEquals(message, is.readAllBytes());
+ }
+ }
}
diff --git a/components/camel-as2/camel-as2-component/src/generated/java/org/apache/camel/component/as2/AS2ClientManagerEndpointConfiguration.java b/components/camel-as2/camel-as2-component/src/generated/java/org/apache/camel/component/as2/AS2ClientManagerEndpointConfiguration.java
index 24e6a57f87380..83701ebdff35a 100644
--- a/components/camel-as2/camel-as2-component/src/generated/java/org/apache/camel/component/as2/AS2ClientManagerEndpointConfiguration.java
+++ b/components/camel-as2/camel-as2-component/src/generated/java/org/apache/camel/component/as2/AS2ClientManagerEndpointConfiguration.java
@@ -44,7 +44,7 @@ public final class AS2ClientManagerEndpointConfiguration extends AS2Configuratio
@ApiParam(optional = true, apiMethods = {@ApiMethod(methodName = "send", description="An RFC2822 address to request a receipt or null if no receipt requested")})
private String dispositionNotificationTo;
@UriParam
- @ApiParam(optional = false, apiMethods = {@ApiMethod(methodName = "send", description="EDI message to transport")})
+ @ApiParam(optional = false, apiMethods = {@ApiMethod(methodName = "send", description="EDI message to transport: a String, an InputStream or a byte array")})
private Object ediMessage;
@UriParam
@ApiParam(optional = true, apiMethods = {@ApiMethod(methodName = "send", description="The charset of the EDI message")})
diff --git a/components/camel-as2/camel-as2-component/src/generated/resources/META-INF/org/apache/camel/component/as2/as2.json b/components/camel-as2/camel-as2-component/src/generated/resources/META-INF/org/apache/camel/component/as2/as2.json
index 989fb9a25f74f..ee51bd92337cf 100644
--- a/components/camel-as2/camel-as2-component/src/generated/resources/META-INF/org/apache/camel/component/as2/as2.json
+++ b/components/camel-as2/camel-as2-component/src/generated/resources/META-INF/org/apache/camel/component/as2/as2.json
@@ -46,7 +46,7 @@
"dispositionNotificationTo": { "index": 10, "kind": "parameter", "displayName": "Disposition Notification To", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The value of the Disposition-Notification-To header. Assigning a value to this parameter requests a message disposition notification (MDN) for the AS2 message." },
"ediMessageCharset": { "index": 11, "kind": "parameter", "displayName": "Edi Message Charset", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "us-ascii", "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The charset of the content type of EDI message." },
"ediMessageTransferEncoding": { "index": 12, "kind": "parameter", "displayName": "Edi Message Transfer Encoding", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The transfer encoding of EDI message." },
- "ediMessageType": { "index": 13, "kind": "parameter", "displayName": "Edi Message Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "application\/edifact", "application\/edi-x12", "application\/edi-consent", "application\/xml" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The content type of EDI message. One of application\/edifact, application\/edi-x12, application\/edi-consent, application\/xml" },
+ "ediMessageType": { "index": 13, "kind": "parameter", "displayName": "Edi Message Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "application\/edifact", "application\/edi-x12", "application\/edi-consent", "application\/xml" ], "deprecated": true, "deprecationNote": "Use ediMessageContentType instead", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The content type of EDI message. One of application\/edifact, application\/edi-x12, application\/edi-consent, application\/xml. client\/send uses this value only when ediMessageContentType is not set. Deprecation note: Use ediMessageContentType instead" },
"from": { "index": 14, "kind": "parameter", "displayName": "From", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The value of the From header of AS2 message." },
"httpConnectionPoolSize": { "index": 15, "kind": "parameter", "displayName": "Http Connection Pool Size", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 5, "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The maximum size of the connection pool for http connections (client only)" },
"httpConnectionPoolTtl": { "index": 16, "kind": "parameter", "displayName": "Http Connection Pool Ttl", "group": "common", "label": "", "required": false, "type": "duration", "javaType": "java.time.Duration", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "15m", "configurationClass": "org.apache.camel.component.as2.AS2Configuration", "configurationField": "configuration", "description": "The time to live for connections in the connection pool (client only)" },
@@ -92,7 +92,7 @@
"server": { "consumerOnly": true, "producerOnly": false, "description": "Receives EDI Messages over HTTP", "methods": { "listen": { "description": "", "signatures": [ "void listen(String requestUriPattern, org.apache.hc.core5.http.io.HttpRequestHandler handler)" ] } } }
},
"apiProperties": {
- "client": { "methods": { "send": { "properties": { "accessToken": { "index": 0, "kind": "parameter", "displayName": "Access Token", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The access token that is used by the client for bearer authentication", "optional": true }, "as2From": { "index": 1, "kind": "parameter", "displayName": "As2 From", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "AS2 name of sender", "optional": false }, "as2MessageStructure": { "index": 2, "kind": "parameter", "displayName": "As2 Message Structure", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2MessageStructure", "enum": [ "PLAIN", "SIGNED", "ENCRYPTED", "SIGNED_ENCRYPTED", "PLAIN_COMPRESSED", "COMPRESSED_SIGNED", "SIGNED_COMPRESSED", "ENCRYPTED_COMPRESSED", "ENCRYPTED_COMPRESSED_SIGNED", "ENCRYPTED_SIGNED_COMPRESSED" ], "deprecated": false, "autowired": false, "secret": false, "description": "The structure of AS2 to send; see AS2MessageStructure", "optional": false }, "as2To": { "index": 3, "kind": "parameter", "displayName": "As2 To", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "AS2 name of recipient", "optional": false }, "attachedFileName": { "index": 4, "kind": "parameter", "displayName": "Attached File Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the attached file or null if user doesn't want to specify it", "optional": true }, "compressionAlgorithm": { "index": 5, "kind": "parameter", "displayName": "Compression Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2CompressionAlgorithm", "enum": [ "ZLIB" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to compress the message or null if sending EDI message uncompressed", "optional": true }, "dispositionNotificationTo": { "index": 6, "kind": "parameter", "displayName": "Disposition Notification To", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "An RFC2822 address to request a receipt or null if no receipt requested", "optional": true }, "ediMessage": { "index": 7, "kind": "parameter", "displayName": "Edi Message", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "description": "EDI message to transport", "optional": false }, "ediMessageCharset": { "index": 8, "kind": "parameter", "displayName": "Edi Message Charset", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The charset of the EDI message", "optional": true }, "ediMessageContentType": { "index": 9, "kind": "parameter", "displayName": "Edi Message Content Type", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type of EDI message", "optional": false }, "ediMessageTransferEncoding": { "index": 10, "kind": "parameter", "displayName": "Edi Message Transfer Encoding", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The transfer encoding used to transport EDI message", "optional": true }, "encryptingAlgorithm": { "index": 11, "kind": "parameter", "displayName": "Encrypting Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2EncryptionAlgorithm", "enum": [ "AES128_CBC", "AES192_CBC", "AES256_CBC", "AES128_CCM", "AES192_CCM", "AES256_CCM", "AES128_GCM", "AES192_GCM", "AES256_GCM", "CAMELLIA128_CBC", "CAMELLIA192_CBC", "CAMELLIA256_CBC", "CAST5_CBC", "DES_CBC", "DES_EDE3_CBC", "GOST28147_GCFB", "IDEA_CBC", "RC2_CBC", "RC4", "SEED_CBC" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to encrypt the message or null if sending EDI message unencrypted", "optional": true }, "encryptingCertificateChain": { "index": 12, "kind": "parameter", "displayName": "Encrypting Certificate Chain", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.cert.Certificate[]", "deprecated": false, "autowired": false, "secret": false, "description": "The chain of certificates used to encrypt the message or null if sending EDI message unencrypted", "optional": true }, "from": { "index": 13, "kind": "parameter", "displayName": "From", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "RFC2822 address of sender", "optional": false }, "password": { "index": 14, "kind": "parameter", "displayName": "Password", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The password that is used by the client for basic authentication", "optional": true }, "receiptDeliveryOption": { "index": 15, "kind": "parameter", "displayName": "Receipt Delivery Option", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The return URL that the message receiver should send an asynchronous MDN to", "optional": true }, "requestUri": { "index": 16, "kind": "parameter", "displayName": "Request Uri", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Resource location to deliver message", "optional": false }, "signedReceiptMicAlgorithms": { "index": 17, "kind": "parameter", "displayName": "Signed Receipt Mic Algorithms", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The senders list of signing algorithms for signing receipt, in preferred order, or null if requesting an unsigned receipt.", "optional": true }, "signingAlgorithm": { "index": 18, "kind": "parameter", "displayName": "Signing Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2SignatureAlgorithm", "enum": [ "SHA3_224WITHRSA", "SHA3_256WITHRSA", "SHA3_384withRSA", "SHA3_512WITHRSA", "MD5WITHRSA", "SHA1WITHRSA", "MD2WITHRSA", "SHA224WITHRSA", "SHA256WITHRSA", "SHA384WITHRSA", "SHA512WITHRSA", "RIPEMD128WITHRSA", "RIPEMD160WITHRSA", "RIPEMD256WITHRSA", "SHA224WITHDSA", "SHA256WITHDSA", "SHA384WITHDSA", "SHA512WITHDSA", "SHA3_224WITHDSA", "SHA3_256WITHDSA", "SHA3_384WITHDSA", "SHA3_512WITHDSA", "SHA1WITHDSA", "SHA3_224WITHECDSA", "SHA3_256WITHECDSA", "SHA3_384WITHECDSA", "SHA3_512WITHECDSA", "SHA1WITHECDSA", "SHA224WITHECDSA", "SHA256WITHECDSA", "SHA384WITHECDSA", "SHA512WITHECDSA", "SHA1WITHPLAIN_ECDSA", "SHA224WITHPLAIN_ECDSA", "SHA256WITHPLAIN_ECDSA", "SHA384WITHPLAIN_ECDSA", "SHA512WITHPLAIN_ECDSA", "RIPEMD160WITHPLAIN_ECDSA", "SHA1WITHRSAANDMGF1", "SHA224WITHRSAANDMGF1", "SHA256WITHRSAANDMGF1", "SHA384WITHRSAANDMGF1", "SHA512WITHRSAANDMGF1", "SHA3_224WITHRSAANDMGF1", "SHA3_256WITHRSAANDMGF1", "SHA3_384WITHRSAANDMGF1", "SHA3_512WITHRSAANDMGF1" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to sign the message or null if sending EDI message unsigned", "optional": true }, "signingCertificateChain": { "index": 19, "kind": "parameter", "displayName": "Signing Certificate Chain", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.cert.Certificate[]", "deprecated": false, "autowired": false, "secret": false, "description": "The chain of certificates used to sign the message or null if sending EDI message unsigned", "optional": true }, "signingPrivateKey": { "index": 20, "kind": "parameter", "displayName": "Signing Private Key", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.PrivateKey", "deprecated": false, "autowired": false, "secret": false, "description": "The private key used to sign EDI message", "optional": true }, "subject": { "index": 21, "kind": "parameter", "displayName": "Subject", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Message subject", "optional": false }, "userName": { "index": 22, "kind": "parameter", "displayName": "User Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The user-name that is used for basic authentication", "optional": true } } } } },
+ "client": { "methods": { "send": { "properties": { "accessToken": { "index": 0, "kind": "parameter", "displayName": "Access Token", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The access token that is used by the client for bearer authentication", "optional": true }, "as2From": { "index": 1, "kind": "parameter", "displayName": "As2 From", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "AS2 name of sender", "optional": false }, "as2MessageStructure": { "index": 2, "kind": "parameter", "displayName": "As2 Message Structure", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2MessageStructure", "enum": [ "PLAIN", "SIGNED", "ENCRYPTED", "SIGNED_ENCRYPTED", "PLAIN_COMPRESSED", "COMPRESSED_SIGNED", "SIGNED_COMPRESSED", "ENCRYPTED_COMPRESSED", "ENCRYPTED_COMPRESSED_SIGNED", "ENCRYPTED_SIGNED_COMPRESSED" ], "deprecated": false, "autowired": false, "secret": false, "description": "The structure of AS2 to send; see AS2MessageStructure", "optional": false }, "as2To": { "index": 3, "kind": "parameter", "displayName": "As2 To", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "AS2 name of recipient", "optional": false }, "attachedFileName": { "index": 4, "kind": "parameter", "displayName": "Attached File Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the attached file or null if user doesn't want to specify it", "optional": true }, "compressionAlgorithm": { "index": 5, "kind": "parameter", "displayName": "Compression Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2CompressionAlgorithm", "enum": [ "ZLIB" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to compress the message or null if sending EDI message uncompressed", "optional": true }, "dispositionNotificationTo": { "index": 6, "kind": "parameter", "displayName": "Disposition Notification To", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "An RFC2822 address to request a receipt or null if no receipt requested", "optional": true }, "ediMessage": { "index": 7, "kind": "parameter", "displayName": "Edi Message", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "description": "EDI message to transport: a String, an InputStream or a byte array", "optional": false }, "ediMessageCharset": { "index": 8, "kind": "parameter", "displayName": "Edi Message Charset", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The charset of the EDI message", "optional": true }, "ediMessageContentType": { "index": 9, "kind": "parameter", "displayName": "Edi Message Content Type", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type of EDI message", "optional": false }, "ediMessageTransferEncoding": { "index": 10, "kind": "parameter", "displayName": "Edi Message Transfer Encoding", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The transfer encoding used to transport EDI message", "optional": true }, "encryptingAlgorithm": { "index": 11, "kind": "parameter", "displayName": "Encrypting Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2EncryptionAlgorithm", "enum": [ "AES128_CBC", "AES192_CBC", "AES256_CBC", "AES128_CCM", "AES192_CCM", "AES256_CCM", "AES128_GCM", "AES192_GCM", "AES256_GCM", "CAMELLIA128_CBC", "CAMELLIA192_CBC", "CAMELLIA256_CBC", "CAST5_CBC", "DES_CBC", "DES_EDE3_CBC", "GOST28147_GCFB", "IDEA_CBC", "RC2_CBC", "RC4", "SEED_CBC" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to encrypt the message or null if sending EDI message unencrypted", "optional": true }, "encryptingCertificateChain": { "index": 12, "kind": "parameter", "displayName": "Encrypting Certificate Chain", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.cert.Certificate[]", "deprecated": false, "autowired": false, "secret": false, "description": "The chain of certificates used to encrypt the message or null if sending EDI message unencrypted", "optional": true }, "from": { "index": 13, "kind": "parameter", "displayName": "From", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "RFC2822 address of sender", "optional": false }, "password": { "index": 14, "kind": "parameter", "displayName": "Password", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The password that is used by the client for basic authentication", "optional": true }, "receiptDeliveryOption": { "index": 15, "kind": "parameter", "displayName": "Receipt Delivery Option", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The return URL that the message receiver should send an asynchronous MDN to", "optional": true }, "requestUri": { "index": 16, "kind": "parameter", "displayName": "Request Uri", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Resource location to deliver message", "optional": false }, "signedReceiptMicAlgorithms": { "index": 17, "kind": "parameter", "displayName": "Signed Receipt Mic Algorithms", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The senders list of signing algorithms for signing receipt, in preferred order, or null if requesting an unsigned receipt.", "optional": true }, "signingAlgorithm": { "index": 18, "kind": "parameter", "displayName": "Signing Algorithm", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.as2.api.AS2SignatureAlgorithm", "enum": [ "SHA3_224WITHRSA", "SHA3_256WITHRSA", "SHA3_384withRSA", "SHA3_512WITHRSA", "MD5WITHRSA", "SHA1WITHRSA", "MD2WITHRSA", "SHA224WITHRSA", "SHA256WITHRSA", "SHA384WITHRSA", "SHA512WITHRSA", "RIPEMD128WITHRSA", "RIPEMD160WITHRSA", "RIPEMD256WITHRSA", "SHA224WITHDSA", "SHA256WITHDSA", "SHA384WITHDSA", "SHA512WITHDSA", "SHA3_224WITHDSA", "SHA3_256WITHDSA", "SHA3_384WITHDSA", "SHA3_512WITHDSA", "SHA1WITHDSA", "SHA3_224WITHECDSA", "SHA3_256WITHECDSA", "SHA3_384WITHECDSA", "SHA3_512WITHECDSA", "SHA1WITHECDSA", "SHA224WITHECDSA", "SHA256WITHECDSA", "SHA384WITHECDSA", "SHA512WITHECDSA", "SHA1WITHPLAIN_ECDSA", "SHA224WITHPLAIN_ECDSA", "SHA256WITHPLAIN_ECDSA", "SHA384WITHPLAIN_ECDSA", "SHA512WITHPLAIN_ECDSA", "RIPEMD160WITHPLAIN_ECDSA", "SHA1WITHRSAANDMGF1", "SHA224WITHRSAANDMGF1", "SHA256WITHRSAANDMGF1", "SHA384WITHRSAANDMGF1", "SHA512WITHRSAANDMGF1", "SHA3_224WITHRSAANDMGF1", "SHA3_256WITHRSAANDMGF1", "SHA3_384WITHRSAANDMGF1", "SHA3_512WITHRSAANDMGF1" ], "deprecated": false, "autowired": false, "secret": false, "description": "The algorithm used to sign the message or null if sending EDI message unsigned", "optional": true }, "signingCertificateChain": { "index": 19, "kind": "parameter", "displayName": "Signing Certificate Chain", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.cert.Certificate[]", "deprecated": false, "autowired": false, "secret": false, "description": "The chain of certificates used to sign the message or null if sending EDI message unsigned", "optional": true }, "signingPrivateKey": { "index": 20, "kind": "parameter", "displayName": "Signing Private Key", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.security.PrivateKey", "deprecated": false, "autowired": false, "secret": false, "description": "The private key used to sign EDI message", "optional": true }, "subject": { "index": 21, "kind": "parameter", "displayName": "Subject", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Message subject", "optional": false }, "userName": { "index": 22, "kind": "parameter", "displayName": "User Name", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The user-name that is used for basic authentication", "optional": true } } } } },
"receipt": { "methods": { "receive": { "properties": { "requestUriPattern": { "index": 0, "kind": "parameter", "displayName": "Request Uri Pattern", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "", "optional": false } } } } },
"server": { "methods": { "listen": { "properties": { "requestUriPattern": { "index": 0, "kind": "parameter", "displayName": "Request Uri Pattern", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "", "optional": false } } } } }
}
diff --git a/components/camel-as2/camel-as2-component/src/main/docs/as2-component.adoc b/components/camel-as2/camel-as2-component/src/main/docs/as2-component.adoc
index 8b3988308f017..22692a23e9e30 100644
--- a/components/camel-as2/camel-as2-component/src/main/docs/as2-component.adoc
+++ b/components/camel-as2/camel-as2-component/src/main/docs/as2-component.adoc
@@ -36,8 +36,10 @@ as2://apiName/methodName
apiName can be one of:
-* client
-* server
+* client: `client/send` sends an EDI message to a trading partner
+* server: `server/listen` receives EDI messages
+* receipt: `receipt/receive` receives the asynchronous MDNs (receipts) that a `client/send` asked for with
+ `receiptDeliveryOption`
// component options: START
@@ -100,6 +102,25 @@ An `as2://server/listen` consumer receives AS2 messages on `serverPortNumber`, f
A `SIGNED`, `ENCRYPTED` or `SIGNED_ENCRYPTED` message structure also needs the keys and certificates of the signing
and encrypting options.
+=== Sending with client/send
+
+The EDI message (`inBody: ediMessage`) can be text, a stream, a `byte[]` or a file, such as the `java.io.File` or the
+file of a `file` consumer, so a route can send the files of a folder without converting them first. Text is encoded
+with `ediMessageCharset` (US-ASCII when it is not set); the other types are sent as their bytes. Any other body that
+the type converters can turn into bytes is sent as those bytes, and a body that cannot be converted fails the
+exchange with a message that names its type.
+
+`requestUri` defaults to `/`. The content type of the message is set with `ediMessageContentType`; the older
+`ediMessageType` option is deprecated, and it is used only when `ediMessageContentType` is not set.
+
+`ediMessageTransferEncoding` can be `7bit`, `8bit`, `binary`, `base64` or `quoted-printable`.
+
+When the trading partner answers with an HTTP status outside 2xx, such as a 500 when the route of an AS2 server fails,
+the exchange fails with an exception that names the status code and reason. The exchange property
+`CamelAs2.interchange` still holds the `HttpCoreContext` with the request and the response. A 2xx answer sets the body
+to the receipt (MDN) when the partner returned one, and to `null` when there is none, such as a send without
+`dispositionNotificationTo` or with an asynchronous receipt.
+
Several `as2://server/listen` consumers can share a `serverPortNumber`, each with its own `requestUriPattern`. Each
consumer applies its own keys and certificates and its own asynchronous MDN settings (`mdnUserName`, `mdnPassword`,
`mdnAccessToken` and `asyncMdnAllowedHosts`) to the messages received on its own pattern.
diff --git a/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java b/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java
index 3bc6aec167045..b13a8e460c592 100644
--- a/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java
+++ b/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Configuration.java
@@ -66,7 +66,9 @@ public class AS2Configuration {
private Integer serverPortNumber;
@UriParam(defaultValue = "/")
private String requestUri = "/";
+ @Deprecated
@UriParam(enums = "application/edifact,application/edi-x12,application/edi-consent,application/xml")
+ @Metadata(deprecationNote = "Use ediMessageContentType instead")
private String ediMessageType;
@UriParam(defaultValue = "us-ascii")
private String ediMessageCharset;
@@ -277,14 +279,16 @@ public void setRequestUri(String requestUri) {
this.requestUri = requestUri;
}
+ @Deprecated
public String getEdiMessageType() {
return ediMessageType;
}
/**
* The content type of EDI message. One of application/edifact, application/edi-x12, application/edi-consent,
- * application/xml
+ * application/xml. client/send uses this value only when ediMessageContentType is not set.
*/
+ @Deprecated
public void setEdiMessageType(String ediMessageType) {
this.ediMessageType = ediMessageType;
}
diff --git a/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Endpoint.java b/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Endpoint.java
index 14b4b8dbba472..a3a5907c7f677 100644
--- a/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Endpoint.java
+++ b/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Endpoint.java
@@ -62,6 +62,10 @@
+ ",greedy,scheduler,schedulerProperties,scheduledExecutorService,backoffMultiplier,backoffIdleThreshold,backoffErrorThreshold,repeatCount,bridgeErrorHandler")
public class AS2Endpoint extends AbstractApiEndpoint {
+ private static final String REQUEST_URI = "requestUri";
+ private static final String DEFAULT_REQUEST_URI = "/";
+ private static final String EDI_MESSAGE_CONTENT_TYPE = "ediMessageContentType";
+
@UriParam
private AS2Configuration configuration;
@@ -166,14 +170,27 @@ public void setAs2MessageStructure(AS2MessageStructure as2MessageStructure) {
configuration.setAs2MessageStructure(as2MessageStructure);
}
+ @Deprecated
public String getEdiMessageType() {
return configuration.getEdiMessageType();
}
- public void setEdiMessageContentType(String ediMessageType) {
+ @Deprecated
+ public void setEdiMessageType(String ediMessageType) {
configuration.setEdiMessageType(ediMessageType);
}
+ public String getEdiMessageContentType() {
+ return configuration instanceof AS2ClientManagerEndpointConfiguration client
+ ? client.getEdiMessageContentType() : null;
+ }
+
+ public void setEdiMessageContentType(String ediMessageContentType) {
+ if (configuration instanceof AS2ClientManagerEndpointConfiguration client) {
+ client.setEdiMessageContentType(ediMessageContentType);
+ }
+ }
+
public String getEdiMessageTransferEncoding() {
return configuration.getEdiMessageTransferEncoding();
}
@@ -278,6 +295,19 @@ public void setSslContext(SSLContext sslContext) {
configuration.setSslContext(sslContext);
}
+ @Override
+ @SuppressWarnings("deprecation")
+ public void interceptProperties(Map properties) {
+ if (apiName == AS2ApiName.CLIENT) {
+ // the generated configuration of client/send has its own requestUri without the default
+ properties.putIfAbsent(REQUEST_URI, DEFAULT_REQUEST_URI);
+ // the deprecated ediMessageType is the content type when ediMessageContentType is not set
+ if (configuration.getEdiMessageType() != null) {
+ properties.putIfAbsent(EDI_MESSAGE_CONTENT_TYPE, configuration.getEdiMessageType());
+ }
+ }
+ }
+
@Override
protected ApiMethodPropertiesHelper getPropertiesHelper() {
return AS2PropertiesHelper.getHelper(getCamelContext());
diff --git a/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Producer.java b/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Producer.java
index b3c389ba8c968..89c7ee5d4403b 100644
--- a/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Producer.java
+++ b/components/camel-as2/camel-as2-component/src/main/java/org/apache/camel/component/as2/AS2Producer.java
@@ -16,13 +16,18 @@
*/
package org.apache.camel.component.as2;
+import java.io.InputStream;
+import java.util.Map;
+
import org.apache.camel.Exchange;
+import org.apache.camel.RuntimeCamelException;
import org.apache.camel.component.as2.api.entity.DispositionNotificationMultipartReportEntity;
import org.apache.camel.component.as2.api.entity.MultipartSignedEntity;
import org.apache.camel.component.as2.internal.AS2ApiName;
import org.apache.camel.component.as2.internal.AS2Constants;
import org.apache.camel.component.as2.internal.AS2PropertiesHelper;
import org.apache.camel.support.component.AbstractApiProducer;
+import org.apache.camel.support.component.ApiMethod;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpResponse;
@@ -33,15 +38,52 @@
*/
public class AS2Producer extends AbstractApiProducer {
+ private static final String EDI_MESSAGE = "ediMessage";
+
public AS2Producer(AS2Endpoint endpoint) {
super(endpoint, AS2PropertiesHelper.getHelper(endpoint.getCamelContext()));
}
+ @Override
+ protected ApiMethod findMethod(Exchange exchange, Map properties) {
+ ApiMethod method = super.findMethod(exchange, properties);
+ if (method != null && !convertEdiMessage(exchange, properties)) {
+ return null;
+ }
+ return method;
+ }
+
+ /**
+ * The client sends text and a stream as they are, and any other EDI message, such as bytes or a file, as its bytes.
+ */
+ private boolean convertEdiMessage(Exchange exchange, Map properties) {
+ Object ediMessage = properties.get(EDI_MESSAGE);
+ if (ediMessage == null || ediMessage instanceof String || ediMessage instanceof InputStream) {
+ return true;
+ }
+ try {
+ properties.put(EDI_MESSAGE,
+ exchange.getContext().getTypeConverter().mandatoryConvertTo(byte[].class, exchange, ediMessage));
+ return true;
+ } catch (Exception e) {
+ exchange.setException(new RuntimeCamelException(
+ String.format("Cannot send an EDI message of type %s: send text, a stream, bytes or a file",
+ ediMessage.getClass().getName()),
+ e));
+ return false;
+ }
+ }
+
@Override
public void interceptResult(Object methodResult, Exchange resultExchange) {
HttpCoreContext context = (HttpCoreContext) methodResult;
resultExchange.setProperty(AS2Constants.AS2_INTERCHANGE, context);
HttpResponse response = context.getResponse();
+ if (response != null && (response.getCode() < 200 || response.getCode() >= 300)) {
+ String reason = response.getReasonPhrase();
+ throw new RuntimeCamelException(
+ "The AS2 partner answered with HTTP status " + response.getCode() + (reason != null ? " " + reason : ""));
+ }
if (response instanceof ClassicHttpResponse classicResponse) {
HttpEntity entity = classicResponse.getEntity();
if (entity instanceof DispositionNotificationMultipartReportEntity || entity instanceof MultipartSignedEntity) {
diff --git a/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ClientSendTest.java b/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ClientSendTest.java
new file mode 100644
index 0000000000000..e2fff84e0f199
--- /dev/null
+++ b/components/camel-as2/camel-as2-component/src/test/java/org/apache/camel/component/as2/AS2ClientSendTest.java
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.as2;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.as2.api.AS2MediaType;
+import org.apache.camel.component.as2.api.AS2MessageStructure;
+import org.apache.camel.component.as2.api.AS2ServerConnection;
+import org.apache.camel.component.as2.api.AS2ServerManager;
+import org.apache.camel.component.as2.api.AS2SignatureAlgorithm;
+import org.apache.camel.component.as2.api.entity.ApplicationEntity;
+import org.apache.camel.component.as2.api.util.HttpMessageUtils;
+import org.apache.camel.component.as2.internal.AS2Constants;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.hc.core5.http.HttpStatus;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * The body types client/send accepts, the default of requestUri, the deprecated ediMessageType option, the
+ * quoted-printable transfer encoding and a partner that answers with an HTTP error (CAMEL-26052).
+ */
+public class AS2ClientSendTest extends AbstractAS2ITSupport {
+
+ private static final String EDI_MESSAGE
+ = "UNB+UNOA:1+005435656:1+006415160:1+060515:1434+00000000000778'UNZ+1+00000000000778'";
+
+ @TempDir
+ static Path inbox;
+
+ private final List received = new CopyOnWriteArrayList<>();
+ private final List receivedPaths = new CopyOnWriteArrayList<>();
+ private AS2ServerConnection serverConnection;
+ private int targetPort;
+
+ @Override
+ public void setupResources() throws Exception {
+ serverConnection = new AS2ServerConnection(
+ "1.1", "AS2ClientSendTest Server", "server.example.com", 0,
+ AS2SignatureAlgorithm.SHA256WITHRSA, null, null, null, "TBD", null, null,
+ null, null, null, "localhost");
+ targetPort = serverConnection.getLocalPort();
+ serverConnection.listen("/fail", (request, response, context) -> response.setCode(HttpStatus.SC_SERVER_ERROR));
+ serverConnection.listen("*", (request, response, context) -> {
+ context.setAttribute(AS2ServerManager.FROM, "mrAS@example.org");
+ context.setAttribute(AS2ServerManager.SUBJECT, "MDN Response");
+ ApplicationEntity entity = HttpMessageUtils.extractEdiPayload(request,
+ new HttpMessageUtils.DecrpytingAndSigningInfo(null, null));
+ receivedPaths.add(request.getPath());
+ received.add(asText(entity.getEdiMessage()));
+ });
+ }
+
+ private String asText(Object ediMessage) {
+ return context.getTypeConverter().convertTo(String.class, ediMessage);
+ }
+
+ @Override
+ public void cleanupResources() {
+ if (serverConnection != null) {
+ serverConnection.close();
+ }
+ }
+
+ @BeforeEach
+ public void clearReceived() {
+ received.clear();
+ receivedPaths.clear();
+ }
+
+ @Test
+ public void sendText() {
+ Object body = requestBodyAndHeaders("direct://SEND", EDI_MESSAGE, as2Headers());
+
+ assertNull(body);
+ assertEquals(List.of(EDI_MESSAGE), received);
+ }
+
+ @Test
+ public void sendBytes() {
+ requestBodyAndHeaders("direct://SEND", EDI_MESSAGE.getBytes(StandardCharsets.US_ASCII), as2Headers());
+
+ assertEquals(List.of(EDI_MESSAGE), received);
+ }
+
+ @Test
+ public void sendFile() throws Exception {
+ File file = Files.writeString(inbox.resolve("message.edi"), EDI_MESSAGE).toFile();
+
+ requestBodyAndHeaders("direct://SEND", file, as2Headers());
+
+ assertEquals(List.of(EDI_MESSAGE), received);
+ }
+
+ @Test
+ public void sendTheFilesOfAFolder() throws Exception {
+ MockEndpoint sent = getMockEndpoint("mock:sent");
+ sent.expectedMessageCount(1);
+
+ Files.writeString(inbox.resolve("order.edi"), EDI_MESSAGE);
+ context.getRouteController().startRoute("files");
+
+ sent.assertIsSatisfied();
+ assertEquals(List.of(EDI_MESSAGE), received);
+ }
+
+ @Test
+ public void sendABodyThatDoesNotConvert() {
+ Map notAnEdiMessage = Map.of("order", "1");
+
+ CamelExecutionException e = assertThrows(CamelExecutionException.class,
+ () -> requestBodyAndHeaders("direct://SEND", notAnEdiMessage, as2Headers()));
+
+ assertTrue(e.getCause().getMessage().contains(notAnEdiMessage.getClass().getName()), e.getCause().getMessage());
+ assertTrue(received.isEmpty());
+ }
+
+ @Test
+ public void requestUriDefaultsToSlash() {
+ Map headers = as2Headers();
+ headers.remove("CamelAs2.requestUri");
+
+ // an as2 component without a component configuration, as with camel run
+ requestBodyAndHeaders("direct://SEND_WITHOUT_COMPONENT_CONFIGURATION", EDI_MESSAGE, headers);
+
+ assertEquals(List.of("/"), receivedPaths);
+ assertEquals(List.of(EDI_MESSAGE), received);
+ }
+
+ @Test
+ public void ediMessageTypeIsUsedAsContentType() {
+ Map headers = as2Headers();
+ headers.remove("CamelAs2.ediMessageContentType");
+
+ requestBodyAndHeaders("direct://SEND_EDI_MESSAGE_TYPE", EDI_MESSAGE, headers);
+
+ assertEquals(List.of(EDI_MESSAGE), received);
+ }
+
+ @Test
+ public void sendQuotedPrintable() {
+ // a long line, an equal sign and characters outside US-ASCII all need encoding
+ String message = EDI_MESSAGE + EDI_MESSAGE + "FTX+AAI+++Prix = 12 €, Grüße'";
+ Map headers = as2Headers();
+ headers.put("CamelAs2.ediMessageTransferEncoding", "quoted-printable");
+ headers.put("CamelAs2.ediMessageCharset", "utf-8");
+
+ requestBodyAndHeaders("direct://SEND", message, headers);
+
+ assertEquals(List.of(message), received);
+ }
+
+ @Test
+ public void partnerErrorFailsTheExchange() {
+ Map headers = as2Headers();
+ headers.put("CamelAs2.requestUri", "/fail");
+
+ CamelExecutionException e = assertThrows(CamelExecutionException.class,
+ () -> requestBodyAndHeaders("direct://SEND", EDI_MESSAGE, headers));
+
+ assertTrue(e.getCause().getMessage().contains("500"), e.getCause().getMessage());
+ // the interchange is still there to look at
+ assertNotNull(e.getExchange().getProperty(AS2Constants.AS2_INTERCHANGE));
+ }
+
+ private Map as2Headers() {
+ Map headers = new HashMap<>();
+ headers.put("CamelAs2.requestUri", "/");
+ headers.put("CamelAs2.subject", "Test Case");
+ headers.put("CamelAs2.from", "mrAS@example.org");
+ headers.put("CamelAs2.as2From", "878051556");
+ headers.put("CamelAs2.as2To", "878051556");
+ headers.put("CamelAs2.as2MessageStructure", AS2MessageStructure.PLAIN);
+ headers.put("CamelAs2.ediMessageContentType", AS2MediaType.APPLICATION_EDIFACT);
+ headers.put("CamelAs2.ediMessageTransferEncoding", "7bit");
+ return headers;
+ }
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext camelContext = super.createCamelContext();
+ camelContext.addComponent("as2-plain", new AS2Component(camelContext));
+ return camelContext;
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ public void configure() {
+ from("direct://SEND")
+ .to("as2://client/send?inBody=ediMessage");
+
+ from("direct://SEND_WITHOUT_COMPONENT_CONFIGURATION")
+ .to("as2-plain://client/send?inBody=ediMessage&targetHostname=localhost&targetPortNumber="
+ + targetPort);
+
+ from("direct://SEND_EDI_MESSAGE_TYPE")
+ .to("as2://client/send?inBody=ediMessage&ediMessageType=application/edifact");
+
+ from("file:" + inbox + "?include=.*\\.edi&noop=true&initialDelay=0&delay=10").routeId("files")
+ .autoStartup(false)
+ .setHeader("CamelAs2.requestUri", constant("/"))
+ .setHeader("CamelAs2.subject", constant("Test Case"))
+ .setHeader("CamelAs2.from", constant("mrAS@example.org"))
+ .setHeader("CamelAs2.as2From", constant("878051556"))
+ .setHeader("CamelAs2.as2To", constant("878051556"))
+ .setHeader("CamelAs2.as2MessageStructure", constant(AS2MessageStructure.PLAIN))
+ .setHeader("CamelAs2.ediMessageContentType", constant(AS2MediaType.APPLICATION_EDIFACT))
+ .to("as2://client/send?inBody=ediMessage")
+ .to("mock:sent");
+ }
+ };
+ }
+
+ @Override
+ protected void customizeConfiguration(AS2Configuration configuration) {
+ configuration.setTargetPortNumber(targetPort);
+ }
+}
diff --git a/components/camel-azure/camel-azure-files/src/generated/resources/META-INF/org/apache/camel/component/file/azure/azure-files.json b/components/camel-azure/camel-azure-files/src/generated/resources/META-INF/org/apache/camel/component/file/azure/azure-files.json
index 231fb1308104c..65fd7e2caa373 100644
--- a/components/camel-azure/camel-azure-files/src/generated/resources/META-INF/org/apache/camel/component/file/azure/azure-files.json
+++ b/components/camel-azure/camel-azure-files/src/generated/resources/META-INF/org/apache/camel/component/file/azure/azure-files.json
@@ -68,7 +68,7 @@
"sendEmptyMessageWhenIdle": { "index": 17, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
"streamDownload": { "index": 18, "kind": "parameter", "displayName": "Stream Download", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.azure.FilesConfiguration", "configurationField": "configuration", "description": "Sets the download method to use when not using a local working directory. If set to true, the remote files are streamed to the route as they are read. When set to false, the remote files are loaded into memory before being sent into the route. If enabling this option then you must set stepwise=false as both cannot be enabled at the same time." },
"bridgeErrorHandler": { "index": 19, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
- "download": { "index": 20, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
+ "download": { "index": 20, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
"exceptionHandler": { "index": 21, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 22, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"inProgressRepository": { "index": 23, "kind": "parameter", "displayName": "In Progress Repository", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.IdempotentRepository", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable in-progress repository org.apache.camel.spi.IdempotentRepository. The in-progress repository is used to account the current in progress files being consumed. By default a memory based repository is used." },
diff --git a/components/camel-dns/src/generated/resources/META-INF/org/apache/camel/component/dns/dns.json b/components/camel-dns/src/generated/resources/META-INF/org/apache/camel/component/dns/dns.json
index 9bd010f45fe95..f6182c1142c32 100644
--- a/components/camel-dns/src/generated/resources/META-INF/org/apache/camel/component/dns/dns.json
+++ b/components/camel-dns/src/generated/resources/META-INF/org/apache/camel/component/dns/dns.json
@@ -29,14 +29,14 @@
},
"headers": {
"CamelDnsClass": { "index": 0, "kind": "header", "displayName": "", "group": "lookup dig", "label": "lookup dig", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The DNS class of the lookup. Should match the values of org.xbill.dns.DClass. Optional.", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_CLASS" },
- "CamelDnsName": { "index": 1, "kind": "header", "displayName": "", "group": "lookup", "label": "lookup", "required": true, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name to lookup", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_NAME" },
+ "CamelDnsName": { "index": 1, "kind": "header", "displayName": "", "group": "lookup dig", "label": "lookup dig", "required": true, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name to lookup", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_NAME" },
"CamelDnsDomain": { "index": 2, "kind": "header", "displayName": "", "group": "ip", "label": "ip", "required": true, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The domain name.", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_DOMAIN" },
"CamelDnsServer": { "index": 3, "kind": "header", "displayName": "", "group": "dig", "label": "dig", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The server in particular for the query. If none is given, the default one specified by the OS will be used. Optional.", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_SERVER" },
- "CamelDnsType": { "index": 4, "kind": "header", "displayName": "", "group": "lookup dig", "label": "lookup dig", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of the lookup. Should match the values of org.xbill.dns.Type. Optional.", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_TYPE" },
- "CamelDnsTerm": { "index": 5, "kind": "header", "displayName": "", "group": "wikipedia", "label": "wikipedia", "required": true, "javaType": "", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The term", "constantName": "org.apache.camel.component.dns.DnsConstants#TERM" }
+ "CamelDnsType": { "index": 4, "kind": "header", "displayName": "", "group": "lookup dig", "label": "lookup dig", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of the lookup. Should match the values of org.xbill.dns.Type. Optional. The dig operation uses A when none or an unknown type is given.", "constantName": "org.apache.camel.component.dns.DnsConstants#DNS_TYPE" },
+ "CamelDnsTerm": { "index": 5, "kind": "header", "displayName": "", "group": "wikipedia", "label": "wikipedia", "required": true, "javaType": "", "deprecated": true, "deprecationNote": "The Wikipedia over DNS service is no longer available", "autowired": false, "secret": false, "description": "The term. Deprecation note: The Wikipedia over DNS service is no longer available", "constantName": "org.apache.camel.component.dns.DnsConstants#TERM" }
},
"properties": {
- "dnsType": { "index": 0, "kind": "path", "displayName": "Dns Type", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.dns.DnsType", "enum": [ "dig", "ip", "lookup", "wikipedia" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of the lookup." },
+ "dnsType": { "index": 0, "kind": "path", "displayName": "Dns Type", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.dns.DnsType", "enum": [ "dig", "ip", "lookup", "wikipedia" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of the lookup. The wikipedia type is deprecated, as the Wikipedia over DNS service it queries is no longer available." },
"lazyStartProducer": { "index": 1, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." }
}
}
diff --git a/components/camel-dns/src/main/docs/dns-component.adoc b/components/camel-dns/src/main/docs/dns-component.adoc
index 63f273f75cf5e..3d51e1e7d14f1 100644
--- a/components/camel-dns/src/main/docs/dns-component.adoc
+++ b/components/camel-dns/src/main/docs/dns-component.adoc
@@ -20,6 +20,7 @@ The component offers the following operations:
* `ip`: to resolve a domain by its ip
* `lookup`: to lookup information about the domain
* `dig`: to run DNS queries
+* `wikipedia` (deprecated): to query the Wikipedia over DNS service, which is no longer available
[NOTE]
====
@@ -177,7 +178,10 @@ YAML::
----
====
-The query must be provided in the header with key `"CamelDnsName"`.
+The query must be provided in the header with key `"CamelDnsName"`; without it the
+exchange fails with an `IllegalArgumentException`. The `"CamelDnsType"` header sets the type of
+the query, such as `MX`, and defaults to `A` when it is not set or not a known type. The
+`"CamelDnsClass"` header sets the DNS class, and defaults to `IN`.
=== Dns Activation Policy
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsComponent.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsComponent.java
index c74542bd46f60..5db0f7be2a52a 100644
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsComponent.java
+++ b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsComponent.java
@@ -57,7 +57,8 @@
*
*
*
- * dns:///wikipedia This endpoint takes one paramter :
+ * dns:///wikipedia (deprecated, the Wikipedia over DNS service is no longer available) This endpoint takes one
+ * parameter :
*
*
CamelDnsTerm: the search term on wikipedia
*
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsConstants.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsConstants.java
index 0c5bce4457a9c..b38b4782757ac 100644
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsConstants.java
+++ b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsConstants.java
@@ -23,13 +23,17 @@ public class DnsConstants {
public static final String OPERATION_DIG = DnsType.dig.name();
public static final String OPERATION_IP = DnsType.ip.name();
public static final String OPERATION_LOOKUP = DnsType.lookup.name();
+ /**
+ * @deprecated the Wikipedia over DNS service is no longer available
+ */
+ @Deprecated
public static final String OPERATION_WIKIPEDIA = DnsType.wikipedia.name();
@Metadata(label = "lookup dig", description = "The DNS class of the lookup. Should match the values of\n" +
"`org.xbill.dns.DClass`. Optional.",
javaType = "String")
public static final String DNS_CLASS = "CamelDnsClass";
- @Metadata(label = "lookup", description = "The name to lookup", javaType = "String", required = true)
+ @Metadata(label = "lookup dig", description = "The name to lookup", javaType = "String", required = true)
public static final String DNS_NAME = "CamelDnsName";
@Metadata(label = "ip", description = "The domain name.", javaType = "String", required = true)
public static final String DNS_DOMAIN = "CamelDnsDomain";
@@ -38,10 +42,15 @@ public class DnsConstants {
javaType = "String")
public static final String DNS_SERVER = "CamelDnsServer";
@Metadata(label = "lookup dig", description = "The type of the lookup. Should match the values of `org.xbill.dns.Type`.\n" +
- "Optional.",
+ "Optional. The dig operation uses A when none or an unknown type is given.",
javaType = "String")
public static final String DNS_TYPE = "CamelDnsType";
- @Metadata(label = "wikipedia", description = "The term", required = true)
+ /**
+ * @deprecated the Wikipedia over DNS service is no longer available
+ */
+ @Deprecated
+ @Metadata(label = "wikipedia", description = "The term", required = true,
+ deprecationNote = "The Wikipedia over DNS service is no longer available")
public static final String TERM = "CamelDnsTerm";
protected DnsConstants() {
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsDigProducer.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsDigProducer.java
index 8659427b2c68c..0395eb90b1c00 100644
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsDigProducer.java
+++ b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsDigProducer.java
@@ -19,6 +19,7 @@
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.StringHelper;
import org.xbill.DNS.DClass;
import org.xbill.DNS.Message;
import org.xbill.DNS.Name;
@@ -42,9 +43,22 @@ public void process(Exchange exchange) throws Exception {
String server = exchange.getIn().getHeader(DnsConstants.DNS_SERVER, String.class);
SimpleResolver resolver = new SimpleResolver(server);
- int type = Type.value(exchange.getIn().getHeader(DnsConstants.DNS_TYPE, String.class));
+ Message query = createQuery(exchange);
+ Message response = resolver.send(query);
+ exchange.getIn().setBody(response);
+ }
+
+ /**
+ * Creates the query from the CamelDnsName, CamelDnsType and CamelDnsClass headers.
+ */
+ Message createQuery(Exchange exchange) throws Exception {
+ String dnsName = exchange.getIn().getHeader(DnsConstants.DNS_NAME, String.class);
+ StringHelper.notEmpty(dnsName, "Header " + DnsConstants.DNS_NAME);
+
+ String typeValue = exchange.getIn().getHeader(DnsConstants.DNS_TYPE, String.class);
+ int type = typeValue != null ? Type.value(typeValue) : -1;
if (type == -1) {
- // default: if unparsable value given, use A.
+ // default: if no or an unparsable value given, use A.
type = Type.A;
}
@@ -59,10 +73,8 @@ public void process(Exchange exchange) throws Exception {
dclass = DClass.IN;
}
- Name name = Name.fromString(exchange.getIn().getHeader(DnsConstants.DNS_NAME, String.class), Name.root);
+ Name name = Name.fromString(dnsName, Name.root);
Record rec = Record.newRecord(name, type, dclass);
- Message query = Message.newQuery(rec);
- Message response = resolver.send(query);
- exchange.getIn().setBody(response);
+ return Message.newQuery(rec);
}
}
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsEndpoint.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsEndpoint.java
index 05b5fba1824aa..160283a4b7739 100644
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsEndpoint.java
+++ b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsEndpoint.java
@@ -42,6 +42,7 @@ public DnsEndpoint(String endpointUri, Component component) {
}
@Override
+ @SuppressWarnings("deprecation")
public Producer createProducer() throws Exception {
if (DnsType.dig == dnsType) {
return new DnsDigProducer(this);
@@ -66,7 +67,8 @@ public DnsType getDnsType() {
}
/**
- * The type of the lookup.
+ * The type of the lookup. The wikipedia type is deprecated, as the Wikipedia over DNS service it queries is no
+ * longer available.
*/
public void setDnsType(DnsType dnsType) {
this.dnsType = dnsType;
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsType.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsType.java
index 0eecac32593a2..a81843070ab7e 100644
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsType.java
+++ b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsType.java
@@ -21,6 +21,10 @@ public enum DnsType {
dig,
ip,
lookup,
+ /**
+ * @deprecated the Wikipedia over DNS service that this type queries is no longer available
+ */
+ @Deprecated
wikipedia
}
diff --git a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsWikipediaProducer.java b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsWikipediaProducer.java
index 2cf0d2bacf386..ed59012419b1e 100644
--- a/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsWikipediaProducer.java
+++ b/components/camel-dns/src/main/java/org/apache/camel/component/dns/DnsWikipediaProducer.java
@@ -35,7 +35,10 @@
* See here for a reference: http://www.commandlinefu.com/commands/view/2829/query-wikipedia-via-console-over-dns
*
* This endpoint accepts the following header: CamelDnsTerm: a simple term to use to query wikipedia.
+ *
+ * @deprecated the Wikipedia over DNS service that this producer queries is no longer available
*/
+@Deprecated
public class DnsWikipediaProducer extends DefaultProducer {
public DnsWikipediaProducer(Endpoint endpoint) {
diff --git a/components/camel-dns/src/test/java/org/apache/camel/component/dns/DnsDigProducerTest.java b/components/camel-dns/src/test/java/org/apache/camel/component/dns/DnsDigProducerTest.java
new file mode 100644
index 0000000000000..e1115ac4de2f9
--- /dev/null
+++ b/components/camel-dns/src/test/java/org/apache/camel/component/dns/DnsDigProducerTest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.dns;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.DefaultExchange;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.xbill.DNS.DClass;
+import org.xbill.DNS.Message;
+import org.xbill.DNS.Record;
+import org.xbill.DNS.Type;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests the query that the dig producer builds from the headers, without sending it.
+ */
+public class DnsDigProducerTest {
+
+ private CamelContext context;
+ private DnsDigProducer producer;
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ context = new DefaultCamelContext();
+ context.start();
+ producer = new DnsDigProducer(context.getEndpoint("dns:dig"));
+ }
+
+ @AfterEach
+ public void tearDown() {
+ context.stop();
+ }
+
+ @Test
+ public void typeAndClassDefaultToAAndIn() throws Exception {
+ Exchange exchange = new DefaultExchange(context);
+ exchange.getIn().setHeader(DnsConstants.DNS_NAME, "camel.apache.org");
+
+ Record question = producer.createQuery(exchange).getQuestion();
+
+ assertEquals("camel.apache.org.", question.getName().toString());
+ assertEquals(Type.A, question.getType());
+ assertEquals(DClass.IN, question.getDClass());
+ }
+
+ @Test
+ public void typeAndClassFromHeaders() throws Exception {
+ Exchange exchange = new DefaultExchange(context);
+ exchange.getIn().setHeader(DnsConstants.DNS_NAME, "camel.apache.org");
+ exchange.getIn().setHeader(DnsConstants.DNS_TYPE, "MX");
+ exchange.getIn().setHeader(DnsConstants.DNS_CLASS, "CH");
+
+ Message query = producer.createQuery(exchange);
+
+ assertEquals(Type.MX, query.getQuestion().getType());
+ assertEquals(DClass.CH, query.getQuestion().getDClass());
+ }
+
+ @Test
+ public void missingNameFails() {
+ Exchange exchange = new DefaultExchange(context);
+ exchange.getIn().setHeader(DnsConstants.DNS_TYPE, "A");
+
+ IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> producer.createQuery(exchange));
+ assertTrue(e.getMessage().contains(DnsConstants.DNS_NAME), e.getMessage());
+ }
+}
diff --git a/components/camel-ftp-common/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java b/components/camel-ftp-common/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java
index 678012a536c2a..cc9195ca19c4d 100644
--- a/components/camel-ftp-common/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java
+++ b/components/camel-ftp-common/src/main/java/org/apache/camel/component/file/remote/RemoteFileEndpoint.java
@@ -62,10 +62,11 @@ public abstract class RemoteFileEndpoint extends GenericFileEndpoint imple
+ "to update file information or not. This can be used to speed up the process if the FTP server has a lot "
+ "of files.")
private boolean fastExistsCheck;
- @UriParam(label = "consumer,advanced", description = "Whether the FTP consumer should download the file. If this "
- + "option is set to false, then the message body will be null, but the consumer will still trigger a Camel "
- + "Exchange that has details about the file such as file name, file size, etc. It's just that the file will "
- + "not be downloaded.")
+ @UriParam(label = "consumer,advanced", defaultValue = "true",
+ description = "Whether the FTP consumer should download the file. If this "
+ + "option is set to false, then the message body will be null, but the consumer will still trigger a Camel "
+ + "Exchange that has details about the file such as file name, file size, etc. It's just that the file will "
+ + "not be downloaded.")
private boolean download = true;
protected RemoteFileEndpoint() {
diff --git a/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/ftp.json b/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/ftp.json
index 8d0a3be6738aa..691f642b84592 100644
--- a/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/ftp.json
+++ b/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/ftp.json
@@ -82,7 +82,7 @@
"sendEmptyMessageWhenIdle": { "index": 23, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
"streamDownload": { "index": 24, "kind": "parameter", "displayName": "Stream Download", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.FtpConfiguration", "configurationField": "configuration", "description": "Sets the download method to use when not using a local working directory. If set to true, the remote files are streamed to the route as they are read. When set to false, the remote files are loaded into memory before being sent into the route. If enabling this option then you must set stepwise=false as both cannot be enabled at the same time." },
"bridgeErrorHandler": { "index": 25, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
- "download": { "index": 26, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
+ "download": { "index": 26, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
"exceptionHandler": { "index": 27, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 28, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"handleDirectoryParserAbsoluteResult": { "index": 29, "kind": "parameter", "displayName": "Handle Directory Parser Absolute Result", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.FtpConfiguration", "configurationField": "configuration", "description": "Allows you to set how the consumer will handle subfolders and files in the path if the directory parser results in with absolute paths. The reason for this is that some FTP servers may return file names with absolute paths, and if so, then the FTP component needs to handle this by converting the returned path into a relative path." },
diff --git a/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/ftps.json b/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/ftps.json
index ba1fade434f6b..1d2a9a2cc22ad 100644
--- a/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/ftps.json
+++ b/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/ftps.json
@@ -83,7 +83,7 @@
"sendEmptyMessageWhenIdle": { "index": 23, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
"streamDownload": { "index": 24, "kind": "parameter", "displayName": "Stream Download", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.FtpsConfiguration", "configurationField": "configuration", "description": "Sets the download method to use when not using a local working directory. If set to true, the remote files are streamed to the route as they are read. When set to false, the remote files are loaded into memory before being sent into the route. If enabling this option then you must set stepwise=false as both cannot be enabled at the same time." },
"bridgeErrorHandler": { "index": 25, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
- "download": { "index": 26, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
+ "download": { "index": 26, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
"exceptionHandler": { "index": 27, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 28, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"handleDirectoryParserAbsoluteResult": { "index": 29, "kind": "parameter", "displayName": "Handle Directory Parser Absolute Result", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.FtpsConfiguration", "configurationField": "configuration", "description": "Allows you to set how the consumer will handle subfolders and files in the path if the directory parser results in with absolute paths. The reason for this is that some FTP servers may return file names with absolute paths, and if so, then the FTP component needs to handle this by converting the returned path into a relative path." },
diff --git a/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/sftp.json b/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/sftp.json
index a0471a76cb2f0..aff91a1d61774 100644
--- a/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/sftp.json
+++ b/components/camel-ftp/src/generated/resources/META-INF/org/apache/camel/component/file/remote/sftp.json
@@ -84,7 +84,7 @@
"sendEmptyMessageWhenIdle": { "index": 20, "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
"streamDownload": { "index": 21, "kind": "parameter", "displayName": "Stream Download", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.SftpConfiguration", "configurationField": "configuration", "description": "Sets the download method to use when not using a local working directory. If set to true, the remote files are streamed to the route as they are read. When set to false, the remote files are loaded into memory before being sent into the route. If enabling this option then you must set stepwise=false as both cannot be enabled at the same time." },
"bridgeErrorHandler": { "index": 22, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
- "download": { "index": 23, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
+ "download": { "index": 23, "kind": "parameter", "displayName": "Download", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the FTP consumer should download the file. If this option is set to false, then the message body will be null, but the consumer will still trigger a Camel Exchange that has details about the file such as file name, file size, etc. It's just that the file will not be downloaded." },
"exceptionHandler": { "index": 24, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 25, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"ignoreFileNotFoundOrPermissionError": { "index": 26, "kind": "parameter", "displayName": "Ignore File Not Found Or Permission Error", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.file.remote.SftpConfiguration", "configurationField": "configuration", "description": "Whether to ignore when (trying to list files in directories or when downloading a file), which does not exist or due to permission error. By default when a directory or file does not exist or insufficient permission, then an exception is thrown. Setting this option to true allows to ignore that instead." },
diff --git a/components/camel-github2/src/generated/resources/META-INF/org/apache/camel/component/github2/github2.json b/components/camel-github2/src/generated/resources/META-INF/org/apache/camel/component/github2/github2.json
index e956fb8a2d632..de592a3659697 100644
--- a/components/camel-github2/src/generated/resources/META-INF/org/apache/camel/component/github2/github2.json
+++ b/components/camel-github2/src/generated/resources/META-INF/org/apache/camel/component/github2/github2.json
@@ -39,9 +39,10 @@
"CamelGitHubIssueTitle": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The title of the issue", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_ISSUE_TITLE" },
"CamelGitHubCommitAuthor": { "index": 4, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The commit author", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_AUTHOR" },
"CamelGitHubCommitCommitter": { "index": 5, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The committer name", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_COMMITTER" },
- "CamelGitHubCommitSha": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The commit sha", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_SHA" },
- "CamelGitHubCommitUrl": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The commit URL", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_URL" },
- "CamelGitHubEventPayload": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "org.kohsuke.github.GHEventPayload", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The event payload", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_EVENT_PAYLOAD" }
+ "CamelGitHubCommitSha": { "index": 6, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The commit sha. The getCommitFile producer reads the file at this commit (a commit id of 40 hexadecimal characters).", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_SHA" },
+ "CamelGitHubFilePath": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The path of the file in the repository for the getCommitFile producer. If not set, the body is the path.", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_FILE_PATH" },
+ "CamelGitHubCommitUrl": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The commit URL", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_COMMIT_URL" },
+ "CamelGitHubEventPayload": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "org.kohsuke.github.GHEventPayload", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The event payload", "constantName": "org.apache.camel.component.github2.GitHub2Constants#GITHUB_EVENT_PAYLOAD" }
},
"properties": {
"type": { "index": 0, "kind": "path", "displayName": "Type", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.github2.GitHub2Type", "enum": [ "CLOSEPULLREQUEST", "PULLREQUESTCOMMENT", "COMMIT", "PULLREQUEST", "TAG", "PULLREQUESTSTATE", "PULLREQUESTFILES", "GETCOMMITFILE", "CREATEISSUE", "EVENT" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "What git operation to execute" },
@@ -56,7 +57,7 @@
"exceptionHandler": { "index": 9, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
"exchangePattern": { "index": 10, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "enum", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
"pollStrategy": { "index": 11, "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel." },
- "encoding": { "index": 12, "kind": "parameter", "displayName": "Encoding", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use the given encoding when getting a git commit file" },
+ "encoding": { "index": 12, "kind": "parameter", "displayName": "Encoding", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The charset of the content of the file for the getCommitFile producer (the default charset of the JVM if not set)" },
"state": { "index": 13, "kind": "parameter", "displayName": "State", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "error", "failure", "pending", "success" ], "deprecated": false, "autowired": false, "secret": false, "description": "To set git commit status state" },
"targetUrl": { "index": 14, "kind": "parameter", "displayName": "Target Url", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To set git commit status target url" },
"lazyStartProducer": { "index": 15, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
diff --git a/components/camel-github2/src/main/docs/github2-component.adoc b/components/camel-github2/src/main/docs/github2-component.adoc
index 446143a8382c9..b2d070e78eac2 100644
--- a/components/camel-github2/src/main/docs/github2-component.adoc
+++ b/components/camel-github2/src/main/docs/github2-component.adoc
@@ -153,9 +153,9 @@ Sets the commit status on a pull request.
|pullRequestFiles |none | - `CamelGitHubPullRequest` (integer) (REQUIRED): Pull request number.
Returns the list of files changed in a pull request.
-|getCommitFile |none | - `CamelGitHubCommitSha` (String) (REQUIRED): Commit SHA.
-- `CamelGitHubFilePath` (String) (REQUIRED): File path.
-Returns the content of a file at a specific commit.
+|getCommitFile |String (the path of the file, if the `CamelGitHubFilePath` header is not set) | - `CamelGitHubCommitSha` (String) (REQUIRED): The commit id (40 hexadecimal characters; a branch or tag name is not accepted).
+- `CamelGitHubFilePath` (String): The path of the file in the repository, such as `docs/README.md`. If not set, the body is the path.
+Returns the content of the file in the tree of that commit, as a `String` (decoded with the `encoding` option, or the default charset of the JVM).
|=======================================================================
=== Example: Consuming commits
diff --git a/components/camel-github2/src/main/java/org/apache/camel/component/github2/GitHub2Constants.java b/components/camel-github2/src/main/java/org/apache/camel/component/github2/GitHub2Constants.java
index 140b48118a239..7560874cd6556 100644
--- a/components/camel-github2/src/main/java/org/apache/camel/component/github2/GitHub2Constants.java
+++ b/components/camel-github2/src/main/java/org/apache/camel/component/github2/GitHub2Constants.java
@@ -35,8 +35,15 @@ public interface GitHub2Constants {
String GITHUB_COMMIT_AUTHOR = "CamelGitHubCommitAuthor";
@Metadata(label = "consumer", description = "The committer name", javaType = "String")
String GITHUB_COMMIT_COMMITTER = "CamelGitHubCommitCommitter";
- @Metadata(label = "consumer", description = "The commit sha", javaType = "String")
+ @Metadata(description = "The commit sha. The getCommitFile producer reads the file at this commit (a commit id of"
+ + " 40 hexadecimal characters).",
+ javaType = "String")
String GITHUB_COMMIT_SHA = "CamelGitHubCommitSha";
+ @Metadata(label = "producer",
+ description = "The path of the file in the repository for the getCommitFile producer. If not set, the body"
+ + " is the path.",
+ javaType = "String")
+ String GITHUB_FILE_PATH = "CamelGitHubFilePath";
@Metadata(label = "consumer", description = "The commit URL", javaType = "String")
String GITHUB_COMMIT_URL = "CamelGitHubCommitUrl";
@Metadata(label = "consumer", description = "The event payload",
diff --git a/components/camel-github2/src/main/java/org/apache/camel/component/github2/GitHub2Endpoint.java b/components/camel-github2/src/main/java/org/apache/camel/component/github2/GitHub2Endpoint.java
index 23d56fc73413f..452eb653a0a1d 100644
--- a/components/camel-github2/src/main/java/org/apache/camel/component/github2/GitHub2Endpoint.java
+++ b/components/camel-github2/src/main/java/org/apache/camel/component/github2/GitHub2Endpoint.java
@@ -252,7 +252,7 @@ public String getEncoding() {
}
/**
- * To use the given encoding when getting a git commit file
+ * The charset of the content of the file for the getCommitFile producer (the default charset of the JVM if not set)
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
diff --git a/components/camel-github2/src/main/java/org/apache/camel/component/github2/producer/GetCommitFileProducer.java b/components/camel-github2/src/main/java/org/apache/camel/component/github2/producer/GetCommitFileProducer.java
index 6de27c410dadb..57563852708af 100644
--- a/components/camel-github2/src/main/java/org/apache/camel/component/github2/producer/GetCommitFileProducer.java
+++ b/components/camel-github2/src/main/java/org/apache/camel/component/github2/producer/GetCommitFileProducer.java
@@ -16,22 +16,28 @@
*/
package org.apache.camel.component.github2.producer;
+import java.io.IOException;
+import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Base64;
+import java.util.regex.Pattern;
import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
import org.apache.camel.component.github2.GitHub2Constants;
import org.apache.camel.component.github2.GitHub2Endpoint;
import org.apache.camel.util.ObjectHelper;
-import org.kohsuke.github.GHBlob;
-import org.kohsuke.github.GHCommit;
+import org.kohsuke.github.GHContent;
/**
- * Producer endpoint that gets a file from a commit. The endpoint requires the "CamelGitHubCommitSha" header,
- * identifying the commit SHA. The message body should contain the file path within the repository.
+ * Producer endpoint that gets the content of a file at a commit. The "CamelGitHubCommitSha" header is the commit id (40
+ * hexadecimal characters), and the "CamelGitHubFilePath" header, or else the message body, is the path of the file in
+ * the repository. The file is read from the tree of that commit, and the body is set to its content as text.
*/
public class GetCommitFileProducer extends AbstractGitHub2Producer {
+ private static final Pattern COMMIT_ID = Pattern.compile("[0-9a-fA-F]{40}");
+
private final String encoding;
public GetCommitFileProducer(GitHub2Endpoint endpoint) {
@@ -43,35 +49,58 @@ public GetCommitFileProducer(GitHub2Endpoint endpoint) {
public void process(Exchange exchange) throws Exception {
String sha = exchange.getIn().getHeader(GitHub2Constants.GITHUB_COMMIT_SHA, String.class);
if (ObjectHelper.isEmpty(sha)) {
- sha = exchange.getIn().getBody(String.class);
+ throw new IllegalArgumentException(
+ "The getCommitFile operation needs the " + GitHub2Constants.GITHUB_COMMIT_SHA
+ + " header with the commit id");
}
-
- if (ObjectHelper.isEmpty(sha)) {
- throw new IllegalArgumentException("Commit SHA must be specified");
+ if (!COMMIT_ID.matcher(sha).matches()) {
+ throw new IllegalArgumentException(
+ "The " + GitHub2Constants.GITHUB_COMMIT_SHA
+ + " header must be a commit id of 40 hexadecimal characters, but was: "
+ + sha);
}
- GHCommit commit = getRepository().getCommit(sha);
- GHBlob blob = null;
+ String path = exchange.getIn().getHeader(GitHub2Constants.GITHUB_FILE_PATH, String.class);
+ if (ObjectHelper.isEmpty(path)) {
+ path = exchange.getIn().getBody(String.class);
+ }
+ if (ObjectHelper.isEmpty(path)) {
+ throw new InvalidPayloadException(
+ exchange, String.class, exchange.getIn(),
+ "set the " + GitHub2Constants.GITHUB_FILE_PATH + " header or the body to the path of the file");
+ }
- // Get the tree and find the file
- // For simplicity, we get the blob SHA from the exchange body if it's a file path
- String filePath = exchange.getIn().getBody(String.class);
- if (filePath != null && !filePath.equals(sha)) {
- // Try to get the file content from the commit
- blob = getRepository().getBlob(sha);
- } else {
- blob = getRepository().getBlob(sha);
+ for (String segment : path.split("/")) {
+ if (".".equals(segment) || "..".equals(segment)) {
+ throw new IllegalArgumentException(
+ "The path of the file must be a path in the tree of the commit, without . or .. segments, but was: "
+ + path);
+ }
}
- String content = null;
- if (blob != null) {
- String encodedContent = blob.getContent();
- Charset charset = encoding != null ? Charset.forName(encoding) : Charset.defaultCharset();
- content = new String(Base64.getDecoder().decode(encodedContent), charset);
+ // the file at its path in the tree of the commit
+ GHContent file = getRepository().getFileContent(path, sha);
+ if (!file.isFile()) {
+ throw new IllegalArgumentException(
+ "The path " + path + " at commit " + sha + " is not a file but a " + file.getType());
}
+ Charset charset = encoding != null ? Charset.forName(encoding) : Charset.defaultCharset();
+ String content = new String(readContent(file), charset);
+
// copy the header of in message to the out message
exchange.getMessage().copyFrom(exchange.getIn());
exchange.getMessage().setBody(content);
}
+
+ private byte[] readContent(GHContent file) throws IOException {
+ if ("base64".equals(file.getEncoding())) {
+ // GitHub wraps the lines of the base64 content
+ return Base64.getMimeDecoder().decode(file.getEncodedContent());
+ }
+ // the contents API gives no content for a file of more than 1 MB: read its blob
+ try (InputStream is = getRepository().getBlob(file.getSha()).read()) {
+ return is.readAllBytes();
+ }
+ }
}
diff --git a/components/camel-github2/src/test/java/org/apache/camel/component/github2/producer/GetCommitFileProducerTest.java b/components/camel-github2/src/test/java/org/apache/camel/component/github2/producer/GetCommitFileProducerTest.java
new file mode 100644
index 0000000000000..30c5145286443
--- /dev/null
+++ b/components/camel-github2/src/test/java/org/apache/camel/component/github2/producer/GetCommitFileProducerTest.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.github2.producer;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Map;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.github2.GitHub2Constants;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.kohsuke.github.GHBlob;
+import org.kohsuke.github.GHContent;
+import org.kohsuke.github.GHRepository;
+import org.kohsuke.github.GitHub;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * The getCommitFile producer reads the file at its path in the tree of the commit.
+ */
+class GetCommitFileProducerTest extends CamelTestSupport {
+
+ private static final String SHA = "0123456789abcdef0123456789abcdef01234567";
+ private static final String PATH = "docs/readme.md";
+ // longer than the 76 characters of a line of MIME base64, so the encoded content has line breaks
+ private static final String TEXT = "The Open Source Integration Framework, with more than 300 connectors: æøå\n";
+
+ private final GHRepository repository = mock(GHRepository.class);
+
+ @BindToRegistry(GitHub2Constants.GITHUB_CLIENT)
+ private final GitHub github = createGitHub();
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:start")
+ .to("github2:getCommitFile?repoOwner=acme&repoName=demo&oauthToken=not-used&encoding=UTF-8");
+ }
+ };
+ }
+
+ @Test
+ void fileFromPathHeader() throws Exception {
+ GHContent content
+ = fileContent("base64", Base64.getMimeEncoder().encodeToString(TEXT.getBytes(StandardCharsets.UTF_8)));
+ when(repository.getFileContent(PATH, SHA)).thenReturn(content);
+
+ String body = template.requestBodyAndHeaders("direct:start", "ignored",
+ Map.of(GitHub2Constants.GITHUB_COMMIT_SHA, SHA, GitHub2Constants.GITHUB_FILE_PATH, PATH), String.class);
+
+ assertEquals(TEXT, body);
+ }
+
+ @Test
+ void fileFromPathInBody() throws Exception {
+ GHContent content
+ = fileContent("base64", Base64.getMimeEncoder().encodeToString(TEXT.getBytes(StandardCharsets.UTF_8)));
+ when(repository.getFileContent(PATH, SHA)).thenReturn(content);
+
+ String body = template.requestBodyAndHeader("direct:start", PATH, GitHub2Constants.GITHUB_COMMIT_SHA, SHA,
+ String.class);
+
+ assertEquals(TEXT, body);
+ }
+
+ @Test
+ void largeFileIsReadAsBlob() throws Exception {
+ // the contents API gives no content for a file of more than 1 MB
+ GHContent content = fileContent("none", "");
+ when(content.getSha()).thenReturn("fedcba9876543210fedcba9876543210fedcba98");
+ when(repository.getFileContent(PATH, SHA)).thenReturn(content);
+ GHBlob blob = mock(GHBlob.class);
+ when(blob.read()).thenReturn(new ByteArrayInputStream(TEXT.getBytes(StandardCharsets.UTF_8)));
+ when(repository.getBlob("fedcba9876543210fedcba9876543210fedcba98")).thenReturn(blob);
+
+ String body = template.requestBodyAndHeader("direct:start", PATH, GitHub2Constants.GITHUB_COMMIT_SHA, SHA,
+ String.class);
+
+ assertEquals(TEXT, body);
+ }
+
+ @Test
+ void shaMustBeCommitId() throws Exception {
+ CamelExecutionException e = assertThrows(CamelExecutionException.class,
+ () -> template.requestBodyAndHeader("direct:start", PATH, GitHub2Constants.GITHUB_COMMIT_SHA, "main"));
+
+ IllegalArgumentException cause = assertInstanceOf(IllegalArgumentException.class, e.getCause());
+ assertTrue(cause.getMessage().contains("40 hexadecimal characters"), cause.getMessage());
+ verify(repository, never()).getFileContent(anyString(), anyString());
+ }
+
+ @Test
+ void pathMustBeInTreeOfCommit() throws Exception {
+ CamelExecutionException e = assertThrows(CamelExecutionException.class,
+ () -> template.requestBodyAndHeader("direct:start", "docs/../readme.md", GitHub2Constants.GITHUB_COMMIT_SHA,
+ SHA));
+
+ IllegalArgumentException cause = assertInstanceOf(IllegalArgumentException.class, e.getCause());
+ assertTrue(cause.getMessage().contains("path in the tree of the commit"), cause.getMessage());
+ verify(repository, never()).getFileContent(anyString(), anyString());
+ }
+
+ @Test
+ void shaHeaderIsRequired() throws Exception {
+ CamelExecutionException e = assertThrows(CamelExecutionException.class,
+ () -> template.requestBody("direct:start", SHA));
+
+ IllegalArgumentException cause = assertInstanceOf(IllegalArgumentException.class, e.getCause());
+ assertTrue(cause.getMessage().contains(GitHub2Constants.GITHUB_COMMIT_SHA), cause.getMessage());
+ verify(repository, never()).getFileContent(anyString(), anyString());
+ }
+
+ private static GHContent fileContent(String encoding, String encodedContent) throws IOException {
+ GHContent content = mock(GHContent.class);
+ when(content.isFile()).thenReturn(true);
+ when(content.getType()).thenReturn("file");
+ when(content.getEncoding()).thenReturn(encoding);
+ when(content.getEncodedContent()).thenReturn(encodedContent);
+ return content;
+ }
+
+ private GitHub createGitHub() {
+ GitHub client = mock(GitHub.class);
+ try {
+ when(client.getRepository("acme/demo")).thenReturn(repository);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ return client;
+ }
+}
diff --git a/components/camel-graphql/src/generated/resources/META-INF/org/apache/camel/component/graphql/graphql.json b/components/camel-graphql/src/generated/resources/META-INF/org/apache/camel/component/graphql/graphql.json
index 73ef1d1a19f3c..c1a6f8bca5d22 100644
--- a/components/camel-graphql/src/generated/resources/META-INF/org/apache/camel/component/graphql/graphql.json
+++ b/components/camel-graphql/src/generated/resources/META-INF/org/apache/camel/component/graphql/graphql.json
@@ -37,10 +37,10 @@
"proxyHost": { "index": 3, "kind": "parameter", "displayName": "Proxy Host", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The proxy host in the format hostname:port." },
"query": { "index": 4, "kind": "parameter", "displayName": "Query", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The query text." },
"queryFile": { "index": 5, "kind": "parameter", "displayName": "Query File", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The query file name located in the classpath (or use file: to load from file system)." },
- "queryHeader": { "index": 6, "kind": "parameter", "displayName": "Query Header", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of a header containing the GraphQL query." },
+ "queryHeader": { "index": 6, "kind": "parameter", "displayName": "Query Header", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of a header containing the GraphQL query. The header is not sent as an HTTP header." },
"throwExceptionOnFailure": { "index": 7, "kind": "parameter", "displayName": "Throw Exception On Failure", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Option to disable throwing the HttpOperationFailedException in case of failed responses from the remote server. This allows you to get all responses regardless of the HTTP status code." },
"variables": { "index": 8, "kind": "parameter", "displayName": "Variables", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.util.json.JsonObject", "deprecated": false, "autowired": false, "secret": false, "description": "The JsonObject instance containing the operation variables." },
- "variablesHeader": { "index": 9, "kind": "parameter", "displayName": "Variables Header", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of a header containing a JsonObject instance containing the operation variables." },
+ "variablesHeader": { "index": 9, "kind": "parameter", "displayName": "Variables Header", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of a header containing the operation variables, as a JsonObject or a Map. The header is not sent as an HTTP header." },
"lazyStartProducer": { "index": 10, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
"httpClient": { "index": 11, "kind": "parameter", "displayName": "Http Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.hc.client5.http.classic.HttpClient", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom pre-existing Http Client. Beware that when using this, then other configurations such as proxy, access token, is not applied and all this must be pre-configured on the Http Client." },
"accessToken": { "index": 12, "kind": "parameter", "displayName": "Access Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "The access token sent in the Authorization header." },
diff --git a/components/camel-graphql/src/main/docs/graphql-component.adoc b/components/camel-graphql/src/main/docs/graphql-component.adoc
index 3ec1d0083d546..f53906a8cfc8a 100644
--- a/components/camel-graphql/src/main/docs/graphql-component.adoc
+++ b/components/camel-graphql/src/main/docs/graphql-component.adoc
@@ -12,7 +12,7 @@
*{component-header}*
-The GraphQL component is a GraphQL client that communicates over HTTP and supports queries and mutations, but not subscriptions. It uses the https://hc.apache.org/httpcomponents-client-4.5.x/index.html[Apache HttpClient] library.
+The GraphQL component is a GraphQL client that communicates over HTTP and supports queries and mutations, but not subscriptions. It sends the requests with the xref:http-component.adoc[HTTP] component, which uses the Apache HttpClient 5 library.
Maven users will need to add the following dependency to their `pom.xml`
for this component:
@@ -37,9 +37,21 @@ include::partial$component-endpoint-headers.adoc[]
== Message Body
-If the `variables` and `variablesHeader` parameters are not set and the IN body is a JsonObject instance, Camel will use it for the operation's variables. If the `query` and `queryFile` parameters are not set and the IN body is a String, Camel will use it as the query. Camel will store the GraphQL response from the external server on the OUT message body.
-All headers from the IN message will be copied to the OUT message, so headers are preserved during routing.
-Additionally, Camel will add the HTTP response headers as well to the OUT message headers.
+If the `query`, `queryFile` and `queryHeader` parameters are not set, the body is the query: it must be text, bytes, a stream or a file, and another body (such as a `Map`) fails with an `InvalidPayloadException`.
+Otherwise, if the `variables` and `variablesHeader` parameters are not set and the body is a `Map` (such as a `JsonObject`), Camel will use it for the operation's variables.
+Camel will store the GraphQL response from the external server on the message body.
+
+== HTTP Headers
+
+The headers of the message are sent as HTTP request headers (filtered by the `headerFilterStrategy`), except:
+
+* the headers named by the `queryHeader` and `variablesHeader` parameters, as the query and the variables are sent in the JSON body of the request;
+* a `Content-Encoding` header, as the request is not compressed.
+
+The producer always sends the request with `Content-Type: application/json`, `Accept: application/json` and `Accept-Encoding: gzip`, whatever the headers of the message are.
+
+After the call, the message keeps its own headers, and Camel adds the HTTP response headers (such as `CamelHttpResponseCode` and the `Content-Type` of the response).
+The headers the producer set for the request (`CamelHttpMethod`, `Accept` and `Accept-Encoding`) do not stay on the message: a header of the message with the same name keeps its value.
== Examples
diff --git a/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlEndpoint.java b/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlEndpoint.java
index 1a0fb874023c1..eb0156708c59a 100644
--- a/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlEndpoint.java
+++ b/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlEndpoint.java
@@ -358,7 +358,8 @@ public String getVariablesHeader() {
}
/**
- * The name of a header containing a JsonObject instance containing the operation variables.
+ * The name of a header containing the operation variables, as a JsonObject or a Map. The header is not sent as an
+ * HTTP header.
*/
public void setVariablesHeader(String variablesHeader) {
this.variablesHeader = variablesHeader;
@@ -369,7 +370,7 @@ public String getQueryHeader() {
}
/**
- * The name of a header containing the GraphQL query.
+ * The name of a header containing the GraphQL query. The header is not sent as an HTTP header.
*/
public void setQueryHeader(String queryHeader) {
this.queryHeader = queryHeader;
diff --git a/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlProducer.java b/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlProducer.java
index 1dff0d91e6880..35ee762d00dfa 100644
--- a/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlProducer.java
+++ b/components/camel-graphql/src/main/java/org/apache/camel/component/graphql/GraphqlProducer.java
@@ -16,11 +16,19 @@
*/
package org.apache.camel.component.graphql;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.file.Path;
+import java.util.Map;
+
import org.apache.camel.AsyncCallback;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.Message;
import org.apache.camel.Producer;
+import org.apache.camel.WrappedFile;
import org.apache.camel.component.http.HttpConstants;
import org.apache.camel.spi.HeaderFilterStrategy;
import org.apache.camel.spi.Registry;
@@ -32,6 +40,9 @@
public class GraphqlProducer extends DefaultAsyncProducer {
+ private static final String ACCEPT = "Accept";
+ private static final String ACCEPT_ENCODING = "Accept-Encoding";
+
private Producer http;
public GraphqlProducer(GraphqlEndpoint endpoint) {
@@ -91,17 +102,28 @@ public GraphqlEndpoint getEndpoint() {
public boolean process(Exchange exchange, AsyncCallback callback) {
Exchange httpExchange = getEndpoint().createExchange();
+ Message request = httpExchange.getIn();
+ MessageHelper.copyHeaders(exchange.getMessage(), request, true);
+ // the query and the variables are sent in the JSON body, not as HTTP headers
+ if (getEndpoint().getQueryHeader() != null) {
+ request.removeHeader(getEndpoint().getQueryHeader());
+ }
+ if (getEndpoint().getVariablesHeader() != null) {
+ request.removeHeader(getEndpoint().getVariablesHeader());
+ }
+ // camel-http would compress the JSON body for a Content-Encoding header of the message
+ request.removeHeader(Exchange.CONTENT_ENCODING);
+ // the headers of the producer win over the headers of the message
// not read by camel-http (skipControlHeaders=true): the httpMethod option of the internal endpoint decides
- httpExchange.getIn().setHeader(HttpConstants.HTTP_METHOD, "post");
- httpExchange.getIn().setHeader("Content-Type", "application/json");
- httpExchange.getIn().setHeader("Accept", "application/json");
- httpExchange.getIn().setHeader("Accept-Encoding", "gzip");
- MessageHelper.copyHeaders(exchange.getMessage(), httpExchange.getIn(), true);
+ request.setHeader(HttpConstants.HTTP_METHOD, "post");
+ request.setHeader(Exchange.CONTENT_TYPE, "application/json");
+ request.setHeader(ACCEPT, "application/json");
+ request.setHeader(ACCEPT_ENCODING, "gzip");
try {
String requestBody
= buildRequestBody(getQuery(exchange), getEndpoint().getOperationName(), getVariables(exchange));
- httpExchange.getIn().setBody(requestBody);
+ request.setBody(requestBody);
try {
http.process(httpExchange);
String data = httpExchange.getMessage().getBody(String.class);
@@ -109,7 +131,17 @@ public boolean process(Exchange exchange, AsyncCallback callback) {
} catch (Exception e) {
exchange.setException(e);
}
- MessageHelper.copyHeaders(httpExchange.getMessage(), exchange.getIn(), true);
+ Message response = httpExchange.getMessage();
+ // the headers the producer set for the request do not stay on the message (a header of the message
+ // with the same name keeps its value); the Content-Type of the response of the server is kept
+ response.removeHeader(HttpConstants.HTTP_METHOD);
+ response.removeHeader(ACCEPT);
+ response.removeHeader(ACCEPT_ENCODING);
+ if (response == request) {
+ // no response message (a failed call): the Content-Type is the one of the request
+ response.removeHeader(Exchange.CONTENT_TYPE);
+ }
+ MessageHelper.copyHeaders(response, exchange.getIn(), true);
} catch (Exception e) {
exchange.setException(e);
}
@@ -133,20 +165,43 @@ private String getQuery(Exchange exchange) throws InvalidPayloadException {
} else if (getEndpoint().getQueryHeader() != null) {
query = exchange.getIn().getHeader(getEndpoint().getQueryHeader(), String.class);
} else {
+ Object body = exchange.getIn().getBody();
+ if (body != null && !isQueryBody(body)) {
+ throw new InvalidPayloadException(
+ exchange, String.class, exchange.getIn(),
+ "the body is the GraphQL query when the query, queryFile and queryHeader options are not set,"
+ + " and must be text, bytes, a stream or a file");
+ }
query = exchange.getIn().getMandatoryBody(String.class);
}
return query;
}
+ private static boolean isQueryBody(Object body) {
+ return body instanceof CharSequence || body instanceof byte[] || body instanceof InputStream
+ || body instanceof Reader || body instanceof File || body instanceof Path
+ || body instanceof WrappedFile;
+ }
+
private JsonObject getVariables(Exchange exchange) {
JsonObject variables = null;
if (getEndpoint().getVariables() != null) {
variables = getEndpoint().getVariables();
} else if (getEndpoint().getVariablesHeader() != null) {
- variables = exchange.getIn().getHeader(getEndpoint().getVariablesHeader(), JsonObject.class);
- } else if (exchange.getIn().getBody() instanceof JsonObject) {
- variables = exchange.getIn().getBody(JsonObject.class);
+ Object value = exchange.getIn().getHeader(getEndpoint().getVariablesHeader());
+ if (value instanceof Map, ?> map) {
+ variables = toJsonObject(map);
+ } else {
+ variables = exchange.getIn().getHeader(getEndpoint().getVariablesHeader(), JsonObject.class);
+ }
+ } else if (exchange.getIn().getBody() instanceof Map, ?> map) {
+ variables = toJsonObject(map);
}
return variables;
}
+
+ @SuppressWarnings("unchecked")
+ private static JsonObject toJsonObject(Map, ?> map) {
+ return map instanceof JsonObject json ? json : new JsonObject((Map) map);
+ }
}
diff --git a/components/camel-graphql/src/test/java/org/apache/camel/component/graphql/GraphqlProducerHeadersTest.java b/components/camel-graphql/src/test/java/org/apache/camel/component/graphql/GraphqlProducerHeadersTest.java
new file mode 100644
index 0000000000000..f831c2c0490ab
--- /dev/null
+++ b/components/camel-graphql/src/test/java/org/apache/camel/component/graphql/GraphqlProducerHeadersTest.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.graphql;
+
+import java.io.IOException;
+import java.util.Map;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.Message;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.graphql.server.GraphqlServer;
+import org.apache.camel.component.http.HttpConstants;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.json.JsonObject;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * The headers of the producer for the HTTP request, and the headers of the message after the call.
+ */
+public class GraphqlProducerHeadersTest extends CamelTestSupport {
+
+ private static final String BOOK_BY_ID_QUERY
+ = "query BookById($id: ID) { bookById(id: $id) { id name author { name } } }";
+
+ private static String booksQueryResult;
+ private static String bookByIdQueryResult;
+ private static GraphqlServer server;
+
+ @BeforeAll
+ public static void setUpBeforeClass() throws Exception {
+ booksQueryResult = readJsonFile("booksQueryResult.json");
+ bookByIdQueryResult = readJsonFile("bookByIdQueryResult.json");
+
+ server = new GraphqlServer();
+ server.start();
+ }
+
+ private static String readJsonFile(String name) throws IOException {
+ ObjectMapper objectMapper = new ObjectMapper();
+ return objectMapper.writeValueAsString(objectMapper.readValue(
+ IOHelper.loadText(ObjectHelper.loadResourceAsStream(name)), Object.class));
+ }
+
+ @AfterAll
+ public static void tearDownAfterClass() {
+ server.shutdown();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:static")
+ .to("graphql://http://localhost:" + server.getPort() + "/graphql?query={books{id name}}");
+ from("direct:headers")
+ .to("graphql://http://localhost:" + server.getPort()
+ + "/graphql?queryHeader=myQuery&variablesHeader=myVariables");
+ from("direct:body")
+ .to("graphql://http://localhost:" + server.getPort() + "/graphql");
+ from("direct:variablesBody")
+ .to("graphql://http://localhost:" + server.getPort()
+ + "/graphql?queryFile=multipleQueries.graphql&operationName=BookById");
+ }
+ };
+ }
+
+ @Test
+ public void requestHeadersOfProducerWinOverMessageHeaders() {
+ Exchange exchange = template.request("direct:static", e -> {
+ e.getIn().setHeader("Content-Type", "text/plain");
+ e.getIn().setHeader("Accept", "text/html");
+ e.getIn().setHeader("Content-Encoding", "gzip");
+ });
+
+ assertNull(exchange.getException());
+ assertEquals(booksQueryResult, exchange.getMessage().getBody(String.class));
+
+ Map sent = server.getLastRequestHeaders();
+ assertEquals("application/json", sent.get("Content-Type"));
+ assertEquals("application/json", sent.get("Accept"));
+ assertFalse(sent.containsKey("Content-Encoding"));
+ }
+
+ @Test
+ public void queryAndVariablesHeadersAreNotSentAsHttpHeaders() {
+ JsonObject variables = new JsonObject();
+ variables.put("id", "book-1");
+
+ Exchange exchange = template.request("direct:headers", e -> {
+ e.getIn().setHeader("myQuery", BOOK_BY_ID_QUERY);
+ e.getIn().setHeader("myVariables", variables);
+ });
+
+ assertNull(exchange.getException());
+ assertEquals(bookByIdQueryResult, exchange.getMessage().getBody(String.class));
+
+ Map sent = server.getLastRequestHeaders();
+ assertFalse(sent.containsKey("myQuery"));
+ assertFalse(sent.containsKey("myVariables"));
+
+ // the headers stay on the message
+ assertEquals(BOOK_BY_ID_QUERY, exchange.getMessage().getHeader("myQuery"));
+ assertNotNull(exchange.getMessage().getHeader("myVariables"));
+ }
+
+ @Test
+ public void requestHeadersOfProducerDoNotStayOnMessage() {
+ Exchange exchange = template.request("direct:static", e -> e.getIn().setBody(""));
+
+ assertNull(exchange.getException());
+ Message message = exchange.getMessage();
+ assertNull(message.getHeader(HttpConstants.HTTP_METHOD));
+ assertNull(message.getHeader("Accept"));
+ assertNull(message.getHeader("Accept-Encoding"));
+ // the Content-Type of the response of the server
+ assertEquals("application/json; charset=UTF-8", message.getHeader("Content-Type"));
+ assertEquals(200, message.getHeader(Exchange.HTTP_RESPONSE_CODE));
+ }
+
+ @Test
+ public void requestHeadersOfMessageAreKeptAfterCall() {
+ Exchange exchange = template.request("direct:static", e -> {
+ e.getIn().setHeader("Accept", "text/html");
+ e.getIn().setHeader("Accept-Encoding", "identity");
+ });
+
+ assertNull(exchange.getException());
+ Message message = exchange.getMessage();
+ assertEquals("text/html", message.getHeader("Accept"));
+ assertEquals("identity", message.getHeader("Accept-Encoding"));
+ assertNull(message.getHeader(HttpConstants.HTTP_METHOD));
+ }
+
+ @Test
+ public void mapBodyIsNotSentAsQuery() {
+ Exchange exchange = template.request("direct:body", e -> e.getIn().setBody(Map.of("id", "1")));
+
+ InvalidPayloadException e = assertInstanceOf(InvalidPayloadException.class, exchange.getException());
+ assertTrue(e.getMessage().contains("queryHeader"), e.getMessage());
+ }
+
+ @Test
+ public void mapBodyIsUsedAsVariables() {
+ Exchange exchange = template.request("direct:variablesBody", e -> e.getIn().setBody(Map.of("id", "book-1")));
+
+ assertNull(exchange.getException());
+ assertEquals(bookByIdQueryResult, exchange.getMessage().getBody(String.class));
+ }
+
+}
diff --git a/components/camel-graphql/src/test/java/org/apache/camel/component/graphql/server/GraphqlServer.java b/components/camel-graphql/src/test/java/org/apache/camel/component/graphql/server/GraphqlServer.java
index 65f71c622482d..ebc0444a4064a 100644
--- a/components/camel-graphql/src/test/java/org/apache/camel/component/graphql/server/GraphqlServer.java
+++ b/components/camel-graphql/src/test/java/org/apache/camel/component/graphql/server/GraphqlServer.java
@@ -18,6 +18,7 @@
import java.io.IOException;
import java.util.Map;
+import java.util.TreeMap;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -40,6 +41,7 @@ public class GraphqlServer {
private final GraphQL graphql;
private final HttpServer server;
+ private volatile Map lastRequestHeaders = Map.of();
public GraphqlServer() {
this.graphql = GraphqlFactory.newGraphQL();
@@ -61,6 +63,13 @@ public int getPort() {
return server.getLocalPort();
}
+ /**
+ * The headers of the last request received by the server, with case-insensitive names.
+ */
+ public Map getLastRequestHeaders() {
+ return lastRequestHeaders;
+ }
+
class GraphqlHandler implements HttpRequestHandler {
private final ObjectMapper objectMapper = new ObjectMapper();
@@ -70,6 +79,12 @@ public void handle(ClassicHttpRequest request, ClassicHttpResponse response, Htt
throws HttpException, IOException {
HttpEntity entity = request.getEntity();
+ Map headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ for (Header header : request.getHeaders()) {
+ headers.put(header.getName(), header.getValue());
+ }
+ lastRequestHeaders = headers;
+
Header h = request.getHeader("kaboom");
if (h != null) {
response.setCode(500);
diff --git a/components/camel-infinispan/camel-infinispan-embedded/src/generated/resources/META-INF/org/apache/camel/component/infinispan/embedded/infinispan-embedded.json b/components/camel-infinispan/camel-infinispan-embedded/src/generated/resources/META-INF/org/apache/camel/component/infinispan/embedded/infinispan-embedded.json
index b884448a4a183..31fe69ab05719 100644
--- a/components/camel-infinispan/camel-infinispan-embedded/src/generated/resources/META-INF/org/apache/camel/component/infinispan/embedded/infinispan-embedded.json
+++ b/components/camel-infinispan/camel-infinispan-embedded/src/generated/resources/META-INF/org/apache/camel/component/infinispan/embedded/infinispan-embedded.json
@@ -38,10 +38,10 @@
"operation": { "index": 11, "kind": "property", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.infinispan.InfinispanOperation", "enum": [ "PUT", "PUTASYNC", "PUTALL", "PUTALLASYNC", "PUTIFABSENT", "PUTIFABSENTASYNC", "GET", "GETORDEFAULT", "CONTAINSKEY", "CONTAINSVALUE", "REMOVE", "REMOVEASYNC", "REPLACE", "REPLACEASYNC", "SIZE", "CLEAR", "CLEARASYNC", "QUERY", "STATS", "COMPUTE", "COMPUTEASYNC" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "PUT", "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The operation to perform" },
"value": { "index": 12, "kind": "property", "displayName": "Value", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Set a specific value for producer operations" },
"autowiredEnabled": { "index": 13, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." },
- "cacheContainer": { "index": 14, "kind": "property", "displayName": "Cache Container", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.manager.EmbeddedCacheManager", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Specifies the cache Container to connect" },
- "cacheContainerConfiguration": { "index": 15, "kind": "property", "displayName": "Cache Container Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.configuration.cache.Configuration", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The CacheContainer configuration. Used if the cacheContainer is not defined." },
+ "cacheContainer": { "index": 14, "kind": "property", "displayName": "Cache Container", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.manager.EmbeddedCacheManager", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Specifies the cache Container to connect Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
+ "cacheContainerConfiguration": { "index": 15, "kind": "property", "displayName": "Cache Container Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.configuration.cache.Configuration", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The CacheContainer configuration. Used if the cacheContainer is not defined. Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
"configurationUri": { "index": 16, "kind": "property", "displayName": "Configuration Uri", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "An implementation specific URI for the CacheManager" },
- "flags": { "index": 17, "kind": "property", "displayName": "Flags", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "A comma separated list of org.infinispan.context.Flag to be applied by default on each cache invocation" },
+ "flags": { "index": 17, "kind": "property", "displayName": "Flags", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "A comma separated list of org.infinispan.context.Flag to be applied by default on each cache invocation Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
"remappingFunction": { "index": 18, "kind": "property", "displayName": "Remapping Function", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.function.BiFunction", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Set a specific remappingFunction to use in a compute operation." },
"resultHeader": { "index": 19, "kind": "property", "displayName": "Result Header", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Store the operation result in a header instead of the message body. By default, resultHeader == null and the query result is stored in the message body, any existing content in the message body is discarded. If resultHeader is set, the value is used as the name of the header to store the query result and the original message body is preserved. This value can be overridden by an in message header named: CamelInfinispanOperationResultHeader" }
},
@@ -85,10 +85,10 @@
"operation": { "index": 12, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.infinispan.InfinispanOperation", "enum": [ "PUT", "PUTASYNC", "PUTALL", "PUTALLASYNC", "PUTIFABSENT", "PUTIFABSENTASYNC", "GET", "GETORDEFAULT", "CONTAINSKEY", "CONTAINSVALUE", "REMOVE", "REMOVEASYNC", "REPLACE", "REPLACEASYNC", "SIZE", "CLEAR", "CLEARASYNC", "QUERY", "STATS", "COMPUTE", "COMPUTEASYNC" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "PUT", "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The operation to perform" },
"value": { "index": 13, "kind": "parameter", "displayName": "Value", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Set a specific value for producer operations" },
"lazyStartProducer": { "index": 14, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
- "cacheContainer": { "index": 15, "kind": "parameter", "displayName": "Cache Container", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.manager.EmbeddedCacheManager", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Specifies the cache Container to connect" },
- "cacheContainerConfiguration": { "index": 16, "kind": "parameter", "displayName": "Cache Container Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.configuration.cache.Configuration", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The CacheContainer configuration. Used if the cacheContainer is not defined." },
+ "cacheContainer": { "index": 15, "kind": "parameter", "displayName": "Cache Container", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.manager.EmbeddedCacheManager", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Specifies the cache Container to connect Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
+ "cacheContainerConfiguration": { "index": 16, "kind": "parameter", "displayName": "Cache Container Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.infinispan.configuration.cache.Configuration", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "The CacheContainer configuration. Used if the cacheContainer is not defined. Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
"configurationUri": { "index": 17, "kind": "parameter", "displayName": "Configuration Uri", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "An implementation specific URI for the CacheManager" },
- "flags": { "index": 18, "kind": "parameter", "displayName": "Flags", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "A comma separated list of org.infinispan.context.Flag to be applied by default on each cache invocation" },
+ "flags": { "index": 18, "kind": "parameter", "displayName": "Flags", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "A comma separated list of org.infinispan.context.Flag to be applied by default on each cache invocation Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an endpoint, this option is not used." },
"remappingFunction": { "index": 19, "kind": "parameter", "displayName": "Remapping Function", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.function.BiFunction", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Set a specific remappingFunction to use in a compute operation." },
"resultHeader": { "index": 20, "kind": "parameter", "displayName": "Result Header", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Store the operation result in a header instead of the message body. By default, resultHeader == null and the query result is stored in the message body, any existing content in the message body is discarded. If resultHeader is set, the value is used as the name of the header to store the query result and the original message body is preserved. This value can be overridden by an in message header named: CamelInfinispanOperationResultHeader" }
}
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 3221910ea61bc..ebf9cd695d851 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
@@ -51,6 +51,21 @@ The consumer allows listening for events from local infinispan cache.
If no cache configuration is provided, embedded cacheContainer is created directly in the component.
+=== Options read on the component only
+
+All the endpoints of the component share one cache manager, which the component creates when it starts. So the
+options that configure the cache manager are read on the component only: `configurationUri`, `cacheContainer`,
+`cacheContainerConfiguration` and `flags`. Set on an endpoint, these options are not used. Configure them on the
+component instead, for example in `application.properties`:
+
+[source,properties]
+----
+camel.component.infinispan-embedded.configuration-uri = file:/etc/infinispan/infinispan.xml
+----
+
+The `configurationUri` is read with the resource loader of Camel, so it can be a name on the class path, a
+`classpath:` or `file:` uri, or an absolute path, and it can use property placeholders.
+
// component options: START
include::partial$component-configure-options.adoc[]
include::partial$component-endpoint-options.adoc[]
@@ -244,11 +259,11 @@ from("infinispan-embedded:source")
from("direct:start")
.setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUT) // <1>
.setHeader(InfinispanConstants.KEY).constant("123") // <2>
- .to("infinispan-embedded:myCacheName?cacheContainer=#cacheContainer"); // <3>
+ .to("infinispan-embedded:myCacheName"); // <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`
+<3> Put an element to the cache named `myCacheName` of the cache manager of the component
--
+
It is possible to configure the lifetime and/or the idle time before the entry expires and gets evicted from the cache, as example:
@@ -281,7 +296,7 @@ from("direct:start")
return qf.from(User.class).having("name").like("%abc%").build();
}
})
- .to("infinispan-embedded:myCacheName?cacheContainer=#cacheManager") ;
+ .to("infinispan-embedded:myCacheName");
----
+
@@ -293,7 +308,7 @@ Java::
+
[source,java]
----
-from("infinispan-embedded:myCacheName?cacheContainer=#cacheManager&customListener=#myCustomListener")
+from("infinispan-embedded:myCacheName?customListener=#myCustomListener")
.to("mock:result");
----
@@ -302,7 +317,7 @@ XML::
[source,xml]
----
-
+
----
@@ -315,7 +330,6 @@ YAML::
from:
uri: infinispan-embedded:myCacheName
parameters:
- cacheContainer: "#cacheManager"
customListener: "#myCustomListener"
steps:
- to:
@@ -366,7 +380,7 @@ XML::
-
+
@@ -429,7 +443,7 @@ XML::
-
+
diff --git a/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedComponent.java b/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedComponent.java
index 3bc6c54e895c1..74fb73b7e5a1e 100644
--- a/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedComponent.java
+++ b/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedComponent.java
@@ -53,7 +53,8 @@ protected Endpoint createEndpoint(String uri, String remaining, Map
+ * Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an
+ * endpoint, this option is not used.
*/
public EmbeddedCacheManager getCacheContainer() {
return cacheContainer;
@@ -62,6 +65,9 @@ public Configuration getCacheContainerConfiguration() {
/**
* The CacheContainer configuration. Used if the cacheContainer is not defined.
+ *
+ * Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an
+ * endpoint, this option is not used.
*/
public void setCacheContainerConfiguration(Configuration cacheContainerConfiguration) {
this.cacheContainerConfiguration = cacheContainerConfiguration;
@@ -126,6 +132,9 @@ public Flag[] getFlags() {
/**
* A comma separated list of org.infinispan.context.Flag to be applied by default on each cache invocation
+ *
+ * Read on the component only, as the cache manager is shared by all the endpoints of the component: set on an
+ * endpoint, this option is not used.
*/
public void setFlags(String flagsAsString) {
String[] flagsArray = flagsAsString.split(",");
diff --git a/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedManager.java b/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedManager.java
index 6df87f4e5dcbc..b89bae420ea13 100644
--- a/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedManager.java
+++ b/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedManager.java
@@ -16,6 +16,9 @@
*/
package org.apache.camel.component.infinispan.embedded;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
import java.util.Set;
import org.apache.camel.CamelContext;
@@ -23,6 +26,7 @@
import org.apache.camel.component.infinispan.InfinispanConstants;
import org.apache.camel.component.infinispan.InfinispanManager;
import org.apache.camel.component.infinispan.InfinispanUtil;
+import org.apache.camel.support.ResourceHelper;
import org.apache.camel.support.service.ServiceSupport;
import org.apache.camel.util.ObjectHelper;
import org.infinispan.Cache;
@@ -82,8 +86,9 @@ public void doStart() throws Exception {
cacheContainer.defineConfiguration("default", containerConf);
} else {
if (ObjectHelper.isNotEmpty(configuration.getConfigurationUri())) {
- cacheContainer = new DefaultCacheManager(
- InfinispanUtil.openInputStream(camelContext, configuration.getConfigurationUri()));
+ try (InputStream is = openConfiguration(configuration.getConfigurationUri())) {
+ cacheContainer = new DefaultCacheManager(is);
+ }
} else {
ConfigurationBuilderHolder holder = new ConfigurationBuilderHolder();
holder.getGlobalConfigurationBuilder().defaultCacheName("default");
@@ -96,6 +101,22 @@ public void doStart() throws Exception {
}
}
+ private InputStream openConfiguration(String uri) throws Exception {
+ if (camelContext != null) {
+ uri = camelContext.resolvePropertyPlaceholders(uri);
+ if (!ResourceHelper.hasScheme(uri) && new File(uri).isAbsolute()) {
+ // an absolute path is a file, not a name on the class path
+ uri = "file:" + uri;
+ }
+ return ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, uri);
+ }
+ InputStream is = InfinispanUtil.openInputStream(null, uri);
+ if (is == null) {
+ throw new FileNotFoundException("Cannot find the configurationUri " + uri + " on the class path");
+ }
+ return is;
+ }
+
@Override
public void doStop() throws Exception {
if (isManagedCacheContainer) {
diff --git a/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/cluster/InfinispanEmbeddedClusterView.java b/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/cluster/InfinispanEmbeddedClusterView.java
index fe6cd0b47352f..a0db91d60c352 100644
--- a/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/cluster/InfinispanEmbeddedClusterView.java
+++ b/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/cluster/InfinispanEmbeddedClusterView.java
@@ -68,6 +68,7 @@ protected InfinispanEmbeddedClusterView(
public void doStart() throws Exception {
super.doStart();
+ manager.setCamelContext(getCamelContext());
ServiceHelper.startService(manager);
this.cache = manager.getCache(getNamespace(), Cache.class);
diff --git a/components/camel-infinispan/camel-infinispan-embedded/src/test/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedComponentConfigurationUriTest.java b/components/camel-infinispan/camel-infinispan-embedded/src/test/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedComponentConfigurationUriTest.java
new file mode 100644
index 0000000000000..0b6cc116fbc91
--- /dev/null
+++ b/components/camel-infinispan/camel-infinispan-embedded/src/test/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedComponentConfigurationUriTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.infinispan.embedded;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * The configurationUri of the component is read with the resource loader of Camel.
+ */
+public class InfinispanEmbeddedComponentConfigurationUriTest {
+
+ private static final String CONFIG
+ = "org/apache/camel/component/infinispan/spring/SpringInfinispanEmbeddedIdempotentRepositoryConfiguration.xml";
+
+ @TempDir
+ Path tempDir;
+
+ private Path configFile;
+
+ @BeforeEach
+ void copyConfig() throws Exception {
+ configFile = tempDir.resolve("infinispan.xml");
+ try (InputStream is = getClass().getClassLoader().getResourceAsStream(CONFIG)) {
+ Files.copy(is, configFile, StandardCopyOption.REPLACE_EXISTING);
+ }
+ }
+
+ @Test
+ public void testClasspathName() throws Exception {
+ assertConfigurationLoaded(CONFIG);
+ }
+
+ @Test
+ public void testClasspathScheme() throws Exception {
+ assertConfigurationLoaded("classpath:" + CONFIG);
+ }
+
+ @Test
+ public void testFileScheme() throws Exception {
+ assertConfigurationLoaded("file:" + configFile.toAbsolutePath());
+ }
+
+ @Test
+ public void testAbsolutePath() throws Exception {
+ assertConfigurationLoaded(configFile.toAbsolutePath().toString());
+ }
+
+ @Test
+ public void testPlaceholder() throws Exception {
+ assertConfigurationLoaded("{{infinispan.config}}");
+ }
+
+ private void assertConfigurationLoaded(String configurationUri) throws Exception {
+ try (CamelContext context = new DefaultCamelContext()) {
+ context.getPropertiesComponent().addInitialProperty("infinispan.config", "file:" + configFile.toAbsolutePath());
+
+ InfinispanEmbeddedComponent component = new InfinispanEmbeddedComponent();
+ component.getConfiguration().setConfigurationUri(configurationUri);
+ context.addComponent(InfinispanEmbeddedComponent.SCHEME, component);
+ context.start();
+
+ // the cache idempotent is only defined in the configuration file
+ assertNotNull(component.getManager().getCacheContainer().getCacheConfiguration("idempotent"),
+ "The configuration " + configurationUri + " is not loaded");
+ }
+ }
+}
diff --git a/components/camel-jdbc/src/generated/resources/META-INF/org/apache/camel/component/jdbc/jdbc.json b/components/camel-jdbc/src/generated/resources/META-INF/org/apache/camel/component/jdbc/jdbc.json
index 5109e64326886..039f9e6ad647f 100644
--- a/components/camel-jdbc/src/generated/resources/META-INF/org/apache/camel/component/jdbc/jdbc.json
+++ b/components/camel-jdbc/src/generated/resources/META-INF/org/apache/camel/component/jdbc/jdbc.json
@@ -31,7 +31,7 @@
},
"headers": {
"CamelJdbcUpdateCount": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "If the query is an UPDATE, query the update count is returned in this OUT header.", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_UPDATE_COUNT" },
- "CamelJdbcRowCount": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "If the query is a SELECT, query the row count is returned in this OUT header.", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_ROW_COUNT" },
+ "CamelJdbcRowCount": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "If the query is a SELECT and the outputType is SelectList, the row count is returned in this OUT header.", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_ROW_COUNT" },
"CamelJdbcColumnNames": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Set", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The column names from the ResultSet as a java.util.Set type.", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_COLUMN_NAMES" },
"CamelJdbcParameters": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A java.util.Map which has the headers to be used if useHeadersAsParameters has been enabled.", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_PARAMETERS" },
"CamelRetrieveGeneratedKeys": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "false", "description": "Set its value to true to retrieve generated keys", "constantName": "org.apache.camel.component.jdbc.JdbcConstants#JDBC_RETRIEVE_GENERATED_KEYS" },
@@ -47,8 +47,8 @@
"parameters": { "index": 4, "kind": "parameter", "displayName": "Parameters", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "statement.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Optional parameters to the java.sql.Statement. For example to set maxRows, fetchSize etc. This is a multi-value option with prefix: statement." },
"readSize": { "index": 5, "kind": "parameter", "displayName": "Read Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The default maximum number of rows that can be read by a polling query. The default value is 0." },
"resetAutoCommit": { "index": 6, "kind": "parameter", "displayName": "Reset Auto Commit", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Camel will set the autoCommit on the JDBC connection to be false, commit the change after executed the statement and reset the autoCommit flag of the connection at the end, if the resetAutoCommit is true. If the JDBC connection doesn't support to reset the autoCommit flag, you can set the resetAutoCommit flag to be false, and Camel will not try to reset the autoCommit flag. When used with XA transactions you most likely need to set it to false so that the transaction manager is in charge of committing this tx." },
- "transacted": { "index": 7, "kind": "parameter", "displayName": "Transacted", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether transactions are in use." },
- "useGetBytesForBlob": { "index": 8, "kind": "parameter", "displayName": "Use Get Bytes For Blob", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "To read BLOB columns as bytes instead of string data. This may be needed for certain databases such as Oracle where you must read BLOB columns as bytes." },
+ "transacted": { "index": 7, "kind": "parameter", "displayName": "Transacted", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": true, "deprecationNote": "Not used: the producer does not read this option", "autowired": false, "secret": false, "defaultValue": false, "description": "Whether transactions are in use. Deprecation note: Not used: the producer does not read this option" },
+ "useGetBytesForBlob": { "index": 8, "kind": "parameter", "displayName": "Use Get Bytes For Blob", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "To read BLOB columns as bytes (a byte) instead of a java.sql.Blob, which cannot be read after the producer has closed the connection. This may be needed for certain databases such as Oracle where you must read BLOB columns as bytes." },
"useHeadersAsParameters": { "index": 9, "kind": "parameter", "displayName": "Use Headers As Parameters", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Set this option to true to use the prepareStatementStrategy with named parameters. This allows to define queries with named placeholders, and use headers with the dynamic values for the query placeholders." },
"useJDBC4ColumnNameAndLabelSemantics": { "index": 10, "kind": "parameter", "displayName": "Use JDBC4 Column Name And Label Semantics", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Sets whether to use JDBC 4 or JDBC 3.0 or older semantic when retrieving column name. JDBC 4.0 uses columnLabel to get the column name where as JDBC 3.0 uses both columnName or columnLabel. Unfortunately JDBC drivers behave differently so you can use this option to work out issues around your JDBC driver if you get problem using this component This option is default true." },
"lazyStartProducer": { "index": 11, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing." },
diff --git a/components/camel-jdbc/src/main/docs/jdbc-component.adoc b/components/camel-jdbc/src/main/docs/jdbc-component.adoc
index 04943660e73f2..d5f4442e8cf16 100644
--- a/components/camel-jdbc/src/main/docs/jdbc-component.adoc
+++ b/components/camel-jdbc/src/main/docs/jdbc-component.adoc
@@ -63,6 +63,18 @@ the result.
*Note:* This component fetches `ResultSetMetaData` to be able to return
the column name as the key in the `Map`.
+With `outputType=SelectList` the header `CamelJdbcRowCount` holds the number of rows of the result.
+
+A `BLOB` or `CLOB` value of a row is a `java.sql.Blob` or `java.sql.Clob`, which can be read only while the connection is
+open, and the producer closes the connection before the route continues (except with `outputType=StreamList`,
+which closes it when the exchange is done). So read such a value inside the producer: set `useGetBytesForBlob=true`
+to get a `BLOB` as a `byte[]`, or convert a `CLOB` to text in the SQL query with a function of the database.
+
+The `SQL` of the message body is mandatory: a message without a body fails with an `InvalidPayloadException`.
+
+The `transacted` option is not used (and deprecated). To take part in a Spring transaction, use the
+xref:spring-jdbc-component.adoc[Spring JDBC Component].
+
=== Generated keys
If you insert data using SQL INSERT, then the RDBMS may support auto
@@ -72,7 +84,8 @@ return the generated keys in headers. +
generated keys will be provided as headers with the keys listed in the
table above.
-Using generated keys does not work together with named parameters.
+The generated keys in the header `CamelGeneratedKeysRows` are a `List` of `Map` objects with the key columns,
+whatever the `outputClass` and `readSize` of the endpoint.
=== Using named parameters
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcConstants.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcConstants.java
index 3dcd18c945114..786c9f1c76065 100644
--- a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcConstants.java
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcConstants.java
@@ -27,8 +27,8 @@ public final class JdbcConstants {
"OUT header.",
javaType = "int")
public static final String JDBC_UPDATE_COUNT = "CamelJdbcUpdateCount";
- @Metadata(label = "producer", description = "If the query is a `SELECT`, query the row count is returned in this OUT\n" +
- "header.",
+ @Metadata(label = "producer", description = "If the query is a `SELECT` and the outputType is `SelectList`, the row\n" +
+ "count is returned in this OUT header.",
javaType = "int")
public static final String JDBC_ROW_COUNT = "CamelJdbcRowCount";
@Metadata(label = "producer", description = "The column names from the ResultSet as a `java.util.Set`\n" +
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java
index 927733d122b8e..c7357ce022bfb 100644
--- a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java
@@ -46,6 +46,8 @@ public class JdbcEndpoint extends DefaultEndpoint {
@UriParam
private int readSize;
@UriParam
+ @Metadata(deprecationNote = "Not used: the producer does not read this option")
+ @Deprecated
private boolean transacted;
@UriParam(defaultValue = "true")
private boolean resetAutoCommit = true;
@@ -112,13 +114,18 @@ public void setReadSize(int readSize) {
this.readSize = readSize;
}
+ @Deprecated
public boolean isTransacted() {
return transacted;
}
/**
* Whether transactions are in use.
+ *
+ * @deprecated not used: the producer does not read this option. The producer takes part in a Spring transaction
+ * through the connection of the data source with the Spring JDBC component.
*/
+ @Deprecated
public void setTransacted(boolean transacted) {
this.transacted = transacted;
}
@@ -258,7 +265,8 @@ public boolean isUseGetBytesForBlob() {
}
/**
- * To read BLOB columns as bytes instead of string data.
+ * To read BLOB columns as bytes (a byte[]) instead of a java.sql.Blob, which cannot be read after the producer has
+ * closed the connection.
*
* This may be needed for certain databases such as Oracle where you must read BLOB columns as bytes.
*/
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcHelper.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcHelper.java
index d6f4d40de0d9b..227b01a7381fe 100644
--- a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcHelper.java
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcHelper.java
@@ -33,6 +33,10 @@ public static Object newBeanInstance(
BeanRowMapper beanRowMapper, Map row)
throws SQLException {
Class> clazz = camelContext.getClassResolver().resolveClass(outputClass);
+ if (clazz == null) {
+ throw new IllegalArgumentException(
+ "Cannot find the outputClass " + outputClass + ": set outputClass to the name of a class on the classpath");
+ }
Object answer = camelContext.getInjector().newInstance(clazz);
Map properties = new LinkedHashMap<>();
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java
index f56bb7588cfe4..f2f8ff5507e8b 100644
--- a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java
@@ -74,7 +74,7 @@ public void process(Exchange exchange) throws Exception {
}
private void processingSqlBySettingAutoCommit(Exchange exchange) throws Exception {
- String sql = exchange.getIn().getBody(String.class);
+ String sql = exchange.getIn().getMandatoryBody(String.class);
Connection conn = null;
boolean autoCommit = false;
boolean shouldCloseResources = true;
@@ -122,7 +122,7 @@ public int getOrder() {
}
private void processingSqlWithoutSettingAutoCommit(Exchange exchange) throws Exception {
- String sql = exchange.getIn().getBody(String.class);
+ String sql = exchange.getIn().getMandatoryBody(String.class);
Connection conn = null;
boolean shouldCloseResources = true;
@@ -372,7 +372,11 @@ protected void setGeneratedKeys(Exchange exchange, Connection conn, ResultSet ge
ResultSetIterator iterator = new ResultSetIterator(
conn, generatedKeys, getEndpoint().isUseJDBC4ColumnNameAndLabelSemantics(),
getEndpoint().isUseGetBytesForBlob());
- List