From b7a779cefec41075bc8d4b4fe5541258d90a4c17 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 13:43:19 +0200 Subject: [PATCH 01/25] CAMEL-24961: camel-catalog - the body a component or data format needs, and the body it leaves after a step A @BodyTypes annotation on the endpoint, data format or language class says the body per side (consumerOut, consumerReply, producerIn, producerOut, marshal, unmarshal and expression in and out): its carriers (null, text, bytes, stream, file, value, map, list, pojo, unchanged, any, unknown), the Java type when it is always the same, the format, the options it depends on, the body for other option values, and a description. The package plugin writes it as a bodyTypes section of the catalog JSON and checks that each side fits the kind and that the options it names exist. A subclass declares its own. The first slice: file, direct, seda, timer, cron, kamelet, http, https, rest-openapi, xslt, sql and the json data format (jackson), read from the code that sets the body and checked against the body types the message history records when routes run. camel_catalog_doc returns them. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../apache/camel/catalog/components/cron.json | 3 + .../camel/catalog/components/direct.json | 5 + .../apache/camel/catalog/components/file.json | 5 + .../apache/camel/catalog/components/http.json | 4 + .../camel/catalog/components/https.json | 4 + .../camel/catalog/components/kamelet.json | 5 + .../catalog/components/rest-openapi.json | 4 + .../apache/camel/catalog/components/seda.json | 5 + .../apache/camel/catalog/components/sql.json | 5 + .../camel/catalog/components/timer.json | 3 + .../apache/camel/catalog/components/xslt.json | 4 + .../camel/catalog/dataformats/jackson.json | 6 + .../org/apache/camel/component/cron/cron.json | 3 + .../camel/component/cron/CronEndpoint.java | 4 + .../apache/camel/component/direct/direct.json | 5 + .../component/direct/DirectEndpoint.java | 6 + .../org/apache/camel/component/file/file.json | 5 + .../camel/component/file/FileEndpoint.java | 14 ++ .../org/apache/camel/component/http/http.json | 4 + .../apache/camel/component/http/https.json | 4 + .../camel/component/http/HttpEndpoint.java | 12 ++ .../camel/component/jackson/jackson.json | 6 + .../component/jackson/JacksonDataFormat.java | 14 ++ .../camel/component/kamelet/kamelet.json | 5 + .../component/kamelet/KameletEndpoint.java | 9 + .../component/rest/openapi/rest-openapi.json | 4 + .../rest/openapi/RestOpenApiEndpoint.java | 10 + .../org/apache/camel/component/seda/seda.json | 5 + .../camel/component/seda/SedaEndpoint.java | 11 + .../org/apache/camel/component/sql/sql.json | 5 + .../camel/component/sql/SqlEndpoint.java | 25 +++ .../apache/camel/component/timer/timer.json | 3 + .../camel/component/timer/TimerEndpoint.java | 4 + .../org/apache/camel/component/xslt/xslt.json | 4 + .../camel/component/xslt/XsltEndpoint.java | 20 ++ .../java/org/apache/camel/spi/BodyType.java | 148 ++++++++++++++ .../java/org/apache/camel/spi/BodyTypes.java | 105 ++++++++++ .../modules/ROOT/pages/camel-catalog.adoc | 69 +++++++ .../ROOT/pages/endpoint-annotations.adoc | 4 + .../jbang/core/commands/ai/CatalogDocs.java | 12 ++ .../core/commands/ai/CatalogDocsTest.java | 19 ++ .../apache/camel/tooling/model/BaseModel.java | 21 ++ .../camel/tooling/model/BodyTypeModel.java | 193 ++++++++++++++++++ .../camel/tooling/model/JsonMapper.java | 86 ++++++++ .../camel/tooling/model/JsonMapperTest.java | 78 +++++++ .../maven/packaging/BodyTypesHelper.java | 185 +++++++++++++++++ .../EndpointSchemaGeneratorMojo.java | 14 ++ .../packaging/PackageDataFormatMojo.java | 2 + .../maven/packaging/PackageLanguageMojo.java | 2 + .../EndpointSchemaGeneratorMojoTest.java | 69 +++++++ .../SomeEndpointExtendingBodyTypes.java | 23 +++ .../SomeEndpointWithBadBodyTypes.java | 66 ++++++ .../endpoint/SomeEndpointWithBodyTypes.java | 33 +++ .../java/org/apache/camel/spi/BodyType.java | 148 ++++++++++++++ .../java/org/apache/camel/spi/BodyTypes.java | 105 ++++++++++ 55 files changed, 1617 insertions(+) create mode 100644 core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java create mode 100644 core/camel-api/src/generated/java/org/apache/camel/spi/BodyTypes.java create mode 100644 tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java create mode 100644 tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java create mode 100644 tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointExtendingBodyTypes.java create mode 100644 tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java create mode 100644 tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBodyTypes.java create mode 100644 tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java create mode 100644 tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyTypes.java diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/cron.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/cron.json index f0a2ca0b9f63d..75c3a691f33d4 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/cron.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/cron.json @@ -28,6 +28,9 @@ "autowiredEnabled": { "index": 1, "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." }, "cronService": { "index": 2, "kind": "property", "displayName": "Cron Service", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of the CamelCronService to use when multiple implementations are provided" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "description": "No body: the message only starts the route" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.cron.api.CamelCronConfiguration", "configurationField": "configuration", "description": "The name of the cron trigger" }, "schedule": { "index": 1, "kind": "parameter", "displayName": "Schedule", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.cron.api.CamelCronConfiguration", "configurationField": "configuration", "description": "A cron expression that will be used to generate events" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/direct.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/direct.json index 25bd03ca6b52c..b79f963ec03b3 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/direct.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/direct.json @@ -31,6 +31,11 @@ "timeout": { "index": 3, "kind": "property", "displayName": "Timeout", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The timeout value to use if block is enabled." }, "autowiredEnabled": { "index": 4, "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." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the caller sent" }, + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unknown" ], "description": "The body the route it calls ends with" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of direct endpoint" }, "bridgeErrorHandler": { "index": 1, "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." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/file.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/file.json index 2d400e50bff03..5458c5f580788 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/file.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/file.json @@ -49,6 +49,11 @@ "CamelFileInitialOffset": { "index": 15, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A long value containing the initial offset.", "constantName": "org.apache.camel.component.file.FileConstants#INITIAL_OFFSET" }, "CamelFileChecksum": { "index": 16, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The checksum of the file written, when checksumAlgorithm is in use", "constantName": "org.apache.camel.component.file.FileConstants#FILE_CHECKSUM" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "file" ], "description": "The file as read: a GenericFile (a java.io.File with preMove), which converts to text, bytes or a stream" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "What converts to an InputStream: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "directoryName": { "index": 0, "kind": "path", "displayName": "Directory Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.io.File", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The starting directory" }, "charset": { "index": 1, "kind": "parameter", "displayName": "Charset", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "This option is used to specify the encoding of the file. You can use this on the consumer, to specify the encodings of the files, which allow Camel to know the charset it should load the file content in case the file content is being accessed. Likewise when writing a file, you can use this option to specify which charset to write the file as well. Do mind that when writing the file Camel may have to read the message content into memory to be able to convert the data into the configured charset, so do not use this if you have big messages." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/http.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/http.json index f6b9d06e87f85..7c35d5b29b3e3 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/http.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/http.json @@ -95,6 +95,10 @@ "CamelHttpCharacterEncoding": { "index": 12, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The character encoding.", "constantName": "org.apache.camel.component.http.HttpConstants#HTTP_CHARACTER_ENCODING" }, "Content-Type": { "index": 13, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The HTTP content type. Is set on both the IN and OUT message to provide a content type, such as text\/html.", "constantName": "org.apache.camel.component.http.HttpConstants#CONTENT_TYPE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "description": "The request body: text, bytes, a stream or a file. A Map or a List fails: marshal it first. Without httpMethod, no body sends a GET and a body a POST" }, + "producerOut": { "carriers": [ "bytes", "stream", "null" ], "description": "The response body: a byte array when its Content-Length is at most responsePayloadStreamingThreshold (8192), otherwise the stream cache (the stream itself with disableStreamCache); null for a response without a body" } + }, "properties": { "httpUri": { "index": 0, "kind": "path", "displayName": "Http Uri", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.net.URI", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The url of the HTTP endpoint to call." }, "disableStreamCache": { "index": 1, "kind": "parameter", "displayName": "Disable Stream Cache", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Determines whether or not the raw input stream is cached or not. The Camel consumer (camel-servlet, camel-jetty etc.) will by default cache the input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persistent store. DefaultHttpBinding will copy the request input stream into a stream cache and put it into message body if this option is false to support reading the stream multiple times. If you use Servlet to bridge\/proxy an endpoint then consider enabling this option to improve performance, in case you do not need to read the message payload multiple times. The producer (camel-http) will by default cache the response body stream. If setting this option to true, then the producers will not cache the response body stream but use the response stream as-is (the stream can only be read once) as the message body." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/https.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/https.json index d17bb0c1e3239..d3f802d744179 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/https.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/https.json @@ -95,6 +95,10 @@ "CamelHttpCharacterEncoding": { "index": 12, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The character encoding.", "constantName": "org.apache.camel.component.http.HttpConstants#HTTP_CHARACTER_ENCODING" }, "Content-Type": { "index": 13, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The HTTP content type. Is set on both the IN and OUT message to provide a content type, such as text\/html.", "constantName": "org.apache.camel.component.http.HttpConstants#CONTENT_TYPE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "description": "The request body: text, bytes, a stream or a file. A Map or a List fails: marshal it first. Without httpMethod, no body sends a GET and a body a POST" }, + "producerOut": { "carriers": [ "bytes", "stream", "null" ], "description": "The response body: a byte array when its Content-Length is at most responsePayloadStreamingThreshold (8192), otherwise the stream cache (the stream itself with disableStreamCache); null for a response without a body" } + }, "properties": { "httpUri": { "index": 0, "kind": "path", "displayName": "Http Uri", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.net.URI", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The url of the HTTP endpoint to call." }, "disableStreamCache": { "index": 1, "kind": "parameter", "displayName": "Disable Stream Cache", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Determines whether or not the raw input stream is cached or not. The Camel consumer (camel-servlet, camel-jetty etc.) will by default cache the input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persistent store. DefaultHttpBinding will copy the request input stream into a stream cache and put it into message body if this option is false to support reading the stream multiple times. If you use Servlet to bridge\/proxy an endpoint then consider enabling this option to improve performance, in case you do not need to read the message payload multiple times. The producer (camel-http) will by default cache the response body stream. If setting this option to true, then the producers will not cache the response body stream but use the response stream as-is (the stream can only be read once) as the message body." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json index 282770899b57b..d8ac7c103040e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/kamelet.json @@ -36,6 +36,11 @@ "noErrorHandler": { "index": 9, "kind": "property", "displayName": "No Error Handler", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether kamelets should use error handling or not. By default, the Kamelet uses the same error handler as from the calling route. This means that if the calling route has error handling that performs retries, or routing to a dead letter channel, then the kamelet route will use this also. This can be turned off by setting this option to true. If off then the kamelet route is not using error handling, and any exception thrown will for source kamelets be logged by the consumer, and the sink\/action kamelets will fail processing." }, "routeTemplateLoaderListener": { "index": 10, "kind": "property", "displayName": "Route Template Loader Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.RouteTemplateLoaderListener", "deprecated": false, "autowired": true, "secret": false, "description": "To plugin a custom listener for when the Kamelet component is loading Kamelets from external resources." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unknown" ], "description": "The body the Kamelet sends, as its data types or its template say. In the template of a Kamelet, kamelet:source gives the body the caller sent" }, + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unknown" ], "description": "The body the template of the Kamelet ends with" } + }, "properties": { "templateId": { "index": 0, "kind": "path", "displayName": "Template Id", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Route Template ID" }, "routeId": { "index": 1, "kind": "path", "displayName": "Route Id", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Route ID. Default value notice: The ID will be auto-generated if not provided" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json index d649162cff1c1..22417ab779dfc 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json @@ -46,6 +46,10 @@ "sslContextParameters": { "index": 19, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" }, "useGlobalSslContextParameters": { "index": 20, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "componentName" ], "description": "The request body of the operation, which the http component sends: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "bytes", "stream", "null" ], "dependsOn": [ "componentName" ], "description": "The response body, as the http component gives it: a byte array or the stream cache; null for a response without a body" } + }, "properties": { "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not given the component tries to load openapi.json resource from the classpath. Note that the host defined on the component and endpoint of this Component should contain the scheme, hostname and optionally the port in the URI syntax (i.e. http:\/\/api.example.com:8080). Overrides component configuration. The OpenApi specification can be loaded from different sources by prefixing with file: classpath: http: https:. Support for https is limited to using the JDK installed UrlHandler, and as such it can be cumbersome to setup TLS\/SSL certificates for https (such as setting a number of javax.net.ssl JVM system properties). How to do that consult the JDK documentation for UrlHandler. Default value notice: By default loads openapi.json file" }, "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/seda.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/seda.json index d3e1df34277b5..268b123f87582 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/seda.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/seda.json @@ -36,6 +36,11 @@ "defaultQueueFactory": { "index": 8, "kind": "property", "displayName": "Default Queue Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.seda.BlockingQueueFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the default queue factory." }, "queueSize": { "index": 9, "kind": "property", "displayName": "Queue Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Sets the default maximum capacity of the SEDA queue (i.e., the number of messages it can hold)." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the producer sent" }, + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "waitForTaskToComplete", "value": "Never", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut), or waitForTaskToComplete=Always, waits for the body the seda route ends with" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of queue" }, "size": { "index": 1, "kind": "parameter", "displayName": "Size", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The maximum capacity of the SEDA queue (i.e., the number of messages it can hold). Will by default use the queueSize set on the SEDA component." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json index c537163715c87..27ec6331908f9 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json @@ -48,6 +48,11 @@ "CamelSqlParameters": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Iterator", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The SQL parameters when using the option useMessageBodyForSql", "constantName": "org.apache.camel.component.sql.SqlConstants#SQL_PARAMETERS" }, "CamelSqlDataSource": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "javax.sql.DataSource", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To use a specific DataSource to operate on another database than the pre configured DataSource on the component", "constantName": "org.apache.camel.component.sql.SqlConstants#SQL_DATA_SOURCE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "map" ], "javaType": "java.util.Map", "dependsOn": [ "outputClass", "outputHeader" ], "byOption": [ { "option": "useIterator", "value": "false", "carriers": [ "list" ] }, { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "A row of the query: a Map of the column names and their values" }, + "producerIn": { "carriers": [ "any" ], "description": "The parameters of the query: a Map for the named ones, a List or an array for the # ones; the query itself with useMessageBodyForSql" }, + "producerOut": { "carriers": [ "list", "unchanged" ], "dependsOn": [ "outputClass", "outputHeader", "noop" ], "byOption": [ { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value", "null" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "The rows of a select: a List of Maps of the column names and their values. A query that is not a select leaves the body unchanged, with the count in the CamelSqlUpdateCount header" } + }, "properties": { "query": { "index": 0, "kind": "path", "displayName": "Query", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "largeInput": true, "inputLanguage": "sql", "description": "Sets the SQL query to perform. You can externalize the query by using file: or classpath: as prefix and specify the location of the file." }, "allowNamedParameters": { "index": 1, "kind": "parameter", "displayName": "Allow Named Parameters", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow using named parameters in the queries." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/timer.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/timer.json index fef8e3d02c437..338cb6f43820c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/timer.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/timer.json @@ -33,6 +33,9 @@ "CamelTimerFiredTime": { "index": 0, "kind": "header", "displayName": "", "group": "consumer", "label": "", "required": false, "javaType": "Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The fired time", "constantName": "org.apache.camel.component.timer.TimerConstants#HEADER_FIRED_TIME" }, "CamelMessageTimestamp": { "index": 1, "kind": "header", "displayName": "", "group": "consumer", "label": "", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The timestamp of the message", "constantName": "org.apache.camel.component.timer.TimerConstants#HEADER_MESSAGE_TIMESTAMP" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "description": "No body: the message only starts the route" } + }, "properties": { "timerName": { "index": 0, "kind": "path", "displayName": "Timer Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the timer" }, "delay": { "index": 1, "kind": "parameter", "displayName": "Delay", "group": "consumer", "label": "", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "The number of milliseconds to wait before the first event is generated. Should not be used in conjunction with the time option. The default value is 1000." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt.json index 0b2ffa8645429..7c6a1d43795b0 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt.json @@ -39,6 +39,10 @@ "CamelXsltStylesheet": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" }, "CamelXsltFileName": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The XSLT file name", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], "byOption": [ { "option": "failOnNullBody", "value": "false", "carriers": [ "null", "text", "bytes", "stream", "file", "pojo" ] } ], "description": "The XML to transform: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source. A Map, a List or no body fails" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultHandlerFactory" ], "byOption": [ { "option": "output", "value": "bytes", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "output", "value": "DOM", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document" }, { "option": "output", "value": "file", "carriers": [ "file" ], "javaType": "java.io.File" } ], "description": "The result of the transformation" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Path to the template. The following is supported by the default URIResolver. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod" }, "allowTemplateFromHeader": { "index": 1, "kind": "parameter", "displayName": "Allow Template From Header", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential security vulnerability if the header is coming from a malicious user, so use this with care." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jackson.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jackson.json index 60f4d41e2401d..36de62e80cf39 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jackson.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jackson.json @@ -15,6 +15,12 @@ "modelName": "json", "modelJavaType": "org.apache.camel.model.dataformat.JsonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as JSON. Text, bytes or a stream that is JSON already is written as it is" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) for a JSON object, a List (ArrayList) for an array; an object of the class unmarshalType names" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "objectMapper": { "index": 1, "kind": "attribute", "displayName": "Object Mapper", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing ObjectMapper with the given id when using Jackson." }, diff --git a/components/camel-cron/src/generated/resources/META-INF/org/apache/camel/component/cron/cron.json b/components/camel-cron/src/generated/resources/META-INF/org/apache/camel/component/cron/cron.json index f0a2ca0b9f63d..75c3a691f33d4 100644 --- a/components/camel-cron/src/generated/resources/META-INF/org/apache/camel/component/cron/cron.json +++ b/components/camel-cron/src/generated/resources/META-INF/org/apache/camel/component/cron/cron.json @@ -28,6 +28,9 @@ "autowiredEnabled": { "index": 1, "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." }, "cronService": { "index": 2, "kind": "property", "displayName": "Cron Service", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of the CamelCronService to use when multiple implementations are provided" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "description": "No body: the message only starts the route" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.cron.api.CamelCronConfiguration", "configurationField": "configuration", "description": "The name of the cron trigger" }, "schedule": { "index": 1, "kind": "parameter", "displayName": "Schedule", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.cron.api.CamelCronConfiguration", "configurationField": "configuration", "description": "A cron expression that will be used to generate events" }, diff --git a/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronEndpoint.java b/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronEndpoint.java index b67ea6348f813..716fab485903a 100644 --- a/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronEndpoint.java +++ b/components/camel-cron/src/main/java/org/apache/camel/component/cron/CronEndpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.component.cron.api.CamelCronConfiguration; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.support.DefaultEndpoint; @@ -34,6 +37,7 @@ */ @UriEndpoint(firstVersion = "3.1.0", scheme = "cron", title = "Cron", syntax = "cron:name", consumerOnly = true, remote = false, category = { Category.SCHEDULING }) +@BodyTypes(consumerOut = @BodyType(value = Carrier.NULL, description = "No body: the message only starts the route")) public class CronEndpoint extends DefaultEndpoint implements DelegateEndpoint { private Endpoint delegate; diff --git a/components/camel-direct/src/generated/resources/META-INF/org/apache/camel/component/direct/direct.json b/components/camel-direct/src/generated/resources/META-INF/org/apache/camel/component/direct/direct.json index 25bd03ca6b52c..b79f963ec03b3 100644 --- a/components/camel-direct/src/generated/resources/META-INF/org/apache/camel/component/direct/direct.json +++ b/components/camel-direct/src/generated/resources/META-INF/org/apache/camel/component/direct/direct.json @@ -31,6 +31,11 @@ "timeout": { "index": 3, "kind": "property", "displayName": "Timeout", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "description": "The timeout value to use if block is enabled." }, "autowiredEnabled": { "index": 4, "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." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the caller sent" }, + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unknown" ], "description": "The body the route it calls ends with" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of direct endpoint" }, "bridgeErrorHandler": { "index": 1, "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." }, diff --git a/components/camel-direct/src/main/java/org/apache/camel/component/direct/DirectEndpoint.java b/components/camel-direct/src/main/java/org/apache/camel/component/direct/DirectEndpoint.java index 1452087ad592a..d40853506ee56 100644 --- a/components/camel-direct/src/main/java/org/apache/camel/component/direct/DirectEndpoint.java +++ b/components/camel-direct/src/main/java/org/apache/camel/component/direct/DirectEndpoint.java @@ -20,6 +20,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -34,6 +37,9 @@ */ @UriEndpoint(firstVersion = "1.0.0", scheme = "direct", title = "Direct", syntax = "direct:name", remote = false, internal = true, category = { Category.CORE, Category.MESSAGING }) +@BodyTypes(consumerOut = @BodyType(value = Carrier.UNCHANGED, description = "The body the caller sent"), + producerIn = @BodyType(Carrier.ANY), + producerOut = @BodyType(value = Carrier.UNKNOWN, description = "The body the route it calls ends with")) public class DirectEndpoint extends DefaultEndpoint { private final DirectComponent component; diff --git a/components/camel-file/src/generated/resources/META-INF/org/apache/camel/component/file/file.json b/components/camel-file/src/generated/resources/META-INF/org/apache/camel/component/file/file.json index 2d400e50bff03..5458c5f580788 100644 --- a/components/camel-file/src/generated/resources/META-INF/org/apache/camel/component/file/file.json +++ b/components/camel-file/src/generated/resources/META-INF/org/apache/camel/component/file/file.json @@ -49,6 +49,11 @@ "CamelFileInitialOffset": { "index": 15, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A long value containing the initial offset.", "constantName": "org.apache.camel.component.file.FileConstants#INITIAL_OFFSET" }, "CamelFileChecksum": { "index": 16, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The checksum of the file written, when checksumAlgorithm is in use", "constantName": "org.apache.camel.component.file.FileConstants#FILE_CHECKSUM" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "file" ], "description": "The file as read: a GenericFile (a java.io.File with preMove), which converts to text, bytes or a stream" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "What converts to an InputStream: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "directoryName": { "index": 0, "kind": "path", "displayName": "Directory Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.io.File", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The starting directory" }, "charset": { "index": 1, "kind": "parameter", "displayName": "Charset", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "This option is used to specify the encoding of the file. You can use this on the consumer, to specify the encodings of the files, which allow Camel to know the charset it should load the file content in case the file content is being accessed. Likewise when writing a file, you can use this option to specify which charset to write the file as well. Do mind that when writing the file Camel may have to read the message content into memory to be able to convert the data into the configured charset, so do not use this if you have big messages." }, diff --git a/components/camel-file/src/main/java/org/apache/camel/component/file/FileEndpoint.java b/components/camel-file/src/main/java/org/apache/camel/component/file/FileEndpoint.java index 621e144f76cd6..283e0b32e9e80 100644 --- a/components/camel-file/src/main/java/org/apache/camel/component/file/FileEndpoint.java +++ b/components/camel-file/src/main/java/org/apache/camel/component/file/FileEndpoint.java @@ -31,6 +31,9 @@ import org.apache.camel.Processor; import org.apache.camel.component.file.strategy.FileMoveExistingStrategy; import org.apache.camel.component.file.strategy.FileProcessStrategyFactory; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -46,6 +49,17 @@ */ @UriEndpoint(firstVersion = "1.0.0", scheme = "file", title = "File", syntax = "file:directoryName", category = { Category.FILE, Category.CORE }, headersClass = FileConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, + description = "The file as read: a GenericFile (a java.io.File with preMove), which" + + " converts to text, bytes or a stream"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + byOption = @BodyType.When(option = "allowNullBody", value = "true", + carrier = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE }), + description = "What converts to an InputStream: text, bytes, a stream or a file. A Map or" + + " a List fails: marshal it first"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class FileEndpoint extends GenericFileEndpoint { private static final Logger LOG = LoggerFactory.getLogger(FileEndpoint.class); diff --git a/components/camel-http/src/generated/resources/META-INF/org/apache/camel/component/http/http.json b/components/camel-http/src/generated/resources/META-INF/org/apache/camel/component/http/http.json index f6b9d06e87f85..7c35d5b29b3e3 100644 --- a/components/camel-http/src/generated/resources/META-INF/org/apache/camel/component/http/http.json +++ b/components/camel-http/src/generated/resources/META-INF/org/apache/camel/component/http/http.json @@ -95,6 +95,10 @@ "CamelHttpCharacterEncoding": { "index": 12, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The character encoding.", "constantName": "org.apache.camel.component.http.HttpConstants#HTTP_CHARACTER_ENCODING" }, "Content-Type": { "index": 13, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The HTTP content type. Is set on both the IN and OUT message to provide a content type, such as text\/html.", "constantName": "org.apache.camel.component.http.HttpConstants#CONTENT_TYPE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "description": "The request body: text, bytes, a stream or a file. A Map or a List fails: marshal it first. Without httpMethod, no body sends a GET and a body a POST" }, + "producerOut": { "carriers": [ "bytes", "stream", "null" ], "description": "The response body: a byte array when its Content-Length is at most responsePayloadStreamingThreshold (8192), otherwise the stream cache (the stream itself with disableStreamCache); null for a response without a body" } + }, "properties": { "httpUri": { "index": 0, "kind": "path", "displayName": "Http Uri", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.net.URI", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The url of the HTTP endpoint to call." }, "disableStreamCache": { "index": 1, "kind": "parameter", "displayName": "Disable Stream Cache", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Determines whether or not the raw input stream is cached or not. The Camel consumer (camel-servlet, camel-jetty etc.) will by default cache the input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persistent store. DefaultHttpBinding will copy the request input stream into a stream cache and put it into message body if this option is false to support reading the stream multiple times. If you use Servlet to bridge\/proxy an endpoint then consider enabling this option to improve performance, in case you do not need to read the message payload multiple times. The producer (camel-http) will by default cache the response body stream. If setting this option to true, then the producers will not cache the response body stream but use the response stream as-is (the stream can only be read once) as the message body." }, diff --git a/components/camel-http/src/generated/resources/META-INF/org/apache/camel/component/http/https.json b/components/camel-http/src/generated/resources/META-INF/org/apache/camel/component/http/https.json index d17bb0c1e3239..d3f802d744179 100644 --- a/components/camel-http/src/generated/resources/META-INF/org/apache/camel/component/http/https.json +++ b/components/camel-http/src/generated/resources/META-INF/org/apache/camel/component/http/https.json @@ -95,6 +95,10 @@ "CamelHttpCharacterEncoding": { "index": 12, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The character encoding.", "constantName": "org.apache.camel.component.http.HttpConstants#HTTP_CHARACTER_ENCODING" }, "Content-Type": { "index": 13, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The HTTP content type. Is set on both the IN and OUT message to provide a content type, such as text\/html.", "constantName": "org.apache.camel.component.http.HttpConstants#CONTENT_TYPE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "description": "The request body: text, bytes, a stream or a file. A Map or a List fails: marshal it first. Without httpMethod, no body sends a GET and a body a POST" }, + "producerOut": { "carriers": [ "bytes", "stream", "null" ], "description": "The response body: a byte array when its Content-Length is at most responsePayloadStreamingThreshold (8192), otherwise the stream cache (the stream itself with disableStreamCache); null for a response without a body" } + }, "properties": { "httpUri": { "index": 0, "kind": "path", "displayName": "Http Uri", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.net.URI", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The url of the HTTP endpoint to call." }, "disableStreamCache": { "index": 1, "kind": "parameter", "displayName": "Disable Stream Cache", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Determines whether or not the raw input stream is cached or not. The Camel consumer (camel-servlet, camel-jetty etc.) will by default cache the input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persistent store. DefaultHttpBinding will copy the request input stream into a stream cache and put it into message body if this option is false to support reading the stream multiple times. If you use Servlet to bridge\/proxy an endpoint then consider enabling this option to improve performance, in case you do not need to read the message payload multiple times. The producer (camel-http) will by default cache the response body stream. If setting this option to true, then the producers will not cache the response body stream but use the response stream as-is (the stream can only be read once) as the message body." }, diff --git a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java index f7f3c664db22d..334bf81faaa1a 100644 --- a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java +++ b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpEndpoint.java @@ -35,6 +35,9 @@ import org.apache.camel.api.management.ManagedResource; import org.apache.camel.http.base.cookie.CookieHandler; import org.apache.camel.http.common.HttpCommonEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -74,6 +77,15 @@ "protocol=http" }) @ManagedResource(description = "Managed HttpEndpoint") +@BodyTypes(producerIn = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The request body: text, bytes, a stream or a file. A Map or a List fails:" + + " marshal it first. Without httpMethod, no body sends a GET and a body a" + + " POST"), + producerOut = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.NULL }, + description = "The response body: a byte array when its Content-Length is at most" + + " responsePayloadStreamingThreshold (8192), otherwise the stream cache" + + " (the stream itself with disableStreamCache); null for a response" + + " without a body")) public class HttpEndpoint extends HttpCommonEndpoint implements LineNumberAware { private static final Logger LOG = LoggerFactory.getLogger(HttpEndpoint.class); diff --git a/components/camel-jackson/src/generated/resources/META-INF/org/apache/camel/component/jackson/jackson.json b/components/camel-jackson/src/generated/resources/META-INF/org/apache/camel/component/jackson/jackson.json index 60f4d41e2401d..36de62e80cf39 100644 --- a/components/camel-jackson/src/generated/resources/META-INF/org/apache/camel/component/jackson/jackson.json +++ b/components/camel-jackson/src/generated/resources/META-INF/org/apache/camel/component/jackson/jackson.json @@ -15,6 +15,12 @@ "modelName": "json", "modelJavaType": "org.apache.camel.model.dataformat.JsonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as JSON. Text, bytes or a stream that is JSON already is written as it is" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) for a JSON object, a List (ArrayList) for an array; an object of the class unmarshalType names" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "objectMapper": { "index": 1, "kind": "attribute", "displayName": "Object Mapper", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing ObjectMapper with the given id when using Jackson." }, diff --git a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java index e01f3254ec18b..6519c2d6a2ae0 100644 --- a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java +++ b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java @@ -23,6 +23,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.json.JsonMapper; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.annotations.Dataformat; import org.apache.camel.support.JsonPayloadHelper; @@ -34,6 +37,17 @@ */ @Dataformat("jackson") @Metadata(excludeProperties = "library,permissions,dateFormatPattern") +@BodyTypes(marshalIn = @BodyType(value = Carrier.ANY, + description = "A Map, a List or a POJO to write as JSON. Text, bytes or a stream that is" + + " JSON already is written as it is"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "json", + description = "The JSON in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "json"), + unmarshalOut = @BodyType(value = { Carrier.MAP, Carrier.LIST }, + dependsOn = { "unmarshalType", "collectionType", "allowUnmarshallType" }, + byOption = @BodyType.When(option = "useList", value = "true", carrier = Carrier.LIST), + description = "A Map (LinkedHashMap) for a JSON object, a List (ArrayList) for an array;" + + " an object of the class unmarshalType names")) public class JacksonDataFormat extends AbstractJacksonDataFormat { private static final Logger LOG = LoggerFactory.getLogger(JacksonDataFormat.class); diff --git a/components/camel-kamelet/src/generated/resources/META-INF/org/apache/camel/component/kamelet/kamelet.json b/components/camel-kamelet/src/generated/resources/META-INF/org/apache/camel/component/kamelet/kamelet.json index 282770899b57b..d8ac7c103040e 100644 --- a/components/camel-kamelet/src/generated/resources/META-INF/org/apache/camel/component/kamelet/kamelet.json +++ b/components/camel-kamelet/src/generated/resources/META-INF/org/apache/camel/component/kamelet/kamelet.json @@ -36,6 +36,11 @@ "noErrorHandler": { "index": 9, "kind": "property", "displayName": "No Error Handler", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether kamelets should use error handling or not. By default, the Kamelet uses the same error handler as from the calling route. This means that if the calling route has error handling that performs retries, or routing to a dead letter channel, then the kamelet route will use this also. This can be turned off by setting this option to true. If off then the kamelet route is not using error handling, and any exception thrown will for source kamelets be logged by the consumer, and the sink\/action kamelets will fail processing." }, "routeTemplateLoaderListener": { "index": 10, "kind": "property", "displayName": "Route Template Loader Listener", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.RouteTemplateLoaderListener", "deprecated": false, "autowired": true, "secret": false, "description": "To plugin a custom listener for when the Kamelet component is loading Kamelets from external resources." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unknown" ], "description": "The body the Kamelet sends, as its data types or its template say. In the template of a Kamelet, kamelet:source gives the body the caller sent" }, + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unknown" ], "description": "The body the template of the Kamelet ends with" } + }, "properties": { "templateId": { "index": 0, "kind": "path", "displayName": "Template Id", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Route Template ID" }, "routeId": { "index": 1, "kind": "path", "displayName": "Route Id", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Route ID. Default value notice: The ID will be auto-generated if not provided" }, diff --git a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletEndpoint.java b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletEndpoint.java index 943f6fe5c129c..879ad17ef9caa 100644 --- a/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletEndpoint.java +++ b/components/camel-kamelet/src/main/java/org/apache/camel/component/kamelet/KameletEndpoint.java @@ -26,6 +26,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.PropertyConfigurer; import org.apache.camel.spi.UriEndpoint; @@ -37,6 +40,12 @@ @UriEndpoint(firstVersion = "3.8.0", scheme = "kamelet", syntax = "kamelet:templateId/routeId", title = "Kamelet", lenientProperties = true, category = Category.CORE) +@BodyTypes(consumerOut = @BodyType(value = Carrier.UNKNOWN, + description = "The body the Kamelet sends, as its data types or its template say. In" + + " the template of a Kamelet, kamelet:source gives the body the caller" + + " sent"), + producerIn = @BodyType(Carrier.ANY), + producerOut = @BodyType(value = Carrier.UNKNOWN, description = "The body the template of the Kamelet ends with")) public class KameletEndpoint extends DefaultEndpoint implements AfterPropertiesConfigured { private final String key; private final Map kameletProperties; diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json index d649162cff1c1..22417ab779dfc 100644 --- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json +++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json @@ -46,6 +46,10 @@ "sslContextParameters": { "index": 19, "kind": "property", "displayName": "Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "object", "javaType": "org.apache.camel.support.jsse.SSLContextParameters", "deprecated": false, "autowired": false, "secret": false, "description": "Customize TLS parameters used by the component. If not set defaults to the TLS parameters set in the Camel context" }, "useGlobalSslContextParameters": { "index": 20, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "componentName" ], "description": "The request body of the operation, which the http component sends: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "bytes", "stream", "null" ], "dependsOn": [ "componentName" ], "description": "The response body, as the http component gives it: a byte array or the stream cache; null for a response without a body" } + }, "properties": { "specificationUri": { "index": 0, "kind": "path", "displayName": "Specification Uri", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "openapi.json", "description": "Path to the OpenApi specification file. The scheme, host base path are taken from this specification, but these can be overridden with properties on the component or endpoint level. If not given the component tries to load openapi.json resource from the classpath. Note that the host defined on the component and endpoint of this Component should contain the scheme, hostname and optionally the port in the URI syntax (i.e. http:\/\/api.example.com:8080). Overrides component configuration. The OpenApi specification can be loaded from different sources by prefixing with file: classpath: http: https:. Support for https is limited to using the JDK installed UrlHandler, and as such it can be cumbersome to setup TLS\/SSL certificates for https (such as setting a number of javax.net.ssl JVM system properties). How to do that consult the JDK documentation for UrlHandler. Default value notice: By default loads openapi.json file" }, "operationId": { "index": 1, "kind": "path", "displayName": "Operation Id", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "ID of the operation from the OpenApi specification. This is required when using producer" }, diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java index d4c39cf24d1c4..4f1c00d080713 100644 --- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java +++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java @@ -62,6 +62,9 @@ import org.apache.camel.component.rest.openapi.validator.DefaultRequestValidator; import org.apache.camel.component.rest.openapi.validator.RequestValidator; import org.apache.camel.component.rest.openapi.validator.RestOpenApiOperation; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.CamelInternalProcessorAdvice; import org.apache.camel.spi.InternalProcessor; import org.apache.camel.spi.Metadata; @@ -92,6 +95,13 @@ */ @UriEndpoint(firstVersion = "3.1.0", scheme = "rest-openapi", title = "REST OpenApi", syntax = "rest-openapi:specificationUri#operationId", category = { Category.REST, Category.API }) +@BodyTypes(producerIn = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + dependsOn = "componentName", + description = "The request body of the operation, which the http component sends: text," + + " bytes, a stream or a file. A Map or a List fails: marshal it first"), + producerOut = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.NULL }, dependsOn = "componentName", + description = "The response body, as the http component gives it: a byte array or the" + + " stream cache; null for a response without a body")) public final class RestOpenApiEndpoint extends DefaultEndpoint { private static final Logger LOG = LoggerFactory.getLogger(RestOpenApiEndpoint.class); diff --git a/components/camel-seda/src/generated/resources/META-INF/org/apache/camel/component/seda/seda.json b/components/camel-seda/src/generated/resources/META-INF/org/apache/camel/component/seda/seda.json index d3e1df34277b5..268b123f87582 100644 --- a/components/camel-seda/src/generated/resources/META-INF/org/apache/camel/component/seda/seda.json +++ b/components/camel-seda/src/generated/resources/META-INF/org/apache/camel/component/seda/seda.json @@ -36,6 +36,11 @@ "defaultQueueFactory": { "index": 8, "kind": "property", "displayName": "Default Queue Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.seda.BlockingQueueFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the default queue factory." }, "queueSize": { "index": 9, "kind": "property", "displayName": "Queue Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Sets the default maximum capacity of the SEDA queue (i.e., the number of messages it can hold)." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the producer sent" }, + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "waitForTaskToComplete", "value": "Never", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut), or waitForTaskToComplete=Always, waits for the body the seda route ends with" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of queue" }, "size": { "index": 1, "kind": "parameter", "displayName": "Size", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The maximum capacity of the SEDA queue (i.e., the number of messages it can hold). Will by default use the queueSize set on the SEDA component." }, diff --git a/components/camel-seda/src/main/java/org/apache/camel/component/seda/SedaEndpoint.java b/components/camel-seda/src/main/java/org/apache/camel/component/seda/SedaEndpoint.java index 0da80bde3d089..7cedba92ad122 100644 --- a/components/camel-seda/src/main/java/org/apache/camel/component/seda/SedaEndpoint.java +++ b/components/camel-seda/src/main/java/org/apache/camel/component/seda/SedaEndpoint.java @@ -40,6 +40,9 @@ import org.apache.camel.api.management.ManagedAttribute; import org.apache.camel.api.management.ManagedOperation; import org.apache.camel.api.management.ManagedResource; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.BrowsableEndpoint; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -59,6 +62,14 @@ @ManagedResource(description = "Managed SedaEndpoint") @UriEndpoint(firstVersion = "1.1.0", scheme = "seda", title = "SEDA", syntax = "seda:name", remote = false, internal = true, category = { Category.CORE, Category.MESSAGING }) +@BodyTypes(consumerOut = @BodyType(value = Carrier.UNCHANGED, description = "The body the producer sent"), + producerIn = @BodyType(Carrier.ANY), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = @BodyType.When(option = "waitForTaskToComplete", value = "Never", + carrier = Carrier.UNCHANGED), + description = "Unchanged for a message that expects no reply (InOnly). A message that" + + " expects one (InOut), or waitForTaskToComplete=Always, waits for the" + + " body the seda route ends with")) public class SedaEndpoint extends DefaultEndpoint implements AsyncEndpoint, BrowsableEndpoint, MultipleConsumersSupport { private static final Logger LOG = LoggerFactory.getLogger(SedaEndpoint.class); diff --git a/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json b/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json index c537163715c87..27ec6331908f9 100644 --- a/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json +++ b/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json @@ -48,6 +48,11 @@ "CamelSqlParameters": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Iterator", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The SQL parameters when using the option useMessageBodyForSql", "constantName": "org.apache.camel.component.sql.SqlConstants#SQL_PARAMETERS" }, "CamelSqlDataSource": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "javax.sql.DataSource", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To use a specific DataSource to operate on another database than the pre configured DataSource on the component", "constantName": "org.apache.camel.component.sql.SqlConstants#SQL_DATA_SOURCE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "map" ], "javaType": "java.util.Map", "dependsOn": [ "outputClass", "outputHeader" ], "byOption": [ { "option": "useIterator", "value": "false", "carriers": [ "list" ] }, { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "A row of the query: a Map of the column names and their values" }, + "producerIn": { "carriers": [ "any" ], "description": "The parameters of the query: a Map for the named ones, a List or an array for the # ones; the query itself with useMessageBodyForSql" }, + "producerOut": { "carriers": [ "list", "unchanged" ], "dependsOn": [ "outputClass", "outputHeader", "noop" ], "byOption": [ { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value", "null" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "The rows of a select: a List of Maps of the column names and their values. A query that is not a select leaves the body unchanged, with the count in the CamelSqlUpdateCount header" } + }, "properties": { "query": { "index": 0, "kind": "path", "displayName": "Query", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "largeInput": true, "inputLanguage": "sql", "description": "Sets the SQL query to perform. You can externalize the query by using file: or classpath: as prefix and specify the location of the file." }, "allowNamedParameters": { "index": 1, "kind": "parameter", "displayName": "Allow Named Parameters", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow using named parameters in the queries." }, diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java index fd6affe1e4d1a..ece6dd8ce371c 100644 --- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java +++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java @@ -21,6 +21,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -32,6 +35,28 @@ */ @UriEndpoint(firstVersion = "1.4.0", scheme = "sql", title = "SQL", syntax = "sql:query", category = { Category.DATABASE }, headersClass = SqlConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.MAP, javaType = "java.util.Map", + dependsOn = { "outputClass", "outputHeader" }, + byOption = { + @BodyType.When(option = "useIterator", value = "false", carrier = Carrier.LIST), + @BodyType.When(option = "outputType", value = "SelectOne", + carrier = { Carrier.MAP, Carrier.VALUE }), + @BodyType.When(option = "outputType", value = "StreamList", carrier = Carrier.LIST, + javaType = "java.util.Iterator") }, + description = "A row of the query: a Map of the column names and their values"), + producerIn = @BodyType(value = Carrier.ANY, + description = "The parameters of the query: a Map for the named ones, a List or an array" + + " for the # ones; the query itself with useMessageBodyForSql"), + producerOut = @BodyType(value = { Carrier.LIST, Carrier.UNCHANGED }, + dependsOn = { "outputClass", "outputHeader", "noop" }, + byOption = { + @BodyType.When(option = "outputType", value = "SelectOne", + carrier = { Carrier.MAP, Carrier.VALUE, Carrier.NULL }), + @BodyType.When(option = "outputType", value = "StreamList", carrier = Carrier.LIST, + javaType = "java.util.Iterator") }, + description = "The rows of a select: a List of Maps of the column names and their values." + + " A query that is not a select leaves the body unchanged, with the count" + + " in the CamelSqlUpdateCount header")) public class SqlEndpoint extends DefaultSqlEndpoint { @UriPath(description = "Sets the SQL query to perform. You can externalize the query by using file: or classpath: as prefix and specify the location of the file.") diff --git a/components/camel-timer/src/generated/resources/META-INF/org/apache/camel/component/timer/timer.json b/components/camel-timer/src/generated/resources/META-INF/org/apache/camel/component/timer/timer.json index fef8e3d02c437..338cb6f43820c 100644 --- a/components/camel-timer/src/generated/resources/META-INF/org/apache/camel/component/timer/timer.json +++ b/components/camel-timer/src/generated/resources/META-INF/org/apache/camel/component/timer/timer.json @@ -33,6 +33,9 @@ "CamelTimerFiredTime": { "index": 0, "kind": "header", "displayName": "", "group": "consumer", "label": "", "required": false, "javaType": "Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The fired time", "constantName": "org.apache.camel.component.timer.TimerConstants#HEADER_FIRED_TIME" }, "CamelMessageTimestamp": { "index": 1, "kind": "header", "displayName": "", "group": "consumer", "label": "", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The timestamp of the message", "constantName": "org.apache.camel.component.timer.TimerConstants#HEADER_MESSAGE_TIMESTAMP" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "description": "No body: the message only starts the route" } + }, "properties": { "timerName": { "index": 0, "kind": "path", "displayName": "Timer Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the timer" }, "delay": { "index": 1, "kind": "parameter", "displayName": "Delay", "group": "consumer", "label": "", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "description": "The number of milliseconds to wait before the first event is generated. Should not be used in conjunction with the time option. The default value is 1000." }, diff --git a/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerEndpoint.java b/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerEndpoint.java index 943e98c3783b8..8fcb40f7acad9 100644 --- a/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerEndpoint.java +++ b/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerEndpoint.java @@ -29,6 +29,9 @@ import org.apache.camel.RuntimeCamelException; import org.apache.camel.api.management.ManagedAttribute; import org.apache.camel.api.management.ManagedResource; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -44,6 +47,7 @@ @UriEndpoint(firstVersion = "1.0.0", scheme = "timer", title = "Timer", syntax = "timer:timerName", consumerOnly = true, remote = false, internal = true, category = { Category.CORE, Category.SCHEDULING }, headersClass = TimerConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.NULL, description = "No body: the message only starts the route")) public class TimerEndpoint extends DefaultEndpoint implements MultipleConsumersSupport { @UriPath @Metadata(required = true) diff --git a/components/camel-xslt/src/generated/resources/META-INF/org/apache/camel/component/xslt/xslt.json b/components/camel-xslt/src/generated/resources/META-INF/org/apache/camel/component/xslt/xslt.json index 0b2ffa8645429..7c6a1d43795b0 100644 --- a/components/camel-xslt/src/generated/resources/META-INF/org/apache/camel/component/xslt/xslt.json +++ b/components/camel-xslt/src/generated/resources/META-INF/org/apache/camel/component/xslt/xslt.json @@ -39,6 +39,10 @@ "CamelXsltStylesheet": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" }, "CamelXsltFileName": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The XSLT file name", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], "byOption": [ { "option": "failOnNullBody", "value": "false", "carriers": [ "null", "text", "bytes", "stream", "file", "pojo" ] } ], "description": "The XML to transform: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source. A Map, a List or no body fails" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultHandlerFactory" ], "byOption": [ { "option": "output", "value": "bytes", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "output", "value": "DOM", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document" }, { "option": "output", "value": "file", "carriers": [ "file" ], "javaType": "java.io.File" } ], "description": "The result of the transformation" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Path to the template. The following is supported by the default URIResolver. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod" }, "allowTemplateFromHeader": { "index": 1, "kind": "parameter", "displayName": "Allow Template From Header", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential security vulnerability if the header is coming from a malicious user, so use this with care." }, diff --git a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java index d7dd5b0ec1b8d..17c699c6e21e0 100644 --- a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java +++ b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java @@ -39,6 +39,9 @@ import org.apache.camel.api.management.ManagedAttribute; import org.apache.camel.api.management.ManagedOperation; import org.apache.camel.api.management.ManagedResource; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ClassResolver; import org.apache.camel.spi.Injector; import org.apache.camel.spi.Metadata; @@ -60,6 +63,23 @@ @ManagedResource(description = "Managed XsltEndpoint") @UriEndpoint(firstVersion = "1.3.0", scheme = "xslt", title = "XSLT", syntax = "xslt:resourceUri", producerOnly = true, remote = false, category = { Category.CORE, Category.TRANSFORMATION }, headersClass = XsltConstants.class) +@BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", dependsOn = "source", + byOption = @BodyType.When(option = "failOnNullBody", value = "false", + carrier = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE, Carrier.POJO }), + description = "The XML to transform: text, bytes, a stream, a file, a DOM or another" + + " javax.xml.transform.Source. A Map, a List or no body fails"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", dependsOn = "resultHandlerFactory", + byOption = { + @BodyType.When(option = "output", value = "bytes", carrier = Carrier.BYTES, + javaType = "byte[]"), + @BodyType.When(option = "output", value = "DOM", carrier = Carrier.POJO, + javaType = "org.w3c.dom.Document"), + @BodyType.When(option = "output", value = "file", carrier = Carrier.FILE, + javaType = "java.io.File") }, + description = "The result of the transformation")) public class XsltEndpoint extends ProcessorEndpoint { private static final Logger LOG = LoggerFactory.getLogger(XsltEndpoint.class); diff --git a/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java b/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java new file mode 100644 index 0000000000000..366a81f7e7116 --- /dev/null +++ b/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java @@ -0,0 +1,148 @@ +/* + * 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.spi; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * One side of {@link BodyTypes}: the body a step needs or leaves. + *

+ * The carriers are coarse on purpose: a carrier that is right is better than a precise Java type that is wrong. Give + * the {@link #javaType()} only when the body is always of that type. + * + * @since 4.24 + */ +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Target({}) +public @interface BodyType { + + /** + * The carriers of the body: the kinds of Java object it is in. Several for a body that can be any of them. None + * when the side is not known. + */ + Carrier[] value() default {}; + + /** + * The Java type of the body, when it is always of this type, such as + * {@code org.apache.camel.component.file.GenericFile}. + */ + String javaType() default ""; + + /** + * The format of the payload, when it is always the same: json, xml, csv, yaml, text or binary. These are the names + * of the data types of Kamelets. + */ + String format() default ""; + + /** + * The options the body depends on. The carriers hold while these options keep their default values; with another + * value the body is not known, unless {@link #byOption()} says it. + */ + String[] dependsOn() default {}; + + /** + * The body for other values of an option, such as {@code output=bytes}. + */ + When[] byOption() default {}; + + /** + * What to know about the body, in a sentence for the documentation and the tools. + */ + String description() default ""; + + /** + * The body when an option has a value. + */ + @Retention(RetentionPolicy.RUNTIME) + @Documented + @Target({}) + @interface When { + + /** + * The name of the option. + */ + String option(); + + /** + * The value of the option. + */ + String value(); + + /** + * The carriers of the body with this value. + */ + Carrier[] carrier(); + + /** + * The Java type of the body with this value, when it is always of this type. + */ + String javaType() default ""; + } + + /** + * The kinds of Java object a body is in. The runtime sorts the bodies it records into kinds as well (null, payload, + * data and collection): text, bytes, a stream, a file and a value are a payload, a map and a pojo are data, a list + * is a collection. + */ + enum Carrier { + + /** No body. */ + NULL("null"), + /** Text: a String. */ + TEXT("text"), + /** A byte array. */ + BYTES("bytes"), + /** A stream: an InputStream, a Reader, or the stream cache of Camel. */ + STREAM("stream"), + /** A file: the GenericFile of the file consumers, a java.io.File or a Path. */ + FILE("file"), + /** A single value: a number, a boolean or an enum. */ + VALUE("value"), + /** A java.util.Map, such as a JSON object parsed or a row of a query. */ + MAP("map"), + /** A List, another Collection, an array or an Iterator, such as a JSON array parsed or the rows of a query. */ + LIST("list"), + /** Another Java object, such as a DOM Document or a class a payload is unmarshalled into. */ + POJO("pojo"), + /** The body as it was before the step: for the body after a step only. */ + UNCHANGED("unchanged"), + /** Any body: for the bodies a step needs only. */ + ANY("any"), + /** + * The body depends on what the other system sends, or on a class the user configures: tooling must not guess + * it. + */ + UNKNOWN("unknown"); + + private final String value; + + Carrier(String value) { + this.value = value; + } + + /** + * The name of the carrier, as the catalog has it. + */ + public String getValue() { + return value; + } + } +} diff --git a/core/camel-api/src/generated/java/org/apache/camel/spi/BodyTypes.java b/core/camel-api/src/generated/java/org/apache/camel/spi/BodyTypes.java new file mode 100644 index 0000000000000..485ac6c17c7d8 --- /dev/null +++ b/core/camel-api/src/generated/java/org/apache/camel/spi/BodyTypes.java @@ -0,0 +1,105 @@ +/* + * 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.spi; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The message body a component, data format or language works with: the body it needs, and the body it leaves after it. + * The build carries it into the catalog, so tooling can say what the body is after a step without running the route: + * the validators, the catalog tools and the documentation. + *

+ * Put it on the endpoint class (the class with {@link UriEndpoint}), the data format class or the language class. A + * subclass does not have the body types of its superclass, as it may change the body: it declares its own. + *

+ * Each side that is given says what the body is with the default options. A side that is not given is not known, and + * tooling must not guess it. A side whose body depends on what the other system sends, or on a class the user + * configures, says {@link BodyType.Carrier#UNKNOWN}. + *

+ * For example the file component: the consumer gives the file it read, the producer writes text, bytes, a stream or a + * file, and leaves the body as it was: + * + *

+ * @BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, description = "The file as read"),
+ *            producerIn = @BodyType({ Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }),
+ *            producerOut = @BodyType(Carrier.UNCHANGED))
+ * 
+ * + * @since 4.24 + */ +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Target({ ElementType.TYPE }) +public @interface BodyTypes { + + /** + * The body of the message the consumer creates. + */ + BodyType consumerOut() default @BodyType; + + /** + * The bodies a consumer that answers the caller can reply with: the body the route ends with, such as the response + * of an HTTP server. + */ + BodyType consumerReply() default @BodyType; + + /** + * The bodies the producer can send or write. + */ + BodyType producerIn() default @BodyType; + + /** + * The body after the producer: {@link BodyType.Carrier#UNCHANGED} when it leaves the body as it was, otherwise what + * it sets, such as the response of a call. + */ + BodyType producerOut() default @BodyType; + + /** + * The bodies a data format can marshal. + */ + BodyType marshalIn() default @BodyType; + + /** + * The body after marshal. + */ + BodyType marshalOut() default @BodyType; + + /** + * The bodies a data format can unmarshal. + */ + BodyType unmarshalIn() default @BodyType; + + /** + * The body after unmarshal. + */ + BodyType unmarshalOut() default @BodyType; + + /** + * The bodies the expressions of a language can read. + */ + BodyType expressionIn() default @BodyType; + + /** + * The result of an expression of a language, which becomes the body in setBody and transform. + */ + BodyType expressionOut() default @BodyType; + +} diff --git a/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc b/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc index 7f63d0149d286..78348be8b710e 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc @@ -122,6 +122,75 @@ public class MailEndpoint extends ScheduledPollEndpoint { Aliases are descriptive names for discovery only; they cannot be used as the scheme in an endpoint URI. +=== Body types in the Catalog + +The options of a component say how to configure it, but not what the message body is after a step. That is the +question people, IDEs and AI agents ask most when they write the next step of a route: the file consumer gives the +file it read, the `http` producer leaves the response as a byte array or a stream, and after `unmarshal: json` the body +is a `Map` or a `List`. + +A component, data format or language can declare its body types, and the catalog then has a `bodyTypes` section with +one entry per side: + +[width="100%",cols="25%,75%",options="header",] +|=== +|Side |The body +|`consumerOut` |The body of the message the consumer creates. +|`consumerReply` |The bodies a consumer that answers the caller can reply with: the body the route ends with. +|`producerIn` |The bodies the producer can send or write. +|`producerOut` |The body after the producer. +|`marshalIn`, `marshalOut` |The bodies a data format can marshal, and the body after marshal. +|`unmarshalIn`, `unmarshalOut` |The bodies a data format can unmarshal, and the body after unmarshal. +|`expressionIn`, `expressionOut` |The bodies the expressions of a language can read, and their result. +|=== + +Each side has the _carriers_ of the body, the kinds of Java object it is in: `null`, `text`, `bytes`, `stream`, +`file`, `value`, `map`, `list` and `pojo`; `unchanged` for a step that leaves the body as it was, `any` for a step that +takes any body, and `unknown` for a body that depends on what the other system sends or on a class the user +configures. A side can also have the Java type when the body is always of that type, the format of the payload (json, +xml, csv, yaml, text or binary), the options the body depends on, the body for other values of an option, and a +description: + +[source,json] +---- +"bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], + "description": "The XML to transform: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source. ..." }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultHandlerFactory" ], + "byOption": [ { "option": "output", "value": "bytes", "carriers": [ "bytes" ], "javaType": "byte[]" }, ... ], + "description": "The result of the transformation" } +} +---- + +The sides say what the body is with the default options. A side that is not in the catalog is not known, and tooling +should not guess it. The Java API gives them on the model: + +[source,java] +---- +CamelCatalog catalog = new DefaultCamelCatalog(); + +BodyTypeModel out = catalog.componentModel("xslt").getBodyType(BodyTypeModel.PRODUCER_OUT); +out.getCarriers(); // [text] +out.getJavaType(); // java.lang.String +---- + +Component developers declare them with the `@BodyTypes` annotation on the endpoint, data format or language class. A +subclass does not have the body types of its superclass, as it may change the body: + +[source,java] +---- +@BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, description = "The file as read ..."), + producerIn = @BodyType({ Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), + producerOut = @BodyType(Carrier.UNCHANGED)) +@UriEndpoint(firstVersion = "1.0.0", scheme = "file", ...) +public class FileEndpoint extends GenericFileEndpoint { +---- + +The build checks that each side belongs to the kind (a consumer-only component has no producer sides), that the +options a side names exist, that `unchanged` is only on the body after a step and `any` only on what a step needs. +The values are read from the code that sets the body, and checked against the body types the message history records +when the routes run. + === Documentation in the Catalog The catalog includes the AsciiDoc documentation pages from all modules. This makes the full diff --git a/docs/user-manual/modules/ROOT/pages/endpoint-annotations.adoc b/docs/user-manual/modules/ROOT/pages/endpoint-annotations.adoc index c46b4fedafcd4..aa9b755a18b8a 100644 --- a/docs/user-manual/modules/ROOT/pages/endpoint-annotations.adoc +++ b/docs/user-manual/modules/ROOT/pages/endpoint-annotations.adoc @@ -31,6 +31,10 @@ configuration parameters; then the class of this field should be annotated with one or more `@UriParam` or `@UriParams` annotations |`@Metadata` | Used for special situations to provide additional information. + +|`@BodyTypes` | The message body the endpoint works with: the body the consumer creates, the bodies the +producer can send, and the body after the producer. See xref:camel-catalog.adoc#_body_types_in_the_catalog[Body types +in the Catalog]. |======================================================================= For example see the `TimerEndpoint` from the `camel-timer` component and diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java index f780f04260069..d69c883fbab17 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java @@ -66,6 +66,13 @@ public final class CatalogDocs { /** The sub-pages of a language's documentation (simple has functions, operators, ognl and advanced). */ private static final List LANGUAGE_DOC_PAGES = List.of("functions", "operators", "ognl", "advanced"); + static final String BODY_TYPES_HINT = "the message body with the default options. consumerOut: the body a from:" + + " gives the route; consumerReply: the bodies it can reply with; producerIn:" + + " the bodies a to: can send; producerOut: the body after the to:; marshal," + + " unmarshal and expression In/Out: the same for a data format and a" + + " language. Carriers: text, bytes, stream, file, value, map, list, pojo," + + " null, unchanged, any, unknown. A side not listed is not known"; + /** * The rules a small model gets wrong most: functions live inside the placeholder, operators between placeholders. * Sent with the simple language result so an answer's examples follow the same shape as the catalog's. @@ -1626,6 +1633,11 @@ private static void addCommonModelFields(JsonObject result, BaseModel model) result.put("deprecationNote", model.getDeprecationNote()); } } + if (!model.getBodyTypes().isEmpty()) { + // what the body is after the step and what it needs, which the options do not say (CAMEL-24961) + result.put("bodyTypes", JsonMapper.asJsonObjectBodyTypes(model.getBodyTypes())); + result.put("bodyTypesHint", BODY_TYPES_HINT); + } } /** diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java index ae686c0d8080d..87de31b39b658 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java +++ b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java @@ -133,6 +133,25 @@ void componentOptionsSayWhetherTheyArePathOrQueryAndTheUriRulesComeAlong() throw assertTrue(direct.getString("uriSyntax").contains("(name) go in the path")); } + @Test + void theBodyTypesSayWhatTheBodyIsAfterAStep() throws Exception { + // CAMEL-24961: what the options of a component do not say + JsonObject xslt = catalogDoc(Map.of("name", "xslt", "kind", "component", "includeOptions", false)); + JsonObject out = ((JsonObject) xslt.get("bodyTypes")).getMap("producerOut"); + assertEquals(List.of("text"), out.getCollection("carriers")); + assertEquals("java.lang.String", out.getString("javaType")); + assertTrue(xslt.getString("bodyTypesHint").contains("A side not listed is not known")); + + JsonObject json = catalogDoc(Map.of("name", "json", "kind", "dataformat", "includeOptions", false)); + JsonObject unmarshalOut = ((JsonObject) json.get("bodyTypes")).getMap("unmarshalOut"); + assertEquals(List.of("map", "list"), unmarshalOut.getCollection("carriers")); + + // a component that does not declare them has none, rather than a guess + JsonObject kafka = catalogDoc(Map.of("name", "kafka", "kind", "component", "includeOptions", false)); + assertNull(kafka.get("bodyTypes")); + assertNull(kafka.get("bodyTypesHint")); + } + @Test void endpointArgumentValidatesAUriAgainstTheComponent() throws Exception { JsonObject bad = catalogDoc(Map.of("endpoint", "timer:tick?period=5s&fixedRte=true&repeatCount=abc")); diff --git a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BaseModel.java b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BaseModel.java index 7e08abe942402..381aeb9412a6d 100644 --- a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BaseModel.java +++ b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BaseModel.java @@ -38,6 +38,7 @@ public abstract class BaseModel { protected boolean nativeSupported; protected List aliases = new ArrayList<>(); protected Map metadata = new LinkedHashMap<>(); + protected Map bodyTypes = new LinkedHashMap<>(); public static Comparator> compareTitle() { return (m1, m2) -> m1.getTitle().compareToIgnoreCase(m2.getTitle()); @@ -175,6 +176,26 @@ public void setMetadata(Map metadata) { this.metadata = metadata; } + /** + * The body types of a component, data format or language, by side ({@link BodyTypeModel#CONSUMER_OUT}, + * {@link BodyTypeModel#PRODUCER_IN}...): the body a step needs and the body it leaves. A side that is not here is + * not known. + */ + public Map getBodyTypes() { + return bodyTypes; + } + + public void setBodyTypes(Map bodyTypes) { + this.bodyTypes = bodyTypes; + } + + /** + * The body type of a side, such as {@link BodyTypeModel#PRODUCER_OUT}, or null when it is not known. + */ + public BodyTypeModel getBodyType(String side) { + return bodyTypes.get(side); + } + @Override public String toString() { return name; diff --git a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java new file mode 100644 index 0000000000000..bde3c29c0090a --- /dev/null +++ b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java @@ -0,0 +1,193 @@ +/* + * 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.tooling.model; + +import java.util.ArrayList; +import java.util.List; + +/** + * One side of the body types of a component, data format or language: the body a step needs, or the body it leaves + * after it, with the default options (CAMEL-24961). + *

+ * The carriers are the kinds of Java object the body is in: null, text, bytes, stream, file, value, map, list and pojo; + * unchanged for a step that leaves the body as it was, any for a step that takes any body, and unknown for a body that + * depends on what the other system sends or on a class the user configures. + */ +public class BodyTypeModel { + + /** The body of the message the consumer creates. */ + public static final String CONSUMER_OUT = "consumerOut"; + /** The bodies a consumer that answers the caller can reply with: the body the route ends with. */ + public static final String CONSUMER_REPLY = "consumerReply"; + /** The bodies the producer can send or write. */ + public static final String PRODUCER_IN = "producerIn"; + /** The body after the producer. */ + public static final String PRODUCER_OUT = "producerOut"; + /** The bodies a data format can marshal. */ + public static final String MARSHAL_IN = "marshalIn"; + /** The body after marshal. */ + public static final String MARSHAL_OUT = "marshalOut"; + /** The bodies a data format can unmarshal. */ + public static final String UNMARSHAL_IN = "unmarshalIn"; + /** The body after unmarshal. */ + public static final String UNMARSHAL_OUT = "unmarshalOut"; + /** The bodies the expressions of a language can read. */ + public static final String EXPRESSION_IN = "expressionIn"; + /** The result of an expression of a language. */ + public static final String EXPRESSION_OUT = "expressionOut"; + + private List carriers = new ArrayList<>(); + private String javaType; + private String format; + private List dependsOn = new ArrayList<>(); + private List byOption = new ArrayList<>(); + private String description; + + /** + * The carriers of the body: one, or several for a body that can be any of them. + */ + public List getCarriers() { + return carriers; + } + + public void setCarriers(List carriers) { + this.carriers = carriers; + } + + /** + * The Java type of the body, when it is always of this type. + */ + public String getJavaType() { + return javaType; + } + + public void setJavaType(String javaType) { + this.javaType = javaType; + } + + /** + * The format of the payload, when it is always the same: json, xml, csv, yaml, text or binary. + */ + public String getFormat() { + return format; + } + + public void setFormat(String format) { + this.format = format; + } + + /** + * The options the body depends on: with another value than the default the body is not known, unless + * {@link #getByOption()} says it. + */ + public List getDependsOn() { + return dependsOn; + } + + public void setDependsOn(List dependsOn) { + this.dependsOn = dependsOn; + } + + /** + * The body for other values of an option. + */ + public List getByOption() { + return byOption; + } + + public void setByOption(List byOption) { + this.byOption = byOption; + } + + /** + * What to know about the body, in a sentence. + */ + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + /** + * Whether the body is left as it was (for the body after a step). + */ + public boolean isUnchanged() { + return carriers.contains("unchanged"); + } + + /** + * Whether the body is not known without the configuration or the data of the other system. + */ + public boolean isUnknown() { + return carriers.isEmpty() || carriers.contains("unknown"); + } + + @Override + public String toString() { + return String.join(", ", carriers) + (javaType != null ? " (" + javaType + ")" : ""); + } + + /** + * The body when an option has a value. + */ + public static class OptionBodyTypeModel { + + private String option; + private String value; + private List carriers = new ArrayList<>(); + private String javaType; + + public String getOption() { + return option; + } + + public void setOption(String option) { + this.option = option; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public List getCarriers() { + return carriers; + } + + public void setCarriers(List carriers) { + this.carriers = carriers; + } + + public String getJavaType() { + return javaType; + } + + public void setJavaType(String javaType) { + this.javaType = javaType; + } + + @Override + public String toString() { + return option + "=" + value + ": " + String.join(", ", carriers); + } + } +} diff --git a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java index ac23618bc572f..28e0ab4a28345 100644 --- a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java +++ b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java @@ -19,7 +19,9 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -97,6 +99,7 @@ public static ComponentModel generateComponentModel(JsonObject obj) { JsonObject mobj = (JsonObject) obj.get("component"); ComponentModel model = new ComponentModel(); parseComponentModel(mobj, model); + model.setBodyTypes(parseBodyTypes(obj.getMap("bodyTypes"))); JsonObject mcprp = (JsonObject) obj.get("componentProperties"); if (mcprp != null) { for (Map.Entry entry : mcprp.entrySet()) { @@ -252,6 +255,7 @@ public static JsonObject asJsonObject(ComponentModel model) { if (!headers.isEmpty()) { wrapper.put("headers", asJsonObject(headers)); } + bodyTypesToJson(model, wrapper); wrapper.put("properties", asJsonObject(model.getEndpointOptions())); if (!model.getApiOptions().isEmpty()) { wrapper.put("apis", apiModelAsJsonObject(model.getApiOptions(), false)); @@ -269,6 +273,7 @@ public static DataFormatModel generateDataFormatModel(JsonObject obj) { JsonObject mobj = (JsonObject) obj.get("dataformat"); DataFormatModel model = new DataFormatModel(); parseModel(mobj, model); + model.setBodyTypes(parseBodyTypes(obj.getMap("bodyTypes"))); parseArtifact(mobj, model); model.setModelName(mobj.getString("modelName")); model.setModelJavaType(mobj.getString("modelJavaType")); @@ -297,6 +302,7 @@ public static JsonObject asJsonObject(DataFormatModel model) { obj.entrySet().removeIf(e -> e.getValue() == null); JsonObject wrapper = new JsonObject(); wrapper.put("dataformat", obj); + bodyTypesToJson(model, wrapper); wrapper.put("properties", asJsonObject(model.getOptions())); return wrapper; } @@ -478,6 +484,7 @@ public static LanguageModel generateLanguageModel(JsonObject obj) { JsonObject mobj = (JsonObject) obj.get("language"); LanguageModel model = new LanguageModel(); parseModel(mobj, model); + model.setBodyTypes(parseBodyTypes(obj.getMap("bodyTypes"))); model.setModelName(mobj.getString("modelName")); model.setModelJavaType(mobj.getString("modelJavaType")); parseArtifact(mobj, model); @@ -523,6 +530,7 @@ public static JsonObject asJsonObject(LanguageModel model) { obj.entrySet().removeIf(e -> e.getValue() == null); JsonObject wrapper = new JsonObject(); wrapper.put("language", obj); + bodyTypesToJson(model, wrapper); wrapper.put("properties", asJsonObject(model.getOptions())); final List functions = model.getFunctions(); if (!functions.isEmpty()) { @@ -693,6 +701,84 @@ private static void parseModel(JsonObject mobj, BaseModel model) { model.setMetadata(mobj.getMapOrDefault("metadata", new JsonObject())); } + /** The body types of a component, data format or language: one object per side (CAMEL-24961). */ + private static Map parseBodyTypes(JsonObject json) { + Map answer = new LinkedHashMap<>(); + if (json == null) { + return answer; + } + for (Map.Entry entry : json.entrySet()) { + JsonObject side = (JsonObject) entry.getValue(); + BodyTypeModel bodyType = new BodyTypeModel(); + bodyType.setCarriers(stringList(side.getCollection("carriers"))); + bodyType.setJavaType(side.getString("javaType")); + bodyType.setFormat(side.getString("format")); + bodyType.setDependsOn(stringList(side.getCollection("dependsOn"))); + Collection byOption = side.getCollection("byOption"); + if (byOption != null) { + for (JsonObject when : byOption) { + BodyTypeModel.OptionBodyTypeModel option = new BodyTypeModel.OptionBodyTypeModel(); + option.setOption(when.getString("option")); + option.setValue(when.getString("value")); + option.setCarriers(stringList(when.getCollection("carriers"))); + option.setJavaType(when.getString("javaType")); + bodyType.getByOption().add(option); + } + } + bodyType.setDescription(side.getString("description")); + answer.put(entry.getKey(), bodyType); + } + return answer; + } + + private static List stringList(Collection values) { + return values != null ? new ArrayList<>(values) : new ArrayList<>(); + } + + /** The body types as a section of their own, next to the options, so each side is a line of the catalog. */ + private static void bodyTypesToJson(BaseModel model, JsonObject wrapper) { + if (model.getBodyTypes().isEmpty()) { + return; + } + wrapper.put("bodyTypes", asJsonObjectBodyTypes(model.getBodyTypes())); + } + + /** + * The body types of a component, data format or language as the catalog has them: an object per side, with the + * carriers, the Java type, the format, the options it depends on, the body for other option values and the + * description (CAMEL-24961). + */ + public static JsonObject asJsonObjectBodyTypes(Map bodyTypes) { + JsonObject json = new JsonObject(); + for (Map.Entry entry : bodyTypes.entrySet()) { + BodyTypeModel bodyType = entry.getValue(); + JsonObject side = new JsonObject(); + side.put("carriers", bodyType.getCarriers()); + side.put("javaType", bodyType.getJavaType()); + side.put("format", bodyType.getFormat()); + if (!bodyType.getDependsOn().isEmpty()) { + side.put("dependsOn", bodyType.getDependsOn()); + } + if (!bodyType.getByOption().isEmpty()) { + JsonArray byOption = new JsonArray(); + for (BodyTypeModel.OptionBodyTypeModel option : bodyType.getByOption()) { + JsonObject when = new JsonObject(); + when.put("option", option.getOption()); + when.put("value", option.getValue()); + when.put("carriers", option.getCarriers()); + when.put("javaType", option.getJavaType()); + when.entrySet().removeIf(e -> e.getValue() == null); + byOption.add(when); + } + side.put("byOption", byOption); + } + side.put("description", bodyType.getDescription()); + side.entrySet().removeIf(e -> e.getValue() == null); + json.put(entry.getKey(), side); + } + return json; + } + private static void parseOption(JsonObject mp, BaseOptionModel option, String name) { option.setName(name); Integer idx = mp.getInteger("index"); diff --git a/tooling/camel-tooling-model/src/test/java/org/apache/camel/tooling/model/JsonMapperTest.java b/tooling/camel-tooling-model/src/test/java/org/apache/camel/tooling/model/JsonMapperTest.java index c97f45b0b7d22..0b5fdc875bc14 100644 --- a/tooling/camel-tooling-model/src/test/java/org/apache/camel/tooling/model/JsonMapperTest.java +++ b/tooling/camel-tooling-model/src/test/java/org/apache/camel/tooling/model/JsonMapperTest.java @@ -23,6 +23,7 @@ import static org.apache.camel.tooling.model.ComponentModel.EndpointHeaderModel; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -161,4 +162,81 @@ void testShouldSerializeAndDeserializeApiReference() { assertEquals(List.of("Object getBody()", " T getBody(Class type)"), m.getSignatures()); assertEquals(List.of("message.getBody(String.class)"), m.getExamples()); } + + @Test + void testShouldWriteBodyTypesOnlyWhenSet() { + // CAMEL-24961: the body a step needs and the body it leaves + ComponentModel model = new ComponentModel(); + String json = JsonMapper.createParameterJsonSchema(model); + assertFalse(json.contains("\"bodyTypes\"")); + assertTrue(JsonMapper.generateComponentModel(json).getBodyTypes().isEmpty()); + + BodyTypeModel in = new BodyTypeModel(); + in.setCarriers(List.of("text", "bytes", "stream", "file")); + in.setFormat("xml"); + BodyTypeModel out = new BodyTypeModel(); + out.setCarriers(List.of("text")); + out.setJavaType("java.lang.String"); + out.setDependsOn(List.of("resultHandlerFactory")); + BodyTypeModel.OptionBodyTypeModel bytes = new BodyTypeModel.OptionBodyTypeModel(); + bytes.setOption("output"); + bytes.setValue("bytes"); + bytes.setCarriers(List.of("bytes")); + bytes.setJavaType("byte[]"); + out.getByOption().add(bytes); + out.setDescription("The result of the transformation"); + model.getBodyTypes().put(BodyTypeModel.PRODUCER_IN, in); + model.getBodyTypes().put(BodyTypeModel.PRODUCER_OUT, out); + + json = JsonMapper.createParameterJsonSchema(model); + assertTrue(json.contains("\"bodyTypes\""), json); + ComponentModel model2 = JsonMapper.generateComponentModel(json); + assertEquals(List.of(BodyTypeModel.PRODUCER_IN, BodyTypeModel.PRODUCER_OUT), + List.copyOf(model2.getBodyTypes().keySet())); + assertNull(model2.getBodyType(BodyTypeModel.CONSUMER_OUT)); + + BodyTypeModel in2 = model2.getBodyType(BodyTypeModel.PRODUCER_IN); + assertEquals(List.of("text", "bytes", "stream", "file"), in2.getCarriers()); + assertEquals("xml", in2.getFormat()); + assertNull(in2.getJavaType()); + assertTrue(in2.getDependsOn().isEmpty()); + assertTrue(in2.getByOption().isEmpty()); + + BodyTypeModel out2 = model2.getBodyType(BodyTypeModel.PRODUCER_OUT); + assertEquals(List.of("text"), out2.getCarriers()); + assertEquals("java.lang.String", out2.getJavaType()); + assertEquals(List.of("resultHandlerFactory"), out2.getDependsOn()); + assertEquals("The result of the transformation", out2.getDescription()); + assertEquals(1, out2.getByOption().size()); + BodyTypeModel.OptionBodyTypeModel bytes2 = out2.getByOption().get(0); + assertEquals("output", bytes2.getOption()); + assertEquals("bytes", bytes2.getValue()); + assertEquals(List.of("bytes"), bytes2.getCarriers()); + assertEquals("byte[]", bytes2.getJavaType()); + assertFalse(out2.isUnchanged()); + assertFalse(out2.isUnknown()); + } + + @Test + void testShouldWriteBodyTypesOfDataFormatsAndLanguages() { + DataFormatModel dataFormat = new DataFormatModel(); + dataFormat.setName("jackson"); + BodyTypeModel unmarshalOut = new BodyTypeModel(); + unmarshalOut.setCarriers(List.of("map", "list")); + unmarshalOut.setDependsOn(List.of("unmarshalType")); + dataFormat.getBodyTypes().put(BodyTypeModel.UNMARSHAL_OUT, unmarshalOut); + DataFormatModel dataFormat2 + = JsonMapper.generateDataFormatModel(JsonMapper.createParameterJsonSchema(dataFormat)); + assertEquals(List.of("map", "list"), dataFormat2.getBodyType(BodyTypeModel.UNMARSHAL_OUT).getCarriers()); + assertEquals(List.of("unmarshalType"), dataFormat2.getBodyType(BodyTypeModel.UNMARSHAL_OUT).getDependsOn()); + + LanguageModel language = new LanguageModel(); + language.setName("constant"); + BodyTypeModel expressionOut = new BodyTypeModel(); + expressionOut.setCarriers(List.of("text")); + language.getBodyTypes().put(BodyTypeModel.EXPRESSION_OUT, expressionOut); + LanguageModel language2 = JsonMapper.generateLanguageModel(JsonMapper.createParameterJsonSchema(language)); + assertEquals(List.of("text"), language2.getBodyType(BodyTypeModel.EXPRESSION_OUT).getCarriers()); + assertNull(language2.getBodyType(BodyTypeModel.EXPRESSION_IN)); + } } diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java new file mode 100644 index 0000000000000..02e23fbd3b8bc --- /dev/null +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java @@ -0,0 +1,185 @@ +/* + * 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.maven.packaging; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; +import org.apache.camel.tooling.model.BaseModel; +import org.apache.camel.tooling.model.BodyTypeModel; +import org.apache.camel.tooling.model.ComponentModel; + +/** + * Carries the {@link BodyTypes} of a component, data format or language into its model, which the catalog JSON is + * written from (CAMEL-24961). + */ +final class BodyTypesHelper { + + private static final Set IN = Set.of(BodyTypeModel.CONSUMER_REPLY, BodyTypeModel.PRODUCER_IN, + BodyTypeModel.MARSHAL_IN, BodyTypeModel.UNMARSHAL_IN, BodyTypeModel.EXPRESSION_IN); + + private BodyTypesHelper() { + } + + /** + * Adds the sides the annotation gives to the model, in the order of the annotation. + * + * @param model the model of the component, data format or language + * @param bodyTypes the annotation, null when the class has none + * @param owner the class with the annotation, for the error message + * @throws IllegalArgumentException when a side does not fit the model: a data format side on a component, a + * producer side on a consumer-only component, unchanged on what a step needs or + * any on what it leaves + */ + static void addBodyTypes(BaseModel model, BodyTypes bodyTypes, Class owner) { + if (bodyTypes == null) { + return; + } + Map sides = new LinkedHashMap<>(); + sides.put(BodyTypeModel.CONSUMER_OUT, bodyTypes.consumerOut()); + sides.put(BodyTypeModel.CONSUMER_REPLY, bodyTypes.consumerReply()); + sides.put(BodyTypeModel.PRODUCER_IN, bodyTypes.producerIn()); + sides.put(BodyTypeModel.PRODUCER_OUT, bodyTypes.producerOut()); + sides.put(BodyTypeModel.MARSHAL_IN, bodyTypes.marshalIn()); + sides.put(BodyTypeModel.MARSHAL_OUT, bodyTypes.marshalOut()); + sides.put(BodyTypeModel.UNMARSHAL_IN, bodyTypes.unmarshalIn()); + sides.put(BodyTypeModel.UNMARSHAL_OUT, bodyTypes.unmarshalOut()); + sides.put(BodyTypeModel.EXPRESSION_IN, bodyTypes.expressionIn()); + sides.put(BodyTypeModel.EXPRESSION_OUT, bodyTypes.expressionOut()); + + Set allowed = allowedSides(model); + Set options = optionNames(model); + for (Map.Entry entry : sides.entrySet()) { + String side = entry.getKey(); + BodyType bodyType = entry.getValue(); + if (bodyType.value().length == 0) { + if (!bodyType.javaType().isEmpty() || !bodyType.format().isEmpty() || bodyType.dependsOn().length > 0 + || bodyType.byOption().length > 0 || !bodyType.description().isEmpty()) { + throw new IllegalArgumentException( + owner.getName() + ": the @BodyTypes " + side + " has no carriers, but other attributes"); + } + continue; + } + if (!allowed.contains(side)) { + throw new IllegalArgumentException( + owner.getName() + ": the @BodyTypes " + side + " is not a side of this " + model.getKind() + + ", which has " + allowed); + } + check(owner, side, bodyType.value()); + for (String option : bodyType.dependsOn()) { + checkOption(owner, side, option, options); + } + for (BodyType.When when : bodyType.byOption()) { + checkOption(owner, side, when.option(), options); + check(owner, side + " " + when.option() + "=" + when.value(), when.carrier()); + } + model.getBodyTypes().put(side, asModel(bodyType)); + } + } + + private static Set allowedSides(BaseModel model) { + return switch (model.getKind()) { + case component -> { + ComponentModel component = (ComponentModel) model; + if (component.isConsumerOnly()) { + yield Set.of(BodyTypeModel.CONSUMER_OUT, BodyTypeModel.CONSUMER_REPLY); + } else if (component.isProducerOnly()) { + yield Set.of(BodyTypeModel.PRODUCER_IN, BodyTypeModel.PRODUCER_OUT); + } + yield Set.of(BodyTypeModel.CONSUMER_OUT, BodyTypeModel.CONSUMER_REPLY, BodyTypeModel.PRODUCER_IN, + BodyTypeModel.PRODUCER_OUT); + } + case dataformat -> Set.of(BodyTypeModel.MARSHAL_IN, BodyTypeModel.MARSHAL_OUT, BodyTypeModel.UNMARSHAL_IN, + BodyTypeModel.UNMARSHAL_OUT); + case language -> Set.of(BodyTypeModel.EXPRESSION_IN, BodyTypeModel.EXPRESSION_OUT); + default -> Set.of(); + }; + } + + /** The options of the model, which the body types can depend on. */ + private static Set optionNames(BaseModel model) { + Set names = new HashSet<>(); + model.getOptions().forEach(o -> names.add(o.getName())); + if (model instanceof ComponentModel component) { + component.getComponentOptions().forEach(o -> names.add(o.getName())); + component.getEndpointOptions().forEach(o -> names.add(o.getName())); + } + return names; + } + + private static void checkOption(Class owner, String side, String option, Set options) { + if (!options.contains(option)) { + throw new IllegalArgumentException( + owner.getName() + ": the @BodyTypes " + side + " depends on " + option + ", which is not an option"); + } + } + + /** + * UNCHANGED is for the body after a step, such as a sql query that leaves it unchanged unless it is a select. ANY + * is for the bodies a step needs. ANY and UNKNOWN stand alone. + */ + private static void check(Class owner, String side, Carrier[] carriers) { + List list = Arrays.asList(carriers); + boolean in = IN.contains(side.split(" ")[0]); + if (in && list.contains(Carrier.UNCHANGED)) { + throw new IllegalArgumentException( + owner.getName() + ": the @BodyTypes " + side + " is what a step needs, which cannot be unchanged"); + } + if (!in && list.contains(Carrier.ANY)) { + throw new IllegalArgumentException( + owner.getName() + ": the @BodyTypes " + side + " is the body after a step, which cannot be any"); + } + if (list.size() > 1 && (list.contains(Carrier.ANY) || list.contains(Carrier.UNKNOWN))) { + throw new IllegalArgumentException( + owner.getName() + ": the @BodyTypes " + side + " has any or unknown with other carriers"); + } + } + + private static BodyTypeModel asModel(BodyType bodyType) { + BodyTypeModel model = new BodyTypeModel(); + model.setCarriers(names(bodyType.value())); + model.setJavaType(emptyAsNull(bodyType.javaType())); + model.setFormat(emptyAsNull(bodyType.format())); + model.setDependsOn(new ArrayList<>(Arrays.asList(bodyType.dependsOn()))); + for (BodyType.When when : bodyType.byOption()) { + BodyTypeModel.OptionBodyTypeModel option = new BodyTypeModel.OptionBodyTypeModel(); + option.setOption(when.option()); + option.setValue(when.value()); + option.setCarriers(names(when.carrier())); + option.setJavaType(emptyAsNull(when.javaType())); + model.getByOption().add(option); + } + model.setDescription(emptyAsNull(bodyType.description())); + return model; + } + + private static List names(Carrier[] carriers) { + return new ArrayList<>(Arrays.stream(carriers).map(Carrier::getValue).toList()); + } + + private static String emptyAsNull(String value) { + return value.isEmpty() ? null : value; + } +} diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojo.java index 061b650e06b54..6621f1022b577 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojo.java @@ -52,6 +52,7 @@ import org.apache.camel.spi.ApiMethod; import org.apache.camel.spi.ApiParam; import org.apache.camel.spi.ApiParams; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -306,6 +307,7 @@ protected ComponentModel writeJSonSchemeAndPropertyConfigurer( SchemaHelper.addModelMetadata(componentModel, project); SchemaHelper.addModelMetadata(componentModel, classElement.getAnnotation(Metadata.class)); + addBodyTypes(componentModel, classElement); String json = JsonMapper.createParameterJsonSchema(componentModel); @@ -322,6 +324,18 @@ protected ComponentModel writeJSonSchemeAndPropertyConfigurer( return componentModel; } + /** + * Adds the body types of the endpoint, which the endpoint class or a superclass declares with {@link BodyTypes} + * (CAMEL-24961). + */ + void addBodyTypes(ComponentModel componentModel, Class classElement) throws MojoExecutionException { + try { + BodyTypesHelper.addBodyTypes(componentModel, classElement.getAnnotation(BodyTypes.class), classElement); + } catch (IllegalArgumentException e) { + throw new MojoExecutionException(e.getMessage(), e); + } + } + /** * Retrieve the metadata added to all the {@code String} constants defined in the class corresponding to the element * {@code headersClass} of the annotation {@code UriEndpoint} along with all its super classes and implemented diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageDataFormatMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageDataFormatMojo.java index edc311d02b7ad..66377f9c3cf08 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageDataFormatMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageDataFormatMojo.java @@ -35,6 +35,7 @@ import javax.inject.Inject; import org.apache.camel.maven.packaging.generics.ClassUtil; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.tooling.model.BaseOptionModel; import org.apache.camel.tooling.model.DataFormatModel; @@ -202,6 +203,7 @@ public int prepareDataFormat() throws MojoExecutionException { SchemaHelper.addModelMetadata(dataFormatModel, project); SchemaHelper.addModelMetadata(dataFormatModel, metadata); + BodyTypesHelper.addBodyTypes(dataFormatModel, clazz.getAnnotation(BodyTypes.class), clazz); if (!modelName.equals(name)) { /* Prefer description from the clazz */ diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageLanguageMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageLanguageMojo.java index 94f1f3974bc89..862a093d70655 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageLanguageMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PackageLanguageMojo.java @@ -29,6 +29,7 @@ import javax.inject.Inject; import org.apache.camel.maven.packaging.generics.ClassUtil; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.annotations.Language; import org.apache.camel.tooling.model.EipModel; @@ -166,6 +167,7 @@ public int prepareLanguage() throws MojoExecutionException { SchemaHelper.addModelMetadata(languageModel, project); SchemaHelper.addModelMetadata(languageModel, javaType.getAnnotation(Metadata.class)); + BodyTypesHelper.addBodyTypes(languageModel, javaType.getAnnotation(BodyTypes.class), javaType); // build json schema for the language String schema = JsonMapper.createParameterJsonSchema(languageModel); diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java index 562fce01273ec..5fa0723fa8f5c 100644 --- a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java @@ -20,11 +20,14 @@ import java.util.List; import org.apache.camel.maven.packaging.endpoint.SomeEndpoint; +import org.apache.camel.maven.packaging.endpoint.SomeEndpointExtendingBodyTypes; import org.apache.camel.maven.packaging.endpoint.SomeEndpointUsingEnumConstants; import org.apache.camel.maven.packaging.endpoint.SomeEndpointUsingEnumConstantsByField; import org.apache.camel.maven.packaging.endpoint.SomeEndpointUsingEnumConstantsByMethod; import org.apache.camel.maven.packaging.endpoint.SomeEndpointUsingInterfaceConstants; +import org.apache.camel.maven.packaging.endpoint.SomeEndpointWithBadBodyTypes; import org.apache.camel.maven.packaging.endpoint.SomeEndpointWithBadHeaders; +import org.apache.camel.maven.packaging.endpoint.SomeEndpointWithBodyTypes; import org.apache.camel.maven.packaging.endpoint.SomeEndpointWithFilter; import org.apache.camel.maven.packaging.endpoint.SomeEndpointWithHeaderClassHierarchy; import org.apache.camel.maven.packaging.endpoint.SomeEndpointWithHeaderInterfaceHierarchy; @@ -33,6 +36,7 @@ import org.apache.camel.maven.packaging.endpoint.SomeExtendingEndpoint; import org.apache.camel.maven.packaging.endpoint.SomeInternalRemoteEndpoint; import org.apache.camel.spi.UriEndpoint; +import org.apache.camel.tooling.model.BodyTypeModel; import org.apache.camel.tooling.model.ComponentModel; import org.apache.camel.tooling.model.ComponentModel.EndpointHeaderModel; import org.apache.maven.plugin.MojoExecutionException; @@ -225,4 +229,69 @@ void testEndpointWithHeadersOnSelfAndSuperclass() { assertEquals("KEY_EMPTY_WITH_JAVA_DOC", headerFromParent.getName()); } + + @Test + void testEndpointWithBodyTypes() throws Exception { + // CAMEL-24961: the body a step needs and the body it leaves, in the order of the annotation + addEndpointOptions("resultHandlerFactory", "output"); + mojo.addBodyTypes(model, SomeEndpointWithBodyTypes.class); + assertEquals(List.of(BodyTypeModel.CONSUMER_OUT, BodyTypeModel.PRODUCER_IN, BodyTypeModel.PRODUCER_OUT), + List.copyOf(model.getBodyTypes().keySet())); + + BodyTypeModel consumerOut = model.getBodyType(BodyTypeModel.CONSUMER_OUT); + assertEquals(List.of("file"), consumerOut.getCarriers()); + assertEquals("org.apache.camel.component.file.GenericFile", consumerOut.getJavaType()); + assertEquals("The file as read", consumerOut.getDescription()); + assertNull(consumerOut.getFormat()); + assertTrue(consumerOut.getDependsOn().isEmpty()); + + assertEquals(List.of("text", "bytes", "stream", "file"), + model.getBodyType(BodyTypeModel.PRODUCER_IN).getCarriers()); + + BodyTypeModel producerOut = model.getBodyType(BodyTypeModel.PRODUCER_OUT); + assertEquals(List.of("text"), producerOut.getCarriers()); + assertEquals("xml", producerOut.getFormat()); + assertEquals(List.of("resultHandlerFactory"), producerOut.getDependsOn()); + assertEquals(1, producerOut.getByOption().size()); + BodyTypeModel.OptionBodyTypeModel bytes = producerOut.getByOption().get(0); + assertEquals("output", bytes.getOption()); + assertEquals("bytes", bytes.getValue()); + assertEquals(List.of("bytes"), bytes.getCarriers()); + assertEquals("byte[]", bytes.getJavaType()); + } + + @Test + void testEndpointDoesNotInheritBodyTypes() throws Exception { + // a subclass may change the body, so it declares its own + mojo.addBodyTypes(model, SomeEndpointExtendingBodyTypes.class); + assertTrue(model.getBodyTypes().isEmpty()); + } + + @Test + void testEndpointWithoutBodyTypes() throws Exception { + mojo.addBodyTypes(model, SomeEndpointWithoutHeaders.class); + assertTrue(model.getBodyTypes().isEmpty()); + } + + @ParameterizedTest + @ValueSource(classes = { + SomeEndpointWithBadBodyTypes.DataFormatSide.class, SomeEndpointWithBadBodyTypes.ProducerSideOfConsumer.class, + SomeEndpointWithBadBodyTypes.UnchangedInput.class, SomeEndpointWithBadBodyTypes.AnyOutput.class, + SomeEndpointWithBadBodyTypes.UnknownWithOthers.class, SomeEndpointWithBadBodyTypes.NoCarriers.class, + SomeEndpointWithBadBodyTypes.UnknownOption.class }) + void testEndpointWithBadBodyTypes(Class clazz) { + addEndpointOptions("output"); + model.setConsumerOnly(clazz.getAnnotation(UriEndpoint.class).consumerOnly()); + MojoExecutionException e = assertThrows(MojoExecutionException.class, () -> mojo.addBodyTypes(model, clazz)); + assertTrue(e.getMessage().startsWith(clazz.getName() + ": the @BodyTypes "), e.getMessage()); + assertTrue(model.getBodyTypes().isEmpty()); + } + + private void addEndpointOptions(String... names) { + for (String name : names) { + ComponentModel.EndpointOptionModel option = new ComponentModel.EndpointOptionModel(); + option.setName(name); + model.addEndpointOption(option); + } + } } diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointExtendingBodyTypes.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointExtendingBodyTypes.java new file mode 100644 index 0000000000000..31f9aa9563d84 --- /dev/null +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointExtendingBodyTypes.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.maven.packaging.endpoint; + +import org.apache.camel.spi.UriEndpoint; + +@UriEndpoint(scheme = "someextbody", syntax = "someextbody", title = "someextbody") +public class SomeEndpointExtendingBodyTypes extends SomeEndpointWithBodyTypes { +} diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java new file mode 100644 index 0000000000000..cd66ff0c96706 --- /dev/null +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java @@ -0,0 +1,66 @@ +/* + * 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.maven.packaging.endpoint; + +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; +import org.apache.camel.spi.UriEndpoint; + +/** + * Body types that do not fit an endpoint, one per nested class. + */ +public final class SomeEndpointWithBadBodyTypes { + + private SomeEndpointWithBadBodyTypes() { + } + + @UriEndpoint(scheme = "some", syntax = "some", title = "some") + @BodyTypes(marshalOut = @BodyType(Carrier.STREAM)) + public static class DataFormatSide { + } + + @UriEndpoint(scheme = "some", syntax = "some", title = "some", consumerOnly = true) + @BodyTypes(producerOut = @BodyType(Carrier.UNCHANGED)) + public static class ProducerSideOfConsumer { + } + + @UriEndpoint(scheme = "some", syntax = "some", title = "some") + @BodyTypes(producerIn = @BodyType(Carrier.UNCHANGED)) + public static class UnchangedInput { + } + + @UriEndpoint(scheme = "some", syntax = "some", title = "some") + @BodyTypes(producerOut = @BodyType(Carrier.ANY)) + public static class AnyOutput { + } + + @UriEndpoint(scheme = "some", syntax = "some", title = "some") + @BodyTypes(producerOut = @BodyType({ Carrier.UNKNOWN, Carrier.TEXT })) + public static class UnknownWithOthers { + } + + @UriEndpoint(scheme = "some", syntax = "some", title = "some") + @BodyTypes(producerOut = @BodyType(javaType = "java.lang.String")) + public static class NoCarriers { + } + + @UriEndpoint(scheme = "some", syntax = "some", title = "some") + @BodyTypes(producerOut = @BodyType(value = Carrier.TEXT, dependsOn = "nope")) + public static class UnknownOption { + } +} diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBodyTypes.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBodyTypes.java new file mode 100644 index 0000000000000..18c10606a6461 --- /dev/null +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBodyTypes.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.maven.packaging.endpoint; + +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; +import org.apache.camel.spi.UriEndpoint; + +@UriEndpoint(scheme = "some", syntax = "some", title = "some") +@BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, javaType = "org.apache.camel.component.file.GenericFile", + description = "The file as read"), + producerIn = @BodyType({ Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", format = "xml", + dependsOn = "resultHandlerFactory", + byOption = @BodyType.When(option = "output", value = "bytes", + carrier = Carrier.BYTES, javaType = "byte[]"))) +public class SomeEndpointWithBodyTypes { +} diff --git a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java new file mode 100644 index 0000000000000..366a81f7e7116 --- /dev/null +++ b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java @@ -0,0 +1,148 @@ +/* + * 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.spi; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * One side of {@link BodyTypes}: the body a step needs or leaves. + *

+ * The carriers are coarse on purpose: a carrier that is right is better than a precise Java type that is wrong. Give + * the {@link #javaType()} only when the body is always of that type. + * + * @since 4.24 + */ +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Target({}) +public @interface BodyType { + + /** + * The carriers of the body: the kinds of Java object it is in. Several for a body that can be any of them. None + * when the side is not known. + */ + Carrier[] value() default {}; + + /** + * The Java type of the body, when it is always of this type, such as + * {@code org.apache.camel.component.file.GenericFile}. + */ + String javaType() default ""; + + /** + * The format of the payload, when it is always the same: json, xml, csv, yaml, text or binary. These are the names + * of the data types of Kamelets. + */ + String format() default ""; + + /** + * The options the body depends on. The carriers hold while these options keep their default values; with another + * value the body is not known, unless {@link #byOption()} says it. + */ + String[] dependsOn() default {}; + + /** + * The body for other values of an option, such as {@code output=bytes}. + */ + When[] byOption() default {}; + + /** + * What to know about the body, in a sentence for the documentation and the tools. + */ + String description() default ""; + + /** + * The body when an option has a value. + */ + @Retention(RetentionPolicy.RUNTIME) + @Documented + @Target({}) + @interface When { + + /** + * The name of the option. + */ + String option(); + + /** + * The value of the option. + */ + String value(); + + /** + * The carriers of the body with this value. + */ + Carrier[] carrier(); + + /** + * The Java type of the body with this value, when it is always of this type. + */ + String javaType() default ""; + } + + /** + * The kinds of Java object a body is in. The runtime sorts the bodies it records into kinds as well (null, payload, + * data and collection): text, bytes, a stream, a file and a value are a payload, a map and a pojo are data, a list + * is a collection. + */ + enum Carrier { + + /** No body. */ + NULL("null"), + /** Text: a String. */ + TEXT("text"), + /** A byte array. */ + BYTES("bytes"), + /** A stream: an InputStream, a Reader, or the stream cache of Camel. */ + STREAM("stream"), + /** A file: the GenericFile of the file consumers, a java.io.File or a Path. */ + FILE("file"), + /** A single value: a number, a boolean or an enum. */ + VALUE("value"), + /** A java.util.Map, such as a JSON object parsed or a row of a query. */ + MAP("map"), + /** A List, another Collection, an array or an Iterator, such as a JSON array parsed or the rows of a query. */ + LIST("list"), + /** Another Java object, such as a DOM Document or a class a payload is unmarshalled into. */ + POJO("pojo"), + /** The body as it was before the step: for the body after a step only. */ + UNCHANGED("unchanged"), + /** Any body: for the bodies a step needs only. */ + ANY("any"), + /** + * The body depends on what the other system sends, or on a class the user configures: tooling must not guess + * it. + */ + UNKNOWN("unknown"); + + private final String value; + + Carrier(String value) { + this.value = value; + } + + /** + * The name of the carrier, as the catalog has it. + */ + public String getValue() { + return value; + } + } +} diff --git a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyTypes.java b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyTypes.java new file mode 100644 index 0000000000000..485ac6c17c7d8 --- /dev/null +++ b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyTypes.java @@ -0,0 +1,105 @@ +/* + * 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.spi; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The message body a component, data format or language works with: the body it needs, and the body it leaves after it. + * The build carries it into the catalog, so tooling can say what the body is after a step without running the route: + * the validators, the catalog tools and the documentation. + *

+ * Put it on the endpoint class (the class with {@link UriEndpoint}), the data format class or the language class. A + * subclass does not have the body types of its superclass, as it may change the body: it declares its own. + *

+ * Each side that is given says what the body is with the default options. A side that is not given is not known, and + * tooling must not guess it. A side whose body depends on what the other system sends, or on a class the user + * configures, says {@link BodyType.Carrier#UNKNOWN}. + *

+ * For example the file component: the consumer gives the file it read, the producer writes text, bytes, a stream or a + * file, and leaves the body as it was: + * + *

+ * @BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, description = "The file as read"),
+ *            producerIn = @BodyType({ Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }),
+ *            producerOut = @BodyType(Carrier.UNCHANGED))
+ * 
+ * + * @since 4.24 + */ +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Target({ ElementType.TYPE }) +public @interface BodyTypes { + + /** + * The body of the message the consumer creates. + */ + BodyType consumerOut() default @BodyType; + + /** + * The bodies a consumer that answers the caller can reply with: the body the route ends with, such as the response + * of an HTTP server. + */ + BodyType consumerReply() default @BodyType; + + /** + * The bodies the producer can send or write. + */ + BodyType producerIn() default @BodyType; + + /** + * The body after the producer: {@link BodyType.Carrier#UNCHANGED} when it leaves the body as it was, otherwise what + * it sets, such as the response of a call. + */ + BodyType producerOut() default @BodyType; + + /** + * The bodies a data format can marshal. + */ + BodyType marshalIn() default @BodyType; + + /** + * The body after marshal. + */ + BodyType marshalOut() default @BodyType; + + /** + * The bodies a data format can unmarshal. + */ + BodyType unmarshalIn() default @BodyType; + + /** + * The body after unmarshal. + */ + BodyType unmarshalOut() default @BodyType; + + /** + * The bodies the expressions of a language can read. + */ + BodyType expressionIn() default @BodyType; + + /** + * The result of an expression of a language, which becomes the body in setBody and transform. + */ + BodyType expressionOut() default @BodyType; + +} From 09db3bec9a3b4ff8c43b67a0306b898cf9eff11d Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 14:14:33 +0200 Subject: [PATCH 02/25] CAMEL-24961: camel-catalog - the body types of platform-http, rest, ftp, jms, kafka, aws2-sqs, the csv, jacksonXml and yaml data formats, and the languages The second slice of the catalog body types: - components: platform-http, rest (and the rest-openapi consumer), ftp, ftps, sftp, jms, activemq, activemq6, amqp, kafka, aws2-sqs, log, mock, scheduler, quartz; - data formats: csv, jacksonXml, snakeYaml; - languages: simple, constant, jsonpath, xpath, groovy, jq. Each value is read from the code that sets the body, and checked against the body types the message history recorded when the tests of the modules and reference routes ran (the ftp integration tests included). camel_catalog_doc gives the body types a line per side, and its answer is cut at 18000 characters instead of 16000, so the four sides of the jms components leave the options a limit asks for room. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../camel/catalog/components/activemq.json | 6 ++ .../camel/catalog/components/activemq6.json | 6 ++ .../apache/camel/catalog/components/amqp.json | 6 ++ .../camel/catalog/components/aws2-sqs.json | 5 ++ .../apache/camel/catalog/components/ftp.json | 5 ++ .../apache/camel/catalog/components/ftps.json | 5 ++ .../apache/camel/catalog/components/jms.json | 6 ++ .../camel/catalog/components/kafka.json | 5 ++ .../apache/camel/catalog/components/log.json | 4 ++ .../apache/camel/catalog/components/mock.json | 4 ++ .../catalog/components/platform-http.json | 4 ++ .../camel/catalog/components/quartz.json | 3 + .../catalog/components/rest-openapi.json | 2 + .../apache/camel/catalog/components/rest.json | 6 ++ .../camel/catalog/components/scheduler.json | 3 + .../apache/camel/catalog/components/sftp.json | 5 ++ .../apache/camel/catalog/dataformats/csv.json | 6 ++ .../camel/catalog/dataformats/jacksonXml.json | 6 ++ .../camel/catalog/dataformats/snakeYaml.json | 6 ++ .../camel/catalog/languages/constant.json | 3 + .../camel/catalog/languages/groovy.json | 4 ++ .../apache/camel/catalog/languages/jq.json | 4 ++ .../camel/catalog/languages/jsonpath.json | 4 ++ .../camel/catalog/languages/simple.json | 4 ++ .../apache/camel/catalog/languages/xpath.json | 4 ++ .../camel/component/activemq/activemq.json | 6 ++ .../component/activemq/ActiveMQEndpoint.java | 39 +++++++++++++ .../camel/component/activemq6/activemq6.json | 6 ++ .../component/activemq6/ActiveMQEndpoint.java | 39 +++++++++++++ .../org/apache/camel/component/amqp/amqp.json | 6 ++ .../camel/component/amqp/AMQPEndpoint.java | 39 +++++++++++++ .../camel/component/aws2/sqs/aws2-sqs.json | 5 ++ .../component/aws2/sqs/Sqs2Endpoint.java | 27 +++++++++ .../org/apache/camel/dataformat/csv/csv.json | 6 ++ .../camel/dataformat/csv/CsvDataFormat.java | 13 +++++ .../camel/component/file/remote/ftp.json | 5 ++ .../camel/component/file/remote/ftps.json | 5 ++ .../camel/component/file/remote/sftp.json | 5 ++ .../component/file/remote/FtpEndpoint.java | 17 ++++++ .../component/file/remote/FtpsEndpoint.java | 17 ++++++ .../component/file/remote/SftpEndpoint.java | 17 ++++++ .../apache/camel/language/groovy/groovy.json | 4 ++ .../camel/language/groovy/GroovyLanguage.java | 5 ++ .../component/jacksonxml/jacksonXml.json | 6 ++ .../jacksonxml/JacksonXMLDataFormat.java | 14 +++++ .../org/apache/camel/component/jms/jms.json | 6 ++ .../camel/component/jms/JmsEndpoint.java | 39 +++++++++++++ .../org/apache/camel/language/jq/jq.json | 4 ++ .../apache/camel/language/jq/JqLanguage.java | 8 +++ .../org/apache/camel/jsonpath/jsonpath.json | 4 ++ .../camel/jsonpath/JsonPathLanguage.java | 12 ++++ .../apache/camel/component/kafka/kafka.json | 5 ++ .../camel/component/kafka/KafkaEndpoint.java | 18 ++++++ .../org/apache/camel/component/log/log.json | 4 ++ .../camel/component/log/LogEndpoint.java | 4 ++ .../org/apache/camel/component/mock/mock.json | 4 ++ .../camel/component/mock/MockEndpoint.java | 4 ++ .../platform/http/platform-http.json | 4 ++ .../platform/http/PlatformHttpEndpoint.java | 13 +++++ .../apache/camel/component/quartz/quartz.json | 3 + .../component/quartz/QuartzEndpoint.java | 4 ++ .../component/rest/openapi/rest-openapi.json | 2 + .../rest/openapi/RestOpenApiEndpoint.java | 12 +++- .../org/apache/camel/component/rest/rest.json | 6 ++ .../camel/component/rest/RestEndpoint.java | 24 ++++++++ .../camel/component/scheduler/scheduler.json | 3 + .../scheduler/SchedulerEndpoint.java | 4 ++ .../camel/component/snakeyaml/snakeYaml.json | 6 ++ .../snakeyaml/SnakeYAMLDataFormat.java | 10 ++++ .../apache/camel/language/xpath/xpath.json | 4 ++ .../camel/language/xpath/XPathLanguage.java | 16 ++++++ .../camel/language/constant/constant.json | 3 + .../apache/camel/language/simple/simple.json | 4 ++ .../language/constant/ConstantLanguage.java | 6 ++ .../camel/language/simple/SimpleLanguage.java | 7 +++ .../pages/camel-4x-upgrade-guide-4_24.adoc | 2 +- .../modules/ROOT/pages/camel-jbang-mcp.adoc | 7 ++- .../jbang/core/commands/ai/CatalogDocs.java | 56 ++++++++++++++++--- .../core/commands/ai/CatalogDocsTest.java | 28 ++++++---- 79 files changed, 710 insertions(+), 23 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/activemq.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/activemq.json index e0b80d458e33e..486cc84e783d9 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/activemq.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/activemq.json @@ -160,6 +160,12 @@ "CamelJmsMessageType": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "org.apache.camel.component.jms.JmsMessageType", "enum": [ "Bytes", "Map", "Object", "Stream", "Text", "Blob" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message type.", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_MESSAGE_TYPE" }, "CamelJmsRequestTimeout": { "index": 17, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds).", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_REQUEST_TIMEOUT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "map", "stream", "null" ], "dependsOn": [ "messageConverter", "transferExchange" ], "byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.jms.Message" }, { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", "stream", "pojo", "null" ] } ], "description": "By the JMS message received: a String for a TextMessage, a byte array for a BytesMessage, a Map for a MapMessage, a stream for a StreamMessage; an ObjectMessage only with objectMessageEnabled" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "The reply, sent as the producer sends a message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage; a Map as a MapMessage. Another Serializable object fails unless objectMessageEnabled" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) gets the body of the reply, as the consumer gives it" } + }, "properties": { "destinationType": { "index": 0, "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "queue", "topic", "temp-queue", "temp-topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" }, "destinationName": { "index": 1, "kind": "path", "displayName": "Destination Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the queue or topic to use as destination" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/activemq6.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/activemq6.json index 99e6755d4daf3..a24c009644694 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/activemq6.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/activemq6.json @@ -160,6 +160,12 @@ "CamelJmsMessageType": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "org.apache.camel.component.jms.JmsMessageType", "enum": [ "Bytes", "Map", "Object", "Stream", "Text", "Blob" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message type.", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_MESSAGE_TYPE" }, "CamelJmsRequestTimeout": { "index": 17, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds).", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_REQUEST_TIMEOUT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "map", "stream", "null" ], "dependsOn": [ "messageConverter", "transferExchange" ], "byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.jms.Message" }, { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", "stream", "pojo", "null" ] } ], "description": "By the JMS message received: a String for a TextMessage, a byte array for a BytesMessage, a Map for a MapMessage, a stream for a StreamMessage; an ObjectMessage only with objectMessageEnabled" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "The reply, sent as the producer sends a message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage; a Map as a MapMessage. Another Serializable object fails unless objectMessageEnabled" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) gets the body of the reply, as the consumer gives it" } + }, "properties": { "destinationType": { "index": 0, "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "queue", "topic", "temp-queue", "temp-topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" }, "destinationName": { "index": 1, "kind": "path", "displayName": "Destination Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the queue or topic to use as destination" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/amqp.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/amqp.json index aa458bcd193d6..8557ccf657541 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/amqp.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/amqp.json @@ -166,6 +166,12 @@ "CamelJmsMessageType": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "org.apache.camel.component.jms.JmsMessageType", "enum": [ "Bytes", "Map", "Object", "Stream", "Text", "Blob" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message type.", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_MESSAGE_TYPE" }, "CamelJmsRequestTimeout": { "index": 17, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds).", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_REQUEST_TIMEOUT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "map", "stream", "null" ], "dependsOn": [ "messageConverter", "transferExchange" ], "byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.jms.Message" }, { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", "stream", "pojo", "null" ] } ], "description": "By the JMS message received: a String for a TextMessage, a byte array for a BytesMessage, a Map for a MapMessage, a stream for a StreamMessage; an ObjectMessage only with objectMessageEnabled" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "The reply, sent as the producer sends a message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage; a Map as a MapMessage. Another Serializable object fails unless objectMessageEnabled" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) gets the body of the reply, as the consumer gives it" } + }, "properties": { "destinationType": { "index": 0, "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "queue", "topic", "temp-queue", "temp-topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" }, "destinationName": { "index": 1, "kind": "path", "displayName": "Destination Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the queue or topic to use as destination" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sqs.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sqs.json index 71cc592888ed6..8ff172f1e1f3b 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sqs.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sqs.json @@ -93,6 +93,11 @@ "CamelAwsSqsFailedMessageCount": { "index": 12, "kind": "header", "displayName": "", "group": "sendBatchMessage", "label": "sendBatchMessage", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of failed messages in a batch send operation.", "constantName": "org.apache.camel.component.aws2.sqs.Sqs2Constants#FAILED_MESSAGE_COUNT" }, "CamelAwsSqsSuccessfulMessageCount": { "index": 13, "kind": "header", "displayName": "", "group": "sendBatchMessage", "label": "sendBatchMessage", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of successful messages in a batch send operation.", "constantName": "org.apache.camel.component.aws2.sqs.Sqs2Constants#SUCCESSFUL_MESSAGE_COUNT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The body of the SQS message" }, + "producerIn": { "carriers": [ "text" ], "byOption": [ { "option": "operation", "value": "sendBatchMessage", "carriers": [ "list", "text" ] } ], "description": "The body of the message to send, as text, so a Map or a POJO is sent as its toString(): marshal it first. sendBatchMessage takes a List of text, or text that batchSeparator splits" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "sendBatchMessage", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse" }, { "option": "operation", "value": "deleteMessage", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.DeleteMessageResponse" }, { "option": "operation", "value": "listQueues", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.ListQueuesResponse" }, { "option": "operation", "value": "purgeQueue", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.PurgeQueueResponse" }, { "option": "operation", "value": "deleteQueue", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.DeleteQueueResponse" } ], "description": "Unchanged for a send, with the id of the message in a header; the response of the AWS SDK for the other operations" } + }, "properties": { "queueNameOrArn": { "index": 0, "kind": "path", "displayName": "Queue Name Or Arn", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Queue name or ARN" }, "amazonAWSHost": { "index": 1, "kind": "parameter", "displayName": "Amazon AWSHost", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "amazonaws.com", "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The hostname of the Amazon AWS cloud." }, 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 e56b6813c06bd..8d0a3be6738aa 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 @@ -50,6 +50,11 @@ "CamelFtpReplyCode": { "index": 15, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply code", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_CODE" }, "CamelFtpReplyString": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply string", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_STRING" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "file" ], "dependsOn": [ "preMove" ], "byOption": [ { "option": "streamDownload", "value": "true", "carriers": [ "stream" ] }, { "option": "download", "value": "false", "carriers": [ "null" ] } ], "description": "The file as read: a RemoteFile, which converts to text, bytes or a stream; a stream with streamDownload; with preMove its content, a byte array" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "What converts to an InputStream: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.FtpConfiguration", "configurationField": "configuration", "description": "Hostname of the FTP server" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.FtpConfiguration", "configurationField": "configuration", "description": "Port of the FTP server" }, 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 075f91d010d24..ba1fade434f6b 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 @@ -51,6 +51,11 @@ "CamelFtpReplyCode": { "index": 15, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply code", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_CODE" }, "CamelFtpReplyString": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply string", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_STRING" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "file" ], "dependsOn": [ "preMove" ], "byOption": [ { "option": "streamDownload", "value": "true", "carriers": [ "stream" ] }, { "option": "download", "value": "false", "carriers": [ "null" ] } ], "description": "The file as read: a RemoteFile, which converts to text, bytes or a stream; a stream with streamDownload; with preMove its content, a byte array" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "What converts to an InputStream: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.FtpsConfiguration", "configurationField": "configuration", "description": "Hostname of the FTP server" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.FtpsConfiguration", "configurationField": "configuration", "description": "Port of the FTP server" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jms.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jms.json index 7307e4f146f23..43327061d9863 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jms.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jms.json @@ -154,6 +154,12 @@ "CamelJmsMessageType": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "org.apache.camel.component.jms.JmsMessageType", "enum": [ "Bytes", "Map", "Object", "Stream", "Text", "Blob" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message type.", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_MESSAGE_TYPE" }, "CamelJmsRequestTimeout": { "index": 17, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds).", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_REQUEST_TIMEOUT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "map", "stream", "null" ], "dependsOn": [ "messageConverter", "transferExchange" ], "byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.jms.Message" }, { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", "stream", "pojo", "null" ] } ], "description": "By the JMS message received: a String for a TextMessage, a byte array for a BytesMessage, a Map for a MapMessage, a stream for a StreamMessage; an ObjectMessage only with objectMessageEnabled" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "The reply, sent as the producer sends a message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage; a Map as a MapMessage. Another Serializable object fails unless objectMessageEnabled" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) gets the body of the reply, as the consumer gives it" } + }, "properties": { "destinationType": { "index": 0, "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "queue", "topic", "temp-queue", "temp-topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" }, "destinationName": { "index": 1, "kind": "path", "displayName": "Destination Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the queue or topic to use as destination" }, 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 f40e398b911ba..d1dafe51f2f12 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 @@ -169,6 +169,11 @@ "CamelKafkaRecordMeta": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "List", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The metadata (only configured if recordMetadata endpoint parameter is true)", "constantName": "org.apache.camel.component.kafka.KafkaConstants#KAFKA_RECORD_META" }, "CamelKafkaManualCommit": { "index": 12, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "org.apache.camel.component.kafka.consumer.KafkaManualCommit", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Can be used for forcing manual offset commit when using Kafka consumer.", "constantName": "org.apache.camel.component.kafka.KafkaConstants#MANUAL_COMMIT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "null" ], "dependsOn": [ "valueDeserializer" ], "byOption": [ { "option": "valueDeserializer", "value": "org.apache.kafka.common.serialization.ByteArrayDeserializer", "carriers": [ "bytes", "null" ], "javaType": "byte[]" }, { "option": "batching", "value": "true", "carriers": [ "list" ] } ], "description": "The value of the record: a String with the default valueDeserializer (StringDeserializer), null for a tombstone. With batching, a List of the exchanges of the records" }, + "producerIn": { "carriers": [ "any" ], "dependsOn": [ "valueSerializer" ], "description": "The value of the record, converted for the valueSerializer: text with the default StringSerializer, so a Map or a POJO is sent as its toString(): marshal it first. With useIterator, an Iterable or an Iterator is sent as one record per element" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Name of the topic to use. On the consumer you can use comma to separate multiple topics. A producer can only send a message to a single topic." }, "additionalProperties": { "index": 1, "kind": "parameter", "displayName": "Additional Properties", "group": "common", "label": "common", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "additionalProperties.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Sets additional properties for either kafka consumer or kafka producer in case they can't be set directly on the camel configurations (e.g.: new Kafka properties that are not reflected yet in Camel configurations), the properties have to be prefixed with additionalProperties., e.g.: additionalProperties.transactional.id=12345&additionalProperties.schema.registry.url=http:\/\/localhost:8811\/avro. If the properties are set in the application.properties file, they must be prefixed with camel.component.kafka.additional-properties (camel.component.kafka-share.additional-properties for the Kafka Share component) followed by the property name enclosed in square brackets, for example the delivery.timeout.ms property in square brackets. This is a multi-value option with prefix: additionalProperties." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/log.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/log.json index 1780d6316af2e..bf19483c839cb 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/log.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/log.json @@ -30,6 +30,10 @@ "autowiredEnabled": { "index": 2, "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." }, "exchangeFormatter": { "index": 3, "kind": "property", "displayName": "Exchange Formatter", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExchangeFormatter", "deprecated": false, "autowired": true, "secret": false, "description": "Sets a custom ExchangeFormatter to convert the Exchange to a String suitable for logging. If not specified, we default to DefaultExchangeFormatter." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "loggerName": { "index": 0, "kind": "path", "displayName": "Logger Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the logging category to use" }, "groupActiveOnly": { "index": 1, "kind": "parameter", "displayName": "Group Active Only", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "If true, will hide stats when no new messages have been received for a time interval, if false, show stats regardless of message traffic." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mock.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mock.json index eadcc424ddeb2..4982ad8453e7f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mock.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mock.json @@ -30,6 +30,10 @@ "autowiredEnabled": { "index": 2, "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." }, "exchangeFormatter": { "index": 3, "kind": "property", "displayName": "Exchange Formatter", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExchangeFormatter", "deprecated": false, "autowired": true, "secret": false, "description": "To use a custom ExchangeFormatter to format the Exchange into a String suitable for logging." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of mock endpoint" }, "assertPeriod": { "index": 1, "kind": "parameter", "displayName": "Assert Period", "group": "producer", "label": "producer", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a grace period after which the mock will re-assert to ensure the preliminary assertion is still valid. This is used, for example, to assert that exactly a number of messages arrive. For example, if the expected count was set to 5, then the assertion is satisfied when five or more messages arrive. To ensure that exactly 5 messages arrive, then you would need to wait a little period to ensure no further message arrives. This is what you can use this method for. By default, this period is disabled." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json index e60f0367259fb..3c00abc0f66aa 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json @@ -33,6 +33,10 @@ "engine": { "index": 5, "kind": "property", "displayName": "Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.spi.PlatformHttpEngine", "deprecated": false, "autowired": false, "secret": false, "description": "An HTTP Server engine implementation to serve the requests" }, "headerFilterStrategy": { "index": 6, "kind": "property", "displayName": "Header Filter Strategy", "group": "filter", "label": "filter", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "bytes", "null", "map", "file" ], "byOption": [ { "option": "useBodyHandler", "value": "false", "carriers": [ "pojo" ] } ], "description": "The request body: the stream cache with the Vert.x engine, a byte array with Spring Boot; null for a request without a body, such as a GET; a Map of the fields of a form (populateBodyWithForm); a File for an upload" }, + "consumerReply": { "carriers": [ "null", "text", "bytes", "stream" ], "description": "The response body: text, bytes, a stream or no body. A Map or a List fails: marshal it first" } + }, "properties": { "path": { "index": 0, "kind": "path", "displayName": "Path", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The path under which this endpoint serves the HTTP requests, for proxy use 'proxy'" }, "consumes": { "index": 1, "kind": "parameter", "displayName": "Consumes", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type this endpoint accepts as an input, such as application\/xml or application\/json. null or *\/* mean no restriction." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/quartz.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/quartz.json index d56eb70d9f853..8b8cc7acc2acb 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/quartz.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/quartz.json @@ -37,6 +37,9 @@ "autoStartScheduler": { "index": 10, "kind": "property", "displayName": "Auto Start Scheduler", "group": "scheduler", "label": "scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started. This option is default true" }, "interruptJobsOnShutdown": { "index": 11, "kind": "property", "displayName": "Interrupt Jobs On Shutdown", "group": "scheduler", "label": "scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to interrupt jobs on shutdown, which forces the scheduler to shut down quicker and attempt to interrupt any running jobs. If this is enabled, then any running jobs can fail due to being interrupted. When a job is interrupted then Camel will mark the exchange to stop to continue routing and set java.util.concurrent.RejectedExecutionException as caused exception. Therefore, use this with care, as its often better to allow Camel jobs to complete and shutdown gracefully." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "description": "No body: the message only starts the route" } + }, "properties": { "groupName": { "index": 0, "kind": "path", "displayName": "Group Name", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Camel", "description": "The quartz group name to use. The combination of group name and trigger name should be unique." }, "triggerName": { "index": 1, "kind": "path", "displayName": "Trigger Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The quartz trigger name to use. The combination of group name and trigger name should be unique." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json index 22417ab779dfc..f175ff957c19b 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-openapi.json @@ -47,6 +47,8 @@ "useGlobalSslContextParameters": { "index": 20, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." } }, "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "bytes", "null", "map", "file" ], "dependsOn": [ "consumerComponentName" ], "description": "The request body as the HTTP consumer gives it (platform-http by default). With the json binding mode of the rest configuration, the object of the schema (bindingPackageScan), or a Map or a List" }, + "consumerReply": { "carriers": [ "null", "text", "bytes", "stream" ], "dependsOn": [ "consumerComponentName" ], "description": "The response body as the HTTP consumer writes it. With the json binding mode of the rest configuration, any object, which the binding writes as JSON" }, "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "componentName" ], "description": "The request body of the operation, which the http component sends: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, "producerOut": { "carriers": [ "bytes", "stream", "null" ], "dependsOn": [ "componentName" ], "description": "The response body, as the http component gives it: a byte array or the stream cache; null for a response without a body" } }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest.json index 041ff7467c2e6..8ad7a7dbc0771 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest.json @@ -43,6 +43,12 @@ "Accept": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The media type such as: 'text\/xml', or 'application\/json' this REST service accepts.", "constantName": "org.apache.camel.component.rest.RestConstants#ACCEPT" }, "CamelHttpResponseCode": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The http response code", "constantName": "org.apache.camel.component.rest.RestConstants#HTTP_RESPONSE_CODE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "bytes", "null", "map", "file" ], "dependsOn": [ "consumerComponentName" ], "byOption": [ { "option": "bindingMode", "value": "json", "carriers": [ "map", "list", "pojo" ] } ], "description": "The request body as the HTTP consumer gives it (platform-http by default). With bindingMode json, the object of inType, or a Map or a List without inType" }, + "consumerReply": { "carriers": [ "null", "text", "bytes", "stream" ], "dependsOn": [ "consumerComponentName" ], "byOption": [ { "option": "bindingMode", "value": "json", "carriers": [ "any" ] } ], "description": "The response body as the HTTP consumer writes it. With bindingMode json, any object, which the binding writes as JSON" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "producerComponentName" ], "byOption": [ { "option": "bindingMode", "value": "json", "carriers": [ "any" ] } ], "description": "The request body the HTTP producer sends (the http component by default). With bindingMode json, any object, which the binding writes as JSON" }, + "producerOut": { "carriers": [ "bytes", "stream", "null" ], "dependsOn": [ "producerComponentName", "outType" ], "description": "The response body as the HTTP producer gives it; with bindingMode json and outType, an object of outType" } + }, "properties": { "method": { "index": 0, "kind": "path", "displayName": "Method", "group": "common", "label": "common", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "get", "post", "put", "delete", "patch", "head", "trace", "connect", "options" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "HTTP method to use." }, "path": { "index": 1, "kind": "path", "displayName": "Path", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The base path, can use * as path suffix to support wildcard HTTP route matching." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/scheduler.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/scheduler.json index 491fc0b24d373..83c5065eeca03 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/scheduler.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/scheduler.json @@ -34,6 +34,9 @@ "headers": { "CamelMessageTimestamp": { "index": 0, "kind": "header", "displayName": "", "group": "consumer", "label": "", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The timestamp of the message", "constantName": "org.apache.camel.component.scheduler.SchedulerConstants#MESSAGE_TIMESTAMP" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "description": "No body: the message only starts the route" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the scheduler" }, "includeMetadata": { "index": 1, "kind": "parameter", "displayName": "Include Metadata", "group": "consumer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to include metadata in the exchange such as fired time, timer name, timer count etc." }, 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 11096138d4192..a0471a76cb2f0 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 @@ -55,6 +55,11 @@ "CamelFtpReplyCode": { "index": 15, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply code", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_CODE" }, "CamelFtpReplyString": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply string", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_STRING" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "file" ], "dependsOn": [ "preMove" ], "byOption": [ { "option": "streamDownload", "value": "true", "carriers": [ "stream" ] }, { "option": "download", "value": "false", "carriers": [ "null" ] } ], "description": "The file as read: a RemoteFile, which converts to text, bytes or a stream; a stream with streamDownload; with preMove its content, a byte array" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "What converts to an InputStream: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.SftpConfiguration", "configurationField": "configuration", "description": "Hostname of the FTP server" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.SftpConfiguration", "configurationField": "configuration", "description": "Port of the FTP server" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/csv.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/csv.json index c1044cee0dd0c..6e696b52703e8 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/csv.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/csv.json @@ -15,6 +15,12 @@ "modelName": "csv", "modelJavaType": "org.apache.camel.model.dataformat.CsvDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list" ], "description": "One row as a Map, or the rows as a List (or an Iterator) of Maps or Lists" }, + "marshalOut": { "carriers": [ "stream" ], "format": "csv", "description": "The CSV in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "csv" }, + "unmarshalOut": { "carriers": [ "list" ], "dependsOn": [ "recordConverterRef" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "A List of the rows, each a List of its values; with useMaps or useOrderedMaps, a Map of the header names and the values" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "format": { "index": 1, "kind": "attribute", "displayName": "Format", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "DEFAULT", "EXCEL", "INFORMIX_UNLOAD", "INFORMIX_UNLOAD_CSV", "MONGODB_CSV", "MONGODB_TSV", "MYSQL", "ORACLE", "POSTGRESQL_CSV", "POSTGRESQL_TEXT", "RFC4180" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "DEFAULT", "description": "The format to use." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jacksonXml.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jacksonXml.json index 1eca4610e6271..e01c38e3002ee 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jacksonXml.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jacksonXml.json @@ -15,6 +15,12 @@ "modelName": "jacksonXml", "modelJavaType": "org.apache.camel.model.dataformat.JacksonXMLDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as XML. Text is written as an XML value, not as it is" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml" }, + "unmarshalOut": { "carriers": [ "map" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) of the XML; an object of the class unmarshalType names" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "xmlMapper": { "index": 1, "kind": "attribute", "displayName": "Xml Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing XmlMapper with the given id." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/snakeYaml.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/snakeYaml.json index cc69504fdca03..a24fa2186d37c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/snakeYaml.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/snakeYaml.json @@ -15,6 +15,12 @@ "modelName": "yaml", "modelJavaType": "org.apache.camel.model.dataformat.YAMLDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as YAML" }, + "marshalOut": { "carriers": [ "stream" ], "format": "yaml", "description": "The YAML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "yaml" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType" ], "description": "A Map (LinkedHashMap) for a mapping, a List (ArrayList) for a sequence; a document that is a single value gives that value" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "library": { "index": 1, "kind": "attribute", "displayName": "Library", "group": "common", "required": false, "type": "enum", "javaType": "org.apache.camel.model.dataformat.YAMLLibrary", "enum": [ "SnakeYAML" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "SnakeYAML", "description": "Which yaml library to use. By default it is SnakeYAML." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/constant.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/constant.json index e1c1c40cb2ea8..9889e6d5b957e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/constant.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/constant.json @@ -15,6 +15,9 @@ "modelName": "constant", "modelJavaType": "org.apache.camel.model.language.ConstantExpression" }, + "bodyTypes": { + "expressionOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultType" ], "description": "The text as it is written; resource:classpath:name loads the text of the resource" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/groovy.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/groovy.json index db276ac056830..fd58e1de9825c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/groovy.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/groovy.json @@ -15,6 +15,10 @@ "modelName": "groovy", "modelJavaType": "org.apache.camel.model.language.GroovyExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the script returns" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jq.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jq.json index 8d658803476a5..781f11d2f1794 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jq.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jq.json @@ -15,6 +15,10 @@ "modelName": "jq", "modelJavaType": "org.apache.camel.model.language.JqExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "format": "json", "description": "JSON as text, bytes, a stream or a file, or a Map" }, + "expressionOut": { "carriers": [ "pojo", "list", "null" ], "dependsOn": [ "resultType" ], "description": "A JsonNode; a List of JsonNode when the filter gives several, null when it gives none" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jsonpath.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jsonpath.json index af55d48104eaa..e3aeffd210b31 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jsonpath.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jsonpath.json @@ -15,6 +15,10 @@ "modelName": "jsonpath", "modelJavaType": "org.apache.camel.model.language.JsonPathExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "JSON as text, bytes, a stream or a file, or parsed: a Map or a List. A POJO is read through Jackson" }, + "expressionOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "writeAsString", "value": "true", "carriers": [ "text", "list" ] } ], "description": "The value the path selects: a Map for an object, a List for an array or for a path with a wildcard or a filter, otherwise text, a number or a boolean" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json index 6de66be485c43..5648229337930 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/simple.json @@ -15,6 +15,10 @@ "modelName": "simple", "modelJavaType": "org.apache.camel.model.language.SimpleExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ] }, + "expressionOut": { "carriers": [ "unknown" ], "description": "A text with functions gives text. A single function, such as ${body} or ${header.foo}, gives its value as it is" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xpath.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xpath.json index 0a6a706898992..e7e50b9357a1e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xpath.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xpath.json @@ -15,6 +15,10 @@ "modelName": "xpath", "modelJavaType": "org.apache.camel.model.language.XPathExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "XML as text, bytes, a stream or a file, or a DOM" }, + "expressionOut": { "carriers": [ "pojo" ], "javaType": "org.w3c.dom.NodeList", "dependsOn": [ "resultType" ], "byOption": [ { "option": "resultQName", "value": "STRING", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "resultQName", "value": "NUMBER", "carriers": [ "value" ], "javaType": "java.lang.Double" }, { "option": "resultQName", "value": "BOOLEAN", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "resultQName", "value": "NODE", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Node" } ], "description": "The nodes the expression selects" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-activemq/src/generated/resources/META-INF/org/apache/camel/component/activemq/activemq.json b/components/camel-activemq/src/generated/resources/META-INF/org/apache/camel/component/activemq/activemq.json index e0b80d458e33e..486cc84e783d9 100644 --- a/components/camel-activemq/src/generated/resources/META-INF/org/apache/camel/component/activemq/activemq.json +++ b/components/camel-activemq/src/generated/resources/META-INF/org/apache/camel/component/activemq/activemq.json @@ -160,6 +160,12 @@ "CamelJmsMessageType": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "org.apache.camel.component.jms.JmsMessageType", "enum": [ "Bytes", "Map", "Object", "Stream", "Text", "Blob" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message type.", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_MESSAGE_TYPE" }, "CamelJmsRequestTimeout": { "index": 17, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds).", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_REQUEST_TIMEOUT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "map", "stream", "null" ], "dependsOn": [ "messageConverter", "transferExchange" ], "byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.jms.Message" }, { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", "stream", "pojo", "null" ] } ], "description": "By the JMS message received: a String for a TextMessage, a byte array for a BytesMessage, a Map for a MapMessage, a stream for a StreamMessage; an ObjectMessage only with objectMessageEnabled" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "The reply, sent as the producer sends a message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage; a Map as a MapMessage. Another Serializable object fails unless objectMessageEnabled" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) gets the body of the reply, as the consumer gives it" } + }, "properties": { "destinationType": { "index": 0, "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "queue", "topic", "temp-queue", "temp-topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" }, "destinationName": { "index": 1, "kind": "path", "displayName": "Destination Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the queue or topic to use as destination" }, diff --git a/components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQEndpoint.java b/components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQEndpoint.java index c2c8432f5ff0f..1e0ca6e7876f6 100644 --- a/components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQEndpoint.java +++ b/components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.component.jms.JmsComponent; import org.apache.camel.component.jms.JmsConfiguration; import org.apache.camel.component.jms.JmsEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -36,6 +39,42 @@ @UriEndpoint(firstVersion = "1.0.0", extendsScheme = "jms", scheme = "activemq", title = "ActiveMQ 5.x", syntax = "activemq:destinationType:destinationName", category = { Category.MESSAGING }) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.NULL }, + dependsOn = { "messageConverter", "transferExchange" }, + byOption = { + @BodyType.When(option = "mapJmsMessage", value = "false", carrier = Carrier.POJO, + javaType = "jakarta.jms.Message"), + @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.MAP, + Carrier.STREAM, Carrier.POJO, Carrier.NULL }) }, + description = "By the JMS message received: a String for a TextMessage, a byte array for a" + + " BytesMessage, a Map for a MapMessage, a stream for a StreamMessage;" + + " an ObjectMessage only with objectMessageEnabled"), + consumerReply = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, + dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, + byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE, Carrier.MAP, Carrier.POJO }), + description = "The reply, sent as the producer sends a message"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, + dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, + byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE, Carrier.MAP, Carrier.POJO }), + description = "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage;" + + " a Map as a MapMessage. Another Serializable object fails unless" + + " objectMessageEnabled"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "exchangePattern", value = "InOnly", + carrier = Carrier.UNCHANGED), + @BodyType.When(option = "disableReplyTo", value = "true", + carrier = Carrier.UNCHANGED) }, + description = "Unchanged for a message that expects no reply (InOnly). A message that" + + " expects one (InOut) gets the body of the reply, as the consumer gives it")) public class ActiveMQEndpoint extends JmsEndpoint implements EndpointServiceLocation { @UriParam(multiValue = true, prefix = "destination.", label = "consumer,advanced") diff --git a/components/camel-activemq6/src/generated/resources/META-INF/org/apache/camel/component/activemq6/activemq6.json b/components/camel-activemq6/src/generated/resources/META-INF/org/apache/camel/component/activemq6/activemq6.json index 99e6755d4daf3..a24c009644694 100644 --- a/components/camel-activemq6/src/generated/resources/META-INF/org/apache/camel/component/activemq6/activemq6.json +++ b/components/camel-activemq6/src/generated/resources/META-INF/org/apache/camel/component/activemq6/activemq6.json @@ -160,6 +160,12 @@ "CamelJmsMessageType": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "org.apache.camel.component.jms.JmsMessageType", "enum": [ "Bytes", "Map", "Object", "Stream", "Text", "Blob" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message type.", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_MESSAGE_TYPE" }, "CamelJmsRequestTimeout": { "index": 17, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds).", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_REQUEST_TIMEOUT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "map", "stream", "null" ], "dependsOn": [ "messageConverter", "transferExchange" ], "byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.jms.Message" }, { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", "stream", "pojo", "null" ] } ], "description": "By the JMS message received: a String for a TextMessage, a byte array for a BytesMessage, a Map for a MapMessage, a stream for a StreamMessage; an ObjectMessage only with objectMessageEnabled" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "The reply, sent as the producer sends a message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage; a Map as a MapMessage. Another Serializable object fails unless objectMessageEnabled" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) gets the body of the reply, as the consumer gives it" } + }, "properties": { "destinationType": { "index": 0, "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "queue", "topic", "temp-queue", "temp-topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" }, "destinationName": { "index": 1, "kind": "path", "displayName": "Destination Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the queue or topic to use as destination" }, diff --git a/components/camel-activemq6/src/main/java/org/apache/camel/component/activemq6/ActiveMQEndpoint.java b/components/camel-activemq6/src/main/java/org/apache/camel/component/activemq6/ActiveMQEndpoint.java index cd3bed8b2bbaf..2ebf48a77856e 100644 --- a/components/camel-activemq6/src/main/java/org/apache/camel/component/activemq6/ActiveMQEndpoint.java +++ b/components/camel-activemq6/src/main/java/org/apache/camel/component/activemq6/ActiveMQEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.component.jms.JmsComponent; import org.apache.camel.component.jms.JmsConfiguration; import org.apache.camel.component.jms.JmsEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -36,6 +39,42 @@ @UriEndpoint(firstVersion = "4.7.0", extendsScheme = "jms", scheme = "activemq6", title = "ActiveMQ 6.x", syntax = "activemq6:destinationType:destinationName", category = { Category.MESSAGING }) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.NULL }, + dependsOn = { "messageConverter", "transferExchange" }, + byOption = { + @BodyType.When(option = "mapJmsMessage", value = "false", carrier = Carrier.POJO, + javaType = "jakarta.jms.Message"), + @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.MAP, + Carrier.STREAM, Carrier.POJO, Carrier.NULL }) }, + description = "By the JMS message received: a String for a TextMessage, a byte array for a" + + " BytesMessage, a Map for a MapMessage, a stream for a StreamMessage;" + + " an ObjectMessage only with objectMessageEnabled"), + consumerReply = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, + dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, + byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE, Carrier.MAP, Carrier.POJO }), + description = "The reply, sent as the producer sends a message"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, + dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, + byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE, Carrier.MAP, Carrier.POJO }), + description = "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage;" + + " a Map as a MapMessage. Another Serializable object fails unless" + + " objectMessageEnabled"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "exchangePattern", value = "InOnly", + carrier = Carrier.UNCHANGED), + @BodyType.When(option = "disableReplyTo", value = "true", + carrier = Carrier.UNCHANGED) }, + description = "Unchanged for a message that expects no reply (InOnly). A message that" + + " expects one (InOut) gets the body of the reply, as the consumer gives it")) public class ActiveMQEndpoint extends JmsEndpoint implements EndpointServiceLocation { @UriParam(multiValue = true, prefix = "destination.", label = "consumer,advanced") diff --git a/components/camel-amqp/src/generated/resources/META-INF/org/apache/camel/component/amqp/amqp.json b/components/camel-amqp/src/generated/resources/META-INF/org/apache/camel/component/amqp/amqp.json index aa458bcd193d6..8557ccf657541 100644 --- a/components/camel-amqp/src/generated/resources/META-INF/org/apache/camel/component/amqp/amqp.json +++ b/components/camel-amqp/src/generated/resources/META-INF/org/apache/camel/component/amqp/amqp.json @@ -166,6 +166,12 @@ "CamelJmsMessageType": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "org.apache.camel.component.jms.JmsMessageType", "enum": [ "Bytes", "Map", "Object", "Stream", "Text", "Blob" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message type.", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_MESSAGE_TYPE" }, "CamelJmsRequestTimeout": { "index": 17, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds).", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_REQUEST_TIMEOUT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "map", "stream", "null" ], "dependsOn": [ "messageConverter", "transferExchange" ], "byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.jms.Message" }, { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", "stream", "pojo", "null" ] } ], "description": "By the JMS message received: a String for a TextMessage, a byte array for a BytesMessage, a Map for a MapMessage, a stream for a StreamMessage; an ObjectMessage only with objectMessageEnabled" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "The reply, sent as the producer sends a message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage; a Map as a MapMessage. Another Serializable object fails unless objectMessageEnabled" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) gets the body of the reply, as the consumer gives it" } + }, "properties": { "destinationType": { "index": 0, "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "queue", "topic", "temp-queue", "temp-topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" }, "destinationName": { "index": 1, "kind": "path", "displayName": "Destination Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the queue or topic to use as destination" }, diff --git a/components/camel-amqp/src/main/java/org/apache/camel/component/amqp/AMQPEndpoint.java b/components/camel-amqp/src/main/java/org/apache/camel/component/amqp/AMQPEndpoint.java index e39ea41759d7e..9ed3d154c6132 100644 --- a/components/camel-amqp/src/main/java/org/apache/camel/component/amqp/AMQPEndpoint.java +++ b/components/camel-amqp/src/main/java/org/apache/camel/component/amqp/AMQPEndpoint.java @@ -18,6 +18,9 @@ import org.apache.camel.Category; import org.apache.camel.component.jms.JmsEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; /** @@ -28,6 +31,42 @@ */ @UriEndpoint(firstVersion = "1.2.0", scheme = "amqp", extendsScheme = "jms", title = "AMQP", syntax = "amqp:destinationType:destinationName", category = { Category.MESSAGING }) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.NULL }, + dependsOn = { "messageConverter", "transferExchange" }, + byOption = { + @BodyType.When(option = "mapJmsMessage", value = "false", carrier = Carrier.POJO, + javaType = "jakarta.jms.Message"), + @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.MAP, + Carrier.STREAM, Carrier.POJO, Carrier.NULL }) }, + description = "By the JMS message received: a String for a TextMessage, a byte array for a" + + " BytesMessage, a Map for a MapMessage, a stream for a StreamMessage;" + + " an ObjectMessage only with objectMessageEnabled"), + consumerReply = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, + dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, + byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE, Carrier.MAP, Carrier.POJO }), + description = "The reply, sent as the producer sends a message"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, + dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, + byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE, Carrier.MAP, Carrier.POJO }), + description = "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage;" + + " a Map as a MapMessage. Another Serializable object fails unless" + + " objectMessageEnabled"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "exchangePattern", value = "InOnly", + carrier = Carrier.UNCHANGED), + @BodyType.When(option = "disableReplyTo", value = "true", + carrier = Carrier.UNCHANGED) }, + description = "Unchanged for a message that expects no reply (InOnly). A message that" + + " expects one (InOut) gets the body of the reply, as the consumer gives it")) public class AMQPEndpoint extends JmsEndpoint { @Override diff --git a/components/camel-aws/camel-aws2-sqs/src/generated/resources/META-INF/org/apache/camel/component/aws2/sqs/aws2-sqs.json b/components/camel-aws/camel-aws2-sqs/src/generated/resources/META-INF/org/apache/camel/component/aws2/sqs/aws2-sqs.json index 71cc592888ed6..8ff172f1e1f3b 100644 --- a/components/camel-aws/camel-aws2-sqs/src/generated/resources/META-INF/org/apache/camel/component/aws2/sqs/aws2-sqs.json +++ b/components/camel-aws/camel-aws2-sqs/src/generated/resources/META-INF/org/apache/camel/component/aws2/sqs/aws2-sqs.json @@ -93,6 +93,11 @@ "CamelAwsSqsFailedMessageCount": { "index": 12, "kind": "header", "displayName": "", "group": "sendBatchMessage", "label": "sendBatchMessage", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of failed messages in a batch send operation.", "constantName": "org.apache.camel.component.aws2.sqs.Sqs2Constants#FAILED_MESSAGE_COUNT" }, "CamelAwsSqsSuccessfulMessageCount": { "index": 13, "kind": "header", "displayName": "", "group": "sendBatchMessage", "label": "sendBatchMessage", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of successful messages in a batch send operation.", "constantName": "org.apache.camel.component.aws2.sqs.Sqs2Constants#SUCCESSFUL_MESSAGE_COUNT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The body of the SQS message" }, + "producerIn": { "carriers": [ "text" ], "byOption": [ { "option": "operation", "value": "sendBatchMessage", "carriers": [ "list", "text" ] } ], "description": "The body of the message to send, as text, so a Map or a POJO is sent as its toString(): marshal it first. sendBatchMessage takes a List of text, or text that batchSeparator splits" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "sendBatchMessage", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse" }, { "option": "operation", "value": "deleteMessage", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.DeleteMessageResponse" }, { "option": "operation", "value": "listQueues", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.ListQueuesResponse" }, { "option": "operation", "value": "purgeQueue", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.PurgeQueueResponse" }, { "option": "operation", "value": "deleteQueue", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.DeleteQueueResponse" } ], "description": "Unchanged for a send, with the id of the message in a header; the response of the AWS SDK for the other operations" } + }, "properties": { "queueNameOrArn": { "index": 0, "kind": "path", "displayName": "Queue Name Or Arn", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Queue name or ARN" }, "amazonAWSHost": { "index": 1, "kind": "parameter", "displayName": "Amazon AWSHost", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "amazonaws.com", "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The hostname of the Amazon AWS cloud." }, diff --git a/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java b/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java index 14b3316f0e4e8..c4f5fe9575899 100644 --- a/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java +++ b/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java @@ -33,6 +33,9 @@ import org.apache.camel.clock.Clock; import org.apache.camel.component.aws2.sqs.client.Sqs2ClientFactory; import org.apache.camel.spi.*; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.support.MonotonicClock; import org.apache.camel.support.ResourceHelper; import org.apache.camel.support.ScheduledPollEndpoint; @@ -60,6 +63,30 @@ @UriEndpoint(firstVersion = "3.1.0", scheme = "aws2-sqs", title = "AWS Simple Queue Service (SQS)", syntax = "aws2-sqs:queueNameOrArn", category = { Category.CLOUD, Category.MESSAGING }, headersClass = Sqs2Constants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", + description = "The body of the SQS message"), + producerIn = @BodyType(value = Carrier.TEXT, + byOption = @BodyType.When(option = "operation", value = "sendBatchMessage", + carrier = { Carrier.LIST, Carrier.TEXT }), + description = "The body of the message to send, as text, so a Map or a POJO is sent as" + + " its toString(): marshal it first. sendBatchMessage takes a List of" + + " text, or text that batchSeparator splits"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + byOption = { + @BodyType.When(option = "operation", value = "sendBatchMessage", + carrier = Carrier.POJO, + javaType = "software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse"), + @BodyType.When(option = "operation", value = "deleteMessage", + carrier = Carrier.POJO, + javaType = "software.amazon.awssdk.services.sqs.model.DeleteMessageResponse"), + @BodyType.When(option = "operation", value = "listQueues", carrier = Carrier.POJO, + javaType = "software.amazon.awssdk.services.sqs.model.ListQueuesResponse"), + @BodyType.When(option = "operation", value = "purgeQueue", carrier = Carrier.POJO, + javaType = "software.amazon.awssdk.services.sqs.model.PurgeQueueResponse"), + @BodyType.When(option = "operation", value = "deleteQueue", carrier = Carrier.POJO, + javaType = "software.amazon.awssdk.services.sqs.model.DeleteQueueResponse") }, + description = "Unchanged for a send, with the id of the message in a header; the response" + + " of the AWS SDK for the other operations")) public class Sqs2Endpoint extends ScheduledPollEndpoint implements HeaderFilterStrategyAware, EndpointServiceLocation { private static final Logger LOG = LoggerFactory.getLogger(Sqs2Endpoint.class); diff --git a/components/camel-csv/src/generated/resources/META-INF/org/apache/camel/dataformat/csv/csv.json b/components/camel-csv/src/generated/resources/META-INF/org/apache/camel/dataformat/csv/csv.json index c1044cee0dd0c..6e696b52703e8 100644 --- a/components/camel-csv/src/generated/resources/META-INF/org/apache/camel/dataformat/csv/csv.json +++ b/components/camel-csv/src/generated/resources/META-INF/org/apache/camel/dataformat/csv/csv.json @@ -15,6 +15,12 @@ "modelName": "csv", "modelJavaType": "org.apache.camel.model.dataformat.CsvDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list" ], "description": "One row as a Map, or the rows as a List (or an Iterator) of Maps or Lists" }, + "marshalOut": { "carriers": [ "stream" ], "format": "csv", "description": "The CSV in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "csv" }, + "unmarshalOut": { "carriers": [ "list" ], "dependsOn": [ "recordConverterRef" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "A List of the rows, each a List of its values; with useMaps or useOrderedMaps, a Map of the header names and the values" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "format": { "index": 1, "kind": "attribute", "displayName": "Format", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "DEFAULT", "EXCEL", "INFORMIX_UNLOAD", "INFORMIX_UNLOAD_CSV", "MONGODB_CSV", "MONGODB_TSV", "MYSQL", "ORACLE", "POSTGRESQL_CSV", "POSTGRESQL_TEXT", "RFC4180" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "DEFAULT", "description": "The format to use." }, diff --git a/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java b/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java index 5e443a58c6444..3baa7fe3c30e7 100644 --- a/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java +++ b/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java @@ -21,6 +21,9 @@ import java.util.StringJoiner; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -36,6 +39,16 @@ * Autogeneration can be disabled. In this case, only the fields defined in csvConfig are written on the output. */ @Dataformat("csv") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.MAP, Carrier.LIST }, + description = "One row as a Map, or the rows as a List (or an Iterator) of Maps or Lists"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "csv", + description = "The CSV in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "csv"), + unmarshalOut = @BodyType(value = Carrier.LIST, dependsOn = "recordConverterRef", + byOption = @BodyType.When(option = "lazyLoad", value = "true", carrier = Carrier.LIST, + javaType = "java.util.Iterator"), + description = "A List of the rows, each a List of its values; with useMaps or" + + " useOrderedMaps, a Map of the header names and the values")) public class CsvDataFormat extends ServiceSupport implements DataFormat, DataFormatName { // CSV format options private CSVFormat csvFormat = CSVFormat.DEFAULT; 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 e56b6813c06bd..8d0a3be6738aa 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 @@ -50,6 +50,11 @@ "CamelFtpReplyCode": { "index": 15, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply code", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_CODE" }, "CamelFtpReplyString": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply string", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_STRING" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "file" ], "dependsOn": [ "preMove" ], "byOption": [ { "option": "streamDownload", "value": "true", "carriers": [ "stream" ] }, { "option": "download", "value": "false", "carriers": [ "null" ] } ], "description": "The file as read: a RemoteFile, which converts to text, bytes or a stream; a stream with streamDownload; with preMove its content, a byte array" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "What converts to an InputStream: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.FtpConfiguration", "configurationField": "configuration", "description": "Hostname of the FTP server" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.FtpConfiguration", "configurationField": "configuration", "description": "Port of the FTP server" }, 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 075f91d010d24..ba1fade434f6b 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 @@ -51,6 +51,11 @@ "CamelFtpReplyCode": { "index": 15, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply code", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_CODE" }, "CamelFtpReplyString": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply string", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_STRING" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "file" ], "dependsOn": [ "preMove" ], "byOption": [ { "option": "streamDownload", "value": "true", "carriers": [ "stream" ] }, { "option": "download", "value": "false", "carriers": [ "null" ] } ], "description": "The file as read: a RemoteFile, which converts to text, bytes or a stream; a stream with streamDownload; with preMove its content, a byte array" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "What converts to an InputStream: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.FtpsConfiguration", "configurationField": "configuration", "description": "Hostname of the FTP server" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.FtpsConfiguration", "configurationField": "configuration", "description": "Port of the FTP server" }, 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 11096138d4192..a0471a76cb2f0 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 @@ -55,6 +55,11 @@ "CamelFtpReplyCode": { "index": 15, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply code", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_CODE" }, "CamelFtpReplyString": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The FTP client reply string", "constantName": "org.apache.camel.component.file.remote.FtpConstants#FTP_REPLY_STRING" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "file" ], "dependsOn": [ "preMove" ], "byOption": [ { "option": "streamDownload", "value": "true", "carriers": [ "stream" ] }, { "option": "download", "value": "false", "carriers": [ "null" ] } ], "description": "The file as read: a RemoteFile, which converts to text, bytes or a stream; a stream with streamDownload; with preMove its content, a byte array" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "What converts to an InputStream: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.SftpConfiguration", "configurationField": "configuration", "description": "Hostname of the FTP server" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.remote.SftpConfiguration", "configurationField": "configuration", "description": "Port of the FTP server" }, diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpEndpoint.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpEndpoint.java index 6c0d8bae52b8a..2abdf1d757ba9 100644 --- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpEndpoint.java +++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpEndpoint.java @@ -33,6 +33,9 @@ import org.apache.camel.component.file.remote.RemoteFileConfiguration.PathSeparator; import org.apache.camel.component.file.remote.strategy.FtpProcessStrategyFactory; import org.apache.camel.component.file.strategy.FileMoveExistingStrategy; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ClassResolver; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -56,6 +59,20 @@ + "startingDirectoryMustHaveAccess,chmodDirectory,forceWrites,copyAndDeleteOnRenameFail," + "renameUsingCopy,synchronous") @ManagedResource(description = "Managed FtpEndpoint") +@BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, dependsOn = "preMove", + byOption = { + @BodyType.When(option = "streamDownload", value = "true", carrier = Carrier.STREAM), + @BodyType.When(option = "download", value = "false", carrier = Carrier.NULL) }, + description = "The file as read: a RemoteFile, which converts to text, bytes or a stream; a" + + " stream with streamDownload; with preMove its content, a byte array"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + byOption = @BodyType.When(option = "allowNullBody", value = "true", + carrier = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE }), + description = "What converts to an InputStream: text, bytes, a stream or a file. A Map or" + + " a List fails: marshal it first"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class FtpEndpoint extends RemoteFileEndpoint { private static final Logger LOG = LoggerFactory.getLogger(FtpEndpoint.class); diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpsEndpoint.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpsEndpoint.java index 37251328723b2..5a80fbc506799 100644 --- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpsEndpoint.java +++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpsEndpoint.java @@ -30,6 +30,9 @@ import org.apache.camel.Category; import org.apache.camel.api.management.ManagedResource; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -54,6 +57,20 @@ + "startingDirectoryMustHaveAccess,chmodDirectory,forceWrites,copyAndDeleteOnRenameFail," + "renameUsingCopy,synchronous") @ManagedResource(description = "Managed FtpsEndpoint") +@BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, dependsOn = "preMove", + byOption = { + @BodyType.When(option = "streamDownload", value = "true", carrier = Carrier.STREAM), + @BodyType.When(option = "download", value = "false", carrier = Carrier.NULL) }, + description = "The file as read: a RemoteFile, which converts to text, bytes or a stream; a" + + " stream with streamDownload; with preMove its content, a byte array"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + byOption = @BodyType.When(option = "allowNullBody", value = "true", + carrier = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE }), + description = "What converts to an InputStream: text, bytes, a stream or a file. A Map or" + + " a List fails: marshal it first"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class FtpsEndpoint extends FtpEndpoint { private static final Logger LOG = LoggerFactory.getLogger(FtpsEndpoint.class); diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpEndpoint.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpEndpoint.java index 7c3bda7a0e864..6ff2ab3c28e90 100644 --- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpEndpoint.java +++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.component.file.GenericFileProducer; import org.apache.camel.component.file.remote.strategy.SftpProcessStrategyFactory; import org.apache.camel.component.file.strategy.FileMoveExistingStrategy; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -37,6 +40,20 @@ + "directoryMustExist,extendedAttributes,probeContentType,startingDirectoryMustExist," + "startingDirectoryMustHaveAccess,forceWrites,copyAndDeleteOnRenameFail," + "renameUsingCopy,synchronous") +@BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, dependsOn = "preMove", + byOption = { + @BodyType.When(option = "streamDownload", value = "true", carrier = Carrier.STREAM), + @BodyType.When(option = "download", value = "false", carrier = Carrier.NULL) }, + description = "The file as read: a RemoteFile, which converts to text, bytes or a stream; a" + + " stream with streamDownload; with preMove its content, a byte array"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + byOption = @BodyType.When(option = "allowNullBody", value = "true", + carrier = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE }), + description = "What converts to an InputStream: text, bytes, a stream or a file. A Map or" + + " a List fails: marshal it first"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class SftpEndpoint extends RemoteFileEndpoint { @UriParam diff --git a/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/language/groovy/groovy.json b/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/language/groovy/groovy.json index db276ac056830..fd58e1de9825c 100644 --- a/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/language/groovy/groovy.json +++ b/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/language/groovy/groovy.json @@ -15,6 +15,10 @@ "modelName": "groovy", "modelJavaType": "org.apache.camel.model.language.GroovyExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in the variable body" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the script returns" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-groovy/src/main/java/org/apache/camel/language/groovy/GroovyLanguage.java b/components/camel-groovy/src/main/java/org/apache/camel/language/groovy/GroovyLanguage.java index 667bc5adb7fca..1fda88d90b5e1 100644 --- a/components/camel-groovy/src/main/java/org/apache/camel/language/groovy/GroovyLanguage.java +++ b/components/camel-groovy/src/main/java/org/apache/camel/language/groovy/GroovyLanguage.java @@ -32,6 +32,9 @@ import org.apache.camel.Ordered; import org.apache.camel.RuntimeCamelException; import org.apache.camel.Service; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.CamelEvent; import org.apache.camel.spi.CompilePreProcessor; import org.apache.camel.spi.EventNotifier; @@ -49,6 +52,8 @@ import org.slf4j.LoggerFactory; @Language("groovy") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, description = "The body as it is, in the variable body"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, description = "What the script returns")) public class GroovyLanguage extends TypedLanguageSupport implements ScriptingLanguage, Service { private static final Logger LOG = LoggerFactory.getLogger(GroovyLanguage.class); diff --git a/components/camel-jacksonxml/src/generated/resources/META-INF/org/apache/camel/component/jacksonxml/jacksonXml.json b/components/camel-jacksonxml/src/generated/resources/META-INF/org/apache/camel/component/jacksonxml/jacksonXml.json index 1eca4610e6271..e01c38e3002ee 100644 --- a/components/camel-jacksonxml/src/generated/resources/META-INF/org/apache/camel/component/jacksonxml/jacksonXml.json +++ b/components/camel-jacksonxml/src/generated/resources/META-INF/org/apache/camel/component/jacksonxml/jacksonXml.json @@ -15,6 +15,12 @@ "modelName": "jacksonXml", "modelJavaType": "org.apache.camel.model.dataformat.JacksonXMLDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as XML. Text is written as an XML value, not as it is" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml" }, + "unmarshalOut": { "carriers": [ "map" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) of the XML; an object of the class unmarshalType names" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "xmlMapper": { "index": 1, "kind": "attribute", "displayName": "Xml Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing XmlMapper with the given id." }, diff --git a/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java b/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java index 5e4567427e425..e421d9bcdeb11 100644 --- a/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java +++ b/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java @@ -44,6 +44,9 @@ import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; import org.apache.camel.WrappedFile; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatContentTypeHeader; import org.apache.camel.spi.DataFormatName; @@ -60,6 +63,17 @@ * Jackson to marshal to and from XML. */ @Dataformat("jacksonXml") +@BodyTypes(marshalIn = @BodyType(value = Carrier.ANY, + description = "A Map, a List or a POJO to write as XML. Text is written as an XML value," + + " not as it is"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "xml", + description = "The XML in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "xml"), + unmarshalOut = @BodyType(value = Carrier.MAP, + dependsOn = { "unmarshalType", "collectionType", "allowUnmarshallType" }, + byOption = @BodyType.When(option = "useList", value = "true", carrier = Carrier.LIST), + description = "A Map (LinkedHashMap) of the XML; an object of the class unmarshalType" + + " names")) public class JacksonXMLDataFormat extends ServiceSupport implements DataFormat, DataFormatName, DataFormatContentTypeHeader, CamelContextAware { diff --git a/components/camel-jms/src/generated/resources/META-INF/org/apache/camel/component/jms/jms.json b/components/camel-jms/src/generated/resources/META-INF/org/apache/camel/component/jms/jms.json index 7307e4f146f23..43327061d9863 100644 --- a/components/camel-jms/src/generated/resources/META-INF/org/apache/camel/component/jms/jms.json +++ b/components/camel-jms/src/generated/resources/META-INF/org/apache/camel/component/jms/jms.json @@ -154,6 +154,12 @@ "CamelJmsMessageType": { "index": 16, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "org.apache.camel.component.jms.JmsMessageType", "enum": [ "Bytes", "Map", "Object", "Stream", "Text", "Blob" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message type.", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_MESSAGE_TYPE" }, "CamelJmsRequestTimeout": { "index": 17, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "20000", "description": "The timeout for waiting for a reply when using the InOut Exchange Pattern (in milliseconds).", "constantName": "org.apache.camel.component.jms.JmsConstants#JMS_REQUEST_TIMEOUT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "map", "stream", "null" ], "dependsOn": [ "messageConverter", "transferExchange" ], "byOption": [ { "option": "mapJmsMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.jms.Message" }, { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "map", "stream", "pojo", "null" ] } ], "description": "By the JMS message received: a String for a TextMessage, a byte array for a BytesMessage, a Map for a MapMessage, a stream for a StreamMessage; an ObjectMessage only with objectMessageEnabled" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "The reply, sent as the producer sends a message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "dependsOn": [ "jmsMessageType", "messageConverter", "transferExchange" ], "byOption": [ { "option": "objectMessageEnabled", "value": "true", "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ] } ], "description": "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage; a Map as a MapMessage. Another Serializable object fails unless objectMessageEnabled" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) gets the body of the reply, as the consumer gives it" } + }, "properties": { "destinationType": { "index": 0, "kind": "path", "displayName": "Destination Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "queue", "topic", "temp-queue", "temp-topic" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "queue", "description": "The kind of destination to use" }, "destinationName": { "index": 1, "kind": "path", "displayName": "Destination Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the queue or topic to use as destination" }, diff --git a/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsEndpoint.java b/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsEndpoint.java index 8c18b428ee573..67a8ec51e5312 100644 --- a/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsEndpoint.java +++ b/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsEndpoint.java @@ -39,6 +39,9 @@ import org.apache.camel.api.management.ManagedAttribute; import org.apache.camel.api.management.ManagedResource; import org.apache.camel.spi.BeanIntrospection; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.HeaderFilterStrategy; import org.apache.camel.spi.HeaderFilterStrategyAware; @@ -73,6 +76,42 @@ @UriEndpoint(firstVersion = "1.0.0", scheme = "jms", title = "JMS", syntax = "jms:destinationType:destinationName", category = { Category.MESSAGING }, headersClass = JmsConstants.class) @Metadata(excludeProperties = "bridgeErrorHandler") +@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.NULL }, + dependsOn = { "messageConverter", "transferExchange" }, + byOption = { + @BodyType.When(option = "mapJmsMessage", value = "false", carrier = Carrier.POJO, + javaType = "jakarta.jms.Message"), + @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.MAP, + Carrier.STREAM, Carrier.POJO, Carrier.NULL }) }, + description = "By the JMS message received: a String for a TextMessage, a byte array for a" + + " BytesMessage, a Map for a MapMessage, a stream for a StreamMessage;" + + " an ObjectMessage only with objectMessageEnabled"), + consumerReply = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, + dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, + byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE, Carrier.MAP, Carrier.POJO }), + description = "The reply, sent as the producer sends a message"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, + dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, + byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", + carrier = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE, Carrier.MAP, Carrier.POJO }), + description = "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage;" + + " a Map as a MapMessage. Another Serializable object fails unless" + + " objectMessageEnabled"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "exchangePattern", value = "InOnly", + carrier = Carrier.UNCHANGED), + @BodyType.When(option = "disableReplyTo", value = "true", + carrier = Carrier.UNCHANGED) }, + description = "Unchanged for a message that expects no reply (InOnly). A message that" + + " expects one (InOut) gets the body of the reply, as the consumer gives it")) public class JmsEndpoint extends DefaultEndpoint implements AsyncEndpoint, HeaderFilterStrategyAware, MultipleConsumersSupport, EndpointServiceLocation { diff --git a/components/camel-jq/src/generated/resources/META-INF/org/apache/camel/language/jq/jq.json b/components/camel-jq/src/generated/resources/META-INF/org/apache/camel/language/jq/jq.json index 8d658803476a5..781f11d2f1794 100644 --- a/components/camel-jq/src/generated/resources/META-INF/org/apache/camel/language/jq/jq.json +++ b/components/camel-jq/src/generated/resources/META-INF/org/apache/camel/language/jq/jq.json @@ -15,6 +15,10 @@ "modelName": "jq", "modelJavaType": "org.apache.camel.model.language.JqExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "format": "json", "description": "JSON as text, bytes, a stream or a file, or a Map" }, + "expressionOut": { "carriers": [ "pojo", "list", "null" ], "dependsOn": [ "resultType" ], "description": "A JsonNode; a List of JsonNode when the filter gives several, null when it gives none" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java b/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java index e21bfd984aca1..3944e84c8d266 100644 --- a/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java +++ b/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java @@ -22,11 +22,19 @@ import net.thisptr.jackson.jq.module.loaders.BuiltinModuleLoader; import org.apache.camel.Expression; import org.apache.camel.StaticService; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.CamelContextHelper; import org.apache.camel.support.SingleInputTypedLanguageSupport; @Language("jq") +@BodyTypes(expressionIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, + format = "json", description = "JSON as text, bytes, a stream or a file, or a Map"), + expressionOut = @BodyType(value = { Carrier.POJO, Carrier.LIST, Carrier.NULL }, dependsOn = "resultType", + description = "A JsonNode; a List of JsonNode when the filter gives several, null when it" + + " gives none")) public class JqLanguage extends SingleInputTypedLanguageSupport implements StaticService { private Scope rootScope; diff --git a/components/camel-jsonpath/src/generated/resources/META-INF/org/apache/camel/jsonpath/jsonpath.json b/components/camel-jsonpath/src/generated/resources/META-INF/org/apache/camel/jsonpath/jsonpath.json index af55d48104eaa..e3aeffd210b31 100644 --- a/components/camel-jsonpath/src/generated/resources/META-INF/org/apache/camel/jsonpath/jsonpath.json +++ b/components/camel-jsonpath/src/generated/resources/META-INF/org/apache/camel/jsonpath/jsonpath.json @@ -15,6 +15,10 @@ "modelName": "jsonpath", "modelJavaType": "org.apache.camel.model.language.JsonPathExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "JSON as text, bytes, a stream or a file, or parsed: a Map or a List. A POJO is read through Jackson" }, + "expressionOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "writeAsString", "value": "true", "carriers": [ "text", "list" ] } ], "description": "The value the path selects: a Map for an object, a List for an array or for a path with a wildcard or a filter, otherwise text, a number or a boolean" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java index 6b5df842e8dad..be5917ef5e01e 100644 --- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java +++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java @@ -25,6 +25,9 @@ import org.apache.camel.Expression; import org.apache.camel.Predicate; import org.apache.camel.jsonpath.easypredicate.EasyPredicateParser; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.PropertyConfigurer; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionAdapter; @@ -32,6 +35,15 @@ import org.apache.camel.support.component.PropertyConfigurerSupport; @Language("jsonpath") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "JSON as text, bytes, a stream or a file, or parsed: a Map or a List. A POJO" + + " is read through Jackson"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, + byOption = @BodyType.When(option = "writeAsString", value = "true", + carrier = { Carrier.TEXT, Carrier.LIST }), + description = "The value the path selects: a Map for an object, a List for an array or" + + " for a path with a wildcard or a filter, otherwise text, a number or a" + + " boolean")) public class JsonPathLanguage extends SingleInputTypedLanguageSupport implements PropertyConfigurer { private boolean suppressExceptions; diff --git a/components/camel-kafka/src/generated/resources/META-INF/org/apache/camel/component/kafka/kafka.json b/components/camel-kafka/src/generated/resources/META-INF/org/apache/camel/component/kafka/kafka.json index f40e398b911ba..d1dafe51f2f12 100644 --- a/components/camel-kafka/src/generated/resources/META-INF/org/apache/camel/component/kafka/kafka.json +++ b/components/camel-kafka/src/generated/resources/META-INF/org/apache/camel/component/kafka/kafka.json @@ -169,6 +169,11 @@ "CamelKafkaRecordMeta": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "List", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The metadata (only configured if recordMetadata endpoint parameter is true)", "constantName": "org.apache.camel.component.kafka.KafkaConstants#KAFKA_RECORD_META" }, "CamelKafkaManualCommit": { "index": 12, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "org.apache.camel.component.kafka.consumer.KafkaManualCommit", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Can be used for forcing manual offset commit when using Kafka consumer.", "constantName": "org.apache.camel.component.kafka.KafkaConstants#MANUAL_COMMIT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "null" ], "dependsOn": [ "valueDeserializer" ], "byOption": [ { "option": "valueDeserializer", "value": "org.apache.kafka.common.serialization.ByteArrayDeserializer", "carriers": [ "bytes", "null" ], "javaType": "byte[]" }, { "option": "batching", "value": "true", "carriers": [ "list" ] } ], "description": "The value of the record: a String with the default valueDeserializer (StringDeserializer), null for a tombstone. With batching, a List of the exchanges of the records" }, + "producerIn": { "carriers": [ "any" ], "dependsOn": [ "valueSerializer" ], "description": "The value of the record, converted for the valueSerializer: text with the default StringSerializer, so a Map or a POJO is sent as its toString(): marshal it first. With useIterator, an Iterable or an Iterator is sent as one record per element" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Name of the topic to use. On the consumer you can use comma to separate multiple topics. A producer can only send a message to a single topic." }, "additionalProperties": { "index": 1, "kind": "parameter", "displayName": "Additional Properties", "group": "common", "label": "common", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "additionalProperties.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.kafka.KafkaConfiguration", "configurationField": "configuration", "description": "Sets additional properties for either kafka consumer or kafka producer in case they can't be set directly on the camel configurations (e.g.: new Kafka properties that are not reflected yet in Camel configurations), the properties have to be prefixed with additionalProperties., e.g.: additionalProperties.transactional.id=12345&additionalProperties.schema.registry.url=http:\/\/localhost:8811\/avro. If the properties are set in the application.properties file, they must be prefixed with camel.component.kafka.additional-properties (camel.component.kafka-share.additional-properties for the Kafka Share component) followed by the property name enclosed in square brackets, for example the delivery.timeout.ms property in square brackets. This is a multi-value option with prefix: additionalProperties." }, diff --git a/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaEndpoint.java b/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaEndpoint.java index 30746c1de1731..85645fbcfe208 100644 --- a/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaEndpoint.java +++ b/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaEndpoint.java @@ -27,6 +27,9 @@ import org.apache.camel.Producer; import org.apache.camel.component.kafka.consumer.KafkaManualCommit; import org.apache.camel.component.kafka.consumer.KafkaManualCommitFactory; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ClassResolver; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.UriEndpoint; @@ -48,6 +51,21 @@ */ @UriEndpoint(firstVersion = "2.13.0", scheme = "kafka", title = "Kafka", syntax = "kafka:topic", category = { Category.MESSAGING }, headersClass = KafkaConstants.class) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.NULL }, dependsOn = "valueDeserializer", + byOption = { + @BodyType.When(option = "valueDeserializer", + value = "org.apache.kafka.common.serialization.ByteArrayDeserializer", + carrier = { Carrier.BYTES, Carrier.NULL }, javaType = "byte[]"), + @BodyType.When(option = "batching", value = "true", carrier = Carrier.LIST) }, + description = "The value of the record: a String with the default valueDeserializer" + + " (StringDeserializer), null for a tombstone. With batching, a List of" + + " the exchanges of the records"), + producerIn = @BodyType(value = Carrier.ANY, dependsOn = "valueSerializer", + description = "The value of the record, converted for the valueSerializer: text with the" + + " default StringSerializer, so a Map or a POJO is sent as its toString():" + + " marshal it first. With useIterator, an Iterable or an Iterator is sent" + + " as one record per element"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class KafkaEndpoint extends DefaultEndpoint implements MultipleConsumersSupport, EndpointServiceLocation { private static final Logger LOG = LoggerFactory.getLogger(KafkaEndpoint.class); diff --git a/components/camel-log/src/generated/resources/META-INF/org/apache/camel/component/log/log.json b/components/camel-log/src/generated/resources/META-INF/org/apache/camel/component/log/log.json index 1780d6316af2e..bf19483c839cb 100644 --- a/components/camel-log/src/generated/resources/META-INF/org/apache/camel/component/log/log.json +++ b/components/camel-log/src/generated/resources/META-INF/org/apache/camel/component/log/log.json @@ -30,6 +30,10 @@ "autowiredEnabled": { "index": 2, "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." }, "exchangeFormatter": { "index": 3, "kind": "property", "displayName": "Exchange Formatter", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExchangeFormatter", "deprecated": false, "autowired": true, "secret": false, "description": "Sets a custom ExchangeFormatter to convert the Exchange to a String suitable for logging. If not specified, we default to DefaultExchangeFormatter." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "loggerName": { "index": 0, "kind": "path", "displayName": "Logger Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the logging category to use" }, "groupActiveOnly": { "index": 1, "kind": "parameter", "displayName": "Group Active Only", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "If true, will hide stats when no new messages have been received for a time interval, if false, show stats regardless of message traffic." }, diff --git a/components/camel-log/src/main/java/org/apache/camel/component/log/LogEndpoint.java b/components/camel-log/src/main/java/org/apache/camel/component/log/LogEndpoint.java index 3f8eff9127211..ce89ba2e3c422 100644 --- a/components/camel-log/src/main/java/org/apache/camel/component/log/LogEndpoint.java +++ b/components/camel-log/src/main/java/org/apache/camel/component/log/LogEndpoint.java @@ -22,6 +22,9 @@ import org.apache.camel.LoggingLevel; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.CamelLogger; import org.apache.camel.spi.ExchangeFormatter; import org.apache.camel.spi.MaskingFormatter; @@ -45,6 +48,7 @@ @UriEndpoint(firstVersion = "1.1.0", scheme = "log", title = "Log Data", remote = false, internal = true, syntax = "log:loggerName", producerOnly = true, category = { Category.CORE, Category.MONITORING }) +@BodyTypes(producerIn = @BodyType(Carrier.ANY), producerOut = @BodyType(Carrier.UNCHANGED)) public class LogEndpoint extends ProcessorEndpoint implements LineNumberAware { private volatile Processor logger; diff --git a/components/camel-mock/src/generated/resources/META-INF/org/apache/camel/component/mock/mock.json b/components/camel-mock/src/generated/resources/META-INF/org/apache/camel/component/mock/mock.json index eadcc424ddeb2..4982ad8453e7f 100644 --- a/components/camel-mock/src/generated/resources/META-INF/org/apache/camel/component/mock/mock.json +++ b/components/camel-mock/src/generated/resources/META-INF/org/apache/camel/component/mock/mock.json @@ -30,6 +30,10 @@ "autowiredEnabled": { "index": 2, "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." }, "exchangeFormatter": { "index": 3, "kind": "property", "displayName": "Exchange Formatter", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExchangeFormatter", "deprecated": false, "autowired": true, "secret": false, "description": "To use a custom ExchangeFormatter to format the Exchange into a String suitable for logging." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of mock endpoint" }, "assertPeriod": { "index": 1, "kind": "parameter", "displayName": "Assert Period", "group": "producer", "label": "producer", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a grace period after which the mock will re-assert to ensure the preliminary assertion is still valid. This is used, for example, to assert that exactly a number of messages arrive. For example, if the expected count was set to 5, then the assertion is satisfied when five or more messages arrive. To ensure that exactly 5 messages arrive, then you would need to wait a little period to ensure no further message arrives. This is what you can use this method for. By default, this period is disabled." }, diff --git a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockEndpoint.java b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockEndpoint.java index 6ac3b02ca1e5c..f3d9e83d1eb0d 100644 --- a/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockEndpoint.java +++ b/components/camel-mock/src/main/java/org/apache/camel/component/mock/MockEndpoint.java @@ -49,6 +49,9 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.BrowsableEndpoint; import org.apache.camel.spi.HeadersMapFactory; import org.apache.camel.spi.InterceptSendToEndpoint; @@ -97,6 +100,7 @@ */ @UriEndpoint(firstVersion = "1.0.0", scheme = "mock", title = "Mock", syntax = "mock:name", producerOnly = true, remote = false, internal = true, category = { Category.CORE, Category.TESTING }, lenientProperties = true) +@BodyTypes(producerIn = @BodyType(Carrier.ANY), producerOut = @BodyType(Carrier.UNCHANGED)) public class MockEndpoint extends DefaultEndpoint implements BrowsableEndpoint, NotifyBuilderMatcher { private static final Logger LOG = LoggerFactory.getLogger(MockEndpoint.class); diff --git a/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json b/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json index e60f0367259fb..3c00abc0f66aa 100644 --- a/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json +++ b/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json @@ -33,6 +33,10 @@ "engine": { "index": 5, "kind": "property", "displayName": "Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.spi.PlatformHttpEngine", "deprecated": false, "autowired": false, "secret": false, "description": "An HTTP Server engine implementation to serve the requests" }, "headerFilterStrategy": { "index": 6, "kind": "property", "displayName": "Header Filter Strategy", "group": "filter", "label": "filter", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "bytes", "null", "map", "file" ], "byOption": [ { "option": "useBodyHandler", "value": "false", "carriers": [ "pojo" ] } ], "description": "The request body: the stream cache with the Vert.x engine, a byte array with Spring Boot; null for a request without a body, such as a GET; a Map of the fields of a form (populateBodyWithForm); a File for an upload" }, + "consumerReply": { "carriers": [ "null", "text", "bytes", "stream" ], "description": "The response body: text, bytes, a stream or no body. A Map or a List fails: marshal it first" } + }, "properties": { "path": { "index": 0, "kind": "path", "displayName": "Path", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The path under which this endpoint serves the HTTP requests, for proxy use 'proxy'" }, "consumes": { "index": 1, "kind": "parameter", "displayName": "Consumes", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type this endpoint accepts as an input, such as application\/xml or application\/json. null or *\/* mean no restriction." }, diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java index c2c67935bff6d..c910d2ddce89e 100644 --- a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java +++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java @@ -34,6 +34,9 @@ import org.apache.camel.component.platform.http.spi.PlatformHttpSecurityHandler; import org.apache.camel.http.base.HttpHeaderFilterStrategy; import org.apache.camel.http.base.OAuthHttpSecuritySupport; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.HeaderFilterStrategy; import org.apache.camel.spi.HeaderFilterStrategyAware; @@ -51,6 +54,16 @@ @UriEndpoint(firstVersion = "3.0.0", scheme = "platform-http", title = "Platform HTTP", syntax = "platform-http:path", category = { Category.HTTP }, consumerOnly = true) @Metadata(annotations = { "protocol=http" }) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.STREAM, Carrier.BYTES, Carrier.NULL, Carrier.MAP, Carrier.FILE }, + byOption = @BodyType.When(option = "useBodyHandler", value = "false", + carrier = Carrier.POJO), + description = "The request body: the stream cache with the Vert.x engine, a byte array" + + " with Spring Boot; null for a request without a body, such as a GET; a" + + " Map of the fields of a form (populateBodyWithForm); a File for an" + + " upload"), + consumerReply = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM }, + description = "The response body: text, bytes, a stream or no body. A Map or a List" + + " fails: marshal it first")) public class PlatformHttpEndpoint extends DefaultEndpoint implements AsyncEndpoint, HeaderFilterStrategyAware, EndpointServiceLocation { diff --git a/components/camel-quartz/src/generated/resources/META-INF/org/apache/camel/component/quartz/quartz.json b/components/camel-quartz/src/generated/resources/META-INF/org/apache/camel/component/quartz/quartz.json index d56eb70d9f853..8b8cc7acc2acb 100644 --- a/components/camel-quartz/src/generated/resources/META-INF/org/apache/camel/component/quartz/quartz.json +++ b/components/camel-quartz/src/generated/resources/META-INF/org/apache/camel/component/quartz/quartz.json @@ -37,6 +37,9 @@ "autoStartScheduler": { "index": 10, "kind": "property", "displayName": "Auto Start Scheduler", "group": "scheduler", "label": "scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started. This option is default true" }, "interruptJobsOnShutdown": { "index": 11, "kind": "property", "displayName": "Interrupt Jobs On Shutdown", "group": "scheduler", "label": "scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to interrupt jobs on shutdown, which forces the scheduler to shut down quicker and attempt to interrupt any running jobs. If this is enabled, then any running jobs can fail due to being interrupted. When a job is interrupted then Camel will mark the exchange to stop to continue routing and set java.util.concurrent.RejectedExecutionException as caused exception. Therefore, use this with care, as its often better to allow Camel jobs to complete and shutdown gracefully." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "description": "No body: the message only starts the route" } + }, "properties": { "groupName": { "index": 0, "kind": "path", "displayName": "Group Name", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Camel", "description": "The quartz group name to use. The combination of group name and trigger name should be unique." }, "triggerName": { "index": 1, "kind": "path", "displayName": "Trigger Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The quartz trigger name to use. The combination of group name and trigger name should be unique." }, diff --git a/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/QuartzEndpoint.java b/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/QuartzEndpoint.java index 7748cdc5d5647..1b71b5f21b8c1 100644 --- a/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/QuartzEndpoint.java +++ b/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/QuartzEndpoint.java @@ -30,6 +30,9 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.Route; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -61,6 +64,7 @@ */ @UriEndpoint(firstVersion = "2.12.0", scheme = "quartz", title = "Quartz", syntax = "quartz:groupName/triggerName", remote = false, consumerOnly = true, category = { Category.SCHEDULING }) +@BodyTypes(consumerOut = @BodyType(value = Carrier.NULL, description = "No body: the message only starts the route")) public class QuartzEndpoint extends DefaultEndpoint { private static final Logger LOG = LoggerFactory.getLogger(QuartzEndpoint.class); diff --git a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json index 22417ab779dfc..f175ff957c19b 100644 --- a/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json +++ b/components/camel-rest-openapi/src/generated/resources/META-INF/org/apache/camel/component/rest/openapi/rest-openapi.json @@ -47,6 +47,8 @@ "useGlobalSslContextParameters": { "index": 20, "kind": "property", "displayName": "Use Global Ssl Context Parameters", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Enable usage of global SSL context parameters." } }, "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "bytes", "null", "map", "file" ], "dependsOn": [ "consumerComponentName" ], "description": "The request body as the HTTP consumer gives it (platform-http by default). With the json binding mode of the rest configuration, the object of the schema (bindingPackageScan), or a Map or a List" }, + "consumerReply": { "carriers": [ "null", "text", "bytes", "stream" ], "dependsOn": [ "consumerComponentName" ], "description": "The response body as the HTTP consumer writes it. With the json binding mode of the rest configuration, any object, which the binding writes as JSON" }, "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "componentName" ], "description": "The request body of the operation, which the http component sends: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, "producerOut": { "carriers": [ "bytes", "stream", "null" ], "dependsOn": [ "componentName" ], "description": "The response body, as the http component gives it: a byte array or the stream cache; null for a response without a body" } }, diff --git a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java index 4f1c00d080713..bdc1e883077c2 100644 --- a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java +++ b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/RestOpenApiEndpoint.java @@ -95,7 +95,17 @@ */ @UriEndpoint(firstVersion = "3.1.0", scheme = "rest-openapi", title = "REST OpenApi", syntax = "rest-openapi:specificationUri#operationId", category = { Category.REST, Category.API }) -@BodyTypes(producerIn = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, +@BodyTypes(consumerOut = @BodyType(value = { Carrier.STREAM, Carrier.BYTES, Carrier.NULL, Carrier.MAP, Carrier.FILE }, + dependsOn = "consumerComponentName", + description = "The request body as the HTTP consumer gives it (platform-http by default)." + + " With the json binding mode of the rest configuration, the object of the" + + " schema (bindingPackageScan), or a Map or a List"), + consumerReply = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM }, + dependsOn = "consumerComponentName", + description = "The response body as the HTTP consumer writes it. With the json binding" + + " mode of the rest configuration, any object, which the binding writes as" + + " JSON"), + producerIn = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, dependsOn = "componentName", description = "The request body of the operation, which the http component sends: text," + " bytes, a stream or a file. A Map or a List fails: marshal it first"), diff --git a/components/camel-rest/src/generated/resources/META-INF/org/apache/camel/component/rest/rest.json b/components/camel-rest/src/generated/resources/META-INF/org/apache/camel/component/rest/rest.json index 041ff7467c2e6..8ad7a7dbc0771 100644 --- a/components/camel-rest/src/generated/resources/META-INF/org/apache/camel/component/rest/rest.json +++ b/components/camel-rest/src/generated/resources/META-INF/org/apache/camel/component/rest/rest.json @@ -43,6 +43,12 @@ "Accept": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The media type such as: 'text\/xml', or 'application\/json' this REST service accepts.", "constantName": "org.apache.camel.component.rest.RestConstants#ACCEPT" }, "CamelHttpResponseCode": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "The http response code", "constantName": "org.apache.camel.component.rest.RestConstants#HTTP_RESPONSE_CODE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "bytes", "null", "map", "file" ], "dependsOn": [ "consumerComponentName" ], "byOption": [ { "option": "bindingMode", "value": "json", "carriers": [ "map", "list", "pojo" ] } ], "description": "The request body as the HTTP consumer gives it (platform-http by default). With bindingMode json, the object of inType, or a Map or a List without inType" }, + "consumerReply": { "carriers": [ "null", "text", "bytes", "stream" ], "dependsOn": [ "consumerComponentName" ], "byOption": [ { "option": "bindingMode", "value": "json", "carriers": [ "any" ] } ], "description": "The response body as the HTTP consumer writes it. With bindingMode json, any object, which the binding writes as JSON" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "producerComponentName" ], "byOption": [ { "option": "bindingMode", "value": "json", "carriers": [ "any" ] } ], "description": "The request body the HTTP producer sends (the http component by default). With bindingMode json, any object, which the binding writes as JSON" }, + "producerOut": { "carriers": [ "bytes", "stream", "null" ], "dependsOn": [ "producerComponentName", "outType" ], "description": "The response body as the HTTP producer gives it; with bindingMode json and outType, an object of outType" } + }, "properties": { "method": { "index": 0, "kind": "path", "displayName": "Method", "group": "common", "label": "common", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "get", "post", "put", "delete", "patch", "head", "trace", "connect", "options" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "HTTP method to use." }, "path": { "index": 1, "kind": "path", "displayName": "Path", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The base path, can use * as path suffix to support wildcard HTTP route matching." }, diff --git a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java index e4275bca1c72e..66b43a1957e16 100644 --- a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java +++ b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java @@ -26,6 +26,9 @@ import org.apache.camel.NoSuchBeanException; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.RestConfiguration; import org.apache.camel.spi.RestConsumerFactory; @@ -55,6 +58,27 @@ @Metadata(annotations = { "protocol=http", }) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.STREAM, Carrier.BYTES, Carrier.NULL, Carrier.MAP, Carrier.FILE }, + dependsOn = "consumerComponentName", + byOption = @BodyType.When(option = "bindingMode", value = "json", + carrier = { Carrier.MAP, Carrier.LIST, Carrier.POJO }), + description = "The request body as the HTTP consumer gives it (platform-http by" + + " default). With bindingMode json, the object of inType, or a Map or a" + + " List without inType"), + consumerReply = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM }, + dependsOn = "consumerComponentName", + byOption = @BodyType.When(option = "bindingMode", value = "json", carrier = Carrier.ANY), + description = "The response body as the HTTP consumer writes it. With bindingMode json," + + " any object, which the binding writes as JSON"), + producerIn = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + dependsOn = "producerComponentName", + byOption = @BodyType.When(option = "bindingMode", value = "json", carrier = Carrier.ANY), + description = "The request body the HTTP producer sends (the http component by default)." + + " With bindingMode json, any object, which the binding writes as JSON"), + producerOut = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.NULL }, + dependsOn = { "producerComponentName", "outType" }, + description = "The response body as the HTTP producer gives it; with bindingMode json and" + + " outType, an object of outType")) public class RestEndpoint extends DefaultEndpoint { public static final String[] DEFAULT_REST_CONSUMER_COMPONENTS diff --git a/components/camel-scheduler/src/generated/resources/META-INF/org/apache/camel/component/scheduler/scheduler.json b/components/camel-scheduler/src/generated/resources/META-INF/org/apache/camel/component/scheduler/scheduler.json index 491fc0b24d373..83c5065eeca03 100644 --- a/components/camel-scheduler/src/generated/resources/META-INF/org/apache/camel/component/scheduler/scheduler.json +++ b/components/camel-scheduler/src/generated/resources/META-INF/org/apache/camel/component/scheduler/scheduler.json @@ -34,6 +34,9 @@ "headers": { "CamelMessageTimestamp": { "index": 0, "kind": "header", "displayName": "", "group": "consumer", "label": "", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The timestamp of the message", "constantName": "org.apache.camel.component.scheduler.SchedulerConstants#MESSAGE_TIMESTAMP" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "description": "No body: the message only starts the route" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the scheduler" }, "includeMetadata": { "index": 1, "kind": "parameter", "displayName": "Include Metadata", "group": "consumer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to include metadata in the exchange such as fired time, timer name, timer count etc." }, diff --git a/components/camel-scheduler/src/main/java/org/apache/camel/component/scheduler/SchedulerEndpoint.java b/components/camel-scheduler/src/main/java/org/apache/camel/component/scheduler/SchedulerEndpoint.java index 54ab073da275d..ac6aa6a500c9c 100644 --- a/components/camel-scheduler/src/main/java/org/apache/camel/component/scheduler/SchedulerEndpoint.java +++ b/components/camel-scheduler/src/main/java/org/apache/camel/component/scheduler/SchedulerEndpoint.java @@ -22,6 +22,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -37,6 +40,7 @@ @UriEndpoint(firstVersion = "2.15.0", scheme = "scheduler", title = "Scheduler", syntax = "scheduler:name", remote = false, consumerOnly = true, category = { Category.CORE, Category.SCHEDULING }, headersClass = SchedulerConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.NULL, description = "No body: the message only starts the route")) public class SchedulerEndpoint extends ScheduledPollEndpoint { @UriPath diff --git a/components/camel-snakeyaml/src/generated/resources/META-INF/org/apache/camel/component/snakeyaml/snakeYaml.json b/components/camel-snakeyaml/src/generated/resources/META-INF/org/apache/camel/component/snakeyaml/snakeYaml.json index cc69504fdca03..a24fa2186d37c 100644 --- a/components/camel-snakeyaml/src/generated/resources/META-INF/org/apache/camel/component/snakeyaml/snakeYaml.json +++ b/components/camel-snakeyaml/src/generated/resources/META-INF/org/apache/camel/component/snakeyaml/snakeYaml.json @@ -15,6 +15,12 @@ "modelName": "yaml", "modelJavaType": "org.apache.camel.model.dataformat.YAMLDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as YAML" }, + "marshalOut": { "carriers": [ "stream" ], "format": "yaml", "description": "The YAML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "yaml" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType" ], "description": "A Map (LinkedHashMap) for a mapping, a List (ArrayList) for a sequence; a document that is a single value gives that value" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "library": { "index": 1, "kind": "attribute", "displayName": "Library", "group": "common", "required": false, "type": "enum", "javaType": "org.apache.camel.model.dataformat.YAMLLibrary", "enum": [ "SnakeYAML" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "SnakeYAML", "description": "Which yaml library to use. By default it is SnakeYAML." }, diff --git a/components/camel-snakeyaml/src/main/java/org/apache/camel/component/snakeyaml/SnakeYAMLDataFormat.java b/components/camel-snakeyaml/src/main/java/org/apache/camel/component/snakeyaml/SnakeYAMLDataFormat.java index 7957afe3e8826..56205efa65b3e 100644 --- a/components/camel-snakeyaml/src/main/java/org/apache/camel/component/snakeyaml/SnakeYAMLDataFormat.java +++ b/components/camel-snakeyaml/src/main/java/org/apache/camel/component/snakeyaml/SnakeYAMLDataFormat.java @@ -25,6 +25,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -47,6 +50,13 @@ * SnakeYAML */ @Dataformat("snakeYaml") +@BodyTypes(marshalIn = @BodyType(value = Carrier.ANY, description = "A Map, a List or a POJO to write as YAML"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "yaml", + description = "The YAML in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "yaml"), + unmarshalOut = @BodyType(value = { Carrier.MAP, Carrier.LIST }, dependsOn = "unmarshalType", + description = "A Map (LinkedHashMap) for a mapping, a List (ArrayList) for a sequence; a" + + " document that is a single value gives that value")) public final class SnakeYAMLDataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private CamelContext camelContext; diff --git a/components/camel-xpath/src/generated/resources/META-INF/org/apache/camel/language/xpath/xpath.json b/components/camel-xpath/src/generated/resources/META-INF/org/apache/camel/language/xpath/xpath.json index 0a6a706898992..e7e50b9357a1e 100644 --- a/components/camel-xpath/src/generated/resources/META-INF/org/apache/camel/language/xpath/xpath.json +++ b/components/camel-xpath/src/generated/resources/META-INF/org/apache/camel/language/xpath/xpath.json @@ -15,6 +15,10 @@ "modelName": "xpath", "modelJavaType": "org.apache.camel.model.language.XPathExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "XML as text, bytes, a stream or a file, or a DOM" }, + "expressionOut": { "carriers": [ "pojo" ], "javaType": "org.w3c.dom.NodeList", "dependsOn": [ "resultType" ], "byOption": [ { "option": "resultQName", "value": "STRING", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "resultQName", "value": "NUMBER", "carriers": [ "value" ], "javaType": "java.lang.Double" }, { "option": "resultQName", "value": "BOOLEAN", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "resultQName", "value": "NODE", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Node" } ], "description": "The nodes the expression selects" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java index 2aca26d203812..7487f7f91317d 100644 --- a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java +++ b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java @@ -25,6 +25,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.Expression; import org.apache.camel.Predicate; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.PropertyConfigurer; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.SingleInputTypedLanguageSupport; @@ -34,6 +37,19 @@ * XPath language. */ @Language("xpath") +@BodyTypes(expressionIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", description = "XML as text, bytes, a stream or a file, or a DOM"), + expressionOut = @BodyType(value = Carrier.POJO, javaType = "org.w3c.dom.NodeList", dependsOn = "resultType", + byOption = { + @BodyType.When(option = "resultQName", value = "STRING", carrier = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "resultQName", value = "NUMBER", carrier = Carrier.VALUE, + javaType = "java.lang.Double"), + @BodyType.When(option = "resultQName", value = "BOOLEAN", carrier = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "resultQName", value = "NODE", carrier = Carrier.POJO, + javaType = "org.w3c.dom.Node") }, + description = "The nodes the expression selects")) public class XPathLanguage extends SingleInputTypedLanguageSupport implements PropertyConfigurer { private QName resultQName; private Class documentType; diff --git a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/constant/constant.json b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/constant/constant.json index e1c1c40cb2ea8..9889e6d5b957e 100644 --- a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/constant/constant.json +++ b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/constant/constant.json @@ -15,6 +15,9 @@ "modelName": "constant", "modelJavaType": "org.apache.camel.model.language.ConstantExpression" }, + "bodyTypes": { + "expressionOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultType" ], "description": "The text as it is written; resource:classpath:name loads the text of the resource" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json index 6de66be485c43..5648229337930 100644 --- a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json +++ b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/simple.json @@ -15,6 +15,10 @@ "modelName": "simple", "modelJavaType": "org.apache.camel.model.language.SimpleExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ] }, + "expressionOut": { "carriers": [ "unknown" ], "description": "A text with functions gives text. A single function, such as ${body} or ${header.foo}, gives its value as it is" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/constant/ConstantLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/constant/ConstantLanguage.java index f15bb94fd69c3..738723733d011 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/constant/ConstantLanguage.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/constant/ConstantLanguage.java @@ -20,6 +20,9 @@ import org.apache.camel.NoTypeConversionAvailableException; import org.apache.camel.Predicate; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionToPredicateAdapter; import org.apache.camel.support.LanguageSupport; @@ -29,6 +32,9 @@ * A language for constant expressions. */ @Language("constant") +@BodyTypes(expressionOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", dependsOn = "resultType", + description = "The text as it is written; resource:classpath:name loads the text of the" + + " resource")) public class ConstantLanguage extends LanguageSupport { public static Expression constant(Object value) { diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java index ddfd3f7c4b0d2..a43ebbb47d4af 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleLanguage.java @@ -23,6 +23,9 @@ import org.apache.camel.Expression; import org.apache.camel.Predicate; import org.apache.camel.StaticService; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.CamelContextHelper; import org.apache.camel.support.ExpressionAdapter; @@ -40,6 +43,10 @@ * The Camel simple language. */ @Language(value = "simple", functionsClass = SimpleConstants.class, operatorsClass = SimpleOperatorConstants.class) +@BodyTypes(expressionIn = @BodyType(Carrier.ANY), + expressionOut = @BodyType(value = Carrier.UNKNOWN, + description = "A text with functions gives text. A single function, such as ${body} or" + + " ${header.foo}, gives its value as it is")) public class SimpleLanguage extends LanguageSupport implements StaticService { private static final Logger LOG = LoggerFactory.getLogger(SimpleLanguage.class); diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc index d22ffd4ca0b3f..618d6a540959f 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc @@ -1267,7 +1267,7 @@ its `application.properties` key as `configKey`. `camel_catalog_doc` without `optionsFilter` now lists the required options and the first 20 other options of a component in full, and the rest by name in `moreOptions` (`limit` lists more in full), and an answer is cut at -16 000 characters with a marker. An option of both the endpoint and the component is listed once, with `scope` +18 000 characters with a marker. An option of both the endpoint and the component is listed once, with `scope` set to `endpoint,component` and its `configKey`, instead of twice, and `matchedOptions` counts option names. A name that only matches a word of an EIP title (such as `retry`) no longer returns that EIP: the answer is a not-found with suggestions. diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc index b39a4bd9e1fe1..305f64e8ccd0b 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-mcp.adoc @@ -315,8 +315,11 @@ project `directory` as an argument, the runtime tools take the integration `name (`mail.*` of smtp) are listed in `prefixOptions`. A filter that matches no option says so, with the closest option names. The answer lists the `sections` of the component page, those that contain the filter first, and `docPage=
` returns one. A full key (`camel.server.port`, `camel.jbang.dependencies`) answers - its group of `application.properties` keys, the key first. An answer is cut at 16 000 characters, with a - marker that says what was left out. + its group of `application.properties` keys, the key first. A component, data format or language that + declares its body types has them in `bodyTypes`, a line per side: what a `from:` gives the route + (`consumerOut`), what a `to:` can send (`producerIn`) and the body after it (`producerOut`), and so on (see + xref:camel-catalog.adoc#_body_types_in_the_catalog[Body types in the Catalog]). An answer is cut at 18 000 + characters, with a marker that says what was left out. `includeOptions` picks the options listed: `common` (the default) leaves out the deprecated and advanced ones and says how many with `omittedOptions`, `required` lists the required ones, `all` everything, `false` none; `optionsFilter` matches a keyword in the option names, descriptions and groups and searches all diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java index d69c883fbab17..b6777140ce3b7 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java @@ -39,6 +39,7 @@ import org.apache.camel.tooling.model.ApiReferenceModel; import org.apache.camel.tooling.model.BaseModel; import org.apache.camel.tooling.model.BaseOptionModel; +import org.apache.camel.tooling.model.BodyTypeModel; import org.apache.camel.tooling.model.ComponentModel; import org.apache.camel.tooling.model.DataFormatModel; import org.apache.camel.tooling.model.EipModel; @@ -66,12 +67,10 @@ public final class CatalogDocs { /** The sub-pages of a language's documentation (simple has functions, operators, ognl and advanced). */ private static final List LANGUAGE_DOC_PAGES = List.of("functions", "operators", "ognl", "advanced"); - static final String BODY_TYPES_HINT = "the message body with the default options. consumerOut: the body a from:" - + " gives the route; consumerReply: the bodies it can reply with; producerIn:" - + " the bodies a to: can send; producerOut: the body after the to:; marshal," - + " unmarshal and expression In/Out: the same for a data format and a" - + " language. Carriers: text, bytes, stream, file, value, map, list, pojo," - + " null, unchanged, any, unknown. A side not listed is not known"; + static final String BODY_TYPES_HINT = "the body with the default options: consumerOut is what a from: gives the" + + " route, consumerReply what it can reply with, producerIn what a to: can" + + " send, producerOut the body after the to: (and so on for marshal, unmarshal" + + " and expression); a side not listed is not known"; /** * The rules a small model gets wrong most: functions live inside the placeholder, operators between placeholders. @@ -1635,11 +1634,49 @@ private static void addCommonModelFields(JsonObject result, BaseModel model) } if (!model.getBodyTypes().isEmpty()) { // what the body is after the step and what it needs, which the options do not say (CAMEL-24961) - result.put("bodyTypes", JsonMapper.asJsonObjectBodyTypes(model.getBodyTypes())); + result.put("bodyTypes", bodyTypes(model.getBodyTypes())); result.put("bodyTypesHint", BODY_TYPES_HINT); } } + /** + * The body types a line per side, as compact as the options are: the carriers, the Java type, the format, the + * description, the body for other option values, and the options that make it not known (CAMEL-24961). + */ + static JsonObject bodyTypes(Map bodyTypes) { + JsonObject answer = new JsonObject(); + for (Map.Entry entry : bodyTypes.entrySet()) { + BodyTypeModel side = entry.getValue(); + StringBuilder line = new StringBuilder(carriers(side.getCarriers(), side.getJavaType())); + if (side.getFormat() != null) { + line.append(", as ").append(side.getFormat()); + } + if (side.getDescription() != null) { + line.append(". ").append(side.getDescription()); + } + if (!side.getByOption().isEmpty()) { + List values = new ArrayList<>(); + for (BodyTypeModel.OptionBodyTypeModel option : side.getByOption()) { + values.add(option.getOption() + "=" + option.getValue() + ": " + + carriers(option.getCarriers(), option.getJavaType())); + } + line.append(". With ").append(String.join("; ", values)); + } + if (!side.getDependsOn().isEmpty()) { + line.append(". Not known when ").append(String.join(" or ", side.getDependsOn())).append(" is set"); + } + answer.put(entry.getKey(), line.toString()); + } + return answer; + } + + private static String carriers(List carriers, String javaType) { + String answer = carriers.size() == 1 + ? carriers.get(0) + : String.join(", ", carriers.subList(0, carriers.size() - 1)) + " or " + carriers.get(carriers.size() - 1); + return javaType != null ? answer + " (" + javaType + ")" : answer; + } + /** * The rules of an endpoint URI for this component, spelled out with its own path parts: what a small model gets * wrong most is a path option written as a query parameter or the other way round, and the YAML form. @@ -1696,9 +1733,10 @@ static String usage(ComponentModel model) { /** * The longest answer, in characters: activemq listed 88 options in 38 K characters, which a client rejected or - * spilled to a file instead of showing it to the model (CAMEL-25541). + * spilled to a file instead of showing it to the model (CAMEL-25541). Raised from 16000 for the body types + * (CAMEL-24961), which the jms components have on four sides. */ - static final int MAX_ANSWER_LENGTH = 16000; + static final int MAX_ANSWER_LENGTH = 18000; /** How much of the text of a page a cut answer keeps at least, before its lists are cut. */ static final int MIN_DOC_KEPT = 8000; diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java index 87de31b39b658..51fc53d6d0bfc 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java +++ b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java @@ -135,21 +135,29 @@ void componentOptionsSayWhetherTheyArePathOrQueryAndTheUriRulesComeAlong() throw @Test void theBodyTypesSayWhatTheBodyIsAfterAStep() throws Exception { - // CAMEL-24961: what the options of a component do not say + // CAMEL-24961: what the options of a component do not say, a line per side JsonObject xslt = catalogDoc(Map.of("name", "xslt", "kind", "component", "includeOptions", false)); - JsonObject out = ((JsonObject) xslt.get("bodyTypes")).getMap("producerOut"); - assertEquals(List.of("text"), out.getCollection("carriers")); - assertEquals("java.lang.String", out.getString("javaType")); - assertTrue(xslt.getString("bodyTypesHint").contains("A side not listed is not known")); + JsonObject sides = (JsonObject) xslt.get("bodyTypes"); + assertEquals("text, bytes, stream, file or pojo, as xml. The XML to transform: text, bytes, a stream, a file, a" + + " DOM or another javax.xml.transform.Source. A Map, a List or no body fails. With" + + " failOnNullBody=false: null, text, bytes, stream, file or pojo. Not known when source is set", + sides.getString("producerIn")); + assertTrue(sides.getString("producerOut").startsWith("text (java.lang.String). The result of the transformation." + + " With output=bytes: bytes (byte[]); output=DOM: pojo")); + assertTrue(xslt.getString("bodyTypesHint").contains("a side not listed is not known")); JsonObject json = catalogDoc(Map.of("name", "json", "kind", "dataformat", "includeOptions", false)); - JsonObject unmarshalOut = ((JsonObject) json.get("bodyTypes")).getMap("unmarshalOut"); - assertEquals(List.of("map", "list"), unmarshalOut.getCollection("carriers")); + assertTrue(((JsonObject) json.get("bodyTypes")).getString("unmarshalOut").startsWith("map or list. ")); + + // a language: what its expressions read, and their result + JsonObject xpath = catalogDoc(Map.of("name", "xpath", "kind", "language", "includeOptions", false)); + assertTrue(((JsonObject) xpath.get("bodyTypes")).getString("expressionOut") + .startsWith("pojo (org.w3c.dom.NodeList). The nodes the expression selects. With resultQName=STRING: text")); // a component that does not declare them has none, rather than a guess - JsonObject kafka = catalogDoc(Map.of("name", "kafka", "kind", "component", "includeOptions", false)); - assertNull(kafka.get("bodyTypes")); - assertNull(kafka.get("bodyTypesHint")); + JsonObject mongodb = catalogDoc(Map.of("name", "mongodb", "kind", "component", "includeOptions", false)); + assertNull(mongodb.get("bodyTypes")); + assertNull(mongodb.get("bodyTypesHint")); } @Test From 82f4901169e5db3f71800a78a98c4058b333b975 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 14:40:19 +0200 Subject: [PATCH 03/25] CAMEL-24961: camel-catalog - the body types of paho-mqtt5 and mongodb paho-mqtt5: the consumer gives the payload as a byte array, the producer sends what converts to one and leaves the body unchanged. mongodb: the consumer gives a Document (or null for a change without its full document with changeStreams); the producer takes a document or a query, and leaves a body by operation: a Document or null for a find of one, a List for findAll, findDistinct and aggregate, a Long for count, the result of the driver for the other writes. Read from the code that sets the body, and checked against a mosquitto and a mongodb container started with camel infra. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../camel/catalog/components/mongodb.json | 5 ++ .../camel/catalog/components/paho-mqtt5.json | 5 ++ .../camel/component/mongodb/mongodb.json | 5 ++ .../component/mongodb/MongoDbEndpoint.java | 53 +++++++++++++++++++ .../component/paho/mqtt5/paho-mqtt5.json | 5 ++ .../paho/mqtt5/PahoMqtt5Endpoint.java | 8 +++ .../core/commands/ai/CatalogDocsTest.java | 6 +-- 7 files changed, 84 insertions(+), 3 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mongodb.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mongodb.json index 62ad7c16ba705..6bfb9c23245ef 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mongodb.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mongodb.json @@ -58,6 +58,11 @@ "CamelMongoDbReturnDocumentType": { "index": 24, "kind": "header", "displayName": "", "group": "producer update one and return", "label": "producer update one and return", "required": false, "javaType": "com.mongodb.client.model.ReturnDocument", "enum": [ "BEFORE", "AFTER" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Indicates which document to return, the document before or after an update and return atomic operation.", "constantName": "org.apache.camel.component.mongodb.MongoDbConstants#RETURN_DOCUMENT" }, "CamelMongoDbOperationOption": { "index": 25, "kind": "header", "displayName": "", "group": "producer update one and options", "label": "producer update one and options", "required": false, "javaType": "Object", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Options to use. When set, options set in the headers will be ignored.", "constantName": "org.apache.camel.component.mongodb.MongoDbConstants#OPTIONS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo" ], "javaType": "org.bson.Document", "byOption": [ { "option": "consumerType", "value": "changeStreams", "carriers": [ "pojo", "null" ] } ], "description": "The document added to the capped collection; with changeStreams the full document of the change, null when the change has none (an update without fullDocument=updateLookup)" }, + "producerIn": { "carriers": [ "any" ], "description": "A document or a query: a Document, a Map or JSON text; a List of them for insert, aggregate and update" }, + "producerOut": { "carriers": [ "unknown" ], "dependsOn": [ "outputType", "writeResultAsHeader" ], "byOption": [ { "option": "operation", "value": "findById", "carriers": [ "pojo", "null" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "findOneByQuery", "carriers": [ "pojo", "null" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "findOneAndDelete", "carriers": [ "pojo", "null" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "findOneAndReplace", "carriers": [ "pojo", "null" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "findOneAndUpdate", "carriers": [ "pojo", "null" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "findAll", "carriers": [ "list" ] }, { "option": "operation", "value": "findDistinct", "carriers": [ "list" ] }, { "option": "operation", "value": "aggregate", "carriers": [ "list" ] }, { "option": "operation", "value": "count", "carriers": [ "value" ], "javaType": "java.lang.Long" }, { "option": "operation", "value": "insert", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "save", "carriers": [ "pojo" ] }, { "option": "operation", "value": "update", "carriers": [ "pojo" ], "javaType": "com.mongodb.client.result.UpdateResult" }, { "option": "operation", "value": "remove", "carriers": [ "pojo" ], "javaType": "com.mongodb.client.result.DeleteResult" }, { "option": "operation", "value": "bulkWrite", "carriers": [ "pojo" ], "javaType": "com.mongodb.bulk.BulkWriteResult" }, { "option": "operation", "value": "command", "carriers": [ "pojo" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "getDbStats", "carriers": [ "pojo" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "getColStats", "carriers": [ "pojo" ], "javaType": "org.bson.Document" } ], "description": "By the operation: a Document or null for a find of one, a List for findAll, findDistinct and aggregate, a Long for count, the document added for insert, the result of the driver for the other writes, and a Document for command and the stats" } + }, "properties": { "connectionBean": { "index": 0, "kind": "path", "displayName": "Connection Bean", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sets the connection bean reference used to lookup a client for connecting to a database if no hosts parameter is present." }, "collection": { "index": 1, "kind": "parameter", "displayName": "Collection", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "endpointIdentity": true, "description": "Sets the name of the MongoDB collection to bind to this endpoint" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/paho-mqtt5.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/paho-mqtt5.json index 3959801c5ee4e..0f670d9baa037 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/paho-mqtt5.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/paho-mqtt5.json @@ -66,6 +66,11 @@ "CamelPahoMqtt5OverrideTopic": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of topic to override and send to instead of topic specified on endpoint.", "constantName": "org.apache.camel.component.paho.mqtt5.PahoMqtt5Constants#CAMEL_PAHO_OVERRIDE_TOPIC" }, "CamelPahoMqtt5MsgProperties": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "consumer,producer", "required": false, "javaType": "org.eclipse.paho.mqttv5.common.packet.MqttProperties", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Consumer: The properties set on the incoming message. Producer: The properties to be set on the outgoing message.", "constantName": "org.apache.camel.component.paho.mqtt5.PahoMqtt5Constants#CAMEL_PAHO_MSG_PROPERTIES" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The payload of the MQTT message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "What converts to a byte array: text, bytes, a stream or a file, sent as the payload" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the topic" }, "automaticReconnect": { "index": 1, "kind": "parameter", "displayName": "Automatic Reconnect", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.paho.mqtt5.PahoMqtt5Configuration", "configurationField": "configuration", "description": "Sets whether the client will automatically attempt to reconnect to the server if the connection is lost. If set to false, the client will not attempt to automatically reconnect to the server in the event that the connection is lost. If set to true, in the event that the connection is lost, the client will attempt to reconnect to the server. It will initially wait 1 second before it attempts to reconnect, for every failed reconnect attempt, the delay will double until it is at 2 minutes at which point the delay will stay at 2 minutes." }, diff --git a/components/camel-mongodb/src/generated/resources/META-INF/org/apache/camel/component/mongodb/mongodb.json b/components/camel-mongodb/src/generated/resources/META-INF/org/apache/camel/component/mongodb/mongodb.json index 62ad7c16ba705..6bfb9c23245ef 100644 --- a/components/camel-mongodb/src/generated/resources/META-INF/org/apache/camel/component/mongodb/mongodb.json +++ b/components/camel-mongodb/src/generated/resources/META-INF/org/apache/camel/component/mongodb/mongodb.json @@ -58,6 +58,11 @@ "CamelMongoDbReturnDocumentType": { "index": 24, "kind": "header", "displayName": "", "group": "producer update one and return", "label": "producer update one and return", "required": false, "javaType": "com.mongodb.client.model.ReturnDocument", "enum": [ "BEFORE", "AFTER" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Indicates which document to return, the document before or after an update and return atomic operation.", "constantName": "org.apache.camel.component.mongodb.MongoDbConstants#RETURN_DOCUMENT" }, "CamelMongoDbOperationOption": { "index": 25, "kind": "header", "displayName": "", "group": "producer update one and options", "label": "producer update one and options", "required": false, "javaType": "Object", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Options to use. When set, options set in the headers will be ignored.", "constantName": "org.apache.camel.component.mongodb.MongoDbConstants#OPTIONS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo" ], "javaType": "org.bson.Document", "byOption": [ { "option": "consumerType", "value": "changeStreams", "carriers": [ "pojo", "null" ] } ], "description": "The document added to the capped collection; with changeStreams the full document of the change, null when the change has none (an update without fullDocument=updateLookup)" }, + "producerIn": { "carriers": [ "any" ], "description": "A document or a query: a Document, a Map or JSON text; a List of them for insert, aggregate and update" }, + "producerOut": { "carriers": [ "unknown" ], "dependsOn": [ "outputType", "writeResultAsHeader" ], "byOption": [ { "option": "operation", "value": "findById", "carriers": [ "pojo", "null" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "findOneByQuery", "carriers": [ "pojo", "null" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "findOneAndDelete", "carriers": [ "pojo", "null" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "findOneAndReplace", "carriers": [ "pojo", "null" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "findOneAndUpdate", "carriers": [ "pojo", "null" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "findAll", "carriers": [ "list" ] }, { "option": "operation", "value": "findDistinct", "carriers": [ "list" ] }, { "option": "operation", "value": "aggregate", "carriers": [ "list" ] }, { "option": "operation", "value": "count", "carriers": [ "value" ], "javaType": "java.lang.Long" }, { "option": "operation", "value": "insert", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "save", "carriers": [ "pojo" ] }, { "option": "operation", "value": "update", "carriers": [ "pojo" ], "javaType": "com.mongodb.client.result.UpdateResult" }, { "option": "operation", "value": "remove", "carriers": [ "pojo" ], "javaType": "com.mongodb.client.result.DeleteResult" }, { "option": "operation", "value": "bulkWrite", "carriers": [ "pojo" ], "javaType": "com.mongodb.bulk.BulkWriteResult" }, { "option": "operation", "value": "command", "carriers": [ "pojo" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "getDbStats", "carriers": [ "pojo" ], "javaType": "org.bson.Document" }, { "option": "operation", "value": "getColStats", "carriers": [ "pojo" ], "javaType": "org.bson.Document" } ], "description": "By the operation: a Document or null for a find of one, a List for findAll, findDistinct and aggregate, a Long for count, the document added for insert, the result of the driver for the other writes, and a Document for command and the stats" } + }, "properties": { "connectionBean": { "index": 0, "kind": "path", "displayName": "Connection Bean", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sets the connection bean reference used to lookup a client for connecting to a database if no hosts parameter is present." }, "collection": { "index": 1, "kind": "parameter", "displayName": "Collection", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "endpointIdentity": true, "description": "Sets the name of the MongoDB collection to bind to this endpoint" }, diff --git a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java index 774d095c2b9b2..feb7ebc4fd87a 100644 --- a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java +++ b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java @@ -40,6 +40,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.StateRepository; @@ -68,6 +71,56 @@ */ @UriEndpoint(firstVersion = "2.19.0", scheme = "mongodb", title = "MongoDB", syntax = "mongodb:connectionBean", category = { Category.DATABASE }, headersClass = MongoDbConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.POJO, javaType = "org.bson.Document", + byOption = @BodyType.When(option = "consumerType", value = "changeStreams", + carrier = { Carrier.POJO, Carrier.NULL }), + description = "The document added to the capped collection; with changeStreams the full" + + " document of the change, null when the change has none (an update" + + " without fullDocument=updateLookup)"), + producerIn = @BodyType(value = Carrier.ANY, + description = "A document or a query: a Document, a Map or JSON text; a List of them for" + + " insert, aggregate and update"), + producerOut = @BodyType(value = Carrier.UNKNOWN, dependsOn = { "outputType", "writeResultAsHeader" }, + byOption = { + @BodyType.When(option = "operation", value = "findById", + carrier = { Carrier.POJO, Carrier.NULL }, + javaType = "org.bson.Document"), + @BodyType.When(option = "operation", value = "findOneByQuery", + carrier = { Carrier.POJO, Carrier.NULL }, + javaType = "org.bson.Document"), + @BodyType.When(option = "operation", value = "findOneAndDelete", + carrier = { Carrier.POJO, Carrier.NULL }, + javaType = "org.bson.Document"), + @BodyType.When(option = "operation", value = "findOneAndReplace", + carrier = { Carrier.POJO, Carrier.NULL }, + javaType = "org.bson.Document"), + @BodyType.When(option = "operation", value = "findOneAndUpdate", + carrier = { Carrier.POJO, Carrier.NULL }, + javaType = "org.bson.Document"), + @BodyType.When(option = "operation", value = "findAll", carrier = Carrier.LIST), + @BodyType.When(option = "operation", value = "findDistinct", carrier = Carrier.LIST), + @BodyType.When(option = "operation", value = "aggregate", carrier = Carrier.LIST), + @BodyType.When(option = "operation", value = "count", carrier = Carrier.VALUE, + javaType = "java.lang.Long"), + @BodyType.When(option = "operation", value = "insert", + carrier = { Carrier.POJO, Carrier.LIST }), + @BodyType.When(option = "operation", value = "save", carrier = Carrier.POJO), + @BodyType.When(option = "operation", value = "update", carrier = Carrier.POJO, + javaType = "com.mongodb.client.result.UpdateResult"), + @BodyType.When(option = "operation", value = "remove", carrier = Carrier.POJO, + javaType = "com.mongodb.client.result.DeleteResult"), + @BodyType.When(option = "operation", value = "bulkWrite", carrier = Carrier.POJO, + javaType = "com.mongodb.bulk.BulkWriteResult"), + @BodyType.When(option = "operation", value = "command", carrier = Carrier.POJO, + javaType = "org.bson.Document"), + @BodyType.When(option = "operation", value = "getDbStats", carrier = Carrier.POJO, + javaType = "org.bson.Document"), + @BodyType.When(option = "operation", value = "getColStats", carrier = Carrier.POJO, + javaType = "org.bson.Document") }, + description = "By the operation: a Document or null for a find of one, a List for" + + " findAll, findDistinct and aggregate, a Long for count, the document" + + " added for insert, the result of the driver for the other writes, and a" + + " Document for command and the stats")) public class MongoDbEndpoint extends DefaultEndpoint implements EndpointServiceLocation { private static final Logger LOG = LoggerFactory.getLogger(MongoDbEndpoint.class); diff --git a/components/camel-paho-mqtt5/src/generated/resources/META-INF/org/apache/camel/component/paho/mqtt5/paho-mqtt5.json b/components/camel-paho-mqtt5/src/generated/resources/META-INF/org/apache/camel/component/paho/mqtt5/paho-mqtt5.json index 3959801c5ee4e..0f670d9baa037 100644 --- a/components/camel-paho-mqtt5/src/generated/resources/META-INF/org/apache/camel/component/paho/mqtt5/paho-mqtt5.json +++ b/components/camel-paho-mqtt5/src/generated/resources/META-INF/org/apache/camel/component/paho/mqtt5/paho-mqtt5.json @@ -66,6 +66,11 @@ "CamelPahoMqtt5OverrideTopic": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of topic to override and send to instead of topic specified on endpoint.", "constantName": "org.apache.camel.component.paho.mqtt5.PahoMqtt5Constants#CAMEL_PAHO_OVERRIDE_TOPIC" }, "CamelPahoMqtt5MsgProperties": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "consumer,producer", "required": false, "javaType": "org.eclipse.paho.mqttv5.common.packet.MqttProperties", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Consumer: The properties set on the incoming message. Producer: The properties to be set on the outgoing message.", "constantName": "org.apache.camel.component.paho.mqtt5.PahoMqtt5Constants#CAMEL_PAHO_MSG_PROPERTIES" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The payload of the MQTT message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "What converts to a byte array: text, bytes, a stream or a file, sent as the payload" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the topic" }, "automaticReconnect": { "index": 1, "kind": "parameter", "displayName": "Automatic Reconnect", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.paho.mqtt5.PahoMqtt5Configuration", "configurationField": "configuration", "description": "Sets whether the client will automatically attempt to reconnect to the server if the connection is lost. If set to false, the client will not attempt to automatically reconnect to the server in the event that the connection is lost. If set to true, in the event that the connection is lost, the client will attempt to reconnect to the server. It will initially wait 1 second before it attempts to reconnect, for every failed reconnect attempt, the delay will double until it is at 2 minutes at which point the delay will stay at 2 minutes." }, diff --git a/components/camel-paho-mqtt5/src/main/java/org/apache/camel/component/paho/mqtt5/PahoMqtt5Endpoint.java b/components/camel-paho-mqtt5/src/main/java/org/apache/camel/component/paho/mqtt5/PahoMqtt5Endpoint.java index de690231832c7..70dea3a4066c8 100644 --- a/components/camel-paho-mqtt5/src/main/java/org/apache/camel/component/paho/mqtt5/PahoMqtt5Endpoint.java +++ b/components/camel-paho-mqtt5/src/main/java/org/apache/camel/component/paho/mqtt5/PahoMqtt5Endpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -44,6 +47,11 @@ @UriEndpoint(firstVersion = "3.8.0", scheme = "paho-mqtt5", title = "Paho MQTT 5", category = { Category.MESSAGING, Category.IOT }, syntax = "paho-mqtt5:topic", headersClass = PahoMqtt5Constants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]", description = "The payload of the MQTT message"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "What converts to a byte array: text, bytes, a stream or a file, sent as" + + " the payload"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class PahoMqtt5Endpoint extends DefaultEndpoint implements EndpointServiceLocation { // Configuration members diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java index 51fc53d6d0bfc..ecae2e67fc50f 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java +++ b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java @@ -155,9 +155,9 @@ void theBodyTypesSayWhatTheBodyIsAfterAStep() throws Exception { .startsWith("pojo (org.w3c.dom.NodeList). The nodes the expression selects. With resultQName=STRING: text")); // a component that does not declare them has none, rather than a guess - JsonObject mongodb = catalogDoc(Map.of("name", "mongodb", "kind", "component", "includeOptions", false)); - assertNull(mongodb.get("bodyTypes")); - assertNull(mongodb.get("bodyTypesHint")); + JsonObject jdbc = catalogDoc(Map.of("name", "jdbc", "kind", "component", "includeOptions", false)); + assertNull(jdbc.get("bodyTypes")); + assertNull(jdbc.get("bodyTypesHint")); } @Test From cd44efe04037751f682f4dafe27c6b027928b9e9 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 16:18:06 +0200 Subject: [PATCH 04/25] CAMEL-24961: camel-catalog - an iterator carrier, and the build rejects an option value without carriers From the review of PR 28241: - An iterator is read once and has no size and no index, so tooling that reads list as a List accepts ${body.size()} or ${body[0]} on it, which fail at runtime. The new iterator carrier names it: sql with outputType=StreamList gives an iterator, not a list. - A @BodyType.When with no carriers (carrier = {}) wrote "carriers": [] into the catalog. The build now rejects it, as it does a side without carriers. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../org/apache/camel/catalog/components/sql.json | 4 ++-- .../META-INF/org/apache/camel/component/sql/sql.json | 4 ++-- .../java/org/apache/camel/component/sql/SqlEndpoint.java | 8 ++++---- .../generated/java/org/apache/camel/spi/BodyType.java | 9 +++++++-- docs/user-manual/modules/ROOT/pages/camel-catalog.adoc | 6 +++--- .../camel/dsl/jbang/core/commands/ai/CatalogDocs.java | 5 +++-- .../org/apache/camel/tooling/model/BodyTypeModel.java | 6 +++--- .../apache/camel/maven/packaging/BodyTypesHelper.java | 8 ++++++-- .../maven/packaging/EndpointSchemaGeneratorMojoTest.java | 2 +- .../packaging/endpoint/SomeEndpointWithBadBodyTypes.java | 6 ++++++ .../src/main/java/org/apache/camel/spi/BodyType.java | 9 +++++++-- 11 files changed, 44 insertions(+), 23 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json index 27ec6331908f9..371e35003ff24 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json @@ -49,9 +49,9 @@ "CamelSqlDataSource": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "javax.sql.DataSource", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To use a specific DataSource to operate on another database than the pre configured DataSource on the component", "constantName": "org.apache.camel.component.sql.SqlConstants#SQL_DATA_SOURCE" } }, "bodyTypes": { - "consumerOut": { "carriers": [ "map" ], "javaType": "java.util.Map", "dependsOn": [ "outputClass", "outputHeader" ], "byOption": [ { "option": "useIterator", "value": "false", "carriers": [ "list" ] }, { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "A row of the query: a Map of the column names and their values" }, + "consumerOut": { "carriers": [ "map" ], "javaType": "java.util.Map", "dependsOn": [ "outputClass", "outputHeader" ], "byOption": [ { "option": "useIterator", "value": "false", "carriers": [ "list" ] }, { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "iterator" ] } ], "description": "A row of the query: a Map of the column names and their values" }, "producerIn": { "carriers": [ "any" ], "description": "The parameters of the query: a Map for the named ones, a List or an array for the # ones; the query itself with useMessageBodyForSql" }, - "producerOut": { "carriers": [ "list", "unchanged" ], "dependsOn": [ "outputClass", "outputHeader", "noop" ], "byOption": [ { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value", "null" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "The rows of a select: a List of Maps of the column names and their values. A query that is not a select leaves the body unchanged, with the count in the CamelSqlUpdateCount header" } + "producerOut": { "carriers": [ "list", "unchanged" ], "dependsOn": [ "outputClass", "outputHeader", "noop" ], "byOption": [ { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value", "null" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "iterator" ] } ], "description": "The rows of a select: a List of Maps of the column names and their values. A query that is not a select leaves the body unchanged, with the count in the CamelSqlUpdateCount header" } }, "properties": { "query": { "index": 0, "kind": "path", "displayName": "Query", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "largeInput": true, "inputLanguage": "sql", "description": "Sets the SQL query to perform. You can externalize the query by using file: or classpath: as prefix and specify the location of the file." }, diff --git a/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json b/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json index 27ec6331908f9..371e35003ff24 100644 --- a/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json +++ b/components/camel-sql/src/generated/resources/META-INF/org/apache/camel/component/sql/sql.json @@ -49,9 +49,9 @@ "CamelSqlDataSource": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "javax.sql.DataSource", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To use a specific DataSource to operate on another database than the pre configured DataSource on the component", "constantName": "org.apache.camel.component.sql.SqlConstants#SQL_DATA_SOURCE" } }, "bodyTypes": { - "consumerOut": { "carriers": [ "map" ], "javaType": "java.util.Map", "dependsOn": [ "outputClass", "outputHeader" ], "byOption": [ { "option": "useIterator", "value": "false", "carriers": [ "list" ] }, { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "A row of the query: a Map of the column names and their values" }, + "consumerOut": { "carriers": [ "map" ], "javaType": "java.util.Map", "dependsOn": [ "outputClass", "outputHeader" ], "byOption": [ { "option": "useIterator", "value": "false", "carriers": [ "list" ] }, { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "iterator" ] } ], "description": "A row of the query: a Map of the column names and their values" }, "producerIn": { "carriers": [ "any" ], "description": "The parameters of the query: a Map for the named ones, a List or an array for the # ones; the query itself with useMessageBodyForSql" }, - "producerOut": { "carriers": [ "list", "unchanged" ], "dependsOn": [ "outputClass", "outputHeader", "noop" ], "byOption": [ { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value", "null" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "The rows of a select: a List of Maps of the column names and their values. A query that is not a select leaves the body unchanged, with the count in the CamelSqlUpdateCount header" } + "producerOut": { "carriers": [ "list", "unchanged" ], "dependsOn": [ "outputClass", "outputHeader", "noop" ], "byOption": [ { "option": "outputType", "value": "SelectOne", "carriers": [ "map", "value", "null" ] }, { "option": "outputType", "value": "StreamList", "carriers": [ "iterator" ] } ], "description": "The rows of a select: a List of Maps of the column names and their values. A query that is not a select leaves the body unchanged, with the count in the CamelSqlUpdateCount header" } }, "properties": { "query": { "index": 0, "kind": "path", "displayName": "Query", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "largeInput": true, "inputLanguage": "sql", "description": "Sets the SQL query to perform. You can externalize the query by using file: or classpath: as prefix and specify the location of the file." }, diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java index ece6dd8ce371c..5ea866d040d28 100644 --- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java +++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java @@ -41,8 +41,8 @@ @BodyType.When(option = "useIterator", value = "false", carrier = Carrier.LIST), @BodyType.When(option = "outputType", value = "SelectOne", carrier = { Carrier.MAP, Carrier.VALUE }), - @BodyType.When(option = "outputType", value = "StreamList", carrier = Carrier.LIST, - javaType = "java.util.Iterator") }, + @BodyType.When(option = "outputType", value = "StreamList", + carrier = Carrier.ITERATOR) }, description = "A row of the query: a Map of the column names and their values"), producerIn = @BodyType(value = Carrier.ANY, description = "The parameters of the query: a Map for the named ones, a List or an array" @@ -52,8 +52,8 @@ byOption = { @BodyType.When(option = "outputType", value = "SelectOne", carrier = { Carrier.MAP, Carrier.VALUE, Carrier.NULL }), - @BodyType.When(option = "outputType", value = "StreamList", carrier = Carrier.LIST, - javaType = "java.util.Iterator") }, + @BodyType.When(option = "outputType", value = "StreamList", + carrier = Carrier.ITERATOR) }, description = "The rows of a select: a List of Maps of the column names and their values." + " A query that is not a select leaves the body unchanged, with the count" + " in the CamelSqlUpdateCount header")) diff --git a/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java b/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java index 366a81f7e7116..8f027971b231d 100644 --- a/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java +++ b/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java @@ -100,7 +100,7 @@ /** * The kinds of Java object a body is in. The runtime sorts the bodies it records into kinds as well (null, payload, * data and collection): text, bytes, a stream, a file and a value are a payload, a map and a pojo are data, a list - * is a collection. + * and an iterator are a collection. */ enum Carrier { @@ -118,8 +118,13 @@ enum Carrier { VALUE("value"), /** A java.util.Map, such as a JSON object parsed or a row of a query. */ MAP("map"), - /** A List, another Collection, an array or an Iterator, such as a JSON array parsed or the rows of a query. */ + /** A List, another Collection or an array, such as a JSON array parsed or the rows of a query. */ LIST("list"), + /** + * An Iterator, which is read once, element by element, and has no size and no index: the rows of a query that + * streams them, or of a CSV file read lazily. + */ + ITERATOR("iterator"), /** Another Java object, such as a DOM Document or a class a payload is unmarshalled into. */ POJO("pojo"), /** The body as it was before the step: for the body after a step only. */ diff --git a/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc b/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc index 78348be8b710e..ce268d3ee666a 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc @@ -145,9 +145,9 @@ one entry per side: |=== Each side has the _carriers_ of the body, the kinds of Java object it is in: `null`, `text`, `bytes`, `stream`, -`file`, `value`, `map`, `list` and `pojo`; `unchanged` for a step that leaves the body as it was, `any` for a step that -takes any body, and `unknown` for a body that depends on what the other system sends or on a class the user -configures. A side can also have the Java type when the body is always of that type, the format of the payload (json, +`file`, `value`, `map`, `list`, `iterator` (read once, with no size and no index) and `pojo`; `unchanged` for a step +that leaves the body as it was, `any` for a step that takes any body, and `unknown` for a body that depends on what +the other system sends or on a class the user configures. A side can also have the Java type when the body is always of that type, the format of the payload (json, xml, csv, yaml, text or binary), the options the body depends on, the body for other values of an option, and a description: diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java index d69c883fbab17..b9b988c5372a5 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java @@ -70,8 +70,9 @@ public final class CatalogDocs { + " gives the route; consumerReply: the bodies it can reply with; producerIn:" + " the bodies a to: can send; producerOut: the body after the to:; marshal," + " unmarshal and expression In/Out: the same for a data format and a" - + " language. Carriers: text, bytes, stream, file, value, map, list, pojo," - + " null, unchanged, any, unknown. A side not listed is not known"; + + " language. Carriers: text, bytes, stream, file, value, map, list," + + " iterator (no size, no index), pojo, null, unchanged, any, unknown. A side" + + " not listed is not known"; /** * The rules a small model gets wrong most: functions live inside the placeholder, operators between placeholders. diff --git a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java index bde3c29c0090a..794c505ecc347 100644 --- a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java +++ b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java @@ -23,9 +23,9 @@ * One side of the body types of a component, data format or language: the body a step needs, or the body it leaves * after it, with the default options (CAMEL-24961). *

- * The carriers are the kinds of Java object the body is in: null, text, bytes, stream, file, value, map, list and pojo; - * unchanged for a step that leaves the body as it was, any for a step that takes any body, and unknown for a body that - * depends on what the other system sends or on a class the user configures. + * The carriers are the kinds of Java object the body is in: null, text, bytes, stream, file, value, map, list, iterator + * and pojo; unchanged for a step that leaves the body as it was, any for a step that takes any body, and unknown for a + * body that depends on what the other system sends or on a class the user configures. */ public class BodyTypeModel { diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java index 02e23fbd3b8bc..2894db39c3729 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java @@ -137,10 +137,14 @@ private static void checkOption(Class owner, String side, String option, Set< } /** - * UNCHANGED is for the body after a step, such as a sql query that leaves it unchanged unless it is a select. ANY - * is for the bodies a step needs. ANY and UNKNOWN stand alone. + * A body has a carrier: an option value without one would say nothing. UNCHANGED is for the body after a step, such + * as a sql query that leaves it unchanged unless it is a select. ANY is for the bodies a step needs. ANY and + * UNKNOWN stand alone. */ private static void check(Class owner, String side, Carrier[] carriers) { + if (carriers.length == 0) { + throw new IllegalArgumentException(owner.getName() + ": the @BodyTypes " + side + " has no carriers"); + } List list = Arrays.asList(carriers); boolean in = IN.contains(side.split(" ")[0]); if (in && list.contains(Carrier.UNCHANGED)) { diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java index 5fa0723fa8f5c..5fa2fe71426d0 100644 --- a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java @@ -278,7 +278,7 @@ void testEndpointWithoutBodyTypes() throws Exception { SomeEndpointWithBadBodyTypes.DataFormatSide.class, SomeEndpointWithBadBodyTypes.ProducerSideOfConsumer.class, SomeEndpointWithBadBodyTypes.UnchangedInput.class, SomeEndpointWithBadBodyTypes.AnyOutput.class, SomeEndpointWithBadBodyTypes.UnknownWithOthers.class, SomeEndpointWithBadBodyTypes.NoCarriers.class, - SomeEndpointWithBadBodyTypes.UnknownOption.class }) + SomeEndpointWithBadBodyTypes.UnknownOption.class, SomeEndpointWithBadBodyTypes.OptionValueWithoutCarriers.class }) void testEndpointWithBadBodyTypes(Class clazz) { addEndpointOptions("output"); model.setConsumerOnly(clazz.getAnnotation(UriEndpoint.class).consumerOnly()); diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java index cd66ff0c96706..9346bf17990e0 100644 --- a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java @@ -63,4 +63,10 @@ public static class NoCarriers { @BodyTypes(producerOut = @BodyType(value = Carrier.TEXT, dependsOn = "nope")) public static class UnknownOption { } + + @UriEndpoint(scheme = "some", syntax = "some", title = "some") + @BodyTypes(producerOut = @BodyType(value = Carrier.TEXT, + byOption = @BodyType.When(option = "output", value = "bytes", carrier = {}))) + public static class OptionValueWithoutCarriers { + } } diff --git a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java index 366a81f7e7116..8f027971b231d 100644 --- a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java +++ b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java @@ -100,7 +100,7 @@ /** * The kinds of Java object a body is in. The runtime sorts the bodies it records into kinds as well (null, payload, * data and collection): text, bytes, a stream, a file and a value are a payload, a map and a pojo are data, a list - * is a collection. + * and an iterator are a collection. */ enum Carrier { @@ -118,8 +118,13 @@ enum Carrier { VALUE("value"), /** A java.util.Map, such as a JSON object parsed or a row of a query. */ MAP("map"), - /** A List, another Collection, an array or an Iterator, such as a JSON array parsed or the rows of a query. */ + /** A List, another Collection or an array, such as a JSON array parsed or the rows of a query. */ LIST("list"), + /** + * An Iterator, which is read once, element by element, and has no size and no index: the rows of a query that + * streams them, or of a CSV file read lazily. + */ + ITERATOR("iterator"), /** Another Java object, such as a DOM Document or a class a payload is unmarshalled into. */ POJO("pojo"), /** The body as it was before the step: for the body after a step only. */ From daec2065d0989e7204c2ba775c6ca215c3912ff2 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 16:20:33 +0200 Subject: [PATCH 05/25] CAMEL-24961: camel-catalog - csv with lazyLoad gives an iterator, and camel_catalog_doc says unknown for no carriers From the review of PR 28242: - The csv data format with lazyLoad=true gives an iterator, with the iterator carrier of PR 28241, not a list. - camel_catalog_doc says unknown for a body without carriers, instead of failing. The build rejects it now, but a catalog read from elsewhere may have one. - Sqs2Endpoint imports org.apache.camel.spi.* already: only the import of the nested BodyType.Carrier stays. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../org/apache/camel/catalog/dataformats/csv.json | 2 +- .../camel/component/aws2/sqs/Sqs2Endpoint.java | 2 -- .../org/apache/camel/dataformat/csv/csv.json | 2 +- .../apache/camel/dataformat/csv/CsvDataFormat.java | 4 ++-- .../dsl/jbang/core/commands/ai/CatalogDocs.java | 4 ++++ .../jbang/core/commands/ai/CatalogDocsTest.java | 14 ++++++++++++++ 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/csv.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/csv.json index 6e696b52703e8..2b073a8fdfe26 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/csv.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/csv.json @@ -19,7 +19,7 @@ "marshalIn": { "carriers": [ "map", "list" ], "description": "One row as a Map, or the rows as a List (or an Iterator) of Maps or Lists" }, "marshalOut": { "carriers": [ "stream" ], "format": "csv", "description": "The CSV in the stream cache, or a byte array when stream caching is off" }, "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "csv" }, - "unmarshalOut": { "carriers": [ "list" ], "dependsOn": [ "recordConverterRef" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "A List of the rows, each a List of its values; with useMaps or useOrderedMaps, a Map of the header names and the values" } + "unmarshalOut": { "carriers": [ "list" ], "dependsOn": [ "recordConverterRef" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "iterator" ] } ], "description": "A List of the rows, each a List of its values; with useMaps or useOrderedMaps, a Map of the header names and the values" } }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, diff --git a/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java b/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java index c4f5fe9575899..7e226d8d92a1e 100644 --- a/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java +++ b/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java @@ -33,9 +33,7 @@ import org.apache.camel.clock.Clock; import org.apache.camel.component.aws2.sqs.client.Sqs2ClientFactory; import org.apache.camel.spi.*; -import org.apache.camel.spi.BodyType; import org.apache.camel.spi.BodyType.Carrier; -import org.apache.camel.spi.BodyTypes; import org.apache.camel.support.MonotonicClock; import org.apache.camel.support.ResourceHelper; import org.apache.camel.support.ScheduledPollEndpoint; diff --git a/components/camel-csv/src/generated/resources/META-INF/org/apache/camel/dataformat/csv/csv.json b/components/camel-csv/src/generated/resources/META-INF/org/apache/camel/dataformat/csv/csv.json index 6e696b52703e8..2b073a8fdfe26 100644 --- a/components/camel-csv/src/generated/resources/META-INF/org/apache/camel/dataformat/csv/csv.json +++ b/components/camel-csv/src/generated/resources/META-INF/org/apache/camel/dataformat/csv/csv.json @@ -19,7 +19,7 @@ "marshalIn": { "carriers": [ "map", "list" ], "description": "One row as a Map, or the rows as a List (or an Iterator) of Maps or Lists" }, "marshalOut": { "carriers": [ "stream" ], "format": "csv", "description": "The CSV in the stream cache, or a byte array when stream caching is off" }, "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "csv" }, - "unmarshalOut": { "carriers": [ "list" ], "dependsOn": [ "recordConverterRef" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "list" ], "javaType": "java.util.Iterator" } ], "description": "A List of the rows, each a List of its values; with useMaps or useOrderedMaps, a Map of the header names and the values" } + "unmarshalOut": { "carriers": [ "list" ], "dependsOn": [ "recordConverterRef" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "iterator" ] } ], "description": "A List of the rows, each a List of its values; with useMaps or useOrderedMaps, a Map of the header names and the values" } }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, diff --git a/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java b/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java index 3baa7fe3c30e7..d90ee300b0c8d 100644 --- a/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java +++ b/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java @@ -45,8 +45,8 @@ description = "The CSV in the stream cache, or a byte array when stream caching is off"), unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "csv"), unmarshalOut = @BodyType(value = Carrier.LIST, dependsOn = "recordConverterRef", - byOption = @BodyType.When(option = "lazyLoad", value = "true", carrier = Carrier.LIST, - javaType = "java.util.Iterator"), + byOption = @BodyType.When(option = "lazyLoad", value = "true", + carrier = Carrier.ITERATOR), description = "A List of the rows, each a List of its values; with useMaps or" + " useOrderedMaps, a Map of the header names and the values")) public class CsvDataFormat extends ServiceSupport implements DataFormat, DataFormatName { diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java index b6777140ce3b7..cf59e42214687 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java @@ -1671,6 +1671,10 @@ static JsonObject bodyTypes(Map bodyTypes) { } private static String carriers(List carriers, String javaType) { + if (carriers.isEmpty()) { + // the build rejects a side without carriers, but a catalog read from elsewhere may have one + return "unknown"; + } String answer = carriers.size() == 1 ? carriers.get(0) : String.join(", ", carriers.subList(0, carriers.size() - 1)) + " or " + carriers.get(carriers.size() - 1); diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java index ecae2e67fc50f..b7a7c781a109c 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java +++ b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java @@ -28,6 +28,7 @@ import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.support.DefaultExchange; import org.apache.camel.support.ExchangeHelper; +import org.apache.camel.tooling.model.BodyTypeModel; import org.apache.camel.tooling.model.EipModel; import org.apache.camel.util.json.JsonArray; import org.apache.camel.util.json.JsonObject; @@ -160,6 +161,19 @@ void theBodyTypesSayWhatTheBodyIsAfterAStep() throws Exception { assertNull(jdbc.get("bodyTypesHint")); } + @Test + void aBodyWithoutCarriersIsUnknown() { + // the build rejects it, but a catalog read from elsewhere may have one: the line says unknown + BodyTypeModel side = new BodyTypeModel(); + side.setCarriers(List.of("text")); + BodyTypeModel.OptionBodyTypeModel bytes = new BodyTypeModel.OptionBodyTypeModel(); + bytes.setOption("output"); + bytes.setValue("bytes"); + side.getByOption().add(bytes); + JsonObject lines = CatalogDocs.bodyTypes(Map.of(BodyTypeModel.PRODUCER_OUT, side)); + assertEquals("text. With output=bytes: unknown", lines.getString(BodyTypeModel.PRODUCER_OUT)); + } + @Test void endpointArgumentValidatesAUriAgainstTheComponent() throws Exception { JsonObject bad = catalogDoc(Map.of("endpoint", "timer:tick?period=5s&fixedRte=true&repeatCount=abc")); From b64c8811fd5f7e3d39f72f475faecd20c0f5a869 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 15:54:58 +0200 Subject: [PATCH 06/25] CAMEL-24961: camel-yaml-dsl-validator - the body walks read the body types of the catalog instead of their own tables The YAML validator's body walks read what a component or a data format does with the body from the catalog, instead of from tables in their source: - the consumer a route starts with (consumerOut): the file as read, text, bytes or data, instead of the file consumer only; - the body after a to: (producerOut): unchanged for log and mock and now for a file write, the response of the http producer as bytes or a stream; - the producers that need text (producerIn), instead of file, ftp, ftps and sftp only; - the body after an unmarshal (unmarshalOut), instead of the json, jacksonXml, yaml and csv table and the options that make something else; - the consumers that reply with text (consumerReply), instead of platform-http; - the consumers that give no body, instead of timer, quartz, scheduler and cron. A side holds for a step only when the step decides every option it depends on: an option the component can also be configured with (the valueDeserializer of kafka) counts only when the endpoint sets it, and a placeholder value is not known. The catalog of an older Camel version has no body types, so the validator's own catalog stands in for it. After a step that fails at runtime the walk stops, so a file write that keeps the body is reported once. The rules about HTTP methods, REST bindings and EIPs stay in the validator; the EIPs get body types with CAMEL-25928. The same reports as before on 1204 human-written route files (the Camel repository, the examples, kamelets, camel-k and camel-kit) and on 1209 model-written ones (the r17 benchmark series), and the doc examples of the validator tests still validate. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../modules/ROOT/pages/camel-catalog.adoc | 4 + .../ROOT/pages/camel-jbang-validation.adoc | 8 +- .../dsl/yaml/validator/BodyTypeFlow.java | 25 +- .../dsl/yaml/validator/CatalogBodyTypes.java | 348 ++++++++++++++++++ .../camel/dsl/yaml/validator/RouteGraph.java | 9 + .../dsl/yaml/validator/TextBodyFlow.java | 154 ++++---- .../dsl/yaml/validator/YamlValidator.java | 20 +- .../dsl/yaml/validator/BodyTypeFlowTest.java | 36 ++ .../dsl/yaml/validator/TextBodyFlowTest.java | 230 +++++++++++- 9 files changed, 749 insertions(+), 85 deletions(-) create mode 100644 dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java diff --git a/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc b/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc index ce268d3ee666a..d97e2614ae783 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc @@ -191,6 +191,10 @@ options a side names exist, that `unchanged` is only on the body after a step an The values are read from the code that sets the body, and checked against the body types the message history records when the routes run. +The YAML validator of the Camel CLI follows the body through the steps of a route with the body types, and reports a +step that cannot work on it, such as a Map that a `to: file` cannot write (see +xref:camel-jbang-validation.adoc#_what_a_running_integration_saw[Camel CLI validation]). + === Documentation in the Catalog The catalog includes the AsciiDoc documentation pages from all modules. This makes the full diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc index 5553b58ff3403..26c18f3af01cd 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc @@ -75,8 +75,12 @@ A part of a Java route the parser cannot work out (a value computed at runtime) The YAML validator follows the message body through the steps of each route, and reports a step that cannot work on it: a field read such as `+${body.qty}+` on text that was never unmarshalled, or a Map that a `to: file` cannot write. -Where the file does not tell what the body is, such as after a `platform-http` or `kafka` consumer, or after a call -with `to: http`, it says nothing. +What a component or a data format does with the body comes from the +xref:camel-catalog.adoc#_body_types_in_the_catalog[body types in the catalog]: the file consumer gives the file it +read, the `http` producer leaves the response as bytes or a stream, and `unmarshal: json` makes a Map or a List. +Where they do not tell what the body is, the validator says nothing: after a `platform-http` consumer the body +depends on the request, and the deserializer of a `kafka` consumer can be set on the component, which the route file +does not show. When an integration runs the routes of the file with the message history on, such as with `camel run --dev`, the validator fills these gaps with what the integration saw at the endpoints of its routes: the body each consumer gave, diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/BodyTypeFlow.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/BodyTypeFlow.java index 10ac2e4adcc4c..613847f223027 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/BodyTypeFlow.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/BodyTypeFlow.java @@ -29,6 +29,7 @@ import static org.apache.camel.dsl.yaml.validator.RouteGraph.Route; import static org.apache.camel.dsl.yaml.validator.RouteGraph.endpointOf; +import static org.apache.camel.dsl.yaml.validator.RouteGraph.from; import static org.apache.camel.dsl.yaml.validator.RouteGraph.normalize; import static org.apache.camel.dsl.yaml.validator.RouteGraph.routes; import static org.apache.camel.dsl.yaml.validator.RouteGraph.scheme; @@ -63,21 +64,15 @@ final class BodyTypeFlow { /** The REST verbs that carry no body, so a route they send to starts with none. */ private static final Set VERBS_WITHOUT_BODY = Set.of("get", "delete", "head"); - /** The consumers that produce no body of their own, so the message reaching the route has none. */ - private static final Set NO_BODY_CONSUMER = Set.of("timer", "quartz", "scheduler", "cron"); - private BodyTypeFlow() { } - static void check(JsonNode target, NodePath path, List errors) { - check(target, path, errors, Set.of()); - } - /** - * @param known the endpoints the caller knows deliver no body, such as {@code direct:getStock} for the GET - * operation of an OpenAPI specification the route binds to (CAMEL-24844 phase B) + * @param known the endpoints the caller knows deliver no body, such as {@code direct:getStock} for the GET + * operation of an OpenAPI specification the route binds to (CAMEL-24844 phase B) + * @param bodyTypes the body types of the catalog, which say the consumers that give no body (timer, cron) */ - static void check(JsonNode target, NodePath path, List errors, Set known) { + static void check(JsonNode target, NodePath path, List errors, Set known, CatalogBodyTypes bodyTypes) { List routes = routes(target); if (routes.isEmpty()) { return; @@ -106,7 +101,7 @@ static void check(JsonNode target, NodePath path, List errors, Set())) { + if (!certainlyWithoutABody(r, callers, restless, new HashSet<>(), bodyTypes)) { continue; } errors.add(Error.builder() @@ -131,7 +126,7 @@ static void check(JsonNode target, NodePath path, List errors, Set> callers, Set restless, - Set seen) { + Set seen, CatalogBodyTypes bodyTypes) { if (!seen.add(route)) { return false; // a cycle: say nothing } @@ -139,7 +134,9 @@ private static boolean certainlyWithoutABody( if (scheme == null) { return false; } - if (NO_BODY_CONSUMER.contains(scheme)) { + // a consumer that produces no body of its own, as the catalog says: timer, cron, scheduler, quartz + CatalogBodyTypes.Answer out = bodyTypes.consumerOut(route.fromUri(), from(route.node())); + if (out != null && out.none()) { return true; } if (!"direct".equals(scheme) && !"seda".equals(scheme) && !"direct-vm".equals(scheme)) { @@ -155,7 +152,7 @@ private static boolean certainlyWithoutABody( if (setsTheBodyBeforeSendingTo(caller, route)) { return false; } - if (!certainlyWithoutABody(caller, callers, restless, seen)) { + if (!certainlyWithoutABody(caller, callers, restless, seen, bodyTypes)) { return false; } } diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java new file mode 100644 index 0000000000000..3259582da25f3 --- /dev/null +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java @@ -0,0 +1,348 @@ +/* + * 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.dsl.yaml.validator; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import com.fasterxml.jackson.databind.JsonNode; +import org.apache.camel.catalog.CamelCatalog; +import org.apache.camel.tooling.model.BaseOptionModel; +import org.apache.camel.tooling.model.BodyTypeModel; +import org.apache.camel.tooling.model.BodyTypeModel.OptionBodyTypeModel; +import org.apache.camel.tooling.model.ComponentModel; +import org.apache.camel.tooling.model.DataFormatModel; +import org.apache.camel.tooling.model.EipModel; + +import static org.apache.camel.dsl.yaml.validator.RouteGraph.scheme; + +/** + * The body types of the catalog (CAMEL-24961), as the walk of {@link TextBodyFlow} reads them: the body a consumer + * gives, the bodies a producer can send and the body it leaves, the body an unmarshal makes, and the bodies a consumer + * that answers its caller can reply with. + *

+ * A side holds for a step only when the step decides every option the side depends on. A component can be configured as + * well ({@code camel.component.kafka.valueDeserializer}), and the route file does not show that: an option of the + * component counts only when the endpoint sets it, and otherwise the side is not known for the step. A value that is + * only known when the route runs (a placeholder) makes it not known too. + */ +final class CatalogBodyTypes { + + /** The carriers of a payload: the text, the bytes, the stream or the file as read or written. */ + private static final Set PAYLOAD = Set.of("text", "bytes", "stream", "file"); + + /** The carriers of parsed data. */ + private static final Set DATA = Set.of("map", "list"); + + private final CamelCatalog catalog; + private final CamelCatalog fallback; + private final Map> components = new ConcurrentHashMap<>(); + private final Map> dataFormats = new ConcurrentHashMap<>(); + private volatile Map> byModelName; + + /** + * @param catalog the catalog of the validator + * @param fallback the catalog to read the body types of a model from when the other has none, as the catalog of an + * older Camel version does; null for none + */ + CatalogBodyTypes(CamelCatalog catalog, CamelCatalog fallback) { + this.catalog = catalog; + this.fallback = fallback; + } + + /** What a side says for a step: its carriers, and its Java type and format when it has them. */ + record Answer(List carriers, String javaType, String format) { + + /** A payload (text, bytes, a stream or a file), maybe no body as well, as an HTTP response without one. */ + boolean payload() { + return carriers.stream().anyMatch(PAYLOAD::contains) && onlyPayload(); + } + + /** Nothing but a payload or no body: no Map, no List, no object of a class. */ + boolean onlyPayload() { + return !carriers.isEmpty() && carriers.stream().allMatch(c -> PAYLOAD.contains(c) || "null".equals(c)); + } + + /** A Map or a List: an iterator is not one, as it is read once and has no index. */ + boolean data() { + return !carriers.isEmpty() && DATA.containsAll(carriers); + } + + /** No body: the consumer gives none (timer). */ + boolean none() { + return carriers.equals(List.of("null")); + } + + /** The body is left as it was. */ + boolean unchanged() { + return carriers.equals(List.of("unchanged")); + } + + /** The file as read. */ + boolean file() { + return carriers.contains("file"); + } + + /** The data format of the format, as an unmarshal or a marshal names it: json, jacksonXml, csv or yaml. */ + String dataFormat() { + if (format == null) { + return null; + } + return switch (format) { + case "json", "csv", "yaml" -> format; + case "xml" -> "jacksonXml"; + default -> null; + }; + } + + /** The carriers in words, without no body: text, bytes, a stream or a file. */ + String inWords() { + List words = new ArrayList<>(); + for (String carrier : carriers) { + switch (carrier) { + case "null" -> { + // a step that needs text takes no body too, and an HTTP response may have none + } + case "stream" -> words.add("a stream"); + case "file" -> words.add("a file"); + case "map" -> words.add("a Map"); + case "list" -> words.add("a List"); + case "iterator" -> words.add("an iterator"); + case "value" -> words.add("a value"); + case "pojo" -> words.add("an object"); + default -> words.add(carrier); + } + } + if (words.size() < 2) { + return String.join("", words); + } + return String.join(", ", words.subList(0, words.size() - 1)) + " or " + words.get(words.size() - 1); + } + } + + /** The body a consumer gives the route it starts. */ + Answer consumerOut(String uri, JsonNode from) { + return componentSide(uri, from, BodyTypeModel.CONSUMER_OUT); + } + + /** The bodies a consumer that answers its caller can reply with: what the route can end with. */ + Answer consumerReply(String uri, JsonNode from) { + return componentSide(uri, from, BodyTypeModel.CONSUMER_REPLY); + } + + /** The bodies a producer can send or write. */ + Answer producerIn(String uri, JsonNode to) { + return componentSide(uri, to, BodyTypeModel.PRODUCER_IN); + } + + /** The body after a producer. */ + Answer producerOut(String uri, JsonNode to) { + return componentSide(uri, to, BodyTypeModel.PRODUCER_OUT); + } + + /** Whether the component of an endpoint is an HTTP component, by its label: platform-http. */ + boolean http(String uri) { + ComponentModel model = component(scheme(uri)); + return model != null && model.getLabel() != null && Arrays.asList(model.getLabel().split(",")).contains("http"); + } + + /** + * The body after an unmarshal with a data format of the YAML DSL (json, csv...) and its options: the data format of + * the catalog is the one its library option names, such as jackson for json. + */ + Answer unmarshalOut(String key, JsonNode options) { + DataFormatModel model = dataFormat(key, options); + return model != null + ? answer(model.getBodyType(BodyTypeModel.UNMARSHAL_OUT), values(options), Set.of()) : null; + } + + private Answer componentSide(String uri, JsonNode node, String side) { + ComponentModel model = component(scheme(uri)); + if (model == null) { + return null; + } + Set configurable = new HashSet<>(); + for (BaseOptionModel option : model.getComponentOptions()) { + configurable.add(option.getName()); + } + Map set = values(node != null && node.isObject() ? node.get("parameters") : null); + String text = node != null && node.isTextual() ? node.asText() + : node != null && node.isObject() && node.has("uri") ? node.get("uri").asText() : null; + set.putAll(query(text)); + return answer(model.getBodyType(side), set, configurable); + } + + /** + * What a side says for the options a step sets: the body for an option value it names, or its body when the options + * it depends on keep their defaults; null when it is not known for the step. + */ + private static Answer answer(BodyTypeModel side, Map set, Set configurable) { + if (side == null) { + return null; + } + Set options = new LinkedHashSet<>(side.getDependsOn()); + side.getByOption().forEach(o -> options.add(o.getOption())); + for (String option : options) { + String value = set.get(option); + if (value == null ? configurable.contains(option) : value.contains("{{") || value.contains("${")) { + // the component may set it, or its value is only known when the route runs + return null; + } + } + Answer matched = null; + for (OptionBodyTypeModel when : side.getByOption()) { + String value = set.get(when.getOption()); + if (value != null && value.equalsIgnoreCase(when.getValue())) { + if (matched != null && !matched.carriers().equals(when.getCarriers())) { + // two options the step sets say different bodies + return null; + } + matched = new Answer(when.getCarriers(), when.getJavaType(), side.getFormat()); + } + } + if (matched != null) { + return matched; + } + if (side.isUnknown() || side.getDependsOn().stream().anyMatch(set::containsKey)) { + return null; + } + return new Answer(side.getCarriers(), side.getJavaType(), side.getFormat()); + } + + /** The options of a node, by name in camel case: allowNullBody as well for allow-null-body. */ + private static Map values(JsonNode node) { + Map answer = new HashMap<>(); + if (node != null && node.isObject()) { + for (var it = node.fieldNames(); it.hasNext();) { + String key = it.next(); + JsonNode value = node.get(key); + answer.put(camelCase(key), value.isValueNode() ? value.asText() : value.toString()); + } + } + return answer; + } + + /** The options in the query of an endpoint uri: file:inbox?noop=true. */ + private static Map query(String uri) { + Map answer = new HashMap<>(); + int q = uri != null ? uri.indexOf('?') : -1; + if (q < 0) { + return answer; + } + for (String pair : uri.substring(q + 1).split("&")) { + int eq = pair.indexOf('='); + if (eq > 0) { + answer.put(camelCase(pair.substring(0, eq)), pair.substring(eq + 1)); + } + } + return answer; + } + + private static String camelCase(String name) { + if (name.indexOf('-') < 0) { + return name; + } + StringBuilder sb = new StringBuilder(name.length()); + boolean upper = false; + for (char c : name.toCharArray()) { + if (c == '-') { + upper = true; + } else { + sb.append(upper ? Character.toUpperCase(c) : c); + upper = false; + } + } + return sb.toString(); + } + + private ComponentModel component(String scheme) { + if (scheme == null) { + return null; + } + return components.computeIfAbsent(scheme, s -> { + ComponentModel model = catalog.componentModel(s); + if ((model == null || model.getBodyTypes().isEmpty()) && fallback != null) { + ComponentModel other = fallback.componentModel(s); + if (other != null && !other.getBodyTypes().isEmpty()) { + model = other; + } + } + return Optional.ofNullable(model); + }).orElse(null); + } + + private DataFormatModel dataFormat(String key, JsonNode options) { + List names = dataFormatNames().getOrDefault(key, List.of()); + String name = names.size() == 1 ? names.get(0) : null; + if (names.size() > 1) { + // json is jackson, gson, fastjson or jsonb: the library option names it + JsonNode library = options != null && options.isObject() ? options.get("library") : null; + String wanted = library != null && library.isValueNode() ? library.asText() : defaultLibrary(key); + name = names.stream().filter(n -> n.equalsIgnoreCase(wanted)).findFirst().orElse(null); + } + if (name == null) { + return null; + } + return dataFormats.computeIfAbsent(name, n -> { + DataFormatModel model = catalog.dataFormatModel(n); + if ((model == null || model.getBodyTypes().isEmpty()) && fallback != null) { + DataFormatModel other = fallback.dataFormatModel(n); + if (other != null && !other.getBodyTypes().isEmpty()) { + model = other; + } + } + return Optional.ofNullable(model); + }).orElse(null); + } + + /** The default of the library option of a data format of the YAML DSL: Jackson for json. */ + private String defaultLibrary(String key) { + EipModel model = catalog.eipModel(key); + if (model != null) { + for (EipModel.EipOptionModel option : model.getOptions()) { + if ("library".equals(option.getName()) && option.getDefaultValue() != null) { + return option.getDefaultValue().toString(); + } + } + } + return null; + } + + /** The data formats of the catalog by the name the YAML DSL gives them: json to fastjson, gson, jackson, jsonb. */ + private Map> dataFormatNames() { + Map> answer = byModelName; + if (answer == null) { + answer = new HashMap<>(); + for (String name : catalog.findDataFormatNames()) { + DataFormatModel model = catalog.dataFormatModel(name); + if (model != null && model.getModelName() != null) { + answer.computeIfAbsent(model.getModelName(), k -> new ArrayList<>()).add(name); + } + } + byModelName = answer; + } + return answer; + } +} diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/RouteGraph.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/RouteGraph.java index 686d6d1e8a7a1..5e73988acea79 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/RouteGraph.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/RouteGraph.java @@ -41,6 +41,15 @@ private RouteGraph() { record Route(String id, String fromUri, JsonNode steps, JsonNode node) { } + /** The from of a route entry, in both the canonical and the short form; null for another entry. */ + static JsonNode from(JsonNode entry) { + if (entry == null || !entry.isObject()) { + return null; + } + JsonNode route = entry.get("route"); + return route != null ? route.get("from") : entry.get("from"); + } + /** The routes of the file, in both the canonical and the short form. */ static List routes(JsonNode target) { List answer = new ArrayList<>(); diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/TextBodyFlow.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/TextBodyFlow.java index 7805e50f33ed6..feb84871f8b09 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/TextBodyFlow.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/TextBodyFlow.java @@ -34,6 +34,7 @@ import org.apache.camel.util.MimeTypeHelper; import static org.apache.camel.dsl.yaml.validator.RouteGraph.endpointOf; +import static org.apache.camel.dsl.yaml.validator.RouteGraph.from; import static org.apache.camel.dsl.yaml.validator.RouteGraph.normalize; import static org.apache.camel.dsl.yaml.validator.RouteGraph.scheme; @@ -52,9 +53,13 @@ * at runtime, because no type converter turns a Map into the stream they write: "No type converter available to convert * from type: java.util.LinkedHashMap to the required type: java.io.InputStream". *

- * Where the walk does not know the body - after a consumer other than the file consumer, or after a to: it cannot - * follow - what a running integration of the routes saw there fills the gap, when all the bodies it saw were of one - * kind (CAMEL-25750): the stream cache of an HTTP request, the List a sql call returns. + * What a component or a data format does with the body comes from the body types of the catalog (CAMEL-24961): the body + * a consumer gives (the file as read), what a producer can write (text, bytes, a stream or a file), the body it leaves + * (log keeps it, the http producer gives the response as bytes or a stream), what an unmarshal makes (a Map or a List), + * and what a consumer can reply with. Where the walk does not know the body - after a consumer or a to: the catalog + * does not say, or after a to: it cannot follow - what a running integration of the routes saw there fills the gap, + * when all the bodies it saw were of one kind (CAMEL-25750): the stream cache of an HTTP request, the List a sql call + * returns. */ final class TextBodyFlow { @@ -92,9 +97,6 @@ final class TextBodyFlow { private static final Set SAME_BODY_BLOCKS = Set.of("choice", "when", "otherwise", "filter", "doTry", "doCatch", "doFinally"); - /** Endpoints that leave the body as it is. */ - private static final Set KEEPS_THE_BODY = Set.of("log", "mock"); - /** Steps that leave the body as it is. */ private static final Set KEEPING_STEPS = Set.of("setHeader", "setHeaders", "setProperty", "setVariable", "setVariables", "removeHeader", "removeHeaders", "removeProperty", "removeProperties", "removeVariable", @@ -106,12 +108,6 @@ final class TextBodyFlow { /** $.sku or $['sku']: a jsonpath that reads a field of the body, which is then an object. */ private static final Pattern JSONPATH_FIELD = Pattern.compile("^\\$\\s*(\\.\\s*[A-Za-z_]|\\[\\s*['\"])"); - /** The data formats whose unmarshal makes a Map or a List of the text. */ - private static final Set PARSES = Set.of("json", "jacksonXml", "yaml", "csv"); - - /** The unmarshal options that make something else of the text: an object of a class, or an iterator. */ - private static final Set NOT_A_MAP = Set.of("unmarshalType", "unmarshalTypeName", "lazyLoad"); - /** The Groovy collection methods whose result is data again: a List or a Map. */ private static final Set GIVES_DATA = Set.of("findAll", "collect", "collectEntries", "grep", "sort", "groupBy", "unique"); @@ -125,9 +121,6 @@ final class TextBodyFlow { /** The parameter of a closure: x -> ... */ private static final Pattern CLOSURE_PARAMETER = Pattern.compile("^\\s*([A-Za-z_]\\w*)\\s*->"); - /** The producers that write the body to a file. */ - private static final Set WRITES_A_FILE = Set.of("file", "ftp", "ftps", "sftp"); - /** * The consumers that bring no HTTP control headers, so an http producer after them picks POST for a body: after an * HTTP consumer, the CamelHttpMethod header of the request picks the method instead. @@ -185,21 +178,21 @@ Set readable() { /** * What a walk knows besides the body: the route, the routes of the file, where reports go (null for a route a step - * calls, which reports from its own walk), whether an http producer sends the body with POST, and the verbs of the + * calls, which reports from its own walk), whether an http producer sends the body with POST, the verbs of the * OpenAPI operations a rest-openapi call can be judged by (empty when a REST binding may write the body), with the - * fields their JSON requests need. + * fields their JSON requests need, and the body types of the catalog. */ private record Walk(String routeId, Map byFrom, List errors, Set seen, boolean post, Map> operations, Map>> requestFields, - Map observed) { + Map observed, CatalogBodyTypes bodyTypes) { /** The walk of a route a step calls: for its outcome alone. */ Walk called() { - return new Walk(null, byFrom, null, seen, false, operations, requestFields, observed); + return new Walk(null, byFrom, null, seen, false, operations, requestFields, observed, bodyTypes); } } - static void check(JsonNode target, NodePath path, List errors, ProjectFacts facts) { + static void check(JsonNode target, NodePath path, List errors, ProjectFacts facts, CatalogBodyTypes bodyTypes) { if (target == null || !target.isArray()) { return; } @@ -240,24 +233,26 @@ static void check(JsonNode target, NodePath path, List errors, ProjectFac String uri = endpointOf(from); String consumer = scheme(uri); boolean post = NO_HTTP_HEADERS.contains(consumer) && !setsHttpHeaders(steps); - Body start = consumerText(from); + Body start = uri != null ? consumerBody(uri, from, bodyTypes) : null; if (start == null && uri != null) { // what the consumer gave in a running integration of the route start = observed(observed, ProjectFacts.consumerKey(uri), "from: " + normalize(uri) + " gave"); } Body end = walk(steps, start, at, new Walk( id, byFrom, errors, new HashSet<>(), post, operations, - requestFields, observed)); - // the body at the end of a platform-http route, or of the route of a REST call, is the reply + requestFields, observed, bodyTypes)); + // the body at the end of the route of a consumer that replies with text (platform-http), or of the route of + // a REST call, is the reply boolean rest = uri != null && restReplies.contains(normalize(uri)); - if (("platform-http".equals(consumer) || rest) && end instanceof Parsed parsed && steps != null + CatalogBodyTypes.Answer reply = uri != null && !rest ? bodyTypes.consumerReply(uri, from) : null; + if ((rest || reply != null && reply.onlyPayload()) && end instanceof Parsed parsed && steps != null && steps.isArray() && !steps.isEmpty() && steps.get(steps.size() - 1).fieldNames().hasNext()) { int last = steps.size() - 1; + String caller = rest ? "REST call" : bodyTypes.http(uri) ? "HTTP request" : consumer + " request"; errors.add(error(at.append(last).append(steps.get(last).fieldNames().next()), id, new Need( - "the body at the end of the route is the reply to the " - + (rest ? "REST call" : "HTTP request"), - "as the last step", rest), + "the body at the end of the route is the reply to the " + caller, "as the last step", + rest), parsed)); } } @@ -272,20 +267,27 @@ private static boolean setsHttpHeaders(JsonNode steps) { return steps != null && steps.toString().toLowerCase(Locale.ROOT).contains("camelhttp"); } - private static JsonNode from(JsonNode entry) { - if (entry == null || !entry.isObject()) { + /** + * The body a consumer starts with, as the catalog says: the file as read (file, ftp), text or bytes (aws2-sqs, + * paho-mqtt5), or data (a row of sql); null when it is not known, or neither text nor data. + */ + private static Body consumerBody(String uri, JsonNode from, CatalogBodyTypes bodyTypes) { + CatalogBodyTypes.Answer out = bodyTypes.consumerOut(uri, from); + if (out == null) { return null; } - JsonNode route = entry.get("route"); - return route != null ? route.get("from") : entry.get("from"); + String consumer = "the " + scheme(uri) + " consumer gives it"; + if (out.payload()) { + // the file as read has the format of the files it reads + return out.file() + ? new Text(consumer + (out.carriers().size() > 1 ? " as " + out.inWords() : ""), fileFormat(from), true) + : new Text(consumer + " as " + out.inWords(), out.dataFormat()); + } + return out.data() ? new Parsed(consumer + " as " + out.inWords(), out.dataFormat()) : null; } - /** The body a consumer starts with: the file consumer reads a file, the text as it is; others are not known. */ - private static Text consumerText(JsonNode from) { - String uri = endpointOf(from); - if (!"file".equals(scheme(uri))) { - return null; - } + /** The format of the files a file consumer reads, by the extension it includes. */ + private static String fileFormat(JsonNode from) { JsonNode parameters = from.get("parameters"); String format = null; for (String key : new String[] { "include", "antInclude", "fileName" }) { @@ -294,7 +296,21 @@ private static Text consumerText(JsonNode from) { format = formatOf(parameters.get(key).asText().replace("\\", "")); } } - return new Text("the file consumer gives it", format, true); + return format; + } + + /** + * The body a producer leaves as the catalog says it: text (the response of the http producer) or data (the List of + * a mongodb findAll); null when it is not known, or neither text nor data. + */ + private static Body producerBody(CatalogBodyTypes.Answer out, String origin) { + if (out == null) { + return null; + } + if (out.payload()) { + return new Text(origin + " as " + out.inWords(), out.dataFormat(), out.file()); + } + return out.data() ? new Parsed(origin + " as " + out.inWords(), out.dataFormat()) : null; } /** @@ -329,6 +345,9 @@ private static Body walk(JsonNode steps, Body body, NodePath at, Walk w) { Parsed element = "split".equals(name) ? splitElement(value, parsed) : null; if (need != null) { w.errors().add(error(here, w.routeId(), need, parsed)); + // the step fails at runtime, so what comes after it is not run with this body: one report + body = null; + continue; } else if (element != null) { walk(value.get("steps"), element, here.append("steps"), w); } @@ -385,7 +404,7 @@ private static Body after(String name, JsonNode value, Body body, Walk w) { : null; } case "unmarshal" -> { - return unmarshalled(value); + return unmarshalled(value, w.bodyTypes()); } case "marshal" -> { String format = value != null && value.isObject() && value.fieldNames().hasNext() @@ -404,11 +423,15 @@ private static Body after(String name, JsonNode value, Body body, Walk w) { } case "to", "toD" -> { String uri = endpointOf(value); - String scheme = scheme(uri); - if (scheme != null && KEEPS_THE_BODY.contains(scheme)) { + CatalogBodyTypes.Answer out = uri != null ? w.bodyTypes().producerOut(uri, value) : null; + if (out != null && out.unchanged()) { + // log, a file write return body; } Body returned = calledRoute(name, uri, body, w); + if (returned == null) { + returned = producerBody(out, name + ": " + normalize(uri) + " returns it"); + } if (returned == null && uri != null) { // what the producer returned in a running integration of the route returned = observed(w.observed(), ProjectFacts.producerKey(uri), @@ -512,22 +535,18 @@ private static Text setBodyText(JsonNode value) { return null; } - /** The body after an unmarshal: parsed data for the data formats that make a Map or a List of the text. */ - private static Parsed unmarshalled(JsonNode value) { + /** + * The body after an unmarshal: parsed data for a data format that makes a Map or a List of the text, as the catalog + * says with the options of the step (not with unmarshalType, which makes an object of a class, or lazyLoad, an + * iterator). + */ + private static Parsed unmarshalled(JsonNode value, CatalogBodyTypes bodyTypes) { if (value == null || !value.isObject() || !value.fieldNames().hasNext()) { return null; } String format = value.fieldNames().next(); - if (!PARSES.contains(format)) { - return null; - } - JsonNode options = value.get(format); - for (String option : NOT_A_MAP) { - if (options != null && options.isObject() && options.has(option)) { - return null; - } - } - return new Parsed("unmarshal: " + format + " turns the text into data", format); + CatalogBodyTypes.Answer out = bodyTypes.unmarshalOut(format, value.get(format)); + return out != null && out.data() ? new Parsed("unmarshal: " + format + " turns the text into data", format) : null; } /** @@ -654,8 +673,10 @@ private record Operation(String spec, String id) { } /** - * A to: that needs the body as text: one that writes a file, an http producer that sends it with POST, or a - * rest-openapi call to an operation whose verb sends it (the producer calls with the verb of the specification). + * A to: that needs the body as text: a producer that the catalog says can only send or write text, bytes, a stream + * or a file (file, ftp), an http producer that sends it with POST, or a rest-openapi call to an operation whose + * verb sends it (the producer calls with the verb of the specification). The http method decides whether the http + * producer sends the body, and a REST binding may write it for rest-openapi: they keep their own rule. */ private static Need needsText(String name, JsonNode value, Walk w) { if (!"to".equals(name) && !"toD".equals(name)) { @@ -666,14 +687,6 @@ private static Need needsText(String name, JsonNode value, Walk w) { if (scheme == null) { return null; } - if (WRITES_A_FILE.contains(scheme)) { - return new Need(name + ": " + scheme + " writes the body to a file", "before this step"); - } - if (w.post() && ("http".equals(scheme) || "https".equals(scheme)) && sendsTheBody(uri, value)) { - return new Need( - name + ": " + scheme + " sends the body as the request (a message with a body is sent as a POST)", - "before this step, or set httpMethod: GET when the call sends no body"); - } if ("rest-openapi".equals(scheme)) { Operation operation = operationOf(uri, value); String verb = operation != null @@ -687,8 +700,21 @@ private static Need needsText(String name, JsonNode value, Walk w) { + verb.toUpperCase(Locale.ROOT) + " in " + operation.spec() + ")", "before this step", true, fields); } + return null; } - return null; + CatalogBodyTypes.Answer in = w.bodyTypes().producerIn(uri, value); + if (in == null || !in.onlyPayload()) { + return null; + } + if ("http".equals(scheme) || "https".equals(scheme)) { + return w.post() && sendsTheBody(uri, value) + ? new Need( + name + ": " + scheme + + " sends the body as the request (a message with a body is sent as a POST)", + "before this step, or set httpMethod: GET when the call sends no body") + : null; + } + return new Need(name + ": " + scheme + " needs the body as " + in.inWords(), "before this step"); } /** diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java index d51ac3e72cb8a..576624c766dc3 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java @@ -87,6 +87,9 @@ public class YamlValidator { private final boolean canonical; private final String schemaJson; private CamelCatalog catalog; + /** The catalog of another Camel version than the one of the validator (CAMEL-24711), if given. */ + private final boolean otherCatalog; + private CatalogBodyTypes bodyTypes; private Schema schema; /** * The schema for a Kamelet: the envelope, with its {@code spec.template} being one entry of the route schema. A @@ -121,6 +124,7 @@ public YamlValidator(boolean canonical, String schemaJson, CamelCatalog catalog) this.canonical = canonical; this.schemaJson = schemaJson; this.catalog = catalog; + this.otherCatalog = catalog != null; } public boolean isCanonical() { @@ -848,9 +852,10 @@ private List validate(JsonNode target, ProjectFacts facts) { checkSimpleSyntaxInScripts(camelOnly, new NodePath(PathType.JSON_POINTER), errors); checkDynamicUri(camelOnly, new NodePath(PathType.JSON_POINTER), errors); // where the body comes from, across the routes of the file (CAMEL-24844) - BodyTypeFlow.check(camelOnly, new NodePath(PathType.JSON_POINTER), errors, facts.bodylessEndpoints()); + BodyTypeFlow.check(camelOnly, new NodePath(PathType.JSON_POINTER), errors, facts.bodylessEndpoints(), + bodyTypes()); // a field read on a body that is still text (CAMEL-24844) - TextBodyFlow.check(camelOnly, new NodePath(PathType.JSON_POINTER), errors, facts); + TextBodyFlow.check(camelOnly, new NodePath(PathType.JSON_POINTER), errors, facts, bodyTypes()); } if (canonical) { checkOneOfCardinality(camelOnly, new NodePath(PathType.JSON_POINTER), errors); @@ -1564,6 +1569,17 @@ private CamelCatalog catalog() { return catalog; } + /** + * The body types of the catalog (CAMEL-24961). The catalog of an older Camel version has none, so the body types of + * the validator's own catalog stand in for a model that has none. + */ + private CatalogBodyTypes bodyTypes() { + if (bodyTypes == null) { + bodyTypes = new CatalogBodyTypes(catalog(), otherCatalog ? new DefaultCamelCatalog() : null); + } + return bodyTypes; + } + private void collectProperties(JsonNode node, Set answer, int depth) { if (node == null || node.isMissingNode() || depth > 3) { return; diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/BodyTypeFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/BodyTypeFlowTest.java index 076987525d9eb..c2bf215eedd8e 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/BodyTypeFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/BodyTypeFlowTest.java @@ -93,6 +93,42 @@ public void testATimerAtTheRootOfTheChain() { assertThat(messages(yaml)).anyMatch(m -> m.contains("reads the message body")); } + @Test + public void testTheConsumersWithoutABodyComeFromTheCatalog() { + // CAMEL-24961: cron gives no body, and neither does an ftp consumer that does not download the file + String yaml = """ + - route: + id: nightly + from: + uri: cron:nightly + parameters: + schedule: 0 0 2 * * ? + steps: + - setHeader: + name: sku + jsonpath: $.sku + - route: + id: listing + from: + uri: ftp:files.example.com/inbox?download=false + steps: + - setHeader: + name: sku + jsonpath: $.sku + - route: + id: files + from: + uri: ftp:files.example.com/inbox + steps: + - setHeader: + name: sku + jsonpath: $.sku + """; + assertThat(messages(yaml)).satisfiesExactly( + m -> assertThat(m).contains("route nightly: jsonpath reads the message body"), + m -> assertThat(m).contains("route listing: jsonpath reads the message body")); + } + @Test public void testAPostCarriesABodySoNothingIsSaid() { String yaml = """ diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java index 976f97598d03e..5c0085afe5a80 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java @@ -16,6 +16,7 @@ */ package org.apache.camel.dsl.yaml.validator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -23,6 +24,9 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; +import org.apache.camel.catalog.DefaultCamelCatalog; +import org.apache.camel.tooling.model.ComponentModel; +import org.apache.camel.tooling.model.DataFormatModel; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -289,7 +293,7 @@ public void testParsedDataWrittenToAFile() { """; assertThat(lines(yaml)).singleElement().satisfies(m -> { assertThat(m).startsWith("Line 12: "); - assertThat(m).contains("route archive: to: file writes the body to a file"); + assertThat(m).contains("route archive: to: file needs the body as text, bytes, a stream or a file"); assertThat(m).contains("the body here is parsed data (a Map or a List), not text"); assertThat(m).contains("unmarshal: json turns the text into data: add marshal: json before this step"); }); @@ -313,7 +317,7 @@ public void testValidateKeepsTheBody() { - to: file:valid """; assertThat(lines(yaml)).singleElement() - .satisfies(m -> assertThat(m).contains("to: file writes the body to a file")); + .satisfies(m -> assertThat(m).contains("to: file needs the body as text, bytes, a stream or a file")); } @Test @@ -818,7 +822,8 @@ public void testTheBodyAProducerReturnedInTheRunningApp() { ProjectFacts seen = observed(ProjectFacts.producerKey("sql:select * from orders"), List.of("java.util.ArrayList"), List.of("collection")); assertThat(lines(yaml, seen)).singleElement().satisfies(m -> { - assertThat(m).contains("to: file writes the body to a file, but the body here is parsed data"); + assertThat(m) + .contains("to: file needs the body as text, bytes, a stream or a file, but the body here is parsed data"); assertThat(m).contains("in the running app, to: sql:select * from orders returned an ArrayList"); // the walk knows no data format for what the running app saw assertThat(m).contains("add marshal with the data format to write (such as marshal: json) before this step"); @@ -866,6 +871,225 @@ public void testWhatTheWalkKnowsComesFirst() { }); } + @Test + public void testTheConsumersOfTheCatalog() { + // CAMEL-24961: what a consumer gives comes from the body types of the catalog + String yaml = """ + - route: + id: sqs + from: + uri: aws2-sqs:orders + steps: + - setHeader: + name: orderId + simple: ${body[orderId]} + - route: + id: mqtt + from: + uri: paho-mqtt5:sensors + steps: + - setBody: + groovy: body.temperature + - route: + id: ftp + from: + uri: ftp:files.example.com/inbox + parameters: + include: .*\\.json + steps: + - setHeader: + name: orderId + simple: ${body[orderId]} + - route: + id: ftpStream + from: + uri: ftp:files.example.com/inbox?streamDownload=true + steps: + - setHeader: + name: orderId + simple: ${body[orderId]} + """; + assertThat(lines(yaml)).satisfiesExactly( + m -> assertThat(m).contains("route sqs: simple reads a field of the body (${body[orderId]})") + .contains("the body here is still text, not parsed data - the aws2-sqs consumer gives it as text"), + m -> assertThat(m).contains("route mqtt: groovy reads fields of the body (body.temperature)") + .contains("the paho-mqtt5 consumer gives it as bytes"), + m -> assertThat(m).contains("route ftp: simple reads a field of the body") + .contains("the body here is the file as it was read (a GenericFile), not parsed data") + .contains("the ftp consumer gives it: add unmarshal: json before this step"), + m -> assertThat(m).contains("route ftpStream: simple reads a field of the body") + .contains("the ftp consumer gives it as a stream")); + } + + @Test + public void testTheProducersOfTheCatalog() { + // the response of the http producer is bytes or a stream, a row of sql is data, and a file write keeps the body + String yaml = """ + - route: + id: price + from: + uri: timer:tick + steps: + - to: https://api.example.com/prices + - setHeader: + name: price + simple: ${body[price]} + - route: + id: rows + from: + uri: sql:select * from orders + steps: + - to: file:orders + - route: + id: archive + from: + uri: file:inbox + steps: + - to: file:backup + - setBody: + groovy: body.items + - route: + id: sensors + from: + uri: file:readings + steps: + - unmarshal: + json: {} + - to: paho-mqtt5:readings + """; + assertThat(lines(yaml)).satisfiesExactly( + m -> assertThat(m).contains("route price: simple reads a field of the body (${body[price]})") + .contains("to: https://api.example.com/prices returns it as bytes or a stream: unmarshal it first"), + m -> assertThat(m).contains("route rows: to: file needs the body as text, bytes, a stream or a file") + .contains("the sql consumer gives it as a Map: add marshal with the data format to write"), + m -> assertThat(m).contains("route archive: groovy reads fields of the body (body.items)") + .contains("the file as it was read (a GenericFile)"), + m -> assertThat(m).contains("route sensors: to: paho-mqtt5 needs the body as text, bytes, a stream or a file") + .contains("unmarshal: json turns the text into data: add marshal: json before this step")); + } + + @Test + public void testTheOptionsTheBodyDependsOn() { + // xslt with output DOM gives a Document, an unmarshal with useList a List, gson is not known, and with download + // false the ftp consumer gives no body + String yaml = """ + - route: + from: + uri: file:in + steps: + - to: xslt:order.xsl?output=DOM + - setBody: + groovy: body.order + - route: + from: + uri: file:in + steps: + - unmarshal: + json: + library: Gson + - to: file:out + - route: + from: + uri: ftp:files.example.com/inbox?download=false + steps: + - setBody: + groovy: body.items + - route: + from: + uri: file:in + steps: + - unmarshal: + json: + useList: true + - to: file:out + """; + assertThat(lines(yaml)).singleElement().satisfies(m -> assertThat(m) + .contains("to: file needs the body as text, bytes, a stream or a file, but the body here is parsed data")); + } + + @Test + public void testWhatTheComponentMayConfigureSaysNothing() { + // the valueDeserializer of kafka and the operation of aws2-sqs can be set on the component, which the route + // does not show; a placeholder is only known when the route runs + String yaml = """ + - route: + from: + uri: kafka:orders + steps: + - setHeader: + name: orderId + simple: ${body[orderId]} + - route: + from: + uri: file:in + steps: + - unmarshal: + json: {} + - to: aws2-sqs:orders + - route: + from: + uri: ftp:files.example.com/inbox?streamDownload={{stream}} + steps: + - setHeader: + name: orderId + simple: ${body[orderId]} + """; + assertThat(lines(yaml)).isEmpty(); + } + + @Test + public void testOneReportForAStepThatFails() { + // the first write fails at runtime, so the second does not run with this body + String yaml = """ + - route: + from: + uri: file:inbox + steps: + - unmarshal: + json: {} + - to: file:archive + - to: file:backup + """; + assertThat(lines(yaml)).singleElement().satisfies(m -> assertThat(m).startsWith("Line 7: ")); + } + + @Test + public void testACatalogWithoutBodyTypes() throws Exception { + // the catalog of an older Camel version has no body types: the validator's own catalog stands in for it + DefaultCamelCatalog older = new DefaultCamelCatalog() { + @Override + public ComponentModel componentModel(String name) { + ComponentModel model = super.componentModel(name); + if (model != null) { + model.setBodyTypes(new LinkedHashMap<>()); + } + return model; + } + + @Override + public DataFormatModel dataFormatModel(String name) { + DataFormatModel model = super.dataFormatModel(name); + if (model != null) { + model.setBodyTypes(new LinkedHashMap<>()); + } + return model; + } + }; + YamlValidator other = new YamlValidator(false, null, older); + other.init(); + String yaml = """ + - route: + from: + uri: file:inbox + steps: + - unmarshal: + json: {} + - to: file:archive + """; + assertThat(YamlValidator.describeAll(yaml, other.validate(yaml))).singleElement() + .satisfies(m -> assertThat(m).contains("to: file needs the body as text, bytes, a stream or a file")); + } + private static ProjectFacts observed(String key, List types, List kinds) { return new ProjectFacts(Set.of(), Map.of(), null, Map.of(), Map.of(key, new ProjectFacts.Observed(types, kinds))); } From 4d64270496b893a76e3ab1c6aad951d46e3d0eeb Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 17:32:12 +0200 Subject: [PATCH 07/25] CAMEL-24961: camel-ai - body types of openai, langchain4j-chat, a2a, docling, milvus, qdrant, ai-tool and ibm-watson-language The AI components declare the body they need and the body they leave, per operation where the operation decides it. The answer of openai and langchain4j-chat is text, also when it is asked for JSON, so the YAML validator now reports a field read on it that has no unmarshal before. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../apache/camel/catalog/components/a2a.json | 6 ++ .../camel/catalog/components/ai-tool.json | 4 + .../camel/catalog/components/docling.json | 5 ++ .../components/ibm-watson-language.json | 4 + .../catalog/components/langchain4j-chat.json | 4 + .../apache/camel/catalog/components/llm.json | 6 ++ .../camel/catalog/components/milvus.json | 4 + .../camel/catalog/components/openai.json | 6 ++ .../camel/catalog/components/qdrant.json | 4 + .../org/apache/camel/component/a2a/a2a.json | 6 ++ .../camel/component/a2a/A2AEndpoint.java | 71 ++++++++++++++++ .../camel/component/ai/tool/ai-tool.json | 4 + .../component/ai/tool/AiToolEndpoint.java | 13 +++ .../camel/component/docling/docling.json | 5 ++ .../component/docling/DoclingEndpoint.java | 66 +++++++++++++++ .../langchain4j/chat/langchain4j-chat.json | 4 + .../chat/LangChain4jChatEndpoint.java | 16 ++++ .../apache/camel/component/milvus/milvus.json | 4 + .../component/milvus/MilvusEndpoint.java | 14 ++++ .../apache/camel/component/openai/llm.json | 6 ++ .../apache/camel/component/openai/openai.json | 6 ++ .../component/openai/OpenAIEndpoint.java | 82 +++++++++++++++++++ .../apache/camel/component/qdrant/qdrant.json | 4 + .../component/qdrant/QdrantEndpoint.java | 18 ++++ .../watson/language/ibm-watson-language.json | 4 + .../language/WatsonLanguageEndpoint.java | 14 ++++ .../ROOT/pages/camel-jbang-validation.adoc | 5 +- 27 files changed, 383 insertions(+), 2 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/a2a.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/a2a.json index 4fb7bd58f9819..2ac1c899e37a7 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/a2a.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/a2a.json @@ -49,6 +49,12 @@ "CamelA2AListStatus": { "index": 17, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Comma-separated status filter for task listing", "constantName": "org.apache.camel.component.a2a.A2AConstants#LIST_STATUS" }, "CamelA2AExtensions": { "index": 18, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "java.util.List", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Negotiated A2A extension URIs requested by the client", "constantName": "org.apache.camel.component.a2a.A2AConstants#EXTENSIONS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text" ], "byOption": [ { "option": "dataFormat", "value": "POJO", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.a2a.model.Message" } ], "description": "The message of the caller, for SendMessage and SendStreamingMessage (the component answers the task and push config requests itself): the text of its parts, one per line, a data part as JSON and a file part as its URL. With dataFormat POJO the Message, with RAW the Message as JSON" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "description": "The reply of the agent: text, sent as one text part (bytes, a stream or a file as their text), or a Message sent as it is. Another body is sent as text: a Task as the text of its last message, a Map or a POJO as its toString(): marshal it first. The reply goes in a Task, completed unless the CamelA2ATaskState header says another state, or as a Message when the CamelA2AResponseType header is message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "byOption": [ { "option": "operation", "value": "TASK_GET", "carriers": [ "any" ] }, { "option": "operation", "value": "TASK_LIST", "carriers": [ "any" ] }, { "option": "operation", "value": "TASK_CANCEL", "carriers": [ "any" ] }, { "option": "operation", "value": "TASK_SUBSCRIBE", "carriers": [ "any" ] }, { "option": "operation", "value": "PUSH_CONFIG_CREATE", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.a2a.model.TaskPushNotificationConfig" }, { "option": "operation", "value": "PUSH_CONFIG_GET", "carriers": [ "any" ] }, { "option": "operation", "value": "PUSH_CONFIG_LIST", "carriers": [ "any" ] }, { "option": "operation", "value": "PUSH_CONFIG_DELETE", "carriers": [ "any" ] } ], "description": "The message to send: text, sent as one text part (bytes, a stream or a file as their text), or a Message sent as it is; MESSAGE_STREAM also takes a SendMessageRequest. Another body is sent as its toString(), so a Map or a POJO needs marshalling first, and JSON text is sent as text. PUSH_CONFIG_CREATE needs a TaskPushNotificationConfig, and the other operations read headers, not the body" }, + "producerOut": { "carriers": [ "text" ], "byOption": [ { "option": "operation", "value": "MESSAGE_STREAM", "carriers": [ "iterator" ], "javaType": "org.apache.camel.component.a2a.streaming.SseEventIterator" }, { "option": "operation", "value": "TASK_GET", "carriers": [ "text" ] }, { "option": "operation", "value": "TASK_LIST", "carriers": [ "list", "null" ] }, { "option": "operation", "value": "TASK_CANCEL", "carriers": [ "text" ] }, { "option": "operation", "value": "TASK_SUBSCRIBE", "carriers": [ "iterator" ], "javaType": "org.apache.camel.component.a2a.streaming.SseEventIterator" }, { "option": "operation", "value": "PUSH_CONFIG_CREATE", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.a2a.model.TaskPushNotificationConfig" }, { "option": "operation", "value": "PUSH_CONFIG_GET", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.a2a.model.TaskPushNotificationConfig" }, { "option": "operation", "value": "PUSH_CONFIG_LIST", "carriers": [ "list", "null" ] }, { "option": "operation", "value": "PUSH_CONFIG_DELETE", "carriers": [ "map" ] }, { "option": "dataFormat", "value": "POJO", "carriers": [ "pojo" ] }, { "option": "dataFormat", "value": "RAW", "carriers": [ "text" ] } ], "description": "The reply of the agent as text: the parts of the Message, or of the last message in the history of the Task, one per line. TASK_GET and TASK_CANCEL give the text of the Task, TASK_LIST a List of Task, MESSAGE_STREAM and TASK_SUBSCRIBE an Iterator of the events as they arrive (split it), and the push config operations a TaskPushNotificationConfig, a List of them, or an empty Map for delete. With dataFormat POJO the Task or the Message, with RAW the JSON of the response as text (a stream of the events for MESSAGE_STREAM and TASK_SUBSCRIBE)" } + }, "properties": { "agentCardSource": { "index": 0, "kind": "path", "displayName": "Agent Card Source", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The agent card source (classpath:, file:, http:\/\/, https:\/\/, or plain name)" }, "agentCard": { "index": 1, "kind": "parameter", "displayName": "Agent Card", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.a2a.model.AgentCard", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.a2a.A2AConfiguration", "configurationField": "configuration", "description": "Agent card bean reference or inline configuration" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ai-tool.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ai-tool.json index 227e918a105ac..c7a63fd81b41e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ai-tool.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ai-tool.json @@ -41,6 +41,10 @@ "autowiredEnabled": { "index": 14, "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." }, "authorizationPolicy": { "index": 15, "kind": "property", "displayName": "Authorization Policy", "group": "security", "label": "consumer,security", "required": false, "type": "object", "javaType": "org.apache.camel.spi.AuthorizationPolicy", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": "configuration", "description": "Reference to an org.apache.camel.spi.AuthorizationPolicy used to authorize tool calls before the route runs. Set it on the component to guard every tool route by construction, or per endpoint to override. The policy authorizes on trustworthy input only: the tool name comes from the route (never from model output), and the caller identity is carried as an exchange property set before the agent ran (for example by camel-spiffe or camel-keycloak), which the model cannot set. Authorize on exchange properties or validated tokens only, never on message headers (on a tool route the headers carry the model-controlled tool arguments). A denied call surfaces to the model as a short refusal rather than a stack trace." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "description": "No body: each argument of the tool call is a header named as its parameter, a Map or a List for a nested JSON value. Undeclared arguments and names starting with camel are dropped" }, + "consumerReply": { "carriers": [ "any" ], "dependsOn": [ "outputSchema", "outputParameters" ], "description": "The tool result, as text: the body converted to a String, so a Map, a List or a POJO is sent as its toString(): marshal it to JSON first. No body gives No result. With outputSchema or outputParameter.NAME options the body must be JSON: a JSON String, a Map, a List, a number or a boolean, and bytes, a stream or another object fail the call" } + }, "properties": { "toolName": { "index": 0, "kind": "path", "displayName": "Tool Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The tool name. This is the name the LLM sees and uses to invoke the tool." }, "argSchema": { "index": 1, "kind": "parameter", "displayName": "Arg Schema", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": "configuration", "description": "Raw JSON Schema for tool input parameters. Supports inline JSON and resource references (classpath:, file:, resource:). Mutually exclusive with the parameter multi-value options. Use for nested objects, arrays, oneOf, and other complex schemas." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/docling.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/docling.json index 2929f7f681345..426611f97d2fd 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/docling.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/docling.json @@ -117,6 +117,11 @@ "CamelDoclingChunkingMaxTokens": { "index": 30, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Maximum tokens per chunk for hybrid chunking", "constantName": "org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MAX_TOKENS" }, "CamelDoclingChunkingMergePeers": { "index": 31, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Whether to merge peer chunks in hybrid chunking", "constantName": "org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MERGE_PEERS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text" ], "description": "The document of an async conversion that completed (SUBMIT_ASYNC_CONVERSION on the same component), as text in the outputFormat it was submitted with: markdown by default, JSON text for json. The task id is in the CamelDoclingTaskId header, and a failed conversion goes to the error handler" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "operation", "value": "BATCH_CONVERT_TO_MARKDOWN", "carriers": [ "list" ] }, { "option": "operation", "value": "BATCH_CONVERT_TO_HTML", "carriers": [ "list" ] }, { "option": "operation", "value": "BATCH_CONVERT_TO_JSON", "carriers": [ "list" ] }, { "option": "operation", "value": "BATCH_EXTRACT_TEXT", "carriers": [ "list" ] }, { "option": "operation", "value": "BATCH_EXTRACT_STRUCTURED_DATA", "carriers": [ "list" ] } ], "description": "The document: its content as text or bytes, or a File (the GenericFile of the file consumers too). A stream or a Path fails: convert it to bytes first. Text that looks like a URL or a path (it starts with http:\/\/, https:\/\/ or \/, or has a backslash) is read as one only with allowUrlSource or allowFilePathSource, and fails otherwise. With the CamelDoclingInputFilePath header the body is not read. The batch operations take a List or an array of paths or files (a directory path with allowFilePathSource), and CHECK_CONVERSION_STATUS the task id, unless the CamelDoclingTaskId header gives it" }, + "producerOut": { "carriers": [ "text" ], "byOption": [ { "option": "operation", "value": "CONVERT_TO_JSON", "carriers": [ "pojo" ], "javaType": "ai.docling.core.DoclingDocument" }, { "option": "operation", "value": "EXTRACT_STRUCTURED_DATA", "carriers": [ "pojo" ], "javaType": "ai.docling.core.DoclingDocument" }, { "option": "operation", "value": "CHECK_CONVERSION_STATUS", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.docling.ConversionStatus" }, { "option": "operation", "value": "EXTRACT_METADATA", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.docling.DocumentMetadata" }, { "option": "operation", "value": "BATCH_CONVERT_TO_MARKDOWN", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "BATCH_CONVERT_TO_HTML", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "BATCH_CONVERT_TO_JSON", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "BATCH_EXTRACT_TEXT", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "BATCH_EXTRACT_STRUCTURED_DATA", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "CHUNK_HYBRID", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "CHUNK_HIERARCHICAL", "carriers": [ "pojo", "list" ] } ], "description": "By the operation: text for the conversions to markdown, HTML and text, which with the docling CLI is the path of the output file unless contentInBody (useDoclingServe gives the content); the task id for SUBMIT_ASYNC_CONVERSION; a DoclingDocument for CONVERT_TO_JSON and EXTRACT_STRUCTURED_DATA; a BatchProcessingResults for the batch operations, a List of BatchConversionResult with splitBatchResults; and a ChunkDocumentResponse for the chunking, a List of Chunk with contentInBody" } + }, "properties": { "operationId": { "index": 0, "kind": "path", "displayName": "Operation Id", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The operation identifier" }, "contentInBody": { "index": 1, "kind": "parameter", "displayName": "Content In Body", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include the content of the output file in the exchange body and delete the output file" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ibm-watson-language.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ibm-watson-language.json index ce47ac5e383e0..d0b502549cf53 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ibm-watson-language.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ibm-watson-language.json @@ -53,6 +53,10 @@ "CamelIBMWatsonLanguageSentimentScore": { "index": 10, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The sentiment score", "constantName": "org.apache.camel.component.ibm.watson.language.WatsonLanguageConstants#SENTIMENT_SCORE" }, "CamelIBMWatsonLanguageSentimentLabel": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The sentiment label (positive, negative, neutral)", "constantName": "org.apache.camel.component.ibm.watson.language.WatsonLanguageConstants#SENTIMENT_LABEL" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The text to analyze for analyzeText, or the URL of the page for analyzeUrl, read as text, unless the CamelIBMWatsonLanguageText or CamelIBMWatsonLanguageUrl header gives it. Without the header, no body or a blank one fails, and a Map or a POJO is analyzed as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "pojo" ], "javaType": "com.ibm.watson.natural_language_understanding.v1.model.AnalysisResults", "description": "The results of the features enabled (sentiment, entities, keywords and so on), with the sentiment score and label and the language in headers too. Converted to text, it is the JSON of the results" } + }, "properties": { "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Logical name" }, "serviceUrl": { "index": 1, "kind": "parameter", "displayName": "Service Url", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.ibm.watson.language.WatsonLanguageConfiguration", "configurationField": "configuration", "description": "The service endpoint URL. If not specified, the default URL will be used." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-chat.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-chat.json index 951f48a17cf57..f1aedc286dafc 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-chat.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/langchain4j-chat.json @@ -48,6 +48,10 @@ "CamelLangChain4jChatRequestModel": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The request model name.", "constantName": "org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#REQUEST_MODEL" }, "CamelLangChain4jChatResponseModel": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The response model name.", "constantName": "org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#RESPONSE_MODEL" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "chatOperation", "value": "CHAT_SINGLE_MESSAGE_WITH_PROMPT", "carriers": [ "map" ] }, { "option": "chatOperation", "value": "CHAT_MULTIPLE_MESSAGES", "carriers": [ "list" ] } ], "description": "The prompt as text, or a ChatMessage; another body is sent as its toString(), and no body fails. CHAT_SINGLE_MESSAGE_WITH_PROMPT takes the variables of the template in the CamelLangChain4jChatPromptTemplate header as a Map, and CHAT_MULTIPLE_MESSAGES a List of ChatMessage" }, + "producerOut": { "carriers": [ "text" ], "description": "The answer of the model as text, also when it is asked for JSON: unmarshal it to read its fields" } + }, "properties": { "chatId": { "index": 0, "kind": "path", "displayName": "Chat Id", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The id" }, "chatOperation": { "index": 1, "kind": "parameter", "displayName": "Chat Operation", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.langchain4j.chat.LangChain4jChatOperations", "enum": [ "CHAT_SINGLE_MESSAGE", "CHAT_SINGLE_MESSAGE_WITH_PROMPT", "CHAT_MULTIPLE_MESSAGES" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "CHAT_SINGLE_MESSAGE", "configurationClass": "org.apache.camel.component.langchain4j.chat.LangChain4jChatConfiguration", "configurationField": "configuration", "description": "Operation in case of Endpoint of type CHAT. The value is one of the values of org.apache.camel.component.langchain4j.chat.LangChain4jChatOperations" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/llm.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/llm.json index a2451cbd1b69b..6870d839b3a6f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/llm.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/llm.json @@ -146,6 +146,12 @@ "CamelOpenAIImageOutputTokens": { "index": 107, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of output tokens billed for the image request. Only reported by GPT image models", "constantName": "org.apache.camel.component.openai.OpenAIConstants#IMAGE_OUTPUT_TOKENS" }, "CamelOpenAIImageTotalTokens": { "index": 108, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The total number of tokens billed for the image request. Only reported by GPT image models", "constantName": "org.apache.camel.component.openai.OpenAIConstants#IMAGE_TOTAL_TOKENS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo" ], "javaType": "com.openai.models.webhooks.UnwrapWebhookEvent", "description": "The event of the webhook operation, verified with webhookSecret, such as a batch or a background response that completed. The event type and the id of the object it is about are in headers" }, + "consumerReply": { "carriers": [ "any" ], "description": "The body at the end of the route is not sent: OpenAI gets 200 without a body, or 500 when the route fails, and then sends the event again" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "operation", "value": "decisions", "carriers": [ "pojo" ], "javaType": "com.openai.models.decisions.DecisionCreateParams" }, { "option": "operation", "value": "batch", "carriers": [ "map", "list", "text", "bytes", "stream", "file" ] }, { "option": "operation", "value": "audio-transcription", "carriers": [ "file", "bytes", "stream" ] }, { "option": "operation", "value": "audio-translation", "carriers": [ "file", "bytes", "stream" ] }, { "option": "operation", "value": "image-edit", "carriers": [ "file", "bytes", "stream", "list" ] } ], "description": "The prompt of chat-completion and responses: text, or a file, bytes or a stream with an image or a PDF (chat-completion also audio), which userMessage then describes. Another body is sent as its toString(), and userMessage or the CamelOpenAIUserMessage header replaces a text body. embeddings and moderation take text or a List of texts (moderation also an image), audio-speech the text to speak, and image-generation the prompt unless imagePrompt is set. batch takes the requests as a Map keyed by custom_id, a List, or JSONL; audio takes the audio and image-edit the image, or a List of images. The operations that read a stored response, a batch or the tool calls of the last answer do not use the body" }, + "producerOut": { "carriers": [ "text" ], "byOption": [ { "option": "streaming", "value": "true", "carriers": [ "iterator" ] }, { "option": "autoToolExecution", "value": "false", "carriers": [ "text", "pojo", "list" ] }, { "option": "operation", "value": "decisions", "carriers": [ "pojo" ], "javaType": "com.openai.models.decisions.Decision" }, { "option": "operation", "value": "responses", "carriers": [ "text" ] }, { "option": "operation", "value": "responses-retrieve", "carriers": [ "text" ] }, { "option": "operation", "value": "responses-cancel", "carriers": [ "text" ] }, { "option": "operation", "value": "batch", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-retrieve", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-cancel", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-results", "carriers": [ "iterator" ] }, { "option": "operation", "value": "embeddings", "carriers": [ "list" ] }, { "option": "operation", "value": "tool-execution", "carriers": [ "null", "unchanged" ] }, { "option": "operation", "value": "audio-transcription", "carriers": [ "text" ] }, { "option": "operation", "value": "audio-translation", "carriers": [ "text" ] }, { "option": "operation", "value": "audio-speech", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "operation", "value": "moderation", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "image-generation", "carriers": [ "bytes", "text", "list" ] }, { "option": "operation", "value": "image-edit", "carriers": [ "bytes", "text", "list" ] } ], "description": "The answer of chat-completion as text, also with outputClass or jsonSchema, where it is JSON text: unmarshal it to read its fields. With streaming, an Iterator of the chunks (text when MCP tools run in a loop). With autoToolExecution=false, the tool calls the model asks for: an Optional of the List of tool calls, or a List of the function calls for responses. embeddings gives a vector (a List of Float), or a List of vectors for a List of texts; image-generation and image-edit the image as bytes or its URL as text, a List for several; batch-results an Iterator of the result lines as Maps. batch and moderation keep the body and set headers, and tool-execution clears it when it runs tool calls" } + }, "properties": { "operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.openai.OpenAIOperations", "enum": [ "chat-completion", "decisions", "responses", "responses-retrieve", "responses-cancel", "batch", "batch-retrieve", "batch-cancel", "batch-results", "embeddings", "tool-execution", "audio-transcription", "audio-translation", "audio-speech", "moderation", "image-generation", "image-edit", "webhook" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The operation to perform: 'chat-completion', 'decisions', 'responses', 'responses-retrieve', 'responses-cancel', 'batch', 'batch-retrieve', 'batch-cancel', 'batch-results', 'embeddings', 'tool-execution', 'audio-transcription', 'audio-translation', 'audio-speech', 'moderation', 'image-generation', 'image-edit', or 'webhook' (a consumer)" }, "additionalBodyProperty": { "index": 1, "kind": "parameter", "displayName": "Additional Body Property", "group": "common", "label": "", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "additionalBodyProperty.", "multiValue": true, "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.openai.OpenAIConfiguration", "configurationField": "configuration", "description": "Additional JSON properties to include in the request body (e.g. additionalBodyProperty.traceId=123). This is a multi-value option with prefix: additionalBodyProperty." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/milvus.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/milvus.json index 401fd632d4ccb..c2c82cb38cd3e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/milvus.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/milvus.json @@ -42,6 +42,10 @@ "CamelMilvusKeyName": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Key Name for Insert\/Upsert operation", "constantName": "org.apache.camel.component.milvus.MilvusHeaders#KEY_NAME" }, "CamelMilvusKeyValue": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Key Value for Insert\/Upsert operation", "constantName": "org.apache.camel.component.milvus.MilvusHeaders#KEY_VALUE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "pojo" ], "description": "The request of the Milvus SDK for the action in the CamelMilvusAction header: a CreateCollectionParam, CreateIndexParam, InsertParam, UpsertParam, SearchSimpleParam, QueryParam or DeleteParam. Another body fails, a vector as a List too: the milvus:embeddings data type transformer builds the InsertParam or UpsertParam from the output of langchain4j-embeddings" }, + "producerOut": { "carriers": [ "pojo" ], "description": "The result of the Milvus SDK for the action: an RpcStatus for CREATE_COLLECTION and CREATE_INDEX, a MutationResult for INSERT, UPSERT and DELETE, a SearchResponse for SEARCH and a QueryResults for QUERY" } + }, "properties": { "collection": { "index": 0, "kind": "path", "displayName": "Collection", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The collection Name" }, "host": { "index": 1, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.milvus.MilvusConfiguration", "configurationField": "configuration", "description": "The host to connect to." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/openai.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/openai.json index d212b19e520cd..4d569fa9d9439 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/openai.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/openai.json @@ -146,6 +146,12 @@ "CamelOpenAIImageOutputTokens": { "index": 107, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of output tokens billed for the image request. Only reported by GPT image models", "constantName": "org.apache.camel.component.openai.OpenAIConstants#IMAGE_OUTPUT_TOKENS" }, "CamelOpenAIImageTotalTokens": { "index": 108, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The total number of tokens billed for the image request. Only reported by GPT image models", "constantName": "org.apache.camel.component.openai.OpenAIConstants#IMAGE_TOTAL_TOKENS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo" ], "javaType": "com.openai.models.webhooks.UnwrapWebhookEvent", "description": "The event of the webhook operation, verified with webhookSecret, such as a batch or a background response that completed. The event type and the id of the object it is about are in headers" }, + "consumerReply": { "carriers": [ "any" ], "description": "The body at the end of the route is not sent: OpenAI gets 200 without a body, or 500 when the route fails, and then sends the event again" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "operation", "value": "decisions", "carriers": [ "pojo" ], "javaType": "com.openai.models.decisions.DecisionCreateParams" }, { "option": "operation", "value": "batch", "carriers": [ "map", "list", "text", "bytes", "stream", "file" ] }, { "option": "operation", "value": "audio-transcription", "carriers": [ "file", "bytes", "stream" ] }, { "option": "operation", "value": "audio-translation", "carriers": [ "file", "bytes", "stream" ] }, { "option": "operation", "value": "image-edit", "carriers": [ "file", "bytes", "stream", "list" ] } ], "description": "The prompt of chat-completion and responses: text, or a file, bytes or a stream with an image or a PDF (chat-completion also audio), which userMessage then describes. Another body is sent as its toString(), and userMessage or the CamelOpenAIUserMessage header replaces a text body. embeddings and moderation take text or a List of texts (moderation also an image), audio-speech the text to speak, and image-generation the prompt unless imagePrompt is set. batch takes the requests as a Map keyed by custom_id, a List, or JSONL; audio takes the audio and image-edit the image, or a List of images. The operations that read a stored response, a batch or the tool calls of the last answer do not use the body" }, + "producerOut": { "carriers": [ "text" ], "byOption": [ { "option": "streaming", "value": "true", "carriers": [ "iterator" ] }, { "option": "autoToolExecution", "value": "false", "carriers": [ "text", "pojo", "list" ] }, { "option": "operation", "value": "decisions", "carriers": [ "pojo" ], "javaType": "com.openai.models.decisions.Decision" }, { "option": "operation", "value": "responses", "carriers": [ "text" ] }, { "option": "operation", "value": "responses-retrieve", "carriers": [ "text" ] }, { "option": "operation", "value": "responses-cancel", "carriers": [ "text" ] }, { "option": "operation", "value": "batch", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-retrieve", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-cancel", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-results", "carriers": [ "iterator" ] }, { "option": "operation", "value": "embeddings", "carriers": [ "list" ] }, { "option": "operation", "value": "tool-execution", "carriers": [ "null", "unchanged" ] }, { "option": "operation", "value": "audio-transcription", "carriers": [ "text" ] }, { "option": "operation", "value": "audio-translation", "carriers": [ "text" ] }, { "option": "operation", "value": "audio-speech", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "operation", "value": "moderation", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "image-generation", "carriers": [ "bytes", "text", "list" ] }, { "option": "operation", "value": "image-edit", "carriers": [ "bytes", "text", "list" ] } ], "description": "The answer of chat-completion as text, also with outputClass or jsonSchema, where it is JSON text: unmarshal it to read its fields. With streaming, an Iterator of the chunks (text when MCP tools run in a loop). With autoToolExecution=false, the tool calls the model asks for: an Optional of the List of tool calls, or a List of the function calls for responses. embeddings gives a vector (a List of Float), or a List of vectors for a List of texts; image-generation and image-edit the image as bytes or its URL as text, a List for several; batch-results an Iterator of the result lines as Maps. batch and moderation keep the body and set headers, and tool-execution clears it when it runs tool calls" } + }, "properties": { "operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.openai.OpenAIOperations", "enum": [ "chat-completion", "decisions", "responses", "responses-retrieve", "responses-cancel", "batch", "batch-retrieve", "batch-cancel", "batch-results", "embeddings", "tool-execution", "audio-transcription", "audio-translation", "audio-speech", "moderation", "image-generation", "image-edit", "webhook" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The operation to perform: 'chat-completion', 'decisions', 'responses', 'responses-retrieve', 'responses-cancel', 'batch', 'batch-retrieve', 'batch-cancel', 'batch-results', 'embeddings', 'tool-execution', 'audio-transcription', 'audio-translation', 'audio-speech', 'moderation', 'image-generation', 'image-edit', or 'webhook' (a consumer)" }, "additionalBodyProperty": { "index": 1, "kind": "parameter", "displayName": "Additional Body Property", "group": "common", "label": "", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "additionalBodyProperty.", "multiValue": true, "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.openai.OpenAIConfiguration", "configurationField": "configuration", "description": "Additional JSON properties to include in the request body (e.g. additionalBodyProperty.traceId=123). This is a multi-value option with prefix: additionalBodyProperty." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/qdrant.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/qdrant.json index 283a45b213cb8..4370a6d815738 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/qdrant.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/qdrant.json @@ -48,6 +48,10 @@ "CamelQdrantPointId": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The point id to use for operation.", "constantName": "org.apache.camel.component.qdrant.QdrantHeaders#POINT_ID" }, "CamelQdrantMaxResults": { "index": 10, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The maximum number of results to return from a similarity search.", "constantName": "org.apache.camel.component.qdrant.QdrantHeaders#MAX_RESULTS" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "pojo", "list", "null" ], "description": "By the action in the CamelQdrantAction header: a VectorParams for CREATE_COLLECTION, a PointStruct or a List of them for UPSERT, a PointId or a List of them for RETRIEVE, a PointsSelector, PointId, Filter or Condition for DELETE, and the query vector as a List of Float, a float array or a PointStruct for SIMILARITY_SEARCH. DELETE_COLLECTION and COLLECTION_INFO do not read the body. Another body fails, such as a number as the id (use PointIdFactory.id) or a List of Double. The qdrant:embeddings data type transformer builds the PointStruct from the output of langchain4j-embeddings" }, + "producerOut": { "carriers": [ "list", "pojo", "unchanged" ], "description": "By the action: a List of RetrievedPoint for RETRIEVE, a List of ScoredPoint for SIMILARITY_SEARCH and a CollectionInfo for COLLECTION_INFO. The other actions keep the body, UPSERT and DELETE with the operation id and status in headers" } + }, "properties": { "collection": { "index": 0, "kind": "path", "displayName": "Collection", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The collection Name" }, "host": { "index": 1, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.qdrant.QdrantConfiguration", "configurationField": "configuration", "description": "The host to connect to." }, diff --git a/components/camel-ai/camel-a2a/src/generated/resources/META-INF/org/apache/camel/component/a2a/a2a.json b/components/camel-ai/camel-a2a/src/generated/resources/META-INF/org/apache/camel/component/a2a/a2a.json index 4fb7bd58f9819..2ac1c899e37a7 100644 --- a/components/camel-ai/camel-a2a/src/generated/resources/META-INF/org/apache/camel/component/a2a/a2a.json +++ b/components/camel-ai/camel-a2a/src/generated/resources/META-INF/org/apache/camel/component/a2a/a2a.json @@ -49,6 +49,12 @@ "CamelA2AListStatus": { "index": 17, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Comma-separated status filter for task listing", "constantName": "org.apache.camel.component.a2a.A2AConstants#LIST_STATUS" }, "CamelA2AExtensions": { "index": 18, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "java.util.List", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Negotiated A2A extension URIs requested by the client", "constantName": "org.apache.camel.component.a2a.A2AConstants#EXTENSIONS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text" ], "byOption": [ { "option": "dataFormat", "value": "POJO", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.a2a.model.Message" } ], "description": "The message of the caller, for SendMessage and SendStreamingMessage (the component answers the task and push config requests itself): the text of its parts, one per line, a data part as JSON and a file part as its URL. With dataFormat POJO the Message, with RAW the Message as JSON" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "description": "The reply of the agent: text, sent as one text part (bytes, a stream or a file as their text), or a Message sent as it is. Another body is sent as text: a Task as the text of its last message, a Map or a POJO as its toString(): marshal it first. The reply goes in a Task, completed unless the CamelA2ATaskState header says another state, or as a Message when the CamelA2AResponseType header is message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "byOption": [ { "option": "operation", "value": "TASK_GET", "carriers": [ "any" ] }, { "option": "operation", "value": "TASK_LIST", "carriers": [ "any" ] }, { "option": "operation", "value": "TASK_CANCEL", "carriers": [ "any" ] }, { "option": "operation", "value": "TASK_SUBSCRIBE", "carriers": [ "any" ] }, { "option": "operation", "value": "PUSH_CONFIG_CREATE", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.a2a.model.TaskPushNotificationConfig" }, { "option": "operation", "value": "PUSH_CONFIG_GET", "carriers": [ "any" ] }, { "option": "operation", "value": "PUSH_CONFIG_LIST", "carriers": [ "any" ] }, { "option": "operation", "value": "PUSH_CONFIG_DELETE", "carriers": [ "any" ] } ], "description": "The message to send: text, sent as one text part (bytes, a stream or a file as their text), or a Message sent as it is; MESSAGE_STREAM also takes a SendMessageRequest. Another body is sent as its toString(), so a Map or a POJO needs marshalling first, and JSON text is sent as text. PUSH_CONFIG_CREATE needs a TaskPushNotificationConfig, and the other operations read headers, not the body" }, + "producerOut": { "carriers": [ "text" ], "byOption": [ { "option": "operation", "value": "MESSAGE_STREAM", "carriers": [ "iterator" ], "javaType": "org.apache.camel.component.a2a.streaming.SseEventIterator" }, { "option": "operation", "value": "TASK_GET", "carriers": [ "text" ] }, { "option": "operation", "value": "TASK_LIST", "carriers": [ "list", "null" ] }, { "option": "operation", "value": "TASK_CANCEL", "carriers": [ "text" ] }, { "option": "operation", "value": "TASK_SUBSCRIBE", "carriers": [ "iterator" ], "javaType": "org.apache.camel.component.a2a.streaming.SseEventIterator" }, { "option": "operation", "value": "PUSH_CONFIG_CREATE", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.a2a.model.TaskPushNotificationConfig" }, { "option": "operation", "value": "PUSH_CONFIG_GET", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.a2a.model.TaskPushNotificationConfig" }, { "option": "operation", "value": "PUSH_CONFIG_LIST", "carriers": [ "list", "null" ] }, { "option": "operation", "value": "PUSH_CONFIG_DELETE", "carriers": [ "map" ] }, { "option": "dataFormat", "value": "POJO", "carriers": [ "pojo" ] }, { "option": "dataFormat", "value": "RAW", "carriers": [ "text" ] } ], "description": "The reply of the agent as text: the parts of the Message, or of the last message in the history of the Task, one per line. TASK_GET and TASK_CANCEL give the text of the Task, TASK_LIST a List of Task, MESSAGE_STREAM and TASK_SUBSCRIBE an Iterator of the events as they arrive (split it), and the push config operations a TaskPushNotificationConfig, a List of them, or an empty Map for delete. With dataFormat POJO the Task or the Message, with RAW the JSON of the response as text (a stream of the events for MESSAGE_STREAM and TASK_SUBSCRIBE)" } + }, "properties": { "agentCardSource": { "index": 0, "kind": "path", "displayName": "Agent Card Source", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The agent card source (classpath:, file:, http:\/\/, https:\/\/, or plain name)" }, "agentCard": { "index": 1, "kind": "parameter", "displayName": "Agent Card", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.a2a.model.AgentCard", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.a2a.A2AConfiguration", "configurationField": "configuration", "description": "Agent card bean reference or inline configuration" }, diff --git a/components/camel-ai/camel-a2a/src/main/java/org/apache/camel/component/a2a/A2AEndpoint.java b/components/camel-ai/camel-a2a/src/main/java/org/apache/camel/component/a2a/A2AEndpoint.java index c9868f484217c..a5abc670b0b6f 100644 --- a/components/camel-ai/camel-a2a/src/main/java/org/apache/camel/component/a2a/A2AEndpoint.java +++ b/components/camel-ai/camel-a2a/src/main/java/org/apache/camel/component/a2a/A2AEndpoint.java @@ -47,6 +47,9 @@ import org.apache.camel.component.a2a.state.A2ATaskStore; import org.apache.camel.component.a2a.state.GuardedTaskStore; import org.apache.camel.component.a2a.state.InMemoryTaskStore; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -70,6 +73,74 @@ syntax = "a2a:agentCardSource", category = { Category.AI }, headersClass = A2AConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.TEXT, + byOption = @BodyType.When(option = "dataFormat", value = "POJO", carrier = Carrier.POJO, + javaType = "org.apache.camel.component.a2a.model.Message"), + description = "The message of the caller, for SendMessage and SendStreamingMessage (the" + + " component answers the task and push config requests itself): the text" + + " of its parts, one per line, a data part as JSON and a file part as its" + + " URL. With dataFormat POJO the Message, with RAW the Message as JSON"), + consumerReply = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + description = "The reply of the agent: text, sent as one text part (bytes, a stream or a" + + " file as their text), or a Message sent as it is. Another body is sent" + + " as text: a Task as the text of its last message, a Map or a POJO as its" + + " toString(): marshal it first. The reply goes in a Task, completed" + + " unless the CamelA2ATaskState header says another state, or as a Message" + + " when the CamelA2AResponseType header is message"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + byOption = { + @BodyType.When(option = "operation", value = "TASK_GET", carrier = Carrier.ANY), + @BodyType.When(option = "operation", value = "TASK_LIST", carrier = Carrier.ANY), + @BodyType.When(option = "operation", value = "TASK_CANCEL", carrier = Carrier.ANY), + @BodyType.When(option = "operation", value = "TASK_SUBSCRIBE", carrier = Carrier.ANY), + @BodyType.When(option = "operation", value = "PUSH_CONFIG_CREATE", + carrier = Carrier.POJO, + javaType = "org.apache.camel.component.a2a.model.TaskPushNotificationConfig"), + @BodyType.When(option = "operation", value = "PUSH_CONFIG_GET", + carrier = Carrier.ANY), + @BodyType.When(option = "operation", value = "PUSH_CONFIG_LIST", + carrier = Carrier.ANY), + @BodyType.When(option = "operation", value = "PUSH_CONFIG_DELETE", + carrier = Carrier.ANY) }, + description = "The message to send: text, sent as one text part (bytes, a stream or a" + + " file as their text), or a Message sent as it is; MESSAGE_STREAM also" + + " takes a SendMessageRequest. Another body is sent as its toString(), so a" + + " Map or a POJO needs marshalling first, and JSON text is sent as text." + + " PUSH_CONFIG_CREATE needs a TaskPushNotificationConfig, and the other" + + " operations read headers, not the body"), + producerOut = @BodyType(value = Carrier.TEXT, + byOption = { + @BodyType.When(option = "operation", value = "MESSAGE_STREAM", + carrier = Carrier.ITERATOR, + javaType = "org.apache.camel.component.a2a.streaming.SseEventIterator"), + @BodyType.When(option = "operation", value = "TASK_GET", carrier = Carrier.TEXT), + @BodyType.When(option = "operation", value = "TASK_LIST", + carrier = { Carrier.LIST, Carrier.NULL }), + @BodyType.When(option = "operation", value = "TASK_CANCEL", carrier = Carrier.TEXT), + @BodyType.When(option = "operation", value = "TASK_SUBSCRIBE", + carrier = Carrier.ITERATOR, + javaType = "org.apache.camel.component.a2a.streaming.SseEventIterator"), + @BodyType.When(option = "operation", value = "PUSH_CONFIG_CREATE", + carrier = Carrier.POJO, + javaType = "org.apache.camel.component.a2a.model.TaskPushNotificationConfig"), + @BodyType.When(option = "operation", value = "PUSH_CONFIG_GET", + carrier = Carrier.POJO, + javaType = "org.apache.camel.component.a2a.model.TaskPushNotificationConfig"), + @BodyType.When(option = "operation", value = "PUSH_CONFIG_LIST", + carrier = { Carrier.LIST, Carrier.NULL }), + @BodyType.When(option = "operation", value = "PUSH_CONFIG_DELETE", + carrier = Carrier.MAP), + @BodyType.When(option = "dataFormat", value = "POJO", carrier = Carrier.POJO), + @BodyType.When(option = "dataFormat", value = "RAW", carrier = Carrier.TEXT) }, + description = "The reply of the agent as text: the parts of the Message, or of the last" + + " message in the history of the Task, one per line. TASK_GET and" + + " TASK_CANCEL give the text of the Task, TASK_LIST a List of Task," + + " MESSAGE_STREAM and TASK_SUBSCRIBE an Iterator of the events as they" + + " arrive (split it), and the push config operations a" + + " TaskPushNotificationConfig, a List of them, or an empty Map for delete." + + " With dataFormat POJO the Task or the Message, with RAW the JSON of the" + + " response as text (a stream of the events for MESSAGE_STREAM and" + + " TASK_SUBSCRIBE)")) public class A2AEndpoint extends DefaultEndpoint { private static final Logger LOG = LoggerFactory.getLogger(A2AEndpoint.class); diff --git a/components/camel-ai/camel-ai-tool/src/generated/resources/META-INF/org/apache/camel/component/ai/tool/ai-tool.json b/components/camel-ai/camel-ai-tool/src/generated/resources/META-INF/org/apache/camel/component/ai/tool/ai-tool.json index 227e918a105ac..c7a63fd81b41e 100644 --- a/components/camel-ai/camel-ai-tool/src/generated/resources/META-INF/org/apache/camel/component/ai/tool/ai-tool.json +++ b/components/camel-ai/camel-ai-tool/src/generated/resources/META-INF/org/apache/camel/component/ai/tool/ai-tool.json @@ -41,6 +41,10 @@ "autowiredEnabled": { "index": 14, "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." }, "authorizationPolicy": { "index": 15, "kind": "property", "displayName": "Authorization Policy", "group": "security", "label": "consumer,security", "required": false, "type": "object", "javaType": "org.apache.camel.spi.AuthorizationPolicy", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": "configuration", "description": "Reference to an org.apache.camel.spi.AuthorizationPolicy used to authorize tool calls before the route runs. Set it on the component to guard every tool route by construction, or per endpoint to override. The policy authorizes on trustworthy input only: the tool name comes from the route (never from model output), and the caller identity is carried as an exchange property set before the agent ran (for example by camel-spiffe or camel-keycloak), which the model cannot set. Authorize on exchange properties or validated tokens only, never on message headers (on a tool route the headers carry the model-controlled tool arguments). A denied call surfaces to the model as a short refusal rather than a stack trace." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "description": "No body: each argument of the tool call is a header named as its parameter, a Map or a List for a nested JSON value. Undeclared arguments and names starting with camel are dropped" }, + "consumerReply": { "carriers": [ "any" ], "dependsOn": [ "outputSchema", "outputParameters" ], "description": "The tool result, as text: the body converted to a String, so a Map, a List or a POJO is sent as its toString(): marshal it to JSON first. No body gives No result. With outputSchema or outputParameter.NAME options the body must be JSON: a JSON String, a Map, a List, a number or a boolean, and bytes, a stream or another object fail the call" } + }, "properties": { "toolName": { "index": 0, "kind": "path", "displayName": "Tool Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The tool name. This is the name the LLM sees and uses to invoke the tool." }, "argSchema": { "index": 1, "kind": "parameter", "displayName": "Arg Schema", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "configurationClass": "org.apache.camel.component.ai.tool.AiToolConfiguration", "configurationField": "configuration", "description": "Raw JSON Schema for tool input parameters. Supports inline JSON and resource references (classpath:, file:, resource:). Mutually exclusive with the parameter multi-value options. Use for nested objects, arrays, oneOf, and other complex schemas." }, diff --git a/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolEndpoint.java b/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolEndpoint.java index 13959fa36d63c..d04929c4df543 100644 --- a/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolEndpoint.java +++ b/components/camel-ai/camel-ai-tool/src/main/java/org/apache/camel/component/ai/tool/AiToolEndpoint.java @@ -20,6 +20,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -42,6 +45,16 @@ consumerOnly = true, remote = false, category = { Category.AI }) +@BodyTypes(consumerOut = @BodyType(value = Carrier.NULL, + description = "No body: each argument of the tool call is a header named as its" + + " parameter, a Map or a List for a nested JSON value. Undeclared" + + " arguments and names starting with camel are dropped"), + consumerReply = @BodyType(value = Carrier.ANY, dependsOn = { "outputSchema", "outputParameters" }, + description = "The tool result, as text: the body converted to a String, so a Map, a" + + " List or a POJO is sent as its toString(): marshal it to JSON first. No" + + " body gives No result. With outputSchema or outputParameter.NAME" + + " options the body must be JSON: a JSON String, a Map, a List, a number" + + " or a boolean, and bytes, a stream or another object fail the call")) public class AiToolEndpoint extends DefaultEndpoint { @Metadata(required = true) diff --git a/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json b/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json index 2929f7f681345..426611f97d2fd 100644 --- a/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json +++ b/components/camel-ai/camel-docling/src/generated/resources/META-INF/org/apache/camel/component/docling/docling.json @@ -117,6 +117,11 @@ "CamelDoclingChunkingMaxTokens": { "index": 30, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Maximum tokens per chunk for hybrid chunking", "constantName": "org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MAX_TOKENS" }, "CamelDoclingChunkingMergePeers": { "index": 31, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Whether to merge peer chunks in hybrid chunking", "constantName": "org.apache.camel.component.docling.DoclingHeaders#CHUNKING_MERGE_PEERS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text" ], "description": "The document of an async conversion that completed (SUBMIT_ASYNC_CONVERSION on the same component), as text in the outputFormat it was submitted with: markdown by default, JSON text for json. The task id is in the CamelDoclingTaskId header, and a failed conversion goes to the error handler" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "operation", "value": "BATCH_CONVERT_TO_MARKDOWN", "carriers": [ "list" ] }, { "option": "operation", "value": "BATCH_CONVERT_TO_HTML", "carriers": [ "list" ] }, { "option": "operation", "value": "BATCH_CONVERT_TO_JSON", "carriers": [ "list" ] }, { "option": "operation", "value": "BATCH_EXTRACT_TEXT", "carriers": [ "list" ] }, { "option": "operation", "value": "BATCH_EXTRACT_STRUCTURED_DATA", "carriers": [ "list" ] } ], "description": "The document: its content as text or bytes, or a File (the GenericFile of the file consumers too). A stream or a Path fails: convert it to bytes first. Text that looks like a URL or a path (it starts with http:\/\/, https:\/\/ or \/, or has a backslash) is read as one only with allowUrlSource or allowFilePathSource, and fails otherwise. With the CamelDoclingInputFilePath header the body is not read. The batch operations take a List or an array of paths or files (a directory path with allowFilePathSource), and CHECK_CONVERSION_STATUS the task id, unless the CamelDoclingTaskId header gives it" }, + "producerOut": { "carriers": [ "text" ], "byOption": [ { "option": "operation", "value": "CONVERT_TO_JSON", "carriers": [ "pojo" ], "javaType": "ai.docling.core.DoclingDocument" }, { "option": "operation", "value": "EXTRACT_STRUCTURED_DATA", "carriers": [ "pojo" ], "javaType": "ai.docling.core.DoclingDocument" }, { "option": "operation", "value": "CHECK_CONVERSION_STATUS", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.docling.ConversionStatus" }, { "option": "operation", "value": "EXTRACT_METADATA", "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.docling.DocumentMetadata" }, { "option": "operation", "value": "BATCH_CONVERT_TO_MARKDOWN", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "BATCH_CONVERT_TO_HTML", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "BATCH_CONVERT_TO_JSON", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "BATCH_EXTRACT_TEXT", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "BATCH_EXTRACT_STRUCTURED_DATA", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "CHUNK_HYBRID", "carriers": [ "pojo", "list" ] }, { "option": "operation", "value": "CHUNK_HIERARCHICAL", "carriers": [ "pojo", "list" ] } ], "description": "By the operation: text for the conversions to markdown, HTML and text, which with the docling CLI is the path of the output file unless contentInBody (useDoclingServe gives the content); the task id for SUBMIT_ASYNC_CONVERSION; a DoclingDocument for CONVERT_TO_JSON and EXTRACT_STRUCTURED_DATA; a BatchProcessingResults for the batch operations, a List of BatchConversionResult with splitBatchResults; and a ChunkDocumentResponse for the chunking, a List of Chunk with contentInBody" } + }, "properties": { "operationId": { "index": 0, "kind": "path", "displayName": "Operation Id", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The operation identifier" }, "contentInBody": { "index": 1, "kind": "parameter", "displayName": "Content In Body", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.docling.DoclingConfiguration", "configurationField": "configuration", "description": "Include the content of the output file in the exchange body and delete the output file" }, diff --git a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingEndpoint.java b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingEndpoint.java index d7e152bfa55f3..9d7f469b717e1 100644 --- a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingEndpoint.java +++ b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingEndpoint.java @@ -20,6 +20,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -33,6 +36,69 @@ title = "Docling", syntax = "docling:operationId", category = { Category.TRANSFORMATION, Category.AI }, headersClass = DoclingHeaders.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.TEXT, + description = "The document of an async conversion that completed" + + " (SUBMIT_ASYNC_CONVERSION on the same component), as text in the" + + " outputFormat it was submitted with: markdown by default, JSON text for" + + " json. The task id is in the CamelDoclingTaskId header, and a failed" + + " conversion goes to the error handler"), + producerIn = @BodyType(value = Carrier.ANY, + byOption = { + @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_MARKDOWN", + carrier = Carrier.LIST), + @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_HTML", + carrier = Carrier.LIST), + @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_JSON", + carrier = Carrier.LIST), + @BodyType.When(option = "operation", value = "BATCH_EXTRACT_TEXT", + carrier = Carrier.LIST), + @BodyType.When(option = "operation", value = "BATCH_EXTRACT_STRUCTURED_DATA", + carrier = Carrier.LIST) }, + description = "The document: its content as text or bytes, or a File (the GenericFile of" + + " the file consumers too). A stream or a Path fails: convert it to bytes" + + " first. Text that looks like a URL or a path (it starts with http://," + + " https:// or /, or has a backslash) is read as one only with" + + " allowUrlSource or allowFilePathSource, and fails otherwise. With the" + + " CamelDoclingInputFilePath header the body is not read. The batch" + + " operations take a List or an array of paths or files (a directory path" + + " with allowFilePathSource), and CHECK_CONVERSION_STATUS the task id, unless" + + " the CamelDoclingTaskId header gives it"), + producerOut = @BodyType(value = Carrier.TEXT, + byOption = { + @BodyType.When(option = "operation", value = "CONVERT_TO_JSON", + carrier = Carrier.POJO, + javaType = "ai.docling.core.DoclingDocument"), + @BodyType.When(option = "operation", value = "EXTRACT_STRUCTURED_DATA", + carrier = Carrier.POJO, + javaType = "ai.docling.core.DoclingDocument"), + @BodyType.When(option = "operation", value = "CHECK_CONVERSION_STATUS", + carrier = Carrier.POJO, + javaType = "org.apache.camel.component.docling.ConversionStatus"), + @BodyType.When(option = "operation", value = "EXTRACT_METADATA", + carrier = Carrier.POJO, + javaType = "org.apache.camel.component.docling.DocumentMetadata"), + @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_MARKDOWN", + carrier = { Carrier.POJO, Carrier.LIST }), + @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_HTML", + carrier = { Carrier.POJO, Carrier.LIST }), + @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_JSON", + carrier = { Carrier.POJO, Carrier.LIST }), + @BodyType.When(option = "operation", value = "BATCH_EXTRACT_TEXT", + carrier = { Carrier.POJO, Carrier.LIST }), + @BodyType.When(option = "operation", value = "BATCH_EXTRACT_STRUCTURED_DATA", + carrier = { Carrier.POJO, Carrier.LIST }), + @BodyType.When(option = "operation", value = "CHUNK_HYBRID", + carrier = { Carrier.POJO, Carrier.LIST }), + @BodyType.When(option = "operation", value = "CHUNK_HIERARCHICAL", + carrier = { Carrier.POJO, Carrier.LIST }) }, + description = "By the operation: text for the conversions to markdown, HTML and text," + + " which with the docling CLI is the path of the output file unless" + + " contentInBody (useDoclingServe gives the content); the task id for" + + " SUBMIT_ASYNC_CONVERSION; a DoclingDocument for CONVERT_TO_JSON and" + + " EXTRACT_STRUCTURED_DATA; a BatchProcessingResults for the batch" + + " operations, a List of BatchConversionResult with splitBatchResults; and a" + + " ChunkDocumentResponse for the chunking, a List of Chunk with" + + " contentInBody")) public class DoclingEndpoint extends ScheduledPollEndpoint { @Metadata(required = true) diff --git a/components/camel-ai/camel-langchain4j-chat/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/chat/langchain4j-chat.json b/components/camel-ai/camel-langchain4j-chat/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/chat/langchain4j-chat.json index 951f48a17cf57..f1aedc286dafc 100644 --- a/components/camel-ai/camel-langchain4j-chat/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/chat/langchain4j-chat.json +++ b/components/camel-ai/camel-langchain4j-chat/src/generated/resources/META-INF/org/apache/camel/component/langchain4j/chat/langchain4j-chat.json @@ -48,6 +48,10 @@ "CamelLangChain4jChatRequestModel": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The request model name.", "constantName": "org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#REQUEST_MODEL" }, "CamelLangChain4jChatResponseModel": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The response model name.", "constantName": "org.apache.camel.component.langchain4j.chat.LangChain4jChatHeaders#RESPONSE_MODEL" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "chatOperation", "value": "CHAT_SINGLE_MESSAGE_WITH_PROMPT", "carriers": [ "map" ] }, { "option": "chatOperation", "value": "CHAT_MULTIPLE_MESSAGES", "carriers": [ "list" ] } ], "description": "The prompt as text, or a ChatMessage; another body is sent as its toString(), and no body fails. CHAT_SINGLE_MESSAGE_WITH_PROMPT takes the variables of the template in the CamelLangChain4jChatPromptTemplate header as a Map, and CHAT_MULTIPLE_MESSAGES a List of ChatMessage" }, + "producerOut": { "carriers": [ "text" ], "description": "The answer of the model as text, also when it is asked for JSON: unmarshal it to read its fields" } + }, "properties": { "chatId": { "index": 0, "kind": "path", "displayName": "Chat Id", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The id" }, "chatOperation": { "index": 1, "kind": "parameter", "displayName": "Chat Operation", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.langchain4j.chat.LangChain4jChatOperations", "enum": [ "CHAT_SINGLE_MESSAGE", "CHAT_SINGLE_MESSAGE_WITH_PROMPT", "CHAT_MULTIPLE_MESSAGES" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "CHAT_SINGLE_MESSAGE", "configurationClass": "org.apache.camel.component.langchain4j.chat.LangChain4jChatConfiguration", "configurationField": "configuration", "description": "Operation in case of Endpoint of type CHAT. The value is one of the values of org.apache.camel.component.langchain4j.chat.LangChain4jChatOperations" }, diff --git a/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatEndpoint.java b/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatEndpoint.java index d333487bb13ea..618d031c8ac85 100644 --- a/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatEndpoint.java +++ b/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatEndpoint.java @@ -20,6 +20,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -33,6 +36,19 @@ syntax = "langchain4j-chat:chatId", producerOnly = true, category = { Category.AI }, headersClass = LangChain4jChatHeaders.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + byOption = { + @BodyType.When(option = "chatOperation", value = "CHAT_SINGLE_MESSAGE_WITH_PROMPT", + carrier = Carrier.MAP), + @BodyType.When(option = "chatOperation", value = "CHAT_MULTIPLE_MESSAGES", + carrier = Carrier.LIST) }, + description = "The prompt as text, or a ChatMessage; another body is sent as its" + + " toString(), and no body fails. CHAT_SINGLE_MESSAGE_WITH_PROMPT takes the" + + " variables of the template in the CamelLangChain4jChatPromptTemplate" + + " header as a Map, and CHAT_MULTIPLE_MESSAGES a List of ChatMessage"), + producerOut = @BodyType(value = Carrier.TEXT, + description = "The answer of the model as text, also when it is asked for JSON: unmarshal" + + " it to read its fields")) public class LangChain4jChatEndpoint extends DefaultEndpoint { @Metadata(required = true) diff --git a/components/camel-ai/camel-milvus/src/generated/resources/META-INF/org/apache/camel/component/milvus/milvus.json b/components/camel-ai/camel-milvus/src/generated/resources/META-INF/org/apache/camel/component/milvus/milvus.json index 401fd632d4ccb..c2c82cb38cd3e 100644 --- a/components/camel-ai/camel-milvus/src/generated/resources/META-INF/org/apache/camel/component/milvus/milvus.json +++ b/components/camel-ai/camel-milvus/src/generated/resources/META-INF/org/apache/camel/component/milvus/milvus.json @@ -42,6 +42,10 @@ "CamelMilvusKeyName": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Key Name for Insert\/Upsert operation", "constantName": "org.apache.camel.component.milvus.MilvusHeaders#KEY_NAME" }, "CamelMilvusKeyValue": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Key Value for Insert\/Upsert operation", "constantName": "org.apache.camel.component.milvus.MilvusHeaders#KEY_VALUE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "pojo" ], "description": "The request of the Milvus SDK for the action in the CamelMilvusAction header: a CreateCollectionParam, CreateIndexParam, InsertParam, UpsertParam, SearchSimpleParam, QueryParam or DeleteParam. Another body fails, a vector as a List too: the milvus:embeddings data type transformer builds the InsertParam or UpsertParam from the output of langchain4j-embeddings" }, + "producerOut": { "carriers": [ "pojo" ], "description": "The result of the Milvus SDK for the action: an RpcStatus for CREATE_COLLECTION and CREATE_INDEX, a MutationResult for INSERT, UPSERT and DELETE, a SearchResponse for SEARCH and a QueryResults for QUERY" } + }, "properties": { "collection": { "index": 0, "kind": "path", "displayName": "Collection", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The collection Name" }, "host": { "index": 1, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.milvus.MilvusConfiguration", "configurationField": "configuration", "description": "The host to connect to." }, diff --git a/components/camel-ai/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusEndpoint.java b/components/camel-ai/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusEndpoint.java index c803a3b4bfdcb..bc647b2b11ea0 100644 --- a/components/camel-ai/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusEndpoint.java +++ b/components/camel-ai/camel-milvus/src/main/java/org/apache/camel/component/milvus/MilvusEndpoint.java @@ -26,6 +26,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -47,6 +50,17 @@ Category.AI }, headersClass = MilvusHeaders.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.POJO, + description = "The request of the Milvus SDK for the action in the CamelMilvusAction" + + " header: a CreateCollectionParam, CreateIndexParam, InsertParam," + + " UpsertParam, SearchSimpleParam, QueryParam or DeleteParam. Another body" + + " fails, a vector as a List too: the milvus:embeddings data type" + + " transformer builds the InsertParam or UpsertParam from the output of" + + " langchain4j-embeddings"), + producerOut = @BodyType(value = Carrier.POJO, + description = "The result of the Milvus SDK for the action: an RpcStatus for" + + " CREATE_COLLECTION and CREATE_INDEX, a MutationResult for INSERT, UPSERT" + + " and DELETE, a SearchResponse for SEARCH and a QueryResults for QUERY")) public class MilvusEndpoint extends DefaultEndpoint implements EndpointServiceLocation { @Metadata(required = true) diff --git a/components/camel-ai/camel-openai/src/generated/resources/META-INF/org/apache/camel/component/openai/llm.json b/components/camel-ai/camel-openai/src/generated/resources/META-INF/org/apache/camel/component/openai/llm.json index a2451cbd1b69b..6870d839b3a6f 100644 --- a/components/camel-ai/camel-openai/src/generated/resources/META-INF/org/apache/camel/component/openai/llm.json +++ b/components/camel-ai/camel-openai/src/generated/resources/META-INF/org/apache/camel/component/openai/llm.json @@ -146,6 +146,12 @@ "CamelOpenAIImageOutputTokens": { "index": 107, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of output tokens billed for the image request. Only reported by GPT image models", "constantName": "org.apache.camel.component.openai.OpenAIConstants#IMAGE_OUTPUT_TOKENS" }, "CamelOpenAIImageTotalTokens": { "index": 108, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The total number of tokens billed for the image request. Only reported by GPT image models", "constantName": "org.apache.camel.component.openai.OpenAIConstants#IMAGE_TOTAL_TOKENS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo" ], "javaType": "com.openai.models.webhooks.UnwrapWebhookEvent", "description": "The event of the webhook operation, verified with webhookSecret, such as a batch or a background response that completed. The event type and the id of the object it is about are in headers" }, + "consumerReply": { "carriers": [ "any" ], "description": "The body at the end of the route is not sent: OpenAI gets 200 without a body, or 500 when the route fails, and then sends the event again" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "operation", "value": "decisions", "carriers": [ "pojo" ], "javaType": "com.openai.models.decisions.DecisionCreateParams" }, { "option": "operation", "value": "batch", "carriers": [ "map", "list", "text", "bytes", "stream", "file" ] }, { "option": "operation", "value": "audio-transcription", "carriers": [ "file", "bytes", "stream" ] }, { "option": "operation", "value": "audio-translation", "carriers": [ "file", "bytes", "stream" ] }, { "option": "operation", "value": "image-edit", "carriers": [ "file", "bytes", "stream", "list" ] } ], "description": "The prompt of chat-completion and responses: text, or a file, bytes or a stream with an image or a PDF (chat-completion also audio), which userMessage then describes. Another body is sent as its toString(), and userMessage or the CamelOpenAIUserMessage header replaces a text body. embeddings and moderation take text or a List of texts (moderation also an image), audio-speech the text to speak, and image-generation the prompt unless imagePrompt is set. batch takes the requests as a Map keyed by custom_id, a List, or JSONL; audio takes the audio and image-edit the image, or a List of images. The operations that read a stored response, a batch or the tool calls of the last answer do not use the body" }, + "producerOut": { "carriers": [ "text" ], "byOption": [ { "option": "streaming", "value": "true", "carriers": [ "iterator" ] }, { "option": "autoToolExecution", "value": "false", "carriers": [ "text", "pojo", "list" ] }, { "option": "operation", "value": "decisions", "carriers": [ "pojo" ], "javaType": "com.openai.models.decisions.Decision" }, { "option": "operation", "value": "responses", "carriers": [ "text" ] }, { "option": "operation", "value": "responses-retrieve", "carriers": [ "text" ] }, { "option": "operation", "value": "responses-cancel", "carriers": [ "text" ] }, { "option": "operation", "value": "batch", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-retrieve", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-cancel", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-results", "carriers": [ "iterator" ] }, { "option": "operation", "value": "embeddings", "carriers": [ "list" ] }, { "option": "operation", "value": "tool-execution", "carriers": [ "null", "unchanged" ] }, { "option": "operation", "value": "audio-transcription", "carriers": [ "text" ] }, { "option": "operation", "value": "audio-translation", "carriers": [ "text" ] }, { "option": "operation", "value": "audio-speech", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "operation", "value": "moderation", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "image-generation", "carriers": [ "bytes", "text", "list" ] }, { "option": "operation", "value": "image-edit", "carriers": [ "bytes", "text", "list" ] } ], "description": "The answer of chat-completion as text, also with outputClass or jsonSchema, where it is JSON text: unmarshal it to read its fields. With streaming, an Iterator of the chunks (text when MCP tools run in a loop). With autoToolExecution=false, the tool calls the model asks for: an Optional of the List of tool calls, or a List of the function calls for responses. embeddings gives a vector (a List of Float), or a List of vectors for a List of texts; image-generation and image-edit the image as bytes or its URL as text, a List for several; batch-results an Iterator of the result lines as Maps. batch and moderation keep the body and set headers, and tool-execution clears it when it runs tool calls" } + }, "properties": { "operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.openai.OpenAIOperations", "enum": [ "chat-completion", "decisions", "responses", "responses-retrieve", "responses-cancel", "batch", "batch-retrieve", "batch-cancel", "batch-results", "embeddings", "tool-execution", "audio-transcription", "audio-translation", "audio-speech", "moderation", "image-generation", "image-edit", "webhook" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The operation to perform: 'chat-completion', 'decisions', 'responses', 'responses-retrieve', 'responses-cancel', 'batch', 'batch-retrieve', 'batch-cancel', 'batch-results', 'embeddings', 'tool-execution', 'audio-transcription', 'audio-translation', 'audio-speech', 'moderation', 'image-generation', 'image-edit', or 'webhook' (a consumer)" }, "additionalBodyProperty": { "index": 1, "kind": "parameter", "displayName": "Additional Body Property", "group": "common", "label": "", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "additionalBodyProperty.", "multiValue": true, "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.openai.OpenAIConfiguration", "configurationField": "configuration", "description": "Additional JSON properties to include in the request body (e.g. additionalBodyProperty.traceId=123). This is a multi-value option with prefix: additionalBodyProperty." }, diff --git a/components/camel-ai/camel-openai/src/generated/resources/META-INF/org/apache/camel/component/openai/openai.json b/components/camel-ai/camel-openai/src/generated/resources/META-INF/org/apache/camel/component/openai/openai.json index d212b19e520cd..4d569fa9d9439 100644 --- a/components/camel-ai/camel-openai/src/generated/resources/META-INF/org/apache/camel/component/openai/openai.json +++ b/components/camel-ai/camel-openai/src/generated/resources/META-INF/org/apache/camel/component/openai/openai.json @@ -146,6 +146,12 @@ "CamelOpenAIImageOutputTokens": { "index": 107, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of output tokens billed for the image request. Only reported by GPT image models", "constantName": "org.apache.camel.component.openai.OpenAIConstants#IMAGE_OUTPUT_TOKENS" }, "CamelOpenAIImageTotalTokens": { "index": 108, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The total number of tokens billed for the image request. Only reported by GPT image models", "constantName": "org.apache.camel.component.openai.OpenAIConstants#IMAGE_TOTAL_TOKENS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo" ], "javaType": "com.openai.models.webhooks.UnwrapWebhookEvent", "description": "The event of the webhook operation, verified with webhookSecret, such as a batch or a background response that completed. The event type and the id of the object it is about are in headers" }, + "consumerReply": { "carriers": [ "any" ], "description": "The body at the end of the route is not sent: OpenAI gets 200 without a body, or 500 when the route fails, and then sends the event again" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "operation", "value": "decisions", "carriers": [ "pojo" ], "javaType": "com.openai.models.decisions.DecisionCreateParams" }, { "option": "operation", "value": "batch", "carriers": [ "map", "list", "text", "bytes", "stream", "file" ] }, { "option": "operation", "value": "audio-transcription", "carriers": [ "file", "bytes", "stream" ] }, { "option": "operation", "value": "audio-translation", "carriers": [ "file", "bytes", "stream" ] }, { "option": "operation", "value": "image-edit", "carriers": [ "file", "bytes", "stream", "list" ] } ], "description": "The prompt of chat-completion and responses: text, or a file, bytes or a stream with an image or a PDF (chat-completion also audio), which userMessage then describes. Another body is sent as its toString(), and userMessage or the CamelOpenAIUserMessage header replaces a text body. embeddings and moderation take text or a List of texts (moderation also an image), audio-speech the text to speak, and image-generation the prompt unless imagePrompt is set. batch takes the requests as a Map keyed by custom_id, a List, or JSONL; audio takes the audio and image-edit the image, or a List of images. The operations that read a stored response, a batch or the tool calls of the last answer do not use the body" }, + "producerOut": { "carriers": [ "text" ], "byOption": [ { "option": "streaming", "value": "true", "carriers": [ "iterator" ] }, { "option": "autoToolExecution", "value": "false", "carriers": [ "text", "pojo", "list" ] }, { "option": "operation", "value": "decisions", "carriers": [ "pojo" ], "javaType": "com.openai.models.decisions.Decision" }, { "option": "operation", "value": "responses", "carriers": [ "text" ] }, { "option": "operation", "value": "responses-retrieve", "carriers": [ "text" ] }, { "option": "operation", "value": "responses-cancel", "carriers": [ "text" ] }, { "option": "operation", "value": "batch", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-retrieve", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-cancel", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "batch-results", "carriers": [ "iterator" ] }, { "option": "operation", "value": "embeddings", "carriers": [ "list" ] }, { "option": "operation", "value": "tool-execution", "carriers": [ "null", "unchanged" ] }, { "option": "operation", "value": "audio-transcription", "carriers": [ "text" ] }, { "option": "operation", "value": "audio-translation", "carriers": [ "text" ] }, { "option": "operation", "value": "audio-speech", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "operation", "value": "moderation", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "image-generation", "carriers": [ "bytes", "text", "list" ] }, { "option": "operation", "value": "image-edit", "carriers": [ "bytes", "text", "list" ] } ], "description": "The answer of chat-completion as text, also with outputClass or jsonSchema, where it is JSON text: unmarshal it to read its fields. With streaming, an Iterator of the chunks (text when MCP tools run in a loop). With autoToolExecution=false, the tool calls the model asks for: an Optional of the List of tool calls, or a List of the function calls for responses. embeddings gives a vector (a List of Float), or a List of vectors for a List of texts; image-generation and image-edit the image as bytes or its URL as text, a List for several; batch-results an Iterator of the result lines as Maps. batch and moderation keep the body and set headers, and tool-execution clears it when it runs tool calls" } + }, "properties": { "operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.openai.OpenAIOperations", "enum": [ "chat-completion", "decisions", "responses", "responses-retrieve", "responses-cancel", "batch", "batch-retrieve", "batch-cancel", "batch-results", "embeddings", "tool-execution", "audio-transcription", "audio-translation", "audio-speech", "moderation", "image-generation", "image-edit", "webhook" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The operation to perform: 'chat-completion', 'decisions', 'responses', 'responses-retrieve', 'responses-cancel', 'batch', 'batch-retrieve', 'batch-cancel', 'batch-results', 'embeddings', 'tool-execution', 'audio-transcription', 'audio-translation', 'audio-speech', 'moderation', 'image-generation', 'image-edit', or 'webhook' (a consumer)" }, "additionalBodyProperty": { "index": 1, "kind": "parameter", "displayName": "Additional Body Property", "group": "common", "label": "", "required": false, "type": "object", "javaType": "java.util.Map", "prefix": "additionalBodyProperty.", "multiValue": true, "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.openai.OpenAIConfiguration", "configurationField": "configuration", "description": "Additional JSON properties to include in the request body (e.g. additionalBodyProperty.traceId=123). This is a multi-value option with prefix: additionalBodyProperty." }, diff --git a/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/OpenAIEndpoint.java b/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/OpenAIEndpoint.java index 1b65e239cb5be..f38b76f35e52c 100644 --- a/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/OpenAIEndpoint.java +++ b/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/OpenAIEndpoint.java @@ -63,6 +63,9 @@ import org.apache.camel.component.ai.tool.AiToolRegistry; import org.apache.camel.component.ai.tool.AiToolRegistryListener; import org.apache.camel.component.ai.tool.AiToolSpec; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -85,6 +88,85 @@ syntax = "openai:operation", category = { Category.AI }, headersClass = OpenAIConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.POJO, javaType = "com.openai.models.webhooks.UnwrapWebhookEvent", + description = "The event of the webhook operation, verified with webhookSecret, such as" + + " a batch or a background response that completed. The event type and" + + " the id of the object it is about are in headers"), + consumerReply = @BodyType(value = Carrier.ANY, + description = "The body at the end of the route is not sent: OpenAI gets 200 without a" + + " body, or 500 when the route fails, and then sends the event again"), + producerIn = @BodyType(value = Carrier.ANY, + byOption = { + @BodyType.When(option = "operation", value = "decisions", carrier = Carrier.POJO, + javaType = "com.openai.models.decisions.DecisionCreateParams"), + @BodyType.When(option = "operation", value = "batch", + carrier = { + Carrier.MAP, Carrier.LIST, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE }), + @BodyType.When(option = "operation", value = "audio-transcription", + carrier = { Carrier.FILE, Carrier.BYTES, Carrier.STREAM }), + @BodyType.When(option = "operation", value = "audio-translation", + carrier = { Carrier.FILE, Carrier.BYTES, Carrier.STREAM }), + @BodyType.When(option = "operation", value = "image-edit", + carrier = { + Carrier.FILE, Carrier.BYTES, Carrier.STREAM, + Carrier.LIST }) }, + description = "The prompt of chat-completion and responses: text, or a file, bytes or a" + + " stream with an image or a PDF (chat-completion also audio), which" + + " userMessage then describes. Another body is sent as its toString()," + + " and userMessage or the CamelOpenAIUserMessage header replaces a text" + + " body. embeddings and moderation take text or a List of texts" + + " (moderation also an image), audio-speech the text to speak, and" + + " image-generation the prompt unless imagePrompt is set. batch takes the" + + " requests as a Map keyed by custom_id, a List, or JSONL; audio takes the" + + " audio and image-edit the image, or a List of images. The operations" + + " that read a stored response, a batch or the tool calls of the last" + + " answer do not use the body"), + producerOut = @BodyType(value = Carrier.TEXT, + byOption = { + @BodyType.When(option = "streaming", value = "true", carrier = Carrier.ITERATOR), + @BodyType.When(option = "autoToolExecution", value = "false", + carrier = { Carrier.TEXT, Carrier.POJO, Carrier.LIST }), + @BodyType.When(option = "operation", value = "decisions", carrier = Carrier.POJO, + javaType = "com.openai.models.decisions.Decision"), + @BodyType.When(option = "operation", value = "responses", carrier = Carrier.TEXT), + @BodyType.When(option = "operation", value = "responses-retrieve", + carrier = Carrier.TEXT), + @BodyType.When(option = "operation", value = "responses-cancel", + carrier = Carrier.TEXT), + @BodyType.When(option = "operation", value = "batch", carrier = Carrier.UNCHANGED), + @BodyType.When(option = "operation", value = "batch-retrieve", + carrier = Carrier.UNCHANGED), + @BodyType.When(option = "operation", value = "batch-cancel", + carrier = Carrier.UNCHANGED), + @BodyType.When(option = "operation", value = "batch-results", + carrier = Carrier.ITERATOR), + @BodyType.When(option = "operation", value = "embeddings", carrier = Carrier.LIST), + @BodyType.When(option = "operation", value = "tool-execution", + carrier = { Carrier.NULL, Carrier.UNCHANGED }), + @BodyType.When(option = "operation", value = "audio-transcription", + carrier = Carrier.TEXT), + @BodyType.When(option = "operation", value = "audio-translation", + carrier = Carrier.TEXT), + @BodyType.When(option = "operation", value = "audio-speech", carrier = Carrier.BYTES, + javaType = "byte[]"), + @BodyType.When(option = "operation", value = "moderation", + carrier = Carrier.UNCHANGED), + @BodyType.When(option = "operation", value = "image-generation", + carrier = { Carrier.BYTES, Carrier.TEXT, Carrier.LIST }), + @BodyType.When(option = "operation", value = "image-edit", + carrier = { Carrier.BYTES, Carrier.TEXT, Carrier.LIST }) }, + description = "The answer of chat-completion as text, also with outputClass or" + + " jsonSchema, where it is JSON text: unmarshal it to read its fields." + + " With streaming, an Iterator of the chunks (text when MCP tools run in" + + " a loop). With autoToolExecution=false, the tool calls the model asks" + + " for: an Optional of the List of tool calls, or a List of the function" + + " calls for responses. embeddings gives a vector (a List of Float), or a" + + " List of vectors for a List of texts; image-generation and image-edit" + + " the image as bytes or its URL as text, a List for several; batch-results" + + " an Iterator of the result lines as Maps. batch and moderation keep the" + + " body and set headers, and tool-execution clears it when it runs tool" + + " calls")) public class OpenAIEndpoint extends DefaultEndpoint { private static final Logger LOG = LoggerFactory.getLogger(OpenAIEndpoint.class); diff --git a/components/camel-ai/camel-qdrant/src/generated/resources/META-INF/org/apache/camel/component/qdrant/qdrant.json b/components/camel-ai/camel-qdrant/src/generated/resources/META-INF/org/apache/camel/component/qdrant/qdrant.json index 283a45b213cb8..4370a6d815738 100644 --- a/components/camel-ai/camel-qdrant/src/generated/resources/META-INF/org/apache/camel/component/qdrant/qdrant.json +++ b/components/camel-ai/camel-qdrant/src/generated/resources/META-INF/org/apache/camel/component/qdrant/qdrant.json @@ -48,6 +48,10 @@ "CamelQdrantPointId": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The point id to use for operation.", "constantName": "org.apache.camel.component.qdrant.QdrantHeaders#POINT_ID" }, "CamelQdrantMaxResults": { "index": 10, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The maximum number of results to return from a similarity search.", "constantName": "org.apache.camel.component.qdrant.QdrantHeaders#MAX_RESULTS" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "pojo", "list", "null" ], "description": "By the action in the CamelQdrantAction header: a VectorParams for CREATE_COLLECTION, a PointStruct or a List of them for UPSERT, a PointId or a List of them for RETRIEVE, a PointsSelector, PointId, Filter or Condition for DELETE, and the query vector as a List of Float, a float array or a PointStruct for SIMILARITY_SEARCH. DELETE_COLLECTION and COLLECTION_INFO do not read the body. Another body fails, such as a number as the id (use PointIdFactory.id) or a List of Double. The qdrant:embeddings data type transformer builds the PointStruct from the output of langchain4j-embeddings" }, + "producerOut": { "carriers": [ "list", "pojo", "unchanged" ], "description": "By the action: a List of RetrievedPoint for RETRIEVE, a List of ScoredPoint for SIMILARITY_SEARCH and a CollectionInfo for COLLECTION_INFO. The other actions keep the body, UPSERT and DELETE with the operation id and status in headers" } + }, "properties": { "collection": { "index": 0, "kind": "path", "displayName": "Collection", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The collection Name" }, "host": { "index": 1, "kind": "parameter", "displayName": "Host", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.qdrant.QdrantConfiguration", "configurationField": "configuration", "description": "The host to connect to." }, diff --git a/components/camel-ai/camel-qdrant/src/main/java/org/apache/camel/component/qdrant/QdrantEndpoint.java b/components/camel-ai/camel-qdrant/src/main/java/org/apache/camel/component/qdrant/QdrantEndpoint.java index 3b7a1b8455400..8dbb2ba6b4878 100644 --- a/components/camel-ai/camel-qdrant/src/main/java/org/apache/camel/component/qdrant/QdrantEndpoint.java +++ b/components/camel-ai/camel-qdrant/src/main/java/org/apache/camel/component/qdrant/QdrantEndpoint.java @@ -25,6 +25,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -46,6 +49,21 @@ Category.AI }, headersClass = QdrantHeaders.class) +@BodyTypes(producerIn = @BodyType(value = { Carrier.POJO, Carrier.LIST, Carrier.NULL }, + description = "By the action in the CamelQdrantAction header: a VectorParams for" + + " CREATE_COLLECTION, a PointStruct or a List of them for UPSERT, a PointId" + + " or a List of them for RETRIEVE, a PointsSelector, PointId, Filter or" + + " Condition for DELETE, and the query vector as a List of Float, a float" + + " array or a PointStruct for SIMILARITY_SEARCH. DELETE_COLLECTION and" + + " COLLECTION_INFO do not read the body. Another body fails, such as a" + + " number as the id (use PointIdFactory.id) or a List of Double. The" + + " qdrant:embeddings data type transformer builds the PointStruct from the" + + " output of langchain4j-embeddings"), + producerOut = @BodyType(value = { Carrier.LIST, Carrier.POJO, Carrier.UNCHANGED }, + description = "By the action: a List of RetrievedPoint for RETRIEVE, a List of" + + " ScoredPoint for SIMILARITY_SEARCH and a CollectionInfo for" + + " COLLECTION_INFO. The other actions keep the body, UPSERT and DELETE with" + + " the operation id and status in headers")) public class QdrantEndpoint extends DefaultEndpoint implements EndpointServiceLocation { @Metadata(required = true) diff --git a/components/camel-ibm/camel-ibm-watson-language/src/generated/resources/META-INF/org/apache/camel/component/ibm/watson/language/ibm-watson-language.json b/components/camel-ibm/camel-ibm-watson-language/src/generated/resources/META-INF/org/apache/camel/component/ibm/watson/language/ibm-watson-language.json index ce47ac5e383e0..d0b502549cf53 100644 --- a/components/camel-ibm/camel-ibm-watson-language/src/generated/resources/META-INF/org/apache/camel/component/ibm/watson/language/ibm-watson-language.json +++ b/components/camel-ibm/camel-ibm-watson-language/src/generated/resources/META-INF/org/apache/camel/component/ibm/watson/language/ibm-watson-language.json @@ -53,6 +53,10 @@ "CamelIBMWatsonLanguageSentimentScore": { "index": 10, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The sentiment score", "constantName": "org.apache.camel.component.ibm.watson.language.WatsonLanguageConstants#SENTIMENT_SCORE" }, "CamelIBMWatsonLanguageSentimentLabel": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The sentiment label (positive, negative, neutral)", "constantName": "org.apache.camel.component.ibm.watson.language.WatsonLanguageConstants#SENTIMENT_LABEL" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The text to analyze for analyzeText, or the URL of the page for analyzeUrl, read as text, unless the CamelIBMWatsonLanguageText or CamelIBMWatsonLanguageUrl header gives it. Without the header, no body or a blank one fails, and a Map or a POJO is analyzed as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "pojo" ], "javaType": "com.ibm.watson.natural_language_understanding.v1.model.AnalysisResults", "description": "The results of the features enabled (sentiment, entities, keywords and so on), with the sentiment score and label and the language in headers too. Converted to text, it is the JSON of the results" } + }, "properties": { "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Logical name" }, "serviceUrl": { "index": 1, "kind": "parameter", "displayName": "Service Url", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.ibm.watson.language.WatsonLanguageConfiguration", "configurationField": "configuration", "description": "The service endpoint URL. If not specified, the default URL will be used." }, diff --git a/components/camel-ibm/camel-ibm-watson-language/src/main/java/org/apache/camel/component/ibm/watson/language/WatsonLanguageEndpoint.java b/components/camel-ibm/camel-ibm-watson-language/src/main/java/org/apache/camel/component/ibm/watson/language/WatsonLanguageEndpoint.java index 801c07756df8d..f8ff4572ffdbb 100644 --- a/components/camel-ibm/camel-ibm-watson-language/src/main/java/org/apache/camel/component/ibm/watson/language/WatsonLanguageEndpoint.java +++ b/components/camel-ibm/camel-ibm-watson-language/src/main/java/org/apache/camel/component/ibm/watson/language/WatsonLanguageEndpoint.java @@ -22,6 +22,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -35,6 +38,17 @@ @UriEndpoint(firstVersion = "4.16.0", scheme = "ibm-watson-language", title = "IBM Watson Language", syntax = "ibm-watson-language:label", producerOnly = true, category = { Category.AI, Category.CLOUD }, headersClass = WatsonLanguageConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The text to analyze for analyzeText, or the URL of the page for" + + " analyzeUrl, read as text, unless the CamelIBMWatsonLanguageText or" + + " CamelIBMWatsonLanguageUrl header gives it. Without the header, no body or" + + " a blank one fails, and a Map or a POJO is analyzed as its toString():" + + " marshal it first"), + producerOut = @BodyType(value = Carrier.POJO, + javaType = "com.ibm.watson.natural_language_understanding.v1.model.AnalysisResults", + description = "The results of the features enabled (sentiment, entities, keywords and so" + + " on), with the sentiment score and label and the language in headers too." + + " Converted to text, it is the JSON of the results")) public class WatsonLanguageEndpoint extends DefaultEndpoint implements EndpointServiceLocation { @UriPath(description = "Logical name") diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc index 26c18f3af01cd..54c39089b8054 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-validation.adoc @@ -77,8 +77,9 @@ The YAML validator follows the message body through the steps of each route, and it: a field read such as `+${body.qty}+` on text that was never unmarshalled, or a Map that a `to: file` cannot write. What a component or a data format does with the body comes from the xref:camel-catalog.adoc#_body_types_in_the_catalog[body types in the catalog]: the file consumer gives the file it -read, the `http` producer leaves the response as bytes or a stream, and `unmarshal: json` makes a Map or a List. -Where they do not tell what the body is, the validator says nothing: after a `platform-http` consumer the body +read, the `http` producer leaves the response as bytes or a stream, and `unmarshal: json` makes a Map or a List. The +answer of `openai:chat-completion` is text, also when it is asked for JSON with `jsonSchema`, so a field read on it +needs `unmarshal: json` first. Where they do not tell what the body is, the validator says nothing: after a `platform-http` consumer the body depends on the request, and the deserializer of a `kafka` consumer can be set on the component, which the route file does not show. From 9069642d0a7e898158e39feee5b1af28b72166fe Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 17:32:12 +0200 Subject: [PATCH 08/25] CAMEL-24961: camel-yaml-dsl-validator - the options in the path of an endpoint count for its body types The operation of openai is in the path (openai:embeddings), so the validator reads the path options with the syntax of the component, as the catalog parses an endpoint. A path the catalog cannot read, such as a toD with an expression, says nothing about its options. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../dsl/yaml/validator/CatalogBodyTypes.java | 35 +++++++++++++++ .../dsl/yaml/validator/TextBodyFlowTest.java | 44 +++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java index 3259582da25f3..897532a0a271d 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java @@ -191,9 +191,44 @@ private Answer componentSide(String uri, JsonNode node, String side) { String text = node != null && node.isTextual() ? node.asText() : node != null && node.isObject() && node.has("uri") ? node.get("uri").asText() : null; set.putAll(query(text)); + readPath(uri, model, set, configurable); return answer(model.getBodyType(side), set, configurable); } + /** + * Adds the options in the path of an endpoint uri, as the syntax of its component names them: the operation of + * openai:embeddings. A path the catalog cannot read says nothing about them, as an option the component may set. + */ + private void readPath(String uri, ComponentModel model, Map set, Set configurable) { + if (uri == null || model.getEndpointPathOptions().isEmpty()) { + return; + } + // the query is read on its own, and may hold what the parser of the catalog does not take, such as a space + int q = uri.indexOf('?'); + String path = q < 0 ? uri : uri.substring(0, q); + Optional> properties = endpointProperties(catalog, path); + if (properties.isEmpty() && fallback != null) { + properties = endpointProperties(fallback, path); + } + for (BaseOptionModel option : model.getEndpointPathOptions()) { + String name = option.getName(); + if (properties.isEmpty()) { + configurable.add(name); + } else if (properties.get().containsKey(name)) { + set.putIfAbsent(name, properties.get().get(name)); + } + } + } + + private static Optional> endpointProperties(CamelCatalog catalog, String uri) { + try { + return Optional.ofNullable(catalog.endpointProperties(uri)); + } catch (Exception e) { + // not an endpoint the catalog can read, such as one of a component it does not have + return Optional.empty(); + } + } + /** * What a side says for the options a step sets: the body for an option value it names, or its body when the options * it depends on keep their defaults; null when it is not known for the step. diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java index 5c0085afe5a80..0c2af877367d5 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java @@ -1037,6 +1037,50 @@ public void testWhatTheComponentMayConfigureSaysNothing() { assertThat(lines(yaml)).isEmpty(); } + @Test + public void testTheOptionsInThePathOfTheEndpoint() { + // the operation of openai is in the path: the answer of chat-completion is text, also when it is asked for as + // JSON, embeddings gives a List, and an operation only known when the route runs says nothing + String yaml = """ + - route: + id: city + from: + uri: timer:tick + steps: + - setBody: + constant: Name a city in Denmark + - to: openai:chat-completion?jsonSchema=resource:classpath:city.json + - setHeader: + name: city + simple: ${body[name]} + - route: + id: vector + from: + uri: timer:tick + steps: + - setBody: + constant: Apache Camel + - to: llm:embeddings + - setHeader: + name: first + simple: ${body[0]} + - route: + id: dynamic + from: + uri: timer:tick + steps: + - setBody: + constant: Apache Camel + - toD: openai:${header.operation} + - setHeader: + name: first + simple: ${body[0]} + """; + assertThat(lines(yaml)).singleElement().satisfies(m -> assertThat(m) + .contains("route city: simple reads a field of the body (${body[name]})") + .contains("to: openai:chat-completion returns it as text: unmarshal it first")); + } + @Test public void testOneReportForAStepThatFails() { // the first write fails at runtime, so the second does not run with this body From 8f830c04e62e20c213e254eeb11efb186a97b15a Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 17:32:12 +0200 Subject: [PATCH 09/25] CAMEL-24961: camel-package-maven-plugin - the build rejects a body type for a value its option cannot have A byOption value must be one of the enum of its option, or true or false for a boolean, ignoring case as tooling compares it with the endpoint: a misspelled operation such as embedding for embeddings would never hold. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../modules/ROOT/pages/camel-catalog.adoc | 3 +- .../maven/packaging/BodyTypesHelper.java | 43 +++++++++++++------ .../EndpointSchemaGeneratorMojoTest.java | 16 +++++-- .../SomeEndpointWithBadBodyTypes.java | 6 +++ 4 files changed, 51 insertions(+), 17 deletions(-) diff --git a/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc b/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc index d97e2614ae783..e4bc5bb6a01ce 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-catalog.adoc @@ -187,7 +187,8 @@ public class FileEndpoint extends GenericFileEndpoint { ---- The build checks that each side belongs to the kind (a consumer-only component has no producer sides), that the -options a side names exist, that `unchanged` is only on the body after a step and `any` only on what a step needs. +options a side names exist, that a value of an option is one the option can have (such as `chat-completion` for the +`operation` of openai), and that `unchanged` is only on the body after a step and `any` only on what a step needs. The values are read from the code that sets the body, and checked against the body types the message history records when the routes run. diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java index 2894db39c3729..193c7f3c42f3b 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java @@ -18,7 +18,7 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -28,6 +28,7 @@ import org.apache.camel.spi.BodyType.Carrier; import org.apache.camel.spi.BodyTypes; import org.apache.camel.tooling.model.BaseModel; +import org.apache.camel.tooling.model.BaseOptionModel; import org.apache.camel.tooling.model.BodyTypeModel; import org.apache.camel.tooling.model.ComponentModel; @@ -50,8 +51,8 @@ private BodyTypesHelper() { * @param bodyTypes the annotation, null when the class has none * @param owner the class with the annotation, for the error message * @throws IllegalArgumentException when a side does not fit the model: a data format side on a component, a - * producer side on a consumer-only component, unchanged on what a step needs or - * any on what it leaves + * producer side on a consumer-only component, unchanged on what a step needs, any + * on what it leaves, or a value an option cannot have */ static void addBodyTypes(BaseModel model, BodyTypes bodyTypes, Class owner) { if (bodyTypes == null) { @@ -70,7 +71,7 @@ static void addBodyTypes(BaseModel model, BodyTypes bodyTypes, Class owner sides.put(BodyTypeModel.EXPRESSION_OUT, bodyTypes.expressionOut()); Set allowed = allowedSides(model); - Set options = optionNames(model); + Map options = options(model); for (Map.Entry entry : sides.entrySet()) { String side = entry.getKey(); BodyType bodyType = entry.getValue(); @@ -93,6 +94,7 @@ static void addBodyTypes(BaseModel model, BodyTypes bodyTypes, Class owner } for (BodyType.When when : bodyType.byOption()) { checkOption(owner, side, when.option(), options); + checkValue(owner, side, when, options.get(when.option())); check(owner, side + " " + when.option() + "=" + when.value(), when.carrier()); } model.getBodyTypes().put(side, asModel(bodyType)); @@ -118,24 +120,39 @@ private static Set allowedSides(BaseModel model) { }; } - /** The options of the model, which the body types can depend on. */ - private static Set optionNames(BaseModel model) { - Set names = new HashSet<>(); - model.getOptions().forEach(o -> names.add(o.getName())); + /** The options of the model by name, which the body types can depend on. */ + private static Map options(BaseModel model) { + Map answer = new HashMap<>(); + model.getOptions().forEach(o -> answer.put(o.getName(), o)); if (model instanceof ComponentModel component) { - component.getComponentOptions().forEach(o -> names.add(o.getName())); - component.getEndpointOptions().forEach(o -> names.add(o.getName())); + component.getComponentOptions().forEach(o -> answer.put(o.getName(), o)); + component.getEndpointOptions().forEach(o -> answer.put(o.getName(), o)); } - return names; + return answer; } - private static void checkOption(Class owner, String side, String option, Set options) { - if (!options.contains(option)) { + private static void checkOption(Class owner, String side, String option, Map options) { + if (!options.containsKey(option)) { throw new IllegalArgumentException( owner.getName() + ": the @BodyTypes " + side + " depends on " + option + ", which is not an option"); } } + /** + * A body for a value the option cannot have would never hold: the value is one of an enum, or true or false for a + * boolean, in any case, as tooling compares it with what the endpoint sets. + */ + private static void checkValue(Class owner, String side, BodyType.When when, BaseOptionModel option) { + List values = option.getEnums() != null && !option.getEnums().isEmpty() + ? option.getEnums() + : "boolean".equals(option.getType()) ? List.of("true", "false") : List.of(); + if (!values.isEmpty() && values.stream().noneMatch(v -> v.equalsIgnoreCase(when.value()))) { + throw new IllegalArgumentException( + owner.getName() + ": the @BodyTypes " + side + " has " + when.option() + "=" + when.value() + + ", which is not a value of the option: " + String.join(", ", values)); + } + } + /** * A body has a carrier: an option value without one would say nothing. UNCHANGED is for the body after a step, such * as a sql query that leaves it unchanged unless it is a select. ANY is for the bodies a step needs. ANY and diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java index 5fa2fe71426d0..24d5b3d86b84e 100644 --- a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java @@ -233,7 +233,8 @@ void testEndpointWithHeadersOnSelfAndSuperclass() { @Test void testEndpointWithBodyTypes() throws Exception { // CAMEL-24961: the body a step needs and the body it leaves, in the order of the annotation - addEndpointOptions("resultHandlerFactory", "output"); + addEndpointOptions("resultHandlerFactory"); + addEnumOption("output", "string", "bytes"); mojo.addBodyTypes(model, SomeEndpointWithBodyTypes.class); assertEquals(List.of(BodyTypeModel.CONSUMER_OUT, BodyTypeModel.PRODUCER_IN, BodyTypeModel.PRODUCER_OUT), List.copyOf(model.getBodyTypes().keySet())); @@ -278,9 +279,10 @@ void testEndpointWithoutBodyTypes() throws Exception { SomeEndpointWithBadBodyTypes.DataFormatSide.class, SomeEndpointWithBadBodyTypes.ProducerSideOfConsumer.class, SomeEndpointWithBadBodyTypes.UnchangedInput.class, SomeEndpointWithBadBodyTypes.AnyOutput.class, SomeEndpointWithBadBodyTypes.UnknownWithOthers.class, SomeEndpointWithBadBodyTypes.NoCarriers.class, - SomeEndpointWithBadBodyTypes.UnknownOption.class, SomeEndpointWithBadBodyTypes.OptionValueWithoutCarriers.class }) + SomeEndpointWithBadBodyTypes.UnknownOption.class, SomeEndpointWithBadBodyTypes.OptionValueWithoutCarriers.class, + SomeEndpointWithBadBodyTypes.ValueTheOptionDoesNotHave.class }) void testEndpointWithBadBodyTypes(Class clazz) { - addEndpointOptions("output"); + addEnumOption("output", "string", "bytes"); model.setConsumerOnly(clazz.getAnnotation(UriEndpoint.class).consumerOnly()); MojoExecutionException e = assertThrows(MojoExecutionException.class, () -> mojo.addBodyTypes(model, clazz)); assertTrue(e.getMessage().startsWith(clazz.getName() + ": the @BodyTypes "), e.getMessage()); @@ -294,4 +296,12 @@ private void addEndpointOptions(String... names) { model.addEndpointOption(option); } } + + private void addEnumOption(String name, String... values) { + ComponentModel.EndpointOptionModel option = new ComponentModel.EndpointOptionModel(); + option.setName(name); + option.setType("enum"); + option.setEnums(List.of(values)); + model.addEndpointOption(option); + } } diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java index 9346bf17990e0..bb786b1aca2df 100644 --- a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java @@ -69,4 +69,10 @@ public static class UnknownOption { byOption = @BodyType.When(option = "output", value = "bytes", carrier = {}))) public static class OptionValueWithoutCarriers { } + + @UriEndpoint(scheme = "some", syntax = "some", title = "some") + @BodyTypes(producerOut = @BodyType(value = Carrier.TEXT, + byOption = @BodyType.When(option = "output", value = "DOM", carrier = Carrier.POJO))) + public static class ValueTheOptionDoesNotHave { + } } From 0be66c57fb11079e313c218964806f4043094da5 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 20:46:31 +0200 Subject: [PATCH 10/25] CAMEL-24961: Rename When.carrier to carriers, as the catalog names it The attribute holds an array, and the catalog JSON and BodyTypeModel call the same field carriers. The Javadoc of BodyTypeModel.isUnknown() says that a side with no carriers is unknown too. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../org/apache/camel/component/file/FileEndpoint.java | 2 +- .../camel/component/jackson/JacksonDataFormat.java | 2 +- .../org/apache/camel/component/seda/SedaEndpoint.java | 2 +- .../org/apache/camel/component/sql/SqlEndpoint.java | 10 +++++----- .../org/apache/camel/component/xslt/XsltEndpoint.java | 8 ++++---- .../generated/java/org/apache/camel/spi/BodyType.java | 2 +- .../org/apache/camel/tooling/model/BodyTypeModel.java | 4 +++- .../apache/camel/maven/packaging/BodyTypesHelper.java | 4 ++-- .../endpoint/SomeEndpointWithBadBodyTypes.java | 2 +- .../packaging/endpoint/SomeEndpointWithBodyTypes.java | 2 +- .../src/main/java/org/apache/camel/spi/BodyType.java | 2 +- 11 files changed, 21 insertions(+), 19 deletions(-) diff --git a/components/camel-file/src/main/java/org/apache/camel/component/file/FileEndpoint.java b/components/camel-file/src/main/java/org/apache/camel/component/file/FileEndpoint.java index 283e0b32e9e80..97c70ff2f7dc4 100644 --- a/components/camel-file/src/main/java/org/apache/camel/component/file/FileEndpoint.java +++ b/components/camel-file/src/main/java/org/apache/camel/component/file/FileEndpoint.java @@ -54,7 +54,7 @@ + " converts to text, bytes or a stream"), producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, byOption = @BodyType.When(option = "allowNullBody", value = "true", - carrier = { + carriers = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), description = "What converts to an InputStream: text, bytes, a stream or a file. A Map or" diff --git a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java index 6519c2d6a2ae0..4afc8fb1cbe30 100644 --- a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java +++ b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java @@ -45,7 +45,7 @@ unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "json"), unmarshalOut = @BodyType(value = { Carrier.MAP, Carrier.LIST }, dependsOn = { "unmarshalType", "collectionType", "allowUnmarshallType" }, - byOption = @BodyType.When(option = "useList", value = "true", carrier = Carrier.LIST), + byOption = @BodyType.When(option = "useList", value = "true", carriers = Carrier.LIST), description = "A Map (LinkedHashMap) for a JSON object, a List (ArrayList) for an array;" + " an object of the class unmarshalType names")) public class JacksonDataFormat extends AbstractJacksonDataFormat { diff --git a/components/camel-seda/src/main/java/org/apache/camel/component/seda/SedaEndpoint.java b/components/camel-seda/src/main/java/org/apache/camel/component/seda/SedaEndpoint.java index 7cedba92ad122..973bd1404bbd1 100644 --- a/components/camel-seda/src/main/java/org/apache/camel/component/seda/SedaEndpoint.java +++ b/components/camel-seda/src/main/java/org/apache/camel/component/seda/SedaEndpoint.java @@ -66,7 +66,7 @@ producerIn = @BodyType(Carrier.ANY), producerOut = @BodyType(value = Carrier.UNKNOWN, byOption = @BodyType.When(option = "waitForTaskToComplete", value = "Never", - carrier = Carrier.UNCHANGED), + carriers = Carrier.UNCHANGED), description = "Unchanged for a message that expects no reply (InOnly). A message that" + " expects one (InOut), or waitForTaskToComplete=Always, waits for the" + " body the seda route ends with")) diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java index 5ea866d040d28..5a7798e61770e 100644 --- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java +++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java @@ -38,11 +38,11 @@ @BodyTypes(consumerOut = @BodyType(value = Carrier.MAP, javaType = "java.util.Map", dependsOn = { "outputClass", "outputHeader" }, byOption = { - @BodyType.When(option = "useIterator", value = "false", carrier = Carrier.LIST), + @BodyType.When(option = "useIterator", value = "false", carriers = Carrier.LIST), @BodyType.When(option = "outputType", value = "SelectOne", - carrier = { Carrier.MAP, Carrier.VALUE }), + carriers = { Carrier.MAP, Carrier.VALUE }), @BodyType.When(option = "outputType", value = "StreamList", - carrier = Carrier.ITERATOR) }, + carriers = Carrier.ITERATOR) }, description = "A row of the query: a Map of the column names and their values"), producerIn = @BodyType(value = Carrier.ANY, description = "The parameters of the query: a Map for the named ones, a List or an array" @@ -51,9 +51,9 @@ dependsOn = { "outputClass", "outputHeader", "noop" }, byOption = { @BodyType.When(option = "outputType", value = "SelectOne", - carrier = { Carrier.MAP, Carrier.VALUE, Carrier.NULL }), + carriers = { Carrier.MAP, Carrier.VALUE, Carrier.NULL }), @BodyType.When(option = "outputType", value = "StreamList", - carrier = Carrier.ITERATOR) }, + carriers = Carrier.ITERATOR) }, description = "The rows of a select: a List of Maps of the column names and their values." + " A query that is not a select leaves the body unchanged, with the count" + " in the CamelSqlUpdateCount header")) diff --git a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java index 17c699c6e21e0..c02124dc45695 100644 --- a/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java +++ b/components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltEndpoint.java @@ -66,18 +66,18 @@ @BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, format = "xml", dependsOn = "source", byOption = @BodyType.When(option = "failOnNullBody", value = "false", - carrier = { + carriers = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }), description = "The XML to transform: text, bytes, a stream, a file, a DOM or another" + " javax.xml.transform.Source. A Map, a List or no body fails"), producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", dependsOn = "resultHandlerFactory", byOption = { - @BodyType.When(option = "output", value = "bytes", carrier = Carrier.BYTES, + @BodyType.When(option = "output", value = "bytes", carriers = Carrier.BYTES, javaType = "byte[]"), - @BodyType.When(option = "output", value = "DOM", carrier = Carrier.POJO, + @BodyType.When(option = "output", value = "DOM", carriers = Carrier.POJO, javaType = "org.w3c.dom.Document"), - @BodyType.When(option = "output", value = "file", carrier = Carrier.FILE, + @BodyType.When(option = "output", value = "file", carriers = Carrier.FILE, javaType = "java.io.File") }, description = "The result of the transformation")) public class XsltEndpoint extends ProcessorEndpoint { diff --git a/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java b/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java index 8f027971b231d..2d2cc3b927240 100644 --- a/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java +++ b/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java @@ -89,7 +89,7 @@ /** * The carriers of the body with this value. */ - Carrier[] carrier(); + Carrier[] carriers(); /** * The Java type of the body with this value, when it is always of this type. diff --git a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java index 794c505ecc347..d9097160e19c6 100644 --- a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java +++ b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/BodyTypeModel.java @@ -132,7 +132,9 @@ public boolean isUnchanged() { } /** - * Whether the body is not known without the configuration or the data of the other system. + * Whether the body is not known without the configuration or the data of the other system. A side with no carriers + * is not known either: the build rejects one, but a catalog from elsewhere, such as JSON written by hand, can have + * it. */ public boolean isUnknown() { return carriers.isEmpty() || carriers.contains("unknown"); diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java index 2894db39c3729..fcb3789aa78a5 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java @@ -93,7 +93,7 @@ static void addBodyTypes(BaseModel model, BodyTypes bodyTypes, Class owner } for (BodyType.When when : bodyType.byOption()) { checkOption(owner, side, when.option(), options); - check(owner, side + " " + when.option() + "=" + when.value(), when.carrier()); + check(owner, side + " " + when.option() + "=" + when.value(), when.carriers()); } model.getBodyTypes().put(side, asModel(bodyType)); } @@ -171,7 +171,7 @@ private static BodyTypeModel asModel(BodyType bodyType) { BodyTypeModel.OptionBodyTypeModel option = new BodyTypeModel.OptionBodyTypeModel(); option.setOption(when.option()); option.setValue(when.value()); - option.setCarriers(names(when.carrier())); + option.setCarriers(names(when.carriers())); option.setJavaType(emptyAsNull(when.javaType())); model.getByOption().add(option); } diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java index 9346bf17990e0..cccd18faa7155 100644 --- a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java @@ -66,7 +66,7 @@ public static class UnknownOption { @UriEndpoint(scheme = "some", syntax = "some", title = "some") @BodyTypes(producerOut = @BodyType(value = Carrier.TEXT, - byOption = @BodyType.When(option = "output", value = "bytes", carrier = {}))) + byOption = @BodyType.When(option = "output", value = "bytes", carriers = {}))) public static class OptionValueWithoutCarriers { } } diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBodyTypes.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBodyTypes.java index 18c10606a6461..3473dc6f438cf 100644 --- a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBodyTypes.java +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBodyTypes.java @@ -28,6 +28,6 @@ producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", format = "xml", dependsOn = "resultHandlerFactory", byOption = @BodyType.When(option = "output", value = "bytes", - carrier = Carrier.BYTES, javaType = "byte[]"))) + carriers = Carrier.BYTES, javaType = "byte[]"))) public class SomeEndpointWithBodyTypes { } diff --git a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java index 8f027971b231d..2d2cc3b927240 100644 --- a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java +++ b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java @@ -89,7 +89,7 @@ /** * The carriers of the body with this value. */ - Carrier[] carrier(); + Carrier[] carriers(); /** * The Java type of the body with this value, when it is always of this type. From 15aaf465fa04661557ef380fa689d3c98d7b1e07 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 20:48:33 +0200 Subject: [PATCH 11/25] CAMEL-24961: Use When.carriers in the annotations of slice 2 Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../component/activemq/ActiveMQEndpoint.java | 12 +++--- .../component/activemq6/ActiveMQEndpoint.java | 12 +++--- .../camel/component/amqp/AMQPEndpoint.java | 12 +++--- .../component/aws2/sqs/Sqs2Endpoint.java | 12 +++--- .../camel/dataformat/csv/CsvDataFormat.java | 2 +- .../component/file/remote/FtpEndpoint.java | 6 +-- .../component/file/remote/FtpsEndpoint.java | 6 +-- .../component/file/remote/SftpEndpoint.java | 6 +-- .../jacksonxml/JacksonXMLDataFormat.java | 2 +- .../camel/component/jms/JmsEndpoint.java | 12 +++--- .../camel/jsonpath/JsonPathLanguage.java | 2 +- .../camel/component/kafka/KafkaEndpoint.java | 4 +- .../component/mongodb/MongoDbEndpoint.java | 37 ++++++++++--------- .../platform/http/PlatformHttpEndpoint.java | 2 +- .../camel/component/rest/RestEndpoint.java | 6 +-- .../camel/language/xpath/XPathLanguage.java | 8 ++-- 16 files changed, 71 insertions(+), 70 deletions(-) diff --git a/components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQEndpoint.java b/components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQEndpoint.java index 1e0ca6e7876f6..34c534d2014d5 100644 --- a/components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQEndpoint.java +++ b/components/camel-activemq/src/main/java/org/apache/camel/component/activemq/ActiveMQEndpoint.java @@ -42,10 +42,10 @@ @BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.NULL }, dependsOn = { "messageConverter", "transferExchange" }, byOption = { - @BodyType.When(option = "mapJmsMessage", value = "false", carrier = Carrier.POJO, + @BodyType.When(option = "mapJmsMessage", value = "false", carriers = Carrier.POJO, javaType = "jakarta.jms.Message"), @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.POJO, Carrier.NULL }) }, description = "By the JMS message received: a String for a TextMessage, a byte array for a" @@ -54,14 +54,14 @@ consumerReply = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP, Carrier.POJO }), description = "The reply, sent as the producer sends a message"), producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP, Carrier.POJO }), description = "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage;" @@ -70,9 +70,9 @@ producerOut = @BodyType(value = Carrier.UNKNOWN, byOption = { @BodyType.When(option = "exchangePattern", value = "InOnly", - carrier = Carrier.UNCHANGED), + carriers = Carrier.UNCHANGED), @BodyType.When(option = "disableReplyTo", value = "true", - carrier = Carrier.UNCHANGED) }, + carriers = Carrier.UNCHANGED) }, description = "Unchanged for a message that expects no reply (InOnly). A message that" + " expects one (InOut) gets the body of the reply, as the consumer gives it")) public class ActiveMQEndpoint extends JmsEndpoint implements EndpointServiceLocation { diff --git a/components/camel-activemq6/src/main/java/org/apache/camel/component/activemq6/ActiveMQEndpoint.java b/components/camel-activemq6/src/main/java/org/apache/camel/component/activemq6/ActiveMQEndpoint.java index 2ebf48a77856e..57373f8b7cde3 100644 --- a/components/camel-activemq6/src/main/java/org/apache/camel/component/activemq6/ActiveMQEndpoint.java +++ b/components/camel-activemq6/src/main/java/org/apache/camel/component/activemq6/ActiveMQEndpoint.java @@ -42,10 +42,10 @@ @BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.NULL }, dependsOn = { "messageConverter", "transferExchange" }, byOption = { - @BodyType.When(option = "mapJmsMessage", value = "false", carrier = Carrier.POJO, + @BodyType.When(option = "mapJmsMessage", value = "false", carriers = Carrier.POJO, javaType = "jakarta.jms.Message"), @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.POJO, Carrier.NULL }) }, description = "By the JMS message received: a String for a TextMessage, a byte array for a" @@ -54,14 +54,14 @@ consumerReply = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP, Carrier.POJO }), description = "The reply, sent as the producer sends a message"), producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP, Carrier.POJO }), description = "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage;" @@ -70,9 +70,9 @@ producerOut = @BodyType(value = Carrier.UNKNOWN, byOption = { @BodyType.When(option = "exchangePattern", value = "InOnly", - carrier = Carrier.UNCHANGED), + carriers = Carrier.UNCHANGED), @BodyType.When(option = "disableReplyTo", value = "true", - carrier = Carrier.UNCHANGED) }, + carriers = Carrier.UNCHANGED) }, description = "Unchanged for a message that expects no reply (InOnly). A message that" + " expects one (InOut) gets the body of the reply, as the consumer gives it")) public class ActiveMQEndpoint extends JmsEndpoint implements EndpointServiceLocation { diff --git a/components/camel-amqp/src/main/java/org/apache/camel/component/amqp/AMQPEndpoint.java b/components/camel-amqp/src/main/java/org/apache/camel/component/amqp/AMQPEndpoint.java index 9ed3d154c6132..4216a71c9529f 100644 --- a/components/camel-amqp/src/main/java/org/apache/camel/component/amqp/AMQPEndpoint.java +++ b/components/camel-amqp/src/main/java/org/apache/camel/component/amqp/AMQPEndpoint.java @@ -34,10 +34,10 @@ @BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.NULL }, dependsOn = { "messageConverter", "transferExchange" }, byOption = { - @BodyType.When(option = "mapJmsMessage", value = "false", carrier = Carrier.POJO, + @BodyType.When(option = "mapJmsMessage", value = "false", carriers = Carrier.POJO, javaType = "jakarta.jms.Message"), @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.POJO, Carrier.NULL }) }, description = "By the JMS message received: a String for a TextMessage, a byte array for a" @@ -46,14 +46,14 @@ consumerReply = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP, Carrier.POJO }), description = "The reply, sent as the producer sends a message"), producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP, Carrier.POJO }), description = "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage;" @@ -62,9 +62,9 @@ producerOut = @BodyType(value = Carrier.UNKNOWN, byOption = { @BodyType.When(option = "exchangePattern", value = "InOnly", - carrier = Carrier.UNCHANGED), + carriers = Carrier.UNCHANGED), @BodyType.When(option = "disableReplyTo", value = "true", - carrier = Carrier.UNCHANGED) }, + carriers = Carrier.UNCHANGED) }, description = "Unchanged for a message that expects no reply (InOnly). A message that" + " expects one (InOut) gets the body of the reply, as the consumer gives it")) public class AMQPEndpoint extends JmsEndpoint { diff --git a/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java b/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java index 7e226d8d92a1e..961073d19076b 100644 --- a/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java +++ b/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java @@ -65,23 +65,23 @@ description = "The body of the SQS message"), producerIn = @BodyType(value = Carrier.TEXT, byOption = @BodyType.When(option = "operation", value = "sendBatchMessage", - carrier = { Carrier.LIST, Carrier.TEXT }), + carriers = { Carrier.LIST, Carrier.TEXT }), description = "The body of the message to send, as text, so a Map or a POJO is sent as" + " its toString(): marshal it first. sendBatchMessage takes a List of" + " text, or text that batchSeparator splits"), producerOut = @BodyType(value = Carrier.UNCHANGED, byOption = { @BodyType.When(option = "operation", value = "sendBatchMessage", - carrier = Carrier.POJO, + carriers = Carrier.POJO, javaType = "software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse"), @BodyType.When(option = "operation", value = "deleteMessage", - carrier = Carrier.POJO, + carriers = Carrier.POJO, javaType = "software.amazon.awssdk.services.sqs.model.DeleteMessageResponse"), - @BodyType.When(option = "operation", value = "listQueues", carrier = Carrier.POJO, + @BodyType.When(option = "operation", value = "listQueues", carriers = Carrier.POJO, javaType = "software.amazon.awssdk.services.sqs.model.ListQueuesResponse"), - @BodyType.When(option = "operation", value = "purgeQueue", carrier = Carrier.POJO, + @BodyType.When(option = "operation", value = "purgeQueue", carriers = Carrier.POJO, javaType = "software.amazon.awssdk.services.sqs.model.PurgeQueueResponse"), - @BodyType.When(option = "operation", value = "deleteQueue", carrier = Carrier.POJO, + @BodyType.When(option = "operation", value = "deleteQueue", carriers = Carrier.POJO, javaType = "software.amazon.awssdk.services.sqs.model.DeleteQueueResponse") }, description = "Unchanged for a send, with the id of the message in a header; the response" + " of the AWS SDK for the other operations")) diff --git a/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java b/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java index d90ee300b0c8d..911b89cef6fd1 100644 --- a/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java +++ b/components/camel-csv/src/main/java/org/apache/camel/dataformat/csv/CsvDataFormat.java @@ -46,7 +46,7 @@ unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "csv"), unmarshalOut = @BodyType(value = Carrier.LIST, dependsOn = "recordConverterRef", byOption = @BodyType.When(option = "lazyLoad", value = "true", - carrier = Carrier.ITERATOR), + carriers = Carrier.ITERATOR), description = "A List of the rows, each a List of its values; with useMaps or" + " useOrderedMaps, a Map of the header names and the values")) public class CsvDataFormat extends ServiceSupport implements DataFormat, DataFormatName { diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpEndpoint.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpEndpoint.java index 2abdf1d757ba9..48417c25b72fc 100644 --- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpEndpoint.java +++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpEndpoint.java @@ -61,13 +61,13 @@ @ManagedResource(description = "Managed FtpEndpoint") @BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, dependsOn = "preMove", byOption = { - @BodyType.When(option = "streamDownload", value = "true", carrier = Carrier.STREAM), - @BodyType.When(option = "download", value = "false", carrier = Carrier.NULL) }, + @BodyType.When(option = "streamDownload", value = "true", carriers = Carrier.STREAM), + @BodyType.When(option = "download", value = "false", carriers = Carrier.NULL) }, description = "The file as read: a RemoteFile, which converts to text, bytes or a stream; a" + " stream with streamDownload; with preMove its content, a byte array"), producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, byOption = @BodyType.When(option = "allowNullBody", value = "true", - carrier = { + carriers = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), description = "What converts to an InputStream: text, bytes, a stream or a file. A Map or" diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpsEndpoint.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpsEndpoint.java index 5a80fbc506799..079079926c9a4 100644 --- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpsEndpoint.java +++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/FtpsEndpoint.java @@ -59,13 +59,13 @@ @ManagedResource(description = "Managed FtpsEndpoint") @BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, dependsOn = "preMove", byOption = { - @BodyType.When(option = "streamDownload", value = "true", carrier = Carrier.STREAM), - @BodyType.When(option = "download", value = "false", carrier = Carrier.NULL) }, + @BodyType.When(option = "streamDownload", value = "true", carriers = Carrier.STREAM), + @BodyType.When(option = "download", value = "false", carriers = Carrier.NULL) }, description = "The file as read: a RemoteFile, which converts to text, bytes or a stream; a" + " stream with streamDownload; with preMove its content, a byte array"), producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, byOption = @BodyType.When(option = "allowNullBody", value = "true", - carrier = { + carriers = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), description = "What converts to an InputStream: text, bytes, a stream or a file. A Map or" diff --git a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpEndpoint.java b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpEndpoint.java index 6ff2ab3c28e90..199e5d28bdaa7 100644 --- a/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpEndpoint.java +++ b/components/camel-ftp/src/main/java/org/apache/camel/component/file/remote/SftpEndpoint.java @@ -42,13 +42,13 @@ + "renameUsingCopy,synchronous") @BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, dependsOn = "preMove", byOption = { - @BodyType.When(option = "streamDownload", value = "true", carrier = Carrier.STREAM), - @BodyType.When(option = "download", value = "false", carrier = Carrier.NULL) }, + @BodyType.When(option = "streamDownload", value = "true", carriers = Carrier.STREAM), + @BodyType.When(option = "download", value = "false", carriers = Carrier.NULL) }, description = "The file as read: a RemoteFile, which converts to text, bytes or a stream; a" + " stream with streamDownload; with preMove its content, a byte array"), producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, byOption = @BodyType.When(option = "allowNullBody", value = "true", - carrier = { + carriers = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), description = "What converts to an InputStream: text, bytes, a stream or a file. A Map or" diff --git a/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java b/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java index e421d9bcdeb11..097f6a2748be5 100644 --- a/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java +++ b/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java @@ -71,7 +71,7 @@ unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "xml"), unmarshalOut = @BodyType(value = Carrier.MAP, dependsOn = { "unmarshalType", "collectionType", "allowUnmarshallType" }, - byOption = @BodyType.When(option = "useList", value = "true", carrier = Carrier.LIST), + byOption = @BodyType.When(option = "useList", value = "true", carriers = Carrier.LIST), description = "A Map (LinkedHashMap) of the XML; an object of the class unmarshalType" + " names")) public class JacksonXMLDataFormat extends ServiceSupport diff --git a/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsEndpoint.java b/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsEndpoint.java index 67a8ec51e5312..1d77420af22df 100644 --- a/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsEndpoint.java +++ b/components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsEndpoint.java @@ -79,10 +79,10 @@ @BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.NULL }, dependsOn = { "messageConverter", "transferExchange" }, byOption = { - @BodyType.When(option = "mapJmsMessage", value = "false", carrier = Carrier.POJO, + @BodyType.When(option = "mapJmsMessage", value = "false", carriers = Carrier.POJO, javaType = "jakarta.jms.Message"), @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.MAP, Carrier.STREAM, Carrier.POJO, Carrier.NULL }) }, description = "By the JMS message received: a String for a TextMessage, a byte array for a" @@ -91,14 +91,14 @@ consumerReply = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP, Carrier.POJO }), description = "The reply, sent as the producer sends a message"), producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, dependsOn = { "jmsMessageType", "messageConverter", "transferExchange" }, byOption = @BodyType.When(option = "objectMessageEnabled", value = "true", - carrier = { + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP, Carrier.POJO }), description = "Text is sent as a TextMessage; bytes, a stream or a file as a BytesMessage;" @@ -107,9 +107,9 @@ producerOut = @BodyType(value = Carrier.UNKNOWN, byOption = { @BodyType.When(option = "exchangePattern", value = "InOnly", - carrier = Carrier.UNCHANGED), + carriers = Carrier.UNCHANGED), @BodyType.When(option = "disableReplyTo", value = "true", - carrier = Carrier.UNCHANGED) }, + carriers = Carrier.UNCHANGED) }, description = "Unchanged for a message that expects no reply (InOnly). A message that" + " expects one (InOut) gets the body of the reply, as the consumer gives it")) public class JmsEndpoint extends DefaultEndpoint diff --git a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java index be5917ef5e01e..880b0bd42336b 100644 --- a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java +++ b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathLanguage.java @@ -40,7 +40,7 @@ + " is read through Jackson"), expressionOut = @BodyType(value = Carrier.UNKNOWN, byOption = @BodyType.When(option = "writeAsString", value = "true", - carrier = { Carrier.TEXT, Carrier.LIST }), + carriers = { Carrier.TEXT, Carrier.LIST }), description = "The value the path selects: a Map for an object, a List for an array or" + " for a path with a wildcard or a filter, otherwise text, a number or a" + " boolean")) diff --git a/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaEndpoint.java b/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaEndpoint.java index 85645fbcfe208..b56c238d99bb1 100644 --- a/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaEndpoint.java +++ b/components/camel-kafka/src/main/java/org/apache/camel/component/kafka/KafkaEndpoint.java @@ -55,8 +55,8 @@ byOption = { @BodyType.When(option = "valueDeserializer", value = "org.apache.kafka.common.serialization.ByteArrayDeserializer", - carrier = { Carrier.BYTES, Carrier.NULL }, javaType = "byte[]"), - @BodyType.When(option = "batching", value = "true", carrier = Carrier.LIST) }, + carriers = { Carrier.BYTES, Carrier.NULL }, javaType = "byte[]"), + @BodyType.When(option = "batching", value = "true", carriers = Carrier.LIST) }, description = "The value of the record: a String with the default valueDeserializer" + " (StringDeserializer), null for a tombstone. With batching, a List of" + " the exchanges of the records"), diff --git a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java index feb7ebc4fd87a..6b2515bd629c4 100644 --- a/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java +++ b/components/camel-mongodb/src/main/java/org/apache/camel/component/mongodb/MongoDbEndpoint.java @@ -73,7 +73,7 @@ category = { Category.DATABASE }, headersClass = MongoDbConstants.class) @BodyTypes(consumerOut = @BodyType(value = Carrier.POJO, javaType = "org.bson.Document", byOption = @BodyType.When(option = "consumerType", value = "changeStreams", - carrier = { Carrier.POJO, Carrier.NULL }), + carriers = { Carrier.POJO, Carrier.NULL }), description = "The document added to the capped collection; with changeStreams the full" + " document of the change, null when the change has none (an update" + " without fullDocument=updateLookup)"), @@ -83,39 +83,40 @@ producerOut = @BodyType(value = Carrier.UNKNOWN, dependsOn = { "outputType", "writeResultAsHeader" }, byOption = { @BodyType.When(option = "operation", value = "findById", - carrier = { Carrier.POJO, Carrier.NULL }, + carriers = { Carrier.POJO, Carrier.NULL }, javaType = "org.bson.Document"), @BodyType.When(option = "operation", value = "findOneByQuery", - carrier = { Carrier.POJO, Carrier.NULL }, + carriers = { Carrier.POJO, Carrier.NULL }, javaType = "org.bson.Document"), @BodyType.When(option = "operation", value = "findOneAndDelete", - carrier = { Carrier.POJO, Carrier.NULL }, + carriers = { Carrier.POJO, Carrier.NULL }, javaType = "org.bson.Document"), @BodyType.When(option = "operation", value = "findOneAndReplace", - carrier = { Carrier.POJO, Carrier.NULL }, + carriers = { Carrier.POJO, Carrier.NULL }, javaType = "org.bson.Document"), @BodyType.When(option = "operation", value = "findOneAndUpdate", - carrier = { Carrier.POJO, Carrier.NULL }, + carriers = { Carrier.POJO, Carrier.NULL }, javaType = "org.bson.Document"), - @BodyType.When(option = "operation", value = "findAll", carrier = Carrier.LIST), - @BodyType.When(option = "operation", value = "findDistinct", carrier = Carrier.LIST), - @BodyType.When(option = "operation", value = "aggregate", carrier = Carrier.LIST), - @BodyType.When(option = "operation", value = "count", carrier = Carrier.VALUE, + @BodyType.When(option = "operation", value = "findAll", carriers = Carrier.LIST), + @BodyType.When(option = "operation", value = "findDistinct", + carriers = Carrier.LIST), + @BodyType.When(option = "operation", value = "aggregate", carriers = Carrier.LIST), + @BodyType.When(option = "operation", value = "count", carriers = Carrier.VALUE, javaType = "java.lang.Long"), @BodyType.When(option = "operation", value = "insert", - carrier = { Carrier.POJO, Carrier.LIST }), - @BodyType.When(option = "operation", value = "save", carrier = Carrier.POJO), - @BodyType.When(option = "operation", value = "update", carrier = Carrier.POJO, + carriers = { Carrier.POJO, Carrier.LIST }), + @BodyType.When(option = "operation", value = "save", carriers = Carrier.POJO), + @BodyType.When(option = "operation", value = "update", carriers = Carrier.POJO, javaType = "com.mongodb.client.result.UpdateResult"), - @BodyType.When(option = "operation", value = "remove", carrier = Carrier.POJO, + @BodyType.When(option = "operation", value = "remove", carriers = Carrier.POJO, javaType = "com.mongodb.client.result.DeleteResult"), - @BodyType.When(option = "operation", value = "bulkWrite", carrier = Carrier.POJO, + @BodyType.When(option = "operation", value = "bulkWrite", carriers = Carrier.POJO, javaType = "com.mongodb.bulk.BulkWriteResult"), - @BodyType.When(option = "operation", value = "command", carrier = Carrier.POJO, + @BodyType.When(option = "operation", value = "command", carriers = Carrier.POJO, javaType = "org.bson.Document"), - @BodyType.When(option = "operation", value = "getDbStats", carrier = Carrier.POJO, + @BodyType.When(option = "operation", value = "getDbStats", carriers = Carrier.POJO, javaType = "org.bson.Document"), - @BodyType.When(option = "operation", value = "getColStats", carrier = Carrier.POJO, + @BodyType.When(option = "operation", value = "getColStats", carriers = Carrier.POJO, javaType = "org.bson.Document") }, description = "By the operation: a Document or null for a find of one, a List for" + " findAll, findDistinct and aggregate, a Long for count, the document" diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java index c910d2ddce89e..2227077b50dd5 100644 --- a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java +++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java @@ -56,7 +56,7 @@ @Metadata(annotations = { "protocol=http" }) @BodyTypes(consumerOut = @BodyType(value = { Carrier.STREAM, Carrier.BYTES, Carrier.NULL, Carrier.MAP, Carrier.FILE }, byOption = @BodyType.When(option = "useBodyHandler", value = "false", - carrier = Carrier.POJO), + carriers = Carrier.POJO), description = "The request body: the stream cache with the Vert.x engine, a byte array" + " with Spring Boot; null for a request without a body, such as a GET; a" + " Map of the fields of a form (populateBodyWithForm); a File for an" diff --git a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java index 66b43a1957e16..d83a749de8f37 100644 --- a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java +++ b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestEndpoint.java @@ -61,18 +61,18 @@ @BodyTypes(consumerOut = @BodyType(value = { Carrier.STREAM, Carrier.BYTES, Carrier.NULL, Carrier.MAP, Carrier.FILE }, dependsOn = "consumerComponentName", byOption = @BodyType.When(option = "bindingMode", value = "json", - carrier = { Carrier.MAP, Carrier.LIST, Carrier.POJO }), + carriers = { Carrier.MAP, Carrier.LIST, Carrier.POJO }), description = "The request body as the HTTP consumer gives it (platform-http by" + " default). With bindingMode json, the object of inType, or a Map or a" + " List without inType"), consumerReply = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM }, dependsOn = "consumerComponentName", - byOption = @BodyType.When(option = "bindingMode", value = "json", carrier = Carrier.ANY), + byOption = @BodyType.When(option = "bindingMode", value = "json", carriers = Carrier.ANY), description = "The response body as the HTTP consumer writes it. With bindingMode json," + " any object, which the binding writes as JSON"), producerIn = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, dependsOn = "producerComponentName", - byOption = @BodyType.When(option = "bindingMode", value = "json", carrier = Carrier.ANY), + byOption = @BodyType.When(option = "bindingMode", value = "json", carriers = Carrier.ANY), description = "The request body the HTTP producer sends (the http component by default)." + " With bindingMode json, any object, which the binding writes as JSON"), producerOut = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.NULL }, diff --git a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java index 7487f7f91317d..1e846164b355b 100644 --- a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java +++ b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java @@ -41,13 +41,13 @@ format = "xml", description = "XML as text, bytes, a stream or a file, or a DOM"), expressionOut = @BodyType(value = Carrier.POJO, javaType = "org.w3c.dom.NodeList", dependsOn = "resultType", byOption = { - @BodyType.When(option = "resultQName", value = "STRING", carrier = Carrier.TEXT, + @BodyType.When(option = "resultQName", value = "STRING", carriers = Carrier.TEXT, javaType = "java.lang.String"), - @BodyType.When(option = "resultQName", value = "NUMBER", carrier = Carrier.VALUE, + @BodyType.When(option = "resultQName", value = "NUMBER", carriers = Carrier.VALUE, javaType = "java.lang.Double"), - @BodyType.When(option = "resultQName", value = "BOOLEAN", carrier = Carrier.VALUE, + @BodyType.When(option = "resultQName", value = "BOOLEAN", carriers = Carrier.VALUE, javaType = "java.lang.Boolean"), - @BodyType.When(option = "resultQName", value = "NODE", carrier = Carrier.POJO, + @BodyType.When(option = "resultQName", value = "NODE", carriers = Carrier.POJO, javaType = "org.w3c.dom.Node") }, description = "The nodes the expression selects")) public class XPathLanguage extends SingleInputTypedLanguageSupport implements PropertyConfigurer { From 1ef9d76dc3537b03568e57f5da65383cef271717 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 20:52:33 +0200 Subject: [PATCH 12/25] CAMEL-24961: Use When.carriers in the annotations of the AI group Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../camel/component/a2a/A2AEndpoint.java | 41 ++++++++-------- .../component/docling/DoclingEndpoint.java | 32 ++++++------- .../chat/LangChain4jChatEndpoint.java | 4 +- .../component/openai/OpenAIEndpoint.java | 47 ++++++++++--------- .../SomeEndpointWithBadBodyTypes.java | 2 +- 5 files changed, 64 insertions(+), 62 deletions(-) diff --git a/components/camel-ai/camel-a2a/src/main/java/org/apache/camel/component/a2a/A2AEndpoint.java b/components/camel-ai/camel-a2a/src/main/java/org/apache/camel/component/a2a/A2AEndpoint.java index a5abc670b0b6f..0f3a5649244da 100644 --- a/components/camel-ai/camel-a2a/src/main/java/org/apache/camel/component/a2a/A2AEndpoint.java +++ b/components/camel-ai/camel-a2a/src/main/java/org/apache/camel/component/a2a/A2AEndpoint.java @@ -74,7 +74,7 @@ category = { Category.AI }, headersClass = A2AConstants.class) @BodyTypes(consumerOut = @BodyType(value = Carrier.TEXT, - byOption = @BodyType.When(option = "dataFormat", value = "POJO", carrier = Carrier.POJO, + byOption = @BodyType.When(option = "dataFormat", value = "POJO", carriers = Carrier.POJO, javaType = "org.apache.camel.component.a2a.model.Message"), description = "The message of the caller, for SendMessage and SendStreamingMessage (the" + " component answers the task and push config requests itself): the text" @@ -89,19 +89,20 @@ + " when the CamelA2AResponseType header is message"), producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, byOption = { - @BodyType.When(option = "operation", value = "TASK_GET", carrier = Carrier.ANY), - @BodyType.When(option = "operation", value = "TASK_LIST", carrier = Carrier.ANY), - @BodyType.When(option = "operation", value = "TASK_CANCEL", carrier = Carrier.ANY), - @BodyType.When(option = "operation", value = "TASK_SUBSCRIBE", carrier = Carrier.ANY), + @BodyType.When(option = "operation", value = "TASK_GET", carriers = Carrier.ANY), + @BodyType.When(option = "operation", value = "TASK_LIST", carriers = Carrier.ANY), + @BodyType.When(option = "operation", value = "TASK_CANCEL", carriers = Carrier.ANY), + @BodyType.When(option = "operation", value = "TASK_SUBSCRIBE", + carriers = Carrier.ANY), @BodyType.When(option = "operation", value = "PUSH_CONFIG_CREATE", - carrier = Carrier.POJO, + carriers = Carrier.POJO, javaType = "org.apache.camel.component.a2a.model.TaskPushNotificationConfig"), @BodyType.When(option = "operation", value = "PUSH_CONFIG_GET", - carrier = Carrier.ANY), + carriers = Carrier.ANY), @BodyType.When(option = "operation", value = "PUSH_CONFIG_LIST", - carrier = Carrier.ANY), + carriers = Carrier.ANY), @BodyType.When(option = "operation", value = "PUSH_CONFIG_DELETE", - carrier = Carrier.ANY) }, + carriers = Carrier.ANY) }, description = "The message to send: text, sent as one text part (bytes, a stream or a" + " file as their text), or a Message sent as it is; MESSAGE_STREAM also" + " takes a SendMessageRequest. Another body is sent as its toString(), so a" @@ -111,27 +112,27 @@ producerOut = @BodyType(value = Carrier.TEXT, byOption = { @BodyType.When(option = "operation", value = "MESSAGE_STREAM", - carrier = Carrier.ITERATOR, + carriers = Carrier.ITERATOR, javaType = "org.apache.camel.component.a2a.streaming.SseEventIterator"), - @BodyType.When(option = "operation", value = "TASK_GET", carrier = Carrier.TEXT), + @BodyType.When(option = "operation", value = "TASK_GET", carriers = Carrier.TEXT), @BodyType.When(option = "operation", value = "TASK_LIST", - carrier = { Carrier.LIST, Carrier.NULL }), - @BodyType.When(option = "operation", value = "TASK_CANCEL", carrier = Carrier.TEXT), + carriers = { Carrier.LIST, Carrier.NULL }), + @BodyType.When(option = "operation", value = "TASK_CANCEL", carriers = Carrier.TEXT), @BodyType.When(option = "operation", value = "TASK_SUBSCRIBE", - carrier = Carrier.ITERATOR, + carriers = Carrier.ITERATOR, javaType = "org.apache.camel.component.a2a.streaming.SseEventIterator"), @BodyType.When(option = "operation", value = "PUSH_CONFIG_CREATE", - carrier = Carrier.POJO, + carriers = Carrier.POJO, javaType = "org.apache.camel.component.a2a.model.TaskPushNotificationConfig"), @BodyType.When(option = "operation", value = "PUSH_CONFIG_GET", - carrier = Carrier.POJO, + carriers = Carrier.POJO, javaType = "org.apache.camel.component.a2a.model.TaskPushNotificationConfig"), @BodyType.When(option = "operation", value = "PUSH_CONFIG_LIST", - carrier = { Carrier.LIST, Carrier.NULL }), + carriers = { Carrier.LIST, Carrier.NULL }), @BodyType.When(option = "operation", value = "PUSH_CONFIG_DELETE", - carrier = Carrier.MAP), - @BodyType.When(option = "dataFormat", value = "POJO", carrier = Carrier.POJO), - @BodyType.When(option = "dataFormat", value = "RAW", carrier = Carrier.TEXT) }, + carriers = Carrier.MAP), + @BodyType.When(option = "dataFormat", value = "POJO", carriers = Carrier.POJO), + @BodyType.When(option = "dataFormat", value = "RAW", carriers = Carrier.TEXT) }, description = "The reply of the agent as text: the parts of the Message, or of the last" + " message in the history of the Task, one per line. TASK_GET and" + " TASK_CANCEL give the text of the Task, TASK_LIST a List of Task," diff --git a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingEndpoint.java b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingEndpoint.java index 9d7f469b717e1..35fbad76dff3e 100644 --- a/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingEndpoint.java +++ b/components/camel-ai/camel-docling/src/main/java/org/apache/camel/component/docling/DoclingEndpoint.java @@ -45,15 +45,15 @@ producerIn = @BodyType(value = Carrier.ANY, byOption = { @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_MARKDOWN", - carrier = Carrier.LIST), + carriers = Carrier.LIST), @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_HTML", - carrier = Carrier.LIST), + carriers = Carrier.LIST), @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_JSON", - carrier = Carrier.LIST), + carriers = Carrier.LIST), @BodyType.When(option = "operation", value = "BATCH_EXTRACT_TEXT", - carrier = Carrier.LIST), + carriers = Carrier.LIST), @BodyType.When(option = "operation", value = "BATCH_EXTRACT_STRUCTURED_DATA", - carrier = Carrier.LIST) }, + carriers = Carrier.LIST) }, description = "The document: its content as text or bytes, or a File (the GenericFile of" + " the file consumers too). A stream or a Path fails: convert it to bytes" + " first. Text that looks like a URL or a path (it starts with http://," @@ -66,31 +66,31 @@ producerOut = @BodyType(value = Carrier.TEXT, byOption = { @BodyType.When(option = "operation", value = "CONVERT_TO_JSON", - carrier = Carrier.POJO, + carriers = Carrier.POJO, javaType = "ai.docling.core.DoclingDocument"), @BodyType.When(option = "operation", value = "EXTRACT_STRUCTURED_DATA", - carrier = Carrier.POJO, + carriers = Carrier.POJO, javaType = "ai.docling.core.DoclingDocument"), @BodyType.When(option = "operation", value = "CHECK_CONVERSION_STATUS", - carrier = Carrier.POJO, + carriers = Carrier.POJO, javaType = "org.apache.camel.component.docling.ConversionStatus"), @BodyType.When(option = "operation", value = "EXTRACT_METADATA", - carrier = Carrier.POJO, + carriers = Carrier.POJO, javaType = "org.apache.camel.component.docling.DocumentMetadata"), @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_MARKDOWN", - carrier = { Carrier.POJO, Carrier.LIST }), + carriers = { Carrier.POJO, Carrier.LIST }), @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_HTML", - carrier = { Carrier.POJO, Carrier.LIST }), + carriers = { Carrier.POJO, Carrier.LIST }), @BodyType.When(option = "operation", value = "BATCH_CONVERT_TO_JSON", - carrier = { Carrier.POJO, Carrier.LIST }), + carriers = { Carrier.POJO, Carrier.LIST }), @BodyType.When(option = "operation", value = "BATCH_EXTRACT_TEXT", - carrier = { Carrier.POJO, Carrier.LIST }), + carriers = { Carrier.POJO, Carrier.LIST }), @BodyType.When(option = "operation", value = "BATCH_EXTRACT_STRUCTURED_DATA", - carrier = { Carrier.POJO, Carrier.LIST }), + carriers = { Carrier.POJO, Carrier.LIST }), @BodyType.When(option = "operation", value = "CHUNK_HYBRID", - carrier = { Carrier.POJO, Carrier.LIST }), + carriers = { Carrier.POJO, Carrier.LIST }), @BodyType.When(option = "operation", value = "CHUNK_HIERARCHICAL", - carrier = { Carrier.POJO, Carrier.LIST }) }, + carriers = { Carrier.POJO, Carrier.LIST }) }, description = "By the operation: text for the conversions to markdown, HTML and text," + " which with the docling CLI is the path of the output file unless" + " contentInBody (useDoclingServe gives the content); the task id for" diff --git a/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatEndpoint.java b/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatEndpoint.java index 618d031c8ac85..e70f27fa5e799 100644 --- a/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatEndpoint.java +++ b/components/camel-ai/camel-langchain4j-chat/src/main/java/org/apache/camel/component/langchain4j/chat/LangChain4jChatEndpoint.java @@ -39,9 +39,9 @@ @BodyTypes(producerIn = @BodyType(value = Carrier.ANY, byOption = { @BodyType.When(option = "chatOperation", value = "CHAT_SINGLE_MESSAGE_WITH_PROMPT", - carrier = Carrier.MAP), + carriers = Carrier.MAP), @BodyType.When(option = "chatOperation", value = "CHAT_MULTIPLE_MESSAGES", - carrier = Carrier.LIST) }, + carriers = Carrier.LIST) }, description = "The prompt as text, or a ChatMessage; another body is sent as its" + " toString(), and no body fails. CHAT_SINGLE_MESSAGE_WITH_PROMPT takes the" + " variables of the template in the CamelLangChain4jChatPromptTemplate" diff --git a/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/OpenAIEndpoint.java b/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/OpenAIEndpoint.java index f38b76f35e52c..4fbad0d31b780 100644 --- a/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/OpenAIEndpoint.java +++ b/components/camel-ai/camel-openai/src/main/java/org/apache/camel/component/openai/OpenAIEndpoint.java @@ -97,18 +97,18 @@ + " body, or 500 when the route fails, and then sends the event again"), producerIn = @BodyType(value = Carrier.ANY, byOption = { - @BodyType.When(option = "operation", value = "decisions", carrier = Carrier.POJO, + @BodyType.When(option = "operation", value = "decisions", carriers = Carrier.POJO, javaType = "com.openai.models.decisions.DecisionCreateParams"), @BodyType.When(option = "operation", value = "batch", - carrier = { + carriers = { Carrier.MAP, Carrier.LIST, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), @BodyType.When(option = "operation", value = "audio-transcription", - carrier = { Carrier.FILE, Carrier.BYTES, Carrier.STREAM }), + carriers = { Carrier.FILE, Carrier.BYTES, Carrier.STREAM }), @BodyType.When(option = "operation", value = "audio-translation", - carrier = { Carrier.FILE, Carrier.BYTES, Carrier.STREAM }), + carriers = { Carrier.FILE, Carrier.BYTES, Carrier.STREAM }), @BodyType.When(option = "operation", value = "image-edit", - carrier = { + carriers = { Carrier.FILE, Carrier.BYTES, Carrier.STREAM, Carrier.LIST }) }, description = "The prompt of chat-completion and responses: text, or a file, bytes or a" @@ -124,38 +124,39 @@ + " answer do not use the body"), producerOut = @BodyType(value = Carrier.TEXT, byOption = { - @BodyType.When(option = "streaming", value = "true", carrier = Carrier.ITERATOR), + @BodyType.When(option = "streaming", value = "true", carriers = Carrier.ITERATOR), @BodyType.When(option = "autoToolExecution", value = "false", - carrier = { Carrier.TEXT, Carrier.POJO, Carrier.LIST }), - @BodyType.When(option = "operation", value = "decisions", carrier = Carrier.POJO, + carriers = { Carrier.TEXT, Carrier.POJO, Carrier.LIST }), + @BodyType.When(option = "operation", value = "decisions", carriers = Carrier.POJO, javaType = "com.openai.models.decisions.Decision"), - @BodyType.When(option = "operation", value = "responses", carrier = Carrier.TEXT), + @BodyType.When(option = "operation", value = "responses", carriers = Carrier.TEXT), @BodyType.When(option = "operation", value = "responses-retrieve", - carrier = Carrier.TEXT), + carriers = Carrier.TEXT), @BodyType.When(option = "operation", value = "responses-cancel", - carrier = Carrier.TEXT), - @BodyType.When(option = "operation", value = "batch", carrier = Carrier.UNCHANGED), + carriers = Carrier.TEXT), + @BodyType.When(option = "operation", value = "batch", carriers = Carrier.UNCHANGED), @BodyType.When(option = "operation", value = "batch-retrieve", - carrier = Carrier.UNCHANGED), + carriers = Carrier.UNCHANGED), @BodyType.When(option = "operation", value = "batch-cancel", - carrier = Carrier.UNCHANGED), + carriers = Carrier.UNCHANGED), @BodyType.When(option = "operation", value = "batch-results", - carrier = Carrier.ITERATOR), - @BodyType.When(option = "operation", value = "embeddings", carrier = Carrier.LIST), + carriers = Carrier.ITERATOR), + @BodyType.When(option = "operation", value = "embeddings", carriers = Carrier.LIST), @BodyType.When(option = "operation", value = "tool-execution", - carrier = { Carrier.NULL, Carrier.UNCHANGED }), + carriers = { Carrier.NULL, Carrier.UNCHANGED }), @BodyType.When(option = "operation", value = "audio-transcription", - carrier = Carrier.TEXT), + carriers = Carrier.TEXT), @BodyType.When(option = "operation", value = "audio-translation", - carrier = Carrier.TEXT), - @BodyType.When(option = "operation", value = "audio-speech", carrier = Carrier.BYTES, + carriers = Carrier.TEXT), + @BodyType.When(option = "operation", value = "audio-speech", + carriers = Carrier.BYTES, javaType = "byte[]"), @BodyType.When(option = "operation", value = "moderation", - carrier = Carrier.UNCHANGED), + carriers = Carrier.UNCHANGED), @BodyType.When(option = "operation", value = "image-generation", - carrier = { Carrier.BYTES, Carrier.TEXT, Carrier.LIST }), + carriers = { Carrier.BYTES, Carrier.TEXT, Carrier.LIST }), @BodyType.When(option = "operation", value = "image-edit", - carrier = { Carrier.BYTES, Carrier.TEXT, Carrier.LIST }) }, + carriers = { Carrier.BYTES, Carrier.TEXT, Carrier.LIST }) }, description = "The answer of chat-completion as text, also with outputClass or" + " jsonSchema, where it is JSON text: unmarshal it to read its fields." + " With streaming, an Iterator of the chunks (text when MCP tools run in" diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java index ea66e2d6834de..8c0f53728d6a6 100644 --- a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java @@ -72,7 +72,7 @@ public static class OptionValueWithoutCarriers { @UriEndpoint(scheme = "some", syntax = "some", title = "some") @BodyTypes(producerOut = @BodyType(value = Carrier.TEXT, - byOption = @BodyType.When(option = "output", value = "DOM", carrier = Carrier.POJO))) + byOption = @BodyType.When(option = "output", value = "DOM", carriers = Carrier.POJO))) public static class ValueTheOptionDoesNotHave { } } From 3872b8ec58ad95e0d503b7cf457ab3d11dc646f8 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 21 Oct 2026 21:35:13 +0200 Subject: [PATCH 13/25] CAMEL-24961: Catalog body types for object storage The body types of aws2-s3, azure-storage-blob, azure-files, dropbox, google-storage, ibm-cos and minio, read from the code and checked at runtime against LocalStack S3 (aws2-s3, and ibm-cos and minio through their S3 API) and Azurite (azure-storage-blob). The pages of aws2-s3, google-storage and minio said getObject returns an S3Object, a Blob or a MinioObject: it returns the content of the object. The validator calls a body the file as read (a GenericFile) only when the file is its only carrier, not for a blob that is a stream or a file. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../camel/catalog/components/aws2-s3.json | 5 + .../camel/catalog/components/azure-files.json | 5 + .../components/azure-storage-blob.json | 5 + .../camel/catalog/components/dropbox.json | 5 + .../catalog/components/google-storage.json | 5 + .../camel/catalog/components/ibm-cos.json | 5 + .../camel/catalog/components/minio.json | 5 + .../camel/catalog/docs/aws2-s3-component.adoc | 4 +- .../docs/aws2-s3-consumer-examples.adoc | 2 +- .../docs/aws2-s3-producer-operations.adoc | 2 +- .../docs/google-storage-component.adoc | 2 +- .../camel/catalog/docs/minio-component.adoc | 8 +- .../camel/component/aws2/s3/aws2-s3.json | 5 + .../src/main/docs/aws2-s3-component.adoc | 4 +- .../main/docs/aws2-s3-consumer-examples.adoc | 2 +- .../docs/aws2-s3-producer-operations.adoc | 2 +- .../component/aws2/s3/AWS2S3Endpoint.java | 91 +++++++++++++++ .../component/file/azure/azure-files.json | 5 + .../component/file/azure/FilesEndpoint.java | 18 +++ .../storage/blob/azure-storage-blob.json | 5 + .../azure/storage/blob/BlobEndpoint.java | 106 ++++++++++++++++++ .../camel/component/dropbox/dropbox.json | 5 + .../component/dropbox/DropboxEndpoint.java | 34 ++++++ .../google/storage/google-storage.json | 5 + .../main/docs/google-storage-component.adoc | 2 +- .../storage/GoogleCloudStorageEndpoint.java | 39 +++++++ .../camel/component/ibm/cos/ibm-cos.json | 5 + .../component/ibm/cos/IBMCOSEndpoint.java | 34 ++++++ .../apache/camel/component/minio/minio.json | 5 + .../src/main/docs/minio-component.adoc | 8 +- .../camel/component/minio/MinioEndpoint.java | 44 ++++++++ .../dsl/yaml/validator/CatalogBodyTypes.java | 7 +- .../dsl/yaml/validator/TextBodyFlow.java | 2 +- .../dsl/yaml/validator/TextBodyFlowTest.java | 53 +++++++++ 34 files changed, 513 insertions(+), 21 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-s3.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-s3.json index a99e76777b8b3..e2d95e2159ccd 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-s3.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-s3.json @@ -145,6 +145,11 @@ "CamelAwsS3UploadLinkHttpRequestHeaders": { "index": 52, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Map>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The headers that are needed by the service for upload (not needed when BrowserCompatible is true)", "constantName": "org.apache.camel.component.aws2.s3.AWS2S3Constants#UPLOAD_LINK_HTTP_REQUEST_HEADERS" }, "CamelAwsS3UploadLinkSignedPayload": { "index": 53, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The request payload that is needed by the service for upload (not needed when BrowserCompatible is true)", "constantName": "org.apache.camel.component.aws2.s3.AWS2S3Constants#UPLOAD_LINK_SIGNED_PAYLOAD" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "byOption": [ { "option": "includeBody", "value": "false", "carriers": [ "stream" ] }, { "option": "ignoreBody", "value": "true", "carriers": [ "null" ] } ], "description": "The content of the object as a byte array, one message per object, with its key and metadata in headers. With includeBody=false the stream of the object, and with ignoreBody=true no body" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "operation", "pojoRequest" ], "description": "The content to upload, when no operation is set: text, bytes, a stream or a file. A Map or a List fails: marshal it first. The operations take their input from headers, or with pojoRequest=true from the request of the AWS SDK in the body, such as a GetObjectRequest" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "getObject", "carriers": [ "stream" ] }, { "option": "operation", "value": "getObjectRange", "carriers": [ "stream" ] }, { "option": "operation", "value": "listObjects", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "listBuckets", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "getObjectTagging", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "getBucketTagging", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "createDownloadLink", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "createUploadLink", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "getBucketPolicy", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "deleteObject", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "headBucket", "carriers": [ "pojo", "unchanged" ] }, { "option": "operation", "value": "headObject", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.HeadObjectResponse" }, { "option": "operation", "value": "deleteObjects", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.DeleteObjectsResponse" }, { "option": "operation", "value": "deleteBucket", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.DeleteBucketResponse" }, { "option": "operation", "value": "createBucket", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.CreateBucketResponse" }, { "option": "operation", "value": "restoreObject", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.RestoreObjectResponse" }, { "option": "operation", "value": "putObjectTagging", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.PutObjectTaggingResponse" }, { "option": "operation", "value": "deleteObjectTagging", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.DeleteObjectTaggingResponse" }, { "option": "operation", "value": "getObjectAcl", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.GetObjectAclResponse" }, { "option": "operation", "value": "putObjectAcl", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.PutObjectAclResponse" }, { "option": "operation", "value": "putBucketTagging", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.PutBucketTaggingResponse" }, { "option": "operation", "value": "deleteBucketTagging", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.DeleteBucketTaggingResponse" }, { "option": "operation", "value": "getBucketVersioning", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.GetBucketVersioningResponse" }, { "option": "operation", "value": "putBucketVersioning", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.PutBucketVersioningResponse" }, { "option": "operation", "value": "putBucketPolicy", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.PutBucketPolicyResponse" }, { "option": "operation", "value": "deleteBucketPolicy", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.DeleteBucketPolicyResponse" } ], "description": "Unchanged after an upload and a copyObject, with the ETag in a header. By the operation: the stream of the object for getObject and getObjectRange, a List for the lists and the tagging gets, the URL as text for the links, the policy JSON for getBucketPolicy, true for deleteObject, and the response of the AWS SDK for the others. getObject with ignoreBody=true, headBucket for a bucket that does not exist and streamingUploadMode keep the body" } + }, "properties": { "bucketNameOrArn": { "index": 0, "kind": "path", "displayName": "Bucket Name Or Arn", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Bucket name or ARN" }, "autoCreateBucket": { "index": 1, "kind": "parameter", "displayName": "Auto Create Bucket", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Setting the autocreation of the S3 bucket bucketName. This will apply also in case of moveAfterRead option enabled, and it will create the destinationBucket if it doesn't exist already." }, 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..47b35f5d38ffa 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 @@ -47,6 +47,11 @@ "CamelFileLocalWorkPath": { "index": 13, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Path to the local work file, if local work directory is used.", "constantName": "org.apache.camel.component.file.azure.FilesConstants#FILE_LOCAL_WORK_PATH" }, "CamelFileHost": { "index": 14, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The remote hostname.", "constantName": "org.apache.camel.component.file.azure.FilesConstants#FILE_HOST" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "file" ], "dependsOn": [ "preMove" ], "byOption": [ { "option": "streamDownload", "value": "true", "carriers": [ "stream" ] }, { "option": "download", "value": "false", "carriers": [ "null" ] } ], "description": "The file as read: a RemoteFile with its content loaded as bytes, which converts to text, bytes or a stream; a stream with streamDownload; with preMove its content, a byte array" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "What converts to an InputStream or a byte array: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "account": { "index": 0, "kind": "path", "displayName": "Account", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.azure.FilesConfiguration", "configurationField": "configuration", "description": "The account to use" }, "share": { "index": 1, "kind": "path", "displayName": "Share", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.azure.FilesConfiguration", "configurationField": "configuration", "description": "The share to use" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-blob.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-blob.json index 677b93044d53d..c69e7afe81ddf 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-blob.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-blob.json @@ -157,6 +157,11 @@ "CamelAzureStorageBlobImmutabilityPolicyMode": { "index": 77, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "com.azure.storage.blob.models.BlobImmutabilityPolicyMode", "enum": [ "Mutable", "Unlocked", "Locked" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(setBlobImmutabilityPolicy) The mode of the immutability policy: UNLOCKED (default, can be modified or deleted), LOCKED (cannot be modified or shortened, only extended), or MUTABLE.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#BLOB_IMMUTABILITY_POLICY_MODE" }, "CamelAzureStorageBlobRehydratePriority": { "index": 78, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "com.azure.storage.blob.models.RehydratePriority", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(setBlobTier) The rehydrate priority used when rehydrating a blob from the archive tier: Standard or High. Ignored when changing tier between non-archive tiers.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#REHYDRATE_PRIORITY" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "file" ], "description": "The content of the blob, one message per blob: a stream that reads it, or with fileDir the java.io.File it is downloaded to" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "operation", "value": "uploadBlockBlob", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "operation", "value": "commitAppendBlob", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "operation", "value": "uploadPageBlob", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "operation", "value": "stageBlockBlobList", "carriers": [ "list", "pojo" ] }, { "option": "operation", "value": "commitBlobBlockList", "carriers": [ "list", "pojo" ] } ], "description": "The content to upload for uploadBlockBlob, commitAppendBlob and uploadPageBlob: text, bytes, a stream or a file; a Map or a List fails: marshal it first. A List of BlobBlock for stageBlockBlobList, and of Block for commitBlobBlockList. getBlob writes into an OutputStream body. The other operations do not use the body, or take their value from a header first: the file of uploadBlockBlobChunked, the tags, the tag filter, the legal hold, the tier and the policy" }, + "producerOut": { "carriers": [ "list" ], "byOption": [ { "option": "operation", "value": "getBlob", "carriers": [ "stream" ] }, { "option": "operation", "value": "downloadBlobToFile", "carriers": [ "file" ], "javaType": "java.io.File" }, { "option": "operation", "value": "getBlobTags", "carriers": [ "map" ], "javaType": "java.util.Map" }, { "option": "operation", "value": "getPageBlobRanges", "carriers": [ "iterator" ], "javaType": "com.azure.core.http.rest.PagedIterable" }, { "option": "operation", "value": "getBlobBlockList", "carriers": [ "pojo" ], "javaType": "com.azure.storage.blob.models.BlockList" }, { "option": "operation", "value": "setBlobImmutabilityPolicy", "carriers": [ "pojo" ], "javaType": "com.azure.storage.blob.models.BlobImmutabilityPolicy" }, { "option": "operation", "value": "setBlobTier", "carriers": [ "pojo" ], "javaType": "com.azure.storage.blob.models.AccessTier" }, { "option": "operation", "value": "copyBlob", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "createBlobSnapshot", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "setBlobLegalHold", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "createBlobContainer", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "deleteBlobContainer", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "deleteBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "downloadLink", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "uploadBlockBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "uploadBlockBlobChunked", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "stageBlockBlobList", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "commitBlobBlockList", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "createAppendBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "commitAppendBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "createPageBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "uploadPageBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "resizePageBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "clearPageBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "setBlobTags", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "undeleteBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" } ], "description": "A List of the items of the SDK for listBlobContainers, the default, findBlobsByTags, listBlobs, listBlobVersions and getChangeFeed. A stream of the content for getBlob, or the OutputStream body it wrote into; the java.io.File for downloadBlobToFile; true for the operations that create, upload, set or delete, with their results in headers, such as the link of downloadLink" } + }, "properties": { "accountName": { "index": 0, "kind": "path", "displayName": "Account Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Azure account name to be used for authentication with azure blob services" }, "containerName": { "index": 1, "kind": "path", "displayName": "Container Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "The blob container name" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dropbox.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dropbox.json index 7233ac5194228..f5be463c68e96 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dropbox.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dropbox.json @@ -43,6 +43,11 @@ "DELETED_PATH": { "index": 11, "kind": "header", "displayName": "", "group": "del", "label": "del", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the path deleted on dropbox", "constantName": "org.apache.camel.component.dropbox.util.DropboxConstants#DELETED_PATH" }, "MOVED_PATH": { "index": 12, "kind": "header", "displayName": "", "group": "move", "label": "move", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the path moved on dropbox", "constantName": "org.apache.camel.component.dropbox.util.DropboxConstants#MOVED_PATH" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "operation", "value": "get", "carriers": [ "stream", "bytes", "map" ] }, { "option": "operation", "value": "search", "carriers": [ "list" ], "javaType": "java.util.List" } ], "description": "One message per poll. get: the content of the file in remotePath as a stream cache (a byte array when stream caching is off), or for a folder a Map of the path to the content of each file. search: a List of SearchMatchV2" }, + "producerIn": { "carriers": [ "any" ], "description": "Only put reads the body, unless localPath or the CamelDropboxLocalPath header names a local file or folder to upload: the content to upload, as text, bytes, a stream or a file. A Map or a List is not uploaded, and the result is KO without an error: marshal it first" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "operation", "value": "put", "carriers": [ "value", "map" ] }, { "option": "operation", "value": "get", "carriers": [ "stream", "bytes", "map" ] }, { "option": "operation", "value": "del", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "move", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "search", "carriers": [ "list" ], "javaType": "java.util.List" } ], "description": "put: OK or KO, a DropboxResultCode, or for a local folder of several files a Map of each remote path to its result. get: the content of the file as a stream cache (a byte array when stream caching is off), or a Map of the path to the content of each file of a folder. del: the path deleted. move: the new path. search: a List of SearchMatchV2" } + }, "properties": { "operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.dropbox.util.DropboxOperation", "enum": [ "put", "del", "search", "get", "move" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.dropbox.DropboxConfiguration", "configurationField": "configuration", "description": "The specific action (typically is a CRUD action) to perform on Dropbox remote folder." }, "clientIdentifier": { "index": 1, "kind": "parameter", "displayName": "Client Identifier", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.dropbox.DropboxConfiguration", "configurationField": "configuration", "description": "Name of the app registered to make API requests" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/google-storage.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/google-storage.json index c074a07ef91bf..669344fe5b628 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/google-storage.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/google-storage.json @@ -79,6 +79,11 @@ "CamelGoogleCloudStorageLastUpdate": { "index": 26, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The last update of the object", "constantName": "org.apache.camel.component.google.storage.GoogleCloudStorageConstants#METADATA_LAST_UPDATE" }, "CamelGoogleCloudStorageOverrideBucketName": { "index": 27, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The bucket Name to override which this object will be stored or which will be used for the current operation or in which this object is contained.", "constantName": "org.apache.camel.component.google.storage.GoogleCloudStorageConstants#OVERRIDE_BUCKET_NAME" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "bytes", "file" ], "byOption": [ { "option": "includeBody", "value": "false", "carriers": [ "pojo" ], "javaType": "com.google.cloud.storage.Blob" } ], "description": "The content of the object, one message per object, with its metadata in headers: a stream cache, or a byte array when stream caching is off. With downloadFileName the java.io.File it is downloaded to, and with includeBody=false the Blob, which has the metadata and not the content" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "operation" ], "description": "The content to upload, when no operation is set: text, bytes, a stream or a file. A Map, a List or no body fails: marshal it first. The operations take their input from options and headers" }, + "producerOut": { "carriers": [ "pojo" ], "javaType": "com.google.cloud.storage.Blob", "byOption": [ { "option": "operation", "value": "getObject", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "operation", "value": "listObjects", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "listBuckets", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "copyObject", "carriers": [ "pojo" ], "javaType": "com.google.cloud.storage.CopyWriter" }, { "option": "operation", "value": "deleteObject", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "deleteBucket", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "createDownloadLink", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "The Blob of the uploaded object. By the operation: the content as a byte array for getObject, with its metadata in headers, a List of Blob or Bucket for the lists, the CopyWriter for copyObject, whose getResult() gives the Blob of the copy, true or false for the deletes and the signed URL as text for createDownloadLink" } + }, "properties": { "bucketName": { "index": 0, "kind": "path", "displayName": "Bucket Name", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.google.storage.GoogleCloudStorageConfiguration", "configurationField": "configuration", "description": "Bucket name or ARN" }, "autoCreateBucket": { "index": 1, "kind": "parameter", "displayName": "Auto Create Bucket", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.google.storage.GoogleCloudStorageConfiguration", "configurationField": "configuration", "description": "Setting the autocreation of the bucket bucketName." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ibm-cos.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ibm-cos.json index 3158ed8eac8c5..02e6f53e84969 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ibm-cos.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ibm-cos.json @@ -77,6 +77,11 @@ "CamelIBMCOSRangeEnd": { "index": 19, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The range end position for partial object retrieval", "constantName": "org.apache.camel.component.ibm.cos.IBMCOSConstants#RANGE_END" }, "CamelIBMCOSBucketExists": { "index": 20, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Whether the bucket exists or not", "constantName": "org.apache.camel.component.ibm.cos.IBMCOSConstants#BUCKET_EXISTS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream" ], "byOption": [ { "option": "includeBody", "value": "false", "carriers": [ "null" ] } ], "description": "The content of the object as a stream, one message per object, with its key and metadata in headers. No body with includeBody=false" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "operation" ], "byOption": [ { "option": "operation", "value": "putObject", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "The content to upload with putObject, the default: text, bytes, a stream or a file. A Map, a List or no body fails: marshal it first. The other operations take their input from headers" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "getObject", "carriers": [ "stream" ] }, { "option": "operation", "value": "getObjectRange", "carriers": [ "stream" ] }, { "option": "operation", "value": "listObjects", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "listBuckets", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "deleteObjects", "carriers": [ "list" ] }, { "option": "operation", "value": "headBucket", "carriers": [ "value" ], "javaType": "java.lang.Boolean" } ], "description": "Unchanged after putObject (with the ETag in a header), copyObject, deleteObject, createBucket and deleteBucket. getObject and getObjectRange give the content as a stream, listObjects a List of the first page of objects, listBuckets a List of Bucket, deleteObjects a List of the deleted objects and headBucket whether the bucket exists" } + }, "properties": { "bucketName": { "index": 0, "kind": "path", "displayName": "Bucket Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Bucket name" }, "autoCreateBucket": { "index": 1, "kind": "parameter", "displayName": "Auto Create Bucket", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.ibm.cos.IBMCOSConfiguration", "configurationField": "configuration", "description": "Automatically create the bucket if it doesn't exist" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/minio.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/minio.json index 317451362eb3c..6ef423af16830 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/minio.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/minio.json @@ -99,6 +99,11 @@ "CamelMinioPresignedURLExpirationTime": { "index": 21, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Expiration of minio presigned url in Seconds", "constantName": "org.apache.camel.component.minio.MinioConstants#PRESIGNED_URL_EXPIRATION_TIME" }, "CamelMinioOverrideBucketName": { "index": 22, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The bucket Name to override which this object will be stored or which will be used for the current operation or in which this object is contained.", "constantName": "org.apache.camel.component.minio.MinioConstants#OVERRIDE_BUCKET_NAME" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "byOption": [ { "option": "includeBody", "value": "false", "carriers": [ "null" ] } ], "description": "The content of the object as a byte array, one message per object, with its metadata in headers. No body with includeBody=false" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "operation", "pojoRequest" ], "description": "The content to upload, when no operation is set: text, bytes, a stream or a file. A Map, a List or no body fails: marshal it first. The operations take their input from headers, or with pojoRequest=true from the builder of the request of the Minio SDK in the body, such as a GetObjectArgs.Builder; deleteObjects works only so" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "getObject", "carriers": [ "stream" ] }, { "option": "operation", "value": "getObjectRange", "carriers": [ "stream" ] }, { "option": "operation", "value": "listObjects", "carriers": [ "iterator" ], "javaType": "java.lang.Iterable>" }, { "option": "operation", "value": "listBuckets", "carriers": [ "iterator" ], "javaType": "java.util.Iterator" }, { "option": "operation", "value": "deleteObject", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "deleteObjects", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "deleteBucket", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "createDownloadLink", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "createUploadLink", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "Unchanged after an upload and a copyObject, with the ETag in a header. By the operation: the stream of the object for getObject and getObjectRange, a lazy Iterable of Result for listObjects, whose get() gives the Item, an Iterator of Bucket for listBuckets, true for the deletes, ok for deleteBucket and the URL as text for the links" } + }, "properties": { "bucketName": { "index": 0, "kind": "path", "displayName": "Bucket Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.minio.MinioConfiguration", "configurationField": "configuration", "description": "Bucket name" }, "autoCreateBucket": { "index": 1, "kind": "parameter", "displayName": "Auto Create Bucket", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.minio.MinioConfiguration", "configurationField": "configuration", "description": "Setting the autocreation of the bucket if bucket name not exist." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-component.adoc index ed3923fa2cafc..56423c115d563 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-component.adoc @@ -69,8 +69,8 @@ Camel-AWS2-S3 component provides the following operation on the producer side: - listBuckets - deleteBucket - listObjects -- getObject (this will return an S3Object instance) -- getObjectRange (this will return an S3Object instance) +- getObject (this will return the content of the object as a stream) +- getObjectRange (this will return the range of the content as a stream) - createDownloadLink - createUploadLink - headBucket diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-consumer-examples.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-consumer-examples.adoc index f86b54a59b311..5e584818cb817 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-consumer-examples.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-consumer-examples.adoc @@ -225,7 +225,7 @@ YAML:: ---- ==== -This consumer polls every 60 seconds, processes up to 5 objects per poll, and doesn't include the object body in the message (only metadata). +This consumer polls every 60 seconds, processes up to 5 objects per poll, and puts the stream of the object in the body instead of reading it into a byte array. Use `ignoreBody: true` to get only the metadata. == Consumer with file filtering and no deletion diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-producer-operations.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-producer-operations.adoc index f7782ee6cf28d..64415177080ab 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-producer-operations.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/aws2-s3-producer-operations.adoc @@ -83,7 +83,7 @@ don't require a key header — just set the `operation` parameter. | | `getObject` -| Get a single object. Returns an `S3Object` instance. +| Get a single object. Returns its content as a stream. | | `getObjectRange` diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/google-storage-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/google-storage-component.adoc index e088354e966aa..4678ee29f9a0d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/google-storage-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/google-storage-component.adoc @@ -544,7 +544,7 @@ YAML:: ---- ==== -This operation will return a Blob object instance related to the `OBJECT_NAME` object in `myCamelBucket` bucket. +This operation will return the content of the `OBJECT_NAME` object in `myCamelBucket` bucket as a byte array, with its metadata in headers. - `CreateDownloadLink`: this operation will return a download link diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/minio-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/minio-component.adoc index a0e2de922b1ac..49889d3f5b579 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/minio-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/minio-component.adoc @@ -103,8 +103,8 @@ Camel-Minio component provides the following operation on the producer side: - `listBuckets` - `deleteBucket` - `listObjects` -- `getObject` (this will return a `MinioObject instance) -- `getObjectRange` (this will return a `MinioObject instance) +- `getObject` (this will return the content of the object as a stream) +- `getObjectRange` (this will return the range of the content as a stream) - `createDownloadLink` (this will return a Presigned download Url) - `createUploadLink` (this will return a Presigned upload url) @@ -450,7 +450,7 @@ YAML:: ---- ==== -This operation will return a MinioObject instance related to the camelKey object in `mycamelbucket` bucket. +This operation will return the content of the camelKey object in `mycamelbucket` bucket as a stream. - `GetObjectRange`: this operation gets a single object range in a specific bucket @@ -514,7 +514,7 @@ YAML:: uri: mock:result ---- ==== -This operation will return a MinioObject instance related to the camelKey object in `mycamelbucket` bucket, containing bytes from 0 to 9. +This operation will return the bytes from 0 to 9 of the camelKey object in `mycamelbucket` bucket as a stream. - `createDownloadLink`: this operation will return a presigned url through which a file can be downloaded using GET method diff --git a/components/camel-aws/camel-aws2-s3/src/generated/resources/META-INF/org/apache/camel/component/aws2/s3/aws2-s3.json b/components/camel-aws/camel-aws2-s3/src/generated/resources/META-INF/org/apache/camel/component/aws2/s3/aws2-s3.json index a99e76777b8b3..e2d95e2159ccd 100644 --- a/components/camel-aws/camel-aws2-s3/src/generated/resources/META-INF/org/apache/camel/component/aws2/s3/aws2-s3.json +++ b/components/camel-aws/camel-aws2-s3/src/generated/resources/META-INF/org/apache/camel/component/aws2/s3/aws2-s3.json @@ -145,6 +145,11 @@ "CamelAwsS3UploadLinkHttpRequestHeaders": { "index": 52, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Map>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The headers that are needed by the service for upload (not needed when BrowserCompatible is true)", "constantName": "org.apache.camel.component.aws2.s3.AWS2S3Constants#UPLOAD_LINK_HTTP_REQUEST_HEADERS" }, "CamelAwsS3UploadLinkSignedPayload": { "index": 53, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The request payload that is needed by the service for upload (not needed when BrowserCompatible is true)", "constantName": "org.apache.camel.component.aws2.s3.AWS2S3Constants#UPLOAD_LINK_SIGNED_PAYLOAD" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "byOption": [ { "option": "includeBody", "value": "false", "carriers": [ "stream" ] }, { "option": "ignoreBody", "value": "true", "carriers": [ "null" ] } ], "description": "The content of the object as a byte array, one message per object, with its key and metadata in headers. With includeBody=false the stream of the object, and with ignoreBody=true no body" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "operation", "pojoRequest" ], "description": "The content to upload, when no operation is set: text, bytes, a stream or a file. A Map or a List fails: marshal it first. The operations take their input from headers, or with pojoRequest=true from the request of the AWS SDK in the body, such as a GetObjectRequest" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "getObject", "carriers": [ "stream" ] }, { "option": "operation", "value": "getObjectRange", "carriers": [ "stream" ] }, { "option": "operation", "value": "listObjects", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "listBuckets", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "getObjectTagging", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "getBucketTagging", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "createDownloadLink", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "createUploadLink", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "getBucketPolicy", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "deleteObject", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "headBucket", "carriers": [ "pojo", "unchanged" ] }, { "option": "operation", "value": "headObject", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.HeadObjectResponse" }, { "option": "operation", "value": "deleteObjects", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.DeleteObjectsResponse" }, { "option": "operation", "value": "deleteBucket", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.DeleteBucketResponse" }, { "option": "operation", "value": "createBucket", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.CreateBucketResponse" }, { "option": "operation", "value": "restoreObject", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.RestoreObjectResponse" }, { "option": "operation", "value": "putObjectTagging", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.PutObjectTaggingResponse" }, { "option": "operation", "value": "deleteObjectTagging", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.DeleteObjectTaggingResponse" }, { "option": "operation", "value": "getObjectAcl", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.GetObjectAclResponse" }, { "option": "operation", "value": "putObjectAcl", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.PutObjectAclResponse" }, { "option": "operation", "value": "putBucketTagging", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.PutBucketTaggingResponse" }, { "option": "operation", "value": "deleteBucketTagging", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.DeleteBucketTaggingResponse" }, { "option": "operation", "value": "getBucketVersioning", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.GetBucketVersioningResponse" }, { "option": "operation", "value": "putBucketVersioning", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.PutBucketVersioningResponse" }, { "option": "operation", "value": "putBucketPolicy", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.PutBucketPolicyResponse" }, { "option": "operation", "value": "deleteBucketPolicy", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.s3.model.DeleteBucketPolicyResponse" } ], "description": "Unchanged after an upload and a copyObject, with the ETag in a header. By the operation: the stream of the object for getObject and getObjectRange, a List for the lists and the tagging gets, the URL as text for the links, the policy JSON for getBucketPolicy, true for deleteObject, and the response of the AWS SDK for the others. getObject with ignoreBody=true, headBucket for a bucket that does not exist and streamingUploadMode keep the body" } + }, "properties": { "bucketNameOrArn": { "index": 0, "kind": "path", "displayName": "Bucket Name Or Arn", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Bucket name or ARN" }, "autoCreateBucket": { "index": 1, "kind": "parameter", "displayName": "Auto Create Bucket", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Setting the autocreation of the S3 bucket bucketName. This will apply also in case of moveAfterRead option enabled, and it will create the destinationBucket if it doesn't exist already." }, diff --git a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc index ed3923fa2cafc..56423c115d563 100644 --- a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc +++ b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc @@ -69,8 +69,8 @@ Camel-AWS2-S3 component provides the following operation on the producer side: - listBuckets - deleteBucket - listObjects -- getObject (this will return an S3Object instance) -- getObjectRange (this will return an S3Object instance) +- getObject (this will return the content of the object as a stream) +- getObjectRange (this will return the range of the content as a stream) - createDownloadLink - createUploadLink - headBucket diff --git a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-consumer-examples.adoc b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-consumer-examples.adoc index f86b54a59b311..5e584818cb817 100644 --- a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-consumer-examples.adoc +++ b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-consumer-examples.adoc @@ -225,7 +225,7 @@ YAML:: ---- ==== -This consumer polls every 60 seconds, processes up to 5 objects per poll, and doesn't include the object body in the message (only metadata). +This consumer polls every 60 seconds, processes up to 5 objects per poll, and puts the stream of the object in the body instead of reading it into a byte array. Use `ignoreBody: true` to get only the metadata. == Consumer with file filtering and no deletion diff --git a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-producer-operations.adoc b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-producer-operations.adoc index f7782ee6cf28d..64415177080ab 100644 --- a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-producer-operations.adoc +++ b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-producer-operations.adoc @@ -83,7 +83,7 @@ don't require a key header — just set the `operation` parameter. | | `getObject` -| Get a single object. Returns an `S3Object` instance. +| Get a single object. Returns its content as a stream. | | `getObjectRange` diff --git a/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Endpoint.java b/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Endpoint.java index 7350a7bebd8f2..2ff11c29cc66f 100644 --- a/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Endpoint.java +++ b/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Endpoint.java @@ -25,6 +25,9 @@ import org.apache.camel.Producer; import org.apache.camel.component.aws2.s3.client.AWS2S3ClientFactory; import org.apache.camel.component.aws2.s3.stream.AWS2S3StreamUploadProducer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.IdempotentRepository; import org.apache.camel.spi.Metadata; @@ -49,6 +52,94 @@ @UriEndpoint(firstVersion = "3.2.0", scheme = "aws2-s3", title = "AWS S3 Storage Service", syntax = "aws2-s3://bucketNameOrArn", category = { Category.CLOUD, Category.FILE }, headersClass = AWS2S3Constants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]", + byOption = { + @BodyType.When(option = "includeBody", value = "false", carriers = Carrier.STREAM), + @BodyType.When(option = "ignoreBody", value = "true", carriers = Carrier.NULL) }, + description = "The content of the object as a byte array, one message per object, with its" + + " key and metadata in headers. With includeBody=false the stream of the" + + " object, and with ignoreBody=true no body"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + dependsOn = { "operation", "pojoRequest" }, + description = "The content to upload, when no operation is set: text, bytes, a stream or a" + + " file. A Map or a List fails: marshal it first. The operations take their" + + " input from headers, or with pojoRequest=true from the request of the AWS SDK" + + " in the body, such as a GetObjectRequest"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + byOption = { + @BodyType.When(option = "operation", value = "getObject", carriers = Carrier.STREAM), + @BodyType.When(option = "operation", value = "getObjectRange", + carriers = Carrier.STREAM), + @BodyType.When(option = "operation", value = "listObjects", carriers = Carrier.LIST, + javaType = "java.util.List"), + @BodyType.When(option = "operation", value = "listBuckets", carriers = Carrier.LIST, + javaType = "java.util.List"), + @BodyType.When(option = "operation", value = "getObjectTagging", + carriers = Carrier.LIST, + javaType = "java.util.List"), + @BodyType.When(option = "operation", value = "getBucketTagging", + carriers = Carrier.LIST, + javaType = "java.util.List"), + @BodyType.When(option = "operation", value = "createDownloadLink", + carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "operation", value = "createUploadLink", + carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "operation", value = "getBucketPolicy", + carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "operation", value = "deleteObject", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "headBucket", + carriers = { Carrier.POJO, Carrier.UNCHANGED }), + @BodyType.When(option = "operation", value = "headObject", carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.HeadObjectResponse"), + @BodyType.When(option = "operation", value = "deleteObjects", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.DeleteObjectsResponse"), + @BodyType.When(option = "operation", value = "deleteBucket", carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.DeleteBucketResponse"), + @BodyType.When(option = "operation", value = "createBucket", carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.CreateBucketResponse"), + @BodyType.When(option = "operation", value = "restoreObject", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.RestoreObjectResponse"), + @BodyType.When(option = "operation", value = "putObjectTagging", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.PutObjectTaggingResponse"), + @BodyType.When(option = "operation", value = "deleteObjectTagging", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.DeleteObjectTaggingResponse"), + @BodyType.When(option = "operation", value = "getObjectAcl", carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.GetObjectAclResponse"), + @BodyType.When(option = "operation", value = "putObjectAcl", carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.PutObjectAclResponse"), + @BodyType.When(option = "operation", value = "putBucketTagging", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.PutBucketTaggingResponse"), + @BodyType.When(option = "operation", value = "deleteBucketTagging", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.DeleteBucketTaggingResponse"), + @BodyType.When(option = "operation", value = "getBucketVersioning", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.GetBucketVersioningResponse"), + @BodyType.When(option = "operation", value = "putBucketVersioning", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.PutBucketVersioningResponse"), + @BodyType.When(option = "operation", value = "putBucketPolicy", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.PutBucketPolicyResponse"), + @BodyType.When(option = "operation", value = "deleteBucketPolicy", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.s3.model.DeleteBucketPolicyResponse") }, + description = "Unchanged after an upload and a copyObject, with the ETag in a header. By the" + + " operation: the stream of the object for getObject and getObjectRange, a" + + " List for the lists and the tagging gets, the URL as text for the links, the" + + " policy JSON for getBucketPolicy, true for deleteObject, and the response of" + + " the AWS SDK for the others. getObject with ignoreBody=true, headBucket for a" + + " bucket that does not exist and streamingUploadMode keep the body")) public class AWS2S3Endpoint extends ScheduledPollEndpoint implements EndpointServiceLocation { private static final Logger LOG = LoggerFactory.getLogger(AWS2S3Endpoint.class); 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..47b35f5d38ffa 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 @@ -47,6 +47,11 @@ "CamelFileLocalWorkPath": { "index": 13, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Path to the local work file, if local work directory is used.", "constantName": "org.apache.camel.component.file.azure.FilesConstants#FILE_LOCAL_WORK_PATH" }, "CamelFileHost": { "index": 14, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The remote hostname.", "constantName": "org.apache.camel.component.file.azure.FilesConstants#FILE_HOST" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "file" ], "dependsOn": [ "preMove" ], "byOption": [ { "option": "streamDownload", "value": "true", "carriers": [ "stream" ] }, { "option": "download", "value": "false", "carriers": [ "null" ] } ], "description": "The file as read: a RemoteFile with its content loaded as bytes, which converts to text, bytes or a stream; a stream with streamDownload; with preMove its content, a byte array" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "What converts to an InputStream or a byte array: text, bytes, a stream or a file. A Map or a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "account": { "index": 0, "kind": "path", "displayName": "Account", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.azure.FilesConfiguration", "configurationField": "configuration", "description": "The account to use" }, "share": { "index": 1, "kind": "path", "displayName": "Share", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.file.azure.FilesConfiguration", "configurationField": "configuration", "description": "The share to use" }, diff --git a/components/camel-azure/camel-azure-files/src/main/java/org/apache/camel/component/file/azure/FilesEndpoint.java b/components/camel-azure/camel-azure-files/src/main/java/org/apache/camel/component/file/azure/FilesEndpoint.java index ccbce1eaba6af..692d67aaae7b6 100644 --- a/components/camel-azure/camel-azure-files/src/main/java/org/apache/camel/component/file/azure/FilesEndpoint.java +++ b/components/camel-azure/camel-azure-files/src/main/java/org/apache/camel/component/file/azure/FilesEndpoint.java @@ -30,6 +30,9 @@ import org.apache.camel.component.file.azure.strategy.FilesProcessStrategyFactory; import org.apache.camel.component.file.remote.RemoteFileConsumer; import org.apache.camel.component.file.remote.RemoteFileEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -51,6 +54,21 @@ + "siteCommand,fastExistsCheck,soTimeout,separator,sendNoop,ignoreFileNotFoundOrPermissionError," + "bufferSize,moveExisting,username,host") @ManagedResource(description = "Camel Azure Files endpoint") +@BodyTypes(consumerOut = @BodyType(value = Carrier.FILE, dependsOn = "preMove", + byOption = { + @BodyType.When(option = "streamDownload", value = "true", carriers = Carrier.STREAM), + @BodyType.When(option = "download", value = "false", carriers = Carrier.NULL) }, + description = "The file as read: a RemoteFile with its content loaded as bytes, which converts" + + " to text, bytes or a stream; a stream with streamDownload; with preMove its" + + " content, a byte array"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + byOption = @BodyType.When(option = "allowNullBody", value = "true", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE }), + description = "What converts to an InputStream or a byte array: text, bytes, a stream or a" + + " file. A Map or a List fails: marshal it first"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class FilesEndpoint extends RemoteFileEndpoint implements EndpointServiceLocation { // without hiding configuration field from type GenericFileEndpoint diff --git a/components/camel-azure/camel-azure-storage-blob/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/blob/azure-storage-blob.json b/components/camel-azure/camel-azure-storage-blob/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/blob/azure-storage-blob.json index 677b93044d53d..c69e7afe81ddf 100644 --- a/components/camel-azure/camel-azure-storage-blob/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/blob/azure-storage-blob.json +++ b/components/camel-azure/camel-azure-storage-blob/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/blob/azure-storage-blob.json @@ -157,6 +157,11 @@ "CamelAzureStorageBlobImmutabilityPolicyMode": { "index": 77, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "com.azure.storage.blob.models.BlobImmutabilityPolicyMode", "enum": [ "Mutable", "Unlocked", "Locked" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(setBlobImmutabilityPolicy) The mode of the immutability policy: UNLOCKED (default, can be modified or deleted), LOCKED (cannot be modified or shortened, only extended), or MUTABLE.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#BLOB_IMMUTABILITY_POLICY_MODE" }, "CamelAzureStorageBlobRehydratePriority": { "index": 78, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "com.azure.storage.blob.models.RehydratePriority", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(setBlobTier) The rehydrate priority used when rehydrating a blob from the archive tier: Standard or High. Ignored when changing tier between non-archive tiers.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#REHYDRATE_PRIORITY" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "file" ], "description": "The content of the blob, one message per blob: a stream that reads it, or with fileDir the java.io.File it is downloaded to" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "operation", "value": "uploadBlockBlob", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "operation", "value": "commitAppendBlob", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "operation", "value": "uploadPageBlob", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "operation", "value": "stageBlockBlobList", "carriers": [ "list", "pojo" ] }, { "option": "operation", "value": "commitBlobBlockList", "carriers": [ "list", "pojo" ] } ], "description": "The content to upload for uploadBlockBlob, commitAppendBlob and uploadPageBlob: text, bytes, a stream or a file; a Map or a List fails: marshal it first. A List of BlobBlock for stageBlockBlobList, and of Block for commitBlobBlockList. getBlob writes into an OutputStream body. The other operations do not use the body, or take their value from a header first: the file of uploadBlockBlobChunked, the tags, the tag filter, the legal hold, the tier and the policy" }, + "producerOut": { "carriers": [ "list" ], "byOption": [ { "option": "operation", "value": "getBlob", "carriers": [ "stream" ] }, { "option": "operation", "value": "downloadBlobToFile", "carriers": [ "file" ], "javaType": "java.io.File" }, { "option": "operation", "value": "getBlobTags", "carriers": [ "map" ], "javaType": "java.util.Map" }, { "option": "operation", "value": "getPageBlobRanges", "carriers": [ "iterator" ], "javaType": "com.azure.core.http.rest.PagedIterable" }, { "option": "operation", "value": "getBlobBlockList", "carriers": [ "pojo" ], "javaType": "com.azure.storage.blob.models.BlockList" }, { "option": "operation", "value": "setBlobImmutabilityPolicy", "carriers": [ "pojo" ], "javaType": "com.azure.storage.blob.models.BlobImmutabilityPolicy" }, { "option": "operation", "value": "setBlobTier", "carriers": [ "pojo" ], "javaType": "com.azure.storage.blob.models.AccessTier" }, { "option": "operation", "value": "copyBlob", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "createBlobSnapshot", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "setBlobLegalHold", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "createBlobContainer", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "deleteBlobContainer", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "deleteBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "downloadLink", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "uploadBlockBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "uploadBlockBlobChunked", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "stageBlockBlobList", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "commitBlobBlockList", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "createAppendBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "commitAppendBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "createPageBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "uploadPageBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "resizePageBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "clearPageBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "setBlobTags", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "undeleteBlob", "carriers": [ "value" ], "javaType": "java.lang.Boolean" } ], "description": "A List of the items of the SDK for listBlobContainers, the default, findBlobsByTags, listBlobs, listBlobVersions and getChangeFeed. A stream of the content for getBlob, or the OutputStream body it wrote into; the java.io.File for downloadBlobToFile; true for the operations that create, upload, set or delete, with their results in headers, such as the link of downloadLink" } + }, "properties": { "accountName": { "index": 0, "kind": "path", "displayName": "Account Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Azure account name to be used for authentication with azure blob services" }, "containerName": { "index": 1, "kind": "path", "displayName": "Container Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "The blob container name" }, diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobEndpoint.java b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobEndpoint.java index e06f9e8c8231c..41283e68f2d1e 100644 --- a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobEndpoint.java +++ b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobEndpoint.java @@ -30,6 +30,9 @@ import org.apache.camel.Producer; import org.apache.camel.component.azure.storage.blob.client.BlobClientFactory; import org.apache.camel.component.azure.storage.blob.operations.BlobOperationResponse; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -42,6 +45,109 @@ @UriEndpoint(firstVersion = "3.3.0", scheme = "azure-storage-blob", title = "Azure Storage Blob Service", syntax = "azure-storage-blob:accountName/containerName", category = { Category.CLOUD, Category.FILE }, headersClass = BlobConstants.class) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.STREAM, Carrier.FILE }, + description = "The content of the blob, one message per blob: a stream that reads it, or" + + " with fileDir the java.io.File it is downloaded to"), + producerIn = @BodyType(value = Carrier.ANY, + byOption = { + @BodyType.When(option = "operation", value = "uploadBlockBlob", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), + @BodyType.When(option = "operation", value = "commitAppendBlob", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), + @BodyType.When(option = "operation", value = "uploadPageBlob", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), + @BodyType.When(option = "operation", value = "stageBlockBlobList", + carriers = { Carrier.LIST, Carrier.POJO }), + @BodyType.When(option = "operation", value = "commitBlobBlockList", + carriers = { Carrier.LIST, Carrier.POJO }) }, + description = "The content to upload for uploadBlockBlob, commitAppendBlob and uploadPageBlob:" + + " text, bytes, a stream or a file; a Map or a List fails: marshal it first. A" + + " List of BlobBlock for stageBlockBlobList, and of Block for" + + " commitBlobBlockList. getBlob writes into an OutputStream body. The other" + + " operations do not use the body, or take their value from a header first: the" + + " file of uploadBlockBlobChunked, the tags, the tag filter, the legal hold, the" + + " tier and the policy"), + producerOut = @BodyType(value = Carrier.LIST, + byOption = { + @BodyType.When(option = "operation", value = "getBlob", carriers = Carrier.STREAM), + @BodyType.When(option = "operation", value = "downloadBlobToFile", + carriers = Carrier.FILE, + javaType = "java.io.File"), + @BodyType.When(option = "operation", value = "getBlobTags", carriers = Carrier.MAP, + javaType = "java.util.Map"), + @BodyType.When(option = "operation", value = "getPageBlobRanges", + carriers = Carrier.ITERATOR, + javaType = "com.azure.core.http.rest.PagedIterable"), + @BodyType.When(option = "operation", value = "getBlobBlockList", + carriers = Carrier.POJO, + javaType = "com.azure.storage.blob.models.BlockList"), + @BodyType.When(option = "operation", value = "setBlobImmutabilityPolicy", + carriers = Carrier.POJO, + javaType = "com.azure.storage.blob.models.BlobImmutabilityPolicy"), + @BodyType.When(option = "operation", value = "setBlobTier", carriers = Carrier.POJO, + javaType = "com.azure.storage.blob.models.AccessTier"), + @BodyType.When(option = "operation", value = "copyBlob", carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "operation", value = "createBlobSnapshot", + carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "operation", value = "setBlobLegalHold", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "createBlobContainer", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "deleteBlobContainer", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "deleteBlob", carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "downloadLink", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "uploadBlockBlob", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "uploadBlockBlobChunked", + carriers = Carrier.VALUE, javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "stageBlockBlobList", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "commitBlobBlockList", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "createAppendBlob", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "commitAppendBlob", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "createPageBlob", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "uploadPageBlob", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "resizePageBlob", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "clearPageBlob", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "setBlobTags", carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "undeleteBlob", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean") }, + description = "A List of the items of the SDK for listBlobContainers, the default," + + " findBlobsByTags, listBlobs, listBlobVersions and getChangeFeed. A stream of" + + " the content for getBlob, or the OutputStream body it wrote into; the" + + " java.io.File for downloadBlobToFile; true for the operations that create," + + " upload, set or delete, with their results in headers, such as the link of" + + " downloadLink")) public class BlobEndpoint extends ScheduledPollEndpoint implements EndpointServiceLocation { @UriParam diff --git a/components/camel-dropbox/src/generated/resources/META-INF/org/apache/camel/component/dropbox/dropbox.json b/components/camel-dropbox/src/generated/resources/META-INF/org/apache/camel/component/dropbox/dropbox.json index 7233ac5194228..f5be463c68e96 100644 --- a/components/camel-dropbox/src/generated/resources/META-INF/org/apache/camel/component/dropbox/dropbox.json +++ b/components/camel-dropbox/src/generated/resources/META-INF/org/apache/camel/component/dropbox/dropbox.json @@ -43,6 +43,11 @@ "DELETED_PATH": { "index": 11, "kind": "header", "displayName": "", "group": "del", "label": "del", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the path deleted on dropbox", "constantName": "org.apache.camel.component.dropbox.util.DropboxConstants#DELETED_PATH" }, "MOVED_PATH": { "index": 12, "kind": "header", "displayName": "", "group": "move", "label": "move", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the path moved on dropbox", "constantName": "org.apache.camel.component.dropbox.util.DropboxConstants#MOVED_PATH" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "operation", "value": "get", "carriers": [ "stream", "bytes", "map" ] }, { "option": "operation", "value": "search", "carriers": [ "list" ], "javaType": "java.util.List" } ], "description": "One message per poll. get: the content of the file in remotePath as a stream cache (a byte array when stream caching is off), or for a folder a Map of the path to the content of each file. search: a List of SearchMatchV2" }, + "producerIn": { "carriers": [ "any" ], "description": "Only put reads the body, unless localPath or the CamelDropboxLocalPath header names a local file or folder to upload: the content to upload, as text, bytes, a stream or a file. A Map or a List is not uploaded, and the result is KO without an error: marshal it first" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "operation", "value": "put", "carriers": [ "value", "map" ] }, { "option": "operation", "value": "get", "carriers": [ "stream", "bytes", "map" ] }, { "option": "operation", "value": "del", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "move", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "search", "carriers": [ "list" ], "javaType": "java.util.List" } ], "description": "put: OK or KO, a DropboxResultCode, or for a local folder of several files a Map of each remote path to its result. get: the content of the file as a stream cache (a byte array when stream caching is off), or a Map of the path to the content of each file of a folder. del: the path deleted. move: the new path. search: a List of SearchMatchV2" } + }, "properties": { "operation": { "index": 0, "kind": "path", "displayName": "Operation", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.dropbox.util.DropboxOperation", "enum": [ "put", "del", "search", "get", "move" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.dropbox.DropboxConfiguration", "configurationField": "configuration", "description": "The specific action (typically is a CRUD action) to perform on Dropbox remote folder." }, "clientIdentifier": { "index": 1, "kind": "parameter", "displayName": "Client Identifier", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.dropbox.DropboxConfiguration", "configurationField": "configuration", "description": "Name of the app registered to make API requests" }, diff --git a/components/camel-dropbox/src/main/java/org/apache/camel/component/dropbox/DropboxEndpoint.java b/components/camel-dropbox/src/main/java/org/apache/camel/component/dropbox/DropboxEndpoint.java index 4755b343859f8..489ee82cd6989 100644 --- a/components/camel-dropbox/src/main/java/org/apache/camel/component/dropbox/DropboxEndpoint.java +++ b/components/camel-dropbox/src/main/java/org/apache/camel/component/dropbox/DropboxEndpoint.java @@ -31,6 +31,9 @@ import org.apache.camel.component.dropbox.util.DropboxConstants; import org.apache.camel.component.dropbox.util.DropboxException; import org.apache.camel.component.dropbox.util.DropboxOperation; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -43,6 +46,37 @@ */ @UriEndpoint(firstVersion = "2.14.0", scheme = "dropbox", title = "Dropbox", syntax = "dropbox:operation", category = { Category.CLOUD, Category.FILE, Category.API }, headersClass = DropboxConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "operation", value = "get", + carriers = { Carrier.STREAM, Carrier.BYTES, Carrier.MAP }), + @BodyType.When(option = "operation", value = "search", carriers = Carrier.LIST, + javaType = "java.util.List") }, + description = "One message per poll. get: the content of the file in remotePath as a stream" + + " cache (a byte array when stream caching is off), or for a folder a Map of" + + " the path to the content of each file. search: a List of SearchMatchV2"), + producerIn = @BodyType(value = Carrier.ANY, + description = "Only put reads the body, unless localPath or the CamelDropboxLocalPath header" + + " names a local file or folder to upload: the content to upload, as text," + + " bytes, a stream or a file. A Map or a List is not uploaded, and the result" + + " is KO without an error: marshal it first"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "operation", value = "put", + carriers = { Carrier.VALUE, Carrier.MAP }), + @BodyType.When(option = "operation", value = "get", + carriers = { Carrier.STREAM, Carrier.BYTES, Carrier.MAP }), + @BodyType.When(option = "operation", value = "del", carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "operation", value = "move", carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "operation", value = "search", carriers = Carrier.LIST, + javaType = "java.util.List") }, + description = "put: OK or KO, a DropboxResultCode, or for a local folder of several files a" + + " Map of each remote path to its result. get: the content of the file as a" + + " stream cache (a byte array when stream caching is off), or a Map of the path" + + " to the content of each file of a folder. del: the path deleted. move: the new" + + " path. search: a List of SearchMatchV2")) public class DropboxEndpoint extends DefaultEndpoint implements EndpointServiceLocation { private static final Logger LOG = LoggerFactory.getLogger(DropboxEndpoint.class); diff --git a/components/camel-google/camel-google-storage/src/generated/resources/META-INF/org/apache/camel/component/google/storage/google-storage.json b/components/camel-google/camel-google-storage/src/generated/resources/META-INF/org/apache/camel/component/google/storage/google-storage.json index c074a07ef91bf..669344fe5b628 100644 --- a/components/camel-google/camel-google-storage/src/generated/resources/META-INF/org/apache/camel/component/google/storage/google-storage.json +++ b/components/camel-google/camel-google-storage/src/generated/resources/META-INF/org/apache/camel/component/google/storage/google-storage.json @@ -79,6 +79,11 @@ "CamelGoogleCloudStorageLastUpdate": { "index": 26, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The last update of the object", "constantName": "org.apache.camel.component.google.storage.GoogleCloudStorageConstants#METADATA_LAST_UPDATE" }, "CamelGoogleCloudStorageOverrideBucketName": { "index": 27, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The bucket Name to override which this object will be stored or which will be used for the current operation or in which this object is contained.", "constantName": "org.apache.camel.component.google.storage.GoogleCloudStorageConstants#OVERRIDE_BUCKET_NAME" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "bytes", "file" ], "byOption": [ { "option": "includeBody", "value": "false", "carriers": [ "pojo" ], "javaType": "com.google.cloud.storage.Blob" } ], "description": "The content of the object, one message per object, with its metadata in headers: a stream cache, or a byte array when stream caching is off. With downloadFileName the java.io.File it is downloaded to, and with includeBody=false the Blob, which has the metadata and not the content" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "operation" ], "description": "The content to upload, when no operation is set: text, bytes, a stream or a file. A Map, a List or no body fails: marshal it first. The operations take their input from options and headers" }, + "producerOut": { "carriers": [ "pojo" ], "javaType": "com.google.cloud.storage.Blob", "byOption": [ { "option": "operation", "value": "getObject", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "operation", "value": "listObjects", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "listBuckets", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "copyObject", "carriers": [ "pojo" ], "javaType": "com.google.cloud.storage.CopyWriter" }, { "option": "operation", "value": "deleteObject", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "deleteBucket", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "createDownloadLink", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "The Blob of the uploaded object. By the operation: the content as a byte array for getObject, with its metadata in headers, a List of Blob or Bucket for the lists, the CopyWriter for copyObject, whose getResult() gives the Blob of the copy, true or false for the deletes and the signed URL as text for createDownloadLink" } + }, "properties": { "bucketName": { "index": 0, "kind": "path", "displayName": "Bucket Name", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.google.storage.GoogleCloudStorageConfiguration", "configurationField": "configuration", "description": "Bucket name or ARN" }, "autoCreateBucket": { "index": 1, "kind": "parameter", "displayName": "Auto Create Bucket", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.google.storage.GoogleCloudStorageConfiguration", "configurationField": "configuration", "description": "Setting the autocreation of the bucket bucketName." }, diff --git a/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc b/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc index e088354e966aa..4678ee29f9a0d 100644 --- a/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc +++ b/components/camel-google/camel-google-storage/src/main/docs/google-storage-component.adoc @@ -544,7 +544,7 @@ YAML:: ---- ==== -This operation will return a Blob object instance related to the `OBJECT_NAME` object in `myCamelBucket` bucket. +This operation will return the content of the `OBJECT_NAME` object in `myCamelBucket` bucket as a byte array, with its metadata in headers. - `CreateDownloadLink`: this operation will return a download link diff --git a/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageEndpoint.java b/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageEndpoint.java index a0ee328b685d6..0e9a495e2dc90 100644 --- a/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageEndpoint.java +++ b/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageEndpoint.java @@ -27,6 +27,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -43,6 +46,42 @@ */ @UriEndpoint(firstVersion = "3.9.0", scheme = "google-storage", title = "Google Storage", syntax = "google-storage:bucketName", category = { Category.CLOUD }, headersClass = GoogleCloudStorageConstants.class) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.STREAM, Carrier.BYTES, Carrier.FILE }, + byOption = @BodyType.When(option = "includeBody", value = "false", carriers = Carrier.POJO, + javaType = "com.google.cloud.storage.Blob"), + description = "The content of the object, one message per object, with its metadata in" + + " headers: a stream cache, or a byte array when stream caching is off. With" + + " downloadFileName the java.io.File it is downloaded to, and with" + + " includeBody=false the Blob, which has the metadata and not the content"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + dependsOn = "operation", + description = "The content to upload, when no operation is set: text, bytes, a stream or a" + + " file. A Map, a List or no body fails: marshal it first. The operations take" + + " their input from options and headers"), + producerOut = @BodyType(value = Carrier.POJO, javaType = "com.google.cloud.storage.Blob", + byOption = { + @BodyType.When(option = "operation", value = "getObject", carriers = Carrier.BYTES, + javaType = "byte[]"), + @BodyType.When(option = "operation", value = "listObjects", carriers = Carrier.LIST, + javaType = "java.util.List"), + @BodyType.When(option = "operation", value = "listBuckets", carriers = Carrier.LIST, + javaType = "java.util.List"), + @BodyType.When(option = "operation", value = "copyObject", carriers = Carrier.POJO, + javaType = "com.google.cloud.storage.CopyWriter"), + @BodyType.When(option = "operation", value = "deleteObject", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "deleteBucket", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "createDownloadLink", + carriers = Carrier.TEXT, + javaType = "java.lang.String") }, + description = "The Blob of the uploaded object. By the operation: the content as a byte array" + + " for getObject, with its metadata in headers, a List of Blob or Bucket for the" + + " lists, the CopyWriter for copyObject, whose getResult() gives the Blob of the" + + " copy, true or false for the deletes and the signed URL as text for" + + " createDownloadLink")) public class GoogleCloudStorageEndpoint extends ScheduledPollEndpoint implements EndpointServiceLocation { private static final Logger LOG = LoggerFactory.getLogger(GoogleCloudStorageEndpoint.class); diff --git a/components/camel-ibm/camel-ibm-cos/src/generated/resources/META-INF/org/apache/camel/component/ibm/cos/ibm-cos.json b/components/camel-ibm/camel-ibm-cos/src/generated/resources/META-INF/org/apache/camel/component/ibm/cos/ibm-cos.json index 3158ed8eac8c5..02e6f53e84969 100644 --- a/components/camel-ibm/camel-ibm-cos/src/generated/resources/META-INF/org/apache/camel/component/ibm/cos/ibm-cos.json +++ b/components/camel-ibm/camel-ibm-cos/src/generated/resources/META-INF/org/apache/camel/component/ibm/cos/ibm-cos.json @@ -77,6 +77,11 @@ "CamelIBMCOSRangeEnd": { "index": 19, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The range end position for partial object retrieval", "constantName": "org.apache.camel.component.ibm.cos.IBMCOSConstants#RANGE_END" }, "CamelIBMCOSBucketExists": { "index": 20, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Whether the bucket exists or not", "constantName": "org.apache.camel.component.ibm.cos.IBMCOSConstants#BUCKET_EXISTS" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream" ], "byOption": [ { "option": "includeBody", "value": "false", "carriers": [ "null" ] } ], "description": "The content of the object as a stream, one message per object, with its key and metadata in headers. No body with includeBody=false" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "operation" ], "byOption": [ { "option": "operation", "value": "putObject", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "The content to upload with putObject, the default: text, bytes, a stream or a file. A Map, a List or no body fails: marshal it first. The other operations take their input from headers" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "getObject", "carriers": [ "stream" ] }, { "option": "operation", "value": "getObjectRange", "carriers": [ "stream" ] }, { "option": "operation", "value": "listObjects", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "listBuckets", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "deleteObjects", "carriers": [ "list" ] }, { "option": "operation", "value": "headBucket", "carriers": [ "value" ], "javaType": "java.lang.Boolean" } ], "description": "Unchanged after putObject (with the ETag in a header), copyObject, deleteObject, createBucket and deleteBucket. getObject and getObjectRange give the content as a stream, listObjects a List of the first page of objects, listBuckets a List of Bucket, deleteObjects a List of the deleted objects and headBucket whether the bucket exists" } + }, "properties": { "bucketName": { "index": 0, "kind": "path", "displayName": "Bucket Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Bucket name" }, "autoCreateBucket": { "index": 1, "kind": "parameter", "displayName": "Auto Create Bucket", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.ibm.cos.IBMCOSConfiguration", "configurationField": "configuration", "description": "Automatically create the bucket if it doesn't exist" }, diff --git a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java index dcbafcfd3dc97..4b0a82ec9a95f 100644 --- a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java +++ b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java @@ -30,6 +30,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.IdempotentRepository; import org.apache.camel.spi.Metadata; @@ -49,6 +52,37 @@ @UriEndpoint(firstVersion = "4.16.0", scheme = "ibm-cos", title = "IBM Cloud Object Storage", syntax = "ibm-cos:bucketName", category = { Category.CLOUD, Category.FILE }, headersClass = IBMCOSConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.STREAM, + byOption = @BodyType.When(option = "includeBody", value = "false", carriers = Carrier.NULL), + description = "The content of the object as a stream, one message per object, with its key" + + " and metadata in headers. No body with includeBody=false"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + dependsOn = "operation", + byOption = @BodyType.When(option = "operation", value = "putObject", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }), + description = "The content to upload with putObject, the default: text, bytes, a stream or a" + + " file. A Map, a List or no body fails: marshal it first. The other" + + " operations take their input from headers"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + byOption = { + @BodyType.When(option = "operation", value = "getObject", carriers = Carrier.STREAM), + @BodyType.When(option = "operation", value = "getObjectRange", + carriers = Carrier.STREAM), + @BodyType.When(option = "operation", value = "listObjects", carriers = Carrier.LIST, + javaType = "java.util.List"), + @BodyType.When(option = "operation", value = "listBuckets", carriers = Carrier.LIST, + javaType = "java.util.List"), + @BodyType.When(option = "operation", value = "deleteObjects", + carriers = Carrier.LIST), + @BodyType.When(option = "operation", value = "headBucket", carriers = Carrier.VALUE, + javaType = "java.lang.Boolean") }, + description = "Unchanged after putObject (with the ETag in a header), copyObject," + + " deleteObject, createBucket and deleteBucket. getObject and getObjectRange" + + " give the content as a stream, listObjects a List of the first page of" + + " objects, listBuckets a List of Bucket, deleteObjects a List of the deleted" + + " objects and headBucket whether the bucket exists")) public class IBMCOSEndpoint extends ScheduledPollEndpoint implements EndpointServiceLocation { private static final Logger LOG = LoggerFactory.getLogger(IBMCOSEndpoint.class); diff --git a/components/camel-minio/src/generated/resources/META-INF/org/apache/camel/component/minio/minio.json b/components/camel-minio/src/generated/resources/META-INF/org/apache/camel/component/minio/minio.json index 317451362eb3c..6ef423af16830 100644 --- a/components/camel-minio/src/generated/resources/META-INF/org/apache/camel/component/minio/minio.json +++ b/components/camel-minio/src/generated/resources/META-INF/org/apache/camel/component/minio/minio.json @@ -99,6 +99,11 @@ "CamelMinioPresignedURLExpirationTime": { "index": 21, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Expiration of minio presigned url in Seconds", "constantName": "org.apache.camel.component.minio.MinioConstants#PRESIGNED_URL_EXPIRATION_TIME" }, "CamelMinioOverrideBucketName": { "index": 22, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The bucket Name to override which this object will be stored or which will be used for the current operation or in which this object is contained.", "constantName": "org.apache.camel.component.minio.MinioConstants#OVERRIDE_BUCKET_NAME" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "byOption": [ { "option": "includeBody", "value": "false", "carriers": [ "null" ] } ], "description": "The content of the object as a byte array, one message per object, with its metadata in headers. No body with includeBody=false" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "operation", "pojoRequest" ], "description": "The content to upload, when no operation is set: text, bytes, a stream or a file. A Map, a List or no body fails: marshal it first. The operations take their input from headers, or with pojoRequest=true from the builder of the request of the Minio SDK in the body, such as a GetObjectArgs.Builder; deleteObjects works only so" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "getObject", "carriers": [ "stream" ] }, { "option": "operation", "value": "getObjectRange", "carriers": [ "stream" ] }, { "option": "operation", "value": "listObjects", "carriers": [ "iterator" ], "javaType": "java.lang.Iterable>" }, { "option": "operation", "value": "listBuckets", "carriers": [ "iterator" ], "javaType": "java.util.Iterator" }, { "option": "operation", "value": "deleteObject", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "deleteObjects", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "deleteBucket", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "createDownloadLink", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "operation", "value": "createUploadLink", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "Unchanged after an upload and a copyObject, with the ETag in a header. By the operation: the stream of the object for getObject and getObjectRange, a lazy Iterable of Result for listObjects, whose get() gives the Item, an Iterator of Bucket for listBuckets, true for the deletes, ok for deleteBucket and the URL as text for the links" } + }, "properties": { "bucketName": { "index": 0, "kind": "path", "displayName": "Bucket Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.minio.MinioConfiguration", "configurationField": "configuration", "description": "Bucket name" }, "autoCreateBucket": { "index": 1, "kind": "parameter", "displayName": "Auto Create Bucket", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.minio.MinioConfiguration", "configurationField": "configuration", "description": "Setting the autocreation of the bucket if bucket name not exist." }, diff --git a/components/camel-minio/src/main/docs/minio-component.adoc b/components/camel-minio/src/main/docs/minio-component.adoc index a0e2de922b1ac..49889d3f5b579 100644 --- a/components/camel-minio/src/main/docs/minio-component.adoc +++ b/components/camel-minio/src/main/docs/minio-component.adoc @@ -103,8 +103,8 @@ Camel-Minio component provides the following operation on the producer side: - `listBuckets` - `deleteBucket` - `listObjects` -- `getObject` (this will return a `MinioObject instance) -- `getObjectRange` (this will return a `MinioObject instance) +- `getObject` (this will return the content of the object as a stream) +- `getObjectRange` (this will return the range of the content as a stream) - `createDownloadLink` (this will return a Presigned download Url) - `createUploadLink` (this will return a Presigned upload url) @@ -450,7 +450,7 @@ YAML:: ---- ==== -This operation will return a MinioObject instance related to the camelKey object in `mycamelbucket` bucket. +This operation will return the content of the camelKey object in `mycamelbucket` bucket as a stream. - `GetObjectRange`: this operation gets a single object range in a specific bucket @@ -514,7 +514,7 @@ YAML:: uri: mock:result ---- ==== -This operation will return a MinioObject instance related to the camelKey object in `mycamelbucket` bucket, containing bytes from 0 to 9. +This operation will return the bytes from 0 to 9 of the camelKey object in `mycamelbucket` bucket as a stream. - `createDownloadLink`: this operation will return a presigned url through which a file can be downloaded using GET method diff --git a/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioEndpoint.java b/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioEndpoint.java index 5a9fc6a3f0f71..7461d32599e87 100644 --- a/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioEndpoint.java +++ b/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioEndpoint.java @@ -28,6 +28,9 @@ import org.apache.camel.Message; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -42,6 +45,47 @@ */ @UriEndpoint(firstVersion = "3.5.0", scheme = "minio", title = "Minio", syntax = "minio:bucketName", category = { Category.CLOUD, Category.FILE }, headersClass = MinioConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]", + byOption = @BodyType.When(option = "includeBody", value = "false", carriers = Carrier.NULL), + description = "The content of the object as a byte array, one message per object, with its" + + " metadata in headers. No body with includeBody=false"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + dependsOn = { "operation", "pojoRequest" }, + description = "The content to upload, when no operation is set: text, bytes, a stream or a" + + " file. A Map, a List or no body fails: marshal it first. The operations take" + + " their input from headers, or with pojoRequest=true from the builder of the" + + " request of the Minio SDK in the body, such as a GetObjectArgs.Builder;" + + " deleteObjects works only so"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + byOption = { + @BodyType.When(option = "operation", value = "getObject", carriers = Carrier.STREAM), + @BodyType.When(option = "operation", value = "getObjectRange", + carriers = Carrier.STREAM), + @BodyType.When(option = "operation", value = "listObjects", + carriers = Carrier.ITERATOR, + javaType = "java.lang.Iterable>"), + @BodyType.When(option = "operation", value = "listBuckets", + carriers = Carrier.ITERATOR, + javaType = "java.util.Iterator"), + @BodyType.When(option = "operation", value = "deleteObject", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "deleteObjects", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "deleteBucket", carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "operation", value = "createDownloadLink", + carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "operation", value = "createUploadLink", + carriers = Carrier.TEXT, + javaType = "java.lang.String") }, + description = "Unchanged after an upload and a copyObject, with the ETag in a header. By the" + + " operation: the stream of the object for getObject and getObjectRange, a" + + " lazy Iterable of Result for listObjects, whose get() gives the Item, an" + + " Iterator of Bucket for listBuckets, true for the deletes, ok for" + + " deleteBucket and the URL as text for the links")) @Deprecated(since = "4.23") public class MinioEndpoint extends ScheduledPollEndpoint implements EndpointServiceLocation { diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java index 897532a0a271d..e3640b1b22536 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java @@ -100,9 +100,12 @@ boolean unchanged() { return carriers.equals(List.of("unchanged")); } - /** The file as read. */ + /** + * The file as read, such as the GenericFile of the file consumer: the file is the only carrier. A blob that is + * a stream or a downloaded file is a payload like any other. + */ boolean file() { - return carriers.contains("file"); + return carriers.equals(List.of("file")); } /** The data format of the format, as an unmarshal or a marshal names it: json, jacksonXml, csv or yaml. */ diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/TextBodyFlow.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/TextBodyFlow.java index feb84871f8b09..b29bc22a71004 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/TextBodyFlow.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/TextBodyFlow.java @@ -280,7 +280,7 @@ private static Body consumerBody(String uri, JsonNode from, CatalogBodyTypes bod if (out.payload()) { // the file as read has the format of the files it reads return out.file() - ? new Text(consumer + (out.carriers().size() > 1 ? " as " + out.inWords() : ""), fileFormat(from), true) + ? new Text(consumer, fileFormat(from), true) : new Text(consumer + " as " + out.inWords(), out.dataFormat()); } return out.data() ? new Parsed(consumer + " as " + out.inWords(), out.dataFormat()) : null; diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java index 0c2af877367d5..2422508a73f51 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java @@ -1081,6 +1081,59 @@ public void testTheOptionsInThePathOfTheEndpoint() { .contains("to: openai:chat-completion returns it as text: unmarshal it first")); } + @Test + public void testTheBodyOfObjectStorage() { + // getObject gives the stream of the object and the blob consumer the stream or the file of the blob, so a field + // read needs an unmarshal; an upload names no operation, which the component may set, and dropbox search gives a + // List + String yaml = """ + - route: + id: get + from: + uri: timer:tick + steps: + - to: aws2-s3:reports?operation=getObject + - setHeader: + name: name + simple: ${body[name]} + - route: + id: upload + from: + uri: timer:tick + steps: + - setBody: + constant: '{"name": "Camel"}' + - to: aws2-s3:reports + - setHeader: + name: name + simple: ${body[name]} + - route: + id: blob + from: + uri: azure-storage-blob:account/reports + steps: + - setHeader: + name: name + simple: ${body[name]} + - route: + id: search + from: + uri: timer:tick + steps: + - to: dropbox:search?query=camel + - setHeader: + name: first + simple: ${body[0]} + """; + assertThat(lines(yaml)).hasSize(2).anySatisfy(m -> assertThat(m) + .contains("route get: simple reads a field of the body (${body[name]})") + .contains("to: aws2-s3:reports returns it as a stream: unmarshal it first")) + .anySatisfy(m -> assertThat(m) + .contains("route blob: simple reads a field of the body (${body[name]})") + .contains("the body here is still text, not parsed data") + .contains("the azure-storage-blob consumer gives it as a stream or a file: unmarshal it first")); + } + @Test public void testOneReportForAStepThatFails() { // the first write fails at runtime, so the second does not run with this body From 07e849749739ee4b523771b653d4f05c5c61a45f Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 22 Oct 2026 07:50:35 +0200 Subject: [PATCH 14/25] CAMEL-24961: camel-yaml-dsl-maven-plugin - ignore the bodyTypes of the data format and language schemas Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../java/org/apache/camel/maven/dsl/yaml/support/Schema.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/Schema.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/Schema.java index ece10f183c110..cc7b9bf26e2a5 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/Schema.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-maven-plugin/src/main/java/org/apache/camel/maven/dsl/yaml/support/Schema.java @@ -30,6 +30,8 @@ public class Schema { public ObjectNode properties; @JsonIgnore public ObjectNode exchangeProperties; + @JsonIgnore + public ObjectNode bodyTypes; @JsonProperty public ObjectNode functions; @JsonProperty From 4017dd4f313b1cd4b1774af3bd1e673b3e38a09f Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 22 Oct 2026 09:48:28 +0200 Subject: [PATCH 15/25] CAMEL-24961: camel-jbang - the options that make a body type not known read as a list, as the carriers do Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../dsl/jbang/core/commands/ai/CatalogDocs.java | 12 ++++++++---- .../dsl/jbang/core/commands/ai/CatalogDocsTest.java | 5 +++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java index cf59e42214687..7aa5bfedab5d3 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocs.java @@ -1663,7 +1663,7 @@ static JsonObject bodyTypes(Map bodyTypes) { line.append(". With ").append(String.join("; ", values)); } if (!side.getDependsOn().isEmpty()) { - line.append(". Not known when ").append(String.join(" or ", side.getDependsOn())).append(" is set"); + line.append(". Not known when ").append(orList(side.getDependsOn())).append(" is set"); } answer.put(entry.getKey(), line.toString()); } @@ -1675,12 +1675,16 @@ private static String carriers(List carriers, String javaType) { // the build rejects a side without carriers, but a catalog read from elsewhere may have one return "unknown"; } - String answer = carriers.size() == 1 - ? carriers.get(0) - : String.join(", ", carriers.subList(0, carriers.size() - 1)) + " or " + carriers.get(carriers.size() - 1); + String answer = orList(carriers); return javaType != null ? answer + " (" + javaType + ")" : answer; } + private static String orList(List values) { + return values.size() == 1 + ? values.get(0) + : String.join(", ", values.subList(0, values.size() - 1)) + " or " + values.get(values.size() - 1); + } + /** * The rules of an endpoint URI for this component, spelled out with its own path parts: what a small model gets * wrong most is a path option written as a query parameter or the other way round, and the YAML form. diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java index b7a7c781a109c..51a1730eb6771 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java +++ b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ai/CatalogDocsTest.java @@ -147,6 +147,11 @@ void theBodyTypesSayWhatTheBodyIsAfterAStep() throws Exception { + " With output=bytes: bytes (byte[]); output=DOM: pojo")); assertTrue(xslt.getString("bodyTypesHint").contains("a side not listed is not known")); + // the options that make a side not known read as a list + JsonObject jms = catalogDoc(Map.of("name", "jms", "kind", "component", "includeOptions", false)); + assertTrue(((JsonObject) jms.get("bodyTypes")).getString("producerIn") + .endsWith(". Not known when jmsMessageType, messageConverter or transferExchange is set")); + JsonObject json = catalogDoc(Map.of("name", "json", "kind", "dataformat", "includeOptions", false)); assertTrue(((JsonObject) json.get("bodyTypes")).getString("unmarshalOut").startsWith("map or list. ")); From 718900ca6deac62a5d04b277ce44f9e96284e487 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 22 Oct 2026 10:00:45 +0200 Subject: [PATCH 16/25] CAMEL-24961: Catalog body types for cloud messaging The body types of aws2-sns, aws2-kinesis, aws2-kinesis-firehose, google-pubsub, azure-servicebus, azure-eventhubs and azure-storage-queue, read from the code and checked at runtime against LocalStack (SNS and Kinesis), the Pub/Sub emulator and Azurite (queues). aws2-sqs sends bytes, a stream or a file as text as well, and sendBatchMessage takes a SendMessageBatchRequest too, which its producer side now says. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../components/aws2-kinesis-firehose.json | 4 ++ .../catalog/components/aws2-kinesis.json | 5 ++ .../camel/catalog/components/aws2-sns.json | 4 ++ .../camel/catalog/components/aws2-sqs.json | 2 +- .../catalog/components/azure-eventhubs.json | 5 ++ .../catalog/components/azure-servicebus.json | 5 ++ .../components/azure-storage-queue.json | 5 ++ .../catalog/components/google-pubsub.json | 5 ++ .../aws2/firehose/aws2-kinesis-firehose.json | 4 ++ .../component/aws2/kinesis/aws2-kinesis.json | 5 ++ .../firehose/KinesisFirehose2Endpoint.java | 42 +++++++++++++++ .../aws2/kinesis/Kinesis2Endpoint.java | 18 +++++++ .../camel/component/aws2/sns/aws2-sns.json | 4 ++ .../component/aws2/sns/Sns2Endpoint.java | 12 +++++ .../camel/component/aws2/sqs/aws2-sqs.json | 2 +- .../component/aws2/sqs/Sqs2Endpoint.java | 11 ++-- .../azure/eventhubs/azure-eventhubs.json | 5 ++ .../azure/eventhubs/EventHubsEndpoint.java | 11 ++++ .../azure/servicebus/azure-servicebus.json | 5 ++ .../azure/servicebus/ServiceBusEndpoint.java | 14 +++++ .../storage/queue/azure-storage-queue.json | 5 ++ .../azure/storage/queue/QueueEndpoint.java | 39 ++++++++++++++ .../google/pubsub/google-pubsub.json | 5 ++ .../google/pubsub/GooglePubsubEndpoint.java | 12 +++++ .../dsl/yaml/validator/TextBodyFlowTest.java | 52 +++++++++++++++++++ 25 files changed, 274 insertions(+), 7 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-kinesis-firehose.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-kinesis-firehose.json index eb7e0ba1ffc53..448eba5c7a094 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-kinesis-firehose.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-kinesis-firehose.json @@ -54,6 +54,10 @@ "CamelAwsKinesisFirehoseEncrypted": { "index": 5, "kind": "header", "displayName": "", "group": "sendBatchRecord", "label": "sendBatchRecord", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Whether the batch operation was encrypted.", "constantName": "org.apache.camel.component.aws2.firehose.KinesisFirehose2Constants#ENCRYPTED" }, "CamelAwsKinesisFirehoseDeliveryStreamStatus": { "index": 6, "kind": "header", "displayName": "", "group": "describeDeliveryStream", "label": "describeDeliveryStream", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The status of the delivery stream.", "constantName": "org.apache.camel.component.aws2.firehose.KinesisFirehose2Constants#DELIVERY_STREAM_STATUS" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "operation", "value": "sendBatchRecord", "carriers": [ "list", "pojo" ] }, { "option": "operation", "value": "createDeliveryStream", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.CreateDeliveryStreamRequest" }, { "option": "operation", "value": "updateDestination", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.UpdateDestinationRequest" }, { "option": "operation", "value": "deleteDeliveryStream", "carriers": [ "any" ] }, { "option": "operation", "value": "describeDeliveryStream", "carriers": [ "any" ] } ], "description": "The data of the record, when no operation is set: text, bytes, a stream or a file. A Map, a List or a POJO fails, and a number is sent as its binary value: marshal it or convert it to text first. sendBatchRecord takes a List of the Record of the Firehose SDK or a PutRecordBatchRequest, and the other operations their request of the AWS SDK, or for deleteDeliveryStream and describeDeliveryStream the CamelAwsKinesisFirehoseDeliveryStreamName header" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "sendBatchRecord", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.PutRecordBatchResponse" }, { "option": "operation", "value": "createDeliveryStream", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.CreateDeliveryStreamResponse" }, { "option": "operation", "value": "deleteDeliveryStream", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.DeleteDeliveryStreamResponse" }, { "option": "operation", "value": "describeDeliveryStream", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.DescribeDeliveryStreamResponse" }, { "option": "operation", "value": "updateDestination", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.UpdateDestinationResponse" } ], "description": "Unchanged after a send, with the id of the record in a header; the response of the AWS SDK for the operations" } + }, "properties": { "streamName": { "index": 0, "kind": "path", "displayName": "Stream Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.firehose.KinesisFirehose2Configuration", "configurationField": "configuration", "description": "Name of the stream" }, "cborEnabled": { "index": 1, "kind": "parameter", "displayName": "Cbor Enabled", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.aws2.firehose.KinesisFirehose2Configuration", "configurationField": "configuration", "description": "This option will set the CBOR_ENABLED property during the execution" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-kinesis.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-kinesis.json index 40e1eb9595bbd..7bc42d67463fa 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-kinesis.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-kinesis.json @@ -72,6 +72,11 @@ "CamelAwsKinesisFailedRecordCount": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of records that failed in a batch put operation.", "constantName": "org.apache.camel.component.aws2.kinesis.Kinesis2Constants#FAILED_RECORD_COUNT" }, "CamelAwsKinesisRecordCount": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The total number of records in a batch put operation.", "constantName": "org.apache.camel.component.aws2.kinesis.Kinesis2Constants#RECORD_COUNT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "byOption": [ { "option": "useKclConsumers", "value": "true", "carriers": [ "pojo" ], "javaType": "java.nio.ByteBuffer" } ], "description": "The data of the record as a byte array, one message per record, with its partition key, sequence number and shard id in headers. With useKclConsumers=true a java.nio.ByteBuffer: convert it to a String or bytes for the steps that read text" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "list" ], "description": "The data of the record: text, bytes, a stream or a file. A List or another Iterable is sent as a batch, one record per element, and each element must be text, bytes, a ByteBuffer or a stream. A Map or a POJO fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the sequence number and the shard id of the record in headers, or the number of records of a batch" } + }, "properties": { "streamName": { "index": 0, "kind": "path", "displayName": "Stream Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.kinesis.Kinesis2Configuration", "configurationField": "configuration", "description": "Name of the stream" }, "cborEnabled": { "index": 1, "kind": "parameter", "displayName": "Cbor Enabled", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.aws2.kinesis.Kinesis2Configuration", "configurationField": "configuration", "description": "This option will set the CBOR_ENABLED property during the execution" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sns.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sns.json index 7329d7204a10f..a95e468d16342 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sns.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sns.json @@ -64,6 +64,10 @@ "CamelAwsSnsFailedMessageCount": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of failed messages in a batch publish operation.", "constantName": "org.apache.camel.component.aws2.sns.Sns2Constants#FAILED_MESSAGE_COUNT" }, "CamelAwsSnsSuccessfulMessageCount": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of successful messages in a batch publish operation.", "constantName": "org.apache.camel.component.aws2.sns.Sns2Constants#SUCCESSFUL_MESSAGE_COUNT" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "batchEnabled", "value": "true", "carriers": [ "list" ] } ], "description": "The message to publish, as text: bytes, a stream or a file are read as text, and a Map or a POJO is sent as its toString(): marshal it first. With messageStructure=json, a JSON object with a message per protocol; with batchEnabled=true, a List of the PublishBatchRequestEntry of the AWS SDK" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "batchEnabled", "value": "true", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sns.model.PublishBatchResponse" } ], "description": "Unchanged after a publish, with the id of the message in a header. With batchEnabled=true, the PublishBatchResponse of the AWS SDK" } + }, "properties": { "topicNameOrArn": { "index": 0, "kind": "path", "displayName": "Topic Name Or Arn", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Topic name or ARN" }, "autoCreateTopic": { "index": 1, "kind": "parameter", "displayName": "Auto Create Topic", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.sns.Sns2Configuration", "configurationField": "configuration", "description": "Setting the auto-creation of the topic" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sqs.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sqs.json index 8ff172f1e1f3b..3f8288b43e5ba 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sqs.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-sqs.json @@ -95,7 +95,7 @@ }, "bodyTypes": { "consumerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The body of the SQS message" }, - "producerIn": { "carriers": [ "text" ], "byOption": [ { "option": "operation", "value": "sendBatchMessage", "carriers": [ "list", "text" ] } ], "description": "The body of the message to send, as text, so a Map or a POJO is sent as its toString(): marshal it first. sendBatchMessage takes a List of text, or text that batchSeparator splits" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "operation", "value": "sendBatchMessage", "carriers": [ "list", "text", "pojo" ] } ], "description": "The body of the message to send, as text: bytes, a stream or a file are read as text, and a Map or a POJO is sent as its toString(): marshal it first. sendBatchMessage takes a List of text, text that batchSeparator splits, or a SendMessageBatchRequest" }, "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "sendBatchMessage", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse" }, { "option": "operation", "value": "deleteMessage", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.DeleteMessageResponse" }, { "option": "operation", "value": "listQueues", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.ListQueuesResponse" }, { "option": "operation", "value": "purgeQueue", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.PurgeQueueResponse" }, { "option": "operation", "value": "deleteQueue", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.DeleteQueueResponse" } ], "description": "Unchanged for a send, with the id of the message in a header; the response of the AWS SDK for the other operations" } }, "properties": { diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-eventhubs.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-eventhubs.json index 77145836e81ec..7e092cf7ffb9e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-eventhubs.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-eventhubs.json @@ -60,6 +60,11 @@ "CamelMessageTimestamp": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The timestamp of the message", "constantName": "org.apache.camel.component.azure.eventhubs.EventHubsConstants#MESSAGE_TIMESTAMP" }, "CamelAzureEventHubsCheckpointUpdatedBy": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "It sets the reason for the checkpoint to have been updated. This is only present on a received EventData.", "constantName": "org.apache.camel.component.azure.eventhubs.EventHubsConstants#CHECKPOINT_UPDATED_BY" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The body of the event, one message per event" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "list" ], "description": "What converts to a byte array: text, bytes, a stream or a file, sent as one event; a Map, a number or a POJO fails: marshal it first. A List is sent as one event per element, in one batch, and an element that is an Exchange or a Message is sent with its headers" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "namespace": { "index": 0, "kind": "path", "displayName": "Namespace", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.eventhubs.EventHubsConfiguration", "configurationField": "configuration", "description": "EventHubs namespace created in Azure Portal." }, "eventHubName": { "index": 1, "kind": "path", "displayName": "Event Hub Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.eventhubs.EventHubsConfiguration", "configurationField": "configuration", "description": "EventHubs name under a specific namespace." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-servicebus.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-servicebus.json index 80ca2d4108039..9fd52d36a0e0a 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-servicebus.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-servicebus.json @@ -82,6 +82,11 @@ "CamelAzureServiceBusProducerOperation": { "index": 23, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.apache.camel.component.azure.servicebus.ServiceBusProducerOperationDefinition", "enum": [ "sendMessages", "scheduleMessages" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Overrides the desired operation to be used in the producer.", "constantName": "org.apache.camel.component.azure.servicebus.ServiceBusConstants#PRODUCER_OPERATION" }, "CamelAzureServiceBusCorrelationId": { "index": 24, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Gets or Sets a correlation identifier.", "constantName": "org.apache.camel.component.azure.servicebus.ServiceBusConstants#CORRELATION_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo" ], "javaType": "com.azure.core.util.BinaryData", "description": "The payload of the Service Bus message as an Azure BinaryData, which converts to a String but not to bytes or a stream: convert it to a String before an unmarshal, a file or another producer" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "list" ], "description": "Sent as text by default: bytes, a stream or a file are read as text, so binary content needs binary=true. A BinaryData, as the consumer gives it, is sent as it is, and a Map or a POJO is sent as its toString(): marshal it first. A List is sent as one message per element" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, also after scheduleMessages" } + }, "properties": { "topicOrQueueName": { "index": 0, "kind": "path", "displayName": "Topic Or Queue Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.servicebus.ServiceBusConfiguration", "configurationField": "configuration", "description": "Selected topic name or the queue name, that is depending on serviceBusType config. For example if serviceBusType=queue, then this will be the queue name and if serviceBusType=topic, this will be the topic name." }, "amqpRetryOptions": { "index": 1, "kind": "parameter", "displayName": "Amqp Retry Options", "group": "common", "label": "common", "required": false, "type": "object", "javaType": "com.azure.core.amqp.AmqpRetryOptions", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.servicebus.ServiceBusConfiguration", "configurationField": "configuration", "description": "Sets the retry options for Service Bus clients. If not specified, the default retry options are used." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-queue.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-queue.json index dbae457091d65..6f772e7362745 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-queue.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-queue.json @@ -61,6 +61,11 @@ "CamelAzureStorageQueueTimeToLive": { "index": 14, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Duration", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(sendMessage) How long the message will stay alive in the queue. If unset the value will default to 7 days, if -1 is passed the message will not expire. The time to live must be -1 or any positive number.", "constantName": "org.apache.camel.component.azure.storage.queue.QueueConstants#TIME_TO_LIVE" }, "CamelAzureStorageQueueCreateQueue": { "index": 15, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(sendMessage) When is set to true, the queue will be automatically created when sending messages to the queue.", "constantName": "org.apache.camel.component.azure.storage.queue.QueueConstants#CREATE_QUEUE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "null" ], "description": "The text of the queue message as a stream, with its id and pop receipt in headers; no body for a message without text" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "operation", "value": "updateMessage", "carriers": [ "text", "bytes", "stream", "file", "null" ] }, { "option": "operation", "value": "listQueues", "carriers": [ "any" ] }, { "option": "operation", "value": "createQueue", "carriers": [ "any" ] }, { "option": "operation", "value": "deleteQueue", "carriers": [ "any" ] }, { "option": "operation", "value": "clearQueue", "carriers": [ "any" ] }, { "option": "operation", "value": "deleteMessage", "carriers": [ "any" ] }, { "option": "operation", "value": "receiveMessages", "carriers": [ "any" ] }, { "option": "operation", "value": "peekMessages", "carriers": [ "any" ] } ], "description": "The text of the message for sendMessage, the default, and updateMessage: bytes, a stream or a file are read as text, and a Map or a POJO is sent as its toString(): marshal it first. sendMessage fails without a body, and updateMessage then changes only the visibility. The other operations do not use the body" }, + "producerOut": { "carriers": [ "value" ], "javaType": "java.lang.Boolean", "byOption": [ { "option": "operation", "value": "listQueues", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "receiveMessages", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "peekMessages", "carriers": [ "list" ], "javaType": "java.util.List" } ], "description": "true after sendMessage, the default, and the operations that create, clear, update or delete, with their results in headers, such as the id and the pop receipt of the message sent. A List of the items of the SDK for listQueues, receiveMessages and peekMessages" } + }, "properties": { "accountName": { "index": 0, "kind": "path", "displayName": "Account Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.queue.QueueConfiguration", "configurationField": "configuration", "description": "Azure account name to be used for authentication with azure queue services" }, "queueName": { "index": 1, "kind": "path", "displayName": "Queue Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.queue.QueueConfiguration", "configurationField": "configuration", "description": "The queue resource name" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/google-pubsub.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/google-pubsub.json index 2da993e22ea32..765633f3cd31b 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/google-pubsub.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/google-pubsub.json @@ -45,6 +45,11 @@ "CamelGooglePubsubAcknowledge": { "index": 5, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "org.apache.camel.component.google.pubsub.consumer.GooglePubsubAcknowledge", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Can be used to manually acknowledge or negative-acknowledge a message when ackMode=NONE.", "constantName": "org.apache.camel.component.google.pubsub.GooglePubsubConstants#GOOGLE_PUBSUB_ACKNOWLEDGE" }, "CamelGooglePubsubDeliveryAttempt": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The delivery attempt counter received from PubSub. This is the approximate number of times the message has been delivered. This will be 1 for the first delivery. This feature requires a dead-letter policy to be configured on the subscription.", "constantName": "org.apache.camel.component.google.pubsub.GooglePubsubConstants#DELIVERY_ATTEMPT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The data of the Pub\/Sub message as a byte array, with its attributes in headers: convert or unmarshal it" }, + "producerIn": { "carriers": [ "text", "bytes" ], "dependsOn": [ "serializer" ], "description": "Text is sent as UTF-8 and bytes as they are; a List of the exchanges of a grouped aggregation is sent as one message per exchange. Any other body goes to the serializer, by default Java serialization, so a Map or a POJO is sent as Java-serialized bytes, and a stream or a file fails: marshal or convert it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the id of the published message in a header" } + }, "properties": { "projectId": { "index": 0, "kind": "path", "displayName": "Project Id", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Google Cloud PubSub Project Id" }, "destinationName": { "index": 1, "kind": "path", "displayName": "Destination Name", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Destination Name. For the consumer this will be the subscription name, while for the producer this will be the topic name." }, diff --git a/components/camel-aws/camel-aws2-kinesis/src/generated/resources/META-INF/org/apache/camel/component/aws2/firehose/aws2-kinesis-firehose.json b/components/camel-aws/camel-aws2-kinesis/src/generated/resources/META-INF/org/apache/camel/component/aws2/firehose/aws2-kinesis-firehose.json index eb7e0ba1ffc53..448eba5c7a094 100644 --- a/components/camel-aws/camel-aws2-kinesis/src/generated/resources/META-INF/org/apache/camel/component/aws2/firehose/aws2-kinesis-firehose.json +++ b/components/camel-aws/camel-aws2-kinesis/src/generated/resources/META-INF/org/apache/camel/component/aws2/firehose/aws2-kinesis-firehose.json @@ -54,6 +54,10 @@ "CamelAwsKinesisFirehoseEncrypted": { "index": 5, "kind": "header", "displayName": "", "group": "sendBatchRecord", "label": "sendBatchRecord", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Whether the batch operation was encrypted.", "constantName": "org.apache.camel.component.aws2.firehose.KinesisFirehose2Constants#ENCRYPTED" }, "CamelAwsKinesisFirehoseDeliveryStreamStatus": { "index": 6, "kind": "header", "displayName": "", "group": "describeDeliveryStream", "label": "describeDeliveryStream", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The status of the delivery stream.", "constantName": "org.apache.camel.component.aws2.firehose.KinesisFirehose2Constants#DELIVERY_STREAM_STATUS" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "operation", "value": "sendBatchRecord", "carriers": [ "list", "pojo" ] }, { "option": "operation", "value": "createDeliveryStream", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.CreateDeliveryStreamRequest" }, { "option": "operation", "value": "updateDestination", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.UpdateDestinationRequest" }, { "option": "operation", "value": "deleteDeliveryStream", "carriers": [ "any" ] }, { "option": "operation", "value": "describeDeliveryStream", "carriers": [ "any" ] } ], "description": "The data of the record, when no operation is set: text, bytes, a stream or a file. A Map, a List or a POJO fails, and a number is sent as its binary value: marshal it or convert it to text first. sendBatchRecord takes a List of the Record of the Firehose SDK or a PutRecordBatchRequest, and the other operations their request of the AWS SDK, or for deleteDeliveryStream and describeDeliveryStream the CamelAwsKinesisFirehoseDeliveryStreamName header" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "sendBatchRecord", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.PutRecordBatchResponse" }, { "option": "operation", "value": "createDeliveryStream", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.CreateDeliveryStreamResponse" }, { "option": "operation", "value": "deleteDeliveryStream", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.DeleteDeliveryStreamResponse" }, { "option": "operation", "value": "describeDeliveryStream", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.DescribeDeliveryStreamResponse" }, { "option": "operation", "value": "updateDestination", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.firehose.model.UpdateDestinationResponse" } ], "description": "Unchanged after a send, with the id of the record in a header; the response of the AWS SDK for the operations" } + }, "properties": { "streamName": { "index": 0, "kind": "path", "displayName": "Stream Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.firehose.KinesisFirehose2Configuration", "configurationField": "configuration", "description": "Name of the stream" }, "cborEnabled": { "index": 1, "kind": "parameter", "displayName": "Cbor Enabled", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.aws2.firehose.KinesisFirehose2Configuration", "configurationField": "configuration", "description": "This option will set the CBOR_ENABLED property during the execution" }, diff --git a/components/camel-aws/camel-aws2-kinesis/src/generated/resources/META-INF/org/apache/camel/component/aws2/kinesis/aws2-kinesis.json b/components/camel-aws/camel-aws2-kinesis/src/generated/resources/META-INF/org/apache/camel/component/aws2/kinesis/aws2-kinesis.json index 40e1eb9595bbd..7bc42d67463fa 100644 --- a/components/camel-aws/camel-aws2-kinesis/src/generated/resources/META-INF/org/apache/camel/component/aws2/kinesis/aws2-kinesis.json +++ b/components/camel-aws/camel-aws2-kinesis/src/generated/resources/META-INF/org/apache/camel/component/aws2/kinesis/aws2-kinesis.json @@ -72,6 +72,11 @@ "CamelAwsKinesisFailedRecordCount": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of records that failed in a batch put operation.", "constantName": "org.apache.camel.component.aws2.kinesis.Kinesis2Constants#FAILED_RECORD_COUNT" }, "CamelAwsKinesisRecordCount": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The total number of records in a batch put operation.", "constantName": "org.apache.camel.component.aws2.kinesis.Kinesis2Constants#RECORD_COUNT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "byOption": [ { "option": "useKclConsumers", "value": "true", "carriers": [ "pojo" ], "javaType": "java.nio.ByteBuffer" } ], "description": "The data of the record as a byte array, one message per record, with its partition key, sequence number and shard id in headers. With useKclConsumers=true a java.nio.ByteBuffer: convert it to a String or bytes for the steps that read text" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "list" ], "description": "The data of the record: text, bytes, a stream or a file. A List or another Iterable is sent as a batch, one record per element, and each element must be text, bytes, a ByteBuffer or a stream. A Map or a POJO fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the sequence number and the shard id of the record in headers, or the number of records of a batch" } + }, "properties": { "streamName": { "index": 0, "kind": "path", "displayName": "Stream Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.kinesis.Kinesis2Configuration", "configurationField": "configuration", "description": "Name of the stream" }, "cborEnabled": { "index": 1, "kind": "parameter", "displayName": "Cbor Enabled", "group": "common", "label": "common", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.aws2.kinesis.Kinesis2Configuration", "configurationField": "configuration", "description": "This option will set the CBOR_ENABLED property during the execution" }, diff --git a/components/camel-aws/camel-aws2-kinesis/src/main/java/org/apache/camel/component/aws2/firehose/KinesisFirehose2Endpoint.java b/components/camel-aws/camel-aws2-kinesis/src/main/java/org/apache/camel/component/aws2/firehose/KinesisFirehose2Endpoint.java index 35e73ae69161e..9cb690c5b8c28 100644 --- a/components/camel-aws/camel-aws2-kinesis/src/main/java/org/apache/camel/component/aws2/firehose/KinesisFirehose2Endpoint.java +++ b/components/camel-aws/camel-aws2-kinesis/src/main/java/org/apache/camel/component/aws2/firehose/KinesisFirehose2Endpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.component.aws2.firehose.client.KinesisFirehoseClientFactory; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -40,6 +43,45 @@ Category.CLOUD, Category.MESSAGING }, headersClass = KinesisFirehose2Constants.class) +@BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + byOption = { + @BodyType.When(option = "operation", value = "sendBatchRecord", + carriers = { Carrier.LIST, Carrier.POJO }), + @BodyType.When(option = "operation", value = "createDeliveryStream", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.firehose.model.CreateDeliveryStreamRequest"), + @BodyType.When(option = "operation", value = "updateDestination", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.firehose.model.UpdateDestinationRequest"), + @BodyType.When(option = "operation", value = "deleteDeliveryStream", + carriers = Carrier.ANY), + @BodyType.When(option = "operation", value = "describeDeliveryStream", + carriers = Carrier.ANY) }, + description = "The data of the record, when no operation is set: text, bytes, a stream or a" + + " file. A Map, a List or a POJO fails, and a number is sent as its binary" + + " value: marshal it or convert it to text first. sendBatchRecord takes a List" + + " of the Record of the Firehose SDK or a PutRecordBatchRequest, and the other" + + " operations their request of the AWS SDK, or for deleteDeliveryStream and" + + " describeDeliveryStream the CamelAwsKinesisFirehoseDeliveryStreamName header"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + byOption = { + @BodyType.When(option = "operation", value = "sendBatchRecord", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.firehose.model.PutRecordBatchResponse"), + @BodyType.When(option = "operation", value = "createDeliveryStream", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.firehose.model.CreateDeliveryStreamResponse"), + @BodyType.When(option = "operation", value = "deleteDeliveryStream", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.firehose.model.DeleteDeliveryStreamResponse"), + @BodyType.When(option = "operation", value = "describeDeliveryStream", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.firehose.model.DescribeDeliveryStreamResponse"), + @BodyType.When(option = "operation", value = "updateDestination", + carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.firehose.model.UpdateDestinationResponse") }, + description = "Unchanged after a send, with the id of the record in a header; the response" + + " of the AWS SDK for the operations")) public class KinesisFirehose2Endpoint extends DefaultEndpoint implements EndpointServiceLocation { @UriParam diff --git a/components/camel-aws/camel-aws2-kinesis/src/main/java/org/apache/camel/component/aws2/kinesis/Kinesis2Endpoint.java b/components/camel-aws/camel-aws2-kinesis/src/main/java/org/apache/camel/component/aws2/kinesis/Kinesis2Endpoint.java index 7bef9ecfb57e0..85746c41217bd 100644 --- a/components/camel-aws/camel-aws2-kinesis/src/main/java/org/apache/camel/component/aws2/kinesis/Kinesis2Endpoint.java +++ b/components/camel-aws/camel-aws2-kinesis/src/main/java/org/apache/camel/component/aws2/kinesis/Kinesis2Endpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -39,6 +42,21 @@ */ @UriEndpoint(firstVersion = "3.2.0", scheme = "aws2-kinesis", title = "AWS Kinesis", syntax = "aws2-kinesis:streamName", category = { Category.CLOUD, Category.MESSAGING }, headersClass = Kinesis2Constants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]", + byOption = @BodyType.When(option = "useKclConsumers", value = "true", + carriers = Carrier.POJO, javaType = "java.nio.ByteBuffer"), + description = "The data of the record as a byte array, one message per record, with its" + + " partition key, sequence number and shard id in headers. With" + + " useKclConsumers=true a java.nio.ByteBuffer: convert it to a String or" + + " bytes for the steps that read text"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.LIST }, + description = "The data of the record: text, bytes, a stream or a file. A List or another" + + " Iterable is sent as a batch, one record per element, and each element" + + " must be text, bytes, a ByteBuffer or a stream. A Map or a POJO fails:" + + " marshal it first"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged, with the sequence number and the shard id of the record in" + + " headers, or the number of records of a batch")) public class Kinesis2Endpoint extends ScheduledPollEndpoint implements EndpointServiceLocation { @UriParam diff --git a/components/camel-aws/camel-aws2-sns/src/generated/resources/META-INF/org/apache/camel/component/aws2/sns/aws2-sns.json b/components/camel-aws/camel-aws2-sns/src/generated/resources/META-INF/org/apache/camel/component/aws2/sns/aws2-sns.json index 7329d7204a10f..a95e468d16342 100644 --- a/components/camel-aws/camel-aws2-sns/src/generated/resources/META-INF/org/apache/camel/component/aws2/sns/aws2-sns.json +++ b/components/camel-aws/camel-aws2-sns/src/generated/resources/META-INF/org/apache/camel/component/aws2/sns/aws2-sns.json @@ -64,6 +64,10 @@ "CamelAwsSnsFailedMessageCount": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of failed messages in a batch publish operation.", "constantName": "org.apache.camel.component.aws2.sns.Sns2Constants#FAILED_MESSAGE_COUNT" }, "CamelAwsSnsSuccessfulMessageCount": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of successful messages in a batch publish operation.", "constantName": "org.apache.camel.component.aws2.sns.Sns2Constants#SUCCESSFUL_MESSAGE_COUNT" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "batchEnabled", "value": "true", "carriers": [ "list" ] } ], "description": "The message to publish, as text: bytes, a stream or a file are read as text, and a Map or a POJO is sent as its toString(): marshal it first. With messageStructure=json, a JSON object with a message per protocol; with batchEnabled=true, a List of the PublishBatchRequestEntry of the AWS SDK" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "batchEnabled", "value": "true", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sns.model.PublishBatchResponse" } ], "description": "Unchanged after a publish, with the id of the message in a header. With batchEnabled=true, the PublishBatchResponse of the AWS SDK" } + }, "properties": { "topicNameOrArn": { "index": 0, "kind": "path", "displayName": "Topic Name Or Arn", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Topic name or ARN" }, "autoCreateTopic": { "index": 1, "kind": "parameter", "displayName": "Auto Create Topic", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.sns.Sns2Configuration", "configurationField": "configuration", "description": "Setting the auto-creation of the topic" }, diff --git a/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Endpoint.java b/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Endpoint.java index e5cdb788e7d50..ac9f04e97c371 100644 --- a/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Endpoint.java +++ b/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Endpoint.java @@ -28,6 +28,7 @@ import org.apache.camel.Producer; import org.apache.camel.component.aws2.sns.client.Sns2ClientFactory; import org.apache.camel.spi.*; +import org.apache.camel.spi.BodyType.Carrier; import org.apache.camel.support.DefaultEndpoint; import org.apache.camel.support.ResourceHelper; import org.apache.camel.util.ObjectHelper; @@ -51,6 +52,17 @@ @UriEndpoint(firstVersion = "3.1.0", scheme = "aws2-sns", title = "AWS Simple Notification System (SNS)", syntax = "aws2-sns:topicNameOrArn", producerOnly = true, category = { Category.CLOUD, Category.MESSAGING, Category.MOBILE }, headersClass = Sns2Constants.class) +@BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + byOption = @BodyType.When(option = "batchEnabled", value = "true", carriers = Carrier.LIST), + description = "The message to publish, as text: bytes, a stream or a file are read as text," + + " and a Map or a POJO is sent as its toString(): marshal it first. With" + + " messageStructure=json, a JSON object with a message per protocol; with" + + " batchEnabled=true, a List of the PublishBatchRequestEntry of the AWS SDK"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + byOption = @BodyType.When(option = "batchEnabled", value = "true", carriers = Carrier.POJO, + javaType = "software.amazon.awssdk.services.sns.model.PublishBatchResponse"), + description = "Unchanged after a publish, with the id of the message in a header. With" + + " batchEnabled=true, the PublishBatchResponse of the AWS SDK")) public class Sns2Endpoint extends DefaultEndpoint implements HeaderFilterStrategyAware, EndpointServiceLocation { private static final Logger LOG = LoggerFactory.getLogger(Sns2Endpoint.class); diff --git a/components/camel-aws/camel-aws2-sqs/src/generated/resources/META-INF/org/apache/camel/component/aws2/sqs/aws2-sqs.json b/components/camel-aws/camel-aws2-sqs/src/generated/resources/META-INF/org/apache/camel/component/aws2/sqs/aws2-sqs.json index 8ff172f1e1f3b..3f8288b43e5ba 100644 --- a/components/camel-aws/camel-aws2-sqs/src/generated/resources/META-INF/org/apache/camel/component/aws2/sqs/aws2-sqs.json +++ b/components/camel-aws/camel-aws2-sqs/src/generated/resources/META-INF/org/apache/camel/component/aws2/sqs/aws2-sqs.json @@ -95,7 +95,7 @@ }, "bodyTypes": { "consumerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The body of the SQS message" }, - "producerIn": { "carriers": [ "text" ], "byOption": [ { "option": "operation", "value": "sendBatchMessage", "carriers": [ "list", "text" ] } ], "description": "The body of the message to send, as text, so a Map or a POJO is sent as its toString(): marshal it first. sendBatchMessage takes a List of text, or text that batchSeparator splits" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "operation", "value": "sendBatchMessage", "carriers": [ "list", "text", "pojo" ] } ], "description": "The body of the message to send, as text: bytes, a stream or a file are read as text, and a Map or a POJO is sent as its toString(): marshal it first. sendBatchMessage takes a List of text, text that batchSeparator splits, or a SendMessageBatchRequest" }, "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "sendBatchMessage", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse" }, { "option": "operation", "value": "deleteMessage", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.DeleteMessageResponse" }, { "option": "operation", "value": "listQueues", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.ListQueuesResponse" }, { "option": "operation", "value": "purgeQueue", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.PurgeQueueResponse" }, { "option": "operation", "value": "deleteQueue", "carriers": [ "pojo" ], "javaType": "software.amazon.awssdk.services.sqs.model.DeleteQueueResponse" } ], "description": "Unchanged for a send, with the id of the message in a header; the response of the AWS SDK for the other operations" } }, "properties": { diff --git a/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java b/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java index 961073d19076b..680fc3ecae452 100644 --- a/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java +++ b/components/camel-aws/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java @@ -63,12 +63,13 @@ headersClass = Sqs2Constants.class) @BodyTypes(consumerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", description = "The body of the SQS message"), - producerIn = @BodyType(value = Carrier.TEXT, + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, byOption = @BodyType.When(option = "operation", value = "sendBatchMessage", - carriers = { Carrier.LIST, Carrier.TEXT }), - description = "The body of the message to send, as text, so a Map or a POJO is sent as" - + " its toString(): marshal it first. sendBatchMessage takes a List of" - + " text, or text that batchSeparator splits"), + carriers = { Carrier.LIST, Carrier.TEXT, Carrier.POJO }), + description = "The body of the message to send, as text: bytes, a stream or a file are read" + + " as text, and a Map or a POJO is sent as its toString(): marshal it first." + + " sendBatchMessage takes a List of text, text that batchSeparator splits, or" + + " a SendMessageBatchRequest"), producerOut = @BodyType(value = Carrier.UNCHANGED, byOption = { @BodyType.When(option = "operation", value = "sendBatchMessage", diff --git a/components/camel-azure/camel-azure-eventhubs/src/generated/resources/META-INF/org/apache/camel/component/azure/eventhubs/azure-eventhubs.json b/components/camel-azure/camel-azure-eventhubs/src/generated/resources/META-INF/org/apache/camel/component/azure/eventhubs/azure-eventhubs.json index 77145836e81ec..7e092cf7ffb9e 100644 --- a/components/camel-azure/camel-azure-eventhubs/src/generated/resources/META-INF/org/apache/camel/component/azure/eventhubs/azure-eventhubs.json +++ b/components/camel-azure/camel-azure-eventhubs/src/generated/resources/META-INF/org/apache/camel/component/azure/eventhubs/azure-eventhubs.json @@ -60,6 +60,11 @@ "CamelMessageTimestamp": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The timestamp of the message", "constantName": "org.apache.camel.component.azure.eventhubs.EventHubsConstants#MESSAGE_TIMESTAMP" }, "CamelAzureEventHubsCheckpointUpdatedBy": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "It sets the reason for the checkpoint to have been updated. This is only present on a received EventData.", "constantName": "org.apache.camel.component.azure.eventhubs.EventHubsConstants#CHECKPOINT_UPDATED_BY" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The body of the event, one message per event" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "list" ], "description": "What converts to a byte array: text, bytes, a stream or a file, sent as one event; a Map, a number or a POJO fails: marshal it first. A List is sent as one event per element, in one batch, and an element that is an Exchange or a Message is sent with its headers" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "namespace": { "index": 0, "kind": "path", "displayName": "Namespace", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.eventhubs.EventHubsConfiguration", "configurationField": "configuration", "description": "EventHubs namespace created in Azure Portal." }, "eventHubName": { "index": 1, "kind": "path", "displayName": "Event Hub Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.eventhubs.EventHubsConfiguration", "configurationField": "configuration", "description": "EventHubs name under a specific namespace." }, diff --git a/components/camel-azure/camel-azure-eventhubs/src/main/java/org/apache/camel/component/azure/eventhubs/EventHubsEndpoint.java b/components/camel-azure/camel-azure-eventhubs/src/main/java/org/apache/camel/component/azure/eventhubs/EventHubsEndpoint.java index 623cd418df6ae..3416e25cd7959 100644 --- a/components/camel-azure/camel-azure-eventhubs/src/main/java/org/apache/camel/component/azure/eventhubs/EventHubsEndpoint.java +++ b/components/camel-azure/camel-azure-eventhubs/src/main/java/org/apache/camel/component/azure/eventhubs/EventHubsEndpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -36,6 +39,14 @@ syntax = "azure-eventhubs:namespace/eventHubName", category = { Category.CLOUD, Category.MESSAGING }, headersClass = EventHubsConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]", + description = "The body of the event, one message per event"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.LIST }, + description = "What converts to a byte array: text, bytes, a stream or a file, sent as one" + + " event; a Map, a number or a POJO fails: marshal it first. A List is sent" + + " as one event per element, in one batch, and an element that is an Exchange" + + " or a Message is sent with its headers"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class EventHubsEndpoint extends DefaultEndpoint implements EndpointServiceLocation { @UriParam diff --git a/components/camel-azure/camel-azure-servicebus/src/generated/resources/META-INF/org/apache/camel/component/azure/servicebus/azure-servicebus.json b/components/camel-azure/camel-azure-servicebus/src/generated/resources/META-INF/org/apache/camel/component/azure/servicebus/azure-servicebus.json index 80ca2d4108039..9fd52d36a0e0a 100644 --- a/components/camel-azure/camel-azure-servicebus/src/generated/resources/META-INF/org/apache/camel/component/azure/servicebus/azure-servicebus.json +++ b/components/camel-azure/camel-azure-servicebus/src/generated/resources/META-INF/org/apache/camel/component/azure/servicebus/azure-servicebus.json @@ -82,6 +82,11 @@ "CamelAzureServiceBusProducerOperation": { "index": 23, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.apache.camel.component.azure.servicebus.ServiceBusProducerOperationDefinition", "enum": [ "sendMessages", "scheduleMessages" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Overrides the desired operation to be used in the producer.", "constantName": "org.apache.camel.component.azure.servicebus.ServiceBusConstants#PRODUCER_OPERATION" }, "CamelAzureServiceBusCorrelationId": { "index": 24, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Gets or Sets a correlation identifier.", "constantName": "org.apache.camel.component.azure.servicebus.ServiceBusConstants#CORRELATION_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo" ], "javaType": "com.azure.core.util.BinaryData", "description": "The payload of the Service Bus message as an Azure BinaryData, which converts to a String but not to bytes or a stream: convert it to a String before an unmarshal, a file or another producer" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "list" ], "description": "Sent as text by default: bytes, a stream or a file are read as text, so binary content needs binary=true. A BinaryData, as the consumer gives it, is sent as it is, and a Map or a POJO is sent as its toString(): marshal it first. A List is sent as one message per element" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, also after scheduleMessages" } + }, "properties": { "topicOrQueueName": { "index": 0, "kind": "path", "displayName": "Topic Or Queue Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.servicebus.ServiceBusConfiguration", "configurationField": "configuration", "description": "Selected topic name or the queue name, that is depending on serviceBusType config. For example if serviceBusType=queue, then this will be the queue name and if serviceBusType=topic, this will be the topic name." }, "amqpRetryOptions": { "index": 1, "kind": "parameter", "displayName": "Amqp Retry Options", "group": "common", "label": "common", "required": false, "type": "object", "javaType": "com.azure.core.amqp.AmqpRetryOptions", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.servicebus.ServiceBusConfiguration", "configurationField": "configuration", "description": "Sets the retry options for Service Bus clients. If not specified, the default retry options are used." }, diff --git a/components/camel-azure/camel-azure-servicebus/src/main/java/org/apache/camel/component/azure/servicebus/ServiceBusEndpoint.java b/components/camel-azure/camel-azure-servicebus/src/main/java/org/apache/camel/component/azure/servicebus/ServiceBusEndpoint.java index 454f081ceba1f..bf5a8f8d08a7e 100644 --- a/components/camel-azure/camel-azure-servicebus/src/main/java/org/apache/camel/component/azure/servicebus/ServiceBusEndpoint.java +++ b/components/camel-azure/camel-azure-servicebus/src/main/java/org/apache/camel/component/azure/servicebus/ServiceBusEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.component.azure.servicebus.client.ServiceBusClientFactory; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -37,6 +40,17 @@ syntax = "azure-servicebus:topicOrQueueName", category = { Category.CLOUD, Category.MESSAGING }, headersClass = ServiceBusConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.POJO, javaType = "com.azure.core.util.BinaryData", + description = "The payload of the Service Bus message as an Azure BinaryData, which" + + " converts to a String but not to bytes or a stream: convert it to a" + + " String before an unmarshal, a file or another producer"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.LIST }, + description = "Sent as text by default: bytes, a stream or a file are read as text, so" + + " binary content needs binary=true. A BinaryData, as the consumer gives it, is" + + " sent as it is, and a Map or a POJO is sent as its toString(): marshal it" + + " first. A List is sent as one message per element"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged, also after scheduleMessages")) public class ServiceBusEndpoint extends DefaultEndpoint implements EndpointServiceLocation { @UriParam diff --git a/components/camel-azure/camel-azure-storage-queue/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/queue/azure-storage-queue.json b/components/camel-azure/camel-azure-storage-queue/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/queue/azure-storage-queue.json index dbae457091d65..6f772e7362745 100644 --- a/components/camel-azure/camel-azure-storage-queue/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/queue/azure-storage-queue.json +++ b/components/camel-azure/camel-azure-storage-queue/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/queue/azure-storage-queue.json @@ -61,6 +61,11 @@ "CamelAzureStorageQueueTimeToLive": { "index": 14, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Duration", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(sendMessage) How long the message will stay alive in the queue. If unset the value will default to 7 days, if -1 is passed the message will not expire. The time to live must be -1 or any positive number.", "constantName": "org.apache.camel.component.azure.storage.queue.QueueConstants#TIME_TO_LIVE" }, "CamelAzureStorageQueueCreateQueue": { "index": 15, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(sendMessage) When is set to true, the queue will be automatically created when sending messages to the queue.", "constantName": "org.apache.camel.component.azure.storage.queue.QueueConstants#CREATE_QUEUE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "stream", "null" ], "description": "The text of the queue message as a stream, with its id and pop receipt in headers; no body for a message without text" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "byOption": [ { "option": "operation", "value": "updateMessage", "carriers": [ "text", "bytes", "stream", "file", "null" ] }, { "option": "operation", "value": "listQueues", "carriers": [ "any" ] }, { "option": "operation", "value": "createQueue", "carriers": [ "any" ] }, { "option": "operation", "value": "deleteQueue", "carriers": [ "any" ] }, { "option": "operation", "value": "clearQueue", "carriers": [ "any" ] }, { "option": "operation", "value": "deleteMessage", "carriers": [ "any" ] }, { "option": "operation", "value": "receiveMessages", "carriers": [ "any" ] }, { "option": "operation", "value": "peekMessages", "carriers": [ "any" ] } ], "description": "The text of the message for sendMessage, the default, and updateMessage: bytes, a stream or a file are read as text, and a Map or a POJO is sent as its toString(): marshal it first. sendMessage fails without a body, and updateMessage then changes only the visibility. The other operations do not use the body" }, + "producerOut": { "carriers": [ "value" ], "javaType": "java.lang.Boolean", "byOption": [ { "option": "operation", "value": "listQueues", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "receiveMessages", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "operation", "value": "peekMessages", "carriers": [ "list" ], "javaType": "java.util.List" } ], "description": "true after sendMessage, the default, and the operations that create, clear, update or delete, with their results in headers, such as the id and the pop receipt of the message sent. A List of the items of the SDK for listQueues, receiveMessages and peekMessages" } + }, "properties": { "accountName": { "index": 0, "kind": "path", "displayName": "Account Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.queue.QueueConfiguration", "configurationField": "configuration", "description": "Azure account name to be used for authentication with azure queue services" }, "queueName": { "index": 1, "kind": "path", "displayName": "Queue Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.queue.QueueConfiguration", "configurationField": "configuration", "description": "The queue resource name" }, diff --git a/components/camel-azure/camel-azure-storage-queue/src/main/java/org/apache/camel/component/azure/storage/queue/QueueEndpoint.java b/components/camel-azure/camel-azure-storage-queue/src/main/java/org/apache/camel/component/azure/storage/queue/QueueEndpoint.java index 1230622682a55..f54464a4537c3 100644 --- a/components/camel-azure/camel-azure-storage-queue/src/main/java/org/apache/camel/component/azure/storage/queue/QueueEndpoint.java +++ b/components/camel-azure/camel-azure-storage-queue/src/main/java/org/apache/camel/component/azure/storage/queue/QueueEndpoint.java @@ -25,6 +25,9 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.component.azure.storage.queue.client.QueueClientFactory; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -37,6 +40,42 @@ @UriEndpoint(firstVersion = "3.3.0", scheme = "azure-storage-queue", title = "Azure Storage Queue Service", syntax = "azure-storage-queue:accountName/queueName", category = { Category.CLOUD, Category.MESSAGING }, headersClass = QueueConstants.class) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.STREAM, Carrier.NULL }, + description = "The text of the queue message as a stream, with its id and pop receipt" + + " in headers; no body for a message without text"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + byOption = { + @BodyType.When(option = "operation", value = "updateMessage", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, + Carrier.NULL }), + @BodyType.When(option = "operation", value = "listQueues", carriers = Carrier.ANY), + @BodyType.When(option = "operation", value = "createQueue", carriers = Carrier.ANY), + @BodyType.When(option = "operation", value = "deleteQueue", carriers = Carrier.ANY), + @BodyType.When(option = "operation", value = "clearQueue", carriers = Carrier.ANY), + @BodyType.When(option = "operation", value = "deleteMessage", carriers = Carrier.ANY), + @BodyType.When(option = "operation", value = "receiveMessages", + carriers = Carrier.ANY), + @BodyType.When(option = "operation", value = "peekMessages", + carriers = Carrier.ANY) }, + description = "The text of the message for sendMessage, the default, and updateMessage: bytes," + + " a stream or a file are read as text, and a Map or a POJO is sent as its" + + " toString(): marshal it first. sendMessage fails without a body, and" + + " updateMessage then changes only the visibility. The other operations do not" + + " use the body"), + producerOut = @BodyType(value = Carrier.VALUE, javaType = "java.lang.Boolean", + byOption = { + @BodyType.When(option = "operation", value = "listQueues", carriers = Carrier.LIST, + javaType = "java.util.List"), + @BodyType.When(option = "operation", value = "receiveMessages", + carriers = Carrier.LIST, + javaType = "java.util.List"), + @BodyType.When(option = "operation", value = "peekMessages", carriers = Carrier.LIST, + javaType = "java.util.List") }, + description = "true after sendMessage, the default, and the operations that create, clear," + + " update or delete, with their results in headers, such as the id and the pop" + + " receipt of the message sent. A List of the items of the SDK for listQueues," + + " receiveMessages and peekMessages")) public class QueueEndpoint extends ScheduledPollEndpoint implements EndpointServiceLocation { private QueueServiceClient queueServiceClient; diff --git a/components/camel-google/camel-google-pubsub/src/generated/resources/META-INF/org/apache/camel/component/google/pubsub/google-pubsub.json b/components/camel-google/camel-google-pubsub/src/generated/resources/META-INF/org/apache/camel/component/google/pubsub/google-pubsub.json index 2da993e22ea32..765633f3cd31b 100644 --- a/components/camel-google/camel-google-pubsub/src/generated/resources/META-INF/org/apache/camel/component/google/pubsub/google-pubsub.json +++ b/components/camel-google/camel-google-pubsub/src/generated/resources/META-INF/org/apache/camel/component/google/pubsub/google-pubsub.json @@ -45,6 +45,11 @@ "CamelGooglePubsubAcknowledge": { "index": 5, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "org.apache.camel.component.google.pubsub.consumer.GooglePubsubAcknowledge", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Can be used to manually acknowledge or negative-acknowledge a message when ackMode=NONE.", "constantName": "org.apache.camel.component.google.pubsub.GooglePubsubConstants#GOOGLE_PUBSUB_ACKNOWLEDGE" }, "CamelGooglePubsubDeliveryAttempt": { "index": 6, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The delivery attempt counter received from PubSub. This is the approximate number of times the message has been delivered. This will be 1 for the first delivery. This feature requires a dead-letter policy to be configured on the subscription.", "constantName": "org.apache.camel.component.google.pubsub.GooglePubsubConstants#DELIVERY_ATTEMPT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The data of the Pub\/Sub message as a byte array, with its attributes in headers: convert or unmarshal it" }, + "producerIn": { "carriers": [ "text", "bytes" ], "dependsOn": [ "serializer" ], "description": "Text is sent as UTF-8 and bytes as they are; a List of the exchanges of a grouped aggregation is sent as one message per exchange. Any other body goes to the serializer, by default Java serialization, so a Map or a POJO is sent as Java-serialized bytes, and a stream or a file fails: marshal or convert it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the id of the published message in a header" } + }, "properties": { "projectId": { "index": 0, "kind": "path", "displayName": "Project Id", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Google Cloud PubSub Project Id" }, "destinationName": { "index": 1, "kind": "path", "displayName": "Destination Name", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The Destination Name. For the consumer this will be the subscription name, while for the producer this will be the topic name." }, diff --git a/components/camel-google/camel-google-pubsub/src/main/java/org/apache/camel/component/google/pubsub/GooglePubsubEndpoint.java b/components/camel-google/camel-google-pubsub/src/main/java/org/apache/camel/component/google/pubsub/GooglePubsubEndpoint.java index cbdacf9ff85e9..9b111e27f3f87 100644 --- a/components/camel-google/camel-google-pubsub/src/main/java/org/apache/camel/component/google/pubsub/GooglePubsubEndpoint.java +++ b/components/camel-google/camel-google-pubsub/src/main/java/org/apache/camel/component/google/pubsub/GooglePubsubEndpoint.java @@ -30,6 +30,7 @@ import org.apache.camel.component.google.pubsub.serializer.DefaultGooglePubsubSerializer; import org.apache.camel.component.google.pubsub.serializer.GooglePubsubSerializer; import org.apache.camel.spi.*; +import org.apache.camel.spi.BodyType.Carrier; import org.apache.camel.support.DefaultEndpoint; import org.apache.camel.util.ObjectHelper; import org.slf4j.Logger; @@ -43,6 +44,17 @@ @UriEndpoint(firstVersion = "2.19.0", scheme = "google-pubsub", title = "Google Pubsub", syntax = "google-pubsub:projectId:destinationName", category = { Category.CLOUD, Category.MESSAGING }, headersClass = GooglePubsubConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]", + description = "The data of the Pub/Sub message as a byte array, with its attributes in" + + " headers: convert or unmarshal it"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES }, dependsOn = "serializer", + description = "Text is sent as UTF-8 and bytes as they are; a List of the exchanges of a" + + " grouped aggregation is sent as one message per exchange. Any other body" + + " goes to the serializer, by default Java serialization, so a Map or a POJO" + + " is sent as Java-serialized bytes, and a stream or a file fails: marshal or" + + " convert it first"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged, with the id of the published message in a header")) public class GooglePubsubEndpoint extends DefaultEndpoint implements EndpointServiceLocation, HeaderFilterStrategyAware, GoogleCommonConfiguration { diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java index 2422508a73f51..27c6c2b9e64a4 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java @@ -1134,6 +1134,58 @@ public void testTheBodyOfObjectStorage() { .contains("the azure-storage-blob consumer gives it as a stream or a file: unmarshal it first")); } + @Test + public void testTheBodyOfCloudMessaging() { + // the event hubs consumer gives bytes and the queue consumer a stream, so a field read needs an unmarshal; + // google-pubsub sends text or bytes, so parsed data must be marshalled first, while aws2-kinesis sends a List + // as a batch of records + String yaml = """ + - route: + id: events + from: + uri: azure-eventhubs:namespace/orders + steps: + - setHeader: + name: id + simple: ${body[id]} + - route: + id: queue + from: + uri: azure-storage-queue:account/orders + steps: + - setHeader: + name: id + simple: ${body[id]} + - route: + id: publish + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: google-pubsub:project:orders + - route: + id: batch + from: + uri: timer:tick + steps: + - setBody: + constant: '[1, 2]' + - unmarshal: + json: {} + - to: aws2-kinesis:orders + """; + assertThat(lines(yaml)).hasSize(3).anySatisfy(m -> assertThat(m) + .contains("route events: simple reads a field of the body (${body[id]})") + .contains("the azure-eventhubs consumer gives it as bytes")) + .anySatisfy(m -> assertThat(m) + .contains("route queue: simple reads a field of the body (${body[id]})") + .contains("the azure-storage-queue consumer gives it as a stream")) + .anySatisfy(m -> assertThat(m).contains("to: google-pubsub needs the body as text or bytes")); + } + @Test public void testOneReportForAStepThatFails() { // the first write fails at runtime, so the second does not run with this body From 1089a04d9abe11af92aebb38126dd379dcdb7d67 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 22 Oct 2026 11:21:13 +0200 Subject: [PATCH 17/25] CAMEL-24961: Catalog body types for the core components and languages The body types of bean, class, browse, controlbus, dataformat, dataset, dataset-test, dynamic-router, dynamic-router-control, event, exec, knative, language, once, ref, rest-api, saga, stream, stub, validator, wasm and xslt-saxon, and of the bean, header, exchangeProperty, variable, ref, file, tokenize and xtokenize languages, read from the code and checked at runtime with camel run (knative over a local environment file). The xpath and jq languages read the source option instead of the body when it is set, which their expressionIn now says, as tokenize and xtokenize do. The component docs of stream, exec, language, once, browse and dataset said things about the body that the code does not do. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../apache/camel/catalog/components/bean.json | 4 ++ .../camel/catalog/components/browse.json | 5 ++ .../camel/catalog/components/class.json | 4 ++ .../camel/catalog/components/controlbus.json | 4 ++ .../camel/catalog/components/dataformat.json | 4 ++ .../catalog/components/dataset-test.json | 4 ++ .../camel/catalog/components/dataset.json | 5 ++ .../components/dynamic-router-control.json | 4 ++ .../catalog/components/dynamic-router.json | 4 ++ .../camel/catalog/components/event.json | 3 ++ .../apache/camel/catalog/components/exec.json | 4 ++ .../camel/catalog/components/knative.json | 6 +++ .../camel/catalog/components/language.json | 4 ++ .../apache/camel/catalog/components/once.json | 3 ++ .../apache/camel/catalog/components/ref.json | 5 ++ .../camel/catalog/components/rest-api.json | 4 ++ .../apache/camel/catalog/components/saga.json | 4 ++ .../camel/catalog/components/stream.json | 5 ++ .../apache/camel/catalog/components/stub.json | 5 ++ .../camel/catalog/components/validator.json | 4 ++ .../apache/camel/catalog/components/wasm.json | 4 ++ .../camel/catalog/components/xslt-saxon.json | 4 ++ .../camel/catalog/docs/browse-component.adoc | 2 +- .../camel/catalog/docs/dataset-component.adoc | 4 +- .../camel/catalog/docs/exec-component.adoc | 8 +-- .../catalog/docs/language-component.adoc | 13 ++--- .../camel/catalog/docs/once-component.adoc | 6 +-- .../camel/catalog/docs/stream-component.adoc | 13 +++-- .../apache/camel/catalog/languages/bean.json | 4 ++ .../catalog/languages/exchangeProperty.json | 3 ++ .../apache/camel/catalog/languages/file.json | 4 ++ .../camel/catalog/languages/header.json | 3 ++ .../apache/camel/catalog/languages/jq.json | 2 +- .../apache/camel/catalog/languages/ref.json | 4 ++ .../camel/catalog/languages/tokenize.json | 4 ++ .../camel/catalog/languages/variable.json | 3 ++ .../apache/camel/catalog/languages/xpath.json | 2 +- .../camel/catalog/languages/xtokenize.json | 4 ++ .../org/apache/camel/component/bean/bean.json | 4 ++ .../camel/component/beanclass/class.json | 4 ++ .../org/apache/camel/language/bean/bean.json | 4 ++ .../camel/component/bean/BeanEndpoint.java | 10 ++++ .../component/beanclass/ClassEndpoint.java | 10 ++++ .../camel/language/bean/BeanLanguage.java | 6 +++ .../apache/camel/component/browse/browse.json | 5 ++ .../src/main/docs/browse-component.adoc | 2 +- .../component/browse/BrowseEndpoint.java | 10 ++++ .../component/controlbus/controlbus.json | 4 ++ .../controlbus/ControlBusEndpoint.java | 22 ++++++++ .../component/dataformat/dataformat.json | 4 ++ .../dataformat/DataFormatEndpoint.java | 9 ++++ .../camel/component/dataset/dataset-test.json | 4 ++ .../camel/component/dataset/dataset.json | 5 ++ .../src/main/docs/dataset-component.adoc | 4 +- .../component/dataset/DataSetEndpoint.java | 11 ++++ .../dataset/DataSetTestEndpoint.java | 8 +++ .../control/dynamic-router-control.json | 4 ++ .../dynamicrouter/routing/dynamic-router.json | 4 ++ .../control/DynamicRouterControlEndpoint.java | 23 +++++++++ .../routing/DynamicRouterEndpoint.java | 10 ++++ .../camel/component/camelevent/event.json | 3 ++ .../camelevent/CamelEventEndpoint.java | 7 +++ .../org/apache/camel/component/exec/exec.json | 4 ++ .../src/main/docs/exec-component.adoc | 8 +-- .../camel/component/exec/ExecEndpoint.java | 12 +++++ .../org/apache/camel/language/jq/jq.json | 2 +- .../apache/camel/language/jq/JqLanguage.java | 3 +- .../camel/component/knative/knative.json | 6 +++ .../component/knative/KnativeEndpoint.java | 20 ++++++++ .../camel/component/language/language.json | 4 ++ .../src/main/docs/language-component.adoc | 13 ++--- .../component/language/LanguageEndpoint.java | 14 +++++ .../org/apache/camel/component/once/once.json | 3 ++ .../src/main/docs/once-component.adoc | 6 +-- .../camel/component/once/OnceEndpoint.java | 8 +++ .../org/apache/camel/component/ref/ref.json | 5 ++ .../camel/component/ref/RefEndpoint.java | 9 ++++ .../apache/camel/component/rest/rest-api.json | 4 ++ .../camel/component/rest/RestApiEndpoint.java | 10 ++++ .../org/apache/camel/component/saga/saga.json | 4 ++ .../camel/component/saga/SagaEndpoint.java | 7 +++ .../camel/language/xtokenizer/xtokenize.json | 4 ++ .../xtokenizer/XMLTokenizeLanguage.java | 9 ++++ .../apache/camel/component/stream/stream.json | 5 ++ .../src/main/docs/stream-component.adoc | 13 +++-- .../component/stream/StreamEndpoint.java | 13 +++++ .../org/apache/camel/component/stub/stub.json | 5 ++ .../camel/component/stub/StubEndpoint.java | 9 ++++ .../camel/component/validator/validator.json | 4 ++ .../validator/ValidatorEndpoint.java | 14 +++++ .../org/apache/camel/component/wasm/wasm.json | 4 ++ .../camel/component/wasm/WasmEndpoint.java | 9 ++++ .../apache/camel/language/xpath/xpath.json | 2 +- .../camel/language/xpath/XPathLanguage.java | 3 +- .../component/xslt/saxon/xslt-saxon.json | 4 ++ .../xslt/saxon/XsltSaxonEndpoint.java | 21 ++++++++ .../apache/camel/language/header/header.json | 3 ++ .../language/property/exchangeProperty.json | 3 ++ .../org/apache/camel/language/ref/ref.json | 4 ++ .../apache/camel/language/simple/file.json | 4 ++ .../camel/language/tokenizer/tokenize.json | 4 ++ .../camel/language/variable/variable.json | 3 ++ .../camel/language/header/HeaderLanguage.java | 6 +++ .../property/ExchangePropertyLanguage.java | 5 ++ .../camel/language/ref/RefLanguage.java | 7 +++ .../camel/language/simple/FileLanguage.java | 11 ++++ .../language/tokenizer/TokenizeLanguage.java | 11 ++++ .../language/variable/VariableLanguage.java | 6 +++ .../dsl/yaml/validator/TextBodyFlowTest.java | 51 +++++++++++++++++++ 109 files changed, 676 insertions(+), 52 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/bean.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/bean.json index 6f2191314ef8a..5cfc327da43e3 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/bean.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/bean.json @@ -29,6 +29,10 @@ "autowiredEnabled": { "index": 2, "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." }, "beanInfoCacheSize": { "index": 3, "kind": "property", "displayName": "Bean Info Cache Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Maximum cache size of internal cache for bean introspection. Setting a value of 0 or negative will disable the cache." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The first parameter of the method gets the body, converted to its type: a String parameter gets a Map or a POJO as its toString(), so marshal it first" }, + "producerOut": { "carriers": [ "unknown" ], "description": "What the method returns, also when it returns null. A void method leaves the body unchanged" } + }, "properties": { "beanName": { "index": 0, "kind": "path", "displayName": "Bean Name", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sets the name of the bean to invoke" }, "method": { "index": 1, "kind": "parameter", "displayName": "Method", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the name of the method to invoke on the bean" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/browse.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/browse.json index 42301919f4bae..26741290eef90 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/browse.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/browse.json @@ -30,6 +30,11 @@ "autowiredEnabled": { "index": 2, "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." }, "browseLimit": { "index": 3, "kind": "property", "displayName": "Browse Limit", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "Maximum number of messages to keep in memory available for browsing. Use 0 for unlimited." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the producer sent: the route runs on the same exchange, in the thread of the producer" }, + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, unless a route consumes from the same browse endpoint: it runs on the same exchange, so the body is the one that route ends with" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A name which can be any string to uniquely identify the endpoint" }, "bridgeErrorHandler": { "index": 1, "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." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/class.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/class.json index 211171c616b1c..27b67ef9d27e7 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/class.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/class.json @@ -29,6 +29,10 @@ "autowiredEnabled": { "index": 2, "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." }, "beanInfoCacheSize": { "index": 3, "kind": "property", "displayName": "Bean Info Cache Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Maximum cache size of internal cache for bean introspection. Setting a value of 0 or negative will disable the cache." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The first parameter of the method gets the body, converted to its type: a String parameter gets a Map or a POJO as its toString(), so marshal it first" }, + "producerOut": { "carriers": [ "unknown" ], "description": "What the method returns, also when it returns null. A void method leaves the body unchanged" } + }, "properties": { "beanName": { "index": 0, "kind": "path", "displayName": "Bean Name", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sets the name of the bean to invoke" }, "method": { "index": 1, "kind": "parameter", "displayName": "Method", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the name of the method to invoke on the bean" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/controlbus.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/controlbus.json index b079ee3b3ad6c..c50a568dc631d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/controlbus.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/controlbus.json @@ -27,6 +27,10 @@ "lazyStartProducer": { "index": 0, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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." }, "autowiredEnabled": { "index": 1, "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." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "command", "value": "language", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "The route actions do not read the body. The language command evaluates the body as its expression, as text" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "action", "value": "status", "carriers": [ "text", "unchanged" ] }, { "option": "action", "value": "stats", "carriers": [ "text", "unchanged" ] }, { "option": "command", "value": "language", "carriers": [ "unknown" ] }, { "option": "async", "value": "true", "carriers": [ "unchanged" ] } ], "description": "The status of the route for action=status, such as Started, and its statistics as XML for action=stats; the result of the expression for the language command. The other actions leave the body unchanged, as does async=true or a task that fails, which is only logged" } + }, "properties": { "command": { "index": 0, "kind": "path", "displayName": "Command", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "route", "language" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Command can be either route or language" }, "language": { "index": 1, "kind": "path", "displayName": "Language", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.spi.Language", "enum": [ "bean", "constant", "datasonnet", "exchangeProperty", "file", "groovy", "header", "hl7terser", "java", "joor", "jq", "jsonpath", "mvel", "ognl", "python", "ref", "simple", "spel", "tokenize", "xpath", "xquery", "xtokenize" ], "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to specify the name of a Language to use for evaluating the message body. If there is any result from the evaluation, then the result is put in the message body." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataformat.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataformat.json index 2f5cef8d00251..ce0269205d373 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataformat.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataformat.json @@ -27,6 +27,10 @@ "lazyStartProducer": { "index": 0, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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." }, "autowiredEnabled": { "index": 1, "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." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "unknown" ], "description": "The body the data format named in the path takes, as for the marshal and unmarshal EIPs" }, + "producerOut": { "carriers": [ "unknown" ], "description": "The body the data format named in the path gives, as for the marshal and unmarshal EIPs" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of data format" }, "operation": { "index": 1, "kind": "path", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "marshal", "unmarshal" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation to use either marshal or unmarshal" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataset-test.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataset-test.json index 2ff48ddf0665e..4fce48833c4fd 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataset-test.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataset-test.json @@ -29,6 +29,10 @@ "autowiredEnabled": { "index": 2, "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." }, "exchangeFormatter": { "index": 3, "kind": "property", "displayName": "Exchange Formatter", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExchangeFormatter", "deprecated": false, "autowired": true, "secret": false, "description": "To use a custom ExchangeFormatter to format the Exchange into a String suitable for logging." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "Each message is compared with the next body read at startup from the endpoint in the name. A mismatch fails the assertions of the endpoint, not the message" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of endpoint to lookup in the registry to use for polling messages used for testing" }, "anyOrder": { "index": 1, "kind": "parameter", "displayName": "Any Order", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the expected messages should arrive in the same order or can be in any order." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataset.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataset.json index 605527e92460f..ce8187b4f9f39 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataset.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataset.json @@ -33,6 +33,11 @@ "headers": { "CamelDataSetIndex": { "index": 0, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The dataset index", "constantName": "org.apache.camel.component.dataset.DataSetConstants#DATASET_INDEX" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unknown" ], "description": "The body the DataSet bean creates for each message: the defaultBody of a SimpleDataSet (the text world!<\/hello> unless set), the bodies of a ListDataSet in turn, or the text of a FileDataSet" }, + "producerIn": { "carriers": [ "any" ], "description": "Each message is compared with the body the DataSet creates for its index. A mismatch fails the assertions of the endpoint, not the message" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.dataset.DataSet", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of DataSet to lookup in the registry" }, "dataSetIndex": { "index": 1, "kind": "parameter", "displayName": "Data Set Index", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "strict", "lenient", "off" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "lenient", "description": "Controls the behaviour of the CamelDataSetIndex header. off (consumer) the header will not be set. strict (consumer) the header will be set. lenient (consumer) the header will be set. off (producer) the header value will not be verified, and will not be set if it is not present. strict (producer) the header value must be present and will be verified. lenient (producer) the header value will be verified if it is present, and will be set if it is not present." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dynamic-router-control.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dynamic-router-control.json index a57cadc2accb3..ae13eadb71f68 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dynamic-router-control.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dynamic-router-control.json @@ -37,6 +37,10 @@ "CamelDynamicRouterPredicateBean": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the bean in the registry that identifies the subscription predicate.", "constantName": "org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants#CONTROL_PREDICATE_BEAN" }, "CamelDynamicRouterExpressionLanguage": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The language for the predicate when supplied as a string.", "constantName": "org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants#CONTROL_EXPRESSION_LANGUAGE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "A DynamicRouterControlMessage, or the subscription in the options or the headers. For subscribe and update without a predicate or a predicateBean, the body must be the Predicate" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "controlAction", "value": "subscribe", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "controlAction", "value": "update", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "controlAction", "value": "unsubscribe", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "controlAction", "value": "list", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "controlAction", "value": "statistics", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "By the action: the id of the subscription for subscribe and update, true when unsubscribe removed it, and the subscriptions or their statistics as text for list and statistics. The CamelDynamicRouterControlAction header overrides the action" } + }, "properties": { "controlAction": { "index": 0, "kind": "path", "displayName": "Control Action", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "subscribe", "unsubscribe", "update", "list", "statistics" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Control action" }, "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/dynamic-router.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dynamic-router.json index 68b9b5dc6f5d8..9328124d78591 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dynamic-router.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dynamic-router.json @@ -27,6 +27,10 @@ "lazyStartProducer": { "index": 0, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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." }, "autowiredEnabled": { "index": 1, "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." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The message to route: the predicates of the subscriptions on the channel decide where it goes" }, + "producerOut": { "carriers": [ "unknown" ], "description": "The body the recipient ends with; with allMatch, the one of the last recipient unless an aggregationStrategy is set. When no subscription matches, a text that says so, with the body in the originalBody header" } + }, "properties": { "channel": { "index": 0, "kind": "path", "displayName": "Channel", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Channel for the Dynamic Router. For example, if the Dynamic Router URI is dynamic-router:\/\/test, then the channel is test. Channels are a way of keeping routing participants, their rules, and exchanges logically separate from the participants, rules, and exchanges on other channels. This can be seen as analogous to VLANs in networking." }, "aggregationStrategy": { "index": 1, "kind": "parameter", "displayName": "Aggregation Strategy", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.dynamicrouter.routing.DynamicRouterConfiguration", "configurationField": "configuration", "description": "Refers to an AggregationStrategy to be used to assemble the replies from the multicasts, into a single outgoing message from the Multicast. By default, Camel will use the last reply as the outgoing message. You can also use a POJO as the AggregationStrategy." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/event.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/event.json index ddac6dc0bb66d..4fa8339122c15 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/event.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/event.json @@ -40,6 +40,9 @@ "CamelEventRedeliveryAttempt": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The redelivery attempt number (for ExchangeRedelivery events)", "constantName": "org.apache.camel.component.camelevent.CamelEventConstants#HEADER_EVENT_REDELIVERY_ATTEMPT" }, "CamelEventBatchSize": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of events in a batch (only set when batchSize is configured)", "constantName": "org.apache.camel.component.camelevent.CamelEventConstants#HEADER_EVENT_BATCH_SIZE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo" ], "javaType": "org.apache.camel.spi.CamelEvent", "dependsOn": [ "batchSize" ], "description": "The event, such as a RouteStartedEvent or an ExchangeCompletedEvent. With a batchSize above 1, a List of the events" } + }, "properties": { "events": { "index": 0, "kind": "path", "displayName": "Events", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Comma-separated list of event types to subscribe to. Event types correspond to CamelEvent.Type enum values (case-insensitive), for example: RouteStarted, RouteStopped, ExchangeCompleted, ExchangeFailed. Wildcard patterns are supported using a suffix, for example: Route matches all route events, Exchange matches all exchange events, and matches all events." }, "async": { "index": 1, "kind": "parameter", "displayName": "Async", "group": "consumer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to process events asynchronously using a thread pool. When enabled, the event notifier thread is not blocked while the event exchange is processed. Use asyncPoolSize to control the maximum number of concurrent event processing threads." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/exec.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/exec.json index 06aea47ab0db6..633ae01e4b135 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/exec.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/exec.json @@ -44,6 +44,10 @@ "CamelExecUseStderrOnEmptyStdout": { "index": 8, "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Indicates that when stdout is empty, this component will populate the Camel Message Body with stderr. This behavior is disabled (false) by default. Requires allowControlHeaders=true on the exec endpoint or component (default is false since Camel 4.20).", "constantName": "org.apache.camel.component.exec.ExecBinding#EXEC_USE_STDERR_ON_EMPTY_STDOUT" }, "CamelExecCommandLogLevel": { "index": 9, "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Logging level to be used for commands during execution. The default value is DEBUG. Possible values are TRACE, DEBUG, INFO, WARN, ERROR or OFF (Values of LoggingLevel enum). Requires allowControlHeaders=true on the exec endpoint or component (default is false since Camel 4.20).", "constantName": "org.apache.camel.component.exec.ExecBinding#EXEC_COMMAND_LOG_LEVEL" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The standard input of the command, when the body converts to a stream: text, bytes, a stream or a file. Another body, or no body, runs the command without input" }, + "producerOut": { "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.exec.ExecResult", "dependsOn": [ "binding" ], "description": "The ExecResult, with the exit value and the standard error in headers. It converts to the text, bytes or stream of the standard output, of the outFile when set, or of the standard error with useStderrOnEmptyStdout" } + }, "properties": { "executable": { "index": 0, "kind": "path", "displayName": "Executable", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sets the executable to be executed. The executable must not be empty or null." }, "args": { "index": 1, "kind": "parameter", "displayName": "Args", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The arguments may be one or many whitespace-separated tokens." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/knative.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/knative.json index 4cd67395d5cb1..2570eea62af00 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/knative.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/knative.json @@ -59,6 +59,12 @@ "CamelCloudEventSubject": { "index": 6, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The subject of the event in the context of the event source.", "constantName": "org.apache.camel.component.knative.KnativeConstants#CLOUD_EVENT_SUBJECT" }, "CamelCloudEventTime": { "index": 7, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The time the event occurred. The producer uses the exchange creation time when not set.", "constantName": "org.apache.camel.component.knative.KnativeConstants#CLOUD_EVENT_TIME" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes", "null", "map", "list", "text", "value" ], "description": "The data of the event as a byte array, empty or null for an event without data. A structured event (Content-Type application\/cloudevents+json) gives its data field parsed from JSON: a Map, a List, text or a value" }, + "consumerReply": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "byOption": [ { "option": "reply", "value": "false", "carriers": [ "any" ] } ], "description": "The data of the reply, sent as bytes: text, bytes, a stream or a file; no body answers 204 No Content. A Map or a POJO fails: marshal it first. With reply=false the body is not sent" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data of the event: text, bytes, a stream or a file, sent as bytes. No body fails, and so does a Map or a POJO: marshal it first" }, + "producerOut": { "carriers": [ "bytes", "null" ], "description": "The body of the response, also for a message that expects no reply (InOnly): a byte array, null for a response without a body" } + }, "properties": { "type": { "index": 0, "kind": "path", "displayName": "Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.knative.spi.Knative.Type", "enum": [ "endpoint", "channel", "event" ], "deprecated": false, "autowired": false, "secret": false, "description": "The Knative resource type" }, "typeId": { "index": 1, "kind": "path", "displayName": "Type Id", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The identifier of the Knative resource" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json index fb260589ad386..caacbaaccad4a 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json @@ -32,6 +32,10 @@ "headers": { "CamelLanguageScript": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String or Expression", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The script to execute provided in the header. Takes precedence over script configured on the endpoint.", "constantName": "org.apache.camel.component.language.LanguageConstants#LANGUAGE_SCRIPT" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "unknown" ], "description": "The body as the language of the script reads it. The script is in the uri, the script option or a resource, or in the CamelLanguageScript header with allowTemplateFromHeader=true, and never in the body" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "transform", "value": "false", "carriers": [ "unchanged" ] }, { "option": "binary", "value": "true", "carriers": [ "stream" ] } ], "description": "The result of the script, as the language gives it. Unchanged with transform=false. With binary=true the content of the resource as a stream, which is not evaluated" } + }, "properties": { "languageName": { "index": 0, "kind": "path", "displayName": "Language Name", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "bean", "constant", "datasonnet", "exchangeProperty", "file", "groovy", "header", "hl7terser", "java", "joor", "jq", "js", "jsonpath", "mvel", "ognl", "python", "python3", "quickjs", "ref", "simple", "spel", "tokenize", "variable", "xpath", "xquery", "xtokenize" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sets the name of the language to use" }, "resourceUri": { "index": 1, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource, or a reference to lookup a bean in the Registry to use as the resource" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/once.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/once.json index 9d9a7c4b8c613..768303766ec43 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/once.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/once.json @@ -29,6 +29,9 @@ "delay": { "index": 2, "kind": "property", "displayName": "Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The number of milliseconds to wait before triggering. Use 0 or negative to fire as soon as possible. The default value is 1000." }, "languages": { "index": 3, "kind": "property", "displayName": "Languages", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether Camel languages are supported such as simple,groovy." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "dependsOn": [ "body" ], "description": "No body without the body option. The body option gives its text, the text of a file:, classpath: or http: resource, a Boolean for true or false, a number for a whole number, or with language:NAME: the result of the expression" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The logical name" }, "body": { "index": 1, "kind": "parameter", "displayName": "Body", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "The data to use as message body. You can externalize the data by using file: or classpath: as prefix and specify the location of the file." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ref.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ref.json index 2c8ab8073ccf7..09ec81acc2563 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ref.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ref.json @@ -28,6 +28,11 @@ "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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." }, "autowiredEnabled": { "index": 2, "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." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unknown" ], "description": "The body the consumer of the endpoint in the registry gives" }, + "producerIn": { "carriers": [ "unknown" ], "description": "The bodies the producer of the endpoint in the registry takes" }, + "producerOut": { "carriers": [ "unknown" ], "description": "The body the producer of the endpoint in the registry leaves" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of endpoint to lookup in the registry." }, "bridgeErrorHandler": { "index": 1, "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." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-api.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-api.json index 0b170f11f2ec8..9eb5e7a75b7c9 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-api.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/rest-api.json @@ -28,6 +28,10 @@ "consumerComponentName": { "index": 1, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The Camel Rest API component to use for the consumer REST transport, such as jetty, servlet, undertow. If no component has been explicitly configured, then Camel will lookup if there is a Camel component that integrates with the Rest DSL, or if a org.apache.camel.spi.RestApiConsumerFactory is registered in the registry. If either one is found, then that is being used." }, "autowiredEnabled": { "index": 2, "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." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "dependsOn": [ "consumerComponentName" ], "description": "The GET request for the API document, which has no body" }, + "consumerReply": { "carriers": [ "null", "text", "bytes", "stream" ], "dependsOn": [ "consumerComponentName" ], "description": "The API document the route of the REST DSL sets: the OpenAPI document as bytes, JSON unless the path ends with .yaml or the Accept header asks for YAML" } + }, "properties": { "path": { "index": 0, "kind": "path", "displayName": "Path", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The base path" }, "apiComponentName": { "index": 1, "kind": "parameter", "displayName": "Api Component Name", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The Camel Rest API component to use for generating the API of the REST services, such as openapi." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/saga.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/saga.json index 98e1f751e6e2b..3249b3bbba388 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/saga.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/saga.json @@ -30,6 +30,10 @@ "headers": { "Long-Running-Action": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The long running action", "constantName": "org.apache.camel.component.saga.SagaConstants#SAGA_LONG_RUNNING_ACTION" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: the saga service calls the completion or compensation endpoints with messages of its own" } + }, "properties": { "action": { "index": 0, "kind": "path", "displayName": "Action", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.saga.SagaEndpoint.SagaEndpointAction", "enum": [ "COMPLETE", "COMPENSATE" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Action to execute (complete or compensate)" }, "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/stream.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/stream.json index 260f2172b9991..96e7923834b0f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/stream.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/stream.json @@ -32,6 +32,11 @@ "CamelStreamIndex": { "index": 0, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The index", "constantName": "org.apache.camel.component.stream.StreamConstants#STREAM_INDEX" }, "CamelStreamComplete": { "index": 1, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Is complete", "constantName": "org.apache.camel.component.stream.StreamConstants#STREAM_COMPLETE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "groupLines" ], "byOption": [ { "option": "readLine", "value": "false", "carriers": [ "bytes" ], "javaType": "byte[]" } ], "description": "Each line of the stream as text. With groupLines, a List of the lines; with readLine=false, all the bytes of the stream" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "description": "Text in the encoding, or bytes, a stream or a file as bytes, followed by a new line; no body writes nothing. A Map or a POJO is written as its toString() and a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "kind": { "index": 0, "kind": "path", "displayName": "Kind", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "in", "out", "err", "header", "file", "http" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Kind of stream to use such as System.in, System.out, a file, or a http url." }, "encoding": { "index": 1, "kind": "parameter", "displayName": "Encoding", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "You can configure the encoding (is a charset name) to use text-based streams (for example, message body is a String object). If not provided, Camel uses the JVM default Charset." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/stub.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/stub.json index 889e38765279c..2aeb9bd3b00d7 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/stub.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/stub.json @@ -38,6 +38,11 @@ "shadow": { "index": 10, "kind": "property", "displayName": "Shadow", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If shadow is enabled then the stub component will register a shadow endpoint with the actual uri that refers to the stub endpoint, meaning you can lookup the endpoint via both stub:kafka:cheese and kafka:cheese." }, "shadowPattern": { "index": 11, "kind": "property", "displayName": "Shadow Pattern", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "If shadow is enabled then this pattern can be used to filter which components to match. Multiple patterns can be separated by comma." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the producer sent" }, + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unknown" ], "description": "Unchanged when no route consumes from the stub endpoint, or for a message that expects no reply (InOnly). A message that expects one (InOut) waits for the body the stub route ends with" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of queue" }, "size": { "index": 1, "kind": "parameter", "displayName": "Size", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The maximum capacity of the SEDA queue (i.e., the number of messages it can hold). Will by default use the queueSize set on the SEDA component." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/validator.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/validator.json index 8f36134aa8181..e6a59c38577e3 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/validator.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/validator.json @@ -28,6 +28,10 @@ "autowiredEnabled": { "index": 1, "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." }, "resourceResolverFactory": { "index": 2, "kind": "property", "displayName": "Resource Resolver Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.validator.ValidatorResourceResolverFactory", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom LSResourceResolver which depends on a dynamic endpoint resource URI" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "headerName" ], "byOption": [ { "option": "failOnNullBody", "value": "false", "carriers": [ "null", "text", "bytes", "stream", "file", "pojo" ] } ], "description": "The XML to validate: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source. A Map, a List or no body fails; with headerName the header is validated instead" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: XML that is not valid fails with a SchemaValidationException" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "URL to a local resource on the classpath, or a reference to lookup a bean in the Registry, or a full URL to a remote resource or resource on the file system which contains the XSD to validate against." }, "failOnNullBody": { "index": 1, "kind": "parameter", "displayName": "Fail On Null Body", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to fail if no body exists." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/wasm.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/wasm.json index 5bf98acf9c617..be436686faa88 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/wasm.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/wasm.json @@ -31,6 +31,10 @@ "CamelWasmExitCode": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The exit code of the module: 0 when it returned from its _start function, otherwise the value it passed to proc_exit. Not set when the module trapped, timed out or exceeded maxOutputSize.", "constantName": "org.apache.camel.wasm.Wasm$Headers#EXIT_CODE" }, "CamelWasmStderr": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "What the module wrote to its standard error, decoded as UTF-8. Not set when the module wrote nothing or timed out.", "constantName": "org.apache.camel.wasm.Wasm$Headers#STDERR" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "description": "The standard input of the module: text, bytes, a stream or a file; no body is an empty input. A Map, a List or a POJO fails: marshal it first" }, + "producerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The standard output of the module, with the exit code in the CamelWasmExitCode header" } + }, "properties": { "module": { "index": 0, "kind": "path", "displayName": "Module", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The WASI Preview 1 command module to run, as a resource: by default from the classpath, or with a prefix such as classpath:, file: or http:" }, "args": { "index": 1, "kind": "parameter", "displayName": "Args", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.wasm.WasmConfiguration", "configurationField": "configuration", "description": "The command line arguments passed to the module, separated by whitespace. Use double quotes around an argument that contains whitespace. The module receives the file name of the module (for example upper.wasm, without scheme, directories or query) as argument zero, followed by these arguments. The arguments are fixed by the route: they cannot be set from message headers." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json index 24a36d9612bf2..28cd2c8d05999 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xslt-saxon.json @@ -43,6 +43,10 @@ "CamelXsltStylesheet": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" }, "CamelXsltFileName": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The XSLT file name", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source", "useJsonBody" ], "byOption": [ { "option": "failOnNullBody", "value": "false", "carriers": [ "null", "text", "bytes", "stream", "file", "pojo" ] } ], "description": "The XML to transform: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source; JSON text with useJsonBody. A Map, a List or no body fails" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultHandlerFactory" ], "byOption": [ { "option": "output", "value": "bytes", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "output", "value": "DOM", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document" }, { "option": "output", "value": "file", "carriers": [ "file" ], "javaType": "java.io.File" } ], "description": "The result of the transformation" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Path to the template. The following is supported by the default URIResolver. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod" }, "allowStAX": { "index": 1, "kind": "parameter", "displayName": "Allow StAX", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow using StAX as the javax.xml.transform.Source. You can enable this if the XSLT library supports StAX such as the Saxon library (camel-saxon). The Xalan library (default in JVM) does not support StAXSource." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/browse-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/browse-component.adoc index 38f0524389619..cb5dee59edc9d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/browse-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/browse-component.adoc @@ -85,7 +85,7 @@ public void inspectReceivedOrders() { // then we can inspect the list of received exchanges from Java for (Exchange exchange : exchanges) { - String payload = exchange.getIn().getBody(); + String payload = exchange.getIn().getBody(String.class); // do something with payload } } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dataset-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dataset-component.adoc index aa41b69fe2740..42b8a9ef640eb 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dataset-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dataset-component.adoc @@ -77,8 +77,8 @@ data set, and provides some useful features to derived classes. |=== |Property |Type |Default |Description -|`defaultHeaders` |`Map` |`null` | Specify the default message body. -For `SimpleDataSet` it is a constant payload; though if you want to create custom payloads per message, +|`defaultHeaders` |`Map` |`null` | Specify the default message headers. +They are the same for each message; though if you want to create custom headers per message, create your own derivation of `DataSetSupport`. |`outputTransformer` |`org.apache.camel.Processor` |null | diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/exec-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/exec-component.adoc index 64ca34aae1f84..31f392b31036e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/exec-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/exec-component.adoc @@ -97,7 +97,7 @@ executable via its standard input (`stdin`). After execution, http://camel.apache.org/exchange.html[the message body] is the result of the execution. -That is, an `org.apache.camel.components.exec.ExecResult` instance containing the +That is, an `org.apache.camel.component.exec.ExecResult` instance containing the `stdout`, `stderr`, _exit value_, and the _out file_. This component supports the following `ExecResult` http://camel.apache.org/type-converter.html[type converters] @@ -305,7 +305,7 @@ Java:: + [source,java] ---- -// When outFile is specified, the body is the content of that file (as InputStream) +// When outFile is specified, the ExecResult in the body converts to the content of that file from("direct:exec") .to("exec:ant.bat?args=-f CamelExecBuildFile.xml -l CamelExecOutFile.txt&outFile=CamelExecOutFile.txt") .to("log:result"); @@ -315,7 +315,7 @@ XML:: + [source,xml] ---- - + @@ -327,7 +327,7 @@ YAML:: + [source,yaml] ---- -# When outFile is specified, the body is the content of that file (as InputStream) +# When outFile is specified, the ExecResult in the body converts to the content of that file - route: from: uri: direct:exec diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/language-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/language-component.adoc index 435519cea521f..e7753b75dc569 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/language-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/language-component.adoc @@ -131,7 +131,7 @@ Java:: [source,java] ---- from("direct:double") - .to("language:groovy:${body} * 2}"); + .to("language:groovy:body * 2"); ---- XML:: @@ -140,7 +140,7 @@ XML:: ---- - + ---- @@ -153,25 +153,26 @@ YAML:: uri: direct:double steps: - to: - uri: "language:groovy:${body} * 2}" + uri: "language:groovy:body * 2" ---- ==== -You can also provide the script as a header as shown below. Here we use +You can also provide the script as a header as shown below, when the endpoint +has `allowTemplateFromHeader=true`. Here we use xref:languages:xpath-language.adoc[XPath] language to extract the text from the `` tag. ._Java-only: providing the script as a message header_ [source,java] ---- -Object out = producer.requestBodyAndHeader("language:xpath", "Hello World", Exchange.LANGUAGE_SCRIPT, "/foo/text()"); +Object out = producer.requestBodyAndHeader("language:xpath?allowTemplateFromHeader=true", "Hello World", Exchange.LANGUAGE_SCRIPT, "/foo/text()"); assertEquals("Hello World", out); ---- == Loading scripts from resources You can specify a resource uri for a script to load in either the -endpoint uri, or in the `Exchange.LANGUAGE_SCRIPT` header. +endpoint uri, or in the `Exchange.LANGUAGE_SCRIPT` header (with `allowTemplateFromHeader=true`). The uri must start with one of the following schemes: `file:`, `classpath:`, or `http:` [tabs] diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/once-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/once-component.adoc index da5b467808ba0..0587dcfad165f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/once-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/once-component.adoc @@ -227,7 +227,7 @@ Java:: + [source,java] ---- -from("once:foo?body=file.data.json&delay=-1").to("bean:myBean?method=someMethodName"); +from("once:foo?body=file:data.json&delay=-1").to("bean:myBean?method=someMethodName"); ---- XML:: @@ -235,7 +235,7 @@ XML:: [source,xml] ---- - + ---- @@ -248,7 +248,7 @@ YAML:: from: uri: once:foo parameters: - body: file.data.json + body: file:data.json delay: -1 steps: - to: diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/stream-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/stream-component.adoc index 706f831209ba6..829eff3eec51c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/stream-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/stream-component.adoc @@ -56,15 +56,14 @@ include::partial$component-endpoint-headers.adoc[] === Message content -The Stream component supports either `String` or `byte[]` for writing -to streams. Just add either `String` or `byte[]` content to the -`message.in.body`. Messages sent to the *stream:* producer in binary -mode are not followed by the newline character (as opposed to the -`String` messages). Message with `null` body will not be appended to the -output stream. + +The Stream component writes text, bytes, a stream or a file: text in the +`encoding`, and the others as bytes, each followed by a new line unless +`appendNewLine` is `false`. A message with a `null` body writes nothing. +Another body, such as a `Map`, is written as its `toString()`, so marshal it +first. + The special `stream:header` URI is used for custom output streams. Just add a `java.io.OutputStream` object to `message.in.header` in the key -`header`. + +`stream`. + See samples for an example. == Examples diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/bean.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/bean.json index af64fdd9106f3..2324355c75a40 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/bean.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/bean.json @@ -15,6 +15,10 @@ "modelName": "method", "modelJavaType": "org.apache.camel.model.language.MethodCallExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The first parameter of the method gets the body, converted to its type" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the method returns; null for a void method" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "ref": { "index": 1, "kind": "attribute", "displayName": "Ref", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Reference to an existing bean (bean id) to lookup in the registry." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/exchangeProperty.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/exchangeProperty.json index 30237a2819e4b..2dc10609366d5 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/exchangeProperty.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/exchangeProperty.json @@ -15,6 +15,9 @@ "modelName": "exchangeProperty", "modelJavaType": "org.apache.camel.model.language.ExchangePropertyExpression" }, + "bodyTypes": { + "expressionOut": { "carriers": [ "unknown" ], "description": "The value of the exchange property as it is, null when there is none" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/file.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/file.json index 1e33e6ba029e5..f74414f152834 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/file.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/file.json @@ -15,6 +15,10 @@ "modelName": "simple", "modelJavaType": "org.apache.camel.model.language.SimpleExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, for ${body}: the file functions read the headers the file consumers set" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "A text with functions gives text, such as a file name. A single function gives its value as it is: ${file:size}, ${file:length} and ${file:modified} a Long, ${file:absolute} a Boolean, the other file functions text, and null without the headers of a file" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/header.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/header.json index d295131eba167..a1e7e1255788b 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/header.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/header.json @@ -15,6 +15,9 @@ "modelName": "header", "modelJavaType": "org.apache.camel.model.language.HeaderExpression" }, + "bodyTypes": { + "expressionOut": { "carriers": [ "unknown" ], "description": "The value of the header as it is, null when there is none. A missing header falls back to the exchange property of that name" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jq.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jq.json index 781f11d2f1794..64157b0b27cfc 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jq.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/jq.json @@ -16,7 +16,7 @@ "modelJavaType": "org.apache.camel.model.language.JqExpression" }, "bodyTypes": { - "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "format": "json", "description": "JSON as text, bytes, a stream or a file, or a Map" }, + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "format": "json", "dependsOn": [ "source" ], "description": "JSON as text, bytes, a stream or a file, or a Map" }, "expressionOut": { "carriers": [ "pojo", "list", "null" ], "dependsOn": [ "resultType" ], "description": "A JsonNode; a List of JsonNode when the filter gives several, null when it gives none" } }, "properties": { diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ref.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ref.json index dcd78c00bc00f..80776995a904c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ref.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ref.json @@ -15,6 +15,10 @@ "modelName": "ref", "modelJavaType": "org.apache.camel.model.language.RefExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "unknown" ], "description": "As the expression or the predicate in the registry reads it" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the expression in the registry returns; a Boolean for a predicate" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/tokenize.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/tokenize.json index 401f57fd5eba4..16dbce3bee17e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/tokenize.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/tokenize.json @@ -15,6 +15,10 @@ "modelName": "tokenize", "modelJavaType": "org.apache.camel.model.language.TokenizerExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "source" ], "description": "Text as text, bytes, a stream or a file. Another body is tokenized as its toString(), and fails with endToken or xml: marshal it first" }, + "expressionOut": { "carriers": [ "iterator" ], "description": "An Iterator of the tokens as text, read once: in setBody the body is the Iterator, for the Split EIP to walk. With group, each N tokens are joined into one text" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "token": { "index": 1, "kind": "attribute", "displayName": "Token", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The (start) token to use as tokenizer, for example you can use the new line token. You can use simple language as the token to support dynamic tokens." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/variable.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/variable.json index 73b49502e5e8f..1700bbf3b51f6 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/variable.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/variable.json @@ -15,6 +15,9 @@ "modelName": "variable", "modelJavaType": "org.apache.camel.model.language.VariableExpression" }, + "bodyTypes": { + "expressionOut": { "carriers": [ "unknown" ], "description": "The value of the variable as it is, null when there is none. A global: or route: prefix reads a global or a route variable" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xpath.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xpath.json index e7e50b9357a1e..052b58d798f56 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xpath.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xpath.json @@ -16,7 +16,7 @@ "modelJavaType": "org.apache.camel.model.language.XPathExpression" }, "bodyTypes": { - "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "XML as text, bytes, a stream or a file, or a DOM" }, + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], "description": "XML as text, bytes, a stream or a file, or a DOM" }, "expressionOut": { "carriers": [ "pojo" ], "javaType": "org.w3c.dom.NodeList", "dependsOn": [ "resultType" ], "byOption": [ { "option": "resultQName", "value": "STRING", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "resultQName", "value": "NUMBER", "carriers": [ "value" ], "javaType": "java.lang.Double" }, { "option": "resultQName", "value": "BOOLEAN", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "resultQName", "value": "NODE", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Node" } ], "description": "The nodes the expression selects" } }, "properties": { diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xtokenize.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xtokenize.json index d9a63ad907f51..b065c75e73731 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xtokenize.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xtokenize.json @@ -15,6 +15,10 @@ "modelName": "xtokenize", "modelJavaType": "org.apache.camel.model.language.XMLTokenizerExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], "description": "XML as text, bytes, a stream or a file, or a DOM" }, + "expressionOut": { "carriers": [ "iterator" ], "description": "An Iterator of the elements the path matches as XML text, read once; mode t gives their text. With group, each N elements are joined into one text" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/component/bean/bean.json b/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/component/bean/bean.json index 6f2191314ef8a..5cfc327da43e3 100644 --- a/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/component/bean/bean.json +++ b/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/component/bean/bean.json @@ -29,6 +29,10 @@ "autowiredEnabled": { "index": 2, "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." }, "beanInfoCacheSize": { "index": 3, "kind": "property", "displayName": "Bean Info Cache Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Maximum cache size of internal cache for bean introspection. Setting a value of 0 or negative will disable the cache." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The first parameter of the method gets the body, converted to its type: a String parameter gets a Map or a POJO as its toString(), so marshal it first" }, + "producerOut": { "carriers": [ "unknown" ], "description": "What the method returns, also when it returns null. A void method leaves the body unchanged" } + }, "properties": { "beanName": { "index": 0, "kind": "path", "displayName": "Bean Name", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sets the name of the bean to invoke" }, "method": { "index": 1, "kind": "parameter", "displayName": "Method", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the name of the method to invoke on the bean" }, diff --git a/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/component/beanclass/class.json b/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/component/beanclass/class.json index 211171c616b1c..27b67ef9d27e7 100644 --- a/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/component/beanclass/class.json +++ b/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/component/beanclass/class.json @@ -29,6 +29,10 @@ "autowiredEnabled": { "index": 2, "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." }, "beanInfoCacheSize": { "index": 3, "kind": "property", "displayName": "Bean Info Cache Size", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Maximum cache size of internal cache for bean introspection. Setting a value of 0 or negative will disable the cache." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The first parameter of the method gets the body, converted to its type: a String parameter gets a Map or a POJO as its toString(), so marshal it first" }, + "producerOut": { "carriers": [ "unknown" ], "description": "What the method returns, also when it returns null. A void method leaves the body unchanged" } + }, "properties": { "beanName": { "index": 0, "kind": "path", "displayName": "Bean Name", "group": "common", "label": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sets the name of the bean to invoke" }, "method": { "index": 1, "kind": "parameter", "displayName": "Method", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the name of the method to invoke on the bean" }, diff --git a/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/language/bean/bean.json b/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/language/bean/bean.json index af64fdd9106f3..2324355c75a40 100644 --- a/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/language/bean/bean.json +++ b/components/camel-bean/src/generated/resources/META-INF/org/apache/camel/language/bean/bean.json @@ -15,6 +15,10 @@ "modelName": "method", "modelJavaType": "org.apache.camel.model.language.MethodCallExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The first parameter of the method gets the body, converted to its type" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the method returns; null for a void method" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "ref": { "index": 1, "kind": "attribute", "displayName": "Ref", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Reference to an existing bean (bean id) to lookup in the registry." }, diff --git a/components/camel-bean/src/main/java/org/apache/camel/component/bean/BeanEndpoint.java b/components/camel-bean/src/main/java/org/apache/camel/component/bean/BeanEndpoint.java index 5817138bf2f9d..be382ee6411c1 100644 --- a/components/camel-bean/src/main/java/org/apache/camel/component/bean/BeanEndpoint.java +++ b/components/camel-bean/src/main/java/org/apache/camel/component/bean/BeanEndpoint.java @@ -25,6 +25,9 @@ import org.apache.camel.ExchangePattern; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -37,6 +40,13 @@ */ @UriEndpoint(firstVersion = "1.0.0", scheme = "bean", title = "Bean", syntax = "bean:beanName", producerOnly = true, remote = false, category = { Category.CORE, Category.SCRIPT }) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The first parameter of the method gets the body, converted to its type: a" + + " String parameter gets a Map or a POJO as its toString(), so marshal it" + + " first"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + description = "What the method returns, also when it returns null. A void method leaves" + + " the body unchanged")) public class BeanEndpoint extends DefaultEndpoint { private transient BeanHolder beanHolder; private transient BeanProcessor processor; diff --git a/components/camel-bean/src/main/java/org/apache/camel/component/beanclass/ClassEndpoint.java b/components/camel-bean/src/main/java/org/apache/camel/component/beanclass/ClassEndpoint.java index f00b922d4ef76..0983f49a4d083 100644 --- a/components/camel-bean/src/main/java/org/apache/camel/component/beanclass/ClassEndpoint.java +++ b/components/camel-bean/src/main/java/org/apache/camel/component/beanclass/ClassEndpoint.java @@ -19,6 +19,9 @@ import org.apache.camel.Category; import org.apache.camel.Component; import org.apache.camel.component.bean.BeanEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; /** @@ -26,6 +29,13 @@ */ @UriEndpoint(firstVersion = "2.4.0", scheme = "class", title = "Class", syntax = "class:beanName", producerOnly = true, remote = false, category = { Category.CORE, Category.SCRIPT }) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The first parameter of the method gets the body, converted to its type: a" + + " String parameter gets a Map or a POJO as its toString(), so marshal it" + + " first"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + description = "What the method returns, also when it returns null. A void method leaves" + + " the body unchanged")) public class ClassEndpoint extends BeanEndpoint { public ClassEndpoint(String endpointUri, Component component) { diff --git a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java index b87aa0b53025d..ef566d0bc63e5 100644 --- a/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java +++ b/components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanLanguage.java @@ -35,6 +35,9 @@ import org.apache.camel.component.bean.MethodNotFoundException; import org.apache.camel.component.bean.ParameterMappingStrategy; import org.apache.camel.component.bean.ParameterMappingStrategyHelper; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Language; import org.apache.camel.spi.PropertyConfigurer; import org.apache.camel.spi.ScriptingLanguage; @@ -57,6 +60,9 @@ * As of Camel 1.5 the bean language also supports invoking a provided bean by its classname or the bean itself. */ @org.apache.camel.spi.annotations.Language("bean") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "The first parameter of the method gets the body, converted to its type"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, description = "What the method returns; null for a void method")) public class BeanLanguage extends TypedLanguageSupport implements ScriptingLanguage, PropertyConfigurer, StaticService { public static final String LANGUAGE = "bean"; diff --git a/components/camel-browse/src/generated/resources/META-INF/org/apache/camel/component/browse/browse.json b/components/camel-browse/src/generated/resources/META-INF/org/apache/camel/component/browse/browse.json index 42301919f4bae..26741290eef90 100644 --- a/components/camel-browse/src/generated/resources/META-INF/org/apache/camel/component/browse/browse.json +++ b/components/camel-browse/src/generated/resources/META-INF/org/apache/camel/component/browse/browse.json @@ -30,6 +30,11 @@ "autowiredEnabled": { "index": 2, "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." }, "browseLimit": { "index": 3, "kind": "property", "displayName": "Browse Limit", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "Maximum number of messages to keep in memory available for browsing. Use 0 for unlimited." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the producer sent: the route runs on the same exchange, in the thread of the producer" }, + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, unless a route consumes from the same browse endpoint: it runs on the same exchange, so the body is the one that route ends with" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A name which can be any string to uniquely identify the endpoint" }, "bridgeErrorHandler": { "index": 1, "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." }, diff --git a/components/camel-browse/src/main/docs/browse-component.adoc b/components/camel-browse/src/main/docs/browse-component.adoc index 38f0524389619..cb5dee59edc9d 100644 --- a/components/camel-browse/src/main/docs/browse-component.adoc +++ b/components/camel-browse/src/main/docs/browse-component.adoc @@ -85,7 +85,7 @@ public void inspectReceivedOrders() { // then we can inspect the list of received exchanges from Java for (Exchange exchange : exchanges) { - String payload = exchange.getIn().getBody(); + String payload = exchange.getIn().getBody(String.class); // do something with payload } } diff --git a/components/camel-browse/src/main/java/org/apache/camel/component/browse/BrowseEndpoint.java b/components/camel-browse/src/main/java/org/apache/camel/component/browse/BrowseEndpoint.java index 35e842ba0eee4..d76af504e63e2 100644 --- a/components/camel-browse/src/main/java/org/apache/camel/component/browse/BrowseEndpoint.java +++ b/components/camel-browse/src/main/java/org/apache/camel/component/browse/BrowseEndpoint.java @@ -28,6 +28,9 @@ import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.BrowsableEndpoint; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -45,6 +48,13 @@ */ @UriEndpoint(firstVersion = "1.3.0", scheme = "browse", title = "Browse", syntax = "browse:name", remote = false, internal = true, category = { Category.CORE, Category.MONITORING }) +@BodyTypes(consumerOut = @BodyType(value = Carrier.UNCHANGED, + description = "The body the producer sent: the route runs on the same exchange, in the" + + " thread of the producer"), + producerIn = @BodyType(Carrier.ANY), + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged, unless a route consumes from the same browse endpoint: it runs on" + + " the same exchange, so the body is the one that route ends with")) public class BrowseEndpoint extends DefaultEndpoint implements BrowsableEndpoint { @UriPath(description = "A name which can be any string to uniquely identify the endpoint") diff --git a/components/camel-controlbus/src/generated/resources/META-INF/org/apache/camel/component/controlbus/controlbus.json b/components/camel-controlbus/src/generated/resources/META-INF/org/apache/camel/component/controlbus/controlbus.json index b079ee3b3ad6c..c50a568dc631d 100644 --- a/components/camel-controlbus/src/generated/resources/META-INF/org/apache/camel/component/controlbus/controlbus.json +++ b/components/camel-controlbus/src/generated/resources/META-INF/org/apache/camel/component/controlbus/controlbus.json @@ -27,6 +27,10 @@ "lazyStartProducer": { "index": 0, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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." }, "autowiredEnabled": { "index": 1, "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." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "command", "value": "language", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "The route actions do not read the body. The language command evaluates the body as its expression, as text" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "action", "value": "status", "carriers": [ "text", "unchanged" ] }, { "option": "action", "value": "stats", "carriers": [ "text", "unchanged" ] }, { "option": "command", "value": "language", "carriers": [ "unknown" ] }, { "option": "async", "value": "true", "carriers": [ "unchanged" ] } ], "description": "The status of the route for action=status, such as Started, and its statistics as XML for action=stats; the result of the expression for the language command. The other actions leave the body unchanged, as does async=true or a task that fails, which is only logged" } + }, "properties": { "command": { "index": 0, "kind": "path", "displayName": "Command", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "route", "language" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Command can be either route or language" }, "language": { "index": 1, "kind": "path", "displayName": "Language", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.spi.Language", "enum": [ "bean", "constant", "datasonnet", "exchangeProperty", "file", "groovy", "header", "hl7terser", "java", "joor", "jq", "jsonpath", "mvel", "ognl", "python", "ref", "simple", "spel", "tokenize", "xpath", "xquery", "xtokenize" ], "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to specify the name of a Language to use for evaluating the message body. If there is any result from the evaluation, then the result is put in the message body." }, diff --git a/components/camel-controlbus/src/main/java/org/apache/camel/component/controlbus/ControlBusEndpoint.java b/components/camel-controlbus/src/main/java/org/apache/camel/component/controlbus/ControlBusEndpoint.java index 07b0af743dc84..9991e90109df0 100644 --- a/components/camel-controlbus/src/main/java/org/apache/camel/component/controlbus/ControlBusEndpoint.java +++ b/components/camel-controlbus/src/main/java/org/apache/camel/component/controlbus/ControlBusEndpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.CamelLogger; import org.apache.camel.spi.Language; import org.apache.camel.spi.Metadata; @@ -39,6 +42,25 @@ */ @UriEndpoint(firstVersion = "2.11.0", scheme = "controlbus", title = "Control Bus", syntax = "controlbus:command:language", remote = false, producerOnly = true, category = { Category.CORE, Category.MONITORING }) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + byOption = @BodyType.When(option = "command", value = "language", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }), + description = "The route actions do not read the body. The language command evaluates the" + + " body as its expression, as text"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + byOption = { + @BodyType.When(option = "action", value = "status", + carriers = { Carrier.TEXT, Carrier.UNCHANGED }), + @BodyType.When(option = "action", value = "stats", + carriers = { Carrier.TEXT, Carrier.UNCHANGED }), + @BodyType.When(option = "command", value = "language", carriers = Carrier.UNKNOWN), + @BodyType.When(option = "async", value = "true", carriers = Carrier.UNCHANGED) }, + description = "The status of the route for action=status, such as Started, and its" + + " statistics as XML for action=stats; the result of the expression for the" + + " language command. The other actions leave the body unchanged, as does" + + " async=true or a task that fails, which is only logged")) public class ControlBusEndpoint extends DefaultEndpoint { @UriPath(description = "Command can be either route or language", enums = "route,language") diff --git a/components/camel-dataformat/src/generated/resources/META-INF/org/apache/camel/component/dataformat/dataformat.json b/components/camel-dataformat/src/generated/resources/META-INF/org/apache/camel/component/dataformat/dataformat.json index 2f5cef8d00251..ce0269205d373 100644 --- a/components/camel-dataformat/src/generated/resources/META-INF/org/apache/camel/component/dataformat/dataformat.json +++ b/components/camel-dataformat/src/generated/resources/META-INF/org/apache/camel/component/dataformat/dataformat.json @@ -27,6 +27,10 @@ "lazyStartProducer": { "index": 0, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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." }, "autowiredEnabled": { "index": 1, "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." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "unknown" ], "description": "The body the data format named in the path takes, as for the marshal and unmarshal EIPs" }, + "producerOut": { "carriers": [ "unknown" ], "description": "The body the data format named in the path gives, as for the marshal and unmarshal EIPs" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of data format" }, "operation": { "index": 1, "kind": "path", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "marshal", "unmarshal" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation to use either marshal or unmarshal" }, diff --git a/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatEndpoint.java b/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatEndpoint.java index 45d03fc6f3b98..6e99495a687db 100644 --- a/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatEndpoint.java +++ b/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -40,6 +43,12 @@ @UriEndpoint(firstVersion = "2.12.0", scheme = "dataformat", title = "Data Format", syntax = "dataformat:name:operation", remote = false, producerOnly = true, category = { Category.CORE, Category.TRANSFORMATION }, lenientProperties = true) +@BodyTypes(producerIn = @BodyType(value = Carrier.UNKNOWN, + description = "The body the data format named in the path takes, as for the marshal and" + + " unmarshal EIPs"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + description = "The body the data format named in the path gives, as for the marshal and" + + " unmarshal EIPs")) public class DataFormatEndpoint extends DefaultEndpoint { private AsyncProcessor processor; diff --git a/components/camel-dataset/src/generated/resources/META-INF/org/apache/camel/component/dataset/dataset-test.json b/components/camel-dataset/src/generated/resources/META-INF/org/apache/camel/component/dataset/dataset-test.json index 2ff48ddf0665e..4fce48833c4fd 100644 --- a/components/camel-dataset/src/generated/resources/META-INF/org/apache/camel/component/dataset/dataset-test.json +++ b/components/camel-dataset/src/generated/resources/META-INF/org/apache/camel/component/dataset/dataset-test.json @@ -29,6 +29,10 @@ "autowiredEnabled": { "index": 2, "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." }, "exchangeFormatter": { "index": 3, "kind": "property", "displayName": "Exchange Formatter", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExchangeFormatter", "deprecated": false, "autowired": true, "secret": false, "description": "To use a custom ExchangeFormatter to format the Exchange into a String suitable for logging." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "Each message is compared with the next body read at startup from the endpoint in the name. A mismatch fails the assertions of the endpoint, not the message" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of endpoint to lookup in the registry to use for polling messages used for testing" }, "anyOrder": { "index": 1, "kind": "parameter", "displayName": "Any Order", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the expected messages should arrive in the same order or can be in any order." }, diff --git a/components/camel-dataset/src/generated/resources/META-INF/org/apache/camel/component/dataset/dataset.json b/components/camel-dataset/src/generated/resources/META-INF/org/apache/camel/component/dataset/dataset.json index 605527e92460f..ce8187b4f9f39 100644 --- a/components/camel-dataset/src/generated/resources/META-INF/org/apache/camel/component/dataset/dataset.json +++ b/components/camel-dataset/src/generated/resources/META-INF/org/apache/camel/component/dataset/dataset.json @@ -33,6 +33,11 @@ "headers": { "CamelDataSetIndex": { "index": 0, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The dataset index", "constantName": "org.apache.camel.component.dataset.DataSetConstants#DATASET_INDEX" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unknown" ], "description": "The body the DataSet bean creates for each message: the defaultBody of a SimpleDataSet (the text world!<\/hello> unless set), the bodies of a ListDataSet in turn, or the text of a FileDataSet" }, + "producerIn": { "carriers": [ "any" ], "description": "Each message is compared with the body the DataSet creates for its index. A mismatch fails the assertions of the endpoint, not the message" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "object", "javaType": "org.apache.camel.component.dataset.DataSet", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of DataSet to lookup in the registry" }, "dataSetIndex": { "index": 1, "kind": "parameter", "displayName": "Data Set Index", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "strict", "lenient", "off" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "lenient", "description": "Controls the behaviour of the CamelDataSetIndex header. off (consumer) the header will not be set. strict (consumer) the header will be set. lenient (consumer) the header will be set. off (producer) the header value will not be verified, and will not be set if it is not present. strict (producer) the header value must be present and will be verified. lenient (producer) the header value will be verified if it is present, and will be set if it is not present." }, diff --git a/components/camel-dataset/src/main/docs/dataset-component.adoc b/components/camel-dataset/src/main/docs/dataset-component.adoc index aa41b69fe2740..42b8a9ef640eb 100644 --- a/components/camel-dataset/src/main/docs/dataset-component.adoc +++ b/components/camel-dataset/src/main/docs/dataset-component.adoc @@ -77,8 +77,8 @@ data set, and provides some useful features to derived classes. |=== |Property |Type |Default |Description -|`defaultHeaders` |`Map` |`null` | Specify the default message body. -For `SimpleDataSet` it is a constant payload; though if you want to create custom payloads per message, +|`defaultHeaders` |`Map` |`null` | Specify the default message headers. +They are the same for each message; though if you want to create custom headers per message, create your own derivation of `DataSetSupport`. |`outputTransformer` |`org.apache.camel.Processor` |null | diff --git a/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetEndpoint.java b/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetEndpoint.java index f05140e174d21..848558c6eb59a 100644 --- a/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetEndpoint.java +++ b/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetEndpoint.java @@ -27,6 +27,9 @@ import org.apache.camel.Producer; import org.apache.camel.Service; import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.CamelLogger; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -48,6 +51,14 @@ @UriEndpoint(firstVersion = "1.3.0", scheme = "dataset", title = "Dataset", syntax = "dataset:name", remote = false, category = { Category.CORE, Category.TESTING }, lenientProperties = true, headersClass = DataSetConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.UNKNOWN, + description = "The body the DataSet bean creates for each message: the defaultBody of a" + + " SimpleDataSet (the text world! unless set), the bodies of a" + + " ListDataSet in turn, or the text of a FileDataSet"), + producerIn = @BodyType(value = Carrier.ANY, + description = "Each message is compared with the body the DataSet creates for its index. A" + + " mismatch fails the assertions of the endpoint, not the message"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class DataSetEndpoint extends MockEndpoint implements Service { private final transient Logger log; private final AtomicInteger receivedCounter = new AtomicInteger(); diff --git a/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetTestEndpoint.java b/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetTestEndpoint.java index e14fc3a4b29d6..bd3a3bc29e58c 100644 --- a/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetTestEndpoint.java +++ b/components/camel-dataset/src/main/java/org/apache/camel/component/dataset/DataSetTestEndpoint.java @@ -27,6 +27,9 @@ import org.apache.camel.Processor; import org.apache.camel.WrappedFile; import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -46,6 +49,11 @@ */ @UriEndpoint(firstVersion = "1.3.0", scheme = "dataset-test", title = "DataSet Test", syntax = "dataset-test:name", remote = false, producerOnly = true, category = { Category.CORE, Category.TESTING }, lenientProperties = true) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "Each message is compared with the next body read at startup from the endpoint" + + " in the name. A mismatch fails the assertions of the endpoint, not the" + + " message"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class DataSetTestEndpoint extends MockEndpoint { private static final Logger LOG = LoggerFactory.getLogger(DataSetTestEndpoint.class); diff --git a/components/camel-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/control/dynamic-router-control.json b/components/camel-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/control/dynamic-router-control.json index a57cadc2accb3..ae13eadb71f68 100644 --- a/components/camel-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/control/dynamic-router-control.json +++ b/components/camel-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/control/dynamic-router-control.json @@ -37,6 +37,10 @@ "CamelDynamicRouterPredicateBean": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the bean in the registry that identifies the subscription predicate.", "constantName": "org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants#CONTROL_PREDICATE_BEAN" }, "CamelDynamicRouterExpressionLanguage": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The language for the predicate when supplied as a string.", "constantName": "org.apache.camel.component.dynamicrouter.control.DynamicRouterControlConstants#CONTROL_EXPRESSION_LANGUAGE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "A DynamicRouterControlMessage, or the subscription in the options or the headers. For subscribe and update without a predicate or a predicateBean, the body must be the Predicate" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "controlAction", "value": "subscribe", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "controlAction", "value": "update", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "controlAction", "value": "unsubscribe", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "controlAction", "value": "list", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "controlAction", "value": "statistics", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "By the action: the id of the subscription for subscribe and update, true when unsubscribe removed it, and the subscriptions or their statistics as text for list and statistics. The CamelDynamicRouterControlAction header overrides the action" } + }, "properties": { "controlAction": { "index": 0, "kind": "path", "displayName": "Control Action", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "subscribe", "unsubscribe", "update", "list", "statistics" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Control action" }, "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-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/routing/dynamic-router.json b/components/camel-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/routing/dynamic-router.json index 68b9b5dc6f5d8..9328124d78591 100644 --- a/components/camel-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/routing/dynamic-router.json +++ b/components/camel-dynamic-router/src/generated/resources/META-INF/org/apache/camel/component/dynamicrouter/routing/dynamic-router.json @@ -27,6 +27,10 @@ "lazyStartProducer": { "index": 0, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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." }, "autowiredEnabled": { "index": 1, "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." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The message to route: the predicates of the subscriptions on the channel decide where it goes" }, + "producerOut": { "carriers": [ "unknown" ], "description": "The body the recipient ends with; with allMatch, the one of the last recipient unless an aggregationStrategy is set. When no subscription matches, a text that says so, with the body in the originalBody header" } + }, "properties": { "channel": { "index": 0, "kind": "path", "displayName": "Channel", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Channel for the Dynamic Router. For example, if the Dynamic Router URI is dynamic-router:\/\/test, then the channel is test. Channels are a way of keeping routing participants, their rules, and exchanges logically separate from the participants, rules, and exchanges on other channels. This can be seen as analogous to VLANs in networking." }, "aggregationStrategy": { "index": 1, "kind": "parameter", "displayName": "Aggregation Strategy", "group": "common", "label": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.dynamicrouter.routing.DynamicRouterConfiguration", "configurationField": "configuration", "description": "Refers to an AggregationStrategy to be used to assemble the replies from the multicasts, into a single outgoing message from the Multicast. By default, Camel will use the last reply as the outgoing message. You can also use a POJO as the AggregationStrategy." }, diff --git a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpoint.java b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpoint.java index 71c3ca372936c..1591b99baa141 100644 --- a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpoint.java +++ b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/control/DynamicRouterControlEndpoint.java @@ -28,6 +28,9 @@ import org.apache.camel.component.dynamicrouter.control.DynamicRouterControlService.DynamicRouterControlServiceFactory; import org.apache.camel.component.dynamicrouter.filter.DynamicRouterFilterService; import org.apache.camel.component.dynamicrouter.routing.DynamicRouterComponent; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -59,6 +62,26 @@ remote = false, headersClass = DynamicRouterControlConstants.class, category = { Category.MESSAGING }) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "A DynamicRouterControlMessage, or the subscription in the options or the" + + " headers. For subscribe and update without a predicate or a predicateBean," + + " the body must be the Predicate"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "controlAction", value = "subscribe", + carriers = Carrier.TEXT, javaType = "java.lang.String"), + @BodyType.When(option = "controlAction", value = "update", carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "controlAction", value = "unsubscribe", + carriers = Carrier.VALUE, javaType = "java.lang.Boolean"), + @BodyType.When(option = "controlAction", value = "list", carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "controlAction", value = "statistics", + carriers = Carrier.TEXT, javaType = "java.lang.String") }, + description = "By the action: the id of the subscription for subscribe and update, true" + + " when unsubscribe removed it, and the subscriptions or their statistics as" + + " text for list and statistics. The CamelDynamicRouterControlAction header" + + " overrides the action")) public class DynamicRouterControlEndpoint extends DefaultEndpoint { static final String URI_CONTROL_ACTIONS = CONTROL_ACTION_SUBSCRIBE + "," + CONTROL_ACTION_UNSUBSCRIBE + "," + diff --git a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/routing/DynamicRouterEndpoint.java b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/routing/DynamicRouterEndpoint.java index 3546dd6bccc41..cda0e5fc8b517 100644 --- a/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/routing/DynamicRouterEndpoint.java +++ b/components/camel-dynamic-router/src/main/java/org/apache/camel/component/dynamicrouter/routing/DynamicRouterEndpoint.java @@ -29,6 +29,9 @@ import org.apache.camel.component.dynamicrouter.routing.DynamicRouterProcessor.DynamicRouterProcessorFactory; import org.apache.camel.component.dynamicrouter.routing.DynamicRouterProducer.DynamicRouterProducerFactory; import org.apache.camel.processor.RecipientList; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; @@ -55,6 +58,13 @@ producerOnly = true, remote = false, category = { Category.MESSAGING, Category.CORE }) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The message to route: the predicates of the subscriptions on the channel" + + " decide where it goes"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + description = "The body the recipient ends with; with allMatch, the one of the last" + + " recipient unless an aggregationStrategy is set. When no subscription" + + " matches, a text that says so, with the body in the originalBody header")) public class DynamicRouterEndpoint extends DefaultEndpoint { private static final Logger LOG = LoggerFactory.getLogger(DynamicRouterEndpoint.class); diff --git a/components/camel-event/src/generated/resources/META-INF/org/apache/camel/component/camelevent/event.json b/components/camel-event/src/generated/resources/META-INF/org/apache/camel/component/camelevent/event.json index ddac6dc0bb66d..4fa8339122c15 100644 --- a/components/camel-event/src/generated/resources/META-INF/org/apache/camel/component/camelevent/event.json +++ b/components/camel-event/src/generated/resources/META-INF/org/apache/camel/component/camelevent/event.json @@ -40,6 +40,9 @@ "CamelEventRedeliveryAttempt": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The redelivery attempt number (for ExchangeRedelivery events)", "constantName": "org.apache.camel.component.camelevent.CamelEventConstants#HEADER_EVENT_REDELIVERY_ATTEMPT" }, "CamelEventBatchSize": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of events in a batch (only set when batchSize is configured)", "constantName": "org.apache.camel.component.camelevent.CamelEventConstants#HEADER_EVENT_BATCH_SIZE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo" ], "javaType": "org.apache.camel.spi.CamelEvent", "dependsOn": [ "batchSize" ], "description": "The event, such as a RouteStartedEvent or an ExchangeCompletedEvent. With a batchSize above 1, a List of the events" } + }, "properties": { "events": { "index": 0, "kind": "path", "displayName": "Events", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Comma-separated list of event types to subscribe to. Event types correspond to CamelEvent.Type enum values (case-insensitive), for example: RouteStarted, RouteStopped, ExchangeCompleted, ExchangeFailed. Wildcard patterns are supported using a suffix, for example: Route matches all route events, Exchange matches all exchange events, and matches all events." }, "async": { "index": 1, "kind": "parameter", "displayName": "Async", "group": "consumer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to process events asynchronously using a thread pool. When enabled, the event notifier thread is not blocked while the event exchange is processed. Use asyncPoolSize to control the maximum number of concurrent event processing threads." }, diff --git a/components/camel-event/src/main/java/org/apache/camel/component/camelevent/CamelEventEndpoint.java b/components/camel-event/src/main/java/org/apache/camel/component/camelevent/CamelEventEndpoint.java index db7538ca95571..a0ca6ccdda9e8 100644 --- a/components/camel-event/src/main/java/org/apache/camel/component/camelevent/CamelEventEndpoint.java +++ b/components/camel-event/src/main/java/org/apache/camel/component/camelevent/CamelEventEndpoint.java @@ -28,6 +28,9 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.CamelEvent; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -49,6 +52,10 @@ consumerOnly = true, remote = false, internal = true, category = { Category.CORE, Category.MONITORING }, headersClass = CamelEventConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.POJO, javaType = "org.apache.camel.spi.CamelEvent", + dependsOn = "batchSize", + description = "The event, such as a RouteStartedEvent or an ExchangeCompletedEvent. With a" + + " batchSize above 1, a List of the events")) public class CamelEventEndpoint extends DefaultEndpoint { @UriPath(description = "Comma-separated list of event types to subscribe to." diff --git a/components/camel-exec/src/generated/resources/META-INF/org/apache/camel/component/exec/exec.json b/components/camel-exec/src/generated/resources/META-INF/org/apache/camel/component/exec/exec.json index 06aea47ab0db6..633ae01e4b135 100644 --- a/components/camel-exec/src/generated/resources/META-INF/org/apache/camel/component/exec/exec.json +++ b/components/camel-exec/src/generated/resources/META-INF/org/apache/camel/component/exec/exec.json @@ -44,6 +44,10 @@ "CamelExecUseStderrOnEmptyStdout": { "index": 8, "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Indicates that when stdout is empty, this component will populate the Camel Message Body with stderr. This behavior is disabled (false) by default. Requires allowControlHeaders=true on the exec endpoint or component (default is false since Camel 4.20).", "constantName": "org.apache.camel.component.exec.ExecBinding#EXEC_USE_STDERR_ON_EMPTY_STDOUT" }, "CamelExecCommandLogLevel": { "index": 9, "kind": "header", "displayName": "", "group": "in", "label": "in", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Logging level to be used for commands during execution. The default value is DEBUG. Possible values are TRACE, DEBUG, INFO, WARN, ERROR or OFF (Values of LoggingLevel enum). Requires allowControlHeaders=true on the exec endpoint or component (default is false since Camel 4.20).", "constantName": "org.apache.camel.component.exec.ExecBinding#EXEC_COMMAND_LOG_LEVEL" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The standard input of the command, when the body converts to a stream: text, bytes, a stream or a file. Another body, or no body, runs the command without input" }, + "producerOut": { "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.exec.ExecResult", "dependsOn": [ "binding" ], "description": "The ExecResult, with the exit value and the standard error in headers. It converts to the text, bytes or stream of the standard output, of the outFile when set, or of the standard error with useStderrOnEmptyStdout" } + }, "properties": { "executable": { "index": 0, "kind": "path", "displayName": "Executable", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sets the executable to be executed. The executable must not be empty or null." }, "args": { "index": 1, "kind": "parameter", "displayName": "Args", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The arguments may be one or many whitespace-separated tokens." }, diff --git a/components/camel-exec/src/main/docs/exec-component.adoc b/components/camel-exec/src/main/docs/exec-component.adoc index 64ca34aae1f84..31f392b31036e 100644 --- a/components/camel-exec/src/main/docs/exec-component.adoc +++ b/components/camel-exec/src/main/docs/exec-component.adoc @@ -97,7 +97,7 @@ executable via its standard input (`stdin`). After execution, http://camel.apache.org/exchange.html[the message body] is the result of the execution. -That is, an `org.apache.camel.components.exec.ExecResult` instance containing the +That is, an `org.apache.camel.component.exec.ExecResult` instance containing the `stdout`, `stderr`, _exit value_, and the _out file_. This component supports the following `ExecResult` http://camel.apache.org/type-converter.html[type converters] @@ -305,7 +305,7 @@ Java:: + [source,java] ---- -// When outFile is specified, the body is the content of that file (as InputStream) +// When outFile is specified, the ExecResult in the body converts to the content of that file from("direct:exec") .to("exec:ant.bat?args=-f CamelExecBuildFile.xml -l CamelExecOutFile.txt&outFile=CamelExecOutFile.txt") .to("log:result"); @@ -315,7 +315,7 @@ XML:: + [source,xml] ---- - + @@ -327,7 +327,7 @@ YAML:: + [source,yaml] ---- -# When outFile is specified, the body is the content of that file (as InputStream) +# When outFile is specified, the ExecResult in the body converts to the content of that file - route: from: uri: direct:exec diff --git a/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java b/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java index 4339c2304e5b8..e2b8378f5b437 100644 --- a/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java +++ b/components/camel-exec/src/main/java/org/apache/camel/component/exec/ExecEndpoint.java @@ -21,6 +21,9 @@ import org.apache.camel.LoggingLevel; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -33,6 +36,15 @@ */ @UriEndpoint(firstVersion = "2.3.0", scheme = "exec", title = "Exec", syntax = "exec:executable", producerOnly = true, remote = false, category = { Category.CORE }, headersClass = ExecBinding.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The standard input of the command, when the body converts to a stream: text," + + " bytes, a stream or a file. Another body, or no body, runs the command" + + " without input"), + producerOut = @BodyType(value = Carrier.POJO, javaType = "org.apache.camel.component.exec.ExecResult", + dependsOn = "binding", + description = "The ExecResult, with the exit value and the standard error in headers. It" + + " converts to the text, bytes or stream of the standard output, of the" + + " outFile when set, or of the standard error with useStderrOnEmptyStdout")) public class ExecEndpoint extends DefaultEndpoint { /** diff --git a/components/camel-jq/src/generated/resources/META-INF/org/apache/camel/language/jq/jq.json b/components/camel-jq/src/generated/resources/META-INF/org/apache/camel/language/jq/jq.json index 781f11d2f1794..64157b0b27cfc 100644 --- a/components/camel-jq/src/generated/resources/META-INF/org/apache/camel/language/jq/jq.json +++ b/components/camel-jq/src/generated/resources/META-INF/org/apache/camel/language/jq/jq.json @@ -16,7 +16,7 @@ "modelJavaType": "org.apache.camel.model.language.JqExpression" }, "bodyTypes": { - "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "format": "json", "description": "JSON as text, bytes, a stream or a file, or a Map" }, + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "map" ], "format": "json", "dependsOn": [ "source" ], "description": "JSON as text, bytes, a stream or a file, or a Map" }, "expressionOut": { "carriers": [ "pojo", "list", "null" ], "dependsOn": [ "resultType" ], "description": "A JsonNode; a List of JsonNode when the filter gives several, null when it gives none" } }, "properties": { diff --git a/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java b/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java index 3944e84c8d266..0e84f1abd3721 100644 --- a/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java +++ b/components/camel-jq/src/main/java/org/apache/camel/language/jq/JqLanguage.java @@ -31,7 +31,8 @@ @Language("jq") @BodyTypes(expressionIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP }, - format = "json", description = "JSON as text, bytes, a stream or a file, or a Map"), + format = "json", dependsOn = "source", + description = "JSON as text, bytes, a stream or a file, or a Map"), expressionOut = @BodyType(value = { Carrier.POJO, Carrier.LIST, Carrier.NULL }, dependsOn = "resultType", description = "A JsonNode; a List of JsonNode when the filter gives several, null when it" + " gives none")) diff --git a/components/camel-knative/camel-knative-component/src/generated/resources/META-INF/org/apache/camel/component/knative/knative.json b/components/camel-knative/camel-knative-component/src/generated/resources/META-INF/org/apache/camel/component/knative/knative.json index 4cd67395d5cb1..2570eea62af00 100644 --- a/components/camel-knative/camel-knative-component/src/generated/resources/META-INF/org/apache/camel/component/knative/knative.json +++ b/components/camel-knative/camel-knative-component/src/generated/resources/META-INF/org/apache/camel/component/knative/knative.json @@ -59,6 +59,12 @@ "CamelCloudEventSubject": { "index": 6, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The subject of the event in the context of the event source.", "constantName": "org.apache.camel.component.knative.KnativeConstants#CLOUD_EVENT_SUBJECT" }, "CamelCloudEventTime": { "index": 7, "kind": "header", "displayName": "", "group": "common", "label": "common", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The time the event occurred. The producer uses the exchange creation time when not set.", "constantName": "org.apache.camel.component.knative.KnativeConstants#CLOUD_EVENT_TIME" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes", "null", "map", "list", "text", "value" ], "description": "The data of the event as a byte array, empty or null for an event without data. A structured event (Content-Type application\/cloudevents+json) gives its data field parsed from JSON: a Map, a List, text or a value" }, + "consumerReply": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "byOption": [ { "option": "reply", "value": "false", "carriers": [ "any" ] } ], "description": "The data of the reply, sent as bytes: text, bytes, a stream or a file; no body answers 204 No Content. A Map or a POJO fails: marshal it first. With reply=false the body is not sent" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data of the event: text, bytes, a stream or a file, sent as bytes. No body fails, and so does a Map or a POJO: marshal it first" }, + "producerOut": { "carriers": [ "bytes", "null" ], "description": "The body of the response, also for a message that expects no reply (InOnly): a byte array, null for a response without a body" } + }, "properties": { "type": { "index": 0, "kind": "path", "displayName": "Type", "group": "common", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.knative.spi.Knative.Type", "enum": [ "endpoint", "channel", "event" ], "deprecated": false, "autowired": false, "secret": false, "description": "The Knative resource type" }, "typeId": { "index": 1, "kind": "path", "displayName": "Type Id", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The identifier of the Knative resource" }, diff --git a/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java b/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java index 5c2530dd8e4a0..d631540590a43 100644 --- a/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java +++ b/components/camel-knative/camel-knative-component/src/main/java/org/apache/camel/component/knative/KnativeEndpoint.java @@ -36,6 +36,9 @@ import org.apache.camel.component.knative.spi.Knative; import org.apache.camel.component.knative.spi.KnativeResource; import org.apache.camel.component.knative.spi.KnativeTransportConfiguration; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -59,6 +62,23 @@ @Metadata(annotations = { "protocol=http", }) +@BodyTypes(consumerOut = @BodyType(value = { + Carrier.BYTES, Carrier.NULL, Carrier.MAP, Carrier.LIST, Carrier.TEXT, + Carrier.VALUE }, + description = "The data of the event as a byte array, empty or null for an event without" + + " data. A structured event (Content-Type application/cloudevents+json) gives" + + " its data field parsed from JSON: a Map, a List, text or a value"), + consumerReply = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + byOption = @BodyType.When(option = "reply", value = "false", carriers = Carrier.ANY), + description = "The data of the reply, sent as bytes: text, bytes, a stream or a file; no" + + " body answers 204 No Content. A Map or a POJO fails: marshal it first." + + " With reply=false the body is not sent"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The data of the event: text, bytes, a stream or a file, sent as bytes. No body" + + " fails, and so does a Map or a POJO: marshal it first"), + producerOut = @BodyType(value = { Carrier.BYTES, Carrier.NULL }, + description = "The body of the response, also for a message that expects no reply (InOnly):" + + " a byte array, null for a response without a body")) public class KnativeEndpoint extends DefaultEndpoint { private static final Logger LOG = LoggerFactory.getLogger(KnativeEndpoint.class); diff --git a/components/camel-language/src/generated/resources/META-INF/org/apache/camel/component/language/language.json b/components/camel-language/src/generated/resources/META-INF/org/apache/camel/component/language/language.json index fb260589ad386..caacbaaccad4a 100644 --- a/components/camel-language/src/generated/resources/META-INF/org/apache/camel/component/language/language.json +++ b/components/camel-language/src/generated/resources/META-INF/org/apache/camel/component/language/language.json @@ -32,6 +32,10 @@ "headers": { "CamelLanguageScript": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String or Expression", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The script to execute provided in the header. Takes precedence over script configured on the endpoint.", "constantName": "org.apache.camel.component.language.LanguageConstants#LANGUAGE_SCRIPT" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "unknown" ], "description": "The body as the language of the script reads it. The script is in the uri, the script option or a resource, or in the CamelLanguageScript header with allowTemplateFromHeader=true, and never in the body" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "transform", "value": "false", "carriers": [ "unchanged" ] }, { "option": "binary", "value": "true", "carriers": [ "stream" ] } ], "description": "The result of the script, as the language gives it. Unchanged with transform=false. With binary=true the content of the resource as a stream, which is not evaluated" } + }, "properties": { "languageName": { "index": 0, "kind": "path", "displayName": "Language Name", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "bean", "constant", "datasonnet", "exchangeProperty", "file", "groovy", "header", "hl7terser", "java", "joor", "jq", "js", "jsonpath", "mvel", "ognl", "python", "python3", "quickjs", "ref", "simple", "spel", "tokenize", "variable", "xpath", "xquery", "xtokenize" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Sets the name of the language to use" }, "resourceUri": { "index": 1, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource, or a reference to lookup a bean in the Registry to use as the resource" }, diff --git a/components/camel-language/src/main/docs/language-component.adoc b/components/camel-language/src/main/docs/language-component.adoc index 435519cea521f..e7753b75dc569 100644 --- a/components/camel-language/src/main/docs/language-component.adoc +++ b/components/camel-language/src/main/docs/language-component.adoc @@ -131,7 +131,7 @@ Java:: [source,java] ---- from("direct:double") - .to("language:groovy:${body} * 2}"); + .to("language:groovy:body * 2"); ---- XML:: @@ -140,7 +140,7 @@ XML:: ---- - + ---- @@ -153,25 +153,26 @@ YAML:: uri: direct:double steps: - to: - uri: "language:groovy:${body} * 2}" + uri: "language:groovy:body * 2" ---- ==== -You can also provide the script as a header as shown below. Here we use +You can also provide the script as a header as shown below, when the endpoint +has `allowTemplateFromHeader=true`. Here we use xref:languages:xpath-language.adoc[XPath] language to extract the text from the `` tag. ._Java-only: providing the script as a message header_ [source,java] ---- -Object out = producer.requestBodyAndHeader("language:xpath", "Hello World", Exchange.LANGUAGE_SCRIPT, "/foo/text()"); +Object out = producer.requestBodyAndHeader("language:xpath?allowTemplateFromHeader=true", "Hello World", Exchange.LANGUAGE_SCRIPT, "/foo/text()"); assertEquals("Hello World", out); ---- == Loading scripts from resources You can specify a resource uri for a script to load in either the -endpoint uri, or in the `Exchange.LANGUAGE_SCRIPT` header. +endpoint uri, or in the `Exchange.LANGUAGE_SCRIPT` header (with `allowTemplateFromHeader=true`). The uri must start with one of the following schemes: `file:`, `classpath:`, or `http:` [tabs] diff --git a/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java b/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java index 3540253abc3ed..bc4a2b97c1c81 100644 --- a/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java +++ b/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java @@ -29,6 +29,9 @@ import org.apache.camel.Producer; import org.apache.camel.RuntimeCamelException; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Language; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -49,6 +52,17 @@ @UriEndpoint(firstVersion = "2.5.0", scheme = "language", title = "Language", syntax = "language:languageName:resourceUri", remote = false, producerOnly = true, category = { Category.CORE, Category.SCRIPT }, headersClass = LanguageConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.UNKNOWN, + description = "The body as the language of the script reads it. The script is in the uri," + + " the script option or a resource, or in the CamelLanguageScript header with" + + " allowTemplateFromHeader=true, and never in the body"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "transform", value = "false", carriers = Carrier.UNCHANGED), + @BodyType.When(option = "binary", value = "true", carriers = Carrier.STREAM) }, + description = "The result of the script, as the language gives it. Unchanged with" + + " transform=false. With binary=true the content of the resource as a" + + " stream, which is not evaluated")) public class LanguageEndpoint extends ResourceEndpoint { private Language language; diff --git a/components/camel-once/src/generated/resources/META-INF/org/apache/camel/component/once/once.json b/components/camel-once/src/generated/resources/META-INF/org/apache/camel/component/once/once.json index 9d9a7c4b8c613..768303766ec43 100644 --- a/components/camel-once/src/generated/resources/META-INF/org/apache/camel/component/once/once.json +++ b/components/camel-once/src/generated/resources/META-INF/org/apache/camel/component/once/once.json @@ -29,6 +29,9 @@ "delay": { "index": 2, "kind": "property", "displayName": "Delay", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The number of milliseconds to wait before triggering. Use 0 or negative to fire as soon as possible. The default value is 1000." }, "languages": { "index": 3, "kind": "property", "displayName": "Languages", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether Camel languages are supported such as simple,groovy." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "dependsOn": [ "body" ], "description": "No body without the body option. The body option gives its text, the text of a file:, classpath: or http: resource, a Boolean for true or false, a number for a whole number, or with language:NAME: the result of the expression" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The logical name" }, "body": { "index": 1, "kind": "parameter", "displayName": "Body", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "The data to use as message body. You can externalize the data by using file: or classpath: as prefix and specify the location of the file." }, diff --git a/components/camel-once/src/main/docs/once-component.adoc b/components/camel-once/src/main/docs/once-component.adoc index da5b467808ba0..0587dcfad165f 100644 --- a/components/camel-once/src/main/docs/once-component.adoc +++ b/components/camel-once/src/main/docs/once-component.adoc @@ -227,7 +227,7 @@ Java:: + [source,java] ---- -from("once:foo?body=file.data.json&delay=-1").to("bean:myBean?method=someMethodName"); +from("once:foo?body=file:data.json&delay=-1").to("bean:myBean?method=someMethodName"); ---- XML:: @@ -235,7 +235,7 @@ XML:: [source,xml] ---- - + ---- @@ -248,7 +248,7 @@ YAML:: from: uri: once:foo parameters: - body: file.data.json + body: file:data.json delay: -1 steps: - to: diff --git a/components/camel-once/src/main/java/org/apache/camel/component/once/OnceEndpoint.java b/components/camel-once/src/main/java/org/apache/camel/component/once/OnceEndpoint.java index bbe267cfc8c9c..80f93e91d9423 100644 --- a/components/camel-once/src/main/java/org/apache/camel/component/once/OnceEndpoint.java +++ b/components/camel-once/src/main/java/org/apache/camel/component/once/OnceEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -35,6 +38,11 @@ */ @UriEndpoint(firstVersion = "4.17.0", scheme = "once", title = "Once", syntax = "once:name", consumerOnly = true, remote = false, category = { Category.CORE, Category.SCHEDULING }) +@BodyTypes(consumerOut = @BodyType(value = Carrier.NULL, dependsOn = "body", + description = "No body without the body option. The body option gives its text, the text of" + + " a file:, classpath: or http: resource, a Boolean for true or false, a" + + " number for a whole number, or with language:NAME: the result of the" + + " expression")) public class OnceEndpoint extends DefaultEndpoint { @UriPath diff --git a/components/camel-ref/src/generated/resources/META-INF/org/apache/camel/component/ref/ref.json b/components/camel-ref/src/generated/resources/META-INF/org/apache/camel/component/ref/ref.json index 2c8ab8073ccf7..09ec81acc2563 100644 --- a/components/camel-ref/src/generated/resources/META-INF/org/apache/camel/component/ref/ref.json +++ b/components/camel-ref/src/generated/resources/META-INF/org/apache/camel/component/ref/ref.json @@ -28,6 +28,11 @@ "lazyStartProducer": { "index": 1, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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." }, "autowiredEnabled": { "index": 2, "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." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unknown" ], "description": "The body the consumer of the endpoint in the registry gives" }, + "producerIn": { "carriers": [ "unknown" ], "description": "The bodies the producer of the endpoint in the registry takes" }, + "producerOut": { "carriers": [ "unknown" ], "description": "The body the producer of the endpoint in the registry leaves" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of endpoint to lookup in the registry." }, "bridgeErrorHandler": { "index": 1, "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." }, diff --git a/components/camel-ref/src/main/java/org/apache/camel/component/ref/RefEndpoint.java b/components/camel-ref/src/main/java/org/apache/camel/component/ref/RefEndpoint.java index cee8b5b83f00f..e71b65a136113 100644 --- a/components/camel-ref/src/main/java/org/apache/camel/component/ref/RefEndpoint.java +++ b/components/camel-ref/src/main/java/org/apache/camel/component/ref/RefEndpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.Endpoint; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriPath; @@ -34,6 +37,12 @@ */ @UriEndpoint(firstVersion = "1.2.0", scheme = "ref", title = "Ref", syntax = "ref:name", remote = false, category = { Category.CORE }) +@BodyTypes(consumerOut = @BodyType(value = Carrier.UNKNOWN, + description = "The body the consumer of the endpoint in the registry gives"), + producerIn = @BodyType(value = Carrier.UNKNOWN, + description = "The bodies the producer of the endpoint in the registry takes"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + description = "The body the producer of the endpoint in the registry leaves")) public class RefEndpoint extends DefaultEndpoint implements DelegateEndpoint { private volatile Endpoint endpoint; diff --git a/components/camel-rest/src/generated/resources/META-INF/org/apache/camel/component/rest/rest-api.json b/components/camel-rest/src/generated/resources/META-INF/org/apache/camel/component/rest/rest-api.json index 0b170f11f2ec8..9eb5e7a75b7c9 100644 --- a/components/camel-rest/src/generated/resources/META-INF/org/apache/camel/component/rest/rest-api.json +++ b/components/camel-rest/src/generated/resources/META-INF/org/apache/camel/component/rest/rest-api.json @@ -28,6 +28,10 @@ "consumerComponentName": { "index": 1, "kind": "property", "displayName": "Consumer Component Name", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The Camel Rest API component to use for the consumer REST transport, such as jetty, servlet, undertow. If no component has been explicitly configured, then Camel will lookup if there is a Camel component that integrates with the Rest DSL, or if a org.apache.camel.spi.RestApiConsumerFactory is registered in the registry. If either one is found, then that is being used." }, "autowiredEnabled": { "index": 2, "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." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "dependsOn": [ "consumerComponentName" ], "description": "The GET request for the API document, which has no body" }, + "consumerReply": { "carriers": [ "null", "text", "bytes", "stream" ], "dependsOn": [ "consumerComponentName" ], "description": "The API document the route of the REST DSL sets: the OpenAPI document as bytes, JSON unless the path ends with .yaml or the Accept header asks for YAML" } + }, "properties": { "path": { "index": 0, "kind": "path", "displayName": "Path", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The base path" }, "apiComponentName": { "index": 1, "kind": "parameter", "displayName": "Api Component Name", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The Camel Rest API component to use for generating the API of the REST services, such as openapi." }, diff --git a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java index 4eeef1a0d522c..e568916ea875e 100644 --- a/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java +++ b/components/camel-rest/src/main/java/org/apache/camel/component/rest/RestApiEndpoint.java @@ -26,6 +26,9 @@ import org.apache.camel.NoSuchBeanException; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.RestApiConsumerFactory; import org.apache.camel.spi.RestApiProcessorFactory; @@ -46,6 +49,13 @@ */ @UriEndpoint(firstVersion = "2.16.0", scheme = "rest-api", title = "REST API", syntax = "rest-api:path", remote = false, consumerOnly = true, category = { Category.CORE, Category.REST }, lenientProperties = true) +@BodyTypes(consumerOut = @BodyType(value = Carrier.NULL, dependsOn = "consumerComponentName", + description = "The GET request for the API document, which has no body"), + consumerReply = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM }, + dependsOn = "consumerComponentName", + description = "The API document the route of the REST DSL sets: the OpenAPI document as" + + " bytes, JSON unless the path ends with .yaml or the Accept header asks" + + " for YAML")) public class RestApiEndpoint extends DefaultEndpoint { public static final String[] DEFAULT_REST_API_CONSUMER_COMPONENTS diff --git a/components/camel-saga/src/generated/resources/META-INF/org/apache/camel/component/saga/saga.json b/components/camel-saga/src/generated/resources/META-INF/org/apache/camel/component/saga/saga.json index 98e1f751e6e2b..3249b3bbba388 100644 --- a/components/camel-saga/src/generated/resources/META-INF/org/apache/camel/component/saga/saga.json +++ b/components/camel-saga/src/generated/resources/META-INF/org/apache/camel/component/saga/saga.json @@ -30,6 +30,10 @@ "headers": { "Long-Running-Action": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The long running action", "constantName": "org.apache.camel.component.saga.SagaConstants#SAGA_LONG_RUNNING_ACTION" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: the saga service calls the completion or compensation endpoints with messages of its own" } + }, "properties": { "action": { "index": 0, "kind": "path", "displayName": "Action", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.saga.SagaEndpoint.SagaEndpointAction", "enum": [ "COMPLETE", "COMPENSATE" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Action to execute (complete or compensate)" }, "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-saga/src/main/java/org/apache/camel/component/saga/SagaEndpoint.java b/components/camel-saga/src/main/java/org/apache/camel/component/saga/SagaEndpoint.java index 089902732e1aa..e4fa071904ebd 100644 --- a/components/camel-saga/src/main/java/org/apache/camel/component/saga/SagaEndpoint.java +++ b/components/camel-saga/src/main/java/org/apache/camel/component/saga/SagaEndpoint.java @@ -20,6 +20,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriPath; @@ -31,6 +34,10 @@ */ @UriEndpoint(firstVersion = "2.21.0", scheme = "saga", title = "Saga", syntax = "saga:action", producerOnly = true, category = { Category.CLUSTERING }, headersClass = SagaConstants.class) +@BodyTypes(producerIn = @BodyType(Carrier.ANY), + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged: the saga service calls the completion or compensation endpoints" + + " with messages of its own")) public class SagaEndpoint extends DefaultEndpoint { public enum SagaEndpointAction { diff --git a/components/camel-stax/src/generated/resources/META-INF/org/apache/camel/language/xtokenizer/xtokenize.json b/components/camel-stax/src/generated/resources/META-INF/org/apache/camel/language/xtokenizer/xtokenize.json index d9a63ad907f51..b065c75e73731 100644 --- a/components/camel-stax/src/generated/resources/META-INF/org/apache/camel/language/xtokenizer/xtokenize.json +++ b/components/camel-stax/src/generated/resources/META-INF/org/apache/camel/language/xtokenizer/xtokenize.json @@ -15,6 +15,10 @@ "modelName": "xtokenize", "modelJavaType": "org.apache.camel.model.language.XMLTokenizerExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], "description": "XML as text, bytes, a stream or a file, or a DOM" }, + "expressionOut": { "carriers": [ "iterator" ], "description": "An Iterator of the elements the path matches as XML text, read once; mode t gives their text. With group, each N elements are joined into one text" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-stax/src/main/java/org/apache/camel/language/xtokenizer/XMLTokenizeLanguage.java b/components/camel-stax/src/main/java/org/apache/camel/language/xtokenizer/XMLTokenizeLanguage.java index b8322dbcaf593..c5c959746f718 100644 --- a/components/camel-stax/src/main/java/org/apache/camel/language/xtokenizer/XMLTokenizeLanguage.java +++ b/components/camel-stax/src/main/java/org/apache/camel/language/xtokenizer/XMLTokenizeLanguage.java @@ -22,6 +22,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionAdapter; import org.apache.camel.support.IteratorConvertTo; @@ -40,6 +43,12 @@ * */ @Language("xtokenize") +@BodyTypes(expressionIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", dependsOn = "source", + description = "XML as text, bytes, a stream or a file, or a DOM"), + expressionOut = @BodyType(value = Carrier.ITERATOR, + description = "An Iterator of the elements the path matches as XML text, read once; mode t" + + " gives their text. With group, each N elements are joined into one text")) public class XMLTokenizeLanguage extends SingleInputTypedLanguageSupport { @Override diff --git a/components/camel-stream/src/generated/resources/META-INF/org/apache/camel/component/stream/stream.json b/components/camel-stream/src/generated/resources/META-INF/org/apache/camel/component/stream/stream.json index 260f2172b9991..96e7923834b0f 100644 --- a/components/camel-stream/src/generated/resources/META-INF/org/apache/camel/component/stream/stream.json +++ b/components/camel-stream/src/generated/resources/META-INF/org/apache/camel/component/stream/stream.json @@ -32,6 +32,11 @@ "CamelStreamIndex": { "index": 0, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The index", "constantName": "org.apache.camel.component.stream.StreamConstants#STREAM_INDEX" }, "CamelStreamComplete": { "index": 1, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Is complete", "constantName": "org.apache.camel.component.stream.StreamConstants#STREAM_COMPLETE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "groupLines" ], "byOption": [ { "option": "readLine", "value": "false", "carriers": [ "bytes" ], "javaType": "byte[]" } ], "description": "Each line of the stream as text. With groupLines, a List of the lines; with readLine=false, all the bytes of the stream" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "description": "Text in the encoding, or bytes, a stream or a file as bytes, followed by a new line; no body writes nothing. A Map or a POJO is written as its toString() and a List fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "kind": { "index": 0, "kind": "path", "displayName": "Kind", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "in", "out", "err", "header", "file", "http" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Kind of stream to use such as System.in, System.out, a file, or a http url." }, "encoding": { "index": 1, "kind": "parameter", "displayName": "Encoding", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "You can configure the encoding (is a charset name) to use text-based streams (for example, message body is a String object). If not provided, Camel uses the JVM default Charset." }, diff --git a/components/camel-stream/src/main/docs/stream-component.adoc b/components/camel-stream/src/main/docs/stream-component.adoc index 706f831209ba6..829eff3eec51c 100644 --- a/components/camel-stream/src/main/docs/stream-component.adoc +++ b/components/camel-stream/src/main/docs/stream-component.adoc @@ -56,15 +56,14 @@ include::partial$component-endpoint-headers.adoc[] === Message content -The Stream component supports either `String` or `byte[]` for writing -to streams. Just add either `String` or `byte[]` content to the -`message.in.body`. Messages sent to the *stream:* producer in binary -mode are not followed by the newline character (as opposed to the -`String` messages). Message with `null` body will not be appended to the -output stream. + +The Stream component writes text, bytes, a stream or a file: text in the +`encoding`, and the others as bytes, each followed by a new line unless +`appendNewLine` is `false`. A message with a `null` body writes nothing. +Another body, such as a `Map`, is written as its `toString()`, so marshal it +first. + The special `stream:header` URI is used for custom output streams. Just add a `java.io.OutputStream` object to `message.in.header` in the key -`header`. + +`stream`. + See samples for an example. == Examples diff --git a/components/camel-stream/src/main/java/org/apache/camel/component/stream/StreamEndpoint.java b/components/camel-stream/src/main/java/org/apache/camel/component/stream/StreamEndpoint.java index f7abcf630cfa1..487599c626727 100644 --- a/components/camel-stream/src/main/java/org/apache/camel/component/stream/StreamEndpoint.java +++ b/components/camel-stream/src/main/java/org/apache/camel/component/stream/StreamEndpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -36,6 +39,16 @@ */ @UriEndpoint(firstVersion = "1.3.0", scheme = "stream", title = "Stream", syntax = "stream:kind", category = { Category.FILE, Category.CORE }, headersClass = StreamConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", dependsOn = "groupLines", + byOption = @BodyType.When(option = "readLine", value = "false", carriers = Carrier.BYTES, + javaType = "byte[]"), + description = "Each line of the stream as text. With groupLines, a List of the lines; with" + + " readLine=false, all the bytes of the stream"), + producerIn = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "Text in the encoding, or bytes, a stream or a file as bytes, followed by a new" + + " line; no body writes nothing. A Map or a POJO is written as its toString()" + + " and a List fails: marshal it first"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class StreamEndpoint extends DefaultEndpoint { private static final Logger LOG = LoggerFactory.getLogger(StreamEndpoint.class); diff --git a/components/camel-stub/src/generated/resources/META-INF/org/apache/camel/component/stub/stub.json b/components/camel-stub/src/generated/resources/META-INF/org/apache/camel/component/stub/stub.json index 889e38765279c..2aeb9bd3b00d7 100644 --- a/components/camel-stub/src/generated/resources/META-INF/org/apache/camel/component/stub/stub.json +++ b/components/camel-stub/src/generated/resources/META-INF/org/apache/camel/component/stub/stub.json @@ -38,6 +38,11 @@ "shadow": { "index": 10, "kind": "property", "displayName": "Shadow", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If shadow is enabled then the stub component will register a shadow endpoint with the actual uri that refers to the stub endpoint, meaning you can lookup the endpoint via both stub:kafka:cheese and kafka:cheese." }, "shadowPattern": { "index": 11, "kind": "property", "displayName": "Shadow Pattern", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "If shadow is enabled then this pattern can be used to filter which components to match. Multiple patterns can be separated by comma." } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "unchanged" ], "description": "The body the producer sent" }, + "producerIn": { "carriers": [ "any" ] }, + "producerOut": { "carriers": [ "unknown" ], "description": "Unchanged when no route consumes from the stub endpoint, or for a message that expects no reply (InOnly). A message that expects one (InOut) waits for the body the stub route ends with" } + }, "properties": { "name": { "index": 0, "kind": "path", "displayName": "Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of queue" }, "size": { "index": 1, "kind": "parameter", "displayName": "Size", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "The maximum capacity of the SEDA queue (i.e., the number of messages it can hold). Will by default use the queueSize set on the SEDA component." }, diff --git a/components/camel-stub/src/main/java/org/apache/camel/component/stub/StubEndpoint.java b/components/camel-stub/src/main/java/org/apache/camel/component/stub/StubEndpoint.java index e745e04d14bac..ee4f40b7b9096 100644 --- a/components/camel-stub/src/main/java/org/apache/camel/component/stub/StubEndpoint.java +++ b/components/camel-stub/src/main/java/org/apache/camel/component/stub/StubEndpoint.java @@ -25,6 +25,9 @@ import org.apache.camel.Producer; import org.apache.camel.component.seda.BlockingQueueFactory; import org.apache.camel.component.seda.SedaEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; /** @@ -38,6 +41,12 @@ */ @UriEndpoint(firstVersion = "2.10.0", scheme = "stub", title = "Stub", syntax = "stub:name", remote = false, internal = true, category = { Category.CORE, Category.TESTING }, lenientProperties = true) +@BodyTypes(consumerOut = @BodyType(value = Carrier.UNCHANGED, description = "The body the producer sent"), + producerIn = @BodyType(Carrier.ANY), + producerOut = @BodyType(value = Carrier.UNKNOWN, + description = "Unchanged when no route consumes from the stub endpoint, or for a message" + + " that expects no reply (InOnly). A message that expects one (InOut) waits" + + " for the body the stub route ends with")) public class StubEndpoint extends SedaEndpoint { public StubEndpoint(String endpointUri, Component component, BlockingQueue queue) { diff --git a/components/camel-validator/src/generated/resources/META-INF/org/apache/camel/component/validator/validator.json b/components/camel-validator/src/generated/resources/META-INF/org/apache/camel/component/validator/validator.json index 8f36134aa8181..e6a59c38577e3 100644 --- a/components/camel-validator/src/generated/resources/META-INF/org/apache/camel/component/validator/validator.json +++ b/components/camel-validator/src/generated/resources/META-INF/org/apache/camel/component/validator/validator.json @@ -28,6 +28,10 @@ "autowiredEnabled": { "index": 1, "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." }, "resourceResolverFactory": { "index": 2, "kind": "property", "displayName": "Resource Resolver Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.validator.ValidatorResourceResolverFactory", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom LSResourceResolver which depends on a dynamic endpoint resource URI" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "headerName" ], "byOption": [ { "option": "failOnNullBody", "value": "false", "carriers": [ "null", "text", "bytes", "stream", "file", "pojo" ] } ], "description": "The XML to validate: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source. A Map, a List or no body fails; with headerName the header is validated instead" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: XML that is not valid fails with a SchemaValidationException" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "URL to a local resource on the classpath, or a reference to lookup a bean in the Registry, or a full URL to a remote resource or resource on the file system which contains the XSD to validate against." }, "failOnNullBody": { "index": 1, "kind": "parameter", "displayName": "Fail On Null Body", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to fail if no body exists." }, diff --git a/components/camel-validator/src/main/java/org/apache/camel/component/validator/ValidatorEndpoint.java b/components/camel-validator/src/main/java/org/apache/camel/component/validator/ValidatorEndpoint.java index 0aa0d1053b495..6b7c85fbe345c 100644 --- a/components/camel-validator/src/main/java/org/apache/camel/component/validator/ValidatorEndpoint.java +++ b/components/camel-validator/src/main/java/org/apache/camel/component/validator/ValidatorEndpoint.java @@ -28,6 +28,9 @@ import org.apache.camel.Producer; import org.apache.camel.api.management.ManagedOperation; import org.apache.camel.api.management.ManagedResource; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -44,6 +47,17 @@ @ManagedResource(description = "Managed ValidatorEndpoint") @UriEndpoint(firstVersion = "1.1.0", scheme = "validator", title = "Validator", syntax = "validator:resourceUri", remote = false, producerOnly = true, category = { Category.CORE, Category.VALIDATION }) +@BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", dependsOn = "headerName", + byOption = @BodyType.When(option = "failOnNullBody", value = "false", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE, Carrier.POJO }), + description = "The XML to validate: text, bytes, a stream, a file, a DOM or another" + + " javax.xml.transform.Source. A Map, a List or no body fails; with headerName" + + " the header is validated instead"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged: XML that is not valid fails with a SchemaValidationException")) public class ValidatorEndpoint extends DefaultEndpoint { @UriPath(description = "URL to a local resource on the classpath, or a reference to lookup a bean in the Registry," diff --git a/components/camel-wasm/src/generated/resources/META-INF/org/apache/camel/component/wasm/wasm.json b/components/camel-wasm/src/generated/resources/META-INF/org/apache/camel/component/wasm/wasm.json index 5bf98acf9c617..be436686faa88 100644 --- a/components/camel-wasm/src/generated/resources/META-INF/org/apache/camel/component/wasm/wasm.json +++ b/components/camel-wasm/src/generated/resources/META-INF/org/apache/camel/component/wasm/wasm.json @@ -31,6 +31,10 @@ "CamelWasmExitCode": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The exit code of the module: 0 when it returned from its _start function, otherwise the value it passed to proc_exit. Not set when the module trapped, timed out or exceeded maxOutputSize.", "constantName": "org.apache.camel.wasm.Wasm$Headers#EXIT_CODE" }, "CamelWasmStderr": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "What the module wrote to its standard error, decoded as UTF-8. Not set when the module wrote nothing or timed out.", "constantName": "org.apache.camel.wasm.Wasm$Headers#STDERR" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "description": "The standard input of the module: text, bytes, a stream or a file; no body is an empty input. A Map, a List or a POJO fails: marshal it first" }, + "producerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The standard output of the module, with the exit code in the CamelWasmExitCode header" } + }, "properties": { "module": { "index": 0, "kind": "path", "displayName": "Module", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The WASI Preview 1 command module to run, as a resource: by default from the classpath, or with a prefix such as classpath:, file: or http:" }, "args": { "index": 1, "kind": "parameter", "displayName": "Args", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.wasm.WasmConfiguration", "configurationField": "configuration", "description": "The command line arguments passed to the module, separated by whitespace. Use double quotes around an argument that contains whitespace. The module receives the file name of the module (for example upper.wasm, without scheme, directories or query) as argument zero, followed by these arguments. The arguments are fixed by the route: they cannot be set from message headers." }, diff --git a/components/camel-wasm/src/main/java/org/apache/camel/component/wasm/WasmEndpoint.java b/components/camel-wasm/src/main/java/org/apache/camel/component/wasm/WasmEndpoint.java index 5e0a663ee21d6..0f423412d0a9e 100644 --- a/components/camel-wasm/src/main/java/org/apache/camel/component/wasm/WasmEndpoint.java +++ b/components/camel-wasm/src/main/java/org/apache/camel/component/wasm/WasmEndpoint.java @@ -27,6 +27,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -44,6 +47,12 @@ @UriEndpoint(firstVersion = "4.4.0", scheme = Wasm.SCHEME, title = "Wasm", syntax = "wasm:module", producerOnly = true, remote = false, category = { Category.CORE, Category.SCRIPT }, headersClass = Wasm.Headers.class) +@BodyTypes(producerIn = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The standard input of the module: text, bytes, a stream or a file; no body is" + + " an empty input. A Map, a List or a POJO fails: marshal it first"), + producerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]", + description = "The standard output of the module, with the exit code in the" + + " CamelWasmExitCode header")) public class WasmEndpoint extends DefaultEndpoint { private static final String DEFAULT_PROGRAM_NAME = "module.wasm"; diff --git a/components/camel-xpath/src/generated/resources/META-INF/org/apache/camel/language/xpath/xpath.json b/components/camel-xpath/src/generated/resources/META-INF/org/apache/camel/language/xpath/xpath.json index e7e50b9357a1e..052b58d798f56 100644 --- a/components/camel-xpath/src/generated/resources/META-INF/org/apache/camel/language/xpath/xpath.json +++ b/components/camel-xpath/src/generated/resources/META-INF/org/apache/camel/language/xpath/xpath.json @@ -16,7 +16,7 @@ "modelJavaType": "org.apache.camel.model.language.XPathExpression" }, "bodyTypes": { - "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "XML as text, bytes, a stream or a file, or a DOM" }, + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], "description": "XML as text, bytes, a stream or a file, or a DOM" }, "expressionOut": { "carriers": [ "pojo" ], "javaType": "org.w3c.dom.NodeList", "dependsOn": [ "resultType" ], "byOption": [ { "option": "resultQName", "value": "STRING", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "resultQName", "value": "NUMBER", "carriers": [ "value" ], "javaType": "java.lang.Double" }, { "option": "resultQName", "value": "BOOLEAN", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "resultQName", "value": "NODE", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Node" } ], "description": "The nodes the expression selects" } }, "properties": { diff --git a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java index 1e846164b355b..67f5f2f174e03 100644 --- a/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java +++ b/components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathLanguage.java @@ -38,7 +38,8 @@ */ @Language("xpath") @BodyTypes(expressionIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, - format = "xml", description = "XML as text, bytes, a stream or a file, or a DOM"), + format = "xml", dependsOn = "source", + description = "XML as text, bytes, a stream or a file, or a DOM"), expressionOut = @BodyType(value = Carrier.POJO, javaType = "org.w3c.dom.NodeList", dependsOn = "resultType", byOption = { @BodyType.When(option = "resultQName", value = "STRING", carriers = Carrier.TEXT, diff --git a/components/camel-xslt-saxon/src/generated/resources/META-INF/org/apache/camel/component/xslt/saxon/xslt-saxon.json b/components/camel-xslt-saxon/src/generated/resources/META-INF/org/apache/camel/component/xslt/saxon/xslt-saxon.json index 24a36d9612bf2..28cd2c8d05999 100644 --- a/components/camel-xslt-saxon/src/generated/resources/META-INF/org/apache/camel/component/xslt/saxon/xslt-saxon.json +++ b/components/camel-xslt-saxon/src/generated/resources/META-INF/org/apache/camel/component/xslt/saxon/xslt-saxon.json @@ -43,6 +43,10 @@ "CamelXsltStylesheet": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" }, "CamelXsltFileName": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The XSLT file name", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_FILE_NAME" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source", "useJsonBody" ], "byOption": [ { "option": "failOnNullBody", "value": "false", "carriers": [ "null", "text", "bytes", "stream", "file", "pojo" ] } ], "description": "The XML to transform: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source; JSON text with useJsonBody. A Map, a List or no body fails" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultHandlerFactory" ], "byOption": [ { "option": "output", "value": "bytes", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "output", "value": "DOM", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document" }, { "option": "output", "value": "file", "carriers": [ "file" ], "javaType": "java.io.File" } ], "description": "The result of the transformation" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Path to the template. The following is supported by the default URIResolver. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod" }, "allowStAX": { "index": 1, "kind": "parameter", "displayName": "Allow StAX", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow using StAX as the javax.xml.transform.Source. You can enable this if the XSLT library supports StAX such as the Saxon library (camel-saxon). The Xalan library (default in JVM) does not support StAXSource." }, diff --git a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java index 062e463f2f8d7..3c5f8ce5e4f19 100644 --- a/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java +++ b/components/camel-xslt-saxon/src/main/java/org/apache/camel/component/xslt/saxon/XsltSaxonEndpoint.java @@ -49,6 +49,9 @@ import org.apache.camel.component.xslt.TransformerFactoryConfigurationStrategy; import org.apache.camel.component.xslt.XsltBuilder; import org.apache.camel.component.xslt.XsltEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ClassResolver; import org.apache.camel.spi.Injector; import org.apache.camel.spi.Metadata; @@ -65,6 +68,24 @@ @ManagedResource(description = "Managed XsltSaxonEndpoint") @UriEndpoint(firstVersion = "3.0.0", scheme = "xslt-saxon", title = "XSLT Saxon", syntax = "xslt-saxon:resourceUri", remote = false, producerOnly = true, category = { Category.CORE, Category.TRANSFORMATION }) +@BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", dependsOn = { "source", "useJsonBody" }, + byOption = @BodyType.When(option = "failOnNullBody", value = "false", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE, Carrier.POJO }), + description = "The XML to transform: text, bytes, a stream, a file, a DOM or another" + + " javax.xml.transform.Source; JSON text with useJsonBody. A Map, a List or no" + + " body fails"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", dependsOn = "resultHandlerFactory", + byOption = { + @BodyType.When(option = "output", value = "bytes", carriers = Carrier.BYTES, + javaType = "byte[]"), + @BodyType.When(option = "output", value = "DOM", carriers = Carrier.POJO, + javaType = "org.w3c.dom.Document"), + @BodyType.When(option = "output", value = "file", carriers = Carrier.FILE, + javaType = "java.io.File") }, + description = "The result of the transformation")) public class XsltSaxonEndpoint extends XsltEndpoint { private static final Logger LOG = LoggerFactory.getLogger(XsltSaxonEndpoint.class); diff --git a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/header/header.json b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/header/header.json index d295131eba167..a1e7e1255788b 100644 --- a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/header/header.json +++ b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/header/header.json @@ -15,6 +15,9 @@ "modelName": "header", "modelJavaType": "org.apache.camel.model.language.HeaderExpression" }, + "bodyTypes": { + "expressionOut": { "carriers": [ "unknown" ], "description": "The value of the header as it is, null when there is none. A missing header falls back to the exchange property of that name" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/property/exchangeProperty.json b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/property/exchangeProperty.json index 30237a2819e4b..2dc10609366d5 100644 --- a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/property/exchangeProperty.json +++ b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/property/exchangeProperty.json @@ -15,6 +15,9 @@ "modelName": "exchangeProperty", "modelJavaType": "org.apache.camel.model.language.ExchangePropertyExpression" }, + "bodyTypes": { + "expressionOut": { "carriers": [ "unknown" ], "description": "The value of the exchange property as it is, null when there is none" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/ref/ref.json b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/ref/ref.json index dcd78c00bc00f..80776995a904c 100644 --- a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/ref/ref.json +++ b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/ref/ref.json @@ -15,6 +15,10 @@ "modelName": "ref", "modelJavaType": "org.apache.camel.model.language.RefExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "unknown" ], "description": "As the expression or the predicate in the registry reads it" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the expression in the registry returns; a Boolean for a predicate" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/file.json b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/file.json index 1e33e6ba029e5..f74414f152834 100644 --- a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/file.json +++ b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/simple/file.json @@ -15,6 +15,10 @@ "modelName": "simple", "modelJavaType": "org.apache.camel.model.language.SimpleExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, for ${body}: the file functions read the headers the file consumers set" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "A text with functions gives text, such as a file name. A single function gives its value as it is: ${file:size}, ${file:length} and ${file:modified} a Long, ${file:absolute} a Boolean, the other file functions text, and null without the headers of a file" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/tokenizer/tokenize.json b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/tokenizer/tokenize.json index 401f57fd5eba4..16dbce3bee17e 100644 --- a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/tokenizer/tokenize.json +++ b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/tokenizer/tokenize.json @@ -15,6 +15,10 @@ "modelName": "tokenize", "modelJavaType": "org.apache.camel.model.language.TokenizerExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "source" ], "description": "Text as text, bytes, a stream or a file. Another body is tokenized as its toString(), and fails with endToken or xml: marshal it first" }, + "expressionOut": { "carriers": [ "iterator" ], "description": "An Iterator of the tokens as text, read once: in setBody the body is the Iterator, for the Split EIP to walk. With group, each N tokens are joined into one text" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "token": { "index": 1, "kind": "attribute", "displayName": "Token", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The (start) token to use as tokenizer, for example you can use the new line token. You can use simple language as the token to support dynamic tokens." }, diff --git a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/variable/variable.json b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/variable/variable.json index 73b49502e5e8f..1700bbf3b51f6 100644 --- a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/variable/variable.json +++ b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/variable/variable.json @@ -15,6 +15,9 @@ "modelName": "variable", "modelJavaType": "org.apache.camel.model.language.VariableExpression" }, + "bodyTypes": { + "expressionOut": { "carriers": [ "unknown" ], "description": "The value of the variable as it is, null when there is none. A global: or route: prefix reads a global or a route variable" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/header/HeaderLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/header/HeaderLanguage.java index 29d2a9207f255..8ade107cb64a4 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/header/HeaderLanguage.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/header/HeaderLanguage.java @@ -18,6 +18,9 @@ import org.apache.camel.Expression; import org.apache.camel.Predicate; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionToPredicateAdapter; import org.apache.camel.support.LanguageSupport; @@ -27,6 +30,9 @@ * A language for header expressions. */ @Language("header") +@BodyTypes(expressionOut = @BodyType(value = Carrier.UNKNOWN, + description = "The value of the header as it is, null when there is none. A missing header" + + " falls back to the exchange property of that name")) public class HeaderLanguage extends LanguageSupport { public static Expression header(String headerName) { diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/property/ExchangePropertyLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/property/ExchangePropertyLanguage.java index d2bc194a6374b..93ca404a250c5 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/property/ExchangePropertyLanguage.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/property/ExchangePropertyLanguage.java @@ -19,6 +19,9 @@ import org.apache.camel.Expression; import org.apache.camel.IsSingleton; import org.apache.camel.Predicate; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Language; import org.apache.camel.support.ExpressionToPredicateAdapter; import org.apache.camel.support.builder.ExpressionBuilder; @@ -27,6 +30,8 @@ * A language for exchange property expressions. */ @org.apache.camel.spi.annotations.Language("exchangeProperty") +@BodyTypes(expressionOut = @BodyType(value = Carrier.UNKNOWN, + description = "The value of the exchange property as it is, null when there is none")) public class ExchangePropertyLanguage implements Language, IsSingleton { public static Expression exchangeProperty(String propertyName) { diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/ref/RefLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/ref/RefLanguage.java index da678eccd338e..e53648c662cca 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/ref/RefLanguage.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/ref/RefLanguage.java @@ -20,6 +20,9 @@ import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.Predicate; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Registry; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionAdapter; @@ -32,6 +35,10 @@ * A language for referred expressions or predicates. */ @Language("ref") +@BodyTypes(expressionIn = @BodyType(value = Carrier.UNKNOWN, + description = "As the expression or the predicate in the registry reads it"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, + description = "What the expression in the registry returns; a Boolean for a predicate")) public class RefLanguage extends TypedLanguageSupport { @Override diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/FileLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/FileLanguage.java index f579745e9895a..51c92bb2a8a5a 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/FileLanguage.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/FileLanguage.java @@ -16,12 +16,23 @@ */ package org.apache.camel.language.simple; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Language; /** * The Camel file language. */ @Language(value = "file", functionsClass = FileConstants.class) +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "The body as it is, for ${body}: the file functions read the headers the file" + + " consumers set"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, + description = "A text with functions gives text, such as a file name. A single function" + + " gives its value as it is: ${file:size}, ${file:length} and" + + " ${file:modified} a Long, ${file:absolute} a Boolean, the other file" + + " functions text, and null without the headers of a file")) public class FileLanguage extends SimpleLanguage { public FileLanguage() { diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java index feb0da7aed7b1..de7daf07135bc 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/tokenizer/TokenizeLanguage.java @@ -21,6 +21,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionAdapter; import org.apache.camel.support.IteratorConvertTo; @@ -40,6 +43,14 @@ * token and endToken. And the xml mode supports the inheritNamespaceTagName option. */ @Language("tokenize") +@BodyTypes(expressionIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + dependsOn = "source", + description = "Text as text, bytes, a stream or a file. Another body is tokenized as its" + + " toString(), and fails with endToken or xml: marshal it first"), + expressionOut = @BodyType(value = Carrier.ITERATOR, + description = "An Iterator of the tokens as text, read once: in setBody the body is the" + + " Iterator, for the Split EIP to walk. With group, each N tokens are" + + " joined into one text")) public class TokenizeLanguage extends SingleInputTypedLanguageSupport { @Override diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/variable/VariableLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/variable/VariableLanguage.java index ba6a306d4e1bf..d1ef73b2cbaf0 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/variable/VariableLanguage.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/variable/VariableLanguage.java @@ -18,6 +18,9 @@ import org.apache.camel.Expression; import org.apache.camel.Predicate; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.ExpressionToPredicateAdapter; import org.apache.camel.support.LanguageSupport; @@ -27,6 +30,9 @@ * A language for variable expressions. */ @Language("variable") +@BodyTypes(expressionOut = @BodyType(value = Carrier.UNKNOWN, + description = "The value of the variable as it is, null when there is none. A global: or" + + " route: prefix reads a global or a route variable")) public class VariableLanguage extends LanguageSupport { public static Expression variable(String name) { diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java index 27c6c2b9e64a4..333ecc82ed601 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java @@ -1186,6 +1186,57 @@ public void testTheBodyOfCloudMessaging() { .anySatisfy(m -> assertThat(m).contains("to: google-pubsub needs the body as text or bytes")); } + @Test + public void testTheBodyOfCoreComponents() { + // the stream consumer gives each line as text, so a field read needs an unmarshal, and stream:out writes text, + // bytes, a stream or a file, so parsed data must be marshalled first; the knative consumer gives bytes, or the + // data of a structured event parsed, so it says nothing, and after a bean the body is what the method returns + String yaml = """ + - route: + id: lines + from: + uri: stream:file?fileName=orders.txt + steps: + - setHeader: + name: id + simple: ${body[id]} + - route: + id: print + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: stream:out + - route: + id: events + from: + uri: knative:endpoint/orders + steps: + - setHeader: + name: id + simple: ${body[id]} + - route: + id: beans + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: bean:orders?method=toText + - to: file:outbox + """; + assertThat(lines(yaml)).hasSize(2).anySatisfy(m -> assertThat(m) + .contains("route lines: simple reads a field of the body (${body[id]})") + .contains("the stream consumer gives it as text")) + .anySatisfy(m -> assertThat(m) + .contains("route print: to: stream needs the body as text, bytes, a stream or a file")); + } + @Test public void testOneReportForAStepThatFails() { // the first write fails at runtime, so the second does not run with this body From 9ac1f8d3623cd027fb9b4a25b22d1cd9d182ceb4 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 22 Oct 2026 11:50:19 +0200 Subject: [PATCH 18/25] CAMEL-24961: Catalog body types for jira, github2, pqc, dns, caffeine and infinispan The body types of jira, github2, pqc, dns, caffeine-cache, caffeine-loadcache, infinispan and infinispan-embedded, the most used components in the route files that had none yet. pqc, dns, caffeine and infinispan-embedded were checked at runtime with camel run; jira and github2 were read from the code. The validator now takes an option a body depends on as unknown also when another option of the step names a body, such as xslt with output=bytes and a resultHandlerFactory, as the BodyType javadoc says. The component docs of jira, github2, dns and infinispan said things about the body that the code does not do. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../catalog/components/caffeine-cache.json | 4 ++ .../components/caffeine-loadcache.json | 4 ++ .../apache/camel/catalog/components/dns.json | 4 ++ .../camel/catalog/components/github2.json | 5 ++ .../components/infinispan-embedded.json | 5 ++ .../camel/catalog/components/infinispan.json | 5 ++ .../apache/camel/catalog/components/jira.json | 5 ++ .../apache/camel/catalog/components/pqc.json | 4 ++ .../camel/catalog/docs/dns-component.adoc | 6 +- .../camel/catalog/docs/github2-component.adoc | 8 ++- .../catalog/docs/infinispan-component.adoc | 40 ++++++----- .../docs/infinispan-embedded-component.adoc | 34 ++++----- .../camel/catalog/docs/jira-component.adoc | 10 ++- .../caffeine/cache/caffeine-cache.json | 4 ++ .../caffeine/load/caffeine-loadcache.json | 4 ++ .../caffeine/cache/CaffeineCacheEndpoint.java | 24 +++++++ .../load/CaffeineLoadCacheEndpoint.java | 25 +++++++ .../org/apache/camel/component/dns/dns.json | 4 ++ .../src/main/docs/dns-component.adoc | 6 +- .../camel/component/dns/DnsEndpoint.java | 20 ++++++ .../camel/component/github2/github2.json | 5 ++ .../src/main/docs/github2-component.adoc | 8 ++- .../component/github2/GitHub2Endpoint.java | 59 +++++++++++++++ .../embedded/infinispan-embedded.json | 5 ++ .../docs/infinispan-embedded-component.adoc | 34 ++++----- .../embedded/InfinispanEmbeddedEndpoint.java | 47 ++++++++++++ .../infinispan/remote/infinispan.json | 5 ++ .../src/main/docs/infinispan-component.adoc | 40 ++++++----- .../remote/InfinispanRemoteEndpoint.java | 47 ++++++++++++ .../org/apache/camel/component/jira/jira.json | 5 ++ .../src/main/docs/jira-component.adoc | 10 ++- .../camel/component/jira/JiraEndpoint.java | 59 +++++++++++++++ .../org/apache/camel/component/pqc/pqc.json | 4 ++ .../camel/component/pqc/PQCEndpoint.java | 54 ++++++++++++++ .../dsl/yaml/validator/CatalogBodyTypes.java | 9 +++ .../dsl/yaml/validator/TextBodyFlowTest.java | 72 +++++++++++++++++++ 36 files changed, 602 insertions(+), 82 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/caffeine-cache.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/caffeine-cache.json index 268c39da8b4d9..7e1cada6d649c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/caffeine-cache.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/caffeine-cache.json @@ -51,6 +51,10 @@ "CamelCaffeineValue": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of key for all put actions (PUT or PUT_ALL).", "constantName": "org.apache.camel.component.caffeine.CaffeineConstants#VALUE" }, "CamelCaffeineOldValue": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The old value returned according to the action.", "constantName": "org.apache.camel.component.caffeine.CaffeineConstants#OLD_VALUE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The value to store for PUT, converted to the valueType when set, and a Map of the entries for PUT_ALL, unless the CamelCaffeineValue header gives it; without either they fail. The other actions do not use the body" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "action", "value": "GET_ALL", "carriers": [ "map" ], "javaType": "java.util.Map" }, { "option": "action", "value": "AS_MAP", "carriers": [ "map" ], "javaType": "java.util.concurrent.ConcurrentMap" }, { "option": "action", "value": "PUT", "carriers": [ "unchanged" ] }, { "option": "action", "value": "PUT_ALL", "carriers": [ "unchanged" ] }, { "option": "action", "value": "INVALIDATE", "carriers": [ "unchanged" ] }, { "option": "action", "value": "INVALIDATE_ALL", "carriers": [ "unchanged" ] }, { "option": "action", "value": "CLEANUP", "carriers": [ "unchanged" ] } ], "description": "By the action, which the CamelCaffeineAction header can set: the value of the key for GET, or the body as it was when the key is not in the cache, a Map of the entries found for GET_ALL, and the cache as a Map for AS_MAP. The other actions keep the body" } + }, "properties": { "cacheName": { "index": 0, "kind": "path", "displayName": "Cache Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Cache name" }, "action": { "index": 1, "kind": "parameter", "displayName": "Action", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "GET", "GET_ALL", "PUT", "PUT_ALL", "INVALIDATE", "INVALIDATE_ALL", "CLEANUP", "AS_MAP" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.caffeine.CaffeineConfiguration", "configurationField": "configuration", "description": "To configure the default cache action. If an action is set in the message header, then the operation from the header takes precedence." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/caffeine-loadcache.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/caffeine-loadcache.json index 2ce307d4d9dc4..32a660551b7f2 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/caffeine-loadcache.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/caffeine-loadcache.json @@ -51,6 +51,10 @@ "CamelCaffeineValue": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of key for all put actions (PUT or PUT_ALL).", "constantName": "org.apache.camel.component.caffeine.CaffeineConstants#VALUE" }, "CamelCaffeineOldValue": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The old value returned according to the action.", "constantName": "org.apache.camel.component.caffeine.CaffeineConstants#OLD_VALUE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The value to store for PUT, converted to the valueType when set, and a Map of the entries for PUT_ALL, unless the CamelCaffeineValue header gives it; without either they fail. The other actions do not use the body" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "action", "value": "GET_ALL", "carriers": [ "map" ], "javaType": "java.util.Map" }, { "option": "action", "value": "AS_MAP", "carriers": [ "map" ], "javaType": "java.util.concurrent.ConcurrentMap" }, { "option": "action", "value": "PUT", "carriers": [ "unchanged" ] }, { "option": "action", "value": "PUT_ALL", "carriers": [ "unchanged" ] }, { "option": "action", "value": "INVALIDATE", "carriers": [ "unchanged" ] }, { "option": "action", "value": "INVALIDATE_ALL", "carriers": [ "unchanged" ] }, { "option": "action", "value": "CLEANUP", "carriers": [ "unchanged" ] } ], "description": "By the action, which the CamelCaffeineAction header can set: the value of the key for GET, from the cache or else the cacheLoader, or the body as it was when the loader gives null, a Map of the entries found or loaded for GET_ALL, and the cache as a Map for AS_MAP. The other actions keep the body" } + }, "properties": { "cacheName": { "index": 0, "kind": "path", "displayName": "Cache Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "the cache name" }, "action": { "index": 1, "kind": "parameter", "displayName": "Action", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "GET", "GET_ALL", "PUT", "PUT_ALL", "INVALIDATE", "INVALIDATE_ALL", "CLEANUP", "AS_MAP" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.caffeine.CaffeineConfiguration", "configurationField": "configuration", "description": "To configure the default cache action. If an action is set in the message header, then the operation from the header takes precedence." }, 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..065d7bed0e5bf 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 @@ -35,6 +35,10 @@ "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" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The body is not used: the name to query is in a header, CamelDnsDomain for ip, CamelDnsName for lookup and dig, and CamelDnsTerm for wikipedia" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "dnsType", "value": "ip", "carriers": [ "pojo" ], "javaType": "java.net.InetAddress" }, { "option": "dnsType", "value": "lookup", "carriers": [ "list" ], "javaType": "org.xbill.DNS.Record[]" }, { "option": "dnsType", "value": "dig", "carriers": [ "pojo" ], "javaType": "org.xbill.DNS.Message" }, { "option": "dnsType", "value": "wikipedia", "carriers": [ "text", "null" ] } ], "description": "By the type: for ip the InetAddress of the domain, which converts to the address as text; for lookup the records of the answer as an array of Record, and the lookup fails when there are none; for dig the response Message; for wikipedia the text of the first TXT record, or no body" } + }, "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." }, "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/github2.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/github2.json index e956fb8a2d632..236cd99c08057 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 @@ -43,6 +43,11 @@ "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" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "null" ], "byOption": [ { "option": "commitMessageAsBody", "value": "false", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHCommit" }, { "option": "type", "value": "PULLREQUEST", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHPullRequest" }, { "option": "type", "value": "PULLREQUESTCOMMENT", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHIssueComment" }, { "option": "type", "value": "TAG", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHTag" }, { "option": "type", "value": "EVENT", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "One message per new item, oldest first. commit gives the commit message (null when the data of the commit cannot be loaded), or the GHCommit with commitMessageAsBody=false, and event the type of the event, such as PUSH, with the GHEventInfo in the CamelGitHubEventPayload header" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "type", "value": "PULLREQUESTCOMMENT", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "CREATEISSUE", "carriers": [ "null", "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "PULLREQUESTSTATE", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "Read as text: the comment for pullRequestComment, which needs a body, and the description of the issue for createIssue and of the commit status for pullRequestState; a Map or a POJO is sent as its toString(), so marshal it first. getCommitFile reads the sha from the body when the CamelGitHubCommitSha header is not set, and the other types read only headers" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "type", "value": "CLOSEPULLREQUEST", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHPullRequest" }, { "option": "type", "value": "PULLREQUESTCOMMENT", "carriers": [ "pojo", "unchanged" ] }, { "option": "type", "value": "PULLREQUESTSTATE", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHCommitStatus" }, { "option": "type", "value": "PULLREQUESTFILES", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "type", "value": "GETCOMMITFILE", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "type", "value": "CREATEISSUE", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHIssue" } ], "description": "The GHPullRequest as read before the close for closePullRequest, the GHIssueComment for pullRequestComment when the exchange expects a reply (InOut), otherwise the body is unchanged, the GHCommitStatus for pullRequestState, a List of GHPullRequestFileDetail for pullRequestFiles, the content of the file as text for getCommitFile, and the GHIssue for createIssue" } + }, "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" }, "branchName": { "index": 1, "kind": "path", "displayName": "Branch Name", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of branch" }, 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 c50ae628c8993..cf0d4383893de 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 @@ -69,6 +69,11 @@ "CamelInfinispanOriginLocal": { "index": 20, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "true if the call originated on the local cache instance; false if originated from a remote one.", "constantName": "org.apache.camel.component.infinispan.InfinispanConstants#ORIGIN_LOCAL" }, "CamelInfinispanCurrentState": { "index": 21, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "True if this event is generated from an existing entry as the listener has Listener.", "constantName": "org.apache.camel.component.infinispan.InfinispanConstants#CURRENT_STATE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "dependsOn": [ "customListener" ], "description": "No body: the event type, the cache name and the key of the entry are in headers, and the value, when the event has one, in the CamelInfinispanEventData header" }, + "producerIn": { "carriers": [ "any" ], "description": "The body is not used: the key, the value and the Map for PUTALL come from the CamelInfinispanKey, CamelInfinispanValue and CamelInfinispanMap headers, or the key and value options" }, + "producerOut": { "carriers": [ "unknown" ], "dependsOn": [ "resultHeader" ], "byOption": [ { "option": "operation", "value": "PUTASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "PUTALL", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "PUTALLASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "PUTIFABSENTASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "CONTAINSKEY", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "CONTAINSVALUE", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "REMOVEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "REPLACEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "SIZE", "carriers": [ "value" ], "javaType": "java.lang.Integer" }, { "option": "operation", "value": "CLEAR", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "CLEARASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "QUERY", "carriers": [ "list", "unchanged" ] }, { "option": "operation", "value": "STATS", "carriers": [ "pojo" ], "javaType": "org.infinispan.stats.Stats" }, { "option": "operation", "value": "COMPUTEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" } ], "description": "The result of the operation, which the CamelInfinispanOperation header can set: the value for GET, or null when the key is not in the cache, the previous value for PUT, the default, a Boolean for CONTAINSKEY, an Integer for SIZE, a List for QUERY and a CompletableFuture for the ASYNC operations; PUTALL and CLEAR keep the body. With resultHeader the result goes to that header and the body is kept" } + }, "properties": { "cacheName": { "index": 0, "kind": "path", "displayName": "Cache Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the cache to use. Use current to use the existing cache name from the currently configured cached manager. Or use default for the default cache manager name." }, "queryBuilder": { "index": 1, "kind": "parameter", "displayName": "Query Builder", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.infinispan.InfinispanQueryBuilder", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Specifies the query builder." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/infinispan.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/infinispan.json index 39e6f3ebde04f..d7949aa592fbb 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/infinispan.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/infinispan.json @@ -78,6 +78,11 @@ "CamelInfinispanEntryVersion": { "index": 16, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Provides access to the version of the created cache entry.", "constantName": "org.apache.camel.component.infinispan.InfinispanConstants#ENTRY_VERSION" }, "CamelInfinispanCommandRetried": { "index": 17, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "This will be true if the write command that caused this had to be retried again due to a topology change.", "constantName": "org.apache.camel.component.infinispan.InfinispanConstants#COMMAND_RETRIED" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "dependsOn": [ "customListener" ], "description": "No body: the event type, the cache name and the key of the entry are in headers, and for the events of a continuous query (queryBuilder) the value in the CamelInfinispanEventData header" }, + "producerIn": { "carriers": [ "any" ], "description": "The body is not used: the key, the value and the Map for PUTALL come from the CamelInfinispanKey, CamelInfinispanValue and CamelInfinispanMap headers, or the key and value options" }, + "producerOut": { "carriers": [ "unknown" ], "dependsOn": [ "resultHeader" ], "byOption": [ { "option": "operation", "value": "PUTASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "PUTALL", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "PUTALLASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "PUTIFABSENTASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "CONTAINSKEY", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "CONTAINSVALUE", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "REMOVEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "REPLACEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "SIZE", "carriers": [ "value" ], "javaType": "java.lang.Integer" }, { "option": "operation", "value": "CLEAR", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "CLEARASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "QUERY", "carriers": [ "list", "unchanged" ] }, { "option": "operation", "value": "STATS", "carriers": [ "pojo" ], "javaType": "org.infinispan.client.hotrod.ServerStatistics" }, { "option": "operation", "value": "COMPUTEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" } ], "description": "The result of the operation, which the CamelInfinispanOperation header can set: the value for GET, the previous value for PUT, the default, which is null unless the FORCE_RETURN_VALUE flag is set, a Boolean for CONTAINSKEY, an Integer for SIZE, a List for QUERY and a CompletableFuture for the ASYNC operations; PUTALL and CLEAR keep the body. With resultHeader the result goes to that header and the body is kept" } + }, "properties": { "cacheName": { "index": 0, "kind": "path", "displayName": "Cache Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the cache to use. Use current to use the existing cache name from the currently configured cached manager. Or use default for the default cache manager name." }, "hosts": { "index": 1, "kind": "parameter", "displayName": "Hosts", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration", "configurationField": "configuration", "description": "Specifies the host of the cache on Infinispan instance. Multiple hosts can be separated by semicolon." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jira.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jira.json index 2b0b518a69fe2..947280f4bdc1a 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jira.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jira.json @@ -60,6 +60,11 @@ "CamelJiraLinkType": { "index": 17, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of link", "constantName": "org.apache.camel.component.jira.JiraConstants#LINK_TYPE" }, "CamelJiraMinutesSpent": { "index": 18, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "-1", "description": "The minutes spent", "constantName": "org.apache.camel.component.jira.JiraConstants#MINUTES_SPENT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo", "null" ], "dependsOn": [ "watchedFields" ], "byOption": [ { "option": "sendOnlyUpdatedField", "value": "false", "carriers": [ "pojo" ], "javaType": "com.atlassian.jira.rest.client.api.domain.Issue" }, { "option": "type", "value": "NEWISSUES", "carriers": [ "pojo" ], "javaType": "com.atlassian.jira.rest.client.api.domain.Issue" }, { "option": "type", "value": "NEWCOMMENTS", "carriers": [ "pojo" ], "javaType": "com.atlassian.jira.rest.client.api.domain.Comment" } ], "description": "One message per new Issue (newIssues) or new Comment (newComments). watchUpdates sends one per watched field that changed, with its new value, such as the Status or the BasicPriority (null when cleared), or the Issue with sendOnlyUpdatedField=false" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "type", "value": "ADDISSUE", "carriers": [ "null", "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "UPDATEISSUE", "carriers": [ "null", "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "TRANSITIONISSUE", "carriers": [ "null", "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "ADDISSUELINK", "carriers": [ "null", "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "ADDCOMMENT", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "ADDWORKLOG", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "ATTACH", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "Read as text: the description for addIssue and updateIssue, the comment for addComment and addWorkLog, which fail without a body, and an optional comment for transitionIssue and addIssueLink; a Map or a POJO is sent as its toString(), so marshal it first. attach uploads a file, or text, bytes or a stream named by the CamelFileName header. The other types read only headers" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "type", "value": "ADDISSUE", "carriers": [ "pojo" ], "javaType": "com.atlassian.jira.rest.client.api.domain.Issue" }, { "option": "type", "value": "FETCHISSUE", "carriers": [ "pojo" ], "javaType": "com.atlassian.jira.rest.client.api.domain.Issue" }, { "option": "type", "value": "FETCHCOMMENTS", "carriers": [ "list" ], "javaType": "java.util.List" } ], "description": "The Issue created for addIssue, the Issue for fetchIssue and the List of its Comments for fetchComments. The other types leave the body unchanged" } + }, "properties": { "type": { "index": 0, "kind": "path", "displayName": "Type", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.jira.JiraType", "enum": [ "ADDCOMMENT", "ADDISSUE", "ATTACH", "DELETEISSUE", "NEWISSUES", "NEWCOMMENTS", "WATCHUPDATES", "UPDATEISSUE", "TRANSITIONISSUE", "WATCHERS", "ADDISSUELINK", "ADDWORKLOG", "FETCHISSUE", "FETCHCOMMENTS" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation to perform. Consumers: NewIssues, NewComments. Producers: AddIssue, AttachFile, DeleteIssue, TransitionIssue, UpdateIssue, Watchers. See this class javadoc description for more information." }, "delay": { "index": 1, "kind": "parameter", "displayName": "Delay", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 6000, "configurationClass": "org.apache.camel.component.jira.JiraConfiguration", "configurationField": "configuration", "description": "Time in milliseconds to elapse for the next poll." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json index 39a2d8dc3ff6c..c3aeb57ed7375 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pqc.json @@ -81,6 +81,10 @@ "CamelPQCHybridEncapsulation": { "index": 21, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "byte[]", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The hybrid encapsulation combining both classical and PQC encapsulations", "constantName": "org.apache.camel.component.pqc.PQCConstants#HYBRID_ENCAPSULATION" }, "CamelPQCHybridVerification": { "index": 22, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The verification result of hybrid signature (both must pass)", "constantName": "org.apache.camel.component.pqc.PQCConstants#HYBRID_VERIFY" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "operation", "value": "sign", "carriers": [ "text", "bytes", "stream" ] }, { "option": "operation", "value": "verify", "carriers": [ "text", "bytes", "stream" ] }, { "option": "operation", "value": "hybridSign", "carriers": [ "text", "bytes", "stream" ] }, { "option": "operation", "value": "hybridVerify", "carriers": [ "text", "bytes", "stream" ] }, { "option": "operation", "value": "extractSecretKeyEncapsulation", "carriers": [ "pojo" ], "javaType": "org.bouncycastle.jcajce.SecretKeyWithEncapsulation" }, { "option": "operation", "value": "extractSecretKeyFromEncapsulation", "carriers": [ "pojo" ], "javaType": "org.bouncycastle.jcajce.SecretKeyWithEncapsulation" }, { "option": "operation", "value": "importKey", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "The payload of sign, verify, hybridSign and hybridVerify: bytes or a stream as they are, text as UTF-8; another body is signed as its text, so marshal it first. extractSecretKeyEncapsulation and extractSecretKeyFromEncapsulation take the SecretKeyWithEncapsulation that generateSecretKeyEncapsulation gives, and importKey the key as bytes, or as text for PEM. The other operations do not use the body" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "generateSecretKeyEncapsulation", "carriers": [ "pojo" ], "javaType": "org.bouncycastle.jcajce.SecretKeyWithEncapsulation" }, { "option": "operation", "value": "extractSecretKeyEncapsulation", "carriers": [ "pojo" ], "javaType": "org.bouncycastle.jcajce.SecretKeyWithEncapsulation" }, { "option": "operation", "value": "extractSecretKeyFromEncapsulation", "carriers": [ "pojo" ], "javaType": "javax.crypto.SecretKey" }, { "option": "operation", "value": "hybridGenerateSecretKeyEncapsulation", "carriers": [ "pojo" ], "javaType": "javax.crypto.SecretKey" }, { "option": "operation", "value": "hybridExtractSecretKeyEncapsulation", "carriers": [ "pojo" ], "javaType": "javax.crypto.SecretKey" }, { "option": "operation", "value": "hybridExtractSecretKeyFromEncapsulation", "carriers": [ "pojo" ], "javaType": "javax.crypto.SecretKey" }, { "option": "storeExtractedSecretKeyAsHeader", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for the signature and key operations, which set their results in headers, such as CamelPQCSignature and CamelPQCVerification. generateSecretKeyEncapsulation and extractSecretKeyEncapsulation give a SecretKeyWithEncapsulation, and the other key encapsulation operations the SecretKey; with storeExtractedSecretKeyAsHeader=true the key is in the CamelPQCSecretKey header instead" } + }, "properties": { "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "Logical name" }, "operation": { "index": 1, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.pqc.PQCOperations", "enum": [ "sign", "verify", "hybridSign", "hybridVerify", "generateSecretKeyEncapsulation", "extractSecretKeyEncapsulation", "extractSecretKeyFromEncapsulation", "hybridGenerateSecretKeyEncapsulation", "hybridExtractSecretKeyEncapsulation", "hybridExtractSecretKeyFromEncapsulation", "getRemainingSignatures", "getKeyState", "deleteKeyState", "generateKeyPair", "exportKey", "importKey", "rotateKey", "getKeyMetadata", "listKeys", "expireKey", "revokeKey" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The operation to perform" }, 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..e2d3c2ac17e8f 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 @@ -17,7 +17,7 @@ DNSJava. The component is a thin layer on top of http://www.xbill.org/dnsjava/[DNSJava]. The component offers the following operations: -* `ip`: to resolve a domain by its ip +* `ip`: to resolve a domain to its ip * `lookup`: to lookup information about the domain * `dig`: to run DNS queries @@ -97,7 +97,7 @@ YAML:: This looks up a domain's IP. For example, _www.example.com_ resolves to 192.0.32.10. -The IP address to lookup must be provided in the header with key `"CamelDnsDomain"`. +The domain to resolve must be provided in the header with key `"CamelDnsDomain"`. === DNS lookup @@ -135,7 +135,7 @@ YAML:: ---- ==== -This returns a set of DNS records associated with a domain. + +This returns the DNS records associated with a domain, as an array of `org.xbill.DNS.Record`. + The name to lookup must be provided in the header with key `"CamelDnsName"`. 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..93cab2b50627a 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 @@ -121,14 +121,15 @@ YAML:: |pullRequest |polling |`org.kohsuke.github.GHPullRequest` -|pullRequestComment |polling |`org.kohsuke.github.GHPullRequestReviewComment` +|pullRequestComment |polling |`org.kohsuke.github.GHIssueComment` |tag |polling |`org.kohsuke.github.GHTag` |commit |polling |`org.kohsuke.github.GHCommit` or `String` with commit message and headers with some metadata. This can be configured by the `commitMessageAsBody` option. -|event |polling |`org.kohsuke.github.GHEventInfo` +|event |polling |`String` with the type of the event, such as `PUSH`, and the `org.kohsuke.github.GHEventInfo` in the +`CamelGitHubEventPayload` header |======================================================================= === Producer Endpoints @@ -147,7 +148,8 @@ pull request discussion is assumed. |createIssue |String (issue body text) | - `CamelGitHubIssueTitle` (String) (REQUIRED): Issue Title. -|pullRequestState |none | - `CamelGitHubPullRequest` (integer) (REQUIRED): Pull request number. +|pullRequestState |String (description of the status) | - `CamelGitHubPullRequestHeadCommitSha` (String) (REQUIRED): The sha +of the commit to set the status on. Sets the commit status on a pull request. |pullRequestFiles |none | - `CamelGitHubPullRequest` (integer) (REQUIRED): Pull request number. diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/infinispan-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/infinispan-component.adoc index a6a5b9645c520..0cf7dff60b1fb 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/infinispan-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/infinispan-component.adoc @@ -66,8 +66,8 @@ This section lists all available operations, along with their header information ** `CamelInfinispanLifespanTimeUnit` ** `CamelInfinispanMaxIdleTime` ** `CamelInfinispanMaxIdleTimeUnit` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Put All Operations [cols="40%,60%a", options="header"] @@ -106,8 +106,8 @@ The resulting value is returned in the exchange *body*. * *Required Headers* ** `CamelInfinispanKey` -* *Result Header* -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Contains Value Operation [cols="40%,60%a", options="header"] @@ -118,8 +118,8 @@ The resulting value is returned in the exchange *body*. * *Required Headers*: ** `CamelInfinispanValue` -* *Result Header* -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Remove Operations [cols="40%,60%a", options="header"] @@ -133,8 +133,8 @@ The resulting value is returned in the exchange *body*. ** `CamelInfinispanValue` * *Optional Headers*: ** `CamelInfinispanValue` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Replace Operations [cols="40%,60%a", options="header"] @@ -153,8 +153,8 @@ The resulting value is returned in the exchange *body*. ** `CamelInfinispanLifespanTimeUnit` ** `CamelInfinispanMaxIdleTime` ** `CamelInfinispanMaxIdleTimeUnit` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Clear Operations [cols="40%,60%a", options="header"] @@ -171,8 +171,8 @@ The resulting value is returned in the exchange *body*. | `InfinispanOperation.SIZE` | Returns the number of entries in the cache |=== -* *Result Header* -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Stats Operation [cols="40%,60%a", options="header"] @@ -181,8 +181,8 @@ The resulting value is returned in the exchange *body*. | `InfinispanOperation.STATS` | Returns statistics about the cache |=== -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Query Operation [cols="40%,60%a", options="header"] @@ -213,11 +213,13 @@ Java:: from("direct:start") .setHeader("CamelInfinispanOperation").constant("PUT") // <1> .setHeader("CamelInfinispanKey").constant("123") // <2> - .to("infinispan:myCacheName?cacheContainer=#cacheContainer"); // <3> + .setHeader("CamelInfinispanValue").constant("Hello") // <3> + .to("infinispan:myCacheName?cacheContainer=#cacheContainer"); // <4> ---- <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> Set the value to store: the message body is not used +<4> Use the configured cache manager `cacheContainer` from the registry to put an element to the cache named `myCacheName` XML:: + @@ -231,6 +233,9 @@ XML:: 123 + + Hello + ---- @@ -249,6 +254,9 @@ YAML:: - setHeader: name: CamelInfinispanKey constant: "123" + - setHeader: + name: CamelInfinispanValue + constant: Hello - to: uri: infinispan:myCacheName parameters: 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 6be7f5019d0f8..3c9b623f0233f 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 @@ -81,8 +81,8 @@ This section lists all available operations, along with their header information ** `CamelInfinispanLifespanTimeUnit` ** `CamelInfinispanMaxIdleTime` ** `CamelInfinispanMaxIdleTimeUnit` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Put All Operations [cols="40%,60%a", options="header"] @@ -120,8 +120,8 @@ This section lists all available operations, along with their header information * *Required Headers* ** `CamelInfinispanKey` -* *Result Header* -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Contains Value Operation [cols="40%,60%a", options="header"] @@ -146,8 +146,8 @@ This section lists all available operations, along with their header information ** `CamelInfinispanKey` * *Optional Headers*: ** `CamelInfinispanValue` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Replace Operations [cols="40%,60%a", options="header"] @@ -166,8 +166,8 @@ This section lists all available operations, along with their header information ** `CamelInfinispanLifespanTimeUnit` ** `CamelInfinispanMaxIdleTime` ** `CamelInfinispanMaxIdleTimeUnit` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Clear Operations [cols="40%,60%a", options="header"] @@ -184,8 +184,8 @@ This section lists all available operations, along with their header information | `InfinispanOperation.SIZE` | Returns the number of entries in the cache |=== -* *Result Header* -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Stats Operation [cols="40%,60%a", options="header"] @@ -194,8 +194,8 @@ This section lists all available operations, along with their header information | `InfinispanOperation.STATS` | Returns statistics about the cache |=== -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Query Operation [cols="40%,60%a", options="header"] @@ -206,8 +206,8 @@ This section lists all available operations, along with their header information * *Required Headers*: ** `CamelInfinispanQueryBuilder` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option [NOTE] ==== @@ -225,11 +225,13 @@ Write methods like put(key, value) and remove(key) do not return the previous va from("direct:start") .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUT) // <1> .setHeader(InfinispanConstants.KEY).constant("123") // <2> - .to("infinispan-embedded:myCacheName?cacheContainer=#cacheContainer"); // <3> + .setHeader(InfinispanConstants.VALUE).constant("Hello") // <3> + .to("infinispan-embedded:myCacheName?cacheContainer=#cacheContainer"); // <4> ---- <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> Set the value to store: the message body is not used +<4> Use the configured cache manager `cacheContainer` from the registry to put an element to the cache named `myCacheName` -- + It is possible to configure the lifetime and/or the idle time before the entry expires and gets evicted from the cache, as example: diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jira-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jira-component.adoc index 62980d5331554..8f47121aa03e0 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jira-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jira-component.adoc @@ -238,7 +238,7 @@ Optional: Required: * `CamelJiraIssueKey`: The issue key identifier. -* the body of the exchange is the description. +* the body of the exchange is the text of the comment. === Attach @@ -247,7 +247,8 @@ Only one file should attach per invocation. Required: * `CamelJiraIssueKey`: The issue key identifier. -* body of the exchange should be of type `File` +* the body of the exchange is the file to attach: a `File`, the file of the file consumer, or text, bytes or a stream, +named by the `CamelFileName` header === DeleteIssue @@ -261,7 +262,10 @@ Required: * `CamelJiraIssueKey`: The issue key identifier. * `CamelJiraIssueTransitionId`: The issue transition `id`. -* the body of the exchange is the description. + +Optional: + +* the body of the exchange is a comment to add to the issue after the transition. === UpdateIssue diff --git a/components/camel-caffeine/src/generated/resources/META-INF/org/apache/camel/component/caffeine/cache/caffeine-cache.json b/components/camel-caffeine/src/generated/resources/META-INF/org/apache/camel/component/caffeine/cache/caffeine-cache.json index 268c39da8b4d9..7e1cada6d649c 100644 --- a/components/camel-caffeine/src/generated/resources/META-INF/org/apache/camel/component/caffeine/cache/caffeine-cache.json +++ b/components/camel-caffeine/src/generated/resources/META-INF/org/apache/camel/component/caffeine/cache/caffeine-cache.json @@ -51,6 +51,10 @@ "CamelCaffeineValue": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of key for all put actions (PUT or PUT_ALL).", "constantName": "org.apache.camel.component.caffeine.CaffeineConstants#VALUE" }, "CamelCaffeineOldValue": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The old value returned according to the action.", "constantName": "org.apache.camel.component.caffeine.CaffeineConstants#OLD_VALUE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The value to store for PUT, converted to the valueType when set, and a Map of the entries for PUT_ALL, unless the CamelCaffeineValue header gives it; without either they fail. The other actions do not use the body" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "action", "value": "GET_ALL", "carriers": [ "map" ], "javaType": "java.util.Map" }, { "option": "action", "value": "AS_MAP", "carriers": [ "map" ], "javaType": "java.util.concurrent.ConcurrentMap" }, { "option": "action", "value": "PUT", "carriers": [ "unchanged" ] }, { "option": "action", "value": "PUT_ALL", "carriers": [ "unchanged" ] }, { "option": "action", "value": "INVALIDATE", "carriers": [ "unchanged" ] }, { "option": "action", "value": "INVALIDATE_ALL", "carriers": [ "unchanged" ] }, { "option": "action", "value": "CLEANUP", "carriers": [ "unchanged" ] } ], "description": "By the action, which the CamelCaffeineAction header can set: the value of the key for GET, or the body as it was when the key is not in the cache, a Map of the entries found for GET_ALL, and the cache as a Map for AS_MAP. The other actions keep the body" } + }, "properties": { "cacheName": { "index": 0, "kind": "path", "displayName": "Cache Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Cache name" }, "action": { "index": 1, "kind": "parameter", "displayName": "Action", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "GET", "GET_ALL", "PUT", "PUT_ALL", "INVALIDATE", "INVALIDATE_ALL", "CLEANUP", "AS_MAP" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.caffeine.CaffeineConfiguration", "configurationField": "configuration", "description": "To configure the default cache action. If an action is set in the message header, then the operation from the header takes precedence." }, diff --git a/components/camel-caffeine/src/generated/resources/META-INF/org/apache/camel/component/caffeine/load/caffeine-loadcache.json b/components/camel-caffeine/src/generated/resources/META-INF/org/apache/camel/component/caffeine/load/caffeine-loadcache.json index 2ce307d4d9dc4..32a660551b7f2 100644 --- a/components/camel-caffeine/src/generated/resources/META-INF/org/apache/camel/component/caffeine/load/caffeine-loadcache.json +++ b/components/camel-caffeine/src/generated/resources/META-INF/org/apache/camel/component/caffeine/load/caffeine-loadcache.json @@ -51,6 +51,10 @@ "CamelCaffeineValue": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of key for all put actions (PUT or PUT_ALL).", "constantName": "org.apache.camel.component.caffeine.CaffeineConstants#VALUE" }, "CamelCaffeineOldValue": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The old value returned according to the action.", "constantName": "org.apache.camel.component.caffeine.CaffeineConstants#OLD_VALUE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The value to store for PUT, converted to the valueType when set, and a Map of the entries for PUT_ALL, unless the CamelCaffeineValue header gives it; without either they fail. The other actions do not use the body" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "action", "value": "GET_ALL", "carriers": [ "map" ], "javaType": "java.util.Map" }, { "option": "action", "value": "AS_MAP", "carriers": [ "map" ], "javaType": "java.util.concurrent.ConcurrentMap" }, { "option": "action", "value": "PUT", "carriers": [ "unchanged" ] }, { "option": "action", "value": "PUT_ALL", "carriers": [ "unchanged" ] }, { "option": "action", "value": "INVALIDATE", "carriers": [ "unchanged" ] }, { "option": "action", "value": "INVALIDATE_ALL", "carriers": [ "unchanged" ] }, { "option": "action", "value": "CLEANUP", "carriers": [ "unchanged" ] } ], "description": "By the action, which the CamelCaffeineAction header can set: the value of the key for GET, from the cache or else the cacheLoader, or the body as it was when the loader gives null, a Map of the entries found or loaded for GET_ALL, and the cache as a Map for AS_MAP. The other actions keep the body" } + }, "properties": { "cacheName": { "index": 0, "kind": "path", "displayName": "Cache Name", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "the cache name" }, "action": { "index": 1, "kind": "parameter", "displayName": "Action", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "GET", "GET_ALL", "PUT", "PUT_ALL", "INVALIDATE", "INVALIDATE_ALL", "CLEANUP", "AS_MAP" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.caffeine.CaffeineConfiguration", "configurationField": "configuration", "description": "To configure the default cache action. If an action is set in the message header, then the operation from the header takes precedence." }, diff --git a/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/cache/CaffeineCacheEndpoint.java b/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/cache/CaffeineCacheEndpoint.java index 8ed4bb8c919c2..f894367f75dc0 100644 --- a/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/cache/CaffeineCacheEndpoint.java +++ b/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/cache/CaffeineCacheEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.Producer; import org.apache.camel.component.caffeine.CaffeineConfiguration; import org.apache.camel.component.caffeine.CaffeineConstants; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -38,6 +41,27 @@ remote = false, internal = true, syntax = "caffeine-cache:cacheName", category = { Category.CACHE, Category.CLUSTERING }, producerOnly = true, headersClass = CaffeineConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The value to store for PUT, converted to the valueType when set, and a Map of" + + " the entries for PUT_ALL, unless the CamelCaffeineValue header gives it;" + + " without either they fail. The other actions do not use the body"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "action", value = "GET_ALL", carriers = Carrier.MAP, + javaType = "java.util.Map"), + @BodyType.When(option = "action", value = "AS_MAP", carriers = Carrier.MAP, + javaType = "java.util.concurrent.ConcurrentMap"), + @BodyType.When(option = "action", value = "PUT", carriers = Carrier.UNCHANGED), + @BodyType.When(option = "action", value = "PUT_ALL", carriers = Carrier.UNCHANGED), + @BodyType.When(option = "action", value = "INVALIDATE", + carriers = Carrier.UNCHANGED), + @BodyType.When(option = "action", value = "INVALIDATE_ALL", + carriers = Carrier.UNCHANGED), + @BodyType.When(option = "action", value = "CLEANUP", carriers = Carrier.UNCHANGED) }, + description = "By the action, which the CamelCaffeineAction header can set: the value of the" + + " key for GET, or the body as it was when the key is not in the cache, a Map" + + " of the entries found for GET_ALL, and the cache as a Map for AS_MAP. The" + + " other actions keep the body")) public class CaffeineCacheEndpoint extends DefaultEndpoint { @UriPath(description = "Cache name") diff --git a/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/load/CaffeineLoadCacheEndpoint.java b/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/load/CaffeineLoadCacheEndpoint.java index 755d0b779957b..58bcf8183d7b3 100644 --- a/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/load/CaffeineLoadCacheEndpoint.java +++ b/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/load/CaffeineLoadCacheEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.Producer; import org.apache.camel.component.caffeine.CaffeineConfiguration; import org.apache.camel.component.caffeine.CaffeineConstants; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -38,6 +41,28 @@ remote = false, internal = true, syntax = "caffeine-loadcache:cacheName", category = { Category.CACHE, Category.CLUSTERING }, producerOnly = true, headersClass = CaffeineConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The value to store for PUT, converted to the valueType when set, and a Map of" + + " the entries for PUT_ALL, unless the CamelCaffeineValue header gives it;" + + " without either they fail. The other actions do not use the body"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "action", value = "GET_ALL", carriers = Carrier.MAP, + javaType = "java.util.Map"), + @BodyType.When(option = "action", value = "AS_MAP", carriers = Carrier.MAP, + javaType = "java.util.concurrent.ConcurrentMap"), + @BodyType.When(option = "action", value = "PUT", carriers = Carrier.UNCHANGED), + @BodyType.When(option = "action", value = "PUT_ALL", carriers = Carrier.UNCHANGED), + @BodyType.When(option = "action", value = "INVALIDATE", + carriers = Carrier.UNCHANGED), + @BodyType.When(option = "action", value = "INVALIDATE_ALL", + carriers = Carrier.UNCHANGED), + @BodyType.When(option = "action", value = "CLEANUP", carriers = Carrier.UNCHANGED) }, + description = "By the action, which the CamelCaffeineAction header can set: the value of the" + + " key for GET, from the cache or else the cacheLoader, or the body as it was" + + " when the loader gives null, a Map of the entries found or loaded for" + + " GET_ALL, and the cache as a Map for AS_MAP. The other actions keep the" + + " body")) public class CaffeineLoadCacheEndpoint extends DefaultEndpoint { @UriPath(description = "the cache name") @Metadata(required = true) 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..065d7bed0e5bf 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 @@ -35,6 +35,10 @@ "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" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The body is not used: the name to query is in a header, CamelDnsDomain for ip, CamelDnsName for lookup and dig, and CamelDnsTerm for wikipedia" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "dnsType", "value": "ip", "carriers": [ "pojo" ], "javaType": "java.net.InetAddress" }, { "option": "dnsType", "value": "lookup", "carriers": [ "list" ], "javaType": "org.xbill.DNS.Record[]" }, { "option": "dnsType", "value": "dig", "carriers": [ "pojo" ], "javaType": "org.xbill.DNS.Message" }, { "option": "dnsType", "value": "wikipedia", "carriers": [ "text", "null" ] } ], "description": "By the type: for ip the InetAddress of the domain, which converts to the address as text; for lookup the records of the answer as an array of Record, and the lookup fails when there are none; for dig the response Message; for wikipedia the text of the first TXT record, or no body" } + }, "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." }, "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..e2d3c2ac17e8f 100644 --- a/components/camel-dns/src/main/docs/dns-component.adoc +++ b/components/camel-dns/src/main/docs/dns-component.adoc @@ -17,7 +17,7 @@ DNSJava. The component is a thin layer on top of http://www.xbill.org/dnsjava/[DNSJava]. The component offers the following operations: -* `ip`: to resolve a domain by its ip +* `ip`: to resolve a domain to its ip * `lookup`: to lookup information about the domain * `dig`: to run DNS queries @@ -97,7 +97,7 @@ YAML:: This looks up a domain's IP. For example, _www.example.com_ resolves to 192.0.32.10. -The IP address to lookup must be provided in the header with key `"CamelDnsDomain"`. +The domain to resolve must be provided in the header with key `"CamelDnsDomain"`. === DNS lookup @@ -135,7 +135,7 @@ YAML:: ---- ==== -This returns a set of DNS records associated with a domain. + +This returns the DNS records associated with a domain, as an array of `org.xbill.DNS.Record`. + The name to lookup must be provided in the header with key `"CamelDnsName"`. 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..7a57bfe3d357c 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 @@ -21,6 +21,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriPath; @@ -31,6 +34,23 @@ */ @UriEndpoint(firstVersion = "2.7.0", scheme = "dns", title = "DNS", syntax = "dns:dnsType", producerOnly = true, category = { Category.NETWORKING }, headersClass = DnsConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The body is not used: the name to query is in a header, CamelDnsDomain for ip," + + " CamelDnsName for lookup and dig, and CamelDnsTerm for wikipedia"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "dnsType", value = "ip", carriers = Carrier.POJO, + javaType = "java.net.InetAddress"), + @BodyType.When(option = "dnsType", value = "lookup", carriers = Carrier.LIST, + javaType = "org.xbill.DNS.Record[]"), + @BodyType.When(option = "dnsType", value = "dig", carriers = Carrier.POJO, + javaType = "org.xbill.DNS.Message"), + @BodyType.When(option = "dnsType", value = "wikipedia", + carriers = { Carrier.TEXT, Carrier.NULL }) }, + description = "By the type: for ip the InetAddress of the domain, which converts to the" + + " address as text; for lookup the records of the answer as an array of" + + " Record, and the lookup fails when there are none; for dig the response" + + " Message; for wikipedia the text of the first TXT record, or no body")) public class DnsEndpoint extends DefaultEndpoint { @UriPath 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..236cd99c08057 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 @@ -43,6 +43,11 @@ "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" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "null" ], "byOption": [ { "option": "commitMessageAsBody", "value": "false", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHCommit" }, { "option": "type", "value": "PULLREQUEST", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHPullRequest" }, { "option": "type", "value": "PULLREQUESTCOMMENT", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHIssueComment" }, { "option": "type", "value": "TAG", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHTag" }, { "option": "type", "value": "EVENT", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "One message per new item, oldest first. commit gives the commit message (null when the data of the commit cannot be loaded), or the GHCommit with commitMessageAsBody=false, and event the type of the event, such as PUSH, with the GHEventInfo in the CamelGitHubEventPayload header" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "type", "value": "PULLREQUESTCOMMENT", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "CREATEISSUE", "carriers": [ "null", "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "PULLREQUESTSTATE", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "Read as text: the comment for pullRequestComment, which needs a body, and the description of the issue for createIssue and of the commit status for pullRequestState; a Map or a POJO is sent as its toString(), so marshal it first. getCommitFile reads the sha from the body when the CamelGitHubCommitSha header is not set, and the other types read only headers" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "type", "value": "CLOSEPULLREQUEST", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHPullRequest" }, { "option": "type", "value": "PULLREQUESTCOMMENT", "carriers": [ "pojo", "unchanged" ] }, { "option": "type", "value": "PULLREQUESTSTATE", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHCommitStatus" }, { "option": "type", "value": "PULLREQUESTFILES", "carriers": [ "list" ], "javaType": "java.util.List" }, { "option": "type", "value": "GETCOMMITFILE", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "type", "value": "CREATEISSUE", "carriers": [ "pojo" ], "javaType": "org.kohsuke.github.GHIssue" } ], "description": "The GHPullRequest as read before the close for closePullRequest, the GHIssueComment for pullRequestComment when the exchange expects a reply (InOut), otherwise the body is unchanged, the GHCommitStatus for pullRequestState, a List of GHPullRequestFileDetail for pullRequestFiles, the content of the file as text for getCommitFile, and the GHIssue for createIssue" } + }, "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" }, "branchName": { "index": 1, "kind": "path", "displayName": "Branch Name", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of branch" }, diff --git a/components/camel-github2/src/main/docs/github2-component.adoc b/components/camel-github2/src/main/docs/github2-component.adoc index 446143a8382c9..93cab2b50627a 100644 --- a/components/camel-github2/src/main/docs/github2-component.adoc +++ b/components/camel-github2/src/main/docs/github2-component.adoc @@ -121,14 +121,15 @@ YAML:: |pullRequest |polling |`org.kohsuke.github.GHPullRequest` -|pullRequestComment |polling |`org.kohsuke.github.GHPullRequestReviewComment` +|pullRequestComment |polling |`org.kohsuke.github.GHIssueComment` |tag |polling |`org.kohsuke.github.GHTag` |commit |polling |`org.kohsuke.github.GHCommit` or `String` with commit message and headers with some metadata. This can be configured by the `commitMessageAsBody` option. -|event |polling |`org.kohsuke.github.GHEventInfo` +|event |polling |`String` with the type of the event, such as `PUSH`, and the `org.kohsuke.github.GHEventInfo` in the +`CamelGitHubEventPayload` header |======================================================================= === Producer Endpoints @@ -147,7 +148,8 @@ pull request discussion is assumed. |createIssue |String (issue body text) | - `CamelGitHubIssueTitle` (String) (REQUIRED): Issue Title. -|pullRequestState |none | - `CamelGitHubPullRequest` (integer) (REQUIRED): Pull request number. +|pullRequestState |String (description of the status) | - `CamelGitHubPullRequestHeadCommitSha` (String) (REQUIRED): The sha +of the commit to set the status on. Sets the commit status on a pull request. |pullRequestFiles |none | - `CamelGitHubPullRequest` (integer) (REQUIRED): Pull request number. 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..ba76c037e7908 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 @@ -32,6 +32,9 @@ import org.apache.camel.component.github2.producer.PullRequestCommentProducer; import org.apache.camel.component.github2.producer.PullRequestFilesProducer; import org.apache.camel.component.github2.producer.PullRequestStateProducer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -58,6 +61,62 @@ */ @UriEndpoint(firstVersion = "4.18.0", scheme = "github2", title = "GitHub2", syntax = "github2:type/branchName", category = { Category.FILE, Category.CLOUD, Category.API }, headersClass = GitHub2Constants.class) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.NULL }, + byOption = { + @BodyType.When(option = "commitMessageAsBody", value = "false", + carriers = Carrier.POJO, javaType = "org.kohsuke.github.GHCommit"), + @BodyType.When(option = "type", value = "PULLREQUEST", carriers = Carrier.POJO, + javaType = "org.kohsuke.github.GHPullRequest"), + @BodyType.When(option = "type", value = "PULLREQUESTCOMMENT", + carriers = Carrier.POJO, + javaType = "org.kohsuke.github.GHIssueComment"), + @BodyType.When(option = "type", value = "TAG", carriers = Carrier.POJO, + javaType = "org.kohsuke.github.GHTag"), + @BodyType.When(option = "type", value = "EVENT", carriers = Carrier.TEXT, + javaType = "java.lang.String") }, + description = "One message per new item, oldest first. commit gives the commit message (null" + + " when the data of the commit cannot be loaded), or the GHCommit with" + + " commitMessageAsBody=false, and event the type of the event, such as PUSH," + + " with the GHEventInfo in the CamelGitHubEventPayload header"), + producerIn = @BodyType(value = Carrier.ANY, + byOption = { + @BodyType.When(option = "type", value = "PULLREQUESTCOMMENT", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), + @BodyType.When(option = "type", value = "CREATEISSUE", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }), + @BodyType.When(option = "type", value = "PULLREQUESTSTATE", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }) }, + description = "Read as text: the comment for pullRequestComment, which needs a body, and the" + + " description of the issue for createIssue and of the commit status for" + + " pullRequestState; a Map or a POJO is sent as its toString(), so marshal it" + + " first. getCommitFile reads the sha from the body when the" + + " CamelGitHubCommitSha header is not set, and the other types read only" + + " headers"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "type", value = "CLOSEPULLREQUEST", carriers = Carrier.POJO, + javaType = "org.kohsuke.github.GHPullRequest"), + @BodyType.When(option = "type", value = "PULLREQUESTCOMMENT", + carriers = { Carrier.POJO, Carrier.UNCHANGED }), + @BodyType.When(option = "type", value = "PULLREQUESTSTATE", carriers = Carrier.POJO, + javaType = "org.kohsuke.github.GHCommitStatus"), + @BodyType.When(option = "type", value = "PULLREQUESTFILES", carriers = Carrier.LIST, + javaType = "java.util.List"), + @BodyType.When(option = "type", value = "GETCOMMITFILE", carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "type", value = "CREATEISSUE", carriers = Carrier.POJO, + javaType = "org.kohsuke.github.GHIssue") }, + description = "The GHPullRequest as read before the close for closePullRequest, the" + + " GHIssueComment for pullRequestComment when the exchange expects a reply" + + " (InOut), otherwise the body is unchanged, the GHCommitStatus for" + + " pullRequestState, a List of GHPullRequestFileDetail for pullRequestFiles," + + " the content of the file as text for getCommitFile, and the GHIssue for" + + " createIssue")) public class GitHub2Endpoint extends ScheduledPollEndpoint implements EndpointServiceLocation { @UriPath 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 c50ae628c8993..cf0d4383893de 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 @@ -69,6 +69,11 @@ "CamelInfinispanOriginLocal": { "index": 20, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "true if the call originated on the local cache instance; false if originated from a remote one.", "constantName": "org.apache.camel.component.infinispan.InfinispanConstants#ORIGIN_LOCAL" }, "CamelInfinispanCurrentState": { "index": 21, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "True if this event is generated from an existing entry as the listener has Listener.", "constantName": "org.apache.camel.component.infinispan.InfinispanConstants#CURRENT_STATE" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "dependsOn": [ "customListener" ], "description": "No body: the event type, the cache name and the key of the entry are in headers, and the value, when the event has one, in the CamelInfinispanEventData header" }, + "producerIn": { "carriers": [ "any" ], "description": "The body is not used: the key, the value and the Map for PUTALL come from the CamelInfinispanKey, CamelInfinispanValue and CamelInfinispanMap headers, or the key and value options" }, + "producerOut": { "carriers": [ "unknown" ], "dependsOn": [ "resultHeader" ], "byOption": [ { "option": "operation", "value": "PUTASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "PUTALL", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "PUTALLASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "PUTIFABSENTASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "CONTAINSKEY", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "CONTAINSVALUE", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "REMOVEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "REPLACEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "SIZE", "carriers": [ "value" ], "javaType": "java.lang.Integer" }, { "option": "operation", "value": "CLEAR", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "CLEARASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "QUERY", "carriers": [ "list", "unchanged" ] }, { "option": "operation", "value": "STATS", "carriers": [ "pojo" ], "javaType": "org.infinispan.stats.Stats" }, { "option": "operation", "value": "COMPUTEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" } ], "description": "The result of the operation, which the CamelInfinispanOperation header can set: the value for GET, or null when the key is not in the cache, the previous value for PUT, the default, a Boolean for CONTAINSKEY, an Integer for SIZE, a List for QUERY and a CompletableFuture for the ASYNC operations; PUTALL and CLEAR keep the body. With resultHeader the result goes to that header and the body is kept" } + }, "properties": { "cacheName": { "index": 0, "kind": "path", "displayName": "Cache Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the cache to use. Use current to use the existing cache name from the currently configured cached manager. Or use default for the default cache manager name." }, "queryBuilder": { "index": 1, "kind": "parameter", "displayName": "Query Builder", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.infinispan.InfinispanQueryBuilder", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.embedded.InfinispanEmbeddedConfiguration", "configurationField": "configuration", "description": "Specifies the query builder." }, 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 6be7f5019d0f8..3c9b623f0233f 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 @@ -81,8 +81,8 @@ This section lists all available operations, along with their header information ** `CamelInfinispanLifespanTimeUnit` ** `CamelInfinispanMaxIdleTime` ** `CamelInfinispanMaxIdleTimeUnit` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Put All Operations [cols="40%,60%a", options="header"] @@ -120,8 +120,8 @@ This section lists all available operations, along with their header information * *Required Headers* ** `CamelInfinispanKey` -* *Result Header* -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Contains Value Operation [cols="40%,60%a", options="header"] @@ -146,8 +146,8 @@ This section lists all available operations, along with their header information ** `CamelInfinispanKey` * *Optional Headers*: ** `CamelInfinispanValue` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Replace Operations [cols="40%,60%a", options="header"] @@ -166,8 +166,8 @@ This section lists all available operations, along with their header information ** `CamelInfinispanLifespanTimeUnit` ** `CamelInfinispanMaxIdleTime` ** `CamelInfinispanMaxIdleTimeUnit` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Clear Operations [cols="40%,60%a", options="header"] @@ -184,8 +184,8 @@ This section lists all available operations, along with their header information | `InfinispanOperation.SIZE` | Returns the number of entries in the cache |=== -* *Result Header* -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Stats Operation [cols="40%,60%a", options="header"] @@ -194,8 +194,8 @@ This section lists all available operations, along with their header information | `InfinispanOperation.STATS` | Returns statistics about the cache |=== -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Query Operation [cols="40%,60%a", options="header"] @@ -206,8 +206,8 @@ This section lists all available operations, along with their header information * *Required Headers*: ** `CamelInfinispanQueryBuilder` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option [NOTE] ==== @@ -225,11 +225,13 @@ Write methods like put(key, value) and remove(key) do not return the previous va from("direct:start") .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUT) // <1> .setHeader(InfinispanConstants.KEY).constant("123") // <2> - .to("infinispan-embedded:myCacheName?cacheContainer=#cacheContainer"); // <3> + .setHeader(InfinispanConstants.VALUE).constant("Hello") // <3> + .to("infinispan-embedded:myCacheName?cacheContainer=#cacheContainer"); // <4> ---- <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> Set the value to store: the message body is not used +<4> Use the configured cache manager `cacheContainer` from the registry to put an element to the cache named `myCacheName` -- + It is possible to configure the lifetime and/or the idle time before the entry expires and gets evicted from the cache, as example: diff --git a/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedEndpoint.java b/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedEndpoint.java index 711209647812c..1191173e3e225 100644 --- a/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedEndpoint.java +++ b/components/camel-infinispan/camel-infinispan-embedded/src/main/java/org/apache/camel/component/infinispan/embedded/InfinispanEmbeddedEndpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.component.infinispan.InfinispanComponent; import org.apache.camel.component.infinispan.InfinispanConstants; import org.apache.camel.component.infinispan.InfinispanEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -36,6 +39,50 @@ @UriEndpoint(firstVersion = "2.13.0", scheme = SCHEME_EMBEDDED, title = "Infinispan Embedded", syntax = "infinispan-embedded:cacheName", category = { Category.CACHE, Category.CLUSTERING }, headersClass = InfinispanConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.NULL, dependsOn = "customListener", + description = "No body: the event type, the cache name and the key of the entry are in" + + " headers, and the value, when the event has one, in the" + + " CamelInfinispanEventData header"), + producerIn = @BodyType(value = Carrier.ANY, + description = "The body is not used: the key, the value and the Map for PUTALL come from the" + + " CamelInfinispanKey, CamelInfinispanValue and CamelInfinispanMap headers, or" + + " the key and value options"), + producerOut = @BodyType(value = Carrier.UNKNOWN, dependsOn = "resultHeader", + byOption = { + @BodyType.When(option = "operation", value = "PUTASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "PUTALL", carriers = Carrier.UNCHANGED), + @BodyType.When(option = "operation", value = "PUTALLASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "PUTIFABSENTASYNC", + carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "CONTAINSKEY", carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "CONTAINSVALUE", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "REMOVEASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "REPLACEASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "SIZE", carriers = Carrier.VALUE, + javaType = "java.lang.Integer"), + @BodyType.When(option = "operation", value = "CLEAR", carriers = Carrier.UNCHANGED), + @BodyType.When(option = "operation", value = "CLEARASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "QUERY", + carriers = { Carrier.LIST, Carrier.UNCHANGED }), + @BodyType.When(option = "operation", value = "STATS", carriers = Carrier.POJO, + javaType = "org.infinispan.stats.Stats"), + @BodyType.When(option = "operation", value = "COMPUTEASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture") }, + description = "The result of the operation, which the CamelInfinispanOperation header can" + + " set: the value for GET, or null when the key is not in the cache, the" + + " previous value for PUT, the default, a Boolean for CONTAINSKEY, an Integer" + + " for SIZE, a List for QUERY and a CompletableFuture for the ASYNC" + + " operations; PUTALL and CLEAR keep the body. With resultHeader the result" + + " goes to that header and the body is kept")) public class InfinispanEmbeddedEndpoint extends InfinispanEndpoint { @UriPath(description = "The name of the cache to use. Use current to use the existing cache name from the currently configured cached manager. Or use default for the default cache manager name.") diff --git a/components/camel-infinispan/camel-infinispan/src/generated/resources/META-INF/org/apache/camel/component/infinispan/remote/infinispan.json b/components/camel-infinispan/camel-infinispan/src/generated/resources/META-INF/org/apache/camel/component/infinispan/remote/infinispan.json index 39e6f3ebde04f..d7949aa592fbb 100644 --- a/components/camel-infinispan/camel-infinispan/src/generated/resources/META-INF/org/apache/camel/component/infinispan/remote/infinispan.json +++ b/components/camel-infinispan/camel-infinispan/src/generated/resources/META-INF/org/apache/camel/component/infinispan/remote/infinispan.json @@ -78,6 +78,11 @@ "CamelInfinispanEntryVersion": { "index": 16, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Provides access to the version of the created cache entry.", "constantName": "org.apache.camel.component.infinispan.InfinispanConstants#ENTRY_VERSION" }, "CamelInfinispanCommandRetried": { "index": 17, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "This will be true if the write command that caused this had to be retried again due to a topology change.", "constantName": "org.apache.camel.component.infinispan.InfinispanConstants#COMMAND_RETRIED" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "null" ], "dependsOn": [ "customListener" ], "description": "No body: the event type, the cache name and the key of the entry are in headers, and for the events of a continuous query (queryBuilder) the value in the CamelInfinispanEventData header" }, + "producerIn": { "carriers": [ "any" ], "description": "The body is not used: the key, the value and the Map for PUTALL come from the CamelInfinispanKey, CamelInfinispanValue and CamelInfinispanMap headers, or the key and value options" }, + "producerOut": { "carriers": [ "unknown" ], "dependsOn": [ "resultHeader" ], "byOption": [ { "option": "operation", "value": "PUTASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "PUTALL", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "PUTALLASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "PUTIFABSENTASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "CONTAINSKEY", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "CONTAINSVALUE", "carriers": [ "value" ], "javaType": "java.lang.Boolean" }, { "option": "operation", "value": "REMOVEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "REPLACEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "SIZE", "carriers": [ "value" ], "javaType": "java.lang.Integer" }, { "option": "operation", "value": "CLEAR", "carriers": [ "unchanged" ] }, { "option": "operation", "value": "CLEARASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" }, { "option": "operation", "value": "QUERY", "carriers": [ "list", "unchanged" ] }, { "option": "operation", "value": "STATS", "carriers": [ "pojo" ], "javaType": "org.infinispan.client.hotrod.ServerStatistics" }, { "option": "operation", "value": "COMPUTEASYNC", "carriers": [ "pojo" ], "javaType": "java.util.concurrent.CompletableFuture" } ], "description": "The result of the operation, which the CamelInfinispanOperation header can set: the value for GET, the previous value for PUT, the default, which is null unless the FORCE_RETURN_VALUE flag is set, a Boolean for CONTAINSKEY, an Integer for SIZE, a List for QUERY and a CompletableFuture for the ASYNC operations; PUTALL and CLEAR keep the body. With resultHeader the result goes to that header and the body is kept" } + }, "properties": { "cacheName": { "index": 0, "kind": "path", "displayName": "Cache Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the cache to use. Use current to use the existing cache name from the currently configured cached manager. Or use default for the default cache manager name." }, "hosts": { "index": 1, "kind": "parameter", "displayName": "Hosts", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration", "configurationField": "configuration", "description": "Specifies the host of the cache on Infinispan instance. Multiple hosts can be separated by semicolon." }, diff --git a/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc b/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc index a6a5b9645c520..0cf7dff60b1fb 100644 --- a/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc +++ b/components/camel-infinispan/camel-infinispan/src/main/docs/infinispan-component.adoc @@ -66,8 +66,8 @@ This section lists all available operations, along with their header information ** `CamelInfinispanLifespanTimeUnit` ** `CamelInfinispanMaxIdleTime` ** `CamelInfinispanMaxIdleTimeUnit` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Put All Operations [cols="40%,60%a", options="header"] @@ -106,8 +106,8 @@ The resulting value is returned in the exchange *body*. * *Required Headers* ** `CamelInfinispanKey` -* *Result Header* -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Contains Value Operation [cols="40%,60%a", options="header"] @@ -118,8 +118,8 @@ The resulting value is returned in the exchange *body*. * *Required Headers*: ** `CamelInfinispanValue` -* *Result Header* -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Remove Operations [cols="40%,60%a", options="header"] @@ -133,8 +133,8 @@ The resulting value is returned in the exchange *body*. ** `CamelInfinispanValue` * *Optional Headers*: ** `CamelInfinispanValue` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Replace Operations [cols="40%,60%a", options="header"] @@ -153,8 +153,8 @@ The resulting value is returned in the exchange *body*. ** `CamelInfinispanLifespanTimeUnit` ** `CamelInfinispanMaxIdleTime` ** `CamelInfinispanMaxIdleTimeUnit` -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Clear Operations [cols="40%,60%a", options="header"] @@ -171,8 +171,8 @@ The resulting value is returned in the exchange *body*. | `InfinispanOperation.SIZE` | Returns the number of entries in the cache |=== -* *Result Header* -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Stats Operation [cols="40%,60%a", options="header"] @@ -181,8 +181,8 @@ The resulting value is returned in the exchange *body*. | `InfinispanOperation.STATS` | Returns statistics about the cache |=== -* *Result Header*: -** `CamelInfinispanOperationResult` +* *Result*: +** the message body, or the header named by the `resultHeader` option .Query Operation [cols="40%,60%a", options="header"] @@ -213,11 +213,13 @@ Java:: from("direct:start") .setHeader("CamelInfinispanOperation").constant("PUT") // <1> .setHeader("CamelInfinispanKey").constant("123") // <2> - .to("infinispan:myCacheName?cacheContainer=#cacheContainer"); // <3> + .setHeader("CamelInfinispanValue").constant("Hello") // <3> + .to("infinispan:myCacheName?cacheContainer=#cacheContainer"); // <4> ---- <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> Set the value to store: the message body is not used +<4> Use the configured cache manager `cacheContainer` from the registry to put an element to the cache named `myCacheName` XML:: + @@ -231,6 +233,9 @@ XML:: 123 + + Hello + ---- @@ -249,6 +254,9 @@ YAML:: - setHeader: name: CamelInfinispanKey constant: "123" + - setHeader: + name: CamelInfinispanValue + constant: Hello - to: uri: infinispan:myCacheName parameters: diff --git a/components/camel-infinispan/camel-infinispan/src/main/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteEndpoint.java b/components/camel-infinispan/camel-infinispan/src/main/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteEndpoint.java index c5c9c633e0f85..4b566f620f3b2 100644 --- a/components/camel-infinispan/camel-infinispan/src/main/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteEndpoint.java +++ b/components/camel-infinispan/camel-infinispan/src/main/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteEndpoint.java @@ -25,6 +25,9 @@ import org.apache.camel.component.infinispan.InfinispanComponent; import org.apache.camel.component.infinispan.InfinispanConstants; import org.apache.camel.component.infinispan.InfinispanEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -39,6 +42,50 @@ */ @UriEndpoint(firstVersion = "2.13.0", scheme = SCHEME_INFINISPAN, title = "Infinispan", syntax = "infinispan:cacheName", category = { Category.CACHE, Category.CLUSTERING }, headersClass = InfinispanConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.NULL, dependsOn = "customListener", + description = "No body: the event type, the cache name and the key of the entry are in" + + " headers, and for the events of a continuous query (queryBuilder) the value" + + " in the CamelInfinispanEventData header"), + producerIn = @BodyType(value = Carrier.ANY, + description = "The body is not used: the key, the value and the Map for PUTALL come from the" + + " CamelInfinispanKey, CamelInfinispanValue and CamelInfinispanMap headers, or" + + " the key and value options"), + producerOut = @BodyType(value = Carrier.UNKNOWN, dependsOn = "resultHeader", + byOption = { + @BodyType.When(option = "operation", value = "PUTASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "PUTALL", carriers = Carrier.UNCHANGED), + @BodyType.When(option = "operation", value = "PUTALLASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "PUTIFABSENTASYNC", + carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "CONTAINSKEY", carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "CONTAINSVALUE", + carriers = Carrier.VALUE, + javaType = "java.lang.Boolean"), + @BodyType.When(option = "operation", value = "REMOVEASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "REPLACEASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "SIZE", carriers = Carrier.VALUE, + javaType = "java.lang.Integer"), + @BodyType.When(option = "operation", value = "CLEAR", carriers = Carrier.UNCHANGED), + @BodyType.When(option = "operation", value = "CLEARASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture"), + @BodyType.When(option = "operation", value = "QUERY", + carriers = { Carrier.LIST, Carrier.UNCHANGED }), + @BodyType.When(option = "operation", value = "STATS", carriers = Carrier.POJO, + javaType = "org.infinispan.client.hotrod.ServerStatistics"), + @BodyType.When(option = "operation", value = "COMPUTEASYNC", carriers = Carrier.POJO, + javaType = "java.util.concurrent.CompletableFuture") }, + description = "The result of the operation, which the CamelInfinispanOperation header can" + + " set: the value for GET, the previous value for PUT, the default, which is" + + " null unless the FORCE_RETURN_VALUE flag is set, a Boolean for CONTAINSKEY," + + " an Integer for SIZE, a List for QUERY and a CompletableFuture for the" + + " ASYNC operations; PUTALL and CLEAR keep the body. With resultHeader the" + + " result goes to that header and the body is kept")) public class InfinispanRemoteEndpoint extends InfinispanEndpoint implements EndpointServiceLocation { @UriPath(description = "The name of the cache to use. Use current to use the existing cache name from the currently configured cached manager. Or use default for the default cache manager name.") diff --git a/components/camel-jira/src/generated/resources/META-INF/org/apache/camel/component/jira/jira.json b/components/camel-jira/src/generated/resources/META-INF/org/apache/camel/component/jira/jira.json index 2b0b518a69fe2..947280f4bdc1a 100644 --- a/components/camel-jira/src/generated/resources/META-INF/org/apache/camel/component/jira/jira.json +++ b/components/camel-jira/src/generated/resources/META-INF/org/apache/camel/component/jira/jira.json @@ -60,6 +60,11 @@ "CamelJiraLinkType": { "index": 17, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The type of link", "constantName": "org.apache.camel.component.jira.JiraConstants#LINK_TYPE" }, "CamelJiraMinutesSpent": { "index": 18, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": "-1", "description": "The minutes spent", "constantName": "org.apache.camel.component.jira.JiraConstants#MINUTES_SPENT" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "pojo", "null" ], "dependsOn": [ "watchedFields" ], "byOption": [ { "option": "sendOnlyUpdatedField", "value": "false", "carriers": [ "pojo" ], "javaType": "com.atlassian.jira.rest.client.api.domain.Issue" }, { "option": "type", "value": "NEWISSUES", "carriers": [ "pojo" ], "javaType": "com.atlassian.jira.rest.client.api.domain.Issue" }, { "option": "type", "value": "NEWCOMMENTS", "carriers": [ "pojo" ], "javaType": "com.atlassian.jira.rest.client.api.domain.Comment" } ], "description": "One message per new Issue (newIssues) or new Comment (newComments). watchUpdates sends one per watched field that changed, with its new value, such as the Status or the BasicPriority (null when cleared), or the Issue with sendOnlyUpdatedField=false" }, + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "type", "value": "ADDISSUE", "carriers": [ "null", "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "UPDATEISSUE", "carriers": [ "null", "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "TRANSITIONISSUE", "carriers": [ "null", "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "ADDISSUELINK", "carriers": [ "null", "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "ADDCOMMENT", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "ADDWORKLOG", "carriers": [ "text", "bytes", "stream", "file" ] }, { "option": "type", "value": "ATTACH", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "Read as text: the description for addIssue and updateIssue, the comment for addComment and addWorkLog, which fail without a body, and an optional comment for transitionIssue and addIssueLink; a Map or a POJO is sent as its toString(), so marshal it first. attach uploads a file, or text, bytes or a stream named by the CamelFileName header. The other types read only headers" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "type", "value": "ADDISSUE", "carriers": [ "pojo" ], "javaType": "com.atlassian.jira.rest.client.api.domain.Issue" }, { "option": "type", "value": "FETCHISSUE", "carriers": [ "pojo" ], "javaType": "com.atlassian.jira.rest.client.api.domain.Issue" }, { "option": "type", "value": "FETCHCOMMENTS", "carriers": [ "list" ], "javaType": "java.util.List" } ], "description": "The Issue created for addIssue, the Issue for fetchIssue and the List of its Comments for fetchComments. The other types leave the body unchanged" } + }, "properties": { "type": { "index": 0, "kind": "path", "displayName": "Type", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.jira.JiraType", "enum": [ "ADDCOMMENT", "ADDISSUE", "ATTACH", "DELETEISSUE", "NEWISSUES", "NEWCOMMENTS", "WATCHUPDATES", "UPDATEISSUE", "TRANSITIONISSUE", "WATCHERS", "ADDISSUELINK", "ADDWORKLOG", "FETCHISSUE", "FETCHCOMMENTS" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Operation to perform. Consumers: NewIssues, NewComments. Producers: AddIssue, AttachFile, DeleteIssue, TransitionIssue, UpdateIssue, Watchers. See this class javadoc description for more information." }, "delay": { "index": 1, "kind": "parameter", "displayName": "Delay", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 6000, "configurationClass": "org.apache.camel.component.jira.JiraConfiguration", "configurationField": "configuration", "description": "Time in milliseconds to elapse for the next poll." }, diff --git a/components/camel-jira/src/main/docs/jira-component.adoc b/components/camel-jira/src/main/docs/jira-component.adoc index 62980d5331554..8f47121aa03e0 100644 --- a/components/camel-jira/src/main/docs/jira-component.adoc +++ b/components/camel-jira/src/main/docs/jira-component.adoc @@ -238,7 +238,7 @@ Optional: Required: * `CamelJiraIssueKey`: The issue key identifier. -* the body of the exchange is the description. +* the body of the exchange is the text of the comment. === Attach @@ -247,7 +247,8 @@ Only one file should attach per invocation. Required: * `CamelJiraIssueKey`: The issue key identifier. -* body of the exchange should be of type `File` +* the body of the exchange is the file to attach: a `File`, the file of the file consumer, or text, bytes or a stream, +named by the `CamelFileName` header === DeleteIssue @@ -261,7 +262,10 @@ Required: * `CamelJiraIssueKey`: The issue key identifier. * `CamelJiraIssueTransitionId`: The issue transition `id`. -* the body of the exchange is the description. + +Optional: + +* the body of the exchange is a comment to add to the issue after the transition. === UpdateIssue diff --git a/components/camel-jira/src/main/java/org/apache/camel/component/jira/JiraEndpoint.java b/components/camel-jira/src/main/java/org/apache/camel/component/jira/JiraEndpoint.java index aeb9797330d78..b763caabafa1a 100644 --- a/components/camel-jira/src/main/java/org/apache/camel/component/jira/JiraEndpoint.java +++ b/components/camel-jira/src/main/java/org/apache/camel/component/jira/JiraEndpoint.java @@ -42,6 +42,9 @@ import org.apache.camel.component.jira.producer.TransitionIssueProducer; import org.apache.camel.component.jira.producer.UpdateIssueProducer; import org.apache.camel.component.jira.producer.WatcherProducer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.Registry; @@ -78,6 +81,62 @@ */ @UriEndpoint(firstVersion = "3.0", scheme = "jira", title = "Jira", syntax = "jira:type", category = { Category.DOCUMENT }, headersClass = JiraConstants.class) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.POJO, Carrier.NULL }, dependsOn = "watchedFields", + byOption = { + @BodyType.When(option = "sendOnlyUpdatedField", value = "false", + carriers = Carrier.POJO, + javaType = "com.atlassian.jira.rest.client.api.domain.Issue"), + @BodyType.When(option = "type", value = "NEWISSUES", carriers = Carrier.POJO, + javaType = "com.atlassian.jira.rest.client.api.domain.Issue"), + @BodyType.When(option = "type", value = "NEWCOMMENTS", carriers = Carrier.POJO, + javaType = "com.atlassian.jira.rest.client.api.domain.Comment") }, + description = "One message per new Issue (newIssues) or new Comment (newComments)." + + " watchUpdates sends one per watched field that changed, with its new value," + + " such as the Status or the BasicPriority (null when cleared), or the Issue" + + " with sendOnlyUpdatedField=false"), + producerIn = @BodyType(value = Carrier.ANY, + byOption = { + @BodyType.When(option = "type", value = "ADDISSUE", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }), + @BodyType.When(option = "type", value = "UPDATEISSUE", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }), + @BodyType.When(option = "type", value = "TRANSITIONISSUE", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }), + @BodyType.When(option = "type", value = "ADDISSUELINK", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }), + @BodyType.When(option = "type", value = "ADDCOMMENT", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), + @BodyType.When(option = "type", value = "ADDWORKLOG", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), + @BodyType.When(option = "type", value = "ATTACH", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }) }, + description = "Read as text: the description for addIssue and updateIssue, the comment for" + + " addComment and addWorkLog, which fail without a body, and an optional" + + " comment for transitionIssue and addIssueLink; a Map or a POJO is sent as" + + " its toString(), so marshal it first. attach uploads a file, or text, bytes" + + " or a stream named by the CamelFileName header. The other types read only" + + " headers"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + byOption = { + @BodyType.When(option = "type", value = "ADDISSUE", carriers = Carrier.POJO, + javaType = "com.atlassian.jira.rest.client.api.domain.Issue"), + @BodyType.When(option = "type", value = "FETCHISSUE", carriers = Carrier.POJO, + javaType = "com.atlassian.jira.rest.client.api.domain.Issue"), + @BodyType.When(option = "type", value = "FETCHCOMMENTS", carriers = Carrier.LIST, + javaType = "java.util.List") }, + description = "The Issue created for addIssue, the Issue for fetchIssue and the List of its" + + " Comments for fetchComments. The other types leave the body unchanged")) public class JiraEndpoint extends ScheduledPollEndpoint implements EndpointServiceLocation { private static final Logger LOG = LoggerFactory.getLogger(JiraEndpoint.class); diff --git a/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json b/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json index 39a2d8dc3ff6c..c3aeb57ed7375 100644 --- a/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json +++ b/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/pqc.json @@ -81,6 +81,10 @@ "CamelPQCHybridEncapsulation": { "index": 21, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "byte[]", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The hybrid encapsulation combining both classical and PQC encapsulations", "constantName": "org.apache.camel.component.pqc.PQCConstants#HYBRID_ENCAPSULATION" }, "CamelPQCHybridVerification": { "index": 22, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The verification result of hybrid signature (both must pass)", "constantName": "org.apache.camel.component.pqc.PQCConstants#HYBRID_VERIFY" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "byOption": [ { "option": "operation", "value": "sign", "carriers": [ "text", "bytes", "stream" ] }, { "option": "operation", "value": "verify", "carriers": [ "text", "bytes", "stream" ] }, { "option": "operation", "value": "hybridSign", "carriers": [ "text", "bytes", "stream" ] }, { "option": "operation", "value": "hybridVerify", "carriers": [ "text", "bytes", "stream" ] }, { "option": "operation", "value": "extractSecretKeyEncapsulation", "carriers": [ "pojo" ], "javaType": "org.bouncycastle.jcajce.SecretKeyWithEncapsulation" }, { "option": "operation", "value": "extractSecretKeyFromEncapsulation", "carriers": [ "pojo" ], "javaType": "org.bouncycastle.jcajce.SecretKeyWithEncapsulation" }, { "option": "operation", "value": "importKey", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "The payload of sign, verify, hybridSign and hybridVerify: bytes or a stream as they are, text as UTF-8; another body is signed as its text, so marshal it first. extractSecretKeyEncapsulation and extractSecretKeyFromEncapsulation take the SecretKeyWithEncapsulation that generateSecretKeyEncapsulation gives, and importKey the key as bytes, or as text for PEM. The other operations do not use the body" }, + "producerOut": { "carriers": [ "unchanged" ], "byOption": [ { "option": "operation", "value": "generateSecretKeyEncapsulation", "carriers": [ "pojo" ], "javaType": "org.bouncycastle.jcajce.SecretKeyWithEncapsulation" }, { "option": "operation", "value": "extractSecretKeyEncapsulation", "carriers": [ "pojo" ], "javaType": "org.bouncycastle.jcajce.SecretKeyWithEncapsulation" }, { "option": "operation", "value": "extractSecretKeyFromEncapsulation", "carriers": [ "pojo" ], "javaType": "javax.crypto.SecretKey" }, { "option": "operation", "value": "hybridGenerateSecretKeyEncapsulation", "carriers": [ "pojo" ], "javaType": "javax.crypto.SecretKey" }, { "option": "operation", "value": "hybridExtractSecretKeyEncapsulation", "carriers": [ "pojo" ], "javaType": "javax.crypto.SecretKey" }, { "option": "operation", "value": "hybridExtractSecretKeyFromEncapsulation", "carriers": [ "pojo" ], "javaType": "javax.crypto.SecretKey" }, { "option": "storeExtractedSecretKeyAsHeader", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for the signature and key operations, which set their results in headers, such as CamelPQCSignature and CamelPQCVerification. generateSecretKeyEncapsulation and extractSecretKeyEncapsulation give a SecretKeyWithEncapsulation, and the other key encapsulation operations the SecretKey; with storeExtractedSecretKeyAsHeader=true the key is in the CamelPQCSecretKey header instead" } + }, "properties": { "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "Logical name" }, "operation": { "index": 1, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": true, "type": "enum", "javaType": "org.apache.camel.component.pqc.PQCOperations", "enum": [ "sign", "verify", "hybridSign", "hybridVerify", "generateSecretKeyEncapsulation", "extractSecretKeyEncapsulation", "extractSecretKeyFromEncapsulation", "hybridGenerateSecretKeyEncapsulation", "hybridExtractSecretKeyEncapsulation", "hybridExtractSecretKeyFromEncapsulation", "getRemainingSignatures", "getKeyState", "deleteKeyState", "generateKeyPair", "exportKey", "importKey", "rotateKey", "getKeyMetadata", "listKeys", "expireKey", "revokeKey" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.pqc.PQCConfiguration", "configurationField": "configuration", "description": "The operation to perform" }, diff --git a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCEndpoint.java b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCEndpoint.java index 3a78b651d698d..a70d51872e1ee 100644 --- a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCEndpoint.java +++ b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/PQCEndpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.support.DefaultEndpoint; @@ -35,6 +38,57 @@ @UriEndpoint(firstVersion = "4.12.0", scheme = "pqc", title = "PQC Algorithms", syntax = "pqc:label", producerOnly = true, category = { Category.SECURITY }, headersClass = PQCConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + byOption = { + @BodyType.When(option = "operation", value = "sign", + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM }), + @BodyType.When(option = "operation", value = "verify", + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM }), + @BodyType.When(option = "operation", value = "hybridSign", + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM }), + @BodyType.When(option = "operation", value = "hybridVerify", + carriers = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM }), + @BodyType.When(option = "operation", value = "extractSecretKeyEncapsulation", + carriers = Carrier.POJO, + javaType = "org.bouncycastle.jcajce.SecretKeyWithEncapsulation"), + @BodyType.When(option = "operation", value = "extractSecretKeyFromEncapsulation", + carriers = Carrier.POJO, + javaType = "org.bouncycastle.jcajce.SecretKeyWithEncapsulation"), + @BodyType.When(option = "operation", value = "importKey", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }) }, + description = "The payload of sign, verify, hybridSign and hybridVerify: bytes or a stream as" + + " they are, text as UTF-8; another body is signed as its text, so marshal it" + + " first. extractSecretKeyEncapsulation and extractSecretKeyFromEncapsulation" + + " take the SecretKeyWithEncapsulation that generateSecretKeyEncapsulation" + + " gives, and importKey the key as bytes, or as text for PEM. The other" + + " operations do not use the body"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + byOption = { + @BodyType.When(option = "operation", value = "generateSecretKeyEncapsulation", + carriers = Carrier.POJO, + javaType = "org.bouncycastle.jcajce.SecretKeyWithEncapsulation"), + @BodyType.When(option = "operation", value = "extractSecretKeyEncapsulation", + carriers = Carrier.POJO, + javaType = "org.bouncycastle.jcajce.SecretKeyWithEncapsulation"), + @BodyType.When(option = "operation", value = "extractSecretKeyFromEncapsulation", + carriers = Carrier.POJO, javaType = "javax.crypto.SecretKey"), + @BodyType.When(option = "operation", value = "hybridGenerateSecretKeyEncapsulation", + carriers = Carrier.POJO, javaType = "javax.crypto.SecretKey"), + @BodyType.When(option = "operation", value = "hybridExtractSecretKeyEncapsulation", + carriers = Carrier.POJO, javaType = "javax.crypto.SecretKey"), + @BodyType.When(option = "operation", + value = "hybridExtractSecretKeyFromEncapsulation", + carriers = Carrier.POJO, javaType = "javax.crypto.SecretKey"), + @BodyType.When(option = "storeExtractedSecretKeyAsHeader", value = "true", + carriers = Carrier.UNCHANGED) }, + description = "Unchanged for the signature and key operations, which set their results in" + + " headers, such as CamelPQCSignature and CamelPQCVerification." + + " generateSecretKeyEncapsulation and extractSecretKeyEncapsulation give a" + + " SecretKeyWithEncapsulation, and the other key encapsulation operations the" + + " SecretKey; with storeExtractedSecretKeyAsHeader=true the key is in the" + + " CamelPQCSecretKey header instead")) public class PQCEndpoint extends DefaultEndpoint { @UriParam diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java index e3640b1b22536..def082d4063b5 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CatalogBodyTypes.java @@ -249,6 +249,15 @@ private static Answer answer(BodyTypeModel side, Map set, Set w.getOption().equals(option) && value.equalsIgnoreCase(w.getValue()))) { + // the body depends on this option, and no option value of the side says the body for its value: the + // value another option names does not hold then, such as output=bytes with a resultHandlerFactory + return null; + } + } Answer matched = null; for (OptionBodyTypeModel when : side.getByOption()) { String value = set.get(when.getOption()); diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java index 333ecc82ed601..0f15009a19dcb 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java @@ -1007,6 +1007,78 @@ public void testTheOptionsTheBodyDependsOn() { .contains("to: file needs the body as text, bytes, a stream or a file, but the body here is parsed data")); } + @Test + public void testTheBodyOfCachesAndSigning() { + // pqc signs text, bytes or a stream, so parsed data must be marshalled first; a caffeine PUT keeps the body, + // so the parsed data is still there for the file producer, while an infinispan GET gives what the cache holds + String yaml = """ + - route: + id: sign + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: pqc:sign?operation=sign + - route: + id: put + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: caffeine-cache:orders?action=PUT&key=1 + - to: file:out + - route: + id: get + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: infinispan:orders?operation=GET&key=1 + - to: file:out + """; + assertThat(lines(yaml)).hasSize(2) + .anySatisfy(m -> assertThat(m).contains("route sign: to: pqc needs the body as text, bytes or a stream")) + .anySatisfy(m -> assertThat(m) + .contains("route put: to: file needs the body as text, bytes, a stream or a file")); + } + + @Test + public void testAnOptionTheBodyDependsOnOutweighsAnotherOption() { + // xslt with output bytes gives bytes, so a field read needs an unmarshal; with a resultHandlerFactory too the + // factory decides the body, and output=bytes no longer says it + String yaml = """ + - route: + id: bytes + from: + uri: file:in + steps: + - to: xslt:order.xsl?output=bytes + - setHeader: + name: id + simple: ${body[id]} + - route: + id: factory + from: + uri: file:in + steps: + - to: xslt:order.xsl?output=bytes&resultHandlerFactory=#myFactory + - setHeader: + name: id + simple: ${body[id]} + """; + assertThat(lines(yaml)).singleElement().satisfies(m -> assertThat(m) + .contains("route bytes: simple reads a field of the body (${body[id]})")); + } + @Test public void testWhatTheComponentMayConfigureSaysNothing() { // the valueDeserializer of kafka and the operation of aws2-sqs can be set on the component, which the route From 0f439b6b95fd60ef0c531397f3bce391e4795add Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 22 Oct 2026 11:55:50 +0200 Subject: [PATCH 19/25] CAMEL-24961: azure-eventhubs - describe the body after the producer, as the other components do Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../org/apache/camel/catalog/components/azure-eventhubs.json | 2 +- .../camel/component/azure/eventhubs/azure-eventhubs.json | 2 +- .../camel/component/azure/eventhubs/EventHubsEndpoint.java | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-eventhubs.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-eventhubs.json index 7e092cf7ffb9e..a81217609b1a0 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-eventhubs.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-eventhubs.json @@ -63,7 +63,7 @@ "bodyTypes": { "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The body of the event, one message per event" }, "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "list" ], "description": "What converts to a byte array: text, bytes, a stream or a file, sent as one event; a Map, a number or a POJO fails: marshal it first. A List is sent as one event per element, in one batch, and an element that is an Exchange or a Message is sent with its headers" }, - "producerOut": { "carriers": [ "unchanged" ] } + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: a send gives no result, and no header is set" } }, "properties": { "namespace": { "index": 0, "kind": "path", "displayName": "Namespace", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.eventhubs.EventHubsConfiguration", "configurationField": "configuration", "description": "EventHubs namespace created in Azure Portal." }, diff --git a/components/camel-azure/camel-azure-eventhubs/src/generated/resources/META-INF/org/apache/camel/component/azure/eventhubs/azure-eventhubs.json b/components/camel-azure/camel-azure-eventhubs/src/generated/resources/META-INF/org/apache/camel/component/azure/eventhubs/azure-eventhubs.json index 7e092cf7ffb9e..a81217609b1a0 100644 --- a/components/camel-azure/camel-azure-eventhubs/src/generated/resources/META-INF/org/apache/camel/component/azure/eventhubs/azure-eventhubs.json +++ b/components/camel-azure/camel-azure-eventhubs/src/generated/resources/META-INF/org/apache/camel/component/azure/eventhubs/azure-eventhubs.json @@ -63,7 +63,7 @@ "bodyTypes": { "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The body of the event, one message per event" }, "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "list" ], "description": "What converts to a byte array: text, bytes, a stream or a file, sent as one event; a Map, a number or a POJO fails: marshal it first. A List is sent as one event per element, in one batch, and an element that is an Exchange or a Message is sent with its headers" }, - "producerOut": { "carriers": [ "unchanged" ] } + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: a send gives no result, and no header is set" } }, "properties": { "namespace": { "index": 0, "kind": "path", "displayName": "Namespace", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.eventhubs.EventHubsConfiguration", "configurationField": "configuration", "description": "EventHubs namespace created in Azure Portal." }, diff --git a/components/camel-azure/camel-azure-eventhubs/src/main/java/org/apache/camel/component/azure/eventhubs/EventHubsEndpoint.java b/components/camel-azure/camel-azure-eventhubs/src/main/java/org/apache/camel/component/azure/eventhubs/EventHubsEndpoint.java index 3416e25cd7959..dbd6c56782527 100644 --- a/components/camel-azure/camel-azure-eventhubs/src/main/java/org/apache/camel/component/azure/eventhubs/EventHubsEndpoint.java +++ b/components/camel-azure/camel-azure-eventhubs/src/main/java/org/apache/camel/component/azure/eventhubs/EventHubsEndpoint.java @@ -46,7 +46,8 @@ + " event; a Map, a number or a POJO fails: marshal it first. A List is sent" + " as one event per element, in one batch, and an element that is an Exchange" + " or a Message is sent with its headers"), - producerOut = @BodyType(Carrier.UNCHANGED)) + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged: a send gives no result, and no header is set")) public class EventHubsEndpoint extends DefaultEndpoint implements EndpointServiceLocation { @UriParam From 41fff210117fa0f2f2a3377a25a9feb4df15aaa4 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 22 Oct 2026 12:32:12 +0200 Subject: [PATCH 20/25] CAMEL-24961: The bodies a step needs say any, never unknown ref, dataformat, the language component and the ref language said unknown for the body they take. The bodies a step needs now have one word for whatever the body is, any, and the build refuses unknown there: unknown stays for the body after a step. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../org/apache/camel/catalog/components/dataformat.json | 2 +- .../org/apache/camel/catalog/components/language.json | 2 +- .../org/apache/camel/catalog/components/ref.json | 2 +- .../org/apache/camel/catalog/languages/ref.json | 2 +- .../apache/camel/component/dataformat/dataformat.json | 2 +- .../camel/component/dataformat/DataFormatEndpoint.java | 2 +- .../org/apache/camel/component/language/language.json | 2 +- .../camel/component/language/LanguageEndpoint.java | 2 +- .../META-INF/org/apache/camel/component/ref/ref.json | 2 +- .../java/org/apache/camel/component/ref/RefEndpoint.java | 2 +- .../generated/java/org/apache/camel/spi/BodyType.java | 2 +- .../META-INF/org/apache/camel/language/ref/ref.json | 2 +- .../java/org/apache/camel/language/ref/RefLanguage.java | 2 +- .../apache/camel/maven/packaging/BodyTypesHelper.java | 9 +++++++-- .../maven/packaging/EndpointSchemaGeneratorMojoTest.java | 1 + .../packaging/endpoint/SomeEndpointWithBadBodyTypes.java | 5 +++++ .../src/main/java/org/apache/camel/spi/BodyType.java | 2 +- 17 files changed, 27 insertions(+), 16 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataformat.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataformat.json index ce0269205d373..779f4c12753d9 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataformat.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/dataformat.json @@ -28,7 +28,7 @@ "autowiredEnabled": { "index": 1, "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." } }, "bodyTypes": { - "producerIn": { "carriers": [ "unknown" ], "description": "The body the data format named in the path takes, as for the marshal and unmarshal EIPs" }, + "producerIn": { "carriers": [ "any" ], "description": "The body the data format named in the path takes, as for the marshal and unmarshal EIPs" }, "producerOut": { "carriers": [ "unknown" ], "description": "The body the data format named in the path gives, as for the marshal and unmarshal EIPs" } }, "properties": { diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json index caacbaaccad4a..dcf729ff34def 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/language.json @@ -33,7 +33,7 @@ "CamelLanguageScript": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String or Expression", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The script to execute provided in the header. Takes precedence over script configured on the endpoint.", "constantName": "org.apache.camel.component.language.LanguageConstants#LANGUAGE_SCRIPT" } }, "bodyTypes": { - "producerIn": { "carriers": [ "unknown" ], "description": "The body as the language of the script reads it. The script is in the uri, the script option or a resource, or in the CamelLanguageScript header with allowTemplateFromHeader=true, and never in the body" }, + "producerIn": { "carriers": [ "any" ], "description": "The body as the language of the script reads it. The script is in the uri, the script option or a resource, or in the CamelLanguageScript header with allowTemplateFromHeader=true, and never in the body" }, "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "transform", "value": "false", "carriers": [ "unchanged" ] }, { "option": "binary", "value": "true", "carriers": [ "stream" ] } ], "description": "The result of the script, as the language gives it. Unchanged with transform=false. With binary=true the content of the resource as a stream, which is not evaluated" } }, "properties": { diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ref.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ref.json index 09ec81acc2563..93438a3abcf58 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ref.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/ref.json @@ -30,7 +30,7 @@ }, "bodyTypes": { "consumerOut": { "carriers": [ "unknown" ], "description": "The body the consumer of the endpoint in the registry gives" }, - "producerIn": { "carriers": [ "unknown" ], "description": "The bodies the producer of the endpoint in the registry takes" }, + "producerIn": { "carriers": [ "any" ], "description": "The bodies the producer of the endpoint in the registry takes" }, "producerOut": { "carriers": [ "unknown" ], "description": "The body the producer of the endpoint in the registry leaves" } }, "properties": { diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ref.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ref.json index 80776995a904c..18e2d383e0732 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ref.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/ref.json @@ -16,7 +16,7 @@ "modelJavaType": "org.apache.camel.model.language.RefExpression" }, "bodyTypes": { - "expressionIn": { "carriers": [ "unknown" ], "description": "As the expression or the predicate in the registry reads it" }, + "expressionIn": { "carriers": [ "any" ], "description": "As the expression or the predicate in the registry reads it" }, "expressionOut": { "carriers": [ "unknown" ], "description": "What the expression in the registry returns; a Boolean for a predicate" } }, "properties": { diff --git a/components/camel-dataformat/src/generated/resources/META-INF/org/apache/camel/component/dataformat/dataformat.json b/components/camel-dataformat/src/generated/resources/META-INF/org/apache/camel/component/dataformat/dataformat.json index ce0269205d373..779f4c12753d9 100644 --- a/components/camel-dataformat/src/generated/resources/META-INF/org/apache/camel/component/dataformat/dataformat.json +++ b/components/camel-dataformat/src/generated/resources/META-INF/org/apache/camel/component/dataformat/dataformat.json @@ -28,7 +28,7 @@ "autowiredEnabled": { "index": 1, "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." } }, "bodyTypes": { - "producerIn": { "carriers": [ "unknown" ], "description": "The body the data format named in the path takes, as for the marshal and unmarshal EIPs" }, + "producerIn": { "carriers": [ "any" ], "description": "The body the data format named in the path takes, as for the marshal and unmarshal EIPs" }, "producerOut": { "carriers": [ "unknown" ], "description": "The body the data format named in the path gives, as for the marshal and unmarshal EIPs" } }, "properties": { diff --git a/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatEndpoint.java b/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatEndpoint.java index 6e99495a687db..58b943e0115d3 100644 --- a/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatEndpoint.java +++ b/components/camel-dataformat/src/main/java/org/apache/camel/component/dataformat/DataFormatEndpoint.java @@ -43,7 +43,7 @@ @UriEndpoint(firstVersion = "2.12.0", scheme = "dataformat", title = "Data Format", syntax = "dataformat:name:operation", remote = false, producerOnly = true, category = { Category.CORE, Category.TRANSFORMATION }, lenientProperties = true) -@BodyTypes(producerIn = @BodyType(value = Carrier.UNKNOWN, +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, description = "The body the data format named in the path takes, as for the marshal and" + " unmarshal EIPs"), producerOut = @BodyType(value = Carrier.UNKNOWN, diff --git a/components/camel-language/src/generated/resources/META-INF/org/apache/camel/component/language/language.json b/components/camel-language/src/generated/resources/META-INF/org/apache/camel/component/language/language.json index caacbaaccad4a..dcf729ff34def 100644 --- a/components/camel-language/src/generated/resources/META-INF/org/apache/camel/component/language/language.json +++ b/components/camel-language/src/generated/resources/META-INF/org/apache/camel/component/language/language.json @@ -33,7 +33,7 @@ "CamelLanguageScript": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String or Expression", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The script to execute provided in the header. Takes precedence over script configured on the endpoint.", "constantName": "org.apache.camel.component.language.LanguageConstants#LANGUAGE_SCRIPT" } }, "bodyTypes": { - "producerIn": { "carriers": [ "unknown" ], "description": "The body as the language of the script reads it. The script is in the uri, the script option or a resource, or in the CamelLanguageScript header with allowTemplateFromHeader=true, and never in the body" }, + "producerIn": { "carriers": [ "any" ], "description": "The body as the language of the script reads it. The script is in the uri, the script option or a resource, or in the CamelLanguageScript header with allowTemplateFromHeader=true, and never in the body" }, "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "transform", "value": "false", "carriers": [ "unchanged" ] }, { "option": "binary", "value": "true", "carriers": [ "stream" ] } ], "description": "The result of the script, as the language gives it. Unchanged with transform=false. With binary=true the content of the resource as a stream, which is not evaluated" } }, "properties": { diff --git a/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java b/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java index bc4a2b97c1c81..2d736c0be1b0d 100644 --- a/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java +++ b/components/camel-language/src/main/java/org/apache/camel/component/language/LanguageEndpoint.java @@ -52,7 +52,7 @@ @UriEndpoint(firstVersion = "2.5.0", scheme = "language", title = "Language", syntax = "language:languageName:resourceUri", remote = false, producerOnly = true, category = { Category.CORE, Category.SCRIPT }, headersClass = LanguageConstants.class) -@BodyTypes(producerIn = @BodyType(value = Carrier.UNKNOWN, +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, description = "The body as the language of the script reads it. The script is in the uri," + " the script option or a resource, or in the CamelLanguageScript header with" + " allowTemplateFromHeader=true, and never in the body"), diff --git a/components/camel-ref/src/generated/resources/META-INF/org/apache/camel/component/ref/ref.json b/components/camel-ref/src/generated/resources/META-INF/org/apache/camel/component/ref/ref.json index 09ec81acc2563..93438a3abcf58 100644 --- a/components/camel-ref/src/generated/resources/META-INF/org/apache/camel/component/ref/ref.json +++ b/components/camel-ref/src/generated/resources/META-INF/org/apache/camel/component/ref/ref.json @@ -30,7 +30,7 @@ }, "bodyTypes": { "consumerOut": { "carriers": [ "unknown" ], "description": "The body the consumer of the endpoint in the registry gives" }, - "producerIn": { "carriers": [ "unknown" ], "description": "The bodies the producer of the endpoint in the registry takes" }, + "producerIn": { "carriers": [ "any" ], "description": "The bodies the producer of the endpoint in the registry takes" }, "producerOut": { "carriers": [ "unknown" ], "description": "The body the producer of the endpoint in the registry leaves" } }, "properties": { diff --git a/components/camel-ref/src/main/java/org/apache/camel/component/ref/RefEndpoint.java b/components/camel-ref/src/main/java/org/apache/camel/component/ref/RefEndpoint.java index e71b65a136113..d2f0410e051b5 100644 --- a/components/camel-ref/src/main/java/org/apache/camel/component/ref/RefEndpoint.java +++ b/components/camel-ref/src/main/java/org/apache/camel/component/ref/RefEndpoint.java @@ -39,7 +39,7 @@ remote = false, category = { Category.CORE }) @BodyTypes(consumerOut = @BodyType(value = Carrier.UNKNOWN, description = "The body the consumer of the endpoint in the registry gives"), - producerIn = @BodyType(value = Carrier.UNKNOWN, + producerIn = @BodyType(value = Carrier.ANY, description = "The bodies the producer of the endpoint in the registry takes"), producerOut = @BodyType(value = Carrier.UNKNOWN, description = "The body the producer of the endpoint in the registry leaves")) diff --git a/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java b/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java index 2d2cc3b927240..be2616566c95e 100644 --- a/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java +++ b/core/camel-api/src/generated/java/org/apache/camel/spi/BodyType.java @@ -133,7 +133,7 @@ enum Carrier { ANY("any"), /** * The body depends on what the other system sends, or on a class the user configures: tooling must not guess - * it. + * it. For the body after a step only: the bodies a step needs are ANY then. */ UNKNOWN("unknown"); diff --git a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/ref/ref.json b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/ref/ref.json index 80776995a904c..18e2d383e0732 100644 --- a/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/ref/ref.json +++ b/core/camel-core-languages/src/generated/resources/META-INF/org/apache/camel/language/ref/ref.json @@ -16,7 +16,7 @@ "modelJavaType": "org.apache.camel.model.language.RefExpression" }, "bodyTypes": { - "expressionIn": { "carriers": [ "unknown" ], "description": "As the expression or the predicate in the registry reads it" }, + "expressionIn": { "carriers": [ "any" ], "description": "As the expression or the predicate in the registry reads it" }, "expressionOut": { "carriers": [ "unknown" ], "description": "What the expression in the registry returns; a Boolean for a predicate" } }, "properties": { diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/ref/RefLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/ref/RefLanguage.java index e53648c662cca..0f13f18fc5c03 100644 --- a/core/camel-core-languages/src/main/java/org/apache/camel/language/ref/RefLanguage.java +++ b/core/camel-core-languages/src/main/java/org/apache/camel/language/ref/RefLanguage.java @@ -35,7 +35,7 @@ * A language for referred expressions or predicates. */ @Language("ref") -@BodyTypes(expressionIn = @BodyType(value = Carrier.UNKNOWN, +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, description = "As the expression or the predicate in the registry reads it"), expressionOut = @BodyType(value = Carrier.UNKNOWN, description = "What the expression in the registry returns; a Boolean for a predicate")) diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java index 8ce467e34661f..fdde7315fe116 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/BodyTypesHelper.java @@ -155,8 +155,9 @@ private static void checkValue(Class owner, String side, BodyType.When when, /** * A body has a carrier: an option value without one would say nothing. UNCHANGED is for the body after a step, such - * as a sql query that leaves it unchanged unless it is a select. ANY is for the bodies a step needs. ANY and - * UNKNOWN stand alone. + * as a sql query that leaves it unchanged unless it is a select. ANY is for the bodies a step needs, and UNKNOWN + * for the body after a step, so the bodies a step needs have one word for "whatever the body is". ANY and UNKNOWN + * stand alone. */ private static void check(Class owner, String side, Carrier[] carriers) { if (carriers.length == 0) { @@ -168,6 +169,10 @@ private static void check(Class owner, String side, Carrier[] carriers) { throw new IllegalArgumentException( owner.getName() + ": the @BodyTypes " + side + " is what a step needs, which cannot be unchanged"); } + if (in && list.contains(Carrier.UNKNOWN)) { + throw new IllegalArgumentException( + owner.getName() + ": the @BodyTypes " + side + " is what a step needs, which is any, not unknown"); + } if (!in && list.contains(Carrier.ANY)) { throw new IllegalArgumentException( owner.getName() + ": the @BodyTypes " + side + " is the body after a step, which cannot be any"); diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java index 24d5b3d86b84e..fc5e64ec4ade0 100644 --- a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/EndpointSchemaGeneratorMojoTest.java @@ -278,6 +278,7 @@ void testEndpointWithoutBodyTypes() throws Exception { @ValueSource(classes = { SomeEndpointWithBadBodyTypes.DataFormatSide.class, SomeEndpointWithBadBodyTypes.ProducerSideOfConsumer.class, SomeEndpointWithBadBodyTypes.UnchangedInput.class, SomeEndpointWithBadBodyTypes.AnyOutput.class, + SomeEndpointWithBadBodyTypes.UnknownInput.class, SomeEndpointWithBadBodyTypes.UnknownWithOthers.class, SomeEndpointWithBadBodyTypes.NoCarriers.class, SomeEndpointWithBadBodyTypes.UnknownOption.class, SomeEndpointWithBadBodyTypes.OptionValueWithoutCarriers.class, SomeEndpointWithBadBodyTypes.ValueTheOptionDoesNotHave.class }) diff --git a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java index 8c0f53728d6a6..9e3fc43a5f623 100644 --- a/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java +++ b/tooling/maven/camel-package-maven-plugin/src/test/java/org/apache/camel/maven/packaging/endpoint/SomeEndpointWithBadBodyTypes.java @@ -49,6 +49,11 @@ public static class UnchangedInput { public static class AnyOutput { } + @UriEndpoint(scheme = "some", syntax = "some", title = "some") + @BodyTypes(producerIn = @BodyType(Carrier.UNKNOWN)) + public static class UnknownInput { + } + @UriEndpoint(scheme = "some", syntax = "some", title = "some") @BodyTypes(producerOut = @BodyType({ Carrier.UNKNOWN, Carrier.TEXT })) public static class UnknownWithOthers { diff --git a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java index 2d2cc3b927240..be2616566c95e 100644 --- a/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java +++ b/tooling/spi-annotations/src/main/java/org/apache/camel/spi/BodyType.java @@ -133,7 +133,7 @@ enum Carrier { ANY("any"), /** * The body depends on what the other system sends, or on a class the user configures: tooling must not guess - * it. + * it. For the body after a step only: the bodies a step needs are ANY then. */ UNKNOWN("unknown"); From 6f5f37419378d9336888a36da6a0ce4c7c8d1b7f Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 22 Oct 2026 14:06:21 +0200 Subject: [PATCH 21/25] CAMEL-24961: Catalog body types for the templating, JSON and XML transform, and validator components The body types of velocity, freemarker, mustache, string-template, chunk, jte, thymeleaf, mvel, jolt, jslt, jsonata, xj, xquery, json-validator, schematron and bean-validator, and of the mvel and xquery languages, read from the code and checked at runtime with camel run. The docs of jolt and jsonata showed JSON text sent to the default options, which take parsed JSON; the examples now set inputType and outputType to JsonString. The template docs now say which context entries need allowContextMapAll and that the template headers need allowTemplateFromHeader, and a few other pages said things about the body or the template that the code does not do. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../catalog/components/bean-validator.json | 4 ++ .../camel/catalog/components/chunk.json | 4 ++ .../camel/catalog/components/freemarker.json | 4 ++ .../apache/camel/catalog/components/jolt.json | 4 ++ .../apache/camel/catalog/components/jslt.json | 4 ++ .../catalog/components/json-validator.json | 4 ++ .../camel/catalog/components/jsonata.json | 4 ++ .../apache/camel/catalog/components/jte.json | 4 ++ .../camel/catalog/components/mustache.json | 4 ++ .../apache/camel/catalog/components/mvel.json | 4 ++ .../camel/catalog/components/schematron.json | 4 ++ .../catalog/components/string-template.json | 4 ++ .../camel/catalog/components/thymeleaf.json | 4 ++ .../camel/catalog/components/velocity.json | 4 ++ .../apache/camel/catalog/components/xj.json | 4 ++ .../camel/catalog/components/xquery.json | 4 ++ .../camel/catalog/docs/chunk-component.adoc | 6 +- .../catalog/docs/freemarker-component.adoc | 12 ++-- .../camel/catalog/docs/jolt-component.adoc | 15 +++-- .../docs/json-validator-component.adoc | 2 +- .../camel/catalog/docs/jsonata-component.adoc | 21 +++++-- .../camel/catalog/docs/jte-component.adoc | 4 +- .../catalog/docs/mustache-component.adoc | 6 +- .../camel/catalog/docs/mvel-component.adoc | 6 +- .../docs/string-template-component.adoc | 11 ++-- .../catalog/docs/thymeleaf-component.adoc | 16 ++++-- .../catalog/docs/velocity-component.adoc | 6 +- .../camel/catalog/docs/xquery-component.adoc | 2 +- .../apache/camel/catalog/languages/mvel.json | 4 ++ .../camel/catalog/languages/xquery.json | 4 ++ .../bean/validator/bean-validator.json | 4 ++ .../bean/validator/BeanValidatorEndpoint.java | 10 ++++ .../apache/camel/component/chunk/chunk.json | 4 ++ .../src/main/docs/chunk-component.adoc | 6 +- .../camel/component/chunk/ChunkEndpoint.java | 11 ++++ .../component/freemarker/freemarker.json | 4 ++ .../src/main/docs/freemarker-component.adoc | 12 ++-- .../freemarker/FreemarkerEndpoint.java | 12 ++++ .../org/apache/camel/component/jolt/jolt.json | 4 ++ .../src/main/docs/jolt-component.adoc | 15 +++-- .../camel/component/jolt/JoltEndpoint.java | 16 ++++++ .../org/apache/camel/component/jslt/jslt.json | 4 ++ .../camel/component/jslt/JsltEndpoint.java | 9 +++ .../jsonvalidator/json-validator.json | 4 ++ .../main/docs/json-validator-component.adoc | 2 +- .../jsonvalidator/JsonValidatorEndpoint.java | 15 +++++ .../camel/component/jsonata/jsonata.json | 4 ++ .../src/main/docs/jsonata-component.adoc | 21 +++++-- .../component/jsonata/JsonataEndpoint.java | 17 ++++++ .../org/apache/camel/component/jte/jte.json | 4 ++ .../src/main/docs/jte-component.adoc | 4 +- .../camel/component/jte/JteEndpoint.java | 11 ++++ .../camel/component/mustache/mustache.json | 4 ++ .../src/main/docs/mustache-component.adoc | 6 +- .../component/mustache/MustacheEndpoint.java | 13 +++++ .../org/apache/camel/component/mvel/mvel.json | 4 ++ .../org/apache/camel/language/mvel/mvel.json | 4 ++ .../src/main/docs/mvel-component.adoc | 6 +- .../camel/component/mvel/MvelEndpoint.java | 10 ++++ .../camel/language/mvel/MvelLanguage.java | 7 +++ .../apache/camel/component/xquery/xquery.json | 4 ++ .../apache/camel/language/xquery/xquery.json | 4 ++ .../src/main/docs/xquery-component.adoc | 2 +- .../component/xquery/XQueryEndpoint.java | 25 +++++++++ .../camel/language/xquery/XQueryLanguage.java | 11 ++++ .../component/schematron/schematron.json | 4 ++ .../schematron/SchematronEndpoint.java | 12 ++++ .../stringtemplate/string-template.json | 4 ++ .../main/docs/string-template-component.adoc | 11 ++-- .../StringTemplateEndpoint.java | 13 +++++ .../camel/component/thymeleaf/thymeleaf.json | 4 ++ .../src/main/docs/thymeleaf-component.adoc | 16 ++++-- .../thymeleaf/ThymeleafEndpoint.java | 12 ++++ .../camel/component/velocity/velocity.json | 4 ++ .../src/main/docs/velocity-component.adoc | 6 +- .../component/velocity/VelocityEndpoint.java | 12 ++++ .../org/apache/camel/component/xj/xj.json | 4 ++ .../apache/camel/component/xj/XJEndpoint.java | 28 ++++++++++ .../dsl/yaml/validator/TextBodyFlowTest.java | 56 +++++++++++++++++++ 79 files changed, 582 insertions(+), 76 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/bean-validator.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/bean-validator.json index f7c5e0354c6ab..b90db05804387 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/bean-validator.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/bean-validator.json @@ -33,6 +33,10 @@ "validationProviderResolver": { "index": 6, "kind": "property", "displayName": "Validation Provider Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "jakarta.validation.ValidationProviderResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a a custom ValidationProviderResolver" }, "validatorFactory": { "index": 7, "kind": "property", "displayName": "Validator Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "jakarta.validation.ValidatorFactory", "deprecated": false, "autowired": true, "secret": false, "description": "To use a custom ValidatorFactory" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "pojo", "list" ], "description": "A POJO with Jakarta Bean Validation constraints, or a List or another Iterable of them, each one validated. Text, a Map or an array has no constraints of its own and passes unchecked; no body fails" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: a body that breaks a constraint fails with a BeanValidationException" } + }, "properties": { "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Where label is an arbitrary text value describing the endpoint" }, "group": { "index": 1, "kind": "parameter", "displayName": "Group", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "jakarta.validation.groups.Default", "description": "To use a custom validation group" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/chunk.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/chunk.json index edf6b67d18cb2..ae08f3605556d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/chunk.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/chunk.json @@ -34,6 +34,10 @@ "CamelChunkResourceUri": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A URI for the template resource to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.chunk.ChunkConstants#CHUNK_RESOURCE_URI" }, "CamelChunkTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.chunk.ChunkConstants#CHUNK_TEMPLATE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as {$body}, as it is: text, or a Map, a List or a POJO to read from; no body prints as empty text, and bytes or a stream are not read as text. The template is the resource, or the CamelChunkTemplate header with allowTemplateFromHeader=true, never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/freemarker.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/freemarker.json index 3075b7efead38..a0f18e467cb59 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/freemarker.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/freemarker.json @@ -37,6 +37,10 @@ "CamelFreemarkerTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.freemarker.FreemarkerConstants#FREEMARKER_TEMPLATE" }, "CamelFreemarkerDataModel": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Object", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The data model", "constantName": "org.apache.camel.component.freemarker.FreemarkerConstants#FREEMARKER_DATA_MODEL" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as body, as it is: text, or a Map, a List or a POJO to read from; convert bytes or a stream to a String first, and no body fails ${body} unless it is written ${body!}. The template is the resource, or the CamelFreemarkerTemplate or CamelFreemarkerResourceUri header with allowTemplateFromHeader=true, and never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, also when it is JSON or XML: unmarshal it to read its fields. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jolt.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jolt.json index 4f7c8a6e3cec9..0638b27c7f26a 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jolt.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jolt.json @@ -34,6 +34,10 @@ "CamelJoltResourceUri": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The resource URI", "constantName": "org.apache.camel.component.jolt.JoltConstants#JOLT_RESOURCE_URI" }, "CamelJoltContext": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The context", "constantName": "org.apache.camel.component.jolt.JoltConstants#JOLT_CONTEXT" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "map", "list" ], "format": "json", "byOption": [ { "option": "inputType", "value": "JsonString", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "Parsed JSON: a Map or a List. JSON as text, bytes, a stream or a file needs inputType=JsonString: without it the body reaches the spec unparsed, and the result is most likely null" }, + "producerOut": { "carriers": [ "map", "list" ], "format": "json", "byOption": [ { "option": "outputType", "value": "JsonString", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "The JSON the spec makes: a Map for an object, a List for an array; JSON text with outputType=JsonString" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowTemplateFromHeader": { "index": 1, "kind": "parameter", "displayName": "Allow Template From Header", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential security vulnerability if the header is coming from a malicious user, so use this with care." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jslt.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jslt.json index a82c39b84d52c..d60f5f1e048d2 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jslt.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jslt.json @@ -35,6 +35,10 @@ "CamelJsltString": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The JSLT Template as String", "constantName": "org.apache.camel.component.jslt.JsltConstants#HEADER_JSLT_STRING" }, "CamelJsltResourceUri": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The resource URI", "constantName": "org.apache.camel.component.jslt.JsltConstants#HEADER_JSLT_RESOURCE_URI" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json", "description": "JSON as text, bytes, a stream, a Reader or a java.io.File, such as the file of the file consumer. A Map, a List, a JsonNode or no body fails: marshal parsed JSON first" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "format": "json", "description": "The result as JSON text, pretty printed with prettyPrint=true" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/json-validator.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/json-validator.json index 48155c275cff2..ab867f3969f7e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/json-validator.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/json-validator.json @@ -30,6 +30,10 @@ "autowiredEnabled": { "index": 3, "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." }, "objectMapper": { "index": 4, "kind": "property", "displayName": "Object Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing ObjectMapper with the given id." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json", "dependsOn": [ "headerName" ], "byOption": [ { "option": "failOnNullBody", "value": "false", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "The JSON to validate: text, bytes, a stream or a file. A Map, a POJO or no body fails: marshal it first; with headerName the header is validated instead" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: JSON that does not match the schema, or text that is not JSON, fails with a JsonValidationException" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jsonata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jsonata.json index d6de7d1584da8..72d92ea7c5c85 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jsonata.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jsonata.json @@ -30,6 +30,10 @@ "autowiredEnabled": { "index": 3, "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." }, "frameBinding": { "index": 4, "kind": "property", "displayName": "Frame Binding", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.jsonata.JsonataFrameBinding", "deprecated": false, "autowired": false, "secret": false, "description": "To configure custom frame bindings and inject user functions." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "map", "list", "pojo" ], "format": "json", "byOption": [ { "option": "inputType", "value": "JsonString", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "JSON data: a Map, a List, a JsonNode or another object Jackson converts. JSON as text, bytes, a stream or a file needs inputType=JsonString: without it text is read as one JSON string, and bytes or a stream fail" }, + "producerOut": { "carriers": [ "pojo" ], "javaType": "com.fasterxml.jackson.databind.JsonNode", "format": "json", "byOption": [ { "option": "outputType", "value": "JsonString", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "The result as a Jackson JsonNode, or as JSON text with outputType=JsonString" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jte.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jte.json index 1d04e8d7d1d21..cfc4c8d5b8aff 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jte.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/jte.json @@ -38,6 +38,10 @@ "CamelJteTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.jte.JteConstants#JTE_TEMPLATE" }, "CamelJteDataModel": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Object", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The data model", "constantName": "org.apache.camel.component.jte.JteConstants#JTE_DATA_MODEL" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template takes an org.apache.camel.component.jte.Model: the body as it is in model.body, and converted to text by model.strBody(). With allowTemplateFromHeader=true the CamelJteDataModel header replaces the model" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, with leading and trailing whitespace trimmed. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mustache.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mustache.json index 97ba41b8eb31f..1ac15dcc8b4ad 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mustache.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mustache.json @@ -35,6 +35,10 @@ "CamelMustacheResourceUri": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A URI for the template resource to use instead of the endpoint.", "constantName": "org.apache.camel.component.mustache.MustacheConstants#MUSTACHE_RESOURCE_URI" }, "CamelMustacheTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.mustache.MustacheConstants#MUSTACHE_TEMPLATE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as body, as it is: text, or a Map, a List or a POJO to read from; convert bytes or a stream to a String first. The template is the resource, or the CamelMustacheTemplate or CamelMustacheResourceUri header with allowTemplateFromHeader=true, and never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, also when it is JSON: unmarshal it to read its fields. Values in double braces are HTML-escaped, in triple braces as they are. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mvel.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mvel.json index 7ae1971429a6c..e66b1e10b7cf8 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mvel.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/mvel.json @@ -34,6 +34,10 @@ "CamelMvelResourceUri": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A URI for the template resource to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.mvel.MvelConstants#MVEL_RESOURCE_URI" }, "CamelMvelTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.mvel.MvelConstants#MVEL_TEMPLATE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as body, as it is: no body prints as null, and bytes or a stream are not read as text. The template is the resource, or the CamelMvelTemplate header with allowTemplateFromHeader=true, never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/schematron.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/schematron.json index 4a36cefb7e7c7..2ea15ac6e3f0d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/schematron.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/schematron.json @@ -27,6 +27,10 @@ "lazyStartProducer": { "index": 0, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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." }, "autowiredEnabled": { "index": 1, "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." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "The XML to validate: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source. A Map or another POJO is read as its toString(): marshal it first; no body fails" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: the CamelSchematronValidationStatus header is SUCCESS or FAILED, and CamelSchematronValidationReport holds the SVRL report. With abort, a failed assert throws a SchematronValidationException" } + }, "properties": { "path": { "index": 0, "kind": "path", "displayName": "Path", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "The path to the schematron rules file. Can either be in class path or location in the file system." }, "abort": { "index": 1, "kind": "parameter", "displayName": "Abort", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Flag to abort the route and throw a schematron validation exception." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/string-template.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/string-template.json index 6c156e63c2717..8eacc56d396b7 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/string-template.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/string-template.json @@ -35,6 +35,10 @@ "CamelStringTemplateVariableMap": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Map of the variables which are made available to a script or template", "constantName": "org.apache.camel.component.stringtemplate.StringTemplateConstants#STRINGTEMPLATE_VARIABLE_MAP" }, "CamelStringTemplateTemplate": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.stringtemplate.StringTemplateConstants#STRINGTEMPLATE_TEMPLATE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as body, as it is: text, or a Map, a List or a POJO to read from; convert bytes or a stream to a String first. The template is the resource, or the CamelStringTemplateTemplate or CamelStringTemplateResourceUri header with allowTemplateFromHeader=true, and never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, also when it is JSON or XML: unmarshal it to read its fields. The headers are kept, and the CamelStringTemplateResourceUri header is set to the uri of the resource" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/thymeleaf.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/thymeleaf.json index 5fd0193f05f47..3999546f8abcb 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/thymeleaf.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/thymeleaf.json @@ -35,6 +35,10 @@ "CamelThymeleafVariableMap": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of this header should be a Map with key\/values that will be override any existing key with the same name. This can be used to preconfigure common key\/values you want to reuse in your Thymeleaf endpoints.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_VARIABLE_MAP" }, "CamelThymeleafServletContext": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "jakarta.servlet.ServletContext", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The ServletContext for a web application.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_SERVLET_CONTEXT" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as ${body}, as it is: text, or a Map, a List or a POJO to read from; no body prints as empty text, and bytes or a stream are not read as text. The template is the resource, or the CamelThymeleafTemplate header with allowTemplateFromHeader=true, never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, in its templateMode such as HTML. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/velocity.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/velocity.json index 951eac85ee9f4..c33d8999d0dc4 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/velocity.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/velocity.json @@ -37,6 +37,10 @@ "CamelVelocityContext": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.apache.velocity.context.Context", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The velocity context to use.", "constantName": "org.apache.camel.component.velocity.VelocityConstants#VELOCITY_CONTEXT" }, "CamelVelocitySupplementalContext": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To add additional information to the used VelocityContext. The value of this header should be a Map with key\/values that will added (override any existing key with the same name). This can be used to pre setup some common key\/values you want to reuse in your velocity endpoints.", "constantName": "org.apache.camel.component.velocity.VelocityConstants#VELOCITY_SUPPLEMENTAL_CONTEXT" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as body, as it is: text, or a Map, a List or a POJO to read from; convert bytes or a stream to a String first. The template is the resource, or the CamelVelocityTemplate or CamelVelocityResourceUri header with allowTemplateFromHeader=true, and never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, also when it is JSON or XML: unmarshal it to read its fields. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json index 2af1f9038eceb..0a57d2901364b 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xj.json @@ -43,6 +43,10 @@ "CamelXsltResourceUri": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A URI for the template resource to load and use instead of the endpoint configured.", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" }, "CamelXsltStylesheet": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "dependsOn": [ "source", "useJsonBody" ], "byOption": [ { "option": "transformDirection", "value": "XML2JSON", "carriers": [ "text", "bytes", "stream", "file", "pojo" ] }, { "option": "transformDirection", "value": "JSON2XML", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "The XML for XML2JSON as text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source; the JSON for JSON2XML as text, bytes, a stream or a file. A Map, a List or no body fails, unless failOnNullBody=false for no body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultHandlerFactory" ], "byOption": [ { "option": "output", "value": "bytes", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "output", "value": "DOM", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document" }, { "option": "output", "value": "file", "carriers": [ "file" ], "javaType": "java.io.File" } ], "description": "The result of the transformation: JSON text with XML2JSON, XML text with JSON2XML. output=DOM works with JSON2XML only" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Path to the template. The following is supported by the default URIResolver. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod" }, "allowStAX": { "index": 1, "kind": "parameter", "displayName": "Allow StAX", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow using StAX as the javax.xml.transform.Source. You can enable this if the XSLT library supports StAX such as the Saxon library (camel-saxon). The Xalan library (default in JVM) does not support StAXSource." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xquery.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xquery.json index 3f3346a8b7bd3..0eebafc59fc30 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xquery.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/xquery.json @@ -31,6 +31,10 @@ "configurationProperties": { "index": 4, "kind": "property", "displayName": "Configuration Properties", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map", "deprecated": false, "autowired": false, "secret": false, "description": "To set custom Saxon configuration properties" }, "moduleURIResolver": { "index": 5, "kind": "property", "displayName": "Module URIResolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "net.sf.saxon.lib.ModuleURIResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use the custom ModuleURIResolver" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], "description": "The XML to query: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source. A Map or no body fails" }, + "producerOut": { "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document", "dependsOn": [ "resultType" ], "byOption": [ { "option": "resultsFormat", "value": "Bytes", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "resultsFormat", "value": "BytesSource", "carriers": [ "pojo" ], "javaType": "org.apache.camel.util.xml.BytesSource" }, { "option": "resultsFormat", "value": "DOMSource", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "resultsFormat", "value": "List", "carriers": [ "list" ] }, { "option": "resultsFormat", "value": "String", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "resultsFormat", "value": "StringSource", "carriers": [ "pojo" ], "javaType": "org.apache.camel.util.xml.StringSource" } ], "description": "The result of the query as a DOM Document. A query that gives text, a number or more than one element fails with the default DOM: set resultsFormat to String or List" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the template to load from classpath or file system" }, "allowStAX": { "index": 1, "kind": "parameter", "displayName": "Allow St AX", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow using StAX mode" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/chunk-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/chunk-component.adoc index 09378c38b3165..7eded1be94874 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/chunk-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/chunk-component.adoc @@ -48,6 +48,8 @@ above. Camel will provide exchange information in the Chunk context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="20%,80%",options="header",] @@ -75,8 +77,8 @@ a `Map`). The `Exchange` is transferred as: Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. == Examples diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/freemarker-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/freemarker-component.adoc index fe794292497d3..f92f067cbfc27 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/freemarker-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/freemarker-component.adoc @@ -66,6 +66,8 @@ The header, `fruit`, is now accessible from the `message.out.headers`. Camel will provide exchange information in the FreeMarker context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="50%,50%",options="header",] |======================================================================= @@ -112,8 +114,8 @@ reloading is thus enabled. This scenario can be used in development. Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. == Examples @@ -288,7 +290,7 @@ Java:: [source,java] ---- from("direct:in") - .setHeader("FreemarkerResourceUri").constant("path/to/my/template.ftl") + .setHeader("CamelFreemarkerResourceUri").constant("path/to/my/template.ftl") .to("freemarker:dummy?allowTemplateFromHeader=true"); ---- @@ -298,7 +300,7 @@ XML:: ---- - + path/to/my/template.ftl @@ -314,7 +316,7 @@ YAML:: uri: direct:in steps: - setHeader: - name: FreemarkerResourceUri + name: CamelFreemarkerResourceUri expression: constant: expression: path/to/my/template.ftl diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jolt-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jolt-component.adoc index 7377730c0f55d..dde30f7c2cfa4 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jolt-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jolt-component.adoc @@ -52,6 +52,8 @@ include::partial$component-endpoint-headers.adoc[] For example, you could use something like +The messages of the queue are JSON text, so the examples set `inputType` and `outputType` to `JsonString`: with the default, `Hydrated`, the body must be parsed JSON (a Map or a List), such as after `unmarshal: json`, and the result is parsed JSON too. + [tabs] ==== Java:: @@ -59,7 +61,7 @@ Java:: [source,java] ---- from("activemq:My.Queue") - .to("jolt:com/acme/MyResponse.json"); + .to("jolt:com/acme/MyResponse.json?inputType=JsonString&outputType=JsonString"); ---- XML:: @@ -68,7 +70,7 @@ XML:: ---- - + ---- @@ -82,6 +84,9 @@ YAML:: steps: - to: uri: jolt:com/acme/MyResponse.json + parameters: + inputType: JsonString + outputType: JsonString ---- ==== @@ -94,7 +99,7 @@ Java:: [source,java] ---- from("activemq:My.Queue") - .to("jolt:file://myfolder/MyResponse.json?contentCache=true") + .to("jolt:file://myfolder/MyResponse.json?contentCache=true&inputType=JsonString&outputType=JsonString") .to("activemq:Another.Queue"); ---- @@ -104,7 +109,7 @@ XML:: ---- - + ---- @@ -121,6 +126,8 @@ YAML:: uri: jolt:file://myfolder/MyResponse.json parameters: contentCache: true + inputType: JsonString + outputType: JsonString - to: uri: activemq:Another.Queue ---- diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/json-validator-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/json-validator-component.adoc index 18312b8a150c5..6cda6ee33d6be 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/json-validator-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/json-validator-component.adoc @@ -12,7 +12,7 @@ *{component-header}* -The JSON Schema Validator component performs bean validation of the message body +The JSON Schema Validator component validates the JSON in the message body against JSON Schemas v4, v6, v7, v2019-09 draft and v2020-12(partial) using the NetworkNT JSON Schema library (https://github.com/networknt/json-schema-validator). diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonata-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonata-component.adoc index 389d7c0763c72..8a8eaf2279a16 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonata-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonata-component.adoc @@ -53,6 +53,8 @@ include::partial$component-endpoint-headers.adoc[] For example, you could use something like: +The messages of the queue are JSON text, so the examples set `inputType` and `outputType` to `JsonString`: with the default, `Jackson`, the body must be JSON data (a Map, a List or a JsonNode), such as after `unmarshal: json`, and the result is a JsonNode. + [tabs] ==== Java:: @@ -60,7 +62,7 @@ Java:: [source,java] ---- from("activemq:My.Queue") - .to("jsonata:com/acme/MyResponse.json"); + .to("jsonata:com/acme/MyResponse.json?inputType=JsonString&outputType=JsonString"); ---- XML:: @@ -69,7 +71,7 @@ XML:: ---- - + ---- @@ -83,6 +85,9 @@ YAML:: steps: - to: uri: jsonata:com/acme/MyResponse.json + parameters: + inputType: JsonString + outputType: JsonString ---- ==== @@ -95,7 +100,7 @@ Java:: [source,java] ---- from("activemq:My.Queue") - .to("jsonata:file://myfolder/MyResponse.json?contentCache=true") + .to("jsonata:file://myfolder/MyResponse.json?contentCache=true&inputType=JsonString&outputType=JsonString") .to("activemq:Another.Queue"); ---- @@ -105,7 +110,7 @@ XML:: ---- - + ---- @@ -122,6 +127,8 @@ YAML:: uri: jsonata:file://myfolder/MyResponse.json parameters: contentCache: true + inputType: JsonString + outputType: JsonString - to: uri: activemq:Another.Queue ---- @@ -139,7 +146,7 @@ Java:: [source,java] ---- from("activemq:My.Queue") - .to("jsonata:file://myfolder/MyResponse.json?contentCache=true&frameBinding=#customBindings") + .to("jsonata:file://myfolder/MyResponse.json?contentCache=true&inputType=JsonString&outputType=JsonString&frameBinding=#customBindings") .to("activemq:Another.Queue"); ---- @@ -149,7 +156,7 @@ XML:: ---- - + ---- @@ -166,6 +173,8 @@ YAML:: uri: jsonata:file://myfolder/MyResponse.json parameters: contentCache: true + inputType: JsonString + outputType: JsonString frameBinding: "#customBindings" - to: uri: activemq:Another.Queue diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jte-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jte-component.adoc index b50239b7b2032..5c9d32a04684f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jte-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jte-component.adoc @@ -81,8 +81,8 @@ message header with the key "*CamelJteDataModel*" just like this Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. == Examples diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mustache-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mustache-component.adoc index 1b113bc0a779c..36dc6d306f5e2 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mustache-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mustache-component.adoc @@ -51,6 +51,8 @@ include::partial$component-endpoint-headers.adoc[] Camel will provide exchange information in the Mustache context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="10%,90%",options="header",] |======================================================================= @@ -77,8 +79,8 @@ Camel will provide exchange information in the Mustache context (just a Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. == Examples diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mvel-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mvel-component.adoc index d20fdfc75d95c..b8709cd862d34 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mvel-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mvel-component.adoc @@ -51,6 +51,8 @@ include::partial$component-endpoint-headers.adoc[] Camel will provide exchange information in the MVEL context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="10%m,90%",options="header",] |======================================================================= @@ -79,8 +81,8 @@ never changes. Camel provides two headers by which you can define a different resource location for a template, or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. == Examples diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/string-template-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/string-template-component.adoc index 38ec47de2aa46..141e3bd68e05a 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/string-template-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/string-template-component.adoc @@ -51,14 +51,15 @@ include::partial$component-endpoint-headers.adoc[] === Headers -Camel will store a reference to the resource in the message header with -key, `org.apache.camel.stringtemplate.resource`. The Resource is an -`org.springframework.core.io.Resource` object. +Camel sets the uri of the template resource in the message header +`CamelStringTemplateResourceUri`. === String Template Context Camel will provide exchange information in the String Template context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="10%,90%",options="header",] |======================================================================= @@ -92,8 +93,8 @@ This scenario can be used in production when the resource never changes. Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. === StringTemplate Attributes diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/thymeleaf-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/thymeleaf-component.adoc index ca557310b6369..4bcb723a06ab6 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/thymeleaf-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/thymeleaf-component.adoc @@ -66,6 +66,8 @@ The `fruit` header is now accessible from the `message.out.headers`. Camel will provide exchange information in the Thymeleaf context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="10%,90%",options="header",] |======================================================================= @@ -90,14 +92,16 @@ The `Exchange` is transferred as: |`response` |The Out message (only for InOut message exchange pattern). |======================================================================= -You can set up a custom Thymeleaf Context yourself by -setting property `allowTemplateFromHeader=true` and setting the message header `CamelThymeleafContext` like this +You can add your own variables to the Thymeleaf context with a `Map` in the message header +`CamelThymeleafVariableMap`. Camel sets the `body`, `header`, `headers`, `variable`, `variables` and +`exception` entries on top of it, and removes the header after use: ._Java-only: programmatic Thymeleaf context setup via Exchange API_ [source,java] ---- -EngineContext engineContext = new EngineContext(variableMap); -exchange.getIn().setHeader("CamelThymeleafContext", engineContext); +Map variableMap = new HashMap<>(); +variableMap.put("greeting", "Hello"); +exchange.getIn().setHeader("CamelThymeleafVariableMap", variableMap); ---- === Hot reloading @@ -112,8 +116,8 @@ when the resource never changes. Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/velocity-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/velocity-component.adoc index cb102bb2f991a..a215ef6531ae3 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/velocity-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/velocity-component.adoc @@ -67,6 +67,8 @@ The `fruit` header is now accessible from the `message.out.headers`. Camel will provide exchange information in the Velocity context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="10%,90%",options="header",] |======================================================================= @@ -195,8 +197,8 @@ when the resource never changes. Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/xquery-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/xquery-component.adoc index a2d941eb0734d..f4cf0dc56d870 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/xquery-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/xquery-component.adoc @@ -165,7 +165,7 @@ Notice how we can reuse the namespace prefixes, *foo* in this case, in the XPath expression for easier namespace-based XQuery expressions! When you use functions in your XQuery expression, you need an explicit -type conversion which is done in the xml configuration via the *@type* +type conversion which is done in the xml configuration via the *resultType* attribute: [source,xml] diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/mvel.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/mvel.json index 760f94c5c7fdc..6b133a1c347e9 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/mvel.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/mvel.json @@ -15,6 +15,10 @@ "modelName": "mvel", "modelJavaType": "org.apache.camel.model.language.MvelExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in request.body or message.body: there is no variable body" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the expression returns" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xquery.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xquery.json index 3bd82a8ede96b..f136ec5a42171 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xquery.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/languages/xquery.json @@ -15,6 +15,10 @@ "modelName": "xquery", "modelJavaType": "org.apache.camel.model.language.XQueryExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], "description": "XML as text, bytes, a stream or a file, or a DOM or another javax.xml.transform.Source. A Map or no body fails" }, + "expressionOut": { "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document", "dependsOn": [ "resultType" ], "description": "The result of the query as a DOM Document. A query that gives text, a number or more than one element fails unless resultType is java.lang.String" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-bean-validator/src/generated/resources/META-INF/org/apache/camel/component/bean/validator/bean-validator.json b/components/camel-bean-validator/src/generated/resources/META-INF/org/apache/camel/component/bean/validator/bean-validator.json index f7c5e0354c6ab..b90db05804387 100644 --- a/components/camel-bean-validator/src/generated/resources/META-INF/org/apache/camel/component/bean/validator/bean-validator.json +++ b/components/camel-bean-validator/src/generated/resources/META-INF/org/apache/camel/component/bean/validator/bean-validator.json @@ -33,6 +33,10 @@ "validationProviderResolver": { "index": 6, "kind": "property", "displayName": "Validation Provider Resolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "jakarta.validation.ValidationProviderResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use a a custom ValidationProviderResolver" }, "validatorFactory": { "index": 7, "kind": "property", "displayName": "Validator Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "jakarta.validation.ValidatorFactory", "deprecated": false, "autowired": true, "secret": false, "description": "To use a custom ValidatorFactory" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "pojo", "list" ], "description": "A POJO with Jakarta Bean Validation constraints, or a List or another Iterable of them, each one validated. Text, a Map or an array has no constraints of its own and passes unchecked; no body fails" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: a body that breaks a constraint fails with a BeanValidationException" } + }, "properties": { "label": { "index": 0, "kind": "path", "displayName": "Label", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Where label is an arbitrary text value describing the endpoint" }, "group": { "index": 1, "kind": "parameter", "displayName": "Group", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "jakarta.validation.groups.Default", "description": "To use a custom validation group" }, diff --git a/components/camel-bean-validator/src/main/java/org/apache/camel/component/bean/validator/BeanValidatorEndpoint.java b/components/camel-bean-validator/src/main/java/org/apache/camel/component/bean/validator/BeanValidatorEndpoint.java index 641fa9e14d6ad..250a5d9df32d1 100644 --- a/components/camel-bean-validator/src/main/java/org/apache/camel/component/bean/validator/BeanValidatorEndpoint.java +++ b/components/camel-bean-validator/src/main/java/org/apache/camel/component/bean/validator/BeanValidatorEndpoint.java @@ -27,6 +27,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -42,6 +45,13 @@ */ @UriEndpoint(firstVersion = "2.3.0", scheme = "bean-validator", title = "Bean Validator", syntax = "bean-validator:label", remote = false, producerOnly = true, category = { Category.VALIDATION }) +@BodyTypes(producerIn = @BodyType(value = { Carrier.POJO, Carrier.LIST }, + description = "A POJO with Jakarta Bean Validation constraints, or a List or another" + + " Iterable of them, each one validated. Text, a Map or an array has no" + + " constraints of its own and passes unchecked; no body fails"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged: a body that breaks a constraint fails with a" + + " BeanValidationException")) public class BeanValidatorEndpoint extends DefaultEndpoint { @UriPath(description = "Where label is an arbitrary text value describing the endpoint") diff --git a/components/camel-chunk/src/generated/resources/META-INF/org/apache/camel/component/chunk/chunk.json b/components/camel-chunk/src/generated/resources/META-INF/org/apache/camel/component/chunk/chunk.json index edf6b67d18cb2..ae08f3605556d 100644 --- a/components/camel-chunk/src/generated/resources/META-INF/org/apache/camel/component/chunk/chunk.json +++ b/components/camel-chunk/src/generated/resources/META-INF/org/apache/camel/component/chunk/chunk.json @@ -34,6 +34,10 @@ "CamelChunkResourceUri": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A URI for the template resource to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.chunk.ChunkConstants#CHUNK_RESOURCE_URI" }, "CamelChunkTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.chunk.ChunkConstants#CHUNK_TEMPLATE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as {$body}, as it is: text, or a Map, a List or a POJO to read from; no body prints as empty text, and bytes or a stream are not read as text. The template is the resource, or the CamelChunkTemplate header with allowTemplateFromHeader=true, never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/components/camel-chunk/src/main/docs/chunk-component.adoc b/components/camel-chunk/src/main/docs/chunk-component.adoc index 09378c38b3165..7eded1be94874 100644 --- a/components/camel-chunk/src/main/docs/chunk-component.adoc +++ b/components/camel-chunk/src/main/docs/chunk-component.adoc @@ -48,6 +48,8 @@ above. Camel will provide exchange information in the Chunk context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="20%,80%",options="header",] @@ -75,8 +77,8 @@ a `Map`). The `Exchange` is transferred as: Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. == Examples diff --git a/components/camel-chunk/src/main/java/org/apache/camel/component/chunk/ChunkEndpoint.java b/components/camel-chunk/src/main/java/org/apache/camel/component/chunk/ChunkEndpoint.java index 701c2303acc40..197e143640800 100644 --- a/components/camel-chunk/src/main/java/org/apache/camel/component/chunk/ChunkEndpoint.java +++ b/components/camel-chunk/src/main/java/org/apache/camel/component/chunk/ChunkEndpoint.java @@ -36,6 +36,9 @@ import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.HeadersMapFactory; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -54,6 +57,14 @@ */ @UriEndpoint(firstVersion = "2.15.0", scheme = "chunk", title = "Chunk", syntax = "chunk:resourceUri", producerOnly = true, remote = false, category = { Category.TRANSFORMATION }, headersClass = ChunkConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The template gets the body as {$body}, as it is: text, or a Map, a List or a" + + " POJO to read from; no body prints as empty text, and bytes or a stream" + + " are not read as text. The template is the resource, or the" + + " CamelChunkTemplate header with allowTemplateFromHeader=true, never the" + + " body"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", + description = "The text the template writes. The headers are kept")) public class ChunkEndpoint extends ResourceEndpoint { private Theme theme; diff --git a/components/camel-freemarker/src/generated/resources/META-INF/org/apache/camel/component/freemarker/freemarker.json b/components/camel-freemarker/src/generated/resources/META-INF/org/apache/camel/component/freemarker/freemarker.json index 3075b7efead38..a0f18e467cb59 100644 --- a/components/camel-freemarker/src/generated/resources/META-INF/org/apache/camel/component/freemarker/freemarker.json +++ b/components/camel-freemarker/src/generated/resources/META-INF/org/apache/camel/component/freemarker/freemarker.json @@ -37,6 +37,10 @@ "CamelFreemarkerTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.freemarker.FreemarkerConstants#FREEMARKER_TEMPLATE" }, "CamelFreemarkerDataModel": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Object", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The data model", "constantName": "org.apache.camel.component.freemarker.FreemarkerConstants#FREEMARKER_DATA_MODEL" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as body, as it is: text, or a Map, a List or a POJO to read from; convert bytes or a stream to a String first, and no body fails ${body} unless it is written ${body!}. The template is the resource, or the CamelFreemarkerTemplate or CamelFreemarkerResourceUri header with allowTemplateFromHeader=true, and never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, also when it is JSON or XML: unmarshal it to read its fields. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/components/camel-freemarker/src/main/docs/freemarker-component.adoc b/components/camel-freemarker/src/main/docs/freemarker-component.adoc index fe794292497d3..f92f067cbfc27 100644 --- a/components/camel-freemarker/src/main/docs/freemarker-component.adoc +++ b/components/camel-freemarker/src/main/docs/freemarker-component.adoc @@ -66,6 +66,8 @@ The header, `fruit`, is now accessible from the `message.out.headers`. Camel will provide exchange information in the FreeMarker context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="50%,50%",options="header",] |======================================================================= @@ -112,8 +114,8 @@ reloading is thus enabled. This scenario can be used in development. Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. == Examples @@ -288,7 +290,7 @@ Java:: [source,java] ---- from("direct:in") - .setHeader("FreemarkerResourceUri").constant("path/to/my/template.ftl") + .setHeader("CamelFreemarkerResourceUri").constant("path/to/my/template.ftl") .to("freemarker:dummy?allowTemplateFromHeader=true"); ---- @@ -298,7 +300,7 @@ XML:: ---- - + path/to/my/template.ftl @@ -314,7 +316,7 @@ YAML:: uri: direct:in steps: - setHeader: - name: FreemarkerResourceUri + name: CamelFreemarkerResourceUri expression: constant: expression: path/to/my/template.ftl diff --git a/components/camel-freemarker/src/main/java/org/apache/camel/component/freemarker/FreemarkerEndpoint.java b/components/camel-freemarker/src/main/java/org/apache/camel/component/freemarker/FreemarkerEndpoint.java index ab38072722161..c8d7b4b486745 100644 --- a/components/camel-freemarker/src/main/java/org/apache/camel/component/freemarker/FreemarkerEndpoint.java +++ b/components/camel-freemarker/src/main/java/org/apache/camel/component/freemarker/FreemarkerEndpoint.java @@ -28,6 +28,9 @@ import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.support.ExchangeHelper; @@ -40,6 +43,15 @@ @UriEndpoint(firstVersion = "2.10.0", scheme = "freemarker", title = "Freemarker", syntax = "freemarker:resourceUri", remote = false, producerOnly = true, category = { Category.TRANSFORMATION }, headersClass = FreemarkerConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The template gets the body as body, as it is: text, or a Map, a List or a" + + " POJO to read from; convert bytes or a stream to a String first, and no" + + " body fails ${body} unless it is written ${body!}. The template is the" + + " resource, or the CamelFreemarkerTemplate or CamelFreemarkerResourceUri" + + " header with allowTemplateFromHeader=true, and never the body"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", + description = "The text the template writes, also when it is JSON or XML: unmarshal it to" + + " read its fields. The headers are kept")) public class FreemarkerEndpoint extends ResourceEndpoint { @UriParam(defaultValue = "false") diff --git a/components/camel-jolt/src/generated/resources/META-INF/org/apache/camel/component/jolt/jolt.json b/components/camel-jolt/src/generated/resources/META-INF/org/apache/camel/component/jolt/jolt.json index 4f7c8a6e3cec9..0638b27c7f26a 100644 --- a/components/camel-jolt/src/generated/resources/META-INF/org/apache/camel/component/jolt/jolt.json +++ b/components/camel-jolt/src/generated/resources/META-INF/org/apache/camel/component/jolt/jolt.json @@ -34,6 +34,10 @@ "CamelJoltResourceUri": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The resource URI", "constantName": "org.apache.camel.component.jolt.JoltConstants#JOLT_RESOURCE_URI" }, "CamelJoltContext": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The context", "constantName": "org.apache.camel.component.jolt.JoltConstants#JOLT_CONTEXT" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "map", "list" ], "format": "json", "byOption": [ { "option": "inputType", "value": "JsonString", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "Parsed JSON: a Map or a List. JSON as text, bytes, a stream or a file needs inputType=JsonString: without it the body reaches the spec unparsed, and the result is most likely null" }, + "producerOut": { "carriers": [ "map", "list" ], "format": "json", "byOption": [ { "option": "outputType", "value": "JsonString", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "The JSON the spec makes: a Map for an object, a List for an array; JSON text with outputType=JsonString" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowTemplateFromHeader": { "index": 1, "kind": "parameter", "displayName": "Allow Template From Header", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow to use resource template from header or not (default false). Enabling this allows to specify dynamic templates via message header. However this can be seen as a potential security vulnerability if the header is coming from a malicious user, so use this with care." }, diff --git a/components/camel-jolt/src/main/docs/jolt-component.adoc b/components/camel-jolt/src/main/docs/jolt-component.adoc index 7377730c0f55d..dde30f7c2cfa4 100644 --- a/components/camel-jolt/src/main/docs/jolt-component.adoc +++ b/components/camel-jolt/src/main/docs/jolt-component.adoc @@ -52,6 +52,8 @@ include::partial$component-endpoint-headers.adoc[] For example, you could use something like +The messages of the queue are JSON text, so the examples set `inputType` and `outputType` to `JsonString`: with the default, `Hydrated`, the body must be parsed JSON (a Map or a List), such as after `unmarshal: json`, and the result is parsed JSON too. + [tabs] ==== Java:: @@ -59,7 +61,7 @@ Java:: [source,java] ---- from("activemq:My.Queue") - .to("jolt:com/acme/MyResponse.json"); + .to("jolt:com/acme/MyResponse.json?inputType=JsonString&outputType=JsonString"); ---- XML:: @@ -68,7 +70,7 @@ XML:: ---- - + ---- @@ -82,6 +84,9 @@ YAML:: steps: - to: uri: jolt:com/acme/MyResponse.json + parameters: + inputType: JsonString + outputType: JsonString ---- ==== @@ -94,7 +99,7 @@ Java:: [source,java] ---- from("activemq:My.Queue") - .to("jolt:file://myfolder/MyResponse.json?contentCache=true") + .to("jolt:file://myfolder/MyResponse.json?contentCache=true&inputType=JsonString&outputType=JsonString") .to("activemq:Another.Queue"); ---- @@ -104,7 +109,7 @@ XML:: ---- - + ---- @@ -121,6 +126,8 @@ YAML:: uri: jolt:file://myfolder/MyResponse.json parameters: contentCache: true + inputType: JsonString + outputType: JsonString - to: uri: activemq:Another.Queue ---- diff --git a/components/camel-jolt/src/main/java/org/apache/camel/component/jolt/JoltEndpoint.java b/components/camel-jolt/src/main/java/org/apache/camel/component/jolt/JoltEndpoint.java index b5c4a65a0bf8e..bc8a1b855006a 100644 --- a/components/camel-jolt/src/main/java/org/apache/camel/component/jolt/JoltEndpoint.java +++ b/components/camel-jolt/src/main/java/org/apache/camel/component/jolt/JoltEndpoint.java @@ -32,6 +32,9 @@ import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -44,6 +47,19 @@ @UriEndpoint(firstVersion = "2.16.0", scheme = "jolt", title = "JOLT", syntax = "jolt:resourceUri", producerOnly = true, remote = false, category = { Category.TRANSFORMATION }, headersClass = JoltConstants.class) @Metadata(excludeProperties = "allowContextMapAll") +@BodyTypes(producerIn = @BodyType(value = { Carrier.MAP, Carrier.LIST }, format = "json", + byOption = @BodyType.When(option = "inputType", value = "JsonString", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }), + description = "Parsed JSON: a Map or a List. JSON as text, bytes, a stream or a file needs" + + " inputType=JsonString: without it the body reaches the spec unparsed, and" + + " the result is most likely null"), + producerOut = @BodyType(value = { Carrier.MAP, Carrier.LIST }, format = "json", + byOption = @BodyType.When(option = "outputType", value = "JsonString", + carriers = Carrier.TEXT, javaType = "java.lang.String"), + description = "The JSON the spec makes: a Map for an object, a List for an array; JSON text" + + " with outputType=JsonString")) public class JoltEndpoint extends ResourceEndpoint { private JoltTransform transform; diff --git a/components/camel-jslt/src/generated/resources/META-INF/org/apache/camel/component/jslt/jslt.json b/components/camel-jslt/src/generated/resources/META-INF/org/apache/camel/component/jslt/jslt.json index a82c39b84d52c..d60f5f1e048d2 100644 --- a/components/camel-jslt/src/generated/resources/META-INF/org/apache/camel/component/jslt/jslt.json +++ b/components/camel-jslt/src/generated/resources/META-INF/org/apache/camel/component/jslt/jslt.json @@ -35,6 +35,10 @@ "CamelJsltString": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The JSLT Template as String", "constantName": "org.apache.camel.component.jslt.JsltConstants#HEADER_JSLT_STRING" }, "CamelJsltResourceUri": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The resource URI", "constantName": "org.apache.camel.component.jslt.JsltConstants#HEADER_JSLT_RESOURCE_URI" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json", "description": "JSON as text, bytes, a stream, a Reader or a java.io.File, such as the file of the file consumer. A Map, a List, a JsonNode or no body fails: marshal parsed JSON first" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "format": "json", "description": "The result as JSON text, pretty printed with prettyPrint=true" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltEndpoint.java b/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltEndpoint.java index 3ca8c381dcc5b..6013f97bf94a8 100644 --- a/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltEndpoint.java +++ b/components/camel-jslt/src/main/java/org/apache/camel/component/jslt/JsltEndpoint.java @@ -51,6 +51,9 @@ import org.apache.camel.ValidationException; import org.apache.camel.WrappedFile; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.support.ExchangeHelper; @@ -63,6 +66,12 @@ */ @UriEndpoint(firstVersion = "3.1.0", scheme = "jslt", title = "JSLT", syntax = "jslt:resourceUri", producerOnly = true, remote = false, category = { Category.TRANSFORMATION }, headersClass = JsltConstants.class) +@BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "json", + description = "JSON as text, bytes, a stream, a Reader or a java.io.File, such as the file of" + + " the file consumer. A Map, a List, a JsonNode or no body fails: marshal" + + " parsed JSON first"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", format = "json", + description = "The result as JSON text, pretty printed with prettyPrint=true")) public class JsltEndpoint extends ResourceEndpoint { private static final ObjectMapper OBJECT_MAPPER; diff --git a/components/camel-json-validator/src/generated/resources/META-INF/org/apache/camel/component/jsonvalidator/json-validator.json b/components/camel-json-validator/src/generated/resources/META-INF/org/apache/camel/component/jsonvalidator/json-validator.json index 48155c275cff2..ab867f3969f7e 100644 --- a/components/camel-json-validator/src/generated/resources/META-INF/org/apache/camel/component/jsonvalidator/json-validator.json +++ b/components/camel-json-validator/src/generated/resources/META-INF/org/apache/camel/component/jsonvalidator/json-validator.json @@ -30,6 +30,10 @@ "autowiredEnabled": { "index": 3, "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." }, "objectMapper": { "index": 4, "kind": "property", "displayName": "Object Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing ObjectMapper with the given id." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json", "dependsOn": [ "headerName" ], "byOption": [ { "option": "failOnNullBody", "value": "false", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "The JSON to validate: text, bytes, a stream or a file. A Map, a POJO or no body fails: marshal it first; with headerName the header is validated instead" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: JSON that does not match the schema, or text that is not JSON, fails with a JsonValidationException" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/components/camel-json-validator/src/main/docs/json-validator-component.adoc b/components/camel-json-validator/src/main/docs/json-validator-component.adoc index 18312b8a150c5..6cda6ee33d6be 100644 --- a/components/camel-json-validator/src/main/docs/json-validator-component.adoc +++ b/components/camel-json-validator/src/main/docs/json-validator-component.adoc @@ -12,7 +12,7 @@ *{component-header}* -The JSON Schema Validator component performs bean validation of the message body +The JSON Schema Validator component validates the JSON in the message body against JSON Schemas v4, v6, v7, v2019-09 draft and v2020-12(partial) using the NetworkNT JSON Schema library (https://github.com/networknt/json-schema-validator). diff --git a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorEndpoint.java b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorEndpoint.java index 44713220763d3..68d8f80b72437 100644 --- a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorEndpoint.java +++ b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorEndpoint.java @@ -33,6 +33,9 @@ import org.apache.camel.ValidationException; import org.apache.camel.api.management.ManagedResource; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -43,6 +46,18 @@ @UriEndpoint(scheme = "json-validator", firstVersion = "2.20.0", title = "JSON Schema Validator", syntax = "json-validator:resourceUri", remote = false, producerOnly = true, category = { Category.VALIDATION }) +@BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + format = "json", dependsOn = "headerName", + byOption = @BodyType.When(option = "failOnNullBody", value = "false", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE }), + description = "The JSON to validate: text, bytes, a stream or a file. A Map, a POJO or no" + + " body fails: marshal it first; with headerName the header is validated" + + " instead"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged: JSON that does not match the schema, or text that is not JSON," + + " fails with a JsonValidationException")) public class JsonValidatorEndpoint extends ResourceEndpoint { private volatile Schema schema; diff --git a/components/camel-jsonata/src/generated/resources/META-INF/org/apache/camel/component/jsonata/jsonata.json b/components/camel-jsonata/src/generated/resources/META-INF/org/apache/camel/component/jsonata/jsonata.json index d6de7d1584da8..72d92ea7c5c85 100644 --- a/components/camel-jsonata/src/generated/resources/META-INF/org/apache/camel/component/jsonata/jsonata.json +++ b/components/camel-jsonata/src/generated/resources/META-INF/org/apache/camel/component/jsonata/jsonata.json @@ -30,6 +30,10 @@ "autowiredEnabled": { "index": 3, "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." }, "frameBinding": { "index": 4, "kind": "property", "displayName": "Frame Binding", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.jsonata.JsonataFrameBinding", "deprecated": false, "autowired": false, "secret": false, "description": "To configure custom frame bindings and inject user functions." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "map", "list", "pojo" ], "format": "json", "byOption": [ { "option": "inputType", "value": "JsonString", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "JSON data: a Map, a List, a JsonNode or another object Jackson converts. JSON as text, bytes, a stream or a file needs inputType=JsonString: without it text is read as one JSON string, and bytes or a stream fail" }, + "producerOut": { "carriers": [ "pojo" ], "javaType": "com.fasterxml.jackson.databind.JsonNode", "format": "json", "byOption": [ { "option": "outputType", "value": "JsonString", "carriers": [ "text" ], "javaType": "java.lang.String" } ], "description": "The result as a Jackson JsonNode, or as JSON text with outputType=JsonString" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/components/camel-jsonata/src/main/docs/jsonata-component.adoc b/components/camel-jsonata/src/main/docs/jsonata-component.adoc index 389d7c0763c72..8a8eaf2279a16 100644 --- a/components/camel-jsonata/src/main/docs/jsonata-component.adoc +++ b/components/camel-jsonata/src/main/docs/jsonata-component.adoc @@ -53,6 +53,8 @@ include::partial$component-endpoint-headers.adoc[] For example, you could use something like: +The messages of the queue are JSON text, so the examples set `inputType` and `outputType` to `JsonString`: with the default, `Jackson`, the body must be JSON data (a Map, a List or a JsonNode), such as after `unmarshal: json`, and the result is a JsonNode. + [tabs] ==== Java:: @@ -60,7 +62,7 @@ Java:: [source,java] ---- from("activemq:My.Queue") - .to("jsonata:com/acme/MyResponse.json"); + .to("jsonata:com/acme/MyResponse.json?inputType=JsonString&outputType=JsonString"); ---- XML:: @@ -69,7 +71,7 @@ XML:: ---- - + ---- @@ -83,6 +85,9 @@ YAML:: steps: - to: uri: jsonata:com/acme/MyResponse.json + parameters: + inputType: JsonString + outputType: JsonString ---- ==== @@ -95,7 +100,7 @@ Java:: [source,java] ---- from("activemq:My.Queue") - .to("jsonata:file://myfolder/MyResponse.json?contentCache=true") + .to("jsonata:file://myfolder/MyResponse.json?contentCache=true&inputType=JsonString&outputType=JsonString") .to("activemq:Another.Queue"); ---- @@ -105,7 +110,7 @@ XML:: ---- - + ---- @@ -122,6 +127,8 @@ YAML:: uri: jsonata:file://myfolder/MyResponse.json parameters: contentCache: true + inputType: JsonString + outputType: JsonString - to: uri: activemq:Another.Queue ---- @@ -139,7 +146,7 @@ Java:: [source,java] ---- from("activemq:My.Queue") - .to("jsonata:file://myfolder/MyResponse.json?contentCache=true&frameBinding=#customBindings") + .to("jsonata:file://myfolder/MyResponse.json?contentCache=true&inputType=JsonString&outputType=JsonString&frameBinding=#customBindings") .to("activemq:Another.Queue"); ---- @@ -149,7 +156,7 @@ XML:: ---- - + ---- @@ -166,6 +173,8 @@ YAML:: uri: jsonata:file://myfolder/MyResponse.json parameters: contentCache: true + inputType: JsonString + outputType: JsonString frameBinding: "#customBindings" - to: uri: activemq:Another.Queue diff --git a/components/camel-jsonata/src/main/java/org/apache/camel/component/jsonata/JsonataEndpoint.java b/components/camel-jsonata/src/main/java/org/apache/camel/component/jsonata/JsonataEndpoint.java index 03e05b49a693f..5d3456e8955cd 100644 --- a/components/camel-jsonata/src/main/java/org/apache/camel/component/jsonata/JsonataEndpoint.java +++ b/components/camel-jsonata/src/main/java/org/apache/camel/component/jsonata/JsonataEndpoint.java @@ -29,6 +29,9 @@ import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.support.ExchangeHelper; @@ -43,6 +46,20 @@ @UriEndpoint(firstVersion = "3.5.0", scheme = "jsonata", title = "JSONata", syntax = "jsonata:resourceUri", producerOnly = true, remote = false, category = { Category.TRANSFORMATION }) +@BodyTypes(producerIn = @BodyType(value = { Carrier.MAP, Carrier.LIST, Carrier.POJO }, format = "json", + byOption = @BodyType.When(option = "inputType", value = "JsonString", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }), + description = "JSON data: a Map, a List, a JsonNode or another object Jackson converts. JSON" + + " as text, bytes, a stream or a file needs inputType=JsonString: without it" + + " text is read as one JSON string, and bytes or a stream fail"), + producerOut = @BodyType(value = Carrier.POJO, javaType = "com.fasterxml.jackson.databind.JsonNode", + format = "json", + byOption = @BodyType.When(option = "outputType", value = "JsonString", + carriers = Carrier.TEXT, javaType = "java.lang.String"), + description = "The result as a Jackson JsonNode, or as JSON text with" + + " outputType=JsonString")) public class JsonataEndpoint extends ResourceEndpoint { private final ObjectMapper mapper = new ObjectMapper(); diff --git a/components/camel-jte/src/generated/resources/META-INF/org/apache/camel/component/jte/jte.json b/components/camel-jte/src/generated/resources/META-INF/org/apache/camel/component/jte/jte.json index 1d04e8d7d1d21..cfc4c8d5b8aff 100644 --- a/components/camel-jte/src/generated/resources/META-INF/org/apache/camel/component/jte/jte.json +++ b/components/camel-jte/src/generated/resources/META-INF/org/apache/camel/component/jte/jte.json @@ -38,6 +38,10 @@ "CamelJteTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.jte.JteConstants#JTE_TEMPLATE" }, "CamelJteDataModel": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Object", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The data model", "constantName": "org.apache.camel.component.jte.JteConstants#JTE_DATA_MODEL" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template takes an org.apache.camel.component.jte.Model: the body as it is in model.body, and converted to text by model.strBody(). With allowTemplateFromHeader=true the CamelJteDataModel header replaces the model" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, with leading and trailing whitespace trimmed. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/components/camel-jte/src/main/docs/jte-component.adoc b/components/camel-jte/src/main/docs/jte-component.adoc index b50239b7b2032..5c9d32a04684f 100644 --- a/components/camel-jte/src/main/docs/jte-component.adoc +++ b/components/camel-jte/src/main/docs/jte-component.adoc @@ -81,8 +81,8 @@ message header with the key "*CamelJteDataModel*" just like this Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. == Examples diff --git a/components/camel-jte/src/main/java/org/apache/camel/component/jte/JteEndpoint.java b/components/camel-jte/src/main/java/org/apache/camel/component/jte/JteEndpoint.java index 2b237ef87fd45..d8720abca8b08 100644 --- a/components/camel-jte/src/main/java/org/apache/camel/component/jte/JteEndpoint.java +++ b/components/camel-jte/src/main/java/org/apache/camel/component/jte/JteEndpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.Component; import org.apache.camel.Exchange; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.support.ExchangeHelper; @@ -35,6 +38,14 @@ */ @UriEndpoint(firstVersion = "4.4.0", scheme = "jte", title = "JTE", syntax = "jte:resourceUri", remote = false, producerOnly = true, category = { Category.TRANSFORMATION }, headersClass = JteConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The template takes an org.apache.camel.component.jte.Model: the body as it is" + + " in model.body, and converted to text by model.strBody(). With" + + " allowTemplateFromHeader=true the CamelJteDataModel header replaces the" + + " model"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", + description = "The text the template writes, with leading and trailing whitespace trimmed." + + " The headers are kept")) public class JteEndpoint extends ResourceEndpoint { @UriParam diff --git a/components/camel-mustache/src/generated/resources/META-INF/org/apache/camel/component/mustache/mustache.json b/components/camel-mustache/src/generated/resources/META-INF/org/apache/camel/component/mustache/mustache.json index 97ba41b8eb31f..1ac15dcc8b4ad 100644 --- a/components/camel-mustache/src/generated/resources/META-INF/org/apache/camel/component/mustache/mustache.json +++ b/components/camel-mustache/src/generated/resources/META-INF/org/apache/camel/component/mustache/mustache.json @@ -35,6 +35,10 @@ "CamelMustacheResourceUri": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A URI for the template resource to use instead of the endpoint.", "constantName": "org.apache.camel.component.mustache.MustacheConstants#MUSTACHE_RESOURCE_URI" }, "CamelMustacheTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.mustache.MustacheConstants#MUSTACHE_TEMPLATE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as body, as it is: text, or a Map, a List or a POJO to read from; convert bytes or a stream to a String first. The template is the resource, or the CamelMustacheTemplate or CamelMustacheResourceUri header with allowTemplateFromHeader=true, and never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, also when it is JSON: unmarshal it to read its fields. Values in double braces are HTML-escaped, in triple braces as they are. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/components/camel-mustache/src/main/docs/mustache-component.adoc b/components/camel-mustache/src/main/docs/mustache-component.adoc index 1b113bc0a779c..36dc6d306f5e2 100644 --- a/components/camel-mustache/src/main/docs/mustache-component.adoc +++ b/components/camel-mustache/src/main/docs/mustache-component.adoc @@ -51,6 +51,8 @@ include::partial$component-endpoint-headers.adoc[] Camel will provide exchange information in the Mustache context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="10%,90%",options="header",] |======================================================================= @@ -77,8 +79,8 @@ Camel will provide exchange information in the Mustache context (just a Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. == Examples diff --git a/components/camel-mustache/src/main/java/org/apache/camel/component/mustache/MustacheEndpoint.java b/components/camel-mustache/src/main/java/org/apache/camel/component/mustache/MustacheEndpoint.java index 83d351081f432..7417f9a9f7c91 100644 --- a/components/camel-mustache/src/main/java/org/apache/camel/component/mustache/MustacheEndpoint.java +++ b/components/camel-mustache/src/main/java/org/apache/camel/component/mustache/MustacheEndpoint.java @@ -31,6 +31,9 @@ import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.support.ExchangeHelper; @@ -45,6 +48,16 @@ @UriEndpoint(firstVersion = "2.12.0", scheme = "mustache", title = "Mustache", syntax = "mustache:resourceUri", remote = false, producerOnly = true, category = { Category.TRANSFORMATION }, headersClass = MustacheConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The template gets the body as body, as it is: text, or a Map, a List or a" + + " POJO to read from; convert bytes or a stream to a String first. The" + + " template is the resource, or the CamelMustacheTemplate or" + + " CamelMustacheResourceUri header with allowTemplateFromHeader=true, and" + + " never the body"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", + description = "The text the template writes, also when it is JSON: unmarshal it to read its" + + " fields. Values in double braces are HTML-escaped, in triple braces as they" + + " are. The headers are kept")) public class MustacheEndpoint extends ResourceEndpoint { private MustacheFactory mustacheFactory; diff --git a/components/camel-mvel/src/generated/resources/META-INF/org/apache/camel/component/mvel/mvel.json b/components/camel-mvel/src/generated/resources/META-INF/org/apache/camel/component/mvel/mvel.json index 7ae1971429a6c..e66b1e10b7cf8 100644 --- a/components/camel-mvel/src/generated/resources/META-INF/org/apache/camel/component/mvel/mvel.json +++ b/components/camel-mvel/src/generated/resources/META-INF/org/apache/camel/component/mvel/mvel.json @@ -34,6 +34,10 @@ "CamelMvelResourceUri": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A URI for the template resource to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.mvel.MvelConstants#MVEL_RESOURCE_URI" }, "CamelMvelTemplate": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.mvel.MvelConstants#MVEL_TEMPLATE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as body, as it is: no body prints as null, and bytes or a stream are not read as text. The template is the resource, or the CamelMvelTemplate header with allowTemplateFromHeader=true, never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/components/camel-mvel/src/generated/resources/META-INF/org/apache/camel/language/mvel/mvel.json b/components/camel-mvel/src/generated/resources/META-INF/org/apache/camel/language/mvel/mvel.json index 760f94c5c7fdc..6b133a1c347e9 100644 --- a/components/camel-mvel/src/generated/resources/META-INF/org/apache/camel/language/mvel/mvel.json +++ b/components/camel-mvel/src/generated/resources/META-INF/org/apache/camel/language/mvel/mvel.json @@ -15,6 +15,10 @@ "modelName": "mvel", "modelJavaType": "org.apache.camel.model.language.MvelExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "any" ], "description": "The body as it is, in request.body or message.body: there is no variable body" }, + "expressionOut": { "carriers": [ "unknown" ], "description": "What the expression returns" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-mvel/src/main/docs/mvel-component.adoc b/components/camel-mvel/src/main/docs/mvel-component.adoc index d20fdfc75d95c..b8709cd862d34 100644 --- a/components/camel-mvel/src/main/docs/mvel-component.adoc +++ b/components/camel-mvel/src/main/docs/mvel-component.adoc @@ -51,6 +51,8 @@ include::partial$component-endpoint-headers.adoc[] Camel will provide exchange information in the MVEL context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="10%m,90%",options="header",] |======================================================================= @@ -79,8 +81,8 @@ never changes. Camel provides two headers by which you can define a different resource location for a template, or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. == Examples diff --git a/components/camel-mvel/src/main/java/org/apache/camel/component/mvel/MvelEndpoint.java b/components/camel-mvel/src/main/java/org/apache/camel/component/mvel/MvelEndpoint.java index 8e67b315b5e46..df13c47cd450c 100644 --- a/components/camel-mvel/src/main/java/org/apache/camel/component/mvel/MvelEndpoint.java +++ b/components/camel-mvel/src/main/java/org/apache/camel/component/mvel/MvelEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.support.ExchangeHelper; @@ -39,6 +42,13 @@ */ @UriEndpoint(firstVersion = "2.12.0", scheme = "mvel", title = "MVEL", syntax = "mvel:resourceUri", producerOnly = true, remote = false, category = { Category.TRANSFORMATION, Category.SCRIPT }, headersClass = MvelConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The template gets the body as body, as it is: no body prints as null, and" + + " bytes or a stream are not read as text. The template is the resource, or" + + " the CamelMvelTemplate header with allowTemplateFromHeader=true, never the" + + " body"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", + description = "The text the template writes. The headers are kept")) public class MvelEndpoint extends ResourceEndpoint { @UriParam diff --git a/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelLanguage.java b/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelLanguage.java index 342a117c91a52..6ba3f13c8e332 100644 --- a/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelLanguage.java +++ b/components/camel-mvel/src/main/java/org/apache/camel/language/mvel/MvelLanguage.java @@ -22,6 +22,9 @@ import org.apache.camel.Expression; import org.apache.camel.ExpressionIllegalSyntaxException; import org.apache.camel.Predicate; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.ScriptingLanguage; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.TypedLanguageSupport; @@ -31,6 +34,10 @@ * An MVEL {@link org.apache.camel.spi.Language} plugin */ @Language("mvel") +@BodyTypes(expressionIn = @BodyType(value = Carrier.ANY, + description = "The body as it is, in request.body or message.body: there is no variable" + + " body"), + expressionOut = @BodyType(value = Carrier.UNKNOWN, description = "What the expression returns")) public class MvelLanguage extends TypedLanguageSupport implements ScriptingLanguage { @Override diff --git a/components/camel-saxon/src/generated/resources/META-INF/org/apache/camel/component/xquery/xquery.json b/components/camel-saxon/src/generated/resources/META-INF/org/apache/camel/component/xquery/xquery.json index 3f3346a8b7bd3..0eebafc59fc30 100644 --- a/components/camel-saxon/src/generated/resources/META-INF/org/apache/camel/component/xquery/xquery.json +++ b/components/camel-saxon/src/generated/resources/META-INF/org/apache/camel/component/xquery/xquery.json @@ -31,6 +31,10 @@ "configurationProperties": { "index": 4, "kind": "property", "displayName": "Configuration Properties", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map", "deprecated": false, "autowired": false, "secret": false, "description": "To set custom Saxon configuration properties" }, "moduleURIResolver": { "index": 5, "kind": "property", "displayName": "Module URIResolver", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "net.sf.saxon.lib.ModuleURIResolver", "deprecated": false, "autowired": false, "secret": false, "description": "To use the custom ModuleURIResolver" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], "description": "The XML to query: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source. A Map or no body fails" }, + "producerOut": { "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document", "dependsOn": [ "resultType" ], "byOption": [ { "option": "resultsFormat", "value": "Bytes", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "resultsFormat", "value": "BytesSource", "carriers": [ "pojo" ], "javaType": "org.apache.camel.util.xml.BytesSource" }, { "option": "resultsFormat", "value": "DOMSource", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "resultsFormat", "value": "List", "carriers": [ "list" ] }, { "option": "resultsFormat", "value": "String", "carriers": [ "text" ], "javaType": "java.lang.String" }, { "option": "resultsFormat", "value": "StringSource", "carriers": [ "pojo" ], "javaType": "org.apache.camel.util.xml.StringSource" } ], "description": "The result of the query as a DOM Document. A query that gives text, a number or more than one element fails with the default DOM: set resultsFormat to String or List" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of the template to load from classpath or file system" }, "allowStAX": { "index": 1, "kind": "parameter", "displayName": "Allow St AX", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to allow using StAX mode" }, diff --git a/components/camel-saxon/src/generated/resources/META-INF/org/apache/camel/language/xquery/xquery.json b/components/camel-saxon/src/generated/resources/META-INF/org/apache/camel/language/xquery/xquery.json index 3bd82a8ede96b..f136ec5a42171 100644 --- a/components/camel-saxon/src/generated/resources/META-INF/org/apache/camel/language/xquery/xquery.json +++ b/components/camel-saxon/src/generated/resources/META-INF/org/apache/camel/language/xquery/xquery.json @@ -15,6 +15,10 @@ "modelName": "xquery", "modelJavaType": "org.apache.camel.model.language.XQueryExpression" }, + "bodyTypes": { + "expressionIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "dependsOn": [ "source" ], "description": "XML as text, bytes, a stream or a file, or a DOM or another javax.xml.transform.Source. A Map or no body fails" }, + "expressionOut": { "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document", "dependsOn": [ "resultType" ], "description": "The result of the query as a DOM Document. A query that gives text, a number or more than one element fails unless resultType is java.lang.String" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node." }, "expression": { "index": 1, "kind": "value", "displayName": "Expression", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The expression value in your chosen language syntax." }, diff --git a/components/camel-saxon/src/main/docs/xquery-component.adoc b/components/camel-saxon/src/main/docs/xquery-component.adoc index a2d941eb0734d..f4cf0dc56d870 100644 --- a/components/camel-saxon/src/main/docs/xquery-component.adoc +++ b/components/camel-saxon/src/main/docs/xquery-component.adoc @@ -165,7 +165,7 @@ Notice how we can reuse the namespace prefixes, *foo* in this case, in the XPath expression for easier namespace-based XQuery expressions! When you use functions in your XQuery expression, you need an explicit -type conversion which is done in the xml configuration via the *@type* +type conversion which is done in the xml configuration via the *resultType* attribute: [source,xml] diff --git a/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryEndpoint.java b/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryEndpoint.java index b6b007b2461d8..4d123f7c950e7 100644 --- a/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryEndpoint.java +++ b/components/camel-saxon/src/main/java/org/apache/camel/component/xquery/XQueryEndpoint.java @@ -26,6 +26,9 @@ import net.sf.saxon.query.StaticQueryContext; import org.apache.camel.Category; import org.apache.camel.Component; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -42,6 +45,28 @@ */ @UriEndpoint(firstVersion = "1.0.0", scheme = "xquery", title = "XQuery", syntax = "xquery:resourceUri", remote = false, category = { Category.TRANSFORMATION }) +@BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", dependsOn = "source", + description = "The XML to query: text, bytes, a stream, a file, a DOM or another" + + " javax.xml.transform.Source. A Map or no body fails"), + producerOut = @BodyType(value = Carrier.POJO, javaType = "org.w3c.dom.Document", dependsOn = "resultType", + byOption = { + @BodyType.When(option = "resultsFormat", value = "Bytes", carriers = Carrier.BYTES, + javaType = "byte[]"), + @BodyType.When(option = "resultsFormat", value = "BytesSource", + carriers = Carrier.POJO, + javaType = "org.apache.camel.util.xml.BytesSource"), + @BodyType.When(option = "resultsFormat", value = "DOMSource", + carriers = Carrier.TEXT, javaType = "java.lang.String"), + @BodyType.When(option = "resultsFormat", value = "List", carriers = Carrier.LIST), + @BodyType.When(option = "resultsFormat", value = "String", carriers = Carrier.TEXT, + javaType = "java.lang.String"), + @BodyType.When(option = "resultsFormat", value = "StringSource", + carriers = Carrier.POJO, + javaType = "org.apache.camel.util.xml.StringSource") }, + description = "The result of the query as a DOM Document. A query that gives text, a number" + + " or more than one element fails with the default DOM: set resultsFormat to" + + " String or List")) public class XQueryEndpoint extends ProcessorEndpoint { private static final Logger LOG = LoggerFactory.getLogger(XQueryEndpoint.class); diff --git a/components/camel-saxon/src/main/java/org/apache/camel/language/xquery/XQueryLanguage.java b/components/camel-saxon/src/main/java/org/apache/camel/language/xquery/XQueryLanguage.java index dfa1ec775941e..935afeb4fee6c 100644 --- a/components/camel-saxon/src/main/java/org/apache/camel/language/xquery/XQueryLanguage.java +++ b/components/camel-saxon/src/main/java/org/apache/camel/language/xquery/XQueryLanguage.java @@ -22,12 +22,23 @@ import org.apache.camel.CamelContext; import org.apache.camel.Expression; import org.apache.camel.component.xquery.XQueryBuilder; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.PropertyConfigurer; import org.apache.camel.spi.annotations.Language; import org.apache.camel.support.SingleInputTypedLanguageSupport; import org.apache.camel.support.component.PropertyConfigurerSupport; @Language("xquery") +@BodyTypes(expressionIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", dependsOn = "source", + description = "XML as text, bytes, a stream or a file, or a DOM or another" + + " javax.xml.transform.Source. A Map or no body fails"), + expressionOut = @BodyType(value = Carrier.POJO, javaType = "org.w3c.dom.Document", dependsOn = "resultType", + description = "The result of the query as a DOM Document. A query that gives text, a" + + " number or more than one element fails unless resultType is" + + " java.lang.String")) public class XQueryLanguage extends SingleInputTypedLanguageSupport implements PropertyConfigurer { private Configuration configuration; diff --git a/components/camel-schematron/src/generated/resources/META-INF/org/apache/camel/component/schematron/schematron.json b/components/camel-schematron/src/generated/resources/META-INF/org/apache/camel/component/schematron/schematron.json index 4a36cefb7e7c7..2ea15ac6e3f0d 100644 --- a/components/camel-schematron/src/generated/resources/META-INF/org/apache/camel/component/schematron/schematron.json +++ b/components/camel-schematron/src/generated/resources/META-INF/org/apache/camel/component/schematron/schematron.json @@ -27,6 +27,10 @@ "lazyStartProducer": { "index": 0, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "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." }, "autowiredEnabled": { "index": 1, "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." } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "The XML to validate: text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source. A Map or another POJO is read as its toString(): marshal it first; no body fails" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged: the CamelSchematronValidationStatus header is SUCCESS or FAILED, and CamelSchematronValidationReport holds the SVRL report. With abort, a failed assert throws a SchematronValidationException" } + }, "properties": { "path": { "index": 0, "kind": "path", "displayName": "Path", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "The path to the schematron rules file. Can either be in class path or location in the file system." }, "abort": { "index": 1, "kind": "parameter", "displayName": "Abort", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Flag to abort the route and throw a schematron validation exception." }, diff --git a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/SchematronEndpoint.java b/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/SchematronEndpoint.java index 3234327bef3f4..e5a4b10cea154 100644 --- a/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/SchematronEndpoint.java +++ b/components/camel-schematron/src/main/java/org/apache/camel/component/schematron/SchematronEndpoint.java @@ -34,6 +34,9 @@ import org.apache.camel.component.schematron.exception.SchematronConfigException; import org.apache.camel.component.schematron.processor.ClassPathURIResolver; import org.apache.camel.component.schematron.processor.TemplatesFactory; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -52,6 +55,15 @@ */ @UriEndpoint(firstVersion = "2.15.0", scheme = "schematron", title = "Schematron", syntax = "schematron:path", remote = false, producerOnly = true, category = { Category.VALIDATION }) +@BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", + description = "The XML to validate: text, bytes, a stream, a file, a DOM or another" + + " javax.xml.transform.Source. A Map or another POJO is read as its" + + " toString(): marshal it first; no body fails"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged: the CamelSchematronValidationStatus header is SUCCESS or FAILED," + + " and CamelSchematronValidationReport holds the SVRL report. With abort, a" + + " failed assert throws a SchematronValidationException")) public class SchematronEndpoint extends DefaultEndpoint { private static final Logger LOG = LoggerFactory.getLogger(SchematronEndpoint.class); diff --git a/components/camel-stringtemplate/src/generated/resources/META-INF/org/apache/camel/component/stringtemplate/string-template.json b/components/camel-stringtemplate/src/generated/resources/META-INF/org/apache/camel/component/stringtemplate/string-template.json index 6c156e63c2717..8eacc56d396b7 100644 --- a/components/camel-stringtemplate/src/generated/resources/META-INF/org/apache/camel/component/stringtemplate/string-template.json +++ b/components/camel-stringtemplate/src/generated/resources/META-INF/org/apache/camel/component/stringtemplate/string-template.json @@ -35,6 +35,10 @@ "CamelStringTemplateVariableMap": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Map of the variables which are made available to a script or template", "constantName": "org.apache.camel.component.stringtemplate.StringTemplateConstants#STRINGTEMPLATE_VARIABLE_MAP" }, "CamelStringTemplateTemplate": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.stringtemplate.StringTemplateConstants#STRINGTEMPLATE_TEMPLATE" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as body, as it is: text, or a Map, a List or a POJO to read from; convert bytes or a stream to a String first. The template is the resource, or the CamelStringTemplateTemplate or CamelStringTemplateResourceUri header with allowTemplateFromHeader=true, and never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, also when it is JSON or XML: unmarshal it to read its fields. The headers are kept, and the CamelStringTemplateResourceUri header is set to the uri of the resource" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/components/camel-stringtemplate/src/main/docs/string-template-component.adoc b/components/camel-stringtemplate/src/main/docs/string-template-component.adoc index 38ec47de2aa46..141e3bd68e05a 100644 --- a/components/camel-stringtemplate/src/main/docs/string-template-component.adoc +++ b/components/camel-stringtemplate/src/main/docs/string-template-component.adoc @@ -51,14 +51,15 @@ include::partial$component-endpoint-headers.adoc[] === Headers -Camel will store a reference to the resource in the message header with -key, `org.apache.camel.stringtemplate.resource`. The Resource is an -`org.springframework.core.io.Resource` object. +Camel sets the uri of the template resource in the message header +`CamelStringTemplateResourceUri`. === String Template Context Camel will provide exchange information in the String Template context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="10%,90%",options="header",] |======================================================================= @@ -92,8 +93,8 @@ This scenario can be used in production when the resource never changes. Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. === StringTemplate Attributes diff --git a/components/camel-stringtemplate/src/main/java/org/apache/camel/component/stringtemplate/StringTemplateEndpoint.java b/components/camel-stringtemplate/src/main/java/org/apache/camel/component/stringtemplate/StringTemplateEndpoint.java index 8fee752f12ff9..070d095abdca8 100644 --- a/components/camel-stringtemplate/src/main/java/org/apache/camel/component/stringtemplate/StringTemplateEndpoint.java +++ b/components/camel-stringtemplate/src/main/java/org/apache/camel/component/stringtemplate/StringTemplateEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.support.ExchangeHelper; @@ -39,6 +42,16 @@ syntax = "string-template:resourceUri", producerOnly = true, remote = false, category = { Category.TRANSFORMATION, Category.SCRIPT }, headersClass = StringTemplateConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The template gets the body as body, as it is: text, or a Map, a List or a" + + " POJO to read from; convert bytes or a stream to a String first. The" + + " template is the resource, or the CamelStringTemplateTemplate or" + + " CamelStringTemplateResourceUri header with allowTemplateFromHeader=true," + + " and never the body"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", + description = "The text the template writes, also when it is JSON or XML: unmarshal it to" + + " read its fields. The headers are kept, and the" + + " CamelStringTemplateResourceUri header is set to the uri of the resource")) public class StringTemplateEndpoint extends ResourceEndpoint { @UriParam diff --git a/components/camel-thymeleaf/src/generated/resources/META-INF/org/apache/camel/component/thymeleaf/thymeleaf.json b/components/camel-thymeleaf/src/generated/resources/META-INF/org/apache/camel/component/thymeleaf/thymeleaf.json index 5fd0193f05f47..3999546f8abcb 100644 --- a/components/camel-thymeleaf/src/generated/resources/META-INF/org/apache/camel/component/thymeleaf/thymeleaf.json +++ b/components/camel-thymeleaf/src/generated/resources/META-INF/org/apache/camel/component/thymeleaf/thymeleaf.json @@ -35,6 +35,10 @@ "CamelThymeleafVariableMap": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The value of this header should be a Map with key\/values that will be override any existing key with the same name. This can be used to preconfigure common key\/values you want to reuse in your Thymeleaf endpoints.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_VARIABLE_MAP" }, "CamelThymeleafServletContext": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "jakarta.servlet.ServletContext", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The ServletContext for a web application.", "constantName": "org.apache.camel.component.thymeleaf.ThymeleafConstants#THYMELEAF_SERVLET_CONTEXT" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as ${body}, as it is: text, or a Map, a List or a POJO to read from; no body prints as empty text, and bytes or a stream are not read as text. The template is the resource, or the CamelThymeleafTemplate header with allowTemplateFromHeader=true, never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, in its templateMode such as HTML. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc b/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc index ca557310b6369..4bcb723a06ab6 100644 --- a/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc +++ b/components/camel-thymeleaf/src/main/docs/thymeleaf-component.adoc @@ -66,6 +66,8 @@ The `fruit` header is now accessible from the `message.out.headers`. Camel will provide exchange information in the Thymeleaf context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="10%,90%",options="header",] |======================================================================= @@ -90,14 +92,16 @@ The `Exchange` is transferred as: |`response` |The Out message (only for InOut message exchange pattern). |======================================================================= -You can set up a custom Thymeleaf Context yourself by -setting property `allowTemplateFromHeader=true` and setting the message header `CamelThymeleafContext` like this +You can add your own variables to the Thymeleaf context with a `Map` in the message header +`CamelThymeleafVariableMap`. Camel sets the `body`, `header`, `headers`, `variable`, `variables` and +`exception` entries on top of it, and removes the header after use: ._Java-only: programmatic Thymeleaf context setup via Exchange API_ [source,java] ---- -EngineContext engineContext = new EngineContext(variableMap); -exchange.getIn().setHeader("CamelThymeleafContext", engineContext); +Map variableMap = new HashMap<>(); +variableMap.put("greeting", "Hello"); +exchange.getIn().setHeader("CamelThymeleafVariableMap", variableMap); ---- === Hot reloading @@ -112,8 +116,8 @@ when the resource never changes. Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= diff --git a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java index 28366d7689639..82c649faabf57 100644 --- a/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java +++ b/components/camel-thymeleaf/src/main/java/org/apache/camel/component/thymeleaf/ThymeleafEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.ExchangePattern; import org.apache.camel.RuntimeCamelException; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -49,6 +52,15 @@ remote = false, producerOnly = true, category = { Category.TRANSFORMATION }, headersClass = ThymeleafConstants.class) @Metadata(excludeProperties = "contentCache") +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The template gets the body as ${body}, as it is: text, or a Map, a List or a" + + " POJO to read from; no body prints as empty text, and bytes or a stream" + + " are not read as text. The template is the resource, or the" + + " CamelThymeleafTemplate header with allowTemplateFromHeader=true, never the" + + " body"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", + description = "The text the template writes, in its templateMode such as HTML. The headers" + + " are kept")) public class ThymeleafEndpoint extends ResourceEndpoint { private TemplateEngine templateEngine; diff --git a/components/camel-velocity/src/generated/resources/META-INF/org/apache/camel/component/velocity/velocity.json b/components/camel-velocity/src/generated/resources/META-INF/org/apache/camel/component/velocity/velocity.json index 951eac85ee9f4..c33d8999d0dc4 100644 --- a/components/camel-velocity/src/generated/resources/META-INF/org/apache/camel/component/velocity/velocity.json +++ b/components/camel-velocity/src/generated/resources/META-INF/org/apache/camel/component/velocity/velocity.json @@ -37,6 +37,10 @@ "CamelVelocityContext": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "org.apache.velocity.context.Context", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The velocity context to use.", "constantName": "org.apache.camel.component.velocity.VelocityConstants#VELOCITY_CONTEXT" }, "CamelVelocitySupplementalContext": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "To add additional information to the used VelocityContext. The value of this header should be a Map with key\/values that will added (override any existing key with the same name). This can be used to pre setup some common key\/values you want to reuse in your velocity endpoints.", "constantName": "org.apache.camel.component.velocity.VelocityConstants#VELOCITY_SUPPLEMENTAL_CONTEXT" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "any" ], "description": "The template gets the body as body, as it is: text, or a Map, a List or a POJO to read from; convert bytes or a stream to a String first. The template is the resource, or the CamelVelocityTemplate or CamelVelocityResourceUri header with allowTemplateFromHeader=true, and never the body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "description": "The text the template writes, also when it is JSON or XML: unmarshal it to read its fields. The headers are kept" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "supportFileReference": true, "description": "Path to the resource. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod." }, "allowContextMapAll": { "index": 1, "kind": "parameter", "displayName": "Allow Context Map All", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether the context map should allow access to all details. By default only the message body and headers can be accessed. This option can be enabled for full access to the current Exchange and CamelContext. Doing so impose a potential security risk as this opens access to the full power of CamelContext API." }, diff --git a/components/camel-velocity/src/main/docs/velocity-component.adoc b/components/camel-velocity/src/main/docs/velocity-component.adoc index cb102bb2f991a..a215ef6531ae3 100644 --- a/components/camel-velocity/src/main/docs/velocity-component.adoc +++ b/components/camel-velocity/src/main/docs/velocity-component.adoc @@ -67,6 +67,8 @@ The `fruit` header is now accessible from the `message.out.headers`. Camel will provide exchange information in the Velocity context (just a `Map`). The `Exchange` is transferred as: +The `body`, `header`, `headers`, `variable`, `variables` and `exception` entries are always +there; the others only when the endpoint has `allowContextMapAll=true`. [width="100%",cols="10%,90%",options="header",] |======================================================================= @@ -195,8 +197,8 @@ when the resource never changes. Camel provides two headers by which you can define a different resource location for a template or the template content itself. If any of these -headers is set, then Camel uses this over the endpoint configured -resource. This allows you to provide a dynamic template at runtime. +headers is set, and the endpoint has `allowTemplateFromHeader=true`, then Camel uses this +over the endpoint configured resource. This allows you to provide a dynamic template at runtime. [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= diff --git a/components/camel-velocity/src/main/java/org/apache/camel/component/velocity/VelocityEndpoint.java b/components/camel-velocity/src/main/java/org/apache/camel/component/velocity/VelocityEndpoint.java index 52317dd6bfd55..c7cfdb98fcf8f 100644 --- a/components/camel-velocity/src/main/java/org/apache/camel/component/velocity/VelocityEndpoint.java +++ b/components/camel-velocity/src/main/java/org/apache/camel/component/velocity/VelocityEndpoint.java @@ -28,6 +28,9 @@ import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.component.ResourceEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.support.ExchangeHelper; @@ -47,6 +50,15 @@ @UriEndpoint(firstVersion = "1.2.0", scheme = "velocity", title = "Velocity", syntax = "velocity:resourceUri", remote = false, producerOnly = true, category = { Category.TRANSFORMATION }, headersClass = VelocityConstants.class) +@BodyTypes(producerIn = @BodyType(value = Carrier.ANY, + description = "The template gets the body as body, as it is: text, or a Map, a List or a" + + " POJO to read from; convert bytes or a stream to a String first. The" + + " template is the resource, or the CamelVelocityTemplate or" + + " CamelVelocityResourceUri header with allowTemplateFromHeader=true, and" + + " never the body"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", + description = "The text the template writes, also when it is JSON or XML: unmarshal it to" + + " read its fields. The headers are kept")) public class VelocityEndpoint extends ResourceEndpoint { private VelocityEngine velocityEngine; diff --git a/components/camel-xj/src/generated/resources/META-INF/org/apache/camel/component/xj/xj.json b/components/camel-xj/src/generated/resources/META-INF/org/apache/camel/component/xj/xj.json index 2af1f9038eceb..0a57d2901364b 100644 --- a/components/camel-xj/src/generated/resources/META-INF/org/apache/camel/component/xj/xj.json +++ b/components/camel-xj/src/generated/resources/META-INF/org/apache/camel/component/xj/xj.json @@ -43,6 +43,10 @@ "CamelXsltResourceUri": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A URI for the template resource to load and use instead of the endpoint configured.", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_RESOURCE_URI" }, "CamelXsltStylesheet": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The template to use instead of the endpoint configured.", "constantName": "org.apache.camel.component.xslt.XsltConstants#XSLT_STYLESHEET" } }, + "bodyTypes": { + "producerIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "dependsOn": [ "source", "useJsonBody" ], "byOption": [ { "option": "transformDirection", "value": "XML2JSON", "carriers": [ "text", "bytes", "stream", "file", "pojo" ] }, { "option": "transformDirection", "value": "JSON2XML", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "The XML for XML2JSON as text, bytes, a stream, a file, a DOM or another javax.xml.transform.Source; the JSON for JSON2XML as text, bytes, a stream or a file. A Map, a List or no body fails, unless failOnNullBody=false for no body" }, + "producerOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "dependsOn": [ "resultHandlerFactory" ], "byOption": [ { "option": "output", "value": "bytes", "carriers": [ "bytes" ], "javaType": "byte[]" }, { "option": "output", "value": "DOM", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document" }, { "option": "output", "value": "file", "carriers": [ "file" ], "javaType": "java.io.File" } ], "description": "The result of the transformation: JSON text with XML2JSON, XML text with JSON2XML. output=DOM works with JSON2XML only" } + }, "properties": { "resourceUri": { "index": 0, "kind": "path", "displayName": "Resource Uri", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Path to the template. The following is supported by the default URIResolver. You can prefix with: classpath, file, http, ref, or bean. classpath, file and http loads the resource using these protocols (classpath is default). ref will lookup the resource in the registry. bean will call a method on a bean to be used as the resource. For bean you can specify the method name after dot, eg bean:myBean.myMethod" }, "allowStAX": { "index": 1, "kind": "parameter", "displayName": "Allow StAX", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to allow using StAX as the javax.xml.transform.Source. You can enable this if the XSLT library supports StAX such as the Saxon library (camel-saxon). The Xalan library (default in JVM) does not support StAXSource." }, diff --git a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJEndpoint.java b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJEndpoint.java index 6a0c7655ba833..4fe5ab7855478 100644 --- a/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJEndpoint.java +++ b/components/camel-xj/src/main/java/org/apache/camel/component/xj/XJEndpoint.java @@ -24,6 +24,9 @@ import org.apache.camel.component.xslt.XsltBuilder; import org.apache.camel.component.xslt.saxon.XsltSaxonBuilder; import org.apache.camel.component.xslt.saxon.XsltSaxonEndpoint; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -34,6 +37,31 @@ @ManagedResource(description = "Managed XJEndpoint") @UriEndpoint(firstVersion = "3.0.0", scheme = "xj", title = "XJ", syntax = "xj:resourceUri", producerOnly = true, remote = false, category = { Category.TRANSFORMATION }, headersClass = XJConstants.class) +@BodyTypes(producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + dependsOn = { "source", "useJsonBody" }, + byOption = { + @BodyType.When(option = "transformDirection", value = "XML2JSON", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, + Carrier.POJO }), + @BodyType.When(option = "transformDirection", value = "JSON2XML", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }) }, + description = "The XML for XML2JSON as text, bytes, a stream, a file, a DOM or another" + + " javax.xml.transform.Source; the JSON for JSON2XML as text, bytes, a stream" + + " or a file. A Map, a List or no body fails, unless failOnNullBody=false for" + + " no body"), + producerOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", dependsOn = "resultHandlerFactory", + byOption = { + @BodyType.When(option = "output", value = "bytes", carriers = Carrier.BYTES, + javaType = "byte[]"), + @BodyType.When(option = "output", value = "DOM", carriers = Carrier.POJO, + javaType = "org.w3c.dom.Document"), + @BodyType.When(option = "output", value = "file", carriers = Carrier.FILE, + javaType = "java.io.File") }, + description = "The result of the transformation: JSON text with XML2JSON, XML text with" + + " JSON2XML. output=DOM works with JSON2XML only")) public class XJEndpoint extends XsltSaxonEndpoint { private final JsonFactory jsonFactory = new JsonFactory(); diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java index 0f15009a19dcb..557ad7d9b4245 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java @@ -1051,6 +1051,62 @@ public void testTheBodyOfCachesAndSigning() { .contains("route put: to: file needs the body as text, bytes, a stream or a file")); } + @Test + public void testTheBodyOfTransformations() { + // jslt and json-validator read JSON text, so parsed data must be marshalled first; a template writes text, so a + // field read needs an unmarshal; and jolt gives parsed JSON, which the file producer cannot write + String yaml = """ + - route: + id: jslt + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: jslt:order.json + - route: + id: check + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: json-validator:order-schema.json + - route: + id: template + from: + uri: timer:tick + steps: + - to: velocity:order.vm + - setHeader: + name: id + simple: ${body[id]} + - route: + id: jolt + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: jolt:spec.json + - to: file:out + """; + assertThat(lines(yaml)).hasSize(4) + .anySatisfy( + m -> assertThat(m).contains("route jslt: to: jslt needs the body as text, bytes, a stream or a file")) + .anySatisfy(m -> assertThat(m) + .contains("route check: to: json-validator needs the body as text, bytes, a stream or a file")) + .anySatisfy(m -> assertThat(m).contains("route template: simple reads a field of the body (${body[id]})")) + .anySatisfy(m -> assertThat(m) + .contains("route jolt: to: file needs the body as text, bytes, a stream or a file")); + } + @Test public void testAnOptionTheBodyDependsOnOutweighsAnotherOption() { // xslt with output bytes gives bytes, so a field read needs an unmarshal; with a resultHandlerFactory too the From 773aec492eb50c4061c9d453870f4ae1385151b8 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 22 Oct 2026 15:59:49 +0200 Subject: [PATCH 22/25] CAMEL-24961: Catalog body types for the text data formats Declares the body before and after marshal and unmarshal for 32 data formats: bindyCsv, bindyFixed, bindyKvp, univocityCsv, univocityFixed, univocityTsv, beanio, flatpack, gson, jsonb, fastjson, groovyJson, groovyXml, jsonApi, toon, ocsf, base64, jaxb, soap, ubl, fhirJson, fhirXml, hl7, swiftMt, swiftMx, ical, rss, syslog, grok, iso8583, asn1 and dfdl. The validator now sees the parsed data that gson, jsonb, fastjson, groovyJson, toon, univocity, beanio and flatpack give, as it does for jackson; the test that used gson as a data format without body types uses gson with an unmarshalType. Fixes the doc prose about the body: bindy unmarshal gives the classType objects (not a List of Maps), jaxb mustBeJAXBElement is false by default, the JSON data formats that write JSON text as it is, base64 unmarshal gives a stream, rss, grok (and its COMBINEDAPACHELOG examples), asn1, dfdl and the SWIFT marshal. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../camel/catalog/dataformats/asn1.json | 6 +++ .../camel/catalog/dataformats/base64.json | 6 +++ .../camel/catalog/dataformats/beanio.json | 6 +++ .../camel/catalog/dataformats/bindyCsv.json | 6 +++ .../camel/catalog/dataformats/bindyFixed.json | 6 +++ .../camel/catalog/dataformats/bindyKvp.json | 6 +++ .../camel/catalog/dataformats/dfdl.json | 6 +++ .../camel/catalog/dataformats/fastjson.json | 6 +++ .../camel/catalog/dataformats/fhirJson.json | 6 +++ .../camel/catalog/dataformats/fhirXml.json | 6 +++ .../camel/catalog/dataformats/flatpack.json | 6 +++ .../camel/catalog/dataformats/grok.json | 4 ++ .../camel/catalog/dataformats/groovyJson.json | 6 +++ .../camel/catalog/dataformats/groovyXml.json | 6 +++ .../camel/catalog/dataformats/gson.json | 6 +++ .../apache/camel/catalog/dataformats/hl7.json | 6 +++ .../camel/catalog/dataformats/ical.json | 6 +++ .../camel/catalog/dataformats/iso8583.json | 6 +++ .../camel/catalog/dataformats/jaxb.json | 6 +++ .../camel/catalog/dataformats/jsonApi.json | 6 +++ .../camel/catalog/dataformats/jsonb.json | 6 +++ .../camel/catalog/dataformats/ocsf.json | 6 +++ .../apache/camel/catalog/dataformats/rss.json | 6 +++ .../camel/catalog/dataformats/soap.json | 6 +++ .../camel/catalog/dataformats/swiftMt.json | 6 +++ .../camel/catalog/dataformats/swiftMx.json | 6 +++ .../camel/catalog/dataformats/syslog.json | 6 +++ .../camel/catalog/dataformats/toon.json | 6 +++ .../apache/camel/catalog/dataformats/ubl.json | 6 +++ .../catalog/dataformats/univocityCsv.json | 6 +++ .../catalog/dataformats/univocityFixed.json | 6 +++ .../catalog/dataformats/univocityTsv.json | 6 +++ .../camel/catalog/docs/asn1-dataformat.adoc | 6 +-- .../camel/catalog/docs/base64-dataformat.adoc | 4 +- .../camel/catalog/docs/bindy-dataformat.adoc | 50 +++++------------ .../camel/catalog/docs/dfdl-dataformat.adoc | 2 +- .../catalog/docs/fastjson-dataformat.adoc | 11 ++-- .../camel/catalog/docs/grok-dataformat.adoc | 10 ++-- .../camel/catalog/docs/gson-dataformat.adoc | 11 ++-- .../catalog/docs/jackson2-dataformat.adoc | 11 ++-- .../catalog/docs/jackson3-dataformat.adoc | 11 ++-- .../camel/catalog/docs/jaxb-dataformat.adoc | 9 ++-- .../camel/catalog/docs/jsonb-dataformat.adoc | 11 ++-- .../camel/catalog/docs/rss-dataformat.adoc | 8 +-- .../catalog/docs/swiftMt-dataformat.adoc | 2 + .../catalog/docs/swiftMx-dataformat.adoc | 2 + .../apache/camel/dataformat/asn1/asn1.json | 6 +++ .../src/main/docs/asn1-dataformat.adoc | 6 +-- .../camel/dataformat/asn1/ASN1DataFormat.java | 21 ++++++++ .../camel/dataformat/base64/base64.json | 6 +++ .../src/main/docs/base64-dataformat.adoc | 4 +- .../dataformat/base64/Base64DataFormat.java | 11 ++++ .../camel/dataformat/beanio/beanio.json | 6 +++ .../dataformat/beanio/BeanIODataFormat.java | 16 ++++++ .../camel/dataformat/bindy/csv/bindyCsv.json | 6 +++ .../dataformat/bindy/fixed/bindyFixed.json | 6 +++ .../camel/dataformat/bindy/kvp/bindyKvp.json | 6 +++ .../src/main/docs/bindy-dataformat.adoc | 50 +++++------------ .../bindy/csv/BindyCsvDataFormat.java | 15 ++++++ .../fixed/BindyFixedLengthDataFormat.java | 18 +++++++ .../kvp/BindyKeyValuePairDataFormat.java | 15 ++++++ .../apache/camel/dataformat/dfdl/dfdl.json | 6 +++ .../src/main/docs/dfdl-dataformat.adoc | 2 +- .../camel/dataformat/dfdl/DfdlDataFormat.java | 14 +++++ .../camel/component/fastjson/fastjson.json | 6 +++ .../src/main/docs/fastjson-dataformat.adoc | 11 ++-- .../fastjson/FastjsonDataFormat.java | 13 +++++ .../apache/camel/component/fhir/fhirJson.json | 6 +++ .../apache/camel/component/fhir/fhirXml.json | 6 +++ .../component/fhir/FhirJsonDataFormat.java | 13 +++++ .../component/fhir/FhirXmlDataFormat.java | 13 +++++ .../camel/dataformat/flatpack/flatpack.json | 6 +++ .../flatpack/FlatpackDataFormat.java | 14 +++++ .../org/apache/camel/component/grok/grok.json | 4 ++ .../src/main/docs/grok-dataformat.adoc | 10 ++-- .../camel/component/grok/GrokDataFormat.java | 8 +++ .../apache/camel/groovy/json/groovyJson.json | 6 +++ .../apache/camel/groovy/xml/groovyXml.json | 6 +++ .../groovy/json/GroovyJSonlDataFormat.java | 13 +++++ .../camel/groovy/xml/GroovyXmlDataFormat.java | 13 +++++ .../org/apache/camel/component/gson/gson.json | 6 +++ .../src/main/docs/gson-dataformat.adoc | 11 ++-- .../camel/component/gson/GsonDataFormat.java | 15 ++++++ .../org/apache/camel/component/hl7/hl7.json | 6 +++ .../camel/component/hl7/HL7DataFormat.java | 19 +++++++ .../org/apache/camel/component/ical/ical.json | 6 +++ .../camel/component/ical/ICalDataFormat.java | 13 +++++ .../camel/dataformat/iso8583/iso8583.json | 6 +++ .../dataformat/iso8583/Iso8583DataFormat.java | 13 +++++ .../src/main/docs/jackson2-dataformat.adoc | 11 ++-- .../src/main/docs/jackson3-dataformat.adoc | 11 ++-- .../org/apache/camel/converter/jaxb/jaxb.json | 6 +++ .../src/main/docs/jaxb-dataformat.adoc | 9 ++-- .../camel/converter/jaxb/JaxbDataFormat.java | 20 +++++++ .../camel/component/jsonapi/jsonApi.json | 6 +++ .../component/jsonapi/JsonApiDataFormat.java | 13 +++++ .../apache/camel/component/jsonb/jsonb.json | 6 +++ .../src/main/docs/jsonb-dataformat.adoc | 11 ++-- .../component/jsonb/JsonbDataFormat.java | 15 ++++++ .../apache/camel/dataformat/ocsf/ocsf.json | 6 +++ .../camel/dataformat/ocsf/OcsfDataFormat.java | 14 +++++ .../org/apache/camel/dataformat/rss/rss.json | 6 +++ .../src/main/docs/rss-dataformat.adoc | 8 +-- .../camel/dataformat/rss/RssDataFormat.java | 13 +++++ .../apache/camel/dataformat/soap/soap.json | 6 +++ .../camel/dataformat/soap/SoapDataFormat.java | 19 +++++++ .../camel/dataformat/swift/mt/swiftMt.json | 6 +++ .../camel/dataformat/swift/mx/swiftMx.json | 6 +++ .../src/main/docs/swiftMt-dataformat.adoc | 2 + .../src/main/docs/swiftMx-dataformat.adoc | 2 + .../swift/mt/SwiftMtDataFormat.java | 17 ++++++ .../swift/mx/SwiftMxDataFormat.java | 17 ++++++ .../apache/camel/component/syslog/syslog.json | 6 +++ .../component/syslog/SyslogDataFormat.java | 14 +++++ .../apache/camel/dataformat/toon/toon.json | 6 +++ .../camel/dataformat/toon/ToonDataFormat.java | 12 +++++ .../org/apache/camel/component/ubl/ubl.json | 6 +++ .../camel/component/ubl/UblDataFormat.java | 13 +++++ .../dataformat/univocity/univocityCsv.json | 6 +++ .../dataformat/univocity/univocityFixed.json | 6 +++ .../dataformat/univocity/univocityTsv.json | 6 +++ .../univocity/UniVocityCsvDataFormat.java | 16 ++++++ .../univocity/UniVocityFixedDataFormat.java | 16 ++++++ .../univocity/UniVocityTsvDataFormat.java | 16 ++++++ .../dsl/yaml/validator/TextBodyFlowTest.java | 53 ++++++++++++++++++- 125 files changed, 1037 insertions(+), 164 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/asn1.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/asn1.json index 03311982f6bce..fc2e98ff7cb26 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/asn1.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/asn1.json @@ -15,6 +15,12 @@ "modelName": "asn1", "modelJavaType": "org.apache.camel.model.dataformat.ASN1DataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "bytes", "stream", "file" ], "dependsOn": [ "unmarshalType" ], "byOption": [ { "option": "usingIterator", "value": "true", "carriers": [ "bytes", "pojo" ] } ], "description": "BER-encoded data, written as it is. With usingIterator, a byte array or a Bouncy Castle ASN1Primitive, and with unmarshalType as well an object of a class the asn1bean compiler generated" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The BER-encoded data in the stream cache, or a byte array when stream caching is off. With usingIterator, and no unmarshalType, nothing is written for a body that is neither a byte array nor an ASN1Primitive" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "BER-encoded data: one record, or several one after the other" }, + "unmarshalOut": { "carriers": [ "bytes" ], "byOption": [ { "option": "usingIterator", "value": "true", "carriers": [ "iterator" ] } ], "description": "The records, encoded again, in one byte array. With usingIterator, an Iterator for the split EIP: of messages with the bytes of one record each, or of objects of the class unmarshalType names" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "unmarshalType": { "index": 1, "kind": "attribute", "displayName": "Unmarshal Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Class to use when unmarshalling." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/base64.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/base64.json index ad3055b9f3acc..e379fd094013b 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/base64.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/base64.json @@ -15,6 +15,12 @@ "modelName": "base64", "modelJavaType": "org.apache.camel.model.dataformat.Base64DataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The bytes to encode: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The Base64 text in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decoded bytes, as a stream" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "lineLength": { "index": 1, "kind": "attribute", "displayName": "Line Length", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 76, "description": "To specific a maximum line length for the encoded data. By default 76 is used." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/beanio.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/beanio.json index d6337118ed60d..1fe7c996b2ab8 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/beanio.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/beanio.json @@ -15,6 +15,12 @@ "modelName": "beanio", "modelJavaType": "org.apache.camel.model.dataformat.BeanioDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo", "list" ], "byOption": [ { "option": "unmarshalSingleObject", "value": "true", "carriers": [ "pojo", "map", "list" ] } ], "description": "A bean of a record of the mapping file, or a List (or an Iterator) of them; a Map is one record only with unmarshalSingleObject" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The records in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ] }, + "unmarshalOut": { "carriers": [ "list" ], "byOption": [ { "option": "unmarshalSingleObject", "value": "true", "carriers": [ "pojo", "map" ] } ], "description": "A List with the bean of each record, of the class the mapping file names (a Map for a map record); with unmarshalSingleObject, the one bean" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "mapping": { "index": 1, "kind": "attribute", "displayName": "Mapping", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The BeanIO mapping file. Is by default loaded from the classpath. You can prefix with file:, http:, or classpath: to denote from where to load the mapping file." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyCsv.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyCsv.json index 647c173c39e7b..23ee0e8a7e218 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyCsv.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyCsv.json @@ -15,6 +15,12 @@ "modelName": "bindy", "modelJavaType": "org.apache.camel.model.dataformat.BindyDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo", "list" ], "description": "An object of the classType class, or a List (or an Iterator) of them; a Map of the model class names to the objects is one record. Other bodies, such as a Map of field values, are not records" }, + "marshalOut": { "carriers": [ "stream" ], "format": "csv", "description": "The CSV in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "csv" }, + "unmarshalOut": { "carriers": [ "pojo", "list" ], "byOption": [ { "option": "unwrapSingleInstance", "value": "false", "carriers": [ "list" ] } ], "description": "An object of the classType class when there is one record, otherwise a List of them; an empty List for no records with allowEmptyStream" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "type": { "index": 1, "kind": "attribute", "displayName": "Type", "group": "common", "required": true, "type": "enum", "javaType": "org.apache.camel.model.dataformat.BindyType", "enum": [ "Csv", "Fixed", "KeyValue" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Csv", "description": "Whether to use Csv, Fixed, or KeyValue." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyFixed.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyFixed.json index d5ce6fb3760d3..42d40b2029b0c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyFixed.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyFixed.json @@ -15,6 +15,12 @@ "modelName": "bindy", "modelJavaType": "org.apache.camel.model.dataformat.BindyDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo", "list" ], "description": "An object of the classType class, or a List (or an Iterator) of them, or a List of Maps of the model class name to the object. The headers CamelBindyFixedLengthHeader and CamelBindyFixedLengthFooter add the header and footer records" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The fixed-length records in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "pojo", "list" ], "byOption": [ { "option": "unwrapSingleInstance", "value": "false", "carriers": [ "list" ] } ], "description": "An object of the classType class when there is one record, otherwise a List of them. The header and footer records go to the headers CamelBindyFixedLengthHeader and CamelBindyFixedLengthFooter" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "type": { "index": 1, "kind": "attribute", "displayName": "Type", "group": "common", "required": true, "type": "enum", "javaType": "org.apache.camel.model.dataformat.BindyType", "enum": [ "Csv", "Fixed", "KeyValue" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Fixed", "description": "Whether to use Csv, Fixed, or KeyValue." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyKvp.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyKvp.json index 611ef30a2f618..de3efcd7f7e31 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyKvp.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/bindyKvp.json @@ -15,6 +15,12 @@ "modelName": "bindy", "modelJavaType": "org.apache.camel.model.dataformat.BindyDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo", "list" ], "description": "An object of the classType class, or a List (or an Iterator) of them; a Map of the model class names to the objects is one message" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The key-value pair messages, one per line, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "pojo", "list" ], "byOption": [ { "option": "unwrapSingleInstance", "value": "false", "carriers": [ "list" ] } ], "description": "An object of the classType class when there is one message (one per line), otherwise a List of them" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "type": { "index": 1, "kind": "attribute", "displayName": "Type", "group": "common", "required": true, "type": "enum", "javaType": "org.apache.camel.model.dataformat.BindyType", "enum": [ "Csv", "Fixed", "KeyValue" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "KeyValue", "description": "Whether to use Csv, Fixed, or KeyValue." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/dfdl.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/dfdl.json index ca76ac1593d1b..e6603b8a9e3d7 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/dfdl.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/dfdl.json @@ -15,6 +15,12 @@ "modelName": "dfdl", "modelJavaType": "org.apache.camel.model.dataformat.DfdlDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "The XML infoset of the DFDL schema, as text or as a DOM Document (or another DOM Node or Source), which is converted to a DOM Document" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The data in the format the DFDL schema describes, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "Data in the format the DFDL schema describes, such as an EDI message" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document", "description": "The XML infoset as a DOM Document" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "schemaUri": { "index": 1, "kind": "attribute", "displayName": "Schema Uri", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The path to the DFDL schema file." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fastjson.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fastjson.json index 6ff07816a4c98..b75e6e4b6e206 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fastjson.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fastjson.json @@ -15,6 +15,12 @@ "modelName": "json", "modelJavaType": "org.apache.camel.model.dataformat.JsonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as JSON. Bytes, a stream, a file from a file consumer, or a String with a JSON object or array is written as it is; any other String becomes a JSON string" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType" ], "description": "A Map (fastjson JSONObject) for a JSON object, a List (JSONArray) for an array; an object of the class unmarshalType names" } + }, "properties": { "prettyPrint": { "index": 0, "kind": "attribute", "displayName": "Pretty Print", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "To enable pretty printing output nicely formatted. Is by default false." }, "unmarshalType": { "index": 1, "kind": "attribute", "displayName": "Unmarshal Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Class name of the java type to use when unmarshalling." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fhirJson.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fhirJson.json index 98c9108add2f2..3c94c8f7277e8 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fhirJson.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fhirJson.json @@ -15,6 +15,12 @@ "modelName": "fhirJson", "modelJavaType": "org.apache.camel.model.dataformat.FhirJsonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "org.hl7.fhir.instance.model.api.IBaseResource", "description": "A HAPI FHIR resource of the fhirVersion, such as a Patient or a Bundle. Text fails: no type converter makes a resource of it" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The FHIR JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.hl7.fhir.instance.model.api.IBaseResource", "description": "The HAPI FHIR resource of the model of the fhirVersion, such as an org.hl7.fhir.r4.model.Patient with R4" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "fhirVersion": { "index": 1, "kind": "attribute", "displayName": "Fhir Version", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "DSTU2", "DSTU2_HL7ORG", "DSTU2_1", "DSTU3", "R4", "R5" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "R4", "description": "The version of FHIR to use. Possible values are: DSTU2, DSTU2_HL7ORG, DSTU2_1, DSTU3, R4, R5." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fhirXml.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fhirXml.json index b8458c3dd6ea4..848c79932ac94 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fhirXml.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fhirXml.json @@ -15,6 +15,12 @@ "modelName": "fhirXml", "modelJavaType": "org.apache.camel.model.dataformat.FhirXmlDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "org.hl7.fhir.instance.model.api.IBaseResource", "description": "A HAPI FHIR resource of the fhirVersion, such as a Patient or a Bundle. Text fails: no type converter makes a resource of it" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The FHIR XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.hl7.fhir.instance.model.api.IBaseResource", "description": "The HAPI FHIR resource of the model of the fhirVersion, such as an org.hl7.fhir.r4.model.Patient with R4" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "fhirVersion": { "index": 1, "kind": "attribute", "displayName": "Fhir Version", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "DSTU2", "DSTU2_HL7ORG", "DSTU2_1", "DSTU3", "R4", "R5" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "R4", "description": "The version of FHIR to use. Possible values are: DSTU2, DSTU2_HL7ORG, DSTU2_1, DSTU3, R4, R5." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/flatpack.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/flatpack.json index 5638a7e2e8a08..7838092a3049f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/flatpack.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/flatpack.json @@ -15,6 +15,12 @@ "modelName": "flatpack", "modelJavaType": "org.apache.camel.model.dataformat.FlatpackDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "list" ], "description": "The rows as a List of Maps, such as the DataSetList unmarshal gives; a single Map fails. Without a definition, the keys of the first Map name the columns" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The records in the stream cache, or a byte array when stream caching is off. An empty List writes nothing" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "list" ], "javaType": "org.apache.camel.component.flatpack.DataSetList", "description": "A DataSetList: a List of the rows, each a HashMap of the column names and the values, which does not keep the column order" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "definition": { "index": 1, "kind": "attribute", "displayName": "Definition", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The flatpack pzmap configuration file. Can be omitted in simpler situations, but its preferred to use the pzmap." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/grok.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/grok.json index f219274c1140e..728fb1f6020a9 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/grok.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/grok.json @@ -15,6 +15,10 @@ "modelName": "grok", "modelJavaType": "org.apache.camel.model.dataformat.GrokDataFormat" }, + "bodyTypes": { + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text", "description": "Lines of text, such as a log file: each line is matched with the pattern" }, + "unmarshalOut": { "carriers": [ "map", "list", "null" ], "description": "A Map of the captures for one match, a List of such Maps for several, or null when no line matches. The Maps cannot be modified" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "pattern": { "index": 1, "kind": "attribute", "displayName": "Pattern", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The grok pattern to match lines of input." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/groovyJson.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/groovyJson.json index dc892d67c8c59..2c5a121121415 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/groovyJson.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/groovyJson.json @@ -15,6 +15,12 @@ "modelName": "groovyJson", "modelJavaType": "org.apache.camel.model.dataformat.GroovyJSonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ], "description": "A Map, a Groovy Node or a Jackson JsonNode to write as JSON. Text, bytes, a stream or a file is written as it is; a List is not supported" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "description": "A Map (Groovy LazyMap) for a JSON object, a List (ArrayList) for an array" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "prettyPrint": { "index": 1, "kind": "attribute", "displayName": "Pretty Print", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to pretty print output nicely formatted." } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/groovyXml.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/groovyXml.json index 0852d10a91908..34f2a2fc7a6fb 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/groovyXml.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/groovyXml.json @@ -15,6 +15,12 @@ "modelName": "groovyXml", "modelJavaType": "org.apache.camel.model.dataformat.GroovyXmlDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ], "description": "A Groovy Node or GPathResult, a Map or a Jackson JsonNode to write as XML. Text, bytes, a stream or a file is written as it is" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "groovy.util.Node", "description": "The XML parsed into a Groovy Node" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "attributeMapping": { "index": 1, "kind": "attribute", "displayName": "Attribute Mapping", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to enable attribute mapping. When enabled, keys that start with _ or character will be mapped to an XML attribute, and vice versa." } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/gson.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/gson.json index b1b147bfa11dd..858352bc3072e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/gson.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/gson.json @@ -15,6 +15,12 @@ "modelName": "json", "modelJavaType": "org.apache.camel.model.dataformat.JsonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as JSON. Bytes, a stream, a file from a file consumer, or a String with a JSON object or array is written as it is; any other String becomes a JSON string" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "allowUnmarshallType" ], "description": "A Map (Gson LinkedTreeMap) for a JSON object, a List (ArrayList) for an array, with the numbers as Double; an object of the class unmarshalType names" } + }, "properties": { "prettyPrint": { "index": 0, "kind": "attribute", "displayName": "Pretty Print", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "To enable pretty printing output nicely formatted. Is by default false." }, "unmarshalType": { "index": 1, "kind": "attribute", "displayName": "Unmarshal Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Class name of the java type to use when unmarshalling." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/hl7.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/hl7.json index 26599aee6c8d0..6447ee4209e89 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/hl7.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/hl7.json @@ -15,6 +15,12 @@ "modelName": "hl7", "modelJavaType": "org.apache.camel.model.dataformat.HL7DataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "pojo" ], "description": "A HAPI Message, or HL7 as text or bytes (ER7 or XML) or an HL7 XML DOM Document, which a type converter parses into a Message. A stream or a file fails: convert it to text first" }, + "marshalOut": { "carriers": [ "stream" ], "description": "HL7 in ER7 (pipe-delimited), or HL7 XML with targetFormat XML, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "HL7 in ER7 (pipe-delimited) or XML, which the parser detects" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "ca.uhn.hl7v2.model.Message", "byOption": [ { "option": "targetFormat", "value": "XML", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document" } ], "description": "The HAPI Message of the structure for its type and version, such as ADT_A01 (a GenericMessage without the structures), with the MSH fields in CamelHL7 headers. With targetFormat XML, the HL7 XML as a DOM Document" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "parser": { "index": 1, "kind": "attribute", "displayName": "Parser", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "ca.uhn.hl7v2.parser.Parser", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HL7 parser." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ical.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ical.json index c590ea3710e1c..3b1d2ddec2e83 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ical.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ical.json @@ -15,6 +15,12 @@ "modelName": "ical", "modelJavaType": "org.apache.camel.model.dataformat.IcalDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "net.fortuna.ical4j.model.Calendar", "description": "An ical4j Calendar, such as unmarshal gives. Text is not parsed: unmarshal the iCalendar text first" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The iCalendar text in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text", "description": "An iCalendar (.ics) document, which ical4j reads as UTF-8" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "net.fortuna.ical4j.model.Calendar", "description": "An ical4j Calendar of the document" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "validating": { "index": 1, "kind": "attribute", "displayName": "Validating", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to validate the iCal document." } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/iso8583.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/iso8583.json index 95f93cb2a74b7..e6496d14e91cf 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/iso8583.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/iso8583.json @@ -15,6 +15,12 @@ "modelName": "iso8583", "modelJavaType": "org.apache.camel.model.dataformat.Iso8583DataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "com.solab.iso8583.IsoMessage", "description": "A j8583 IsoMessage, such as unmarshal gives. A Map is not converted" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The ISO-8583 message in the stream cache, or a byte array when stream caching is off: ASCII or binary, as the j8583 configuration says" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "An ISO-8583 message of the ISO-Type in the CamelIso8583IsoType header, or else the isoType option: unmarshal fails without either" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "com.solab.iso8583.IsoMessage", "description": "A j8583 IsoMessage: getAt(n) gives field n" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "configFile": { "index": 1, "kind": "attribute", "displayName": "Config File", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "j8583-config.xml", "description": "The j8583 configuration file to load from classpath" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jaxb.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jaxb.json index 202d64da3fe60..f63c43ae3cbf7 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jaxb.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jaxb.json @@ -15,6 +15,12 @@ "modelName": "jaxb", "modelJavaType": "org.apache.camel.model.dataformat.JaxbDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "dependsOn": [ "partNamespace" ], "byOption": [ { "option": "mustBeJAXBElement", "value": "true", "carriers": [ "pojo" ] } ], "description": "A JAXB object: a class with @XmlRootElement, a JAXBElement, or a class the ObjectFactory makes an element of. Text, bytes, a stream or a file is written as it is, as XML already, unless mustBeJAXBElement is true" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "The XML: text, bytes, a stream, a file, a DOM Document, a DOMSource or a StreamSource" }, + "unmarshalOut": { "carriers": [ "pojo" ], "description": "The object of the root element, of a JAXB class of contextPath, or of partClass when set; a JAXBElement, where JAXB gives one, when ignoreJAXBElement is false" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "contextPath": { "index": 1, "kind": "attribute", "displayName": "Context Path", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Package name where your JAXB classes are located." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jsonApi.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jsonApi.json index ff661f35e9415..654f1f927daff 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jsonApi.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jsonApi.json @@ -15,6 +15,12 @@ "modelName": "jsonApi", "modelJavaType": "org.apache.camel.model.dataformat.JsonApiDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "description": "One resource object of a class dataFormatTypes names, annotated with @Type and @Id of JSONAPI-Converter. A Map or a List fails" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON:API document in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "pojo", "null" ], "description": "The primary data as an object of the class mainFormatType names, or no body when the data is null. A document whose data is an array fails" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "dataFormatTypes": { "index": 1, "kind": "attribute", "displayName": "Data Format Types", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The classes to take into account for the marshalling. Multiple classes can be separated by comma." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jsonb.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jsonb.json index d89137d9303a8..d90876750735f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jsonb.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jsonb.json @@ -15,6 +15,12 @@ "modelName": "json", "modelJavaType": "org.apache.camel.model.dataformat.JsonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as JSON. Bytes, a stream, a file from a file consumer, or a String with a JSON object or array is written as it is; any other String becomes a JSON string" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "allowUnmarshallType" ], "description": "A Map (HashMap with Yasson) for a JSON object, a List (ArrayList) for an array, with the numbers as BigDecimal; an object of the class unmarshalType names" } + }, "properties": { "objectMapper": { "index": 0, "kind": "attribute", "displayName": "Jsonb instance", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing Jsonb instance with the given id." }, "prettyPrint": { "index": 1, "kind": "attribute", "displayName": "Pretty Print", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "To enable pretty printing output nicely formatted. Is by default false." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ocsf.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ocsf.json index 781965395f562..7153701d2234c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ocsf.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ocsf.json @@ -15,6 +15,12 @@ "modelName": "ocsf", "modelJavaType": "org.apache.camel.model.dataformat.OcsfDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list", "pojo" ], "description": "An OCSF event such as a DetectionFinding, a Map or a List to write as JSON. A String is written as one JSON string and bytes as Base64, not as they are" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.apache.camel.dataformat.ocsf.model.OcsfEvent", "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "The base OcsfEvent; an object of the class unmarshalType names, such as DetectionFinding" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "objectMapper": { "index": 1, "kind": "attribute", "displayName": "Object Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing ObjectMapper with the given id when using Jackson." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/rss.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/rss.json index 04e3693f48337..aed9ccedeffe4 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/rss.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/rss.json @@ -15,6 +15,12 @@ "modelName": "rss", "modelJavaType": "org.apache.camel.model.dataformat.RssDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "pojo" ], "description": "A ROME SyndFeed, such as the rss consumer gives, or the XML text of an RSS or Atom feed, which is parsed first" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The RSS or Atom XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml", "description": "An RSS or Atom feed" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "com.rometools.rome.feed.synd.SyndFeed", "description": "A ROME SyndFeed of the feed" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" } } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/soap.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/soap.json index 27dc19f35f7d8..f723d8733fbe5 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/soap.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/soap.json @@ -15,6 +15,12 @@ "modelName": "soap", "modelJavaType": "org.apache.camel.model.dataformat.SoapDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "dependsOn": [ "elementNameStrategy" ], "description": "A JAXB object whose class has @XmlType with a name, written as the one element of the SOAP body; text fails. When the exchange has a caught exception (onException, doCatch), a SOAP fault of it is written instead" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The SOAP envelope in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "A SOAP envelope of the version: text, bytes, a stream, a file, a DOM Document, a DOMSource or a StreamSource" }, + "unmarshalOut": { "carriers": [ "pojo", "null" ], "description": "The JAXB object of the first element of the SOAP body, with the SOAP headers in the org.apache.camel.dataformat.soap.UNMARSHALLED_HEADER_LIST header. No body when the SOAP body is empty or a fault, which becomes the exception of the exchange" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "contextPath": { "index": 1, "kind": "attribute", "displayName": "Context Path", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Package name where your JAXB classes are located." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/swiftMt.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/swiftMt.json index b301798cfcc3d..6cae4036a20df 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/swiftMt.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/swiftMt.json @@ -15,6 +15,12 @@ "modelName": "swiftMt", "modelJavaType": "org.apache.camel.model.dataformat.SwiftMtDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "com.prowidesoftware.swift.model.mt.AbstractMT", "byOption": [ { "option": "writeInJson", "value": "true", "carriers": [ "pojo" ], "javaType": "com.prowidesoftware.JsonSerializable" } ], "description": "A Prowide MT message, such as an MT103, as unmarshal gives. The body is not converted: MT text fails" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The MT message in FIN format, or JSON with writeInJson, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "An MT message in FIN format" }, + "unmarshalOut": { "carriers": [ "pojo", "null" ], "javaType": "com.prowidesoftware.swift.model.mt.AbstractMT", "description": "The Prowide class of the message type, such as MT103; null when the type is not known" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "writeInJson": { "index": 1, "kind": "attribute", "displayName": "Write In Json", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to marshal messages in JSON format." } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/swiftMx.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/swiftMx.json index 7a4095f2c07e4..13b5e1b80be61 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/swiftMx.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/swiftMx.json @@ -15,6 +15,12 @@ "modelName": "swiftMx", "modelJavaType": "org.apache.camel.model.dataformat.SwiftMxDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "com.prowidesoftware.swift.model.mx.AbstractMX", "byOption": [ { "option": "writeInJson", "value": "true", "carriers": [ "pojo" ], "javaType": "com.prowidesoftware.JsonSerializable" } ], "description": "A Prowide MX message, such as an MxPacs00800108, as unmarshal gives. The body is not converted: MX XML text fails" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The MX XML, or JSON with writeInJson, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml", "description": "An MX message, read as UTF-8" }, + "unmarshalOut": { "carriers": [ "pojo", "null" ], "javaType": "com.prowidesoftware.swift.model.mx.AbstractMX", "description": "The Prowide class of the message by its namespace (or readMessageId), such as MxPacs00800108; null when the type is not detected" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "writeInJson": { "index": 1, "kind": "attribute", "displayName": "Write In Json", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to marshal messages in JSON format." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/syslog.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/syslog.json index 8d459f60a63ce..895c8414874fb 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/syslog.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/syslog.json @@ -15,6 +15,12 @@ "modelName": "syslog", "modelJavaType": "org.apache.camel.model.dataformat.SyslogDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "pojo" ], "description": "A SyslogMessage, or the text of a syslog message, which is parsed first. A missing facility, severity, hostname or timestamp gets a default" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The syslog message in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text", "description": "An RFC 3164 or RFC 5424 message, decoded with the charset of the exchange" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.syslog.SyslogMessage", "description": "A SyslogMessage, an Rfc5424SyslogMessage for an RFC 5424 message. The facility, severity, hostname and timestamp are headers as well" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" } } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/toon.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/toon.json index 5d2b6d93b885e..1e4df693490da 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/toon.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/toon.json @@ -15,6 +15,12 @@ "modelName": "toon", "modelJavaType": "org.apache.camel.model.dataformat.ToonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "value", "map", "list", "pojo" ], "description": "A Map, a List, a POJO or a value to write as TOON. A String must be JSON text; bytes, a stream or a file are not read as text" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The TOON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "description": "A Map (LinkedHashMap) for an object, a List for an array; a document that is a single value gives that value" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "indent": { "index": 1, "kind": "attribute", "displayName": "Indent", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 2, "description": "Number of spaces per indentation level." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ubl.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ubl.json index 2d96ae90a3f20..d6718b2b065f9 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ubl.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/ubl.json @@ -15,6 +15,12 @@ "modelName": "ubl", "modelJavaType": "org.apache.camel.model.dataformat.UblDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "description": "A UBL 2.1 document of ph-ubl, such as an InvoiceType or a CreditNoteType: its class name gives the document type. Text fails" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The UBL XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml", "description": "A UBL 2.1 document, whose root element gives the document type" }, + "unmarshalOut": { "carriers": [ "pojo" ], "description": "The ph-ubl object of the document type, such as an InvoiceType for an Invoice" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "prettyPrint": { "index": 1, "kind": "attribute", "displayName": "Pretty Print", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable pretty printing (formatted) output of the XML" } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityCsv.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityCsv.json index 6660216a3fc08..63f145ca731c2 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityCsv.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityCsv.json @@ -15,6 +15,12 @@ "modelName": "univocityCsv", "modelJavaType": "org.apache.camel.model.dataformat.UniVocityCsvDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list" ], "description": "One row as a Map, or the rows as a List (or an Iterator) of Maps. Rows that are Lists, as unmarshal gives without asMap, are not accepted" }, + "marshalOut": { "carriers": [ "stream" ], "format": "csv", "description": "The CSV in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "csv" }, + "unmarshalOut": { "carriers": [ "list" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "iterator" ] } ], "description": "A List of the rows, each a List of its values (the first line too, unless headerExtractionEnabled); with asMap, a Map of the header names and the values" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "delimiter": { "index": 1, "kind": "attribute", "displayName": "Delimiter", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": ",", "description": "The delimiter of values." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityFixed.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityFixed.json index c1f7ace71e99f..fd9c4a470c4a7 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityFixed.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityFixed.json @@ -15,6 +15,12 @@ "modelName": "univocityFixed", "modelJavaType": "org.apache.camel.model.dataformat.UniVocityFixedDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list" ], "description": "One row as a Map, or the rows as a List (or an Iterator) of Maps. Rows that are Lists, as unmarshal gives without asMap, are not accepted" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The fixed-width records in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "list" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "iterator" ] } ], "description": "A List of the rows, each a List of its values (the first line too, unless headerExtractionEnabled); with asMap, a Map of the header names and the values" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "padding": { "index": 1, "kind": "attribute", "displayName": "Padding", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The padding character. The default value is a space." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityTsv.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityTsv.json index 429d262794370..4d19cfc96af77 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityTsv.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/univocityTsv.json @@ -15,6 +15,12 @@ "modelName": "univocityTsv", "modelJavaType": "org.apache.camel.model.dataformat.UniVocityTsvDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list" ], "description": "One row as a Map, or the rows as a List (or an Iterator) of Maps. Rows that are Lists, as unmarshal gives without asMap, are not accepted" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The TSV in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "list" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "iterator" ] } ], "description": "A List of the rows, each a List of its values (the first line too, unless headerExtractionEnabled); with asMap, a Map of the header names and the values" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "escapeChar": { "index": 1, "kind": "attribute", "displayName": "Escape Char", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "\\", "description": "The escape character." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/asn1-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/asn1-dataformat.adoc index da053284c8fbc..c71b2d0cbdf3f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/asn1-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/asn1-dataformat.adoc @@ -10,7 +10,7 @@ *Since Camel {since}* The https://www.itu.int/en/ITU-T/asn1/Pages/introduction.aspx[ASN.1 Data Format] is a Camel Framework's data format implementation based on Bouncy Castle's bcprov-jdk18on library and jASN.1's java compiler for the formal notation used for describing data transmitted by telecommunications protocols, regardless of language implementation and physical representation of these data, whatever the application, whether complex or very simple. -Messages can be unmarshalled (conversion to simple Java POJO(s)) to plain Java objects. +Messages can be unmarshalled to byte arrays, or, with `usingIterator` and `unmarshalType`, to plain Java objects (POJOs) of the classes the jASN.1 compiler generated. With the help of Camel's routing engine and data transformations, you can then play with POJO(s) and apply customized formatting and call other Camel Components to convert and send messages to upstream systems. == ASN.1 Data Format Options @@ -23,7 +23,7 @@ include::partial$dataformat-options.adoc[] There are 3 different ways to unmarshal ASN.1 structured messages. (Usually binary files) -In this first example, we unmarshal BER file payload to OutputStream and send it to mock endpoint. +In this first example, we unmarshal BER file payload to a byte array, with the records encoded again, and send it to mock endpoint. [tabs] ==== @@ -50,7 +50,7 @@ YAML:: ==== In the second example, we unmarshal BER file payload to a byte array using Split EIP. -The reason for applying Split EIP is that usually each BER file or (ASN.1 structured file) contains multiple records to process and Split EIP helps us to get each record in a file as byte arrays which is actually ASN1Primitive's instance (by the use of Bouncy Castle's ASN.1 support in bcprov-jdk18on library) +The reason for applying Split EIP is that usually each BER file or (ASN.1 structured file) contains multiple records to process and Split EIP helps us to get each record in a file as a message whose body is the bytes of one record, encoded as an ASN1Primitive (by the use of Bouncy Castle's ASN.1 support in bcprov-jdk18on library) Byte arrays then may be converted to ASN1Primitive by the help of public static method in (ASN1Primitive.fromByteArray) In such example, note that you need to set `usingIterator=true` diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/base64-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/base64-dataformat.adoc index ed64bf4741567..c32f93ec74c36 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/base64-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/base64-dataformat.adoc @@ -123,8 +123,8 @@ YAML:: == Unmarshal -In this example, we unmarshal the payload from the JMS queue to a byte[] -object, before its processed by the `newOrder` processor. +In this example, we unmarshal the payload from the JMS queue to a stream of +the decoded bytes, before its processed by the `newOrder` processor. [tabs] ==== diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/bindy-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/bindy-dataformat.adoc index 83c6f9946c0bc..39afbd71a4427 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/bindy-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/bindy-dataformat.adoc @@ -1896,51 +1896,25 @@ from("file://inbox") .to("direct:handleOrders"); ---- -The Camel route will pick up files in the inbox directory, unmarshall -CSV records into a collection of model objects and send the collection + - to the route referenced by `handleOrders`. +The Camel route will pick up files in the inbox directory, unmarshal the +CSV records into model objects and send them to the route referenced +by `handleOrders`. -The collection returned is a *List of Map* objects. Each Map within the -list contains the model objects marshalled out of each line of -the CSV. The reason behind this is that _each line can correspond to -more than one object_. This can be confusing when you expect one -object to be returned per line. +The body after unmarshal is a *List* of the objects of the `classType` class, +one for each record. When there is only one record, the body is that object, +unless `unwrapSingleInstance` is `false`. The objects of the classes that +`@Link` links are set in the fields of the object of each record. With +`allowEmptyStream=true`, a file without records gives an empty List. -Each object can be retrieved using its class name. +To process one Order at a time in a route, use a Splitter, which also +takes the single Order of a file with one record: ._Java-only: Java annotation model class_ [source,java] ---- -List> unmarshaledModels = (List>) exchange.getIn().getBody(); - -int modelCount = 0; -for (Map model : unmarshaledModels) { - for (String className : model.keySet()) { - Object obj = model.get(className); - LOG.info("Count: {}, {}", modelCount, obj.toString()); - } - modelCount++; -} - -LOG.info("Total CSV records received by the csv bean: {}", modelCount); ----- - -Assuming that you want to extract a single Order object from this map -for processing in a route, you could use a combination of a -Splitter and a Processor as per -the following: - -._Java-only: inline Processor implementation_ -[source,java] ----- from("file://inbox") .unmarshal(bindy) .split(body()) - .process(exchange -> { - Message in = exchange.getIn(); - Map modelMap = (Map) in.getBody(); - in.setBody(modelMap.get(Order.class.getCanonicalName())); - }) .to("direct:handleSingleOrder") .end(); ---- @@ -2036,8 +2010,8 @@ the queue manager will raise an error. In the YAML DSL, the data format is `bindy`, and its `type` is `Csv`, `Fixed` or `KeyValue`. The `classType` is the model class. -The following route reads CSV files, unmarshals them into a list of `Order` objects, -and splits the list to handle one order at a time: +The following route reads CSV files, unmarshals them into a list of `Order` objects +(or one `Order` for a file with one record), and splits the list to handle one order at a time: [source,yaml] ---- diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dfdl-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dfdl-dataformat.adoc index 83db51bfd03e6..a38c81307072b 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dfdl-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/dfdl-dataformat.adoc @@ -64,7 +64,7 @@ YAML:: ==== === Marshal (XML to fixed format) -Below is an example of using the DFDL Data Format to unmarshal an EDI message into an XML DOM Document: +Below is an example of using the DFDL Data Format to marshal XML (a DOM Document, or XML text) into an EDI message: [tabs] ==== diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/fastjson-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/fastjson-dataformat.adoc index 9e89cce982de0..c121c9c030eed 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/fastjson-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/fastjson-dataformat.adoc @@ -60,11 +60,12 @@ include::partial$dataformat-options.adoc[] == A body that is already JSON -A body that already is the JSON text is written as it is, not serialized as a Java object: a file, an `InputStream`, -a `byte[]`, and a `String` whose text is a JSON object or array (it starts with `{` and ends with `}`, or `[` and -`]`). So `marshal: json` after reading a JSON file, or after building the JSON with a template or a Simple -expression, sends that JSON unchanged. Any other `String` is written as a JSON string, and POJOs, maps and lists are -marshalled as usual. All the JSON data formats of Camel do the same. +A body that already is the JSON text is written as it is, not serialized as a Java object: a file from a consumer +such as file or ftp, an `InputStream`, a `byte[]`, and a `String` whose text is a JSON object or array (it starts +with `{` and ends with `}`, or `[` and `]`). So `marshal: json` after reading a JSON file, or after building the +JSON with a template or a Simple expression, sends that JSON unchanged. Any other `String` is written as a JSON +string, and POJOs, maps and lists are marshalled as usual. The Jackson, Gson, Jsonb and Fastjson JSON data formats +do the same. == Dependencies diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/grok-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/grok-dataformat.adoc index 370e02d7966fd..cdf2d3441c018 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/grok-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/grok-dataformat.adoc @@ -10,7 +10,9 @@ *Since Camel {since}* This component provides dataformat for processing inputs with grok patterns. -Grok patterns are used to process unstructured data into structured objects - `List>`. +Grok patterns are used to process unstructured data into structured objects: a `Map` of the captures +for one match, a `List` of such Maps for several matches, or no body when nothing matches. With a split, as in the +examples below, an input with one match gives a `Map` whose entries are split one by one. This component is based on the https://github.com/thekrakken/java-grok[Java Grok library] @@ -76,7 +78,7 @@ Java:: [source,java] ---- from("file://apacheLogs") - .unmarshal().grok("%{COMBINEDAPACHELOG") + .unmarshal().grok("%{COMBINEDAPACHELOG}") .split(body()).filter(simple("${body[response]} starts with '4'")) .to("log:4xx"); ---- @@ -87,7 +89,7 @@ XML:: ---- - + ${body} @@ -108,7 +110,7 @@ YAML:: steps: - unmarshal: grok: - pattern: "%{COMBINEDAPACHELOG" + pattern: "%{COMBINEDAPACHELOG}" - split: simple: "${body}" steps: diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/gson-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/gson-dataformat.adoc index 07dfe44bf0dea..511d0eef9b034 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/gson-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/gson-dataformat.adoc @@ -60,11 +60,12 @@ include::partial$dataformat-options.adoc[] == A body that is already JSON -A body that already is the JSON text is written as it is, not serialized as a Java object: a file, an `InputStream`, -a `byte[]`, and a `String` whose text is a JSON object or array (it starts with `{` and ends with `}`, or `[` and -`]`). So `marshal: json` after reading a JSON file, or after building the JSON with a template or a Simple -expression, sends that JSON unchanged. Any other `String` is written as a JSON string, and POJOs, maps and lists are -marshalled as usual. All the JSON data formats of Camel do the same. +A body that already is the JSON text is written as it is, not serialized as a Java object: a file from a consumer +such as file or ftp, an `InputStream`, a `byte[]`, and a `String` whose text is a JSON object or array (it starts +with `{` and ends with `}`, or `[` and `]`). So `marshal: json` after reading a JSON file, or after building the +JSON with a template or a Simple expression, sends that JSON unchanged. Any other `String` is written as a JSON +string, and POJOs, maps and lists are marshalled as usual. The Jackson, Gson, Jsonb and Fastjson JSON data formats +do the same. == Dependencies diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jackson2-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jackson2-dataformat.adoc index 96e49f1ee2221..8abae4e00092a 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jackson2-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jackson2-dataformat.adoc @@ -68,11 +68,12 @@ in the Camel dataformat. === A body that is already JSON -A body that already is the JSON text is written as it is, not serialized as a Java object: a file, an `InputStream`, -a `byte[]`, and a `String` whose text is a JSON object or array (it starts with `{` and ends with `}`, or `[` and -`]`). So `marshal: json` after reading a JSON file, or after building the JSON with a template or a Simple -expression, sends that JSON unchanged. Any other `String` is written as a JSON string, and POJOs, maps and lists are -marshalled as usual. All the JSON data formats of Camel do the same. +A body that already is the JSON text is written as it is, not serialized as a Java object: a file from a consumer +such as file or ftp, an `InputStream`, a `byte[]`, and a `String` whose text is a JSON object or array (it starts +with `{` and ends with `}`, or `[` and `]`). So `marshal: json` after reading a JSON file, or after building the +JSON with a template or a Simple expression, sends that JSON unchanged. Any other `String` is written as a JSON +string, and POJOs, maps and lists are marshalled as usual. The Jackson, Gson, Jsonb and Fastjson JSON data formats +do the same. === Using custom ObjectMapper diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jackson3-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jackson3-dataformat.adoc index 149c8ff604991..a368586b823ac 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jackson3-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jackson3-dataformat.adoc @@ -96,11 +96,12 @@ in the Camel dataformat. === A body that is already JSON -A body that already is the JSON text is written as it is, not serialized as a Java object: a file, an `InputStream`, -a `byte[]`, and a `String` whose text is a JSON object or array (it starts with `{` and ends with `}`, or `[` and -`]`). So `marshal: json` after reading a JSON file, or after building the JSON with a template or a Simple -expression, sends that JSON unchanged. Any other `String` is written as a JSON string, and POJOs, maps and lists are -marshalled as usual. All the JSON data formats of Camel do the same. +A body that already is the JSON text is written as it is, not serialized as a Java object: a file from a consumer +such as file or ftp, an `InputStream`, a `byte[]`, and a `String` whose text is a JSON object or array (it starts +with `{` and ends with `}`, or `[` and `]`). So `marshal: json` after reading a JSON file, or after building the +JSON with a template or a Simple expression, sends that JSON unchanged. Any other `String` is written as a JSON +string, and POJOs, maps and lists are marshalled as usual. The Jackson, Gson, Jsonb and Fastjson JSON data formats +do the same. === Using custom ObjectMapper diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jaxb-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jaxb-dataformat.adoc index a12c7a13d1615..b32e36b186d9e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jaxb-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jaxb-dataformat.adoc @@ -344,14 +344,15 @@ You can do the same using the XML DSL: === Marshal data that is already XML -The JAXB marshaller requires that the message body is JAXB compatible, +The JAXB marshaller marshals a message body that is JAXB compatible, e.g., it is a `JAXBElement`, a java instance that has JAXB annotations, or extends `JAXBElement`. There can be situations where the message body is already in XML, e.g., from a `String` type. -`JaxbDataFormat` has an option named `mustBeJAXBElement` which you can set to `false` to relax this check and -have the JAXB marshaller only attempt marshalling on `JAXBElement` (`javax.xml.bind.JAXBIntrospector#isElement` returns `true`). -In those situations, the marshaller will fall back to marshal the message body as-is. +The option `mustBeJAXBElement` is `false` by default: a message body that is not JAXB compatible +(`jakarta.xml.bind.JAXBIntrospector#isElement` returns `false`) is then written as-is, as XML already. +Text, bytes, a stream or a file can be written this way; a `Map` or a `List` fails. +Set `mustBeJAXBElement` to `true` to fail with an `InvalidPayloadException` instead. == Dependencies diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonb-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonb-dataformat.adoc index 3d0a251f888f8..a0818a001afc4 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonb-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jsonb-dataformat.adoc @@ -59,11 +59,12 @@ include::partial$dataformat-options.adoc[] == A body that is already JSON -A body that already is the JSON text is written as it is, not serialized as a Java object: a file, an `InputStream`, -a `byte[]`, and a `String` whose text is a JSON object or array (it starts with `{` and ends with `}`, or `[` and -`]`). So `marshal: json` after reading a JSON file, or after building the JSON with a template or a Simple -expression, sends that JSON unchanged. Any other `String` is written as a JSON string, and POJOs, maps and lists are -marshalled as usual. All the JSON data formats of Camel do the same. +A body that already is the JSON text is written as it is, not serialized as a Java object: a file from a consumer +such as file or ftp, an `InputStream`, a `byte[]`, and a `String` whose text is a JSON object or array (it starts +with `{` and ends with `}`, or `[` and `]`). So `marshal: json` after reading a JSON file, or after building the +JSON with a template or a Simple expression, sends that JSON unchanged. Any other `String` is written as a JSON +string, and POJOs, maps and lists are marshalled as usual. The Jackson, Gson, Jsonb and Fastjson JSON data formats +do the same. == Dependencies diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/rss-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/rss-dataformat.adoc index 478303b5f755e..7efb718134cd1 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/rss-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/rss-dataformat.adoc @@ -12,8 +12,8 @@ The RSS component ships with an RSS dataformat that can be used to convert between String (as XML) and ROME RSS model objects. -* marshal = from ROME `SyndFeed` to XML `String` -* unmarshal = from XML `String` to ROME `SyndFeed` +* marshal = from ROME `SyndFeed` (or the XML text of a feed) to XML +* unmarshal = from XML (text, bytes, a stream or a file) to ROME `SyndFeed` A route using this would look something like this: @@ -42,8 +42,8 @@ include::partial$dataformat-options.adoc[] The RSS component ships with an RSS dataformat that can be used to convert between String (as XML) and ROME RSS model objects. -* marshal = from ROME `SyndFeed` to XML `String` -* unmarshal = from XML `String` to ROME `SyndFeed` +* marshal = from ROME `SyndFeed` (or the XML text of a feed) to XML +* unmarshal = from XML (text, bytes, a stream or a file) to ROME `SyndFeed` A route using the RSS dataformat will look like this: diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/swiftMt-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/swiftMt-dataformat.adoc index c64420eeb40ed..5aac6e7416d50 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/swiftMt-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/swiftMt-dataformat.adoc @@ -118,6 +118,8 @@ YAML:: == Marshal In this example, we marshal the messages read from a JMS queue in SWIFT format before storing the result into a file. +The body must be a Prowide MT object, such as an `MT103`, as unmarshal gives: it is not converted, so an MT +message as text fails. [tabs] ==== diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/swiftMx-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/swiftMx-dataformat.adoc index 74c2a6f52a0f3..fa97d128ddbfe 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/swiftMx-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/swiftMx-dataformat.adoc @@ -118,6 +118,8 @@ YAML:: == Marshal In this example, we marshal the messages read from a JMS queue in SWIFT format before storing the result into a file. +The body must be a Prowide MX object, such as an `MxPacs00800108`, as unmarshal gives: it is not converted, so an MX +message as text fails. [tabs] ==== diff --git a/components/camel-asn1/src/generated/resources/META-INF/org/apache/camel/dataformat/asn1/asn1.json b/components/camel-asn1/src/generated/resources/META-INF/org/apache/camel/dataformat/asn1/asn1.json index 03311982f6bce..fc2e98ff7cb26 100644 --- a/components/camel-asn1/src/generated/resources/META-INF/org/apache/camel/dataformat/asn1/asn1.json +++ b/components/camel-asn1/src/generated/resources/META-INF/org/apache/camel/dataformat/asn1/asn1.json @@ -15,6 +15,12 @@ "modelName": "asn1", "modelJavaType": "org.apache.camel.model.dataformat.ASN1DataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "bytes", "stream", "file" ], "dependsOn": [ "unmarshalType" ], "byOption": [ { "option": "usingIterator", "value": "true", "carriers": [ "bytes", "pojo" ] } ], "description": "BER-encoded data, written as it is. With usingIterator, a byte array or a Bouncy Castle ASN1Primitive, and with unmarshalType as well an object of a class the asn1bean compiler generated" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The BER-encoded data in the stream cache, or a byte array when stream caching is off. With usingIterator, and no unmarshalType, nothing is written for a body that is neither a byte array nor an ASN1Primitive" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "BER-encoded data: one record, or several one after the other" }, + "unmarshalOut": { "carriers": [ "bytes" ], "byOption": [ { "option": "usingIterator", "value": "true", "carriers": [ "iterator" ] } ], "description": "The records, encoded again, in one byte array. With usingIterator, an Iterator for the split EIP: of messages with the bytes of one record each, or of objects of the class unmarshalType names" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "unmarshalType": { "index": 1, "kind": "attribute", "displayName": "Unmarshal Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Class to use when unmarshalling." }, diff --git a/components/camel-asn1/src/main/docs/asn1-dataformat.adoc b/components/camel-asn1/src/main/docs/asn1-dataformat.adoc index da053284c8fbc..c71b2d0cbdf3f 100644 --- a/components/camel-asn1/src/main/docs/asn1-dataformat.adoc +++ b/components/camel-asn1/src/main/docs/asn1-dataformat.adoc @@ -10,7 +10,7 @@ *Since Camel {since}* The https://www.itu.int/en/ITU-T/asn1/Pages/introduction.aspx[ASN.1 Data Format] is a Camel Framework's data format implementation based on Bouncy Castle's bcprov-jdk18on library and jASN.1's java compiler for the formal notation used for describing data transmitted by telecommunications protocols, regardless of language implementation and physical representation of these data, whatever the application, whether complex or very simple. -Messages can be unmarshalled (conversion to simple Java POJO(s)) to plain Java objects. +Messages can be unmarshalled to byte arrays, or, with `usingIterator` and `unmarshalType`, to plain Java objects (POJOs) of the classes the jASN.1 compiler generated. With the help of Camel's routing engine and data transformations, you can then play with POJO(s) and apply customized formatting and call other Camel Components to convert and send messages to upstream systems. == ASN.1 Data Format Options @@ -23,7 +23,7 @@ include::partial$dataformat-options.adoc[] There are 3 different ways to unmarshal ASN.1 structured messages. (Usually binary files) -In this first example, we unmarshal BER file payload to OutputStream and send it to mock endpoint. +In this first example, we unmarshal BER file payload to a byte array, with the records encoded again, and send it to mock endpoint. [tabs] ==== @@ -50,7 +50,7 @@ YAML:: ==== In the second example, we unmarshal BER file payload to a byte array using Split EIP. -The reason for applying Split EIP is that usually each BER file or (ASN.1 structured file) contains multiple records to process and Split EIP helps us to get each record in a file as byte arrays which is actually ASN1Primitive's instance (by the use of Bouncy Castle's ASN.1 support in bcprov-jdk18on library) +The reason for applying Split EIP is that usually each BER file or (ASN.1 structured file) contains multiple records to process and Split EIP helps us to get each record in a file as a message whose body is the bytes of one record, encoded as an ASN1Primitive (by the use of Bouncy Castle's ASN.1 support in bcprov-jdk18on library) Byte arrays then may be converted to ASN1Primitive by the help of public static method in (ASN1Primitive.fromByteArray) In such example, note that you need to set `usingIterator=true` diff --git a/components/camel-asn1/src/main/java/org/apache/camel/dataformat/asn1/ASN1DataFormat.java b/components/camel-asn1/src/main/java/org/apache/camel/dataformat/asn1/ASN1DataFormat.java index dd8f4614372a5..54ed472b5d035 100644 --- a/components/camel-asn1/src/main/java/org/apache/camel/dataformat/asn1/ASN1DataFormat.java +++ b/components/camel-asn1/src/main/java/org/apache/camel/dataformat/asn1/ASN1DataFormat.java @@ -24,6 +24,9 @@ import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -34,6 +37,24 @@ import org.bouncycastle.asn1.ASN1Primitive; @Dataformat("asn1") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, dependsOn = "unmarshalType", + byOption = @BodyType.When(option = "usingIterator", value = "true", + carriers = { Carrier.BYTES, Carrier.POJO }), + description = "BER-encoded data, written as it is. With usingIterator, a byte array or a" + + " Bouncy Castle ASN1Primitive, and with unmarshalType as well an object of a" + + " class the asn1bean compiler generated"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The BER-encoded data in the stream cache, or a byte array when stream caching" + + " is off. With usingIterator, and no unmarshalType, nothing is written for a" + + " body that is neither a byte array nor an ASN1Primitive"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "BER-encoded data: one record, or several one after the other"), + unmarshalOut = @BodyType(value = Carrier.BYTES, + byOption = @BodyType.When(option = "usingIterator", value = "true", + carriers = Carrier.ITERATOR), + description = "The records, encoded again, in one byte array. With usingIterator, an" + + " Iterator for the split EIP: of messages with the bytes of one record" + + " each, or of objects of the class unmarshalType names")) public class ASN1DataFormat extends ServiceSupport implements DataFormat, DataFormatName { private boolean usingIterator; diff --git a/components/camel-base64/src/generated/resources/META-INF/org/apache/camel/dataformat/base64/base64.json b/components/camel-base64/src/generated/resources/META-INF/org/apache/camel/dataformat/base64/base64.json index ad3055b9f3acc..e379fd094013b 100644 --- a/components/camel-base64/src/generated/resources/META-INF/org/apache/camel/dataformat/base64/base64.json +++ b/components/camel-base64/src/generated/resources/META-INF/org/apache/camel/dataformat/base64/base64.json @@ -15,6 +15,12 @@ "modelName": "base64", "modelJavaType": "org.apache.camel.model.dataformat.Base64DataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The bytes to encode: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The Base64 text in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decoded bytes, as a stream" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "lineLength": { "index": 1, "kind": "attribute", "displayName": "Line Length", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 76, "description": "To specific a maximum line length for the encoded data. By default 76 is used." }, diff --git a/components/camel-base64/src/main/docs/base64-dataformat.adoc b/components/camel-base64/src/main/docs/base64-dataformat.adoc index ed64bf4741567..c32f93ec74c36 100644 --- a/components/camel-base64/src/main/docs/base64-dataformat.adoc +++ b/components/camel-base64/src/main/docs/base64-dataformat.adoc @@ -123,8 +123,8 @@ YAML:: == Unmarshal -In this example, we unmarshal the payload from the JMS queue to a byte[] -object, before its processed by the `newOrder` processor. +In this example, we unmarshal the payload from the JMS queue to a stream of +the decoded bytes, before its processed by the `newOrder` processor. [tabs] ==== diff --git a/components/camel-base64/src/main/java/org/apache/camel/dataformat/base64/Base64DataFormat.java b/components/camel-base64/src/main/java/org/apache/camel/dataformat/base64/Base64DataFormat.java index 74d90b89c95ef..d5cedec412cd1 100644 --- a/components/camel-base64/src/main/java/org/apache/camel/dataformat/base64/Base64DataFormat.java +++ b/components/camel-base64/src/main/java/org/apache/camel/dataformat/base64/Base64DataFormat.java @@ -20,6 +20,9 @@ import java.io.OutputStream; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -31,6 +34,14 @@ import org.apache.commons.codec.binary.Base64OutputStream; @Dataformat("base64") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The bytes to encode: text in the charset of the exchange, bytes, a stream or a" + + " file"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "text", + description = "The Base64 text in the stream cache, or a byte array when stream caching is" + + " off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "text"), + unmarshalOut = @BodyType(value = Carrier.STREAM, description = "The decoded bytes, as a stream")) public class Base64DataFormat extends ServiceSupport implements DataFormat, DataFormatName { private int lineLength = Base64.MIME_CHUNK_SIZE; diff --git a/components/camel-beanio/src/generated/resources/META-INF/org/apache/camel/dataformat/beanio/beanio.json b/components/camel-beanio/src/generated/resources/META-INF/org/apache/camel/dataformat/beanio/beanio.json index d6337118ed60d..1fe7c996b2ab8 100644 --- a/components/camel-beanio/src/generated/resources/META-INF/org/apache/camel/dataformat/beanio/beanio.json +++ b/components/camel-beanio/src/generated/resources/META-INF/org/apache/camel/dataformat/beanio/beanio.json @@ -15,6 +15,12 @@ "modelName": "beanio", "modelJavaType": "org.apache.camel.model.dataformat.BeanioDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo", "list" ], "byOption": [ { "option": "unmarshalSingleObject", "value": "true", "carriers": [ "pojo", "map", "list" ] } ], "description": "A bean of a record of the mapping file, or a List (or an Iterator) of them; a Map is one record only with unmarshalSingleObject" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The records in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ] }, + "unmarshalOut": { "carriers": [ "list" ], "byOption": [ { "option": "unmarshalSingleObject", "value": "true", "carriers": [ "pojo", "map" ] } ], "description": "A List with the bean of each record, of the class the mapping file names (a Map for a map record); with unmarshalSingleObject, the one bean" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "mapping": { "index": 1, "kind": "attribute", "displayName": "Mapping", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The BeanIO mapping file. Is by default loaded from the classpath. You can prefix with file:, http:, or classpath: to denote from where to load the mapping file." }, diff --git a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIODataFormat.java b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIODataFormat.java index abb3aed9195a9..17500dfbb6da8 100644 --- a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIODataFormat.java +++ b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIODataFormat.java @@ -32,6 +32,9 @@ import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; import org.apache.camel.NoTypeConversionAvailableException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -51,6 +54,19 @@ * A data format ( {@link DataFormat}) for beanio data. */ @Dataformat("beanio") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.POJO, Carrier.LIST }, + byOption = @BodyType.When(option = "unmarshalSingleObject", value = "true", + carriers = { Carrier.POJO, Carrier.MAP, Carrier.LIST }), + description = "A bean of a record of the mapping file, or a List (or an Iterator) of them; a" + + " Map is one record only with unmarshalSingleObject"), + marshalOut = @BodyType(value = Carrier.STREAM, + description = "The records in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType({ Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), + unmarshalOut = @BodyType(value = Carrier.LIST, + byOption = @BodyType.When(option = "unmarshalSingleObject", value = "true", + carriers = { Carrier.POJO, Carrier.MAP }), + description = "A List with the bean of each record, of the class the mapping file names" + + " (a Map for a map record); with unmarshalSingleObject, the one bean")) public class BeanIODataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private transient CamelContext camelContext; diff --git a/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/csv/bindyCsv.json b/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/csv/bindyCsv.json index 647c173c39e7b..23ee0e8a7e218 100644 --- a/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/csv/bindyCsv.json +++ b/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/csv/bindyCsv.json @@ -15,6 +15,12 @@ "modelName": "bindy", "modelJavaType": "org.apache.camel.model.dataformat.BindyDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo", "list" ], "description": "An object of the classType class, or a List (or an Iterator) of them; a Map of the model class names to the objects is one record. Other bodies, such as a Map of field values, are not records" }, + "marshalOut": { "carriers": [ "stream" ], "format": "csv", "description": "The CSV in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "csv" }, + "unmarshalOut": { "carriers": [ "pojo", "list" ], "byOption": [ { "option": "unwrapSingleInstance", "value": "false", "carriers": [ "list" ] } ], "description": "An object of the classType class when there is one record, otherwise a List of them; an empty List for no records with allowEmptyStream" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "type": { "index": 1, "kind": "attribute", "displayName": "Type", "group": "common", "required": true, "type": "enum", "javaType": "org.apache.camel.model.dataformat.BindyType", "enum": [ "Csv", "Fixed", "KeyValue" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Csv", "description": "Whether to use Csv, Fixed, or KeyValue." }, diff --git a/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/fixed/bindyFixed.json b/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/fixed/bindyFixed.json index d5ce6fb3760d3..42d40b2029b0c 100644 --- a/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/fixed/bindyFixed.json +++ b/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/fixed/bindyFixed.json @@ -15,6 +15,12 @@ "modelName": "bindy", "modelJavaType": "org.apache.camel.model.dataformat.BindyDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo", "list" ], "description": "An object of the classType class, or a List (or an Iterator) of them, or a List of Maps of the model class name to the object. The headers CamelBindyFixedLengthHeader and CamelBindyFixedLengthFooter add the header and footer records" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The fixed-length records in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "pojo", "list" ], "byOption": [ { "option": "unwrapSingleInstance", "value": "false", "carriers": [ "list" ] } ], "description": "An object of the classType class when there is one record, otherwise a List of them. The header and footer records go to the headers CamelBindyFixedLengthHeader and CamelBindyFixedLengthFooter" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "type": { "index": 1, "kind": "attribute", "displayName": "Type", "group": "common", "required": true, "type": "enum", "javaType": "org.apache.camel.model.dataformat.BindyType", "enum": [ "Csv", "Fixed", "KeyValue" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Fixed", "description": "Whether to use Csv, Fixed, or KeyValue." }, diff --git a/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/kvp/bindyKvp.json b/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/kvp/bindyKvp.json index 611ef30a2f618..de3efcd7f7e31 100644 --- a/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/kvp/bindyKvp.json +++ b/components/camel-bindy/src/generated/resources/META-INF/org/apache/camel/dataformat/bindy/kvp/bindyKvp.json @@ -15,6 +15,12 @@ "modelName": "bindy", "modelJavaType": "org.apache.camel.model.dataformat.BindyDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo", "list" ], "description": "An object of the classType class, or a List (or an Iterator) of them; a Map of the model class names to the objects is one message" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The key-value pair messages, one per line, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "pojo", "list" ], "byOption": [ { "option": "unwrapSingleInstance", "value": "false", "carriers": [ "list" ] } ], "description": "An object of the classType class when there is one message (one per line), otherwise a List of them" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "type": { "index": 1, "kind": "attribute", "displayName": "Type", "group": "common", "required": true, "type": "enum", "javaType": "org.apache.camel.model.dataformat.BindyType", "enum": [ "Csv", "Fixed", "KeyValue" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "KeyValue", "description": "Whether to use Csv, Fixed, or KeyValue." }, diff --git a/components/camel-bindy/src/main/docs/bindy-dataformat.adoc b/components/camel-bindy/src/main/docs/bindy-dataformat.adoc index 83c6f9946c0bc..39afbd71a4427 100644 --- a/components/camel-bindy/src/main/docs/bindy-dataformat.adoc +++ b/components/camel-bindy/src/main/docs/bindy-dataformat.adoc @@ -1896,51 +1896,25 @@ from("file://inbox") .to("direct:handleOrders"); ---- -The Camel route will pick up files in the inbox directory, unmarshall -CSV records into a collection of model objects and send the collection + - to the route referenced by `handleOrders`. +The Camel route will pick up files in the inbox directory, unmarshal the +CSV records into model objects and send them to the route referenced +by `handleOrders`. -The collection returned is a *List of Map* objects. Each Map within the -list contains the model objects marshalled out of each line of -the CSV. The reason behind this is that _each line can correspond to -more than one object_. This can be confusing when you expect one -object to be returned per line. +The body after unmarshal is a *List* of the objects of the `classType` class, +one for each record. When there is only one record, the body is that object, +unless `unwrapSingleInstance` is `false`. The objects of the classes that +`@Link` links are set in the fields of the object of each record. With +`allowEmptyStream=true`, a file without records gives an empty List. -Each object can be retrieved using its class name. +To process one Order at a time in a route, use a Splitter, which also +takes the single Order of a file with one record: ._Java-only: Java annotation model class_ [source,java] ---- -List> unmarshaledModels = (List>) exchange.getIn().getBody(); - -int modelCount = 0; -for (Map model : unmarshaledModels) { - for (String className : model.keySet()) { - Object obj = model.get(className); - LOG.info("Count: {}, {}", modelCount, obj.toString()); - } - modelCount++; -} - -LOG.info("Total CSV records received by the csv bean: {}", modelCount); ----- - -Assuming that you want to extract a single Order object from this map -for processing in a route, you could use a combination of a -Splitter and a Processor as per -the following: - -._Java-only: inline Processor implementation_ -[source,java] ----- from("file://inbox") .unmarshal(bindy) .split(body()) - .process(exchange -> { - Message in = exchange.getIn(); - Map modelMap = (Map) in.getBody(); - in.setBody(modelMap.get(Order.class.getCanonicalName())); - }) .to("direct:handleSingleOrder") .end(); ---- @@ -2036,8 +2010,8 @@ the queue manager will raise an error. In the YAML DSL, the data format is `bindy`, and its `type` is `Csv`, `Fixed` or `KeyValue`. The `classType` is the model class. -The following route reads CSV files, unmarshals them into a list of `Order` objects, -and splits the list to handle one order at a time: +The following route reads CSV files, unmarshals them into a list of `Order` objects +(or one `Order` for a file with one record), and splits the list to handle one order at a time: [source,yaml] ---- diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/csv/BindyCsvDataFormat.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/csv/BindyCsvDataFormat.java index 1942a866e5738..edb9ceb2c69ca 100644 --- a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/csv/BindyCsvDataFormat.java +++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/csv/BindyCsvDataFormat.java @@ -41,6 +41,9 @@ import org.apache.camel.dataformat.bindy.FormatFactory; import org.apache.camel.dataformat.bindy.WrappedException; import org.apache.camel.dataformat.bindy.util.ConverterUtils; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Dataformat; import org.apache.camel.support.ExchangeHelper; import org.apache.camel.support.ObjectHelper; @@ -52,6 +55,18 @@ * Marshal and unmarshal between POJOs and Comma separated values (CSV) format using Camel Bindy */ @Dataformat("bindyCsv") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.POJO, Carrier.LIST }, + description = "An object of the classType class, or a List (or an Iterator) of them; a Map of" + + " the model class names to the objects is one record. Other bodies, such as" + + " a Map of field values, are not records"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "csv", + description = "The CSV in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "csv"), + unmarshalOut = @BodyType(value = { Carrier.POJO, Carrier.LIST }, + byOption = @BodyType.When(option = "unwrapSingleInstance", value = "false", + carriers = Carrier.LIST), + description = "An object of the classType class when there is one record, otherwise a" + + " List of them; an empty List for no records with allowEmptyStream")) public class BindyCsvDataFormat extends BindyAbstractDataFormat { private static final Logger LOG = LoggerFactory.getLogger(BindyCsvDataFormat.class); diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/fixed/BindyFixedLengthDataFormat.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/fixed/BindyFixedLengthDataFormat.java index 978c8ccabdc00..b90fc6588d7e7 100644 --- a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/fixed/BindyFixedLengthDataFormat.java +++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/fixed/BindyFixedLengthDataFormat.java @@ -35,6 +35,9 @@ import org.apache.camel.dataformat.bindy.FormatFactory; import org.apache.camel.dataformat.bindy.UnicodeHelper; import org.apache.camel.dataformat.bindy.util.ConverterUtils; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Dataformat; import org.apache.camel.support.ExchangeHelper; import org.apache.camel.support.ObjectHelper; @@ -46,6 +49,21 @@ * Marshal and unmarshal between POJOs and fixed field length format using Camel Bindy */ @Dataformat("bindyFixed") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.POJO, Carrier.LIST }, + description = "An object of the classType class, or a List (or an Iterator) of them, or a" + + " List of Maps of the model class name to the object. The headers" + + " CamelBindyFixedLengthHeader and CamelBindyFixedLengthFooter add the header" + + " and footer records"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "text", + description = "The fixed-length records in the stream cache, or a byte array when stream" + + " caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "text"), + unmarshalOut = @BodyType(value = { Carrier.POJO, Carrier.LIST }, + byOption = @BodyType.When(option = "unwrapSingleInstance", value = "false", + carriers = Carrier.LIST), + description = "An object of the classType class when there is one record, otherwise a" + + " List of them. The header and footer records go to the headers" + + " CamelBindyFixedLengthHeader and CamelBindyFixedLengthFooter")) public class BindyFixedLengthDataFormat extends BindyAbstractDataFormat { public static final String CAMEL_BINDY_FIXED_LENGTH_HEADER = "CamelBindyFixedLengthHeader"; diff --git a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/kvp/BindyKeyValuePairDataFormat.java b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/kvp/BindyKeyValuePairDataFormat.java index 74e69c723879c..72b0c9ee21665 100644 --- a/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/kvp/BindyKeyValuePairDataFormat.java +++ b/components/camel-bindy/src/main/java/org/apache/camel/dataformat/bindy/kvp/BindyKeyValuePairDataFormat.java @@ -37,6 +37,9 @@ import org.apache.camel.dataformat.bindy.FormatFactory; import org.apache.camel.dataformat.bindy.WrappedException; import org.apache.camel.dataformat.bindy.util.ConverterUtils; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Dataformat; import org.apache.camel.support.ExchangeHelper; import org.apache.camel.support.ObjectHelper; @@ -48,6 +51,18 @@ * Marshal and unmarshal between POJOs and key-value pair (KVP) format using Camel Bindy */ @Dataformat("bindyKvp") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.POJO, Carrier.LIST }, + description = "An object of the classType class, or a List (or an Iterator) of them; a Map of" + + " the model class names to the objects is one message"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "text", + description = "The key-value pair messages, one per line, in the stream cache, or a byte" + + " array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "text"), + unmarshalOut = @BodyType(value = { Carrier.POJO, Carrier.LIST }, + byOption = @BodyType.When(option = "unwrapSingleInstance", value = "false", + carriers = Carrier.LIST), + description = "An object of the classType class when there is one message (one per" + + " line), otherwise a List of them")) public class BindyKeyValuePairDataFormat extends BindyAbstractDataFormat { private static final Logger LOG = LoggerFactory.getLogger(BindyKeyValuePairDataFormat.class); diff --git a/components/camel-dfdl/src/generated/resources/META-INF/org/apache/camel/dataformat/dfdl/dfdl.json b/components/camel-dfdl/src/generated/resources/META-INF/org/apache/camel/dataformat/dfdl/dfdl.json index ca76ac1593d1b..e6603b8a9e3d7 100644 --- a/components/camel-dfdl/src/generated/resources/META-INF/org/apache/camel/dataformat/dfdl/dfdl.json +++ b/components/camel-dfdl/src/generated/resources/META-INF/org/apache/camel/dataformat/dfdl/dfdl.json @@ -15,6 +15,12 @@ "modelName": "dfdl", "modelJavaType": "org.apache.camel.model.dataformat.DfdlDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "The XML infoset of the DFDL schema, as text or as a DOM Document (or another DOM Node or Source), which is converted to a DOM Document" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The data in the format the DFDL schema describes, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "Data in the format the DFDL schema describes, such as an EDI message" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document", "description": "The XML infoset as a DOM Document" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "schemaUri": { "index": 1, "kind": "attribute", "displayName": "Schema Uri", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The path to the DFDL schema file." }, diff --git a/components/camel-dfdl/src/main/docs/dfdl-dataformat.adoc b/components/camel-dfdl/src/main/docs/dfdl-dataformat.adoc index 83db51bfd03e6..a38c81307072b 100644 --- a/components/camel-dfdl/src/main/docs/dfdl-dataformat.adoc +++ b/components/camel-dfdl/src/main/docs/dfdl-dataformat.adoc @@ -64,7 +64,7 @@ YAML:: ==== === Marshal (XML to fixed format) -Below is an example of using the DFDL Data Format to unmarshal an EDI message into an XML DOM Document: +Below is an example of using the DFDL Data Format to marshal XML (a DOM Document, or XML text) into an EDI message: [tabs] ==== diff --git a/components/camel-dfdl/src/main/java/org/apache/camel/dataformat/dfdl/DfdlDataFormat.java b/components/camel-dfdl/src/main/java/org/apache/camel/dataformat/dfdl/DfdlDataFormat.java index 0938d47fbed71..f60b15d7185c8 100644 --- a/components/camel-dfdl/src/main/java/org/apache/camel/dataformat/dfdl/DfdlDataFormat.java +++ b/components/camel-dfdl/src/main/java/org/apache/camel/dataformat/dfdl/DfdlDataFormat.java @@ -28,6 +28,9 @@ import org.apache.camel.Exchange; import org.apache.camel.component.dfdl.DfdlParseException; import org.apache.camel.component.dfdl.DfdlUnparseException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.Resource; import org.apache.camel.spi.annotations.Dataformat; @@ -44,6 +47,17 @@ import org.apache.daffodil.japi.io.InputSourceDataInputStream; @Dataformat("dfdl") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", + description = "The XML infoset of the DFDL schema, as text or as a DOM Document (or another" + + " DOM Node or Source), which is converted to a DOM Document"), + marshalOut = @BodyType(value = Carrier.STREAM, + description = "The data in the format the DFDL schema describes, in the stream cache, or a" + + " byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "Data in the format the DFDL schema describes, such as an EDI message"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "org.w3c.dom.Document", + description = "The XML infoset as a DOM Document")) public class DfdlDataFormat extends ServiceSupport implements DataFormat, CamelContextAware { private CamelContext camelContext; private String schemaUri; diff --git a/components/camel-fastjson/src/generated/resources/META-INF/org/apache/camel/component/fastjson/fastjson.json b/components/camel-fastjson/src/generated/resources/META-INF/org/apache/camel/component/fastjson/fastjson.json index 6ff07816a4c98..b75e6e4b6e206 100644 --- a/components/camel-fastjson/src/generated/resources/META-INF/org/apache/camel/component/fastjson/fastjson.json +++ b/components/camel-fastjson/src/generated/resources/META-INF/org/apache/camel/component/fastjson/fastjson.json @@ -15,6 +15,12 @@ "modelName": "json", "modelJavaType": "org.apache.camel.model.dataformat.JsonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as JSON. Bytes, a stream, a file from a file consumer, or a String with a JSON object or array is written as it is; any other String becomes a JSON string" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType" ], "description": "A Map (fastjson JSONObject) for a JSON object, a List (JSONArray) for an array; an object of the class unmarshalType names" } + }, "properties": { "prettyPrint": { "index": 0, "kind": "attribute", "displayName": "Pretty Print", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "To enable pretty printing output nicely formatted. Is by default false." }, "unmarshalType": { "index": 1, "kind": "attribute", "displayName": "Unmarshal Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Class name of the java type to use when unmarshalling." }, diff --git a/components/camel-fastjson/src/main/docs/fastjson-dataformat.adoc b/components/camel-fastjson/src/main/docs/fastjson-dataformat.adoc index 9e89cce982de0..c121c9c030eed 100644 --- a/components/camel-fastjson/src/main/docs/fastjson-dataformat.adoc +++ b/components/camel-fastjson/src/main/docs/fastjson-dataformat.adoc @@ -60,11 +60,12 @@ include::partial$dataformat-options.adoc[] == A body that is already JSON -A body that already is the JSON text is written as it is, not serialized as a Java object: a file, an `InputStream`, -a `byte[]`, and a `String` whose text is a JSON object or array (it starts with `{` and ends with `}`, or `[` and -`]`). So `marshal: json` after reading a JSON file, or after building the JSON with a template or a Simple -expression, sends that JSON unchanged. Any other `String` is written as a JSON string, and POJOs, maps and lists are -marshalled as usual. All the JSON data formats of Camel do the same. +A body that already is the JSON text is written as it is, not serialized as a Java object: a file from a consumer +such as file or ftp, an `InputStream`, a `byte[]`, and a `String` whose text is a JSON object or array (it starts +with `{` and ends with `}`, or `[` and `]`). So `marshal: json` after reading a JSON file, or after building the +JSON with a template or a Simple expression, sends that JSON unchanged. Any other `String` is written as a JSON +string, and POJOs, maps and lists are marshalled as usual. The Jackson, Gson, Jsonb and Fastjson JSON data formats +do the same. == Dependencies diff --git a/components/camel-fastjson/src/main/java/org/apache/camel/component/fastjson/FastjsonDataFormat.java b/components/camel-fastjson/src/main/java/org/apache/camel/component/fastjson/FastjsonDataFormat.java index de6af31cee911..82d77c788b1fa 100644 --- a/components/camel-fastjson/src/main/java/org/apache/camel/component/fastjson/FastjsonDataFormat.java +++ b/components/camel-fastjson/src/main/java/org/apache/camel/component/fastjson/FastjsonDataFormat.java @@ -28,6 +28,9 @@ import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; import org.apache.camel.Message; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatContentTypeHeader; import org.apache.camel.spi.DataFormatName; @@ -41,6 +44,16 @@ */ @Dataformat("fastjson") @Metadata(includeProperties = "unmarshalType,unmarshalTypeName,prettyPrint,contentTypeHeader") +@BodyTypes(marshalIn = @BodyType(value = Carrier.ANY, + description = "A Map, a List or a POJO to write as JSON. Bytes, a stream, a file from a file" + + " consumer, or a String with a JSON object or array is written as it is; any" + + " other String becomes a JSON string"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "json", + description = "The JSON in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "json"), + unmarshalOut = @BodyType(value = { Carrier.MAP, Carrier.LIST }, dependsOn = "unmarshalType", + description = "A Map (fastjson JSONObject) for a JSON object, a List (JSONArray) for an" + + " array; an object of the class unmarshalType names")) public class FastjsonDataFormat extends ServiceSupport implements DataFormat, DataFormatName, DataFormatContentTypeHeader, CamelContextAware { diff --git a/components/camel-fhir/camel-fhir-component/src/generated/resources/META-INF/org/apache/camel/component/fhir/fhirJson.json b/components/camel-fhir/camel-fhir-component/src/generated/resources/META-INF/org/apache/camel/component/fhir/fhirJson.json index 98c9108add2f2..3c94c8f7277e8 100644 --- a/components/camel-fhir/camel-fhir-component/src/generated/resources/META-INF/org/apache/camel/component/fhir/fhirJson.json +++ b/components/camel-fhir/camel-fhir-component/src/generated/resources/META-INF/org/apache/camel/component/fhir/fhirJson.json @@ -15,6 +15,12 @@ "modelName": "fhirJson", "modelJavaType": "org.apache.camel.model.dataformat.FhirJsonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "org.hl7.fhir.instance.model.api.IBaseResource", "description": "A HAPI FHIR resource of the fhirVersion, such as a Patient or a Bundle. Text fails: no type converter makes a resource of it" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The FHIR JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.hl7.fhir.instance.model.api.IBaseResource", "description": "The HAPI FHIR resource of the model of the fhirVersion, such as an org.hl7.fhir.r4.model.Patient with R4" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "fhirVersion": { "index": 1, "kind": "attribute", "displayName": "Fhir Version", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "DSTU2", "DSTU2_HL7ORG", "DSTU2_1", "DSTU3", "R4", "R5" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "R4", "description": "The version of FHIR to use. Possible values are: DSTU2, DSTU2_HL7ORG, DSTU2_1, DSTU3, R4, R5." }, diff --git a/components/camel-fhir/camel-fhir-component/src/generated/resources/META-INF/org/apache/camel/component/fhir/fhirXml.json b/components/camel-fhir/camel-fhir-component/src/generated/resources/META-INF/org/apache/camel/component/fhir/fhirXml.json index b8458c3dd6ea4..848c79932ac94 100644 --- a/components/camel-fhir/camel-fhir-component/src/generated/resources/META-INF/org/apache/camel/component/fhir/fhirXml.json +++ b/components/camel-fhir/camel-fhir-component/src/generated/resources/META-INF/org/apache/camel/component/fhir/fhirXml.json @@ -15,6 +15,12 @@ "modelName": "fhirXml", "modelJavaType": "org.apache.camel.model.dataformat.FhirXmlDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "org.hl7.fhir.instance.model.api.IBaseResource", "description": "A HAPI FHIR resource of the fhirVersion, such as a Patient or a Bundle. Text fails: no type converter makes a resource of it" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The FHIR XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.hl7.fhir.instance.model.api.IBaseResource", "description": "The HAPI FHIR resource of the model of the fhirVersion, such as an org.hl7.fhir.r4.model.Patient with R4" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "fhirVersion": { "index": 1, "kind": "attribute", "displayName": "Fhir Version", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "DSTU2", "DSTU2_HL7ORG", "DSTU2_1", "DSTU3", "R4", "R5" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "R4", "description": "The version of FHIR to use. Possible values are: DSTU2, DSTU2_HL7ORG, DSTU2_1, DSTU3, R4, R5." }, diff --git a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirJsonDataFormat.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirJsonDataFormat.java index 5bf4f20ff4276..c2bbda7a3c4bf 100644 --- a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirJsonDataFormat.java +++ b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirJsonDataFormat.java @@ -23,10 +23,23 @@ import ca.uhn.fhir.parser.IParser; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Dataformat; import org.hl7.fhir.instance.model.api.IBaseResource; @Dataformat("fhirJson") +@BodyTypes(marshalIn = @BodyType(value = Carrier.POJO, javaType = "org.hl7.fhir.instance.model.api.IBaseResource", + description = "A HAPI FHIR resource of the fhirVersion, such as a Patient or a Bundle. Text" + + " fails: no type converter makes a resource of it"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "json", + description = "The FHIR JSON in the stream cache, or a byte array when stream caching" + + " is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "json"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "org.hl7.fhir.instance.model.api.IBaseResource", + description = "The HAPI FHIR resource of the model of the fhirVersion, such as an" + + " org.hl7.fhir.r4.model.Patient with R4")) public class FhirJsonDataFormat extends FhirDataFormat { @Override diff --git a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirXmlDataFormat.java b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirXmlDataFormat.java index 71d7006206a6b..c1a136a301008 100644 --- a/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirXmlDataFormat.java +++ b/components/camel-fhir/camel-fhir-component/src/main/java/org/apache/camel/component/fhir/FhirXmlDataFormat.java @@ -23,10 +23,23 @@ import ca.uhn.fhir.parser.IParser; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Dataformat; import org.hl7.fhir.instance.model.api.IBaseResource; @Dataformat("fhirXml") +@BodyTypes(marshalIn = @BodyType(value = Carrier.POJO, javaType = "org.hl7.fhir.instance.model.api.IBaseResource", + description = "A HAPI FHIR resource of the fhirVersion, such as a Patient or a Bundle. Text" + + " fails: no type converter makes a resource of it"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "xml", + description = "The FHIR XML in the stream cache, or a byte array when stream caching" + + " is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "xml"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "org.hl7.fhir.instance.model.api.IBaseResource", + description = "The HAPI FHIR resource of the model of the fhirVersion, such as an" + + " org.hl7.fhir.r4.model.Patient with R4")) public class FhirXmlDataFormat extends FhirDataFormat { @Override diff --git a/components/camel-flatpack/src/generated/resources/META-INF/org/apache/camel/dataformat/flatpack/flatpack.json b/components/camel-flatpack/src/generated/resources/META-INF/org/apache/camel/dataformat/flatpack/flatpack.json index 5638a7e2e8a08..7838092a3049f 100644 --- a/components/camel-flatpack/src/generated/resources/META-INF/org/apache/camel/dataformat/flatpack/flatpack.json +++ b/components/camel-flatpack/src/generated/resources/META-INF/org/apache/camel/dataformat/flatpack/flatpack.json @@ -15,6 +15,12 @@ "modelName": "flatpack", "modelJavaType": "org.apache.camel.model.dataformat.FlatpackDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "list" ], "description": "The rows as a List of Maps, such as the DataSetList unmarshal gives; a single Map fails. Without a definition, the keys of the first Map name the columns" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The records in the stream cache, or a byte array when stream caching is off. An empty List writes nothing" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "list" ], "javaType": "org.apache.camel.component.flatpack.DataSetList", "description": "A DataSetList: a List of the rows, each a HashMap of the column names and the values, which does not keep the column order" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "definition": { "index": 1, "kind": "attribute", "displayName": "Definition", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The flatpack pzmap configuration file. Can be omitted in simpler situations, but its preferred to use the pzmap." }, diff --git a/components/camel-flatpack/src/main/java/org/apache/camel/dataformat/flatpack/FlatpackDataFormat.java b/components/camel-flatpack/src/main/java/org/apache/camel/dataformat/flatpack/FlatpackDataFormat.java index a53465316bb43..b95927a29ae01 100644 --- a/components/camel-flatpack/src/main/java/org/apache/camel/dataformat/flatpack/FlatpackDataFormat.java +++ b/components/camel-flatpack/src/main/java/org/apache/camel/dataformat/flatpack/FlatpackDataFormat.java @@ -36,6 +36,9 @@ import net.sf.flatpack.writer.Writer; import org.apache.camel.Exchange; import org.apache.camel.component.flatpack.DataSetList; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -59,6 +62,17 @@ * Notice: The Flatpack library does currently not support header and trailers for the marshal operation. */ @Dataformat("flatpack") +@BodyTypes(marshalIn = @BodyType(value = Carrier.LIST, + description = "The rows as a List of Maps, such as the DataSetList unmarshal gives; a single" + + " Map fails. Without a definition, the keys of the first Map name the" + + " columns"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "text", + description = "The records in the stream cache, or a byte array when stream caching is off." + + " An empty List writes nothing"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "text"), + unmarshalOut = @BodyType(value = Carrier.LIST, javaType = "org.apache.camel.component.flatpack.DataSetList", + description = "A DataSetList: a List of the rows, each a HashMap of the column names and" + + " the values, which does not keep the column order")) public class FlatpackDataFormat extends ServiceSupport implements DataFormat, DataFormatName { private static final Logger LOG = LoggerFactory.getLogger(FlatpackDataFormat.class); private ParserFactory parserFactory = DefaultParserFactory.getInstance(); diff --git a/components/camel-grok/src/generated/resources/META-INF/org/apache/camel/component/grok/grok.json b/components/camel-grok/src/generated/resources/META-INF/org/apache/camel/component/grok/grok.json index f219274c1140e..728fb1f6020a9 100644 --- a/components/camel-grok/src/generated/resources/META-INF/org/apache/camel/component/grok/grok.json +++ b/components/camel-grok/src/generated/resources/META-INF/org/apache/camel/component/grok/grok.json @@ -15,6 +15,10 @@ "modelName": "grok", "modelJavaType": "org.apache.camel.model.dataformat.GrokDataFormat" }, + "bodyTypes": { + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text", "description": "Lines of text, such as a log file: each line is matched with the pattern" }, + "unmarshalOut": { "carriers": [ "map", "list", "null" ], "description": "A Map of the captures for one match, a List of such Maps for several, or null when no line matches. The Maps cannot be modified" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "pattern": { "index": 1, "kind": "attribute", "displayName": "Pattern", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The grok pattern to match lines of input." }, diff --git a/components/camel-grok/src/main/docs/grok-dataformat.adoc b/components/camel-grok/src/main/docs/grok-dataformat.adoc index 370e02d7966fd..cdf2d3441c018 100644 --- a/components/camel-grok/src/main/docs/grok-dataformat.adoc +++ b/components/camel-grok/src/main/docs/grok-dataformat.adoc @@ -10,7 +10,9 @@ *Since Camel {since}* This component provides dataformat for processing inputs with grok patterns. -Grok patterns are used to process unstructured data into structured objects - `List>`. +Grok patterns are used to process unstructured data into structured objects: a `Map` of the captures +for one match, a `List` of such Maps for several matches, or no body when nothing matches. With a split, as in the +examples below, an input with one match gives a `Map` whose entries are split one by one. This component is based on the https://github.com/thekrakken/java-grok[Java Grok library] @@ -76,7 +78,7 @@ Java:: [source,java] ---- from("file://apacheLogs") - .unmarshal().grok("%{COMBINEDAPACHELOG") + .unmarshal().grok("%{COMBINEDAPACHELOG}") .split(body()).filter(simple("${body[response]} starts with '4'")) .to("log:4xx"); ---- @@ -87,7 +89,7 @@ XML:: ---- - + ${body} @@ -108,7 +110,7 @@ YAML:: steps: - unmarshal: grok: - pattern: "%{COMBINEDAPACHELOG" + pattern: "%{COMBINEDAPACHELOG}" - split: simple: "${body}" steps: diff --git a/components/camel-grok/src/main/java/org/apache/camel/component/grok/GrokDataFormat.java b/components/camel-grok/src/main/java/org/apache/camel/component/grok/GrokDataFormat.java index 9a75abe69f365..089e2c067fe2b 100644 --- a/components/camel-grok/src/main/java/org/apache/camel/component/grok/GrokDataFormat.java +++ b/components/camel-grok/src/main/java/org/apache/camel/component/grok/GrokDataFormat.java @@ -32,6 +32,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -40,6 +43,11 @@ import org.apache.camel.util.ObjectHelper; @Dataformat("grok") +@BodyTypes(unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "text", + description = "Lines of text, such as a log file: each line is matched with the pattern"), + unmarshalOut = @BodyType(value = { Carrier.MAP, Carrier.LIST, Carrier.NULL }, + description = "A Map of the captures for one match, a List of such Maps for several, or" + + " null when no line matches. The Maps cannot be modified")) public class GrokDataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private CamelContext camelContext; diff --git a/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/groovy/json/groovyJson.json b/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/groovy/json/groovyJson.json index dc892d67c8c59..2c5a121121415 100644 --- a/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/groovy/json/groovyJson.json +++ b/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/groovy/json/groovyJson.json @@ -15,6 +15,12 @@ "modelName": "groovyJson", "modelJavaType": "org.apache.camel.model.dataformat.GroovyJSonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ], "description": "A Map, a Groovy Node or a Jackson JsonNode to write as JSON. Text, bytes, a stream or a file is written as it is; a List is not supported" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "description": "A Map (Groovy LazyMap) for a JSON object, a List (ArrayList) for an array" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "prettyPrint": { "index": 1, "kind": "attribute", "displayName": "Pretty Print", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to pretty print output nicely formatted." } diff --git a/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/groovy/xml/groovyXml.json b/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/groovy/xml/groovyXml.json index 0852d10a91908..34f2a2fc7a6fb 100644 --- a/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/groovy/xml/groovyXml.json +++ b/components/camel-groovy/src/generated/resources/META-INF/org/apache/camel/groovy/xml/groovyXml.json @@ -15,6 +15,12 @@ "modelName": "groovyXml", "modelJavaType": "org.apache.camel.model.dataformat.GroovyXmlDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file", "map", "pojo" ], "description": "A Groovy Node or GPathResult, a Map or a Jackson JsonNode to write as XML. Text, bytes, a stream or a file is written as it is" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "groovy.util.Node", "description": "The XML parsed into a Groovy Node" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "attributeMapping": { "index": 1, "kind": "attribute", "displayName": "Attribute Mapping", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to enable attribute mapping. When enabled, keys that start with _ or character will be mapped to an XML attribute, and vice versa." } diff --git a/components/camel-groovy/src/main/java/org/apache/camel/groovy/json/GroovyJSonlDataFormat.java b/components/camel-groovy/src/main/java/org/apache/camel/groovy/json/GroovyJSonlDataFormat.java index 14d6675d62899..63194c8461a34 100644 --- a/components/camel-groovy/src/main/java/org/apache/camel/groovy/json/GroovyJSonlDataFormat.java +++ b/components/camel-groovy/src/main/java/org/apache/camel/groovy/json/GroovyJSonlDataFormat.java @@ -25,6 +25,9 @@ import groovy.json.JsonSlurper; import groovy.util.Node; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -32,6 +35,16 @@ import org.apache.camel.support.service.ServiceSupport; @Dataformat("groovyJson") +@BodyTypes(marshalIn = @BodyType(value = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP, + Carrier.POJO }, + description = "A Map, a Groovy Node or a Jackson JsonNode to write as JSON. Text, bytes, a" + + " stream or a file is written as it is; a List is not supported"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "json", + description = "The JSON in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "json"), + unmarshalOut = @BodyType(value = { Carrier.MAP, Carrier.LIST }, + description = "A Map (Groovy LazyMap) for a JSON object, a List (ArrayList) for an array")) public class GroovyJSonlDataFormat extends ServiceSupport implements DataFormat, DataFormatName { private boolean prettyPrint = true; diff --git a/components/camel-groovy/src/main/java/org/apache/camel/groovy/xml/GroovyXmlDataFormat.java b/components/camel-groovy/src/main/java/org/apache/camel/groovy/xml/GroovyXmlDataFormat.java index ea13e5cf2537d..48eb71d9b6d66 100644 --- a/components/camel-groovy/src/main/java/org/apache/camel/groovy/xml/GroovyXmlDataFormat.java +++ b/components/camel-groovy/src/main/java/org/apache/camel/groovy/xml/GroovyXmlDataFormat.java @@ -50,6 +50,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -57,6 +60,16 @@ import org.apache.camel.util.StringHelper; @Dataformat("groovyXml") +@BodyTypes(marshalIn = @BodyType(value = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.MAP, + Carrier.POJO }, + description = "A Groovy Node or GPathResult, a Map or a Jackson JsonNode to write as XML." + + " Text, bytes, a stream or a file is written as it is"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "xml", + description = "The XML in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "xml"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "groovy.util.Node", + description = "The XML parsed into a Groovy Node")) public class GroovyXmlDataFormat extends ServiceSupport implements DataFormat, DataFormatName { private static final int START_TAG = 1; diff --git a/components/camel-gson/src/generated/resources/META-INF/org/apache/camel/component/gson/gson.json b/components/camel-gson/src/generated/resources/META-INF/org/apache/camel/component/gson/gson.json index b1b147bfa11dd..858352bc3072e 100644 --- a/components/camel-gson/src/generated/resources/META-INF/org/apache/camel/component/gson/gson.json +++ b/components/camel-gson/src/generated/resources/META-INF/org/apache/camel/component/gson/gson.json @@ -15,6 +15,12 @@ "modelName": "json", "modelJavaType": "org.apache.camel.model.dataformat.JsonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as JSON. Bytes, a stream, a file from a file consumer, or a String with a JSON object or array is written as it is; any other String becomes a JSON string" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "allowUnmarshallType" ], "description": "A Map (Gson LinkedTreeMap) for a JSON object, a List (ArrayList) for an array, with the numbers as Double; an object of the class unmarshalType names" } + }, "properties": { "prettyPrint": { "index": 0, "kind": "attribute", "displayName": "Pretty Print", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "To enable pretty printing output nicely formatted. Is by default false." }, "unmarshalType": { "index": 1, "kind": "attribute", "displayName": "Unmarshal Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Class name of the java type to use when unmarshalling." }, diff --git a/components/camel-gson/src/main/docs/gson-dataformat.adoc b/components/camel-gson/src/main/docs/gson-dataformat.adoc index 07dfe44bf0dea..511d0eef9b034 100644 --- a/components/camel-gson/src/main/docs/gson-dataformat.adoc +++ b/components/camel-gson/src/main/docs/gson-dataformat.adoc @@ -60,11 +60,12 @@ include::partial$dataformat-options.adoc[] == A body that is already JSON -A body that already is the JSON text is written as it is, not serialized as a Java object: a file, an `InputStream`, -a `byte[]`, and a `String` whose text is a JSON object or array (it starts with `{` and ends with `}`, or `[` and -`]`). So `marshal: json` after reading a JSON file, or after building the JSON with a template or a Simple -expression, sends that JSON unchanged. Any other `String` is written as a JSON string, and POJOs, maps and lists are -marshalled as usual. All the JSON data formats of Camel do the same. +A body that already is the JSON text is written as it is, not serialized as a Java object: a file from a consumer +such as file or ftp, an `InputStream`, a `byte[]`, and a `String` whose text is a JSON object or array (it starts +with `{` and ends with `}`, or `[` and `]`). So `marshal: json` after reading a JSON file, or after building the +JSON with a template or a Simple expression, sends that JSON unchanged. Any other `String` is written as a JSON +string, and POJOs, maps and lists are marshalled as usual. The Jackson, Gson, Jsonb and Fastjson JSON data formats +do the same. == Dependencies diff --git a/components/camel-gson/src/main/java/org/apache/camel/component/gson/GsonDataFormat.java b/components/camel-gson/src/main/java/org/apache/camel/component/gson/GsonDataFormat.java index 8cec81eb4c78e..ec19c25821fda 100644 --- a/components/camel-gson/src/main/java/org/apache/camel/component/gson/GsonDataFormat.java +++ b/components/camel-gson/src/main/java/org/apache/camel/component/gson/GsonDataFormat.java @@ -36,6 +36,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatContentTypeHeader; import org.apache.camel.spi.DataFormatName; @@ -51,6 +54,18 @@ */ @Dataformat("gson") @Metadata(includeProperties = "unmarshalType,unmarshalTypeName,prettyPrint,dateFormatPattern,contentTypeHeader,allowUnmarshallType") +@BodyTypes(marshalIn = @BodyType(value = Carrier.ANY, + description = "A Map, a List or a POJO to write as JSON. Bytes, a stream, a file from a file" + + " consumer, or a String with a JSON object or array is written as it is; any" + + " other String becomes a JSON string"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "json", + description = "The JSON in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "json"), + unmarshalOut = @BodyType(value = { Carrier.MAP, Carrier.LIST }, + dependsOn = { "unmarshalType", "allowUnmarshallType" }, + description = "A Map (Gson LinkedTreeMap) for a JSON object, a List (ArrayList) for an" + + " array, with the numbers as Double; an object of the class unmarshalType" + + " names")) public class GsonDataFormat extends ServiceSupport implements DataFormat, DataFormatName, DataFormatContentTypeHeader, CamelContextAware { diff --git a/components/camel-hl7/src/generated/resources/META-INF/org/apache/camel/component/hl7/hl7.json b/components/camel-hl7/src/generated/resources/META-INF/org/apache/camel/component/hl7/hl7.json index 26599aee6c8d0..6447ee4209e89 100644 --- a/components/camel-hl7/src/generated/resources/META-INF/org/apache/camel/component/hl7/hl7.json +++ b/components/camel-hl7/src/generated/resources/META-INF/org/apache/camel/component/hl7/hl7.json @@ -15,6 +15,12 @@ "modelName": "hl7", "modelJavaType": "org.apache.camel.model.dataformat.HL7DataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "pojo" ], "description": "A HAPI Message, or HL7 as text or bytes (ER7 or XML) or an HL7 XML DOM Document, which a type converter parses into a Message. A stream or a file fails: convert it to text first" }, + "marshalOut": { "carriers": [ "stream" ], "description": "HL7 in ER7 (pipe-delimited), or HL7 XML with targetFormat XML, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "HL7 in ER7 (pipe-delimited) or XML, which the parser detects" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "ca.uhn.hl7v2.model.Message", "byOption": [ { "option": "targetFormat", "value": "XML", "carriers": [ "pojo" ], "javaType": "org.w3c.dom.Document" } ], "description": "The HAPI Message of the structure for its type and version, such as ADT_A01 (a GenericMessage without the structures), with the MSH fields in CamelHL7 headers. With targetFormat XML, the HL7 XML as a DOM Document" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "parser": { "index": 1, "kind": "attribute", "displayName": "Parser", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "ca.uhn.hl7v2.parser.Parser", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HL7 parser." }, diff --git a/components/camel-hl7/src/main/java/org/apache/camel/component/hl7/HL7DataFormat.java b/components/camel-hl7/src/main/java/org/apache/camel/component/hl7/HL7DataFormat.java index 27298829a3e15..70afe6c2f7370 100644 --- a/components/camel-hl7/src/main/java/org/apache/camel/component/hl7/HL7DataFormat.java +++ b/components/camel-hl7/src/main/java/org/apache/camel/component/hl7/HL7DataFormat.java @@ -32,6 +32,9 @@ import ca.uhn.hl7v2.validation.ValidationContext; import ca.uhn.hl7v2.validation.impl.ValidationContextFactory; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -95,6 +98,22 @@ * @see org.apache.camel.component.hl7.HL7MLLPCodec */ @Dataformat("hl7") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.POJO }, + description = "A HAPI Message, or HL7 as text or bytes (ER7 or XML) or an HL7 XML DOM" + + " Document, which a type converter parses into a Message. A stream or a file" + + " fails: convert it to text first"), + marshalOut = @BodyType(value = Carrier.STREAM, + description = "HL7 in ER7 (pipe-delimited), or HL7 XML with targetFormat XML, in the stream" + + " cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "HL7 in ER7 (pipe-delimited) or XML, which the parser detects"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "ca.uhn.hl7v2.model.Message", + byOption = @BodyType.When(option = "targetFormat", value = "XML", carriers = Carrier.POJO, + javaType = "org.w3c.dom.Document"), + description = "The HAPI Message of the structure for its type and version, such as" + + " ADT_A01 (a GenericMessage without the structures), with the MSH fields" + + " in CamelHL7 headers. With targetFormat XML, the HL7 XML as a DOM" + + " Document")) public class HL7DataFormat extends ServiceSupport implements DataFormat, DataFormatName { private static final Map HEADER_MAP = new HashMap<>(); diff --git a/components/camel-ical/src/generated/resources/META-INF/org/apache/camel/component/ical/ical.json b/components/camel-ical/src/generated/resources/META-INF/org/apache/camel/component/ical/ical.json index c590ea3710e1c..3b1d2ddec2e83 100644 --- a/components/camel-ical/src/generated/resources/META-INF/org/apache/camel/component/ical/ical.json +++ b/components/camel-ical/src/generated/resources/META-INF/org/apache/camel/component/ical/ical.json @@ -15,6 +15,12 @@ "modelName": "ical", "modelJavaType": "org.apache.camel.model.dataformat.IcalDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "net.fortuna.ical4j.model.Calendar", "description": "An ical4j Calendar, such as unmarshal gives. Text is not parsed: unmarshal the iCalendar text first" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The iCalendar text in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text", "description": "An iCalendar (.ics) document, which ical4j reads as UTF-8" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "net.fortuna.ical4j.model.Calendar", "description": "An ical4j Calendar of the document" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "validating": { "index": 1, "kind": "attribute", "displayName": "Validating", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to validate the iCal document." } diff --git a/components/camel-ical/src/main/java/org/apache/camel/component/ical/ICalDataFormat.java b/components/camel-ical/src/main/java/org/apache/camel/component/ical/ICalDataFormat.java index 61ee10bf2985b..308c22a3800b8 100644 --- a/components/camel-ical/src/main/java/org/apache/camel/component/ical/ICalDataFormat.java +++ b/components/camel-ical/src/main/java/org/apache/camel/component/ical/ICalDataFormat.java @@ -23,6 +23,9 @@ import net.fortuna.ical4j.data.CalendarOutputter; import net.fortuna.ical4j.model.Calendar; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -32,6 +35,16 @@ * Bridge ICal data format to camel world. */ @Dataformat("ical") +@BodyTypes(marshalIn = @BodyType(value = Carrier.POJO, javaType = "net.fortuna.ical4j.model.Calendar", + description = "An ical4j Calendar, such as unmarshal gives. Text is not parsed: unmarshal the" + + " iCalendar text first"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "text", + description = "The iCalendar text in the stream cache, or a byte array when stream caching is" + + " off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "text", + description = "An iCalendar (.ics) document, which ical4j reads as UTF-8"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "net.fortuna.ical4j.model.Calendar", + description = "An ical4j Calendar of the document")) public class ICalDataFormat extends ServiceSupport implements DataFormat, DataFormatName { private boolean validating; diff --git a/components/camel-iso8583/src/generated/resources/META-INF/org/apache/camel/dataformat/iso8583/iso8583.json b/components/camel-iso8583/src/generated/resources/META-INF/org/apache/camel/dataformat/iso8583/iso8583.json index 95f93cb2a74b7..e6496d14e91cf 100644 --- a/components/camel-iso8583/src/generated/resources/META-INF/org/apache/camel/dataformat/iso8583/iso8583.json +++ b/components/camel-iso8583/src/generated/resources/META-INF/org/apache/camel/dataformat/iso8583/iso8583.json @@ -15,6 +15,12 @@ "modelName": "iso8583", "modelJavaType": "org.apache.camel.model.dataformat.Iso8583DataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "com.solab.iso8583.IsoMessage", "description": "A j8583 IsoMessage, such as unmarshal gives. A Map is not converted" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The ISO-8583 message in the stream cache, or a byte array when stream caching is off: ASCII or binary, as the j8583 configuration says" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "An ISO-8583 message of the ISO-Type in the CamelIso8583IsoType header, or else the isoType option: unmarshal fails without either" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "com.solab.iso8583.IsoMessage", "description": "A j8583 IsoMessage: getAt(n) gives field n" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "configFile": { "index": 1, "kind": "attribute", "displayName": "Config File", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "j8583-config.xml", "description": "The j8583 configuration file to load from classpath" }, diff --git a/components/camel-iso8583/src/main/java/org/apache/camel/dataformat/iso8583/Iso8583DataFormat.java b/components/camel-iso8583/src/main/java/org/apache/camel/dataformat/iso8583/Iso8583DataFormat.java index a476e8c3c7ef8..c8dd62f3033f9 100644 --- a/components/camel-iso8583/src/main/java/org/apache/camel/dataformat/iso8583/Iso8583DataFormat.java +++ b/components/camel-iso8583/src/main/java/org/apache/camel/dataformat/iso8583/Iso8583DataFormat.java @@ -24,6 +24,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.Metadata; @@ -36,6 +39,16 @@ */ @Dataformat("iso8583") @Metadata(firstVersion = "4.14.0", title = "ISO-8583") +@BodyTypes(marshalIn = @BodyType(value = Carrier.POJO, javaType = "com.solab.iso8583.IsoMessage", + description = "A j8583 IsoMessage, such as unmarshal gives. A Map is not converted"), + marshalOut = @BodyType(value = Carrier.STREAM, + description = "The ISO-8583 message in the stream cache, or a byte array when stream caching" + + " is off: ASCII or binary, as the j8583 configuration says"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "An ISO-8583 message of the ISO-Type in the CamelIso8583IsoType header, or" + + " else the isoType option: unmarshal fails without either"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "com.solab.iso8583.IsoMessage", + description = "A j8583 IsoMessage: getAt(n) gives field n")) public class Iso8583DataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private CamelContext camelContext; diff --git a/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc b/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc index 96e49f1ee2221..8abae4e00092a 100644 --- a/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc +++ b/components/camel-jackson/src/main/docs/jackson2-dataformat.adoc @@ -68,11 +68,12 @@ in the Camel dataformat. === A body that is already JSON -A body that already is the JSON text is written as it is, not serialized as a Java object: a file, an `InputStream`, -a `byte[]`, and a `String` whose text is a JSON object or array (it starts with `{` and ends with `}`, or `[` and -`]`). So `marshal: json` after reading a JSON file, or after building the JSON with a template or a Simple -expression, sends that JSON unchanged. Any other `String` is written as a JSON string, and POJOs, maps and lists are -marshalled as usual. All the JSON data formats of Camel do the same. +A body that already is the JSON text is written as it is, not serialized as a Java object: a file from a consumer +such as file or ftp, an `InputStream`, a `byte[]`, and a `String` whose text is a JSON object or array (it starts +with `{` and ends with `}`, or `[` and `]`). So `marshal: json` after reading a JSON file, or after building the +JSON with a template or a Simple expression, sends that JSON unchanged. Any other `String` is written as a JSON +string, and POJOs, maps and lists are marshalled as usual. The Jackson, Gson, Jsonb and Fastjson JSON data formats +do the same. === Using custom ObjectMapper diff --git a/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc b/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc index 149c8ff604991..a368586b823ac 100644 --- a/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc +++ b/components/camel-jackson3/src/main/docs/jackson3-dataformat.adoc @@ -96,11 +96,12 @@ in the Camel dataformat. === A body that is already JSON -A body that already is the JSON text is written as it is, not serialized as a Java object: a file, an `InputStream`, -a `byte[]`, and a `String` whose text is a JSON object or array (it starts with `{` and ends with `}`, or `[` and -`]`). So `marshal: json` after reading a JSON file, or after building the JSON with a template or a Simple -expression, sends that JSON unchanged. Any other `String` is written as a JSON string, and POJOs, maps and lists are -marshalled as usual. All the JSON data formats of Camel do the same. +A body that already is the JSON text is written as it is, not serialized as a Java object: a file from a consumer +such as file or ftp, an `InputStream`, a `byte[]`, and a `String` whose text is a JSON object or array (it starts +with `{` and ends with `}`, or `[` and `]`). So `marshal: json` after reading a JSON file, or after building the +JSON with a template or a Simple expression, sends that JSON unchanged. Any other `String` is written as a JSON +string, and POJOs, maps and lists are marshalled as usual. The Jackson, Gson, Jsonb and Fastjson JSON data formats +do the same. === Using custom ObjectMapper diff --git a/components/camel-jaxb/src/generated/resources/META-INF/org/apache/camel/converter/jaxb/jaxb.json b/components/camel-jaxb/src/generated/resources/META-INF/org/apache/camel/converter/jaxb/jaxb.json index 202d64da3fe60..f63c43ae3cbf7 100644 --- a/components/camel-jaxb/src/generated/resources/META-INF/org/apache/camel/converter/jaxb/jaxb.json +++ b/components/camel-jaxb/src/generated/resources/META-INF/org/apache/camel/converter/jaxb/jaxb.json @@ -15,6 +15,12 @@ "modelName": "jaxb", "modelJavaType": "org.apache.camel.model.dataformat.JaxbDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "dependsOn": [ "partNamespace" ], "byOption": [ { "option": "mustBeJAXBElement", "value": "true", "carriers": [ "pojo" ] } ], "description": "A JAXB object: a class with @XmlRootElement, a JAXBElement, or a class the ObjectFactory makes an element of. Text, bytes, a stream or a file is written as it is, as XML already, unless mustBeJAXBElement is true" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "The XML: text, bytes, a stream, a file, a DOM Document, a DOMSource or a StreamSource" }, + "unmarshalOut": { "carriers": [ "pojo" ], "description": "The object of the root element, of a JAXB class of contextPath, or of partClass when set; a JAXBElement, where JAXB gives one, when ignoreJAXBElement is false" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "contextPath": { "index": 1, "kind": "attribute", "displayName": "Context Path", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Package name where your JAXB classes are located." }, diff --git a/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc b/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc index a12c7a13d1615..b32e36b186d9e 100644 --- a/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc +++ b/components/camel-jaxb/src/main/docs/jaxb-dataformat.adoc @@ -344,14 +344,15 @@ You can do the same using the XML DSL: === Marshal data that is already XML -The JAXB marshaller requires that the message body is JAXB compatible, +The JAXB marshaller marshals a message body that is JAXB compatible, e.g., it is a `JAXBElement`, a java instance that has JAXB annotations, or extends `JAXBElement`. There can be situations where the message body is already in XML, e.g., from a `String` type. -`JaxbDataFormat` has an option named `mustBeJAXBElement` which you can set to `false` to relax this check and -have the JAXB marshaller only attempt marshalling on `JAXBElement` (`javax.xml.bind.JAXBIntrospector#isElement` returns `true`). -In those situations, the marshaller will fall back to marshal the message body as-is. +The option `mustBeJAXBElement` is `false` by default: a message body that is not JAXB compatible +(`jakarta.xml.bind.JAXBIntrospector#isElement` returns `false`) is then written as-is, as XML already. +Text, bytes, a stream or a file can be written this way; a `Map` or a `List` fails. +Set `mustBeJAXBElement` to `true` to fail with an `InvalidPayloadException` instead. == Dependencies diff --git a/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java b/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java index 6ef18ca809832..99237a8778833 100644 --- a/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java +++ b/components/camel-jaxb/src/main/java/org/apache/camel/converter/jaxb/JaxbDataFormat.java @@ -57,6 +57,9 @@ import org.apache.camel.InvalidPayloadException; import org.apache.camel.NoTypeConversionAvailableException; import org.apache.camel.TypeConverter; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatContentTypeHeader; import org.apache.camel.spi.DataFormatName; @@ -73,6 +76,23 @@ * and from XML */ @Dataformat("jaxb") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + dependsOn = "partNamespace", + byOption = @BodyType.When(option = "mustBeJAXBElement", value = "true", + carriers = Carrier.POJO), + description = "A JAXB object: a class with @XmlRootElement, a JAXBElement, or a class the" + + " ObjectFactory makes an element of. Text, bytes, a stream or a file is" + + " written as it is, as XML already, unless mustBeJAXBElement is true"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "xml", + description = "The XML in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", + description = "The XML: text, bytes, a stream, a file, a DOM Document, a DOMSource or a" + + " StreamSource"), + unmarshalOut = @BodyType(value = Carrier.POJO, + description = "The object of the root element, of a JAXB class of contextPath, or of" + + " partClass when set; a JAXBElement, where JAXB gives one, when" + + " ignoreJAXBElement is false")) public class JaxbDataFormat extends ServiceSupport implements DataFormat, DataFormatName, DataFormatContentTypeHeader, CamelContextAware { diff --git a/components/camel-jsonapi/src/generated/resources/META-INF/org/apache/camel/component/jsonapi/jsonApi.json b/components/camel-jsonapi/src/generated/resources/META-INF/org/apache/camel/component/jsonapi/jsonApi.json index ff661f35e9415..654f1f927daff 100644 --- a/components/camel-jsonapi/src/generated/resources/META-INF/org/apache/camel/component/jsonapi/jsonApi.json +++ b/components/camel-jsonapi/src/generated/resources/META-INF/org/apache/camel/component/jsonapi/jsonApi.json @@ -15,6 +15,12 @@ "modelName": "jsonApi", "modelJavaType": "org.apache.camel.model.dataformat.JsonApiDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "description": "One resource object of a class dataFormatTypes names, annotated with @Type and @Id of JSONAPI-Converter. A Map or a List fails" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON:API document in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "pojo", "null" ], "description": "The primary data as an object of the class mainFormatType names, or no body when the data is null. A document whose data is an array fails" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "dataFormatTypes": { "index": 1, "kind": "attribute", "displayName": "Data Format Types", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The classes to take into account for the marshalling. Multiple classes can be separated by comma." }, diff --git a/components/camel-jsonapi/src/main/java/org/apache/camel/component/jsonapi/JsonApiDataFormat.java b/components/camel-jsonapi/src/main/java/org/apache/camel/component/jsonapi/JsonApiDataFormat.java index b485601870b62..706eca4c735ed 100644 --- a/components/camel-jsonapi/src/main/java/org/apache/camel/component/jsonapi/JsonApiDataFormat.java +++ b/components/camel-jsonapi/src/main/java/org/apache/camel/component/jsonapi/JsonApiDataFormat.java @@ -26,6 +26,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -35,6 +38,16 @@ * JSonApi data format for marshal/unmarshal */ @Dataformat("jsonApi") +@BodyTypes(marshalIn = @BodyType(value = Carrier.POJO, + description = "One resource object of a class dataFormatTypes names, annotated with @Type and" + + " @Id of JSONAPI-Converter. A Map or a List fails"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "json", + description = "The JSON:API document in the stream cache, or a byte array when stream" + + " caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "json"), + unmarshalOut = @BodyType(value = { Carrier.POJO, Carrier.NULL }, + description = "The primary data as an object of the class mainFormatType names, or no body" + + " when the data is null. A document whose data is an array fails")) public class JsonApiDataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private CamelContext camelContext; diff --git a/components/camel-jsonb/src/generated/resources/META-INF/org/apache/camel/component/jsonb/jsonb.json b/components/camel-jsonb/src/generated/resources/META-INF/org/apache/camel/component/jsonb/jsonb.json index d89137d9303a8..d90876750735f 100644 --- a/components/camel-jsonb/src/generated/resources/META-INF/org/apache/camel/component/jsonb/jsonb.json +++ b/components/camel-jsonb/src/generated/resources/META-INF/org/apache/camel/component/jsonb/jsonb.json @@ -15,6 +15,12 @@ "modelName": "json", "modelJavaType": "org.apache.camel.model.dataformat.JsonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as JSON. Bytes, a stream, a file from a file consumer, or a String with a JSON object or array is written as it is; any other String becomes a JSON string" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "allowUnmarshallType" ], "description": "A Map (HashMap with Yasson) for a JSON object, a List (ArrayList) for an array, with the numbers as BigDecimal; an object of the class unmarshalType names" } + }, "properties": { "objectMapper": { "index": 0, "kind": "attribute", "displayName": "Jsonb instance", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing Jsonb instance with the given id." }, "prettyPrint": { "index": 1, "kind": "attribute", "displayName": "Pretty Print", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "To enable pretty printing output nicely formatted. Is by default false." }, diff --git a/components/camel-jsonb/src/main/docs/jsonb-dataformat.adoc b/components/camel-jsonb/src/main/docs/jsonb-dataformat.adoc index 3d0a251f888f8..a0818a001afc4 100644 --- a/components/camel-jsonb/src/main/docs/jsonb-dataformat.adoc +++ b/components/camel-jsonb/src/main/docs/jsonb-dataformat.adoc @@ -59,11 +59,12 @@ include::partial$dataformat-options.adoc[] == A body that is already JSON -A body that already is the JSON text is written as it is, not serialized as a Java object: a file, an `InputStream`, -a `byte[]`, and a `String` whose text is a JSON object or array (it starts with `{` and ends with `}`, or `[` and -`]`). So `marshal: json` after reading a JSON file, or after building the JSON with a template or a Simple -expression, sends that JSON unchanged. Any other `String` is written as a JSON string, and POJOs, maps and lists are -marshalled as usual. All the JSON data formats of Camel do the same. +A body that already is the JSON text is written as it is, not serialized as a Java object: a file from a consumer +such as file or ftp, an `InputStream`, a `byte[]`, and a `String` whose text is a JSON object or array (it starts +with `{` and ends with `}`, or `[` and `]`). So `marshal: json` after reading a JSON file, or after building the +JSON with a template or a Simple expression, sends that JSON unchanged. Any other `String` is written as a JSON +string, and POJOs, maps and lists are marshalled as usual. The Jackson, Gson, Jsonb and Fastjson JSON data formats +do the same. == Dependencies diff --git a/components/camel-jsonb/src/main/java/org/apache/camel/component/jsonb/JsonbDataFormat.java b/components/camel-jsonb/src/main/java/org/apache/camel/component/jsonb/JsonbDataFormat.java index c1f72ebcfa7de..5ac4e58dfa719 100644 --- a/components/camel-jsonb/src/main/java/org/apache/camel/component/jsonb/JsonbDataFormat.java +++ b/components/camel-jsonb/src/main/java/org/apache/camel/component/jsonb/JsonbDataFormat.java @@ -32,6 +32,9 @@ import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; import org.apache.camel.RuntimeCamelException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.Metadata; @@ -44,6 +47,18 @@ */ @Dataformat("jsonb") @Metadata(includeProperties = "unmarshalTypeName,unmarshalType,objectMapper,prettyPrint,binaryStrategy,encoding,propertyOrder,propertyNamingStrategy,skipNull,allowUnmarshallType") +@BodyTypes(marshalIn = @BodyType(value = Carrier.ANY, + description = "A Map, a List or a POJO to write as JSON. Bytes, a stream, a file from a file" + + " consumer, or a String with a JSON object or array is written as it is; any" + + " other String becomes a JSON string"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "json", + description = "The JSON in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "json"), + unmarshalOut = @BodyType(value = { Carrier.MAP, Carrier.LIST }, + dependsOn = { "unmarshalType", "allowUnmarshallType" }, + description = "A Map (HashMap with Yasson) for a JSON object, a List (ArrayList) for an" + + " array, with the numbers as BigDecimal; an object of the class" + + " unmarshalType names")) public class JsonbDataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { /** diff --git a/components/camel-ocsf/src/generated/resources/META-INF/org/apache/camel/dataformat/ocsf/ocsf.json b/components/camel-ocsf/src/generated/resources/META-INF/org/apache/camel/dataformat/ocsf/ocsf.json index 781965395f562..7153701d2234c 100644 --- a/components/camel-ocsf/src/generated/resources/META-INF/org/apache/camel/dataformat/ocsf/ocsf.json +++ b/components/camel-ocsf/src/generated/resources/META-INF/org/apache/camel/dataformat/ocsf/ocsf.json @@ -15,6 +15,12 @@ "modelName": "ocsf", "modelJavaType": "org.apache.camel.model.dataformat.OcsfDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list", "pojo" ], "description": "An OCSF event such as a DetectionFinding, a Map or a List to write as JSON. A String is written as one JSON string and bytes as Base64, not as they are" }, + "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.apache.camel.dataformat.ocsf.model.OcsfEvent", "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "The base OcsfEvent; an object of the class unmarshalType names, such as DetectionFinding" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "objectMapper": { "index": 1, "kind": "attribute", "displayName": "Object Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing ObjectMapper with the given id when using Jackson." }, diff --git a/components/camel-ocsf/src/main/java/org/apache/camel/dataformat/ocsf/OcsfDataFormat.java b/components/camel-ocsf/src/main/java/org/apache/camel/dataformat/ocsf/OcsfDataFormat.java index 0fb99d39c5c66..d44389d3ffed4 100644 --- a/components/camel-ocsf/src/main/java/org/apache/camel/dataformat/ocsf/OcsfDataFormat.java +++ b/components/camel-ocsf/src/main/java/org/apache/camel/dataformat/ocsf/OcsfDataFormat.java @@ -36,6 +36,9 @@ import org.apache.camel.Exchange; import org.apache.camel.WrappedFile; import org.apache.camel.dataformat.ocsf.model.OcsfEvent; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.Metadata; @@ -55,6 +58,17 @@ */ @Dataformat("ocsf") @Metadata(excludeProperties = "library") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.MAP, Carrier.LIST, Carrier.POJO }, + description = "An OCSF event such as a DetectionFinding, a Map or a List to write as JSON. A" + + " String is written as one JSON string and bytes as Base64, not as they are"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "json", + description = "The JSON in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "json"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "org.apache.camel.dataformat.ocsf.model.OcsfEvent", + dependsOn = { "unmarshalType", "collectionType", "allowUnmarshallType" }, + byOption = @BodyType.When(option = "useList", value = "true", carriers = Carrier.LIST), + description = "The base OcsfEvent; an object of the class unmarshalType names, such as" + + " DetectionFinding")) public class OcsfDataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private static final Logger LOG = LoggerFactory.getLogger(OcsfDataFormat.class); diff --git a/components/camel-rss/src/generated/resources/META-INF/org/apache/camel/dataformat/rss/rss.json b/components/camel-rss/src/generated/resources/META-INF/org/apache/camel/dataformat/rss/rss.json index 04e3693f48337..aed9ccedeffe4 100644 --- a/components/camel-rss/src/generated/resources/META-INF/org/apache/camel/dataformat/rss/rss.json +++ b/components/camel-rss/src/generated/resources/META-INF/org/apache/camel/dataformat/rss/rss.json @@ -15,6 +15,12 @@ "modelName": "rss", "modelJavaType": "org.apache.camel.model.dataformat.RssDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "pojo" ], "description": "A ROME SyndFeed, such as the rss consumer gives, or the XML text of an RSS or Atom feed, which is parsed first" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The RSS or Atom XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml", "description": "An RSS or Atom feed" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "com.rometools.rome.feed.synd.SyndFeed", "description": "A ROME SyndFeed of the feed" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" } } diff --git a/components/camel-rss/src/main/docs/rss-dataformat.adoc b/components/camel-rss/src/main/docs/rss-dataformat.adoc index 478303b5f755e..7efb718134cd1 100644 --- a/components/camel-rss/src/main/docs/rss-dataformat.adoc +++ b/components/camel-rss/src/main/docs/rss-dataformat.adoc @@ -12,8 +12,8 @@ The RSS component ships with an RSS dataformat that can be used to convert between String (as XML) and ROME RSS model objects. -* marshal = from ROME `SyndFeed` to XML `String` -* unmarshal = from XML `String` to ROME `SyndFeed` +* marshal = from ROME `SyndFeed` (or the XML text of a feed) to XML +* unmarshal = from XML (text, bytes, a stream or a file) to ROME `SyndFeed` A route using this would look something like this: @@ -42,8 +42,8 @@ include::partial$dataformat-options.adoc[] The RSS component ships with an RSS dataformat that can be used to convert between String (as XML) and ROME RSS model objects. -* marshal = from ROME `SyndFeed` to XML `String` -* unmarshal = from XML `String` to ROME `SyndFeed` +* marshal = from ROME `SyndFeed` (or the XML text of a feed) to XML +* unmarshal = from XML (text, bytes, a stream or a file) to ROME `SyndFeed` A route using the RSS dataformat will look like this: diff --git a/components/camel-rss/src/main/java/org/apache/camel/dataformat/rss/RssDataFormat.java b/components/camel-rss/src/main/java/org/apache/camel/dataformat/rss/RssDataFormat.java index ca7ff7ebe47b0..46a2086f9280f 100644 --- a/components/camel-rss/src/main/java/org/apache/camel/dataformat/rss/RssDataFormat.java +++ b/components/camel-rss/src/main/java/org/apache/camel/dataformat/rss/RssDataFormat.java @@ -21,6 +21,9 @@ import com.rometools.rome.feed.synd.SyndFeed; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -40,6 +43,16 @@ *

*/ @Dataformat("rss") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.POJO }, + description = "A ROME SyndFeed, such as the rss consumer gives, or the XML text of an RSS or" + + " Atom feed, which is parsed first"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "xml", + description = "The RSS or Atom XML in the stream cache, or a byte array when stream caching" + + " is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "xml", + description = "An RSS or Atom feed"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "com.rometools.rome.feed.synd.SyndFeed", + description = "A ROME SyndFeed of the feed")) public class RssDataFormat extends ServiceSupport implements DataFormat, DataFormatName { @Override diff --git a/components/camel-soap/src/generated/resources/META-INF/org/apache/camel/dataformat/soap/soap.json b/components/camel-soap/src/generated/resources/META-INF/org/apache/camel/dataformat/soap/soap.json index 27dc19f35f7d8..f723d8733fbe5 100644 --- a/components/camel-soap/src/generated/resources/META-INF/org/apache/camel/dataformat/soap/soap.json +++ b/components/camel-soap/src/generated/resources/META-INF/org/apache/camel/dataformat/soap/soap.json @@ -15,6 +15,12 @@ "modelName": "soap", "modelJavaType": "org.apache.camel.model.dataformat.SoapDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "dependsOn": [ "elementNameStrategy" ], "description": "A JAXB object whose class has @XmlType with a name, written as the one element of the SOAP body; text fails. When the exchange has a caught exception (onException, doCatch), a SOAP fault of it is written instead" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The SOAP envelope in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "A SOAP envelope of the version: text, bytes, a stream, a file, a DOM Document, a DOMSource or a StreamSource" }, + "unmarshalOut": { "carriers": [ "pojo", "null" ], "description": "The JAXB object of the first element of the SOAP body, with the SOAP headers in the org.apache.camel.dataformat.soap.UNMARSHALLED_HEADER_LIST header. No body when the SOAP body is empty or a fault, which becomes the exception of the exchange" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "contextPath": { "index": 1, "kind": "attribute", "displayName": "Context Path", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Package name where your JAXB classes are located." }, diff --git a/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/SoapDataFormat.java b/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/SoapDataFormat.java index a3e0eeb0d343e..39029f776ae23 100644 --- a/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/SoapDataFormat.java +++ b/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/SoapDataFormat.java @@ -36,6 +36,9 @@ import org.apache.camel.dataformat.soap.name.ElementNameStrategy; import org.apache.camel.dataformat.soap.name.ServiceInterfaceStrategy; import org.apache.camel.dataformat.soap.name.TypeNameStrategy; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.annotations.Dataformat; import org.slf4j.Logger; @@ -48,6 +51,22 @@ */ @Dataformat("soap") @Metadata(excludeProperties = "library,instanceClass,contentTypeFormat,defaultInstance") +@BodyTypes(marshalIn = @BodyType(value = Carrier.POJO, dependsOn = "elementNameStrategy", + description = "A JAXB object whose class has @XmlType with a name, written as the one element" + + " of the SOAP body; text fails. When the exchange has a caught exception" + + " (onException, doCatch), a SOAP fault of it is written instead"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "xml", + description = "The SOAP envelope in the stream cache, or a byte array when stream caching is" + + " off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", + description = "A SOAP envelope of the version: text, bytes, a stream, a file, a DOM" + + " Document, a DOMSource or a StreamSource"), + unmarshalOut = @BodyType(value = { Carrier.POJO, Carrier.NULL }, + description = "The JAXB object of the first element of the SOAP body, with the SOAP headers" + + " in the org.apache.camel.dataformat.soap.UNMARSHALLED_HEADER_LIST header." + + " No body when the SOAP body is empty or a fault, which becomes the" + + " exception of the exchange")) public class SoapDataFormat extends JaxbDataFormat { public static final String SOAP_UNMARSHALLED_HEADER_LIST = "org.apache.camel.dataformat.soap.UNMARSHALLED_HEADER_LIST"; diff --git a/components/camel-swift/src/generated/resources/META-INF/org/apache/camel/dataformat/swift/mt/swiftMt.json b/components/camel-swift/src/generated/resources/META-INF/org/apache/camel/dataformat/swift/mt/swiftMt.json index b301798cfcc3d..6cae4036a20df 100644 --- a/components/camel-swift/src/generated/resources/META-INF/org/apache/camel/dataformat/swift/mt/swiftMt.json +++ b/components/camel-swift/src/generated/resources/META-INF/org/apache/camel/dataformat/swift/mt/swiftMt.json @@ -15,6 +15,12 @@ "modelName": "swiftMt", "modelJavaType": "org.apache.camel.model.dataformat.SwiftMtDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "com.prowidesoftware.swift.model.mt.AbstractMT", "byOption": [ { "option": "writeInJson", "value": "true", "carriers": [ "pojo" ], "javaType": "com.prowidesoftware.JsonSerializable" } ], "description": "A Prowide MT message, such as an MT103, as unmarshal gives. The body is not converted: MT text fails" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The MT message in FIN format, or JSON with writeInJson, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "An MT message in FIN format" }, + "unmarshalOut": { "carriers": [ "pojo", "null" ], "javaType": "com.prowidesoftware.swift.model.mt.AbstractMT", "description": "The Prowide class of the message type, such as MT103; null when the type is not known" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "writeInJson": { "index": 1, "kind": "attribute", "displayName": "Write In Json", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to marshal messages in JSON format." } diff --git a/components/camel-swift/src/generated/resources/META-INF/org/apache/camel/dataformat/swift/mx/swiftMx.json b/components/camel-swift/src/generated/resources/META-INF/org/apache/camel/dataformat/swift/mx/swiftMx.json index 7a4095f2c07e4..13b5e1b80be61 100644 --- a/components/camel-swift/src/generated/resources/META-INF/org/apache/camel/dataformat/swift/mx/swiftMx.json +++ b/components/camel-swift/src/generated/resources/META-INF/org/apache/camel/dataformat/swift/mx/swiftMx.json @@ -15,6 +15,12 @@ "modelName": "swiftMx", "modelJavaType": "org.apache.camel.model.dataformat.SwiftMxDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "com.prowidesoftware.swift.model.mx.AbstractMX", "byOption": [ { "option": "writeInJson", "value": "true", "carriers": [ "pojo" ], "javaType": "com.prowidesoftware.JsonSerializable" } ], "description": "A Prowide MX message, such as an MxPacs00800108, as unmarshal gives. The body is not converted: MX XML text fails" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The MX XML, or JSON with writeInJson, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml", "description": "An MX message, read as UTF-8" }, + "unmarshalOut": { "carriers": [ "pojo", "null" ], "javaType": "com.prowidesoftware.swift.model.mx.AbstractMX", "description": "The Prowide class of the message by its namespace (or readMessageId), such as MxPacs00800108; null when the type is not detected" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "writeInJson": { "index": 1, "kind": "attribute", "displayName": "Write In Json", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to marshal messages in JSON format." }, diff --git a/components/camel-swift/src/main/docs/swiftMt-dataformat.adoc b/components/camel-swift/src/main/docs/swiftMt-dataformat.adoc index c64420eeb40ed..5aac6e7416d50 100644 --- a/components/camel-swift/src/main/docs/swiftMt-dataformat.adoc +++ b/components/camel-swift/src/main/docs/swiftMt-dataformat.adoc @@ -118,6 +118,8 @@ YAML:: == Marshal In this example, we marshal the messages read from a JMS queue in SWIFT format before storing the result into a file. +The body must be a Prowide MT object, such as an `MT103`, as unmarshal gives: it is not converted, so an MT +message as text fails. [tabs] ==== diff --git a/components/camel-swift/src/main/docs/swiftMx-dataformat.adoc b/components/camel-swift/src/main/docs/swiftMx-dataformat.adoc index 74c2a6f52a0f3..fa97d128ddbfe 100644 --- a/components/camel-swift/src/main/docs/swiftMx-dataformat.adoc +++ b/components/camel-swift/src/main/docs/swiftMx-dataformat.adoc @@ -118,6 +118,8 @@ YAML:: == Marshal In this example, we marshal the messages read from a JMS queue in SWIFT format before storing the result into a file. +The body must be a Prowide MX object, such as an `MxPacs00800108`, as unmarshal gives: it is not converted, so an MX +message as text fails. [tabs] ==== diff --git a/components/camel-swift/src/main/java/org/apache/camel/dataformat/swift/mt/SwiftMtDataFormat.java b/components/camel-swift/src/main/java/org/apache/camel/dataformat/swift/mt/SwiftMtDataFormat.java index cca11349775e5..a470cbc9cde87 100644 --- a/components/camel-swift/src/main/java/org/apache/camel/dataformat/swift/mt/SwiftMtDataFormat.java +++ b/components/camel-swift/src/main/java/org/apache/camel/dataformat/swift/mt/SwiftMtDataFormat.java @@ -23,6 +23,9 @@ import com.prowidesoftware.JsonSerializable; import com.prowidesoftware.swift.model.mt.AbstractMT; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.Metadata; @@ -35,6 +38,20 @@ */ @Dataformat("swiftMt") @Metadata(firstVersion = "3.20.0", title = "SWIFT MT") +@BodyTypes(marshalIn = @BodyType(value = Carrier.POJO, javaType = "com.prowidesoftware.swift.model.mt.AbstractMT", + byOption = @BodyType.When(option = "writeInJson", value = "true", carriers = Carrier.POJO, + javaType = "com.prowidesoftware.JsonSerializable"), + description = "A Prowide MT message, such as an MT103, as unmarshal gives. The body is not" + + " converted: MT text fails"), + marshalOut = @BodyType(value = Carrier.STREAM, + description = "The MT message in FIN format, or JSON with writeInJson, in the stream cache," + + " or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "An MT message in FIN format"), + unmarshalOut = @BodyType(value = { Carrier.POJO, Carrier.NULL }, + javaType = "com.prowidesoftware.swift.model.mt.AbstractMT", + description = "The Prowide class of the message type, such as MT103; null when the type is" + + " not known")) public class SwiftMtDataFormat extends ServiceSupport implements DataFormat, DataFormatName { /** diff --git a/components/camel-swift/src/main/java/org/apache/camel/dataformat/swift/mx/SwiftMxDataFormat.java b/components/camel-swift/src/main/java/org/apache/camel/dataformat/swift/mx/SwiftMxDataFormat.java index 16ccb08b4d175..8b9eb67a1a192 100644 --- a/components/camel-swift/src/main/java/org/apache/camel/dataformat/swift/mx/SwiftMxDataFormat.java +++ b/components/camel-swift/src/main/java/org/apache/camel/dataformat/swift/mx/SwiftMxDataFormat.java @@ -26,6 +26,9 @@ import com.prowidesoftware.swift.model.mx.MxReadConfiguration; import com.prowidesoftware.swift.model.mx.MxWriteConfiguration; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.Metadata; @@ -39,6 +42,20 @@ */ @Dataformat("swiftMx") @Metadata(firstVersion = "3.20.0", title = "SWIFT MX") +@BodyTypes(marshalIn = @BodyType(value = Carrier.POJO, javaType = "com.prowidesoftware.swift.model.mx.AbstractMX", + byOption = @BodyType.When(option = "writeInJson", value = "true", carriers = Carrier.POJO, + javaType = "com.prowidesoftware.JsonSerializable"), + description = "A Prowide MX message, such as an MxPacs00800108, as unmarshal gives. The body" + + " is not converted: MX XML text fails"), + marshalOut = @BodyType(value = Carrier.STREAM, + description = "The MX XML, or JSON with writeInJson, in the stream cache, or a byte array" + + " when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "xml", + description = "An MX message, read as UTF-8"), + unmarshalOut = @BodyType(value = { Carrier.POJO, Carrier.NULL }, + javaType = "com.prowidesoftware.swift.model.mx.AbstractMX", + description = "The Prowide class of the message by its namespace (or readMessageId), such" + + " as MxPacs00800108; null when the type is not detected")) public class SwiftMxDataFormat extends ServiceSupport implements DataFormat, DataFormatName { /** * The specific configuration to use when marshalling a message. Ignored if {@code writeInJson} is set to diff --git a/components/camel-syslog/src/generated/resources/META-INF/org/apache/camel/component/syslog/syslog.json b/components/camel-syslog/src/generated/resources/META-INF/org/apache/camel/component/syslog/syslog.json index 8d459f60a63ce..895c8414874fb 100644 --- a/components/camel-syslog/src/generated/resources/META-INF/org/apache/camel/component/syslog/syslog.json +++ b/components/camel-syslog/src/generated/resources/META-INF/org/apache/camel/component/syslog/syslog.json @@ -15,6 +15,12 @@ "modelName": "syslog", "modelJavaType": "org.apache.camel.model.dataformat.SyslogDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "pojo" ], "description": "A SyslogMessage, or the text of a syslog message, which is parsed first. A missing facility, severity, hostname or timestamp gets a default" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The syslog message in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text", "description": "An RFC 3164 or RFC 5424 message, decoded with the charset of the exchange" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.apache.camel.component.syslog.SyslogMessage", "description": "A SyslogMessage, an Rfc5424SyslogMessage for an RFC 5424 message. The facility, severity, hostname and timestamp are headers as well" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" } } diff --git a/components/camel-syslog/src/main/java/org/apache/camel/component/syslog/SyslogDataFormat.java b/components/camel-syslog/src/main/java/org/apache/camel/component/syslog/SyslogDataFormat.java index 8782238b18ec7..005232fba2d84 100644 --- a/components/camel-syslog/src/main/java/org/apache/camel/component/syslog/SyslogDataFormat.java +++ b/components/camel-syslog/src/main/java/org/apache/camel/component/syslog/SyslogDataFormat.java @@ -21,6 +21,9 @@ import java.util.Date; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -28,6 +31,17 @@ import org.apache.camel.support.service.ServiceSupport; @Dataformat("syslog") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.POJO }, + description = "A SyslogMessage, or the text of a syslog message, which is parsed first. A" + + " missing facility, severity, hostname or timestamp gets a default"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "text", + description = "The syslog message in the stream cache, or a byte array when stream caching is" + + " off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "text", + description = "An RFC 3164 or RFC 5424 message, decoded with the charset of the exchange"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "org.apache.camel.component.syslog.SyslogMessage", + description = "A SyslogMessage, an Rfc5424SyslogMessage for an RFC 5424 message. The" + + " facility, severity, hostname and timestamp are headers as well")) public class SyslogDataFormat extends ServiceSupport implements DataFormat, DataFormatName { @Override diff --git a/components/camel-toon/src/generated/resources/META-INF/org/apache/camel/dataformat/toon/toon.json b/components/camel-toon/src/generated/resources/META-INF/org/apache/camel/dataformat/toon/toon.json index 5d2b6d93b885e..1e4df693490da 100644 --- a/components/camel-toon/src/generated/resources/META-INF/org/apache/camel/dataformat/toon/toon.json +++ b/components/camel-toon/src/generated/resources/META-INF/org/apache/camel/dataformat/toon/toon.json @@ -15,6 +15,12 @@ "modelName": "toon", "modelJavaType": "org.apache.camel.model.dataformat.ToonDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "value", "map", "list", "pojo" ], "description": "A Map, a List, a POJO or a value to write as TOON. A String must be JSON text; bytes, a stream or a file are not read as text" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The TOON in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "description": "A Map (LinkedHashMap) for an object, a List for an array; a document that is a single value gives that value" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "indent": { "index": 1, "kind": "attribute", "displayName": "Indent", "group": "common", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 2, "description": "Number of spaces per indentation level." }, diff --git a/components/camel-toon/src/main/java/org/apache/camel/dataformat/toon/ToonDataFormat.java b/components/camel-toon/src/main/java/org/apache/camel/dataformat/toon/ToonDataFormat.java index 33e603cf7e399..649aaec2453e8 100644 --- a/components/camel-toon/src/main/java/org/apache/camel/dataformat/toon/ToonDataFormat.java +++ b/components/camel-toon/src/main/java/org/apache/camel/dataformat/toon/ToonDataFormat.java @@ -33,6 +33,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatContentTypeHeader; import org.apache.camel.spi.DataFormatName; @@ -48,6 +51,15 @@ */ @Dataformat("toon") @Metadata(firstVersion = "4.23.0", title = "TOON") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.VALUE, Carrier.MAP, Carrier.LIST, Carrier.POJO }, + description = "A Map, a List, a POJO or a value to write as TOON. A String must be JSON text;" + + " bytes, a stream or a file are not read as text"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "text", + description = "The TOON in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "text"), + unmarshalOut = @BodyType(value = { Carrier.MAP, Carrier.LIST }, + description = "A Map (LinkedHashMap) for an object, a List for an array; a document that is" + + " a single value gives that value")) public class ToonDataFormat extends ServiceSupport implements DataFormat, DataFormatName, DataFormatContentTypeHeader, CamelContextAware { diff --git a/components/camel-ubl/src/generated/resources/META-INF/org/apache/camel/component/ubl/ubl.json b/components/camel-ubl/src/generated/resources/META-INF/org/apache/camel/component/ubl/ubl.json index 2d96ae90a3f20..d6718b2b065f9 100644 --- a/components/camel-ubl/src/generated/resources/META-INF/org/apache/camel/component/ubl/ubl.json +++ b/components/camel-ubl/src/generated/resources/META-INF/org/apache/camel/component/ubl/ubl.json @@ -15,6 +15,12 @@ "modelName": "ubl", "modelJavaType": "org.apache.camel.model.dataformat.UblDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "description": "A UBL 2.1 document of ph-ubl, such as an InvoiceType or a CreditNoteType: its class name gives the document type. Text fails" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The UBL XML in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml", "description": "A UBL 2.1 document, whose root element gives the document type" }, + "unmarshalOut": { "carriers": [ "pojo" ], "description": "The ph-ubl object of the document type, such as an InvoiceType for an Invoice" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "prettyPrint": { "index": 1, "kind": "attribute", "displayName": "Pretty Print", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable pretty printing (formatted) output of the XML" } diff --git a/components/camel-ubl/src/main/java/org/apache/camel/component/ubl/UblDataFormat.java b/components/camel-ubl/src/main/java/org/apache/camel/component/ubl/UblDataFormat.java index c77c34c42df6c..89b30fa81f8c9 100644 --- a/components/camel-ubl/src/main/java/org/apache/camel/component/ubl/UblDataFormat.java +++ b/components/camel-ubl/src/main/java/org/apache/camel/component/ubl/UblDataFormat.java @@ -31,6 +31,9 @@ import org.apache.camel.CamelContextAware; import org.apache.camel.CamelExchangeException; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.Metadata; @@ -43,6 +46,16 @@ */ @Dataformat("ubl") @Metadata(firstVersion = "4.23.0", title = "UBL") +@BodyTypes(marshalIn = @BodyType(value = Carrier.POJO, + description = "A UBL 2.1 document of ph-ubl, such as an InvoiceType or a CreditNoteType: its" + + " class name gives the document type. Text fails"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "xml", + description = "The UBL XML in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "xml", + description = "A UBL 2.1 document, whose root element gives the document type"), + unmarshalOut = @BodyType(value = Carrier.POJO, + description = "The ph-ubl object of the document type, such as an InvoiceType for an" + + " Invoice")) public class UblDataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private CamelContext camelContext; diff --git a/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityCsv.json b/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityCsv.json index 6660216a3fc08..63f145ca731c2 100644 --- a/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityCsv.json +++ b/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityCsv.json @@ -15,6 +15,12 @@ "modelName": "univocityCsv", "modelJavaType": "org.apache.camel.model.dataformat.UniVocityCsvDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list" ], "description": "One row as a Map, or the rows as a List (or an Iterator) of Maps. Rows that are Lists, as unmarshal gives without asMap, are not accepted" }, + "marshalOut": { "carriers": [ "stream" ], "format": "csv", "description": "The CSV in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "csv" }, + "unmarshalOut": { "carriers": [ "list" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "iterator" ] } ], "description": "A List of the rows, each a List of its values (the first line too, unless headerExtractionEnabled); with asMap, a Map of the header names and the values" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "delimiter": { "index": 1, "kind": "attribute", "displayName": "Delimiter", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": ",", "description": "The delimiter of values." }, diff --git a/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityFixed.json b/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityFixed.json index c1f7ace71e99f..fd9c4a470c4a7 100644 --- a/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityFixed.json +++ b/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityFixed.json @@ -15,6 +15,12 @@ "modelName": "univocityFixed", "modelJavaType": "org.apache.camel.model.dataformat.UniVocityFixedDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list" ], "description": "One row as a Map, or the rows as a List (or an Iterator) of Maps. Rows that are Lists, as unmarshal gives without asMap, are not accepted" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The fixed-width records in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "list" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "iterator" ] } ], "description": "A List of the rows, each a List of its values (the first line too, unless headerExtractionEnabled); with asMap, a Map of the header names and the values" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "padding": { "index": 1, "kind": "attribute", "displayName": "Padding", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The padding character. The default value is a space." }, diff --git a/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityTsv.json b/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityTsv.json index 429d262794370..4d19cfc96af77 100644 --- a/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityTsv.json +++ b/components/camel-univocity-parsers/src/generated/resources/META-INF/org/apache/camel/dataformat/univocity/univocityTsv.json @@ -15,6 +15,12 @@ "modelName": "univocityTsv", "modelJavaType": "org.apache.camel.model.dataformat.UniVocityTsvDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list" ], "description": "One row as a Map, or the rows as a List (or an Iterator) of Maps. Rows that are Lists, as unmarshal gives without asMap, are not accepted" }, + "marshalOut": { "carriers": [ "stream" ], "format": "text", "description": "The TSV in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text" }, + "unmarshalOut": { "carriers": [ "list" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "iterator" ] } ], "description": "A List of the rows, each a List of its values (the first line too, unless headerExtractionEnabled); with asMap, a Map of the header names and the values" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "escapeChar": { "index": 1, "kind": "attribute", "displayName": "Escape Char", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "\\", "description": "The escape character." }, diff --git a/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityCsvDataFormat.java b/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityCsvDataFormat.java index 70611f9d59b83..91b2034c6cb01 100644 --- a/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityCsvDataFormat.java +++ b/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityCsvDataFormat.java @@ -23,12 +23,28 @@ import com.univocity.parsers.csv.CsvParserSettings; import com.univocity.parsers.csv.CsvWriter; import com.univocity.parsers.csv.CsvWriterSettings; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Dataformat; /** * This class is the data format that uses the CSV uniVocity parser. */ @Dataformat("univocityCsv") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.MAP, Carrier.LIST }, + description = "One row as a Map, or the rows as a List (or an Iterator) of Maps. Rows that are" + + " Lists, as unmarshal gives without asMap, are not accepted"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "csv", + description = "The CSV in the stream cache, or a byte array when stream caching" + + " is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "csv"), + unmarshalOut = @BodyType(value = Carrier.LIST, + byOption = @BodyType.When(option = "lazyLoad", value = "true", + carriers = Carrier.ITERATOR), + description = "A List of the rows, each a List of its values (the first line too, unless" + + " headerExtractionEnabled); with asMap, a Map of the header names and" + + " the values")) public class UniVocityCsvDataFormat extends AbstractUniVocityDataFormat { diff --git a/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityFixedDataFormat.java b/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityFixedDataFormat.java index 55b7f3e0e930c..9db99f9550058 100644 --- a/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityFixedDataFormat.java +++ b/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityFixedDataFormat.java @@ -25,12 +25,28 @@ import com.univocity.parsers.fixed.FixedWidthParserSettings; import com.univocity.parsers.fixed.FixedWidthWriter; import com.univocity.parsers.fixed.FixedWidthWriterSettings; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Dataformat; /** * This class is the data format that uses the fixed-width uniVocity parser. */ @Dataformat("univocityFixed") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.MAP, Carrier.LIST }, + description = "One row as a Map, or the rows as a List (or an Iterator) of Maps. Rows that are" + + " Lists, as unmarshal gives without asMap, are not accepted"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "text", + description = "The fixed-width records in the stream cache, or a byte array when stream" + + " caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "text"), + unmarshalOut = @BodyType(value = Carrier.LIST, + byOption = @BodyType.When(option = "lazyLoad", value = "true", + carriers = Carrier.ITERATOR), + description = "A List of the rows, each a List of its values (the first line too, unless" + + " headerExtractionEnabled); with asMap, a Map of the header names and" + + " the values")) public class UniVocityFixedDataFormat extends AbstractUniVocityDataFormat { diff --git a/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityTsvDataFormat.java b/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityTsvDataFormat.java index 33d4bcaea7b77..0c939104d08fb 100644 --- a/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityTsvDataFormat.java +++ b/components/camel-univocity-parsers/src/main/java/org/apache/camel/dataformat/univocity/UniVocityTsvDataFormat.java @@ -23,12 +23,28 @@ import com.univocity.parsers.tsv.TsvParserSettings; import com.univocity.parsers.tsv.TsvWriter; import com.univocity.parsers.tsv.TsvWriterSettings; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Dataformat; /** * This class is the data format that uses the TSV uniVocity parser. */ @Dataformat("univocityTsv") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.MAP, Carrier.LIST }, + description = "One row as a Map, or the rows as a List (or an Iterator) of Maps. Rows that are" + + " Lists, as unmarshal gives without asMap, are not accepted"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "text", + description = "The TSV in the stream cache, or a byte array when stream caching" + + " is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "text"), + unmarshalOut = @BodyType(value = Carrier.LIST, + byOption = @BodyType.When(option = "lazyLoad", value = "true", + carriers = Carrier.ITERATOR), + description = "A List of the rows, each a List of its values (the first line too, unless" + + " headerExtractionEnabled); with asMap, a Map of the header names and" + + " the values")) public class UniVocityTsvDataFormat extends AbstractUniVocityDataFormat { diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java index 557ad7d9b4245..44b57a2428ea8 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java @@ -970,8 +970,8 @@ public void testTheProducersOfTheCatalog() { @Test public void testTheOptionsTheBodyDependsOn() { - // xslt with output DOM gives a Document, an unmarshal with useList a List, gson is not known, and with download - // false the ftp consumer gives no body + // xslt with output DOM gives a Document, an unmarshal with useList a List, gson with an unmarshalType an object + // of that class, and with download false the ftp consumer gives no body String yaml = """ - route: from: @@ -987,6 +987,7 @@ public void testTheOptionsTheBodyDependsOn() { - unmarshal: json: library: Gson + unmarshalType: com.acme.Order - to: file:out - route: from: @@ -1107,6 +1108,54 @@ public void testTheBodyOfTransformations() { .contains("route jolt: to: file needs the body as text, bytes, a stream or a file")); } + @Test + public void testTheBodyOfTextDataFormats() { + // json with Gson and univocityCsv parse the text into a Map or a List, which the file producer cannot write; + // univocityCsv with lazyLoad gives an iterator, and jaxb an object of a class, which say nothing + String yaml = """ + - route: + id: gson + from: + uri: file:in + steps: + - unmarshal: + json: + library: Gson + - to: file:out + - route: + id: rows + from: + uri: file:in + steps: + - unmarshal: + univocityCsv: {} + - to: file:out + - route: + id: lazy + from: + uri: file:in + steps: + - unmarshal: + univocityCsv: + lazyLoad: true + - to: file:out + - route: + id: jaxb + from: + uri: file:in + steps: + - unmarshal: + jaxb: + contextPath: com.acme.model + - to: file:out + """; + assertThat(lines(yaml)).hasSize(2) + .anySatisfy(m -> assertThat(m) + .contains("route gson: to: file needs the body as text, bytes, a stream or a file")) + .anySatisfy(m -> assertThat(m) + .contains("route rows: to: file needs the body as text, bytes, a stream or a file")); + } + @Test public void testAnOptionTheBodyDependsOnOutweighsAnotherOption() { // xslt with output bytes gives bytes, so a field read needs an unmarshal; with a resultHandlerFactory too the From 7d3b8f35796b9d4d8afba0fd9bea8cd694bb303f Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 22 Oct 2026 16:52:11 +0200 Subject: [PATCH 23/25] CAMEL-24961: Catalog body types for the binary data formats Declares the body before and after marshal and unmarshal for the last 20 data formats, so all 56 data formats of the catalog have body types: avro, avroJackson, protobuf, protobufJackson, thrift, cbor, fory, parquetAvro, zipFile, tarFile, gzipDeflater, zipDeflater, lzf, crypto, pgp, pqc, xmlSecurity, barcode, mimeMultipart and smooks. The body after a jackson or jacksonXml unmarshal depends on allowJmsType too. Fixes the doc prose about the body: gzipDeflater writes and reads .gz files, zipDeflater reads any compression level, tarFile is not compressed and its split must be streaming, the CamelFileName of zipFile and tarFile, protobuf and thrift unmarshal need the instanceClass, parquetAvro takes and gives Lists, the mimeMultipart content type, the memory pqc needs, and the XML and YAML examples of the Jackson avro and protobuf data formats give a JsonNode, as the Java ones do. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../camel/catalog/dataformats/avro.json | 6 +++ .../catalog/dataformats/avroJackson.json | 6 +++ .../camel/catalog/dataformats/barcode.json | 6 +++ .../camel/catalog/dataformats/cbor.json | 6 +++ .../camel/catalog/dataformats/crypto.json | 6 +++ .../camel/catalog/dataformats/fory.json | 6 +++ .../catalog/dataformats/gzipDeflater.json | 6 +++ .../camel/catalog/dataformats/jackson.json | 2 +- .../camel/catalog/dataformats/jacksonXml.json | 2 +- .../apache/camel/catalog/dataformats/lzf.json | 6 +++ .../catalog/dataformats/mimeMultipart.json | 6 +++ .../catalog/dataformats/parquetAvro.json | 6 +++ .../apache/camel/catalog/dataformats/pgp.json | 6 +++ .../apache/camel/catalog/dataformats/pqc.json | 6 +++ .../camel/catalog/dataformats/protobuf.json | 6 +++ .../catalog/dataformats/protobufJackson.json | 6 +++ .../camel/catalog/dataformats/smooks.json | 6 +++ .../camel/catalog/dataformats/tarFile.json | 6 +++ .../camel/catalog/dataformats/thrift.json | 6 +++ .../catalog/dataformats/xmlSecurity.json | 6 +++ .../catalog/dataformats/zipDeflater.json | 6 +++ .../camel/catalog/dataformats/zipFile.json | 6 +++ .../catalog/docs/avroJackson2-dataformat.adoc | 3 +- .../catalog/docs/avroJackson3-dataformat.adoc | 3 +- .../catalog/docs/gzipDeflater-dataformat.adoc | 6 ++- .../docs/mimeMultipart-dataformat.adoc | 4 +- .../catalog/docs/parquetAvro-dataformat.adoc | 4 +- .../camel/catalog/docs/pqc-dataformat.adoc | 4 +- .../catalog/docs/protobuf-dataformat.adoc | 7 ++- .../docs/protobufJackson2-dataformat.adoc | 3 +- .../docs/protobufJackson3-dataformat.adoc | 3 +- .../catalog/docs/tarFile-dataformat.adoc | 20 +++++---- .../camel/catalog/docs/thrift-dataformat.adoc | 3 +- .../catalog/docs/zipDeflater-dataformat.adoc | 5 +-- .../catalog/docs/zipFile-dataformat.adoc | 2 +- .../apache/camel/dataformat/avro/avro.json | 6 +++ .../camel/dataformat/avro/AvroDataFormat.java | 18 ++++++++ .../camel/dataformat/barcode/barcode.json | 6 +++ .../dataformat/barcode/BarcodeDataFormat.java | 15 +++++++ .../org/apache/camel/component/cbor/cbor.json | 6 +++ .../camel/component/cbor/CBORDataFormat.java | 16 +++++++ .../apache/camel/converter/crypto/pgp.json | 6 +++ .../camel/converter/crypto/PGPDataFormat.java | 15 +++++++ .../apache/camel/converter/crypto/crypto.json | 6 +++ .../converter/crypto/CryptoDataFormat.java | 15 +++++++ .../org/apache/camel/component/fory/fory.json | 6 +++ .../camel/component/fory/ForyDataFormat.java | 15 +++++++ .../component/jackson/avro/avroJackson.json | 6 +++ .../main/docs/avroJackson2-dataformat.adoc | 3 +- .../jackson/avro/JacksonAvroDataFormat.java | 17 ++++++++ .../jackson/protobuf/protobufJackson.json | 6 +++ .../docs/protobufJackson2-dataformat.adoc | 3 +- .../protobuf/JacksonProtobufDataFormat.java | 18 ++++++++ .../camel/component/jackson/jackson.json | 2 +- .../component/jackson/JacksonDataFormat.java | 2 +- .../main/docs/avroJackson3-dataformat.adoc | 3 +- .../docs/protobufJackson3-dataformat.adoc | 3 +- .../component/jacksonxml/jacksonXml.json | 2 +- .../jacksonxml/JacksonXMLDataFormat.java | 2 +- .../org/apache/camel/dataformat/lzf/lzf.json | 6 +++ .../camel/dataformat/lzf/LZFDataFormat.java | 13 ++++++ .../mime/multipart/mimeMultipart.json | 6 +++ .../main/docs/mimeMultipart-dataformat.adoc | 4 +- .../multipart/MimeMultipartDataFormat.java | 23 ++++++++++ .../dataformat/parquet/avro/parquetAvro.json | 6 +++ .../src/main/docs/parquetAvro-dataformat.adoc | 4 +- .../parquet/avro/ParquetAvroDataFormat.java | 17 ++++++++ .../camel/component/pqc/dataformat/pqc.json | 6 +++ .../src/main/docs/pqc-dataformat.adoc | 4 +- .../pqc/dataformat/PQCDataFormat.java | 13 ++++++ .../camel/dataformat/protobuf/protobuf.json | 6 +++ .../src/main/docs/protobuf-dataformat.adoc | 7 ++- .../protobuf/ProtobufDataFormat.java | 20 +++++++++ .../camel/dataformat/smooks/smooks.json | 6 +++ .../dataformat/smooks/SmooksDataFormat.java | 19 ++++++++ .../camel/dataformat/tarfile/tarFile.json | 6 +++ .../src/main/docs/tarFile-dataformat.adoc | 20 +++++---- .../dataformat/tarfile/TarFileDataFormat.java | 22 ++++++++++ .../camel/dataformat/thrift/thrift.json | 6 +++ .../src/main/docs/thrift-dataformat.adoc | 3 +- .../dataformat/thrift/ThriftDataFormat.java | 29 +++++++++++++ .../dataformat/xmlsecurity/xmlSecurity.json | 6 +++ .../xmlsecurity/XMLSecurityDataFormat.java | 18 ++++++++ .../dataformat/deflater/gzipDeflater.json | 6 +++ .../dataformat/deflater/zipDeflater.json | 6 +++ .../main/docs/gzipDeflater-dataformat.adoc | 6 ++- .../src/main/docs/zipDeflater-dataformat.adoc | 5 +-- .../deflater/GzipDeflaterDataFormat.java | 15 +++++++ .../deflater/ZipDeflaterDataFormat.java | 15 +++++++ .../camel/dataformat/zipfile/zipFile.json | 6 +++ .../src/main/docs/zipFile-dataformat.adoc | 2 +- .../dataformat/zipfile/ZipFileDataFormat.java | 20 +++++++++ .../dsl/yaml/validator/TextBodyFlowTest.java | 43 +++++++++++++++++++ 93 files changed, 716 insertions(+), 66 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/avro.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/avro.json index 58f2269f6f69c..9d4dc3970e309 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/avro.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/avro.json @@ -15,6 +15,12 @@ "modelName": "avro", "modelJavaType": "org.apache.camel.model.dataformat.AvroDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "description": "An Avro record: an object of a class the Avro compiler generated, or a GenericRecord of the schema of instanceClassName. Without instanceClassName the schema comes from the class of the body, so a GenericRecord fails. A Map is not converted" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The record in Avro binary encoding, without the schema (not an Avro container file), in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "One record in Avro binary encoding, as marshal writes it: unmarshal fails without instanceClassName (or a schema set in Java)" }, + "unmarshalOut": { "carriers": [ "pojo" ], "description": "An object of the class instanceClassName names; a GenericRecord when a schema set in Java has no class on the classpath" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "instanceClassName": { "index": 1, "kind": "attribute", "displayName": "Instance Class Name", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Class name to use for marshal and unmarshalling." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/avroJackson.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/avroJackson.json index 5566c435d41b7..d33b64b316a89 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/avroJackson.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/avroJackson.json @@ -15,6 +15,12 @@ "modelName": "avro", "modelJavaType": "org.apache.camel.model.dataformat.AvroDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list", "pojo" ], "description": "A POJO, a Map or a JsonNode to write with the Avro schema of the schemaResolver, or a List for an array schema. A String or bytes are not written as they are" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The Avro binary data, without the schema, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Avro binary data of the schema of the schemaResolver. A String fails" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType", "allowJmsType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) for an Avro record, a List (ArrayList) for an array; an object of the class unmarshalType names, such as JsonNode" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "objectMapper": { "index": 1, "kind": "attribute", "displayName": "Object Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing ObjectMapper with the given id when using Jackson." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/barcode.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/barcode.json index 0614e200145b5..df4e573fc7f17 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/barcode.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/barcode.json @@ -15,6 +15,12 @@ "modelName": "barcode", "modelJavaType": "org.apache.camel.model.dataformat.BarcodeDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text", "description": "The text to encode: bytes, a stream or a file are read in the charset of the exchange. It must suit the barcodeFormat, such as digits only for EAN-13" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The image of the barcode, a PNG unless imageType is JPG or GIF, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "An image ImageIO reads, such as PNG, JPEG or GIF, of any barcode format ZXing reads, whatever barcodeFormat is" }, + "unmarshalOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "format": "text", "description": "The text of the barcode, with the format found in the BarcodeFormat header and the ZXing result metadata, such as ORIENTATION, as headers" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "barcodeFormat": { "index": 1, "kind": "attribute", "displayName": "Barcode Format", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "AZTEC", "CODABAR", "CODE_39", "CODE_93", "CODE_128", "DATA_MATRIX", "EAN_8", "EAN_13", "ITF", "MAXICODE", "PDF_417", "QR_CODE", "RSS_14", "RSS_EXPANDED", "UPC_A", "UPC_E", "UPC_EAN_EXTENSION" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "QR_CODE", "description": "Barcode format such as QR-Code." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/cbor.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/cbor.json index c988a717c0293..f2182f1488ff7 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/cbor.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/cbor.json @@ -15,6 +15,12 @@ "modelName": "cbor", "modelJavaType": "org.apache.camel.model.dataformat.CBORDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list", "pojo" ], "description": "A Map, a List or a POJO to write as CBOR. A String or bytes are written as one CBOR text or byte string, not as they are" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The CBOR data in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "CBOR data. A String fails" }, + "unmarshalOut": { "carriers": [ "pojo" ], "dependsOn": [ "collectionType", "allowUnmarshallType", "allowJmsType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "An object of the class unmarshalType names, such as java.util.Map: unmarshal fails without unmarshalType" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "objectMapper": { "index": 1, "kind": "attribute", "displayName": "Object Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing CBOR ObjectMapper with the given id when using Jackson." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/crypto.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/crypto.json index 455c88df0988a..026c69bddd49e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/crypto.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/crypto.json @@ -15,6 +15,12 @@ "modelName": "crypto", "modelJavaType": "org.apache.camel.model.dataformat.CryptoDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The bytes to encrypt: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The encrypted data in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Encrypted data as marshal writes it, with the same inline and shouldAppendHMAC settings" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decrypted bytes in the stream cache, or a byte array when stream caching is off" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "algorithm": { "index": 1, "kind": "attribute", "displayName": "Algorithm", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The JCE algorithm name indicating the cryptographic algorithm that will be used." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fory.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fory.json index 405ce1ab75770..f177fcd03ad61 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fory.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/fory.json @@ -15,6 +15,12 @@ "modelName": "fory", "modelJavaType": "org.apache.camel.model.dataformat.ForyDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list", "pojo" ], "description": "An object of the unmarshalType class, or a List, a Map or another type Fory registers itself; another class only with requireClassRegistration false. A String or bytes are serialized as objects, not written as they are" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The Fory binary data in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Fory binary data, as marshal writes it" }, + "unmarshalOut": { "carriers": [ "unknown" ], "description": "The object marshal wrote, of the class in the data: unmarshalType only registers a class and does not convert the result" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "unmarshalType": { "index": 1, "kind": "attribute", "displayName": "Unmarshal Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Class of the java type to use when unmarshalling" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/gzipDeflater.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/gzipDeflater.json index ef97b73d91259..0b4becc027ec8 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/gzipDeflater.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/gzipDeflater.json @@ -15,6 +15,12 @@ "modelName": "gzipDeflater", "modelJavaType": "org.apache.camel.model.dataformat.GzipDeflaterDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data to compress: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The gzip data, as in a .gz file, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Gzip data, such as a .gz file; gzip members one after the other are read as one" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decompressed data in the stream cache, or a byte array when stream caching is off" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" } } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jackson.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jackson.json index 36de62e80cf39..09e670b682e82 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jackson.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jackson.json @@ -19,7 +19,7 @@ "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as JSON. Text, bytes or a stream that is JSON already is written as it is" }, "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, - "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) for a JSON object, a List (ArrayList) for an array; an object of the class unmarshalType names" } + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType", "allowJmsType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) for a JSON object, a List (ArrayList) for an array; an object of the class unmarshalType names" } }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jacksonXml.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jacksonXml.json index e01c38e3002ee..2d1e6bd0fe518 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jacksonXml.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/jacksonXml.json @@ -19,7 +19,7 @@ "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as XML. Text is written as an XML value, not as it is" }, "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The XML in the stream cache, or a byte array when stream caching is off" }, "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml" }, - "unmarshalOut": { "carriers": [ "map" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) of the XML; an object of the class unmarshalType names" } + "unmarshalOut": { "carriers": [ "map" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType", "allowJmsType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) of the XML; an object of the class unmarshalType names" } }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/lzf.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/lzf.json index 17164c16d1e96..664ef6a95ffc5 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/lzf.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/lzf.json @@ -15,6 +15,12 @@ "modelName": "lzf", "modelJavaType": "org.apache.camel.model.dataformat.LZFDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data to compress: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The LZF data in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "LZF data, such as marshal gives, with or without usingParallelCompression" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decompressed data in the stream cache, or a byte array when stream caching is off" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "usingParallelCompression": { "index": 1, "kind": "attribute", "displayName": "Using Parallel Compression", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable encoding (compress) using multiple processing cores." } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/mimeMultipart.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/mimeMultipart.json index df18b27b46bb0..abc8a7181cfcb 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/mimeMultipart.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/mimeMultipart.json @@ -15,6 +15,12 @@ "modelName": "mimeMultipart", "modelJavaType": "org.apache.camel.model.dataformat.MimeMultipartDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The body of the first part, of the content type in the Content-Type header (application\/octet-stream when not set); the attachments of the message are the other parts" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The MIME multipart in the stream cache, or a byte array when stream caching is off, with its MIME headers as Camel headers unless headersInline is true. Without attachments the body is written as it is, unless multipartWithoutAttachment or headersInline is true" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "A MIME multipart, with its Content-Type (multipart\/*) and MIME-Version as Camel headers, as marshal leaves them; with headersInline, the MIME headers are at the start of the body" }, + "unmarshalOut": { "carriers": [ "stream" ], "byOption": [ { "option": "headersInline", "value": "true", "carriers": [ "stream", "unchanged" ] } ], "description": "The first part, decoded, as a stream, with the other parts as attachments and its Content-Type as a header. Without a multipart Content-Type header the body is given back as a stream; with headersInline, a body that is not a multipart stays as it was" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "multipartSubType": { "index": 1, "kind": "attribute", "displayName": "Multipart Sub Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "mixed", "description": "Specify the subtype of the MIME Multipart." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/parquetAvro.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/parquetAvro.json index db9480d27935e..008c2efc3b87f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/parquetAvro.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/parquetAvro.json @@ -15,6 +15,12 @@ "modelName": "parquetAvro", "modelJavaType": "org.apache.camel.model.dataformat.ParquetAvroDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "list" ], "description": "A List of Avro GenericRecords, or of objects of the class unmarshalType names. A single record fails, and so does an empty List without unmarshalType" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The Parquet file in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "A Parquet file, which is read into memory" }, + "unmarshalOut": { "carriers": [ "list" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "iterator" ] } ], "description": "A List (ArrayList) of the records: GenericRecords, or objects of the class unmarshalType names. With lazyLoad, an Iterator of them for the split EIP" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "compressionCodecName": { "index": 1, "kind": "attribute", "displayName": "Compression Codec Name", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "UNCOMPRESSED", "SNAPPY", "GZIP", "LZO", "BROTLI", "LZ4", "ZSTD", "LZ4_RAW" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "GZIP", "description": "Compression codec to use when marshalling." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/pgp.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/pgp.json index 78b19aa674a63..516d48cf50eb8 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/pgp.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/pgp.json @@ -15,6 +15,12 @@ "modelName": "pgp", "modelJavaType": "org.apache.camel.model.dataformat.PGPDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data to encrypt: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The PGP message in the stream cache, or a byte array when stream caching is off: binary, or ASCII armored text when armored is true" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "A PGP message, binary or ASCII armored: the armor is detected, whatever armored is set to" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decrypted data in the stream cache, or a byte array when stream caching is off" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "keyUserid": { "index": 1, "kind": "attribute", "displayName": "Key Userid", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The user ID of the key in the PGP keyring used during encryption. Can also be only a part of a user ID." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/pqc.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/pqc.json index dabdf55ea63af..d8114a080b7b4 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/pqc.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/pqc.json @@ -15,6 +15,12 @@ "modelName": "pqc", "modelJavaType": "org.apache.camel.model.dataformat.PQCDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data to encrypt, read whole into memory: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The encrypted message in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "An encrypted message as marshal writes it" }, + "unmarshalOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The decrypted data, as a byte array" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "keyEncapsulationAlgorithm": { "index": 1, "kind": "attribute", "displayName": "Key Encapsulation Algorithm", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLKEM", "BIKE", "HQC", "CMCE", "SABER", "FRODO", "NTRU", "NTRULPRime", "SNTRUPrime", "KYBER" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MLKEM", "description": "The Post-Quantum KEM algorithm to use for key encapsulation." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/protobuf.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/protobuf.json index d7236b51496f2..11e96da6003b1 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/protobuf.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/protobuf.json @@ -15,6 +15,12 @@ "modelName": "protobuf", "modelJavaType": "org.apache.camel.model.dataformat.ProtobufDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo", "map" ], "description": "A protobuf Message of a generated class, or a Map of the fields of the instanceClass message, which needs instanceClass. JSON text is not converted" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The protobuf binary data, or JSON with contentTypeFormat json, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "byOption": [ { "option": "contentTypeFormat", "value": "json", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "Protobuf binary data, or JSON with contentTypeFormat json: unmarshal fails without instanceClass" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "com.google.protobuf.Message", "description": "The generated class of instanceClass, such as AddressBookProtos$Person; convertBodyTo Map gives its fields" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "instanceClass": { "index": 1, "kind": "attribute", "displayName": "Instance Class", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of class to use when unmarshalling." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/protobufJackson.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/protobufJackson.json index 21fcffd762504..69b59c80abd0e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/protobufJackson.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/protobufJackson.json @@ -15,6 +15,12 @@ "modelName": "protobuf", "modelJavaType": "org.apache.camel.model.dataformat.ProtobufDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "pojo" ], "description": "A POJO, a Map or a JsonNode to write as the message of the protobuf schema of the schemaResolver. Text, bytes or a stream are written as they are, not encoded" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The protobuf binary data in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Protobuf binary data of the schema of the schemaResolver. A String fails" }, + "unmarshalOut": { "carriers": [ "map" ], "dependsOn": [ "unmarshalType", "collectionType", "useList", "allowUnmarshallType", "allowJmsType" ], "description": "A Map (LinkedHashMap) of the fields of the message; an object of the class unmarshalType names, such as JsonNode" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "objectMapper": { "index": 1, "kind": "attribute", "displayName": "Object Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing ObjectMapper with the given id when using Jackson." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/smooks.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/smooks.json index 1b47b2463d9f0..394866d941986 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/smooks.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/smooks.json @@ -15,6 +15,12 @@ "modelName": "smooks", "modelJavaType": "org.apache.camel.model.dataformat.SmooksDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list", "pojo" ], "description": "A Java object graph, such as the beans unmarshal gives, which Smooks reads as a JavaSource. Text, bytes or a stream are not parsed: Smooks reads them as a Java object too" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The text Smooks writes in UTF-8, such as the XML of the object graph or the output of a template of the config, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data the reader of the smooks config reads: XML by default, or EDI, CSV or JSON with a reader" }, + "unmarshalOut": { "carriers": [ "unknown" ], "description": "What the exports of the smooks config give: the bean a JavaSink export extracts (a Map of the beans when it extracts several or none), the text of a StringSink, or a List of the results of several exports (empty without exports)" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "smooksConfig": { "index": 1, "kind": "attribute", "displayName": "Smooks Config", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Path to the Smooks configuration file." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/tarFile.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/tarFile.json index e8de72f7835f4..c18e1f82a8231 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/tarFile.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/tarFile.json @@ -15,6 +15,12 @@ "modelName": "tarFile", "modelJavaType": "org.apache.camel.model.dataformat.TarFileDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The content of the one entry: text, bytes, a stream or a file. The entry size is the CamelFileLength header, or else what the stream has available, and must match the content" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The tar file, not compressed, in the stream cache, or a byte array when stream caching is off. The CamelFileName header is the entry name with .tar" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "A tar file with one entry, or with several when usingIterator. A .tar.gz is unmarshalled with gzipDeflater first" }, + "unmarshalOut": { "carriers": [ "stream" ], "byOption": [ { "option": "usingIterator", "value": "true", "carriers": [ "iterator" ], "javaType": "org.apache.camel.dataformat.tarfile.TarIterator" } ], "description": "The content of the one entry in the stream cache, or a byte array when stream caching is off; a tar with more entries, a folder too, fails. With usingIterator, an Iterator for a streaming split EIP: of messages whose body streams one file of the archive, to read before the next" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "usingIterator": { "index": 1, "kind": "attribute", "displayName": "Using Iterator", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use an iterator to split tar entries when the tar file has more than one entry, for use with the splitter EIP in streaming mode." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/thrift.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/thrift.json index 5c23c04979263..616ce922f40b5 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/thrift.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/thrift.json @@ -15,6 +15,12 @@ "modelName": "thrift", "modelJavaType": "org.apache.camel.model.dataformat.ThriftDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "org.apache.thrift.TBase", "description": "An object of a class the Thrift compiler generated, as unmarshal gives. The body is not converted: other bodies fail" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The Thrift binary data, or JSON with contentTypeFormat json or sjson, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "dependsOn": [ "contentTypeFormat" ], "byOption": [ { "option": "contentTypeFormat", "value": "binary", "carriers": [ "bytes", "stream", "file" ] }, { "option": "contentTypeFormat", "value": "json", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "Thrift binary data, or with contentTypeFormat json the Thrift JSON protocol (field ids and types) as marshal writes it. sjson is for marshal only" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.apache.thrift.TBase", "dependsOn": [ "contentTypeFormat" ], "byOption": [ { "option": "contentTypeFormat", "value": "binary", "carriers": [ "pojo" ], "javaType": "org.apache.thrift.TBase" }, { "option": "contentTypeFormat", "value": "json", "carriers": [ "pojo" ], "javaType": "org.apache.thrift.TBase" } ], "description": "An object of the class instanceClass names: unmarshal fails without it" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "instanceClass": { "index": 1, "kind": "attribute", "displayName": "Instance Class", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of class to use when unmarshalling." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/xmlSecurity.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/xmlSecurity.json index 807dbb9586178..f83608db4ae07 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/xmlSecurity.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/xmlSecurity.json @@ -15,6 +15,12 @@ "modelName": "xmlSecurity", "modelJavaType": "org.apache.camel.model.dataformat.XMLSecurityDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "The XML: text, bytes, a stream, a file, a DOM Document, a DOMSource or a StreamSource" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The XML with EncryptedData elements, in the stream cache, or a byte array when stream caching is off. Without secureTag the whole document is encrypted; with it the elements it selects, or their content when secureTagContents is true" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "The XML with EncryptedData elements: text, bytes, a stream, a file, a DOM Document, a DOMSource or a StreamSource" }, + "unmarshalOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "format": "xml", "description": "The decrypted XML document, as a byte array" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "xmlCipherAlgorithm": { "index": 1, "kind": "attribute", "displayName": "Xml Cipher Algorithm", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "TRIPLEDES", "AES_128", "AES_128_GCM", "AES_192", "AES_192_GCM", "AES_256", "AES_256_GCM", "SEED_128", "CAMELLIA_128", "CAMELLIA_192", "CAMELLIA_256" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "AES_256_GCM", "description": "The cipher algorithm to be used for encryption\/decryption of the XML message content." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/zipDeflater.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/zipDeflater.json index a5c9ee1b7475f..5415be8522b7e 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/zipDeflater.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/zipDeflater.json @@ -15,6 +15,12 @@ "modelName": "zipDeflater", "modelJavaType": "org.apache.camel.model.dataformat.ZipDeflaterDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data to compress: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The deflate data in the zlib format, not a zip file, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Deflate data in the zlib format, such as marshal gives with any compressionLevel" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decompressed data in the stream cache, or a byte array when stream caching is off" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "compressionLevel": { "index": 1, "kind": "attribute", "displayName": "Compression Level", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.Integer", "enum": [ "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "-1", "description": "Compression level to use (0-9). -1 is default compression, 0 is no compression, and 9 is the best compression." } diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/zipFile.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/zipFile.json index fc77b1a60e734..4f10e3ce1307d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/zipFile.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/zipFile.json @@ -15,6 +15,12 @@ "modelName": "zipFile", "modelJavaType": "org.apache.camel.model.dataformat.ZipFileDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The content of the one entry: text in the charset of the exchange, bytes, a stream or a file. The entry name is the file name of the CamelFileName header (its whole path with preservePathElements), or the message id" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The zip file in the stream cache, or a byte array when stream caching is off. The CamelFileName header is the entry name with .zip" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "A zip file with one entry, or with several when usingIterator" }, + "unmarshalOut": { "carriers": [ "stream" ], "byOption": [ { "option": "usingIterator", "value": "true", "carriers": [ "iterator" ], "javaType": "org.apache.camel.dataformat.zipfile.ZipIterator" } ], "description": "The content of the one entry in the stream cache, or a byte array when stream caching is off; a zip with more entries, a folder too, fails. With usingIterator, an Iterator for the split EIP: of messages with the content of one file each, in a stream cache" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "usingIterator": { "index": 1, "kind": "attribute", "displayName": "Using Iterator", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the zip file has more than one entry, the setting this option to true, allows working with the splitter EIP, to split the data using an iterator in a streaming mode." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/avroJackson2-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/avroJackson2-dataformat.adoc index b399745171b57..d67ac24b3407d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/avroJackson2-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/avroJackson2-dataformat.adoc @@ -38,7 +38,7 @@ XML:: ---- - + ---- @@ -54,6 +54,7 @@ YAML:: - unmarshal: avro: library: Jackson + unmarshalType: com.fasterxml.jackson.databind.JsonNode - to: uri: log:info ---- diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/avroJackson3-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/avroJackson3-dataformat.adoc index 86d1ed6302af1..ba20549e7390a 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/avroJackson3-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/avroJackson3-dataformat.adoc @@ -38,7 +38,7 @@ XML:: ---- - + ---- @@ -54,6 +54,7 @@ YAML:: - unmarshal: avro: library: Jackson + unmarshalType: tools.jackson.databind.JsonNode - to: uri: log:info ---- diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/gzipDeflater-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/gzipDeflater-dataformat.adoc index aeffae59cc68a..741a2bf4c8df4 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/gzipDeflater-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/gzipDeflater-dataformat.adoc @@ -21,8 +21,10 @@ using `gzip` tool. [NOTE] ==== -This dataformat is not for working with gzip files such as uncompressing and building gzip files. -Instead, use the xref:dataformats:zipFile-dataformat.adoc[zipfile] dataformat. +Marshal writes the gzip format of a `.gz` file, and unmarshal reads it, so this data format builds and uncompresses +gzip files. A `.tar.gz` file is a tar archive in gzip: unmarshal it with gzipDeflater, then with the +xref:dataformats:tarFile-dataformat.adoc[tarFile] data format. For zip files, use the +xref:dataformats:zipFile-dataformat.adoc[zipFile] data format. ==== == Options diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mimeMultipart-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mimeMultipart-dataformat.adoc index 9b5318b2267cb..a88c92a270fe0 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mimeMultipart-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mimeMultipart-dataformat.adoc @@ -66,8 +66,8 @@ version (1.0) if the "headersInline" parameter is set to false. |Content-Type |String |The content of this header will be used as a content type for the message body part. If no content type is set, "application/octet-stream" is assumed. After the marshal operation, the content type is set to -"multipart/related" or empty if the "headersInline" parameter is set to -true. +"multipart/" with the "multipartSubType" ("multipart/mixed" by default), or empty +if the "headersInline" parameter is set to true. |Content-Encoding |String |If the incoming content type is "text/*" the content encoding will be set to the encoding parameter of the Content-Type MIME header of the diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/parquetAvro-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/parquetAvro-dataformat.adoc index c53eb43e4b87e..c2166b39675fc 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/parquetAvro-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/parquetAvro-dataformat.adoc @@ -27,7 +27,7 @@ include::partial$dataformat-options.adoc[] There are ways to unmarshal parquet files/structures, usually binary parquet files, where camel DSL allows. -In this first example we unmarshal file payload to OutputStream and send it to mock endpoint, then we will be able to get GenericRecord or POJO (it could be a list if that is coming through) +In this first example we unmarshal file payload to a List of the records and send it to mock endpoint: GenericRecords, or POJOs with `unmarshalType`. With `lazyLoad`, the body is an Iterator of them instead. [tabs] ==== @@ -58,7 +58,7 @@ With `unmarshalType`, the records are objects of that class. Without it, they ar == Marshal -Marshalling is the reverse process of unmarshalling, so when you have your `GenericRecord` or POJO and marshal it, you will get the parquet-formatted output stream on your producer endpoint. +Marshalling is the reverse process of unmarshalling, so when you have a List of `GenericRecord` objects or POJOs and marshal it, you will get the parquet-formatted output stream on your producer endpoint. A single record that is not in a List fails. [tabs] ==== diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/pqc-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/pqc-dataformat.adoc index b8bd8cf22697a..e983435fe9221 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/pqc-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/pqc-dataformat.adoc @@ -417,7 +417,7 @@ A KEM `KeyGenerator` keeps the spec passed to `init()` until `generateKey()` rea **2. Large Payloads** -To guarantee integrity, the authenticated (AEAD) cipher verifies the authentication tag before releasing any plaintext, so the payload is processed as a whole rather than incrementally. Enable stream caching to let Camel spill large bodies to disk on the route: +To guarantee integrity, the authenticated (AEAD) cipher verifies the authentication tag before releasing any plaintext, so the payload is processed as a whole rather than incrementally. Marshal and unmarshal hold the whole plaintext and the whole ciphertext in memory as byte arrays, so the payload must fit in memory, about twice over; stream caching does not change that. Stream caching only keeps the marshalled result for the next steps, and spills it to disk with `spoolEnabled`: ._Java-only: stream caching large files with PQCDataFormat_ [source,java] @@ -481,7 +481,7 @@ Security.addProvider(new BouncyCastlePQCProvider()); **Issue**: OutOfMemoryError with large files -* **Solution**: Authenticated (AEAD) encryption processes the payload as a whole; enable stream caching so Camel spills large bodies to disk: +* **Solution**: Authenticated (AEAD) encryption processes the payload as a whole, in memory: give the JVM enough heap for about twice the payload, or split large files into smaller messages. Stream caching only keeps the marshalled result for the next steps: + ._Java-only: enabling stream caching for large files_ [source,java] diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobuf-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobuf-dataformat.adoc index 210acbe359f46..f70031acabe07 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobuf-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobuf-dataformat.adoc @@ -37,7 +37,7 @@ include::partial$dataformat-options.adoc[] It's possible to parse JSON message to convert it to the protobuf format and unparse it back using native util converter. To use this option, set contentTypeFormat value to `json` or call protobuf with second parameter. -If the default instance is not specified, always use the native protobuf format. +Unmarshal needs the default instance (`instanceClass`) in both formats; marshal writes the given `Message` in either. The sample code shows below: ._Java-only: programmatic protobuf configuration with content type format_ @@ -59,9 +59,8 @@ do so, it will fall back to retrieve it as proto `Message`. As mentioned above, you can define the content type format to choose from JSON or native to serialize/deserialize data from/to. In addition, you can also obtain the data as `Map` and let this component do the heavy lifting to parse the -data from proto `Message` to `Map`, -you will need to set the `contentTypeFormat` to `native` -and explicitly define the data type `Map` when you get body of the exchange. +data from proto `Message` to `Map`, in either `contentTypeFormat`, +by explicitly defining the data type `Map` when you get body of the exchange. For instance: `exchange.getMessage().getBody(Map.class)`. In the `Map`, the value of a `bytes` field is a `byte[]`; when a `Map` is converted to a message, a `bytes` field takes a `byte[]` (or a `ByteString`). diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobufJackson2-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobufJackson2-dataformat.adoc index 5a24229148d7f..63984745ada54 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobufJackson2-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobufJackson2-dataformat.adoc @@ -38,7 +38,7 @@ XML:: ---- - + ---- @@ -54,6 +54,7 @@ YAML:: - unmarshal: protobuf: library: Jackson + unmarshalType: com.fasterxml.jackson.databind.JsonNode - to: uri: log:info ---- diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobufJackson3-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobufJackson3-dataformat.adoc index 54928ce6fbd09..0c0d61a182b9d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobufJackson3-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/protobufJackson3-dataformat.adoc @@ -38,7 +38,7 @@ XML:: ---- - + ---- @@ -54,6 +54,7 @@ YAML:: - unmarshal: protobuf: library: Jackson + unmarshalType: tools.jackson.databind.JsonNode - to: uri: log:info ---- diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/tarFile-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/tarFile-dataformat.adoc index 208d3d504277e..ac5a5cf9268d6 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/tarFile-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/tarFile-dataformat.adoc @@ -9,10 +9,11 @@ *Since Camel {since}* -The Tar File Data Format is a message compression -and decompression format. Messages can be marshalled (compressed) to -Tar Files containing a single entry, and Tar Files containing a single -entry can be unmarshalled (decompressed) to the original file contents. +The Tar File Data Format is a message archiving format. Messages can be +marshalled to Tar Files containing a single entry, and Tar Files containing a +single entry can be unmarshalled to the original file contents. The Tar File +is not compressed: for a `.tar.gz`, marshal it with the +xref:dataformats:gzipDeflater-dataformat.adoc[gzipDeflater] data format as well. There is also an aggregation strategy that can aggregate multiple messages into a single Tar File. @@ -27,9 +28,8 @@ include::partial$dataformat-options.adoc[] == Marshal -In this example, we marshal a regular text/XML payload to a compressed -payload using Tar File compression, and send it to an ActiveMQ queue -called MY_QUEUE. +In this example, we marshal a regular text/XML payload to a Tar File +payload, and send it to an ActiveMQ queue called MY_QUEUE. [tabs] ==== @@ -74,7 +74,7 @@ The name of the Tar entry inside the created Tar File is based on the incoming `CamelFileName` message header, which is the standard message header used by the file component. Additionally, the outgoing `CamelFileName` message header is automatically set to the -value of the incoming `CamelFileName` message header, with the ".tar" +file name of the incoming `CamelFileName` message header, without its path, with the ".tar" suffix. So, for example, if the following route finds a file named "test.txt" in the input directory, the output will be a Tar File named "test.txt.tar" containing a single Tar entry named "test.txt": @@ -219,7 +219,9 @@ like this .end(); ---- -IMPORTANT: You cannot use TarSplitter in _parallel_ mode with the splitter. +IMPORTANT: You cannot use TarSplitter in _parallel_ mode with the splitter. The splitter must be _streaming_ too: the +body of each message streams its entry from the Tar File, which is read on as the splitter goes, so a splitter that +is not streaming gives messages with empty bodies. == Aggregate diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/thrift-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/thrift-dataformat.adoc index 5fe872609a507..dcdf08c4e9441 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/thrift-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/thrift-dataformat.adoc @@ -28,7 +28,8 @@ include::partial$dataformat-options.adoc[] It's possible to parse JSON message to convert it to the Thrift format and serialize it back using native util converter. To use this option, set contentTypeFormat value to 'json' or call thrift with second parameter. -If the default instance is not specified, always use the native binary Thrift format. +Unmarshal needs the default instance (`instanceClass`) in the binary and json formats; marshal writes the given Thrift +object in any of them. The simple JSON format is write-only (marshal) and produces a simple output format suitable for parsing by scripting languages. The sample code shows below: diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/zipDeflater-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/zipDeflater-dataformat.adoc index 2f1b58ac3100c..3e6b7b91df176 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/zipDeflater-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/zipDeflater-dataformat.adoc @@ -84,9 +84,8 @@ YAML:: In this example, we unmarshal a zipped payload from an ActiveMQ queue called MY_QUEUE to its original format, and forward it for processing to -the UnZippedMessageProcessor. Note that the compression Level employed -during marshaling should be identical to the one employed during -unmarshalling to avoid errors. +the UnZippedMessageProcessor. Unmarshal reads the data of any +compression level, so the level of the marshal does not need to be set. ._Java-only: inline Processor instance_ [source,java] diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/zipFile-dataformat.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/zipFile-dataformat.adoc index eb8970c15a581..bcf8de12fc820 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/zipFile-dataformat.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/zipFile-dataformat.adoc @@ -69,7 +69,7 @@ The name of the Zip entry inside the created Zip file is based on the incoming `CamelFileName` message header, which is the standard message header used by the file component. Additionally, the outgoing `CamelFileName` message header is automatically set to the -value of the incoming `CamelFileName` message header, with the ".zip" +file name of the incoming `CamelFileName` message header, without its path, with the ".zip" suffix. So, for example, if the following route finds a file named "test.txt" in the input directory, the output will be a Zip file named "test.txt.zip" containing a single Zip entry named "test.txt": diff --git a/components/camel-avro/src/generated/resources/META-INF/org/apache/camel/dataformat/avro/avro.json b/components/camel-avro/src/generated/resources/META-INF/org/apache/camel/dataformat/avro/avro.json index 58f2269f6f69c..9d4dc3970e309 100644 --- a/components/camel-avro/src/generated/resources/META-INF/org/apache/camel/dataformat/avro/avro.json +++ b/components/camel-avro/src/generated/resources/META-INF/org/apache/camel/dataformat/avro/avro.json @@ -15,6 +15,12 @@ "modelName": "avro", "modelJavaType": "org.apache.camel.model.dataformat.AvroDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "description": "An Avro record: an object of a class the Avro compiler generated, or a GenericRecord of the schema of instanceClassName. Without instanceClassName the schema comes from the class of the body, so a GenericRecord fails. A Map is not converted" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The record in Avro binary encoding, without the schema (not an Avro container file), in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "One record in Avro binary encoding, as marshal writes it: unmarshal fails without instanceClassName (or a schema set in Java)" }, + "unmarshalOut": { "carriers": [ "pojo" ], "description": "An object of the class instanceClassName names; a GenericRecord when a schema set in Java has no class on the classpath" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "instanceClassName": { "index": 1, "kind": "attribute", "displayName": "Instance Class Name", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Class name to use for marshal and unmarshalling." }, diff --git a/components/camel-avro/src/main/java/org/apache/camel/dataformat/avro/AvroDataFormat.java b/components/camel-avro/src/main/java/org/apache/camel/dataformat/avro/AvroDataFormat.java index cc1fcc360134c..c7537187eb770 100644 --- a/components/camel-avro/src/main/java/org/apache/camel/dataformat/avro/AvroDataFormat.java +++ b/components/camel-avro/src/main/java/org/apache/camel/dataformat/avro/AvroDataFormat.java @@ -37,6 +37,9 @@ import org.apache.camel.CamelException; import org.apache.camel.Exchange; import org.apache.camel.avro.support.AvroClassSecuritySupport; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.Metadata; @@ -49,6 +52,21 @@ "collectionTypeName,collectionType,useList,moduleClassNames,moduleRefs,enableFeatures," + "disableFeatures,allowUnmarshallType,timezone,autoDiscoverObjectMapper," + "contentTypeHeader,schemaResolver,autoDiscoverSchemaResolver,unmarshalType,unmarshalTypeName") +@BodyTypes(marshalIn = @BodyType(value = Carrier.POJO, + description = "An Avro record: an object of a class the Avro compiler generated, or a" + + " GenericRecord of the schema of instanceClassName. Without" + + " instanceClassName the schema comes from the class of the body, so a" + + " GenericRecord fails. A Map is not converted"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The record in Avro binary encoding, without the schema (not an Avro" + + " container file), in the stream cache, or a byte array when stream caching" + + " is off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "One record in Avro binary encoding, as marshal writes it: unmarshal fails" + + " without instanceClassName (or a schema set in Java)"), + unmarshalOut = @BodyType(value = Carrier.POJO, + description = "An object of the class instanceClassName names; a GenericRecord when a" + + " schema set in Java has no class on the classpath")) public class AvroDataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private static final String GENERIC_CONTAINER_CLASSNAME = GenericContainer.class.getName(); diff --git a/components/camel-barcode/src/generated/resources/META-INF/org/apache/camel/dataformat/barcode/barcode.json b/components/camel-barcode/src/generated/resources/META-INF/org/apache/camel/dataformat/barcode/barcode.json index 0614e200145b5..df4e573fc7f17 100644 --- a/components/camel-barcode/src/generated/resources/META-INF/org/apache/camel/dataformat/barcode/barcode.json +++ b/components/camel-barcode/src/generated/resources/META-INF/org/apache/camel/dataformat/barcode/barcode.json @@ -15,6 +15,12 @@ "modelName": "barcode", "modelJavaType": "org.apache.camel.model.dataformat.BarcodeDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "text", "description": "The text to encode: bytes, a stream or a file are read in the charset of the exchange. It must suit the barcodeFormat, such as digits only for EAN-13" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The image of the barcode, a PNG unless imageType is JPG or GIF, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "An image ImageIO reads, such as PNG, JPEG or GIF, of any barcode format ZXing reads, whatever barcodeFormat is" }, + "unmarshalOut": { "carriers": [ "text" ], "javaType": "java.lang.String", "format": "text", "description": "The text of the barcode, with the format found in the BarcodeFormat header and the ZXing result metadata, such as ORIENTATION, as headers" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "barcodeFormat": { "index": 1, "kind": "attribute", "displayName": "Barcode Format", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "AZTEC", "CODABAR", "CODE_39", "CODE_93", "CODE_128", "DATA_MATRIX", "EAN_8", "EAN_13", "ITF", "MAXICODE", "PDF_417", "QR_CODE", "RSS_14", "RSS_EXPANDED", "UPC_A", "UPC_E", "UPC_EAN_EXTENSION" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "QR_CODE", "description": "Barcode format such as QR-Code." }, diff --git a/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java b/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java index 1ab95a87603fc..4a64827e738b0 100644 --- a/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java +++ b/components/camel-barcode/src/main/java/org/apache/camel/dataformat/barcode/BarcodeDataFormat.java @@ -41,6 +41,9 @@ import com.google.zxing.datamatrix.encoder.SymbolShapeHint; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -57,6 +60,18 @@ * https://github.com/zxing/zxing */ @Dataformat("barcode") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "text", + description = "The text to encode: bytes, a stream or a file are read in the charset of the" + + " exchange. It must suit the barcodeFormat, such as digits only for EAN-13"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The image of the barcode, a PNG unless imageType is JPG or GIF, in the stream" + + " cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "An image ImageIO reads, such as PNG, JPEG or GIF, of any barcode format ZXing" + + " reads, whatever barcodeFormat is"), + unmarshalOut = @BodyType(value = Carrier.TEXT, javaType = "java.lang.String", format = "text", + description = "The text of the barcode, with the format found in the BarcodeFormat header" + + " and the ZXing result metadata, such as ORIENTATION, as headers")) public class BarcodeDataFormat extends ServiceSupport implements DataFormat, DataFormatName { private static final Logger LOG = LoggerFactory.getLogger(BarcodeDataFormat.class); diff --git a/components/camel-cbor/src/generated/resources/META-INF/org/apache/camel/component/cbor/cbor.json b/components/camel-cbor/src/generated/resources/META-INF/org/apache/camel/component/cbor/cbor.json index c988a717c0293..f2182f1488ff7 100644 --- a/components/camel-cbor/src/generated/resources/META-INF/org/apache/camel/component/cbor/cbor.json +++ b/components/camel-cbor/src/generated/resources/META-INF/org/apache/camel/component/cbor/cbor.json @@ -15,6 +15,12 @@ "modelName": "cbor", "modelJavaType": "org.apache.camel.model.dataformat.CBORDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list", "pojo" ], "description": "A Map, a List or a POJO to write as CBOR. A String or bytes are written as one CBOR text or byte string, not as they are" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The CBOR data in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "CBOR data. A String fails" }, + "unmarshalOut": { "carriers": [ "pojo" ], "dependsOn": [ "collectionType", "allowUnmarshallType", "allowJmsType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "An object of the class unmarshalType names, such as java.util.Map: unmarshal fails without unmarshalType" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "objectMapper": { "index": 1, "kind": "attribute", "displayName": "Object Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing CBOR ObjectMapper with the given id when using Jackson." }, diff --git a/components/camel-cbor/src/main/java/org/apache/camel/component/cbor/CBORDataFormat.java b/components/camel-cbor/src/main/java/org/apache/camel/component/cbor/CBORDataFormat.java index 9f547509567a3..8a70961945409 100644 --- a/components/camel-cbor/src/main/java/org/apache/camel/component/cbor/CBORDataFormat.java +++ b/components/camel-cbor/src/main/java/org/apache/camel/component/cbor/CBORDataFormat.java @@ -41,6 +41,9 @@ import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; import org.apache.camel.WrappedFile; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -51,6 +54,19 @@ import org.slf4j.LoggerFactory; @Dataformat("cbor") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.MAP, Carrier.LIST, Carrier.POJO }, + description = "A Map, a List or a POJO to write as CBOR. A String or bytes are written as one" + + " CBOR text or byte string, not as they are"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The CBOR data in the stream cache, or a byte array when stream caching is" + + " off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "CBOR data. A String fails"), + unmarshalOut = @BodyType(value = Carrier.POJO, + dependsOn = { "collectionType", "allowUnmarshallType", "allowJmsType" }, + byOption = @BodyType.When(option = "useList", value = "true", carriers = Carrier.LIST), + description = "An object of the class unmarshalType names, such as java.util.Map:" + + " unmarshal fails without unmarshalType")) public class CBORDataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private static final Logger LOG = LoggerFactory.getLogger(CBORDataFormat.class); diff --git a/components/camel-crypto-pgp/src/generated/resources/META-INF/org/apache/camel/converter/crypto/pgp.json b/components/camel-crypto-pgp/src/generated/resources/META-INF/org/apache/camel/converter/crypto/pgp.json index 78b19aa674a63..516d48cf50eb8 100644 --- a/components/camel-crypto-pgp/src/generated/resources/META-INF/org/apache/camel/converter/crypto/pgp.json +++ b/components/camel-crypto-pgp/src/generated/resources/META-INF/org/apache/camel/converter/crypto/pgp.json @@ -15,6 +15,12 @@ "modelName": "pgp", "modelJavaType": "org.apache.camel.model.dataformat.PGPDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data to encrypt: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The PGP message in the stream cache, or a byte array when stream caching is off: binary, or ASCII armored text when armored is true" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "A PGP message, binary or ASCII armored: the armor is detected, whatever armored is set to" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decrypted data in the stream cache, or a byte array when stream caching is off" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "keyUserid": { "index": 1, "kind": "attribute", "displayName": "Key Userid", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The user ID of the key in the PGP keyring used during encryption. Can also be only a part of a user ID." }, diff --git a/components/camel-crypto-pgp/src/main/java/org/apache/camel/converter/crypto/PGPDataFormat.java b/components/camel-crypto-pgp/src/main/java/org/apache/camel/converter/crypto/PGPDataFormat.java index 6215d3e0b6f2a..937e07b251175 100644 --- a/components/camel-crypto-pgp/src/main/java/org/apache/camel/converter/crypto/PGPDataFormat.java +++ b/components/camel-crypto-pgp/src/main/java/org/apache/camel/converter/crypto/PGPDataFormat.java @@ -23,6 +23,9 @@ import java.util.Map; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.annotations.Dataformat; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPrivateKey; @@ -36,6 +39,18 @@ * See also {@link PGPKeyAccessDataFormat}. */ @Dataformat("pgp") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The data to encrypt: text in the charset of the exchange, bytes, a stream or a" + + " file"), + marshalOut = @BodyType(value = Carrier.STREAM, + description = "The PGP message in the stream cache, or a byte array when stream caching is" + + " off: binary, or ASCII armored text when armored is true"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "A PGP message, binary or ASCII armored: the armor is detected, whatever" + + " armored is set to"), + unmarshalOut = @BodyType(value = Carrier.STREAM, + description = "The decrypted data in the stream cache, or a byte array when stream caching" + + " is off")) public class PGPDataFormat extends PGPKeyAccessDataFormat implements PGPPublicKeyAccessor, PGPSecretKeyAccessor { public static final String KEY_FILE_NAME = "CamelPGPDataFormatKeyFileName"; diff --git a/components/camel-crypto/src/generated/resources/META-INF/org/apache/camel/converter/crypto/crypto.json b/components/camel-crypto/src/generated/resources/META-INF/org/apache/camel/converter/crypto/crypto.json index 455c88df0988a..026c69bddd49e 100644 --- a/components/camel-crypto/src/generated/resources/META-INF/org/apache/camel/converter/crypto/crypto.json +++ b/components/camel-crypto/src/generated/resources/META-INF/org/apache/camel/converter/crypto/crypto.json @@ -15,6 +15,12 @@ "modelName": "crypto", "modelJavaType": "org.apache.camel.model.dataformat.CryptoDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The bytes to encrypt: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The encrypted data in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Encrypted data as marshal writes it, with the same inline and shouldAppendHMAC settings" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decrypted bytes in the stream cache, or a byte array when stream caching is off" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "algorithm": { "index": 1, "kind": "attribute", "displayName": "Algorithm", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The JCE algorithm name indicating the cryptographic algorithm that will be used." }, diff --git a/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/CryptoDataFormat.java b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/CryptoDataFormat.java index ae5052b180570..68f59ab096b6a 100644 --- a/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/CryptoDataFormat.java +++ b/components/camel-crypto/src/main/java/org/apache/camel/converter/crypto/CryptoDataFormat.java @@ -32,6 +32,9 @@ import javax.crypto.spec.IvParameterSpec; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -68,6 +71,18 @@ * */ @Dataformat("crypto") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The bytes to encrypt: text in the charset of the exchange, bytes, a stream or a" + + " file"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The encrypted data in the stream cache, or a byte array when stream caching is" + + " off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "Encrypted data as marshal writes it, with the same inline and" + + " shouldAppendHMAC settings"), + unmarshalOut = @BodyType(value = Carrier.STREAM, + description = "The decrypted bytes in the stream cache, or a byte array when stream caching" + + " is off")) public class CryptoDataFormat extends ServiceSupport implements DataFormat, DataFormatName { public static final String KEY = "CamelCryptoKey"; diff --git a/components/camel-fory/src/generated/resources/META-INF/org/apache/camel/component/fory/fory.json b/components/camel-fory/src/generated/resources/META-INF/org/apache/camel/component/fory/fory.json index 405ce1ab75770..f177fcd03ad61 100644 --- a/components/camel-fory/src/generated/resources/META-INF/org/apache/camel/component/fory/fory.json +++ b/components/camel-fory/src/generated/resources/META-INF/org/apache/camel/component/fory/fory.json @@ -15,6 +15,12 @@ "modelName": "fory", "modelJavaType": "org.apache.camel.model.dataformat.ForyDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list", "pojo" ], "description": "An object of the unmarshalType class, or a List, a Map or another type Fory registers itself; another class only with requireClassRegistration false. A String or bytes are serialized as objects, not written as they are" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The Fory binary data in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Fory binary data, as marshal writes it" }, + "unmarshalOut": { "carriers": [ "unknown" ], "description": "The object marshal wrote, of the class in the data: unmarshalType only registers a class and does not convert the result" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "unmarshalType": { "index": 1, "kind": "attribute", "displayName": "Unmarshal Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Class of the java type to use when unmarshalling" }, diff --git a/components/camel-fory/src/main/java/org/apache/camel/component/fory/ForyDataFormat.java b/components/camel-fory/src/main/java/org/apache/camel/component/fory/ForyDataFormat.java index 89e44762d2fb9..a42f71d62bc2e 100644 --- a/components/camel-fory/src/main/java/org/apache/camel/component/fory/ForyDataFormat.java +++ b/components/camel-fory/src/main/java/org/apache/camel/component/fory/ForyDataFormat.java @@ -21,6 +21,9 @@ import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.Metadata; @@ -37,6 +40,18 @@ */ @Dataformat("fory") @Metadata(firstVersion = "4.9.0", title = "Fory") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.MAP, Carrier.LIST, Carrier.POJO }, + description = "An object of the unmarshalType class, or a List, a Map or another type Fory" + + " registers itself; another class only with requireClassRegistration false." + + " A String or bytes are serialized as objects, not written as they are"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The Fory binary data in the stream cache, or a byte array when stream caching" + + " is off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "Fory binary data, as marshal writes it"), + unmarshalOut = @BodyType(value = Carrier.UNKNOWN, + description = "The object marshal wrote, of the class in the data: unmarshalType only" + + " registers a class and does not convert the result")) public class ForyDataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private CamelContext camelContext; diff --git a/components/camel-jackson-avro/src/generated/resources/META-INF/org/apache/camel/component/jackson/avro/avroJackson.json b/components/camel-jackson-avro/src/generated/resources/META-INF/org/apache/camel/component/jackson/avro/avroJackson.json index 5566c435d41b7..d33b64b316a89 100644 --- a/components/camel-jackson-avro/src/generated/resources/META-INF/org/apache/camel/component/jackson/avro/avroJackson.json +++ b/components/camel-jackson-avro/src/generated/resources/META-INF/org/apache/camel/component/jackson/avro/avroJackson.json @@ -15,6 +15,12 @@ "modelName": "avro", "modelJavaType": "org.apache.camel.model.dataformat.AvroDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list", "pojo" ], "description": "A POJO, a Map or a JsonNode to write with the Avro schema of the schemaResolver, or a List for an array schema. A String or bytes are not written as they are" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The Avro binary data, without the schema, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Avro binary data of the schema of the schemaResolver. A String fails" }, + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType", "allowJmsType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) for an Avro record, a List (ArrayList) for an array; an object of the class unmarshalType names, such as JsonNode" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "objectMapper": { "index": 1, "kind": "attribute", "displayName": "Object Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing ObjectMapper with the given id when using Jackson." }, diff --git a/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc b/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc index b399745171b57..d67ac24b3407d 100644 --- a/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc +++ b/components/camel-jackson-avro/src/main/docs/avroJackson2-dataformat.adoc @@ -38,7 +38,7 @@ XML:: ---- - + ---- @@ -54,6 +54,7 @@ YAML:: - unmarshal: avro: library: Jackson + unmarshalType: com.fasterxml.jackson.databind.JsonNode - to: uri: log:info ---- diff --git a/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/JacksonAvroDataFormat.java b/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/JacksonAvroDataFormat.java index e27a577c0901c..e2cef081c7435 100644 --- a/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/JacksonAvroDataFormat.java +++ b/components/camel-jackson-avro/src/main/java/org/apache/camel/component/jackson/avro/JacksonAvroDataFormat.java @@ -20,6 +20,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.avro.AvroMapper; import org.apache.camel.component.jackson.AbstractJacksonDataFormat; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.annotations.Dataformat; @@ -29,6 +32,20 @@ @Dataformat("avroJackson") @Metadata(firstVersion = "3.10.0", title = "Avro Jackson", excludeProperties = "library,instanceClassName,schema,serializablePackages") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.MAP, Carrier.LIST, Carrier.POJO }, + description = "A POJO, a Map or a JsonNode to write with the Avro schema of the" + + " schemaResolver, or a List for an array schema. A String or bytes are not" + + " written as they are"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The Avro binary data, without the schema, in the stream cache, or a byte" + + " array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "Avro binary data of the schema of the schemaResolver. A String fails"), + unmarshalOut = @BodyType(value = { Carrier.MAP, Carrier.LIST }, + dependsOn = { "unmarshalType", "collectionType", "allowUnmarshallType", "allowJmsType" }, + byOption = @BodyType.When(option = "useList", value = "true", carriers = Carrier.LIST), + description = "A Map (LinkedHashMap) for an Avro record, a List (ArrayList) for an array;" + + " an object of the class unmarshalType names, such as JsonNode")) public class JacksonAvroDataFormat extends AbstractJacksonDataFormat { /** diff --git a/components/camel-jackson-protobuf/src/generated/resources/META-INF/org/apache/camel/component/jackson/protobuf/protobufJackson.json b/components/camel-jackson-protobuf/src/generated/resources/META-INF/org/apache/camel/component/jackson/protobuf/protobufJackson.json index 21fcffd762504..69b59c80abd0e 100644 --- a/components/camel-jackson-protobuf/src/generated/resources/META-INF/org/apache/camel/component/jackson/protobuf/protobufJackson.json +++ b/components/camel-jackson-protobuf/src/generated/resources/META-INF/org/apache/camel/component/jackson/protobuf/protobufJackson.json @@ -15,6 +15,12 @@ "modelName": "protobuf", "modelJavaType": "org.apache.camel.model.dataformat.ProtobufDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "pojo" ], "description": "A POJO, a Map or a JsonNode to write as the message of the protobuf schema of the schemaResolver. Text, bytes or a stream are written as they are, not encoded" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The protobuf binary data in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Protobuf binary data of the schema of the schemaResolver. A String fails" }, + "unmarshalOut": { "carriers": [ "map" ], "dependsOn": [ "unmarshalType", "collectionType", "useList", "allowUnmarshallType", "allowJmsType" ], "description": "A Map (LinkedHashMap) of the fields of the message; an object of the class unmarshalType names, such as JsonNode" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "objectMapper": { "index": 1, "kind": "attribute", "displayName": "Object Mapper", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Lookup and use the existing ObjectMapper with the given id when using Jackson." }, diff --git a/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc b/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc index 5a24229148d7f..63984745ada54 100644 --- a/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc +++ b/components/camel-jackson-protobuf/src/main/docs/protobufJackson2-dataformat.adoc @@ -38,7 +38,7 @@ XML:: ---- - + ---- @@ -54,6 +54,7 @@ YAML:: - unmarshal: protobuf: library: Jackson + unmarshalType: com.fasterxml.jackson.databind.JsonNode - to: uri: log:info ---- diff --git a/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/JacksonProtobufDataFormat.java b/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/JacksonProtobufDataFormat.java index 1878e3ab5ad43..dd3c6af4d4d2c 100644 --- a/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/JacksonProtobufDataFormat.java +++ b/components/camel-jackson-protobuf/src/main/java/org/apache/camel/component/jackson/protobuf/JacksonProtobufDataFormat.java @@ -20,6 +20,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.protobuf.ProtobufMapper; import org.apache.camel.component.jackson.JacksonDataFormat; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.annotations.Dataformat; @@ -29,6 +32,21 @@ @Dataformat("protobufJackson") @Metadata(firstVersion = "3.10.0", title = "Protobuf Jackson", excludeProperties = "library,permissions,dateFormatPattern,instanceClass,contentTypeFormat,defaultInstance") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.MAP, Carrier.POJO }, + description = "A POJO, a Map or a JsonNode to write as the message of the protobuf schema of" + + " the schemaResolver. Text, bytes or a stream are written as they are, not" + + " encoded"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The protobuf binary data in the stream cache, or a byte array when stream" + + " caching is off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "Protobuf binary data of the schema of the schemaResolver. A String fails"), + unmarshalOut = @BodyType(value = Carrier.MAP, + dependsOn = { + "unmarshalType", "collectionType", "useList", "allowUnmarshallType", + "allowJmsType" }, + description = "A Map (LinkedHashMap) of the fields of the message; an object of the class" + + " unmarshalType names, such as JsonNode")) public class JacksonProtobufDataFormat extends JacksonDataFormat { /** diff --git a/components/camel-jackson/src/generated/resources/META-INF/org/apache/camel/component/jackson/jackson.json b/components/camel-jackson/src/generated/resources/META-INF/org/apache/camel/component/jackson/jackson.json index 36de62e80cf39..09e670b682e82 100644 --- a/components/camel-jackson/src/generated/resources/META-INF/org/apache/camel/component/jackson/jackson.json +++ b/components/camel-jackson/src/generated/resources/META-INF/org/apache/camel/component/jackson/jackson.json @@ -19,7 +19,7 @@ "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as JSON. Text, bytes or a stream that is JSON already is written as it is" }, "marshalOut": { "carriers": [ "stream" ], "format": "json", "description": "The JSON in the stream cache, or a byte array when stream caching is off" }, "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "json" }, - "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) for a JSON object, a List (ArrayList) for an array; an object of the class unmarshalType names" } + "unmarshalOut": { "carriers": [ "map", "list" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType", "allowJmsType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) for a JSON object, a List (ArrayList) for an array; an object of the class unmarshalType names" } }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, diff --git a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java index 4afc8fb1cbe30..d239d34c1f8cd 100644 --- a/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java +++ b/components/camel-jackson/src/main/java/org/apache/camel/component/jackson/JacksonDataFormat.java @@ -44,7 +44,7 @@ description = "The JSON in the stream cache, or a byte array when stream caching is off"), unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "json"), unmarshalOut = @BodyType(value = { Carrier.MAP, Carrier.LIST }, - dependsOn = { "unmarshalType", "collectionType", "allowUnmarshallType" }, + dependsOn = { "unmarshalType", "collectionType", "allowUnmarshallType", "allowJmsType" }, byOption = @BodyType.When(option = "useList", value = "true", carriers = Carrier.LIST), description = "A Map (LinkedHashMap) for a JSON object, a List (ArrayList) for an array;" + " an object of the class unmarshalType names")) diff --git a/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc b/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc index 86d1ed6302af1..ba20549e7390a 100644 --- a/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc +++ b/components/camel-jackson3-avro/src/main/docs/avroJackson3-dataformat.adoc @@ -38,7 +38,7 @@ XML:: ---- - + ---- @@ -54,6 +54,7 @@ YAML:: - unmarshal: avro: library: Jackson + unmarshalType: tools.jackson.databind.JsonNode - to: uri: log:info ---- diff --git a/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc b/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc index 54928ce6fbd09..0c0d61a182b9d 100644 --- a/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc +++ b/components/camel-jackson3-protobuf/src/main/docs/protobufJackson3-dataformat.adoc @@ -38,7 +38,7 @@ XML:: ---- - + ---- @@ -54,6 +54,7 @@ YAML:: - unmarshal: protobuf: library: Jackson + unmarshalType: tools.jackson.databind.JsonNode - to: uri: log:info ---- diff --git a/components/camel-jacksonxml/src/generated/resources/META-INF/org/apache/camel/component/jacksonxml/jacksonXml.json b/components/camel-jacksonxml/src/generated/resources/META-INF/org/apache/camel/component/jacksonxml/jacksonXml.json index e01c38e3002ee..2d1e6bd0fe518 100644 --- a/components/camel-jacksonxml/src/generated/resources/META-INF/org/apache/camel/component/jacksonxml/jacksonXml.json +++ b/components/camel-jacksonxml/src/generated/resources/META-INF/org/apache/camel/component/jacksonxml/jacksonXml.json @@ -19,7 +19,7 @@ "marshalIn": { "carriers": [ "any" ], "description": "A Map, a List or a POJO to write as XML. Text is written as an XML value, not as it is" }, "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The XML in the stream cache, or a byte array when stream caching is off" }, "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "format": "xml" }, - "unmarshalOut": { "carriers": [ "map" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) of the XML; an object of the class unmarshalType names" } + "unmarshalOut": { "carriers": [ "map" ], "dependsOn": [ "unmarshalType", "collectionType", "allowUnmarshallType", "allowJmsType" ], "byOption": [ { "option": "useList", "value": "true", "carriers": [ "list" ] } ], "description": "A Map (LinkedHashMap) of the XML; an object of the class unmarshalType names" } }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, diff --git a/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java b/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java index 097f6a2748be5..fba4416c2d895 100644 --- a/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java +++ b/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java @@ -70,7 +70,7 @@ description = "The XML in the stream cache, or a byte array when stream caching is off"), unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "xml"), unmarshalOut = @BodyType(value = Carrier.MAP, - dependsOn = { "unmarshalType", "collectionType", "allowUnmarshallType" }, + dependsOn = { "unmarshalType", "collectionType", "allowUnmarshallType", "allowJmsType" }, byOption = @BodyType.When(option = "useList", value = "true", carriers = Carrier.LIST), description = "A Map (LinkedHashMap) of the XML; an object of the class unmarshalType" + " names")) diff --git a/components/camel-lzf/src/generated/resources/META-INF/org/apache/camel/dataformat/lzf/lzf.json b/components/camel-lzf/src/generated/resources/META-INF/org/apache/camel/dataformat/lzf/lzf.json index 17164c16d1e96..664ef6a95ffc5 100644 --- a/components/camel-lzf/src/generated/resources/META-INF/org/apache/camel/dataformat/lzf/lzf.json +++ b/components/camel-lzf/src/generated/resources/META-INF/org/apache/camel/dataformat/lzf/lzf.json @@ -15,6 +15,12 @@ "modelName": "lzf", "modelJavaType": "org.apache.camel.model.dataformat.LZFDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data to compress: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The LZF data in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "LZF data, such as marshal gives, with or without usingParallelCompression" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decompressed data in the stream cache, or a byte array when stream caching is off" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "usingParallelCompression": { "index": 1, "kind": "attribute", "displayName": "Using Parallel Compression", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable encoding (compress) using multiple processing cores." } diff --git a/components/camel-lzf/src/main/java/org/apache/camel/dataformat/lzf/LZFDataFormat.java b/components/camel-lzf/src/main/java/org/apache/camel/dataformat/lzf/LZFDataFormat.java index 97062cd494b56..9e0ca7493906d 100644 --- a/components/camel-lzf/src/main/java/org/apache/camel/dataformat/lzf/LZFDataFormat.java +++ b/components/camel-lzf/src/main/java/org/apache/camel/dataformat/lzf/LZFDataFormat.java @@ -23,6 +23,9 @@ import com.ning.compress.lzf.LZFOutputStream; import com.ning.compress.lzf.parallel.PLZFOutputStream; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -34,6 +37,16 @@ * LZF data format. See {@link org.apache.camel.model.dataformat.LZFDataFormat} for "deflate" compression. */ @Dataformat("lzf") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The data to compress: text in the charset of the exchange, bytes, a stream" + + " or a file"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The LZF data in the stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "LZF data, such as marshal gives, with or without usingParallelCompression"), + unmarshalOut = @BodyType(value = Carrier.STREAM, + description = "The decompressed data in the stream cache, or a byte array when stream" + + " caching is off")) public class LZFDataFormat extends ServiceSupport implements DataFormat, DataFormatName { private boolean usingParallelCompression; diff --git a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/dataformat/mime/multipart/mimeMultipart.json b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/dataformat/mime/multipart/mimeMultipart.json index df18b27b46bb0..abc8a7181cfcb 100644 --- a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/dataformat/mime/multipart/mimeMultipart.json +++ b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/dataformat/mime/multipart/mimeMultipart.json @@ -15,6 +15,12 @@ "modelName": "mimeMultipart", "modelJavaType": "org.apache.camel.model.dataformat.MimeMultipartDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The body of the first part, of the content type in the Content-Type header (application\/octet-stream when not set); the attachments of the message are the other parts" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The MIME multipart in the stream cache, or a byte array when stream caching is off, with its MIME headers as Camel headers unless headersInline is true. Without attachments the body is written as it is, unless multipartWithoutAttachment or headersInline is true" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "A MIME multipart, with its Content-Type (multipart\/*) and MIME-Version as Camel headers, as marshal leaves them; with headersInline, the MIME headers are at the start of the body" }, + "unmarshalOut": { "carriers": [ "stream" ], "byOption": [ { "option": "headersInline", "value": "true", "carriers": [ "stream", "unchanged" ] } ], "description": "The first part, decoded, as a stream, with the other parts as attachments and its Content-Type as a header. Without a multipart Content-Type header the body is given back as a stream; with headersInline, a body that is not a multipart stays as it was" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "multipartSubType": { "index": 1, "kind": "attribute", "displayName": "Multipart Sub Type", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "mixed", "description": "Specify the subtype of the MIME Multipart." }, diff --git a/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc b/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc index 9b5318b2267cb..a88c92a270fe0 100644 --- a/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc +++ b/components/camel-mail/src/main/docs/mimeMultipart-dataformat.adoc @@ -66,8 +66,8 @@ version (1.0) if the "headersInline" parameter is set to false. |Content-Type |String |The content of this header will be used as a content type for the message body part. If no content type is set, "application/octet-stream" is assumed. After the marshal operation, the content type is set to -"multipart/related" or empty if the "headersInline" parameter is set to -true. +"multipart/" with the "multipartSubType" ("multipart/mixed" by default), or empty +if the "headersInline" parameter is set to true. |Content-Encoding |String |If the incoming content type is "text/*" the content encoding will be set to the encoding parameter of the Content-Type MIME header of the diff --git a/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java b/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java index f64bdfa545bb9..f2eac282a944b 100644 --- a/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java +++ b/components/camel-mail/src/main/java/org/apache/camel/dataformat/mime/multipart/MimeMultipartDataFormat.java @@ -51,6 +51,9 @@ import org.apache.camel.attachment.AttachmentMessage; import org.apache.camel.attachment.DefaultAttachment; import org.apache.camel.component.mail.MailHeaderFilterStrategy; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.HeaderFilterStrategy; import org.apache.camel.spi.annotations.Dataformat; import org.apache.camel.support.DefaultDataFormat; @@ -62,6 +65,26 @@ import org.slf4j.LoggerFactory; @Dataformat("mimeMultipart") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The body of the first part, of the content type in the Content-Type header" + + " (application/octet-stream when not set); the attachments of the message are" + + " the other parts"), + marshalOut = @BodyType(value = Carrier.STREAM, + description = "The MIME multipart in the stream cache, or a byte array when stream caching is" + + " off, with its MIME headers as Camel headers unless headersInline is true." + + " Without attachments the body is written as it is, unless" + + " multipartWithoutAttachment or headersInline is true"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "A MIME multipart, with its Content-Type (multipart/*) and MIME-Version as" + + " Camel headers, as marshal leaves them; with headersInline, the MIME" + + " headers are at the start of the body"), + unmarshalOut = @BodyType(value = Carrier.STREAM, + byOption = @BodyType.When(option = "headersInline", value = "true", + carriers = { Carrier.STREAM, Carrier.UNCHANGED }), + description = "The first part, decoded, as a stream, with the other parts as attachments" + + " and its Content-Type as a header. Without a multipart Content-Type header" + + " the body is given back as a stream; with headersInline, a body that is" + + " not a multipart stays as it was")) public class MimeMultipartDataFormat extends DefaultDataFormat { private static final Logger LOG = LoggerFactory.getLogger(MimeMultipartDataFormat.class); private static final String MIME_VERSION = "MIME-Version"; diff --git a/components/camel-parquet-avro/src/generated/resources/META-INF/org/apache/camel/dataformat/parquet/avro/parquetAvro.json b/components/camel-parquet-avro/src/generated/resources/META-INF/org/apache/camel/dataformat/parquet/avro/parquetAvro.json index db9480d27935e..008c2efc3b87f 100644 --- a/components/camel-parquet-avro/src/generated/resources/META-INF/org/apache/camel/dataformat/parquet/avro/parquetAvro.json +++ b/components/camel-parquet-avro/src/generated/resources/META-INF/org/apache/camel/dataformat/parquet/avro/parquetAvro.json @@ -15,6 +15,12 @@ "modelName": "parquetAvro", "modelJavaType": "org.apache.camel.model.dataformat.ParquetAvroDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "list" ], "description": "A List of Avro GenericRecords, or of objects of the class unmarshalType names. A single record fails, and so does an empty List without unmarshalType" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The Parquet file in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "A Parquet file, which is read into memory" }, + "unmarshalOut": { "carriers": [ "list" ], "byOption": [ { "option": "lazyLoad", "value": "true", "carriers": [ "iterator" ] } ], "description": "A List (ArrayList) of the records: GenericRecords, or objects of the class unmarshalType names. With lazyLoad, an Iterator of them for the split EIP" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "compressionCodecName": { "index": 1, "kind": "attribute", "displayName": "Compression Codec Name", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "UNCOMPRESSED", "SNAPPY", "GZIP", "LZO", "BROTLI", "LZ4", "ZSTD", "LZ4_RAW" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "GZIP", "description": "Compression codec to use when marshalling." }, diff --git a/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc b/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc index c53eb43e4b87e..c2166b39675fc 100644 --- a/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc +++ b/components/camel-parquet-avro/src/main/docs/parquetAvro-dataformat.adoc @@ -27,7 +27,7 @@ include::partial$dataformat-options.adoc[] There are ways to unmarshal parquet files/structures, usually binary parquet files, where camel DSL allows. -In this first example we unmarshal file payload to OutputStream and send it to mock endpoint, then we will be able to get GenericRecord or POJO (it could be a list if that is coming through) +In this first example we unmarshal file payload to a List of the records and send it to mock endpoint: GenericRecords, or POJOs with `unmarshalType`. With `lazyLoad`, the body is an Iterator of them instead. [tabs] ==== @@ -58,7 +58,7 @@ With `unmarshalType`, the records are objects of that class. Without it, they ar == Marshal -Marshalling is the reverse process of unmarshalling, so when you have your `GenericRecord` or POJO and marshal it, you will get the parquet-formatted output stream on your producer endpoint. +Marshalling is the reverse process of unmarshalling, so when you have a List of `GenericRecord` objects or POJOs and marshal it, you will get the parquet-formatted output stream on your producer endpoint. A single record that is not in a List fails. [tabs] ==== diff --git a/components/camel-parquet-avro/src/main/java/org/apache/camel/dataformat/parquet/avro/ParquetAvroDataFormat.java b/components/camel-parquet-avro/src/main/java/org/apache/camel/dataformat/parquet/avro/ParquetAvroDataFormat.java index b3f283b8dcab1..51be46e22ffe5 100644 --- a/components/camel-parquet-avro/src/main/java/org/apache/camel/dataformat/parquet/avro/ParquetAvroDataFormat.java +++ b/components/camel-parquet-avro/src/main/java/org/apache/camel/dataformat/parquet/avro/ParquetAvroDataFormat.java @@ -29,6 +29,9 @@ import org.apache.avro.generic.GenericRecord; import org.apache.avro.reflect.ReflectData; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -48,6 +51,20 @@ import static org.apache.parquet.hadoop.metadata.CompressionCodecName.GZIP; @Dataformat("parquetAvro") +@BodyTypes(marshalIn = @BodyType(value = Carrier.LIST, + description = "A List of Avro GenericRecords, or of objects of the class unmarshalType names." + + " A single record fails, and so does an empty List without unmarshalType"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The Parquet file in the stream cache, or a byte array when stream caching is" + + " off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "A Parquet file, which is read into memory"), + unmarshalOut = @BodyType(value = Carrier.LIST, + byOption = @BodyType.When(option = "lazyLoad", value = "true", + carriers = Carrier.ITERATOR), + description = "A List (ArrayList) of the records: GenericRecords, or objects of the class" + + " unmarshalType names. With lazyLoad, an Iterator of them for the split" + + " EIP")) public class ParquetAvroDataFormat extends ServiceSupport implements DataFormat, DataFormatName { private static final Logger LOG = LoggerFactory.getLogger(ParquetAvroDataFormat.class); diff --git a/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/dataformat/pqc.json b/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/dataformat/pqc.json index dabdf55ea63af..d8114a080b7b4 100644 --- a/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/dataformat/pqc.json +++ b/components/camel-pqc/src/generated/resources/META-INF/org/apache/camel/component/pqc/dataformat/pqc.json @@ -15,6 +15,12 @@ "modelName": "pqc", "modelJavaType": "org.apache.camel.model.dataformat.PQCDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data to encrypt, read whole into memory: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The encrypted message in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "An encrypted message as marshal writes it" }, + "unmarshalOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The decrypted data, as a byte array" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "keyEncapsulationAlgorithm": { "index": 1, "kind": "attribute", "displayName": "Key Encapsulation Algorithm", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "MLKEM", "BIKE", "HQC", "CMCE", "SABER", "FRODO", "NTRU", "NTRULPRime", "SNTRUPrime", "KYBER" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MLKEM", "description": "The Post-Quantum KEM algorithm to use for key encapsulation." }, diff --git a/components/camel-pqc/src/main/docs/pqc-dataformat.adoc b/components/camel-pqc/src/main/docs/pqc-dataformat.adoc index b8bd8cf22697a..e983435fe9221 100644 --- a/components/camel-pqc/src/main/docs/pqc-dataformat.adoc +++ b/components/camel-pqc/src/main/docs/pqc-dataformat.adoc @@ -417,7 +417,7 @@ A KEM `KeyGenerator` keeps the spec passed to `init()` until `generateKey()` rea **2. Large Payloads** -To guarantee integrity, the authenticated (AEAD) cipher verifies the authentication tag before releasing any plaintext, so the payload is processed as a whole rather than incrementally. Enable stream caching to let Camel spill large bodies to disk on the route: +To guarantee integrity, the authenticated (AEAD) cipher verifies the authentication tag before releasing any plaintext, so the payload is processed as a whole rather than incrementally. Marshal and unmarshal hold the whole plaintext and the whole ciphertext in memory as byte arrays, so the payload must fit in memory, about twice over; stream caching does not change that. Stream caching only keeps the marshalled result for the next steps, and spills it to disk with `spoolEnabled`: ._Java-only: stream caching large files with PQCDataFormat_ [source,java] @@ -481,7 +481,7 @@ Security.addProvider(new BouncyCastlePQCProvider()); **Issue**: OutOfMemoryError with large files -* **Solution**: Authenticated (AEAD) encryption processes the payload as a whole; enable stream caching so Camel spills large bodies to disk: +* **Solution**: Authenticated (AEAD) encryption processes the payload as a whole, in memory: give the JVM enough heap for about twice the payload, or split large files into smaller messages. Stream caching only keeps the marshalled result for the next steps: + ._Java-only: enabling stream caching for large files_ [source,java] diff --git a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/dataformat/PQCDataFormat.java b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/dataformat/PQCDataFormat.java index d3bec69317535..6282ca7b7d8bc 100644 --- a/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/dataformat/PQCDataFormat.java +++ b/components/camel-pqc/src/main/java/org/apache/camel/component/pqc/dataformat/PQCDataFormat.java @@ -36,6 +36,9 @@ import org.apache.camel.Exchange; import org.apache.camel.component.pqc.PQCKeyEncapsulationAlgorithms; import org.apache.camel.component.pqc.PQCSymmetricAlgorithms; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -97,6 +100,16 @@ * */ @Dataformat("pqc") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The data to encrypt, read whole into memory: text in the charset of the" + + " exchange, bytes, a stream or a file"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The encrypted message in the stream cache, or a byte array when stream caching" + + " is off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "An encrypted message as marshal writes it"), + unmarshalOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]", + description = "The decrypted data, as a byte array")) public class PQCDataFormat extends ServiceSupport implements DataFormat, DataFormatName { public static final String KEY_PAIR = "CamelPQCKeyPair"; diff --git a/components/camel-protobuf/src/generated/resources/META-INF/org/apache/camel/dataformat/protobuf/protobuf.json b/components/camel-protobuf/src/generated/resources/META-INF/org/apache/camel/dataformat/protobuf/protobuf.json index d7236b51496f2..11e96da6003b1 100644 --- a/components/camel-protobuf/src/generated/resources/META-INF/org/apache/camel/dataformat/protobuf/protobuf.json +++ b/components/camel-protobuf/src/generated/resources/META-INF/org/apache/camel/dataformat/protobuf/protobuf.json @@ -15,6 +15,12 @@ "modelName": "protobuf", "modelJavaType": "org.apache.camel.model.dataformat.ProtobufDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo", "map" ], "description": "A protobuf Message of a generated class, or a Map of the fields of the instanceClass message, which needs instanceClass. JSON text is not converted" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The protobuf binary data, or JSON with contentTypeFormat json, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "byOption": [ { "option": "contentTypeFormat", "value": "json", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "Protobuf binary data, or JSON with contentTypeFormat json: unmarshal fails without instanceClass" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "com.google.protobuf.Message", "description": "The generated class of instanceClass, such as AddressBookProtos$Person; convertBodyTo Map gives its fields" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "instanceClass": { "index": 1, "kind": "attribute", "displayName": "Instance Class", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of class to use when unmarshalling." }, diff --git a/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc b/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc index 210acbe359f46..f70031acabe07 100644 --- a/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc +++ b/components/camel-protobuf/src/main/docs/protobuf-dataformat.adoc @@ -37,7 +37,7 @@ include::partial$dataformat-options.adoc[] It's possible to parse JSON message to convert it to the protobuf format and unparse it back using native util converter. To use this option, set contentTypeFormat value to `json` or call protobuf with second parameter. -If the default instance is not specified, always use the native protobuf format. +Unmarshal needs the default instance (`instanceClass`) in both formats; marshal writes the given `Message` in either. The sample code shows below: ._Java-only: programmatic protobuf configuration with content type format_ @@ -59,9 +59,8 @@ do so, it will fall back to retrieve it as proto `Message`. As mentioned above, you can define the content type format to choose from JSON or native to serialize/deserialize data from/to. In addition, you can also obtain the data as `Map` and let this component do the heavy lifting to parse the -data from proto `Message` to `Map`, -you will need to set the `contentTypeFormat` to `native` -and explicitly define the data type `Map` when you get body of the exchange. +data from proto `Message` to `Map`, in either `contentTypeFormat`, +by explicitly defining the data type `Map` when you get body of the exchange. For instance: `exchange.getMessage().getBody(Map.class)`. In the `Map`, the value of a `bytes` field is a `byte[]`; when a `Map` is converted to a message, a `bytes` field takes a `byte[]` (or a `ByteString`). diff --git a/components/camel-protobuf/src/main/java/org/apache/camel/dataformat/protobuf/ProtobufDataFormat.java b/components/camel-protobuf/src/main/java/org/apache/camel/dataformat/protobuf/ProtobufDataFormat.java index c820885f7d8f1..27b3112138ba9 100644 --- a/components/camel-protobuf/src/main/java/org/apache/camel/dataformat/protobuf/ProtobufDataFormat.java +++ b/components/camel-protobuf/src/main/java/org/apache/camel/dataformat/protobuf/ProtobufDataFormat.java @@ -32,6 +32,9 @@ import org.apache.camel.Exchange; import org.apache.camel.InvalidPayloadException; import org.apache.camel.NoTypeConversionAvailableException; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatContentTypeHeader; import org.apache.camel.spi.DataFormatName; @@ -48,6 +51,23 @@ + "enableFeatures,disableFeatures,allowUnmarshallType,timezone,autoDiscoverObjectMapper," + "schemaResolver,autoDiscoverSchemaResolver,unmarshalType,unmarshalTypeName") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.POJO, Carrier.MAP }, + description = "A protobuf Message of a generated class, or a Map of the fields of the" + + " instanceClass message, which needs instanceClass. JSON text is not" + + " converted"), + marshalOut = @BodyType(value = Carrier.STREAM, + description = "The protobuf binary data, or JSON with contentTypeFormat json, in the stream" + + " cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + byOption = @BodyType.When(option = "contentTypeFormat", value = "json", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }), + description = "Protobuf binary data, or JSON with contentTypeFormat json: unmarshal fails" + + " without instanceClass"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "com.google.protobuf.Message", + description = "The generated class of instanceClass, such as AddressBookProtos$Person;" + + " convertBodyTo Map gives its fields")) public class ProtobufDataFormat extends ServiceSupport implements DataFormat, DataFormatName, DataFormatContentTypeHeader, CamelContextAware { diff --git a/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/dataformat/smooks/smooks.json b/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/dataformat/smooks/smooks.json index 1b47b2463d9f0..394866d941986 100644 --- a/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/dataformat/smooks/smooks.json +++ b/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/dataformat/smooks/smooks.json @@ -15,6 +15,12 @@ "modelName": "smooks", "modelJavaType": "org.apache.camel.model.dataformat.SmooksDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "map", "list", "pojo" ], "description": "A Java object graph, such as the beans unmarshal gives, which Smooks reads as a JavaSource. Text, bytes or a stream are not parsed: Smooks reads them as a Java object too" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The text Smooks writes in UTF-8, such as the XML of the object graph or the output of a template of the config, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data the reader of the smooks config reads: XML by default, or EDI, CSV or JSON with a reader" }, + "unmarshalOut": { "carriers": [ "unknown" ], "description": "What the exports of the smooks config give: the bean a JavaSink export extracts (a Map of the beans when it extracts several or none), the text of a StringSink, or a List of the results of several exports (empty without exports)" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "smooksConfig": { "index": 1, "kind": "attribute", "displayName": "Smooks Config", "group": "common", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Path to the Smooks configuration file." }, diff --git a/components/camel-smooks/src/main/java/org/apache/camel/dataformat/smooks/SmooksDataFormat.java b/components/camel-smooks/src/main/java/org/apache/camel/dataformat/smooks/SmooksDataFormat.java index fb979ccdf3a8f..7b6e50cccb391 100644 --- a/components/camel-smooks/src/main/java/org/apache/camel/dataformat/smooks/SmooksDataFormat.java +++ b/components/camel-smooks/src/main/java/org/apache/camel/dataformat/smooks/SmooksDataFormat.java @@ -30,6 +30,9 @@ import org.apache.camel.component.smooks.SmooksComponent; import org.apache.camel.component.smooks.SmooksProcessor; import org.apache.camel.component.smooks.SmooksSecuritySupport; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.annotations.Dataformat; import org.apache.camel.support.CamelContextHelper; @@ -60,6 +63,22 @@ *

*/ @Dataformat("smooks") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.MAP, Carrier.LIST, Carrier.POJO }, + description = "A Java object graph, such as the beans unmarshal gives, which Smooks reads as a" + + " JavaSource. Text, bytes or a stream are not parsed: Smooks reads them as a" + + " Java object too"), + marshalOut = @BodyType(value = Carrier.STREAM, + description = "The text Smooks writes in UTF-8, such as the XML of the object graph or the" + + " output of a template of the config, in the stream cache, or a byte array" + + " when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The data the reader of the smooks config reads: XML by default, or EDI, CSV" + + " or JSON with a reader"), + unmarshalOut = @BodyType(value = Carrier.UNKNOWN, + description = "What the exports of the smooks config give: the bean a JavaSink export" + + " extracts (a Map of the beans when it extracts several or none), the text" + + " of a StringSink, or a List of the results of several exports (empty" + + " without exports)")) public class SmooksDataFormat extends ServiceSupport implements DataFormat, CamelContextAware { private Smooks smooks; diff --git a/components/camel-tarfile/src/generated/resources/META-INF/org/apache/camel/dataformat/tarfile/tarFile.json b/components/camel-tarfile/src/generated/resources/META-INF/org/apache/camel/dataformat/tarfile/tarFile.json index e8de72f7835f4..c18e1f82a8231 100644 --- a/components/camel-tarfile/src/generated/resources/META-INF/org/apache/camel/dataformat/tarfile/tarFile.json +++ b/components/camel-tarfile/src/generated/resources/META-INF/org/apache/camel/dataformat/tarfile/tarFile.json @@ -15,6 +15,12 @@ "modelName": "tarFile", "modelJavaType": "org.apache.camel.model.dataformat.TarFileDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The content of the one entry: text, bytes, a stream or a file. The entry size is the CamelFileLength header, or else what the stream has available, and must match the content" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The tar file, not compressed, in the stream cache, or a byte array when stream caching is off. The CamelFileName header is the entry name with .tar" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "A tar file with one entry, or with several when usingIterator. A .tar.gz is unmarshalled with gzipDeflater first" }, + "unmarshalOut": { "carriers": [ "stream" ], "byOption": [ { "option": "usingIterator", "value": "true", "carriers": [ "iterator" ], "javaType": "org.apache.camel.dataformat.tarfile.TarIterator" } ], "description": "The content of the one entry in the stream cache, or a byte array when stream caching is off; a tar with more entries, a folder too, fails. With usingIterator, an Iterator for a streaming split EIP: of messages whose body streams one file of the archive, to read before the next" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "usingIterator": { "index": 1, "kind": "attribute", "displayName": "Using Iterator", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use an iterator to split tar entries when the tar file has more than one entry, for use with the splitter EIP in streaming mode." }, diff --git a/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc b/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc index 208d3d504277e..ac5a5cf9268d6 100644 --- a/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc +++ b/components/camel-tarfile/src/main/docs/tarFile-dataformat.adoc @@ -9,10 +9,11 @@ *Since Camel {since}* -The Tar File Data Format is a message compression -and decompression format. Messages can be marshalled (compressed) to -Tar Files containing a single entry, and Tar Files containing a single -entry can be unmarshalled (decompressed) to the original file contents. +The Tar File Data Format is a message archiving format. Messages can be +marshalled to Tar Files containing a single entry, and Tar Files containing a +single entry can be unmarshalled to the original file contents. The Tar File +is not compressed: for a `.tar.gz`, marshal it with the +xref:dataformats:gzipDeflater-dataformat.adoc[gzipDeflater] data format as well. There is also an aggregation strategy that can aggregate multiple messages into a single Tar File. @@ -27,9 +28,8 @@ include::partial$dataformat-options.adoc[] == Marshal -In this example, we marshal a regular text/XML payload to a compressed -payload using Tar File compression, and send it to an ActiveMQ queue -called MY_QUEUE. +In this example, we marshal a regular text/XML payload to a Tar File +payload, and send it to an ActiveMQ queue called MY_QUEUE. [tabs] ==== @@ -74,7 +74,7 @@ The name of the Tar entry inside the created Tar File is based on the incoming `CamelFileName` message header, which is the standard message header used by the file component. Additionally, the outgoing `CamelFileName` message header is automatically set to the -value of the incoming `CamelFileName` message header, with the ".tar" +file name of the incoming `CamelFileName` message header, without its path, with the ".tar" suffix. So, for example, if the following route finds a file named "test.txt" in the input directory, the output will be a Tar File named "test.txt.tar" containing a single Tar entry named "test.txt": @@ -219,7 +219,9 @@ like this .end(); ---- -IMPORTANT: You cannot use TarSplitter in _parallel_ mode with the splitter. +IMPORTANT: You cannot use TarSplitter in _parallel_ mode with the splitter. The splitter must be _streaming_ too: the +body of each message streams its entry from the Tar File, which is read on as the splitter goes, so a splitter that +is not streaming gives messages with empty bodies. == Aggregate diff --git a/components/camel-tarfile/src/main/java/org/apache/camel/dataformat/tarfile/TarFileDataFormat.java b/components/camel-tarfile/src/main/java/org/apache/camel/dataformat/tarfile/TarFileDataFormat.java index eadf65c5dc79a..5358d42b63212 100644 --- a/components/camel-tarfile/src/main/java/org/apache/camel/dataformat/tarfile/TarFileDataFormat.java +++ b/components/camel-tarfile/src/main/java/org/apache/camel/dataformat/tarfile/TarFileDataFormat.java @@ -25,6 +25,9 @@ import java.util.Iterator; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -45,6 +48,25 @@ * Tar file data format. Based on ZipFileDataFormat from camel-zipfile component */ @Dataformat("tarFile") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The content of the one entry: text, bytes, a stream or a file. The entry size" + + " is the CamelFileLength header, or else what the stream has available, and" + + " must match the content"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The tar file, not compressed, in the stream cache, or a byte array when" + + " stream caching is off. The CamelFileName header is the entry name with" + + " .tar"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "A tar file with one entry, or with several when usingIterator. A .tar.gz" + + " is unmarshalled with gzipDeflater first"), + unmarshalOut = @BodyType(value = Carrier.STREAM, + byOption = @BodyType.When(option = "usingIterator", value = "true", + carriers = Carrier.ITERATOR, + javaType = "org.apache.camel.dataformat.tarfile.TarIterator"), + description = "The content of the one entry in the stream cache, or a byte array when" + + " stream caching is off; a tar with more entries, a folder too, fails." + + " With usingIterator, an Iterator for a streaming split EIP: of messages" + + " whose body streams one file of the archive, to read before the next")) public class TarFileDataFormat extends ServiceSupport implements DataFormat, DataFormatName { /** * The default maximum decompressed size (in bytes), which corresponds to 1G. diff --git a/components/camel-thrift/src/generated/resources/META-INF/org/apache/camel/dataformat/thrift/thrift.json b/components/camel-thrift/src/generated/resources/META-INF/org/apache/camel/dataformat/thrift/thrift.json index 5c23c04979263..616ce922f40b5 100644 --- a/components/camel-thrift/src/generated/resources/META-INF/org/apache/camel/dataformat/thrift/thrift.json +++ b/components/camel-thrift/src/generated/resources/META-INF/org/apache/camel/dataformat/thrift/thrift.json @@ -15,6 +15,12 @@ "modelName": "thrift", "modelJavaType": "org.apache.camel.model.dataformat.ThriftDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "pojo" ], "javaType": "org.apache.thrift.TBase", "description": "An object of a class the Thrift compiler generated, as unmarshal gives. The body is not converted: other bodies fail" }, + "marshalOut": { "carriers": [ "stream" ], "description": "The Thrift binary data, or JSON with contentTypeFormat json or sjson, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "dependsOn": [ "contentTypeFormat" ], "byOption": [ { "option": "contentTypeFormat", "value": "binary", "carriers": [ "bytes", "stream", "file" ] }, { "option": "contentTypeFormat", "value": "json", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "Thrift binary data, or with contentTypeFormat json the Thrift JSON protocol (field ids and types) as marshal writes it. sjson is for marshal only" }, + "unmarshalOut": { "carriers": [ "pojo" ], "javaType": "org.apache.thrift.TBase", "dependsOn": [ "contentTypeFormat" ], "byOption": [ { "option": "contentTypeFormat", "value": "binary", "carriers": [ "pojo" ], "javaType": "org.apache.thrift.TBase" }, { "option": "contentTypeFormat", "value": "json", "carriers": [ "pojo" ], "javaType": "org.apache.thrift.TBase" } ], "description": "An object of the class instanceClass names: unmarshal fails without it" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "instanceClass": { "index": 1, "kind": "attribute", "displayName": "Instance Class", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Name of class to use when unmarshalling." }, diff --git a/components/camel-thrift/src/main/docs/thrift-dataformat.adoc b/components/camel-thrift/src/main/docs/thrift-dataformat.adoc index 5fe872609a507..dcdf08c4e9441 100644 --- a/components/camel-thrift/src/main/docs/thrift-dataformat.adoc +++ b/components/camel-thrift/src/main/docs/thrift-dataformat.adoc @@ -28,7 +28,8 @@ include::partial$dataformat-options.adoc[] It's possible to parse JSON message to convert it to the Thrift format and serialize it back using native util converter. To use this option, set contentTypeFormat value to 'json' or call thrift with second parameter. -If the default instance is not specified, always use the native binary Thrift format. +Unmarshal needs the default instance (`instanceClass`) in the binary and json formats; marshal writes the given Thrift +object in any of them. The simple JSON format is write-only (marshal) and produces a simple output format suitable for parsing by scripting languages. The sample code shows below: diff --git a/components/camel-thrift/src/main/java/org/apache/camel/dataformat/thrift/ThriftDataFormat.java b/components/camel-thrift/src/main/java/org/apache/camel/dataformat/thrift/ThriftDataFormat.java index 83530bfafef20..9be654c887409 100644 --- a/components/camel-thrift/src/main/java/org/apache/camel/dataformat/thrift/ThriftDataFormat.java +++ b/components/camel-thrift/src/main/java/org/apache/camel/dataformat/thrift/ThriftDataFormat.java @@ -24,6 +24,9 @@ import org.apache.camel.CamelContextAware; import org.apache.camel.CamelException; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatContentTypeHeader; import org.apache.camel.spi.DataFormatName; @@ -40,6 +43,32 @@ import org.apache.thrift.protocol.TSimpleJSONProtocol; @Dataformat("thrift") +@BodyTypes(marshalIn = @BodyType(value = Carrier.POJO, javaType = "org.apache.thrift.TBase", + description = "An object of a class the Thrift compiler generated, as unmarshal gives. The" + + " body is not converted: other bodies fail"), + marshalOut = @BodyType(value = Carrier.STREAM, + description = "The Thrift binary data, or JSON with contentTypeFormat json or sjson, in the" + + " stream cache, or a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, dependsOn = "contentTypeFormat", + byOption = { + @BodyType.When(option = "contentTypeFormat", value = "binary", + carriers = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }), + @BodyType.When(option = "contentTypeFormat", value = "json", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }) }, + description = "Thrift binary data, or with contentTypeFormat json the Thrift JSON protocol" + + " (field ids and types) as marshal writes it. sjson is for marshal only"), + unmarshalOut = @BodyType(value = Carrier.POJO, javaType = "org.apache.thrift.TBase", + dependsOn = "contentTypeFormat", + byOption = { + @BodyType.When(option = "contentTypeFormat", value = "binary", + carriers = Carrier.POJO, + javaType = "org.apache.thrift.TBase"), + @BodyType.When(option = "contentTypeFormat", value = "json", + carriers = Carrier.POJO, + javaType = "org.apache.thrift.TBase") }, + description = "An object of the class instanceClass names: unmarshal fails without it")) public class ThriftDataFormat extends ServiceSupport implements DataFormat, DataFormatName, DataFormatContentTypeHeader, CamelContextAware { diff --git a/components/camel-xmlsecurity/src/generated/resources/META-INF/org/apache/camel/dataformat/xmlsecurity/xmlSecurity.json b/components/camel-xmlsecurity/src/generated/resources/META-INF/org/apache/camel/dataformat/xmlsecurity/xmlSecurity.json index 807dbb9586178..f83608db4ae07 100644 --- a/components/camel-xmlsecurity/src/generated/resources/META-INF/org/apache/camel/dataformat/xmlsecurity/xmlSecurity.json +++ b/components/camel-xmlsecurity/src/generated/resources/META-INF/org/apache/camel/dataformat/xmlsecurity/xmlSecurity.json @@ -15,6 +15,12 @@ "modelName": "xmlSecurity", "modelJavaType": "org.apache.camel.model.dataformat.XMLSecurityDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "The XML: text, bytes, a stream, a file, a DOM Document, a DOMSource or a StreamSource" }, + "marshalOut": { "carriers": [ "stream" ], "format": "xml", "description": "The XML with EncryptedData elements, in the stream cache, or a byte array when stream caching is off. Without secureTag the whole document is encrypted; with it the elements it selects, or their content when secureTagContents is true" }, + "unmarshalIn": { "carriers": [ "text", "bytes", "stream", "file", "pojo" ], "format": "xml", "description": "The XML with EncryptedData elements: text, bytes, a stream, a file, a DOM Document, a DOMSource or a StreamSource" }, + "unmarshalOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "format": "xml", "description": "The decrypted XML document, as a byte array" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "xmlCipherAlgorithm": { "index": 1, "kind": "attribute", "displayName": "Xml Cipher Algorithm", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.String", "enum": [ "TRIPLEDES", "AES_128", "AES_128_GCM", "AES_192", "AES_192_GCM", "AES_256", "AES_256_GCM", "SEED_128", "CAMELLIA_128", "CAMELLIA_192", "CAMELLIA_256" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "AES_256_GCM", "description": "The cipher algorithm to be used for encryption\/decryption of the XML message content." }, diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java index d49891116b3e6..bb59abec9aa97 100644 --- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java +++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/dataformat/xmlsecurity/XMLSecurityDataFormat.java @@ -50,6 +50,9 @@ import org.apache.camel.StreamCache; import org.apache.camel.language.xpath.DefaultNamespaceContext; import org.apache.camel.language.xpath.XPathBuilder; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -69,6 +72,21 @@ import org.slf4j.LoggerFactory; @Dataformat("xmlSecurity") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", + description = "The XML: text, bytes, a stream, a file, a DOM Document, a DOMSource or a" + + " StreamSource"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "xml", + description = "The XML with EncryptedData elements, in the stream cache, or a byte array when" + + " stream caching is off. Without secureTag the whole document is encrypted;" + + " with it the elements it selects, or their content when secureTagContents" + + " is true"), + unmarshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE, Carrier.POJO }, + format = "xml", + description = "The XML with EncryptedData elements: text, bytes, a stream, a file, a DOM" + + " Document, a DOMSource or a StreamSource"), + unmarshalOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]", format = "xml", + description = "The decrypted XML document, as a byte array")) public class XMLSecurityDataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware { private static final Logger LOG = LoggerFactory.getLogger(XMLSecurityDataFormat.class); diff --git a/components/camel-zip-deflater/src/generated/resources/META-INF/org/apache/camel/dataformat/deflater/gzipDeflater.json b/components/camel-zip-deflater/src/generated/resources/META-INF/org/apache/camel/dataformat/deflater/gzipDeflater.json index ef97b73d91259..0b4becc027ec8 100644 --- a/components/camel-zip-deflater/src/generated/resources/META-INF/org/apache/camel/dataformat/deflater/gzipDeflater.json +++ b/components/camel-zip-deflater/src/generated/resources/META-INF/org/apache/camel/dataformat/deflater/gzipDeflater.json @@ -15,6 +15,12 @@ "modelName": "gzipDeflater", "modelJavaType": "org.apache.camel.model.dataformat.GzipDeflaterDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data to compress: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The gzip data, as in a .gz file, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Gzip data, such as a .gz file; gzip members one after the other are read as one" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decompressed data in the stream cache, or a byte array when stream caching is off" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" } } diff --git a/components/camel-zip-deflater/src/generated/resources/META-INF/org/apache/camel/dataformat/deflater/zipDeflater.json b/components/camel-zip-deflater/src/generated/resources/META-INF/org/apache/camel/dataformat/deflater/zipDeflater.json index a5c9ee1b7475f..5415be8522b7e 100644 --- a/components/camel-zip-deflater/src/generated/resources/META-INF/org/apache/camel/dataformat/deflater/zipDeflater.json +++ b/components/camel-zip-deflater/src/generated/resources/META-INF/org/apache/camel/dataformat/deflater/zipDeflater.json @@ -15,6 +15,12 @@ "modelName": "zipDeflater", "modelJavaType": "org.apache.camel.model.dataformat.ZipDeflaterDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The data to compress: text in the charset of the exchange, bytes, a stream or a file" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The deflate data in the zlib format, not a zip file, in the stream cache, or a byte array when stream caching is off" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "Deflate data in the zlib format, such as marshal gives with any compressionLevel" }, + "unmarshalOut": { "carriers": [ "stream" ], "description": "The decompressed data in the stream cache, or a byte array when stream caching is off" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "compressionLevel": { "index": 1, "kind": "attribute", "displayName": "Compression Level", "group": "common", "required": false, "type": "enum", "javaType": "java.lang.Integer", "enum": [ "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "-1", "description": "Compression level to use (0-9). -1 is default compression, 0 is no compression, and 9 is the best compression." } diff --git a/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc b/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc index aeffae59cc68a..741a2bf4c8df4 100644 --- a/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc +++ b/components/camel-zip-deflater/src/main/docs/gzipDeflater-dataformat.adoc @@ -21,8 +21,10 @@ using `gzip` tool. [NOTE] ==== -This dataformat is not for working with gzip files such as uncompressing and building gzip files. -Instead, use the xref:dataformats:zipFile-dataformat.adoc[zipfile] dataformat. +Marshal writes the gzip format of a `.gz` file, and unmarshal reads it, so this data format builds and uncompresses +gzip files. A `.tar.gz` file is a tar archive in gzip: unmarshal it with gzipDeflater, then with the +xref:dataformats:tarFile-dataformat.adoc[tarFile] data format. For zip files, use the +xref:dataformats:zipFile-dataformat.adoc[zipFile] data format. ==== == Options diff --git a/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc b/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc index 2f1b58ac3100c..3e6b7b91df176 100644 --- a/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc +++ b/components/camel-zip-deflater/src/main/docs/zipDeflater-dataformat.adoc @@ -84,9 +84,8 @@ YAML:: In this example, we unmarshal a zipped payload from an ActiveMQ queue called MY_QUEUE to its original format, and forward it for processing to -the UnZippedMessageProcessor. Note that the compression Level employed -during marshaling should be identical to the one employed during -unmarshalling to avoid errors. +the UnZippedMessageProcessor. Unmarshal reads the data of any +compression level, so the level of the marshal does not need to be set. ._Java-only: inline Processor instance_ [source,java] diff --git a/components/camel-zip-deflater/src/main/java/org/apache/camel/dataformat/deflater/GzipDeflaterDataFormat.java b/components/camel-zip-deflater/src/main/java/org/apache/camel/dataformat/deflater/GzipDeflaterDataFormat.java index 78bd5ae099a19..1d948183a314a 100644 --- a/components/camel-zip-deflater/src/main/java/org/apache/camel/dataformat/deflater/GzipDeflaterDataFormat.java +++ b/components/camel-zip-deflater/src/main/java/org/apache/camel/dataformat/deflater/GzipDeflaterDataFormat.java @@ -21,6 +21,9 @@ import java.io.OutputStream; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -34,6 +37,18 @@ * GZip {@link org.apache.camel.spi.DataFormat} for reading/writing data using gzip. */ @Dataformat("gzipDeflater") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The data to compress: text in the charset of the exchange, bytes, a stream" + + " or a file"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The gzip data, as in a .gz file, in the stream cache, or a byte array when" + + " stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "Gzip data, such as a .gz file; gzip members one after the other are read as" + + " one"), + unmarshalOut = @BodyType(value = Carrier.STREAM, + description = "The decompressed data in the stream cache, or a byte array when stream" + + " caching is off")) public class GzipDeflaterDataFormat extends ServiceSupport implements DataFormat, DataFormatName { @Override diff --git a/components/camel-zip-deflater/src/main/java/org/apache/camel/dataformat/deflater/ZipDeflaterDataFormat.java b/components/camel-zip-deflater/src/main/java/org/apache/camel/dataformat/deflater/ZipDeflaterDataFormat.java index 2b6c61b82fe4b..8255b2061a85a 100644 --- a/components/camel-zip-deflater/src/main/java/org/apache/camel/dataformat/deflater/ZipDeflaterDataFormat.java +++ b/components/camel-zip-deflater/src/main/java/org/apache/camel/dataformat/deflater/ZipDeflaterDataFormat.java @@ -23,6 +23,9 @@ import java.util.zip.InflaterInputStream; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -34,6 +37,18 @@ * Deflate (zip) compression data format (does not support zip files, instead use zipfile dataformat). */ @Dataformat("zipDeflater") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The data to compress: text in the charset of the exchange, bytes, a stream" + + " or a file"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The deflate data in the zlib format, not a zip file, in the stream cache, or" + + " a byte array when stream caching is off"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "Deflate data in the zlib format, such as marshal gives with any" + + " compressionLevel"), + unmarshalOut = @BodyType(value = Carrier.STREAM, + description = "The decompressed data in the stream cache, or a byte array when stream" + + " caching is off")) public class ZipDeflaterDataFormat extends ServiceSupport implements DataFormat, DataFormatName { private int compressionLevel; diff --git a/components/camel-zipfile/src/generated/resources/META-INF/org/apache/camel/dataformat/zipfile/zipFile.json b/components/camel-zipfile/src/generated/resources/META-INF/org/apache/camel/dataformat/zipfile/zipFile.json index fc77b1a60e734..4f10e3ce1307d 100644 --- a/components/camel-zipfile/src/generated/resources/META-INF/org/apache/camel/dataformat/zipfile/zipFile.json +++ b/components/camel-zipfile/src/generated/resources/META-INF/org/apache/camel/dataformat/zipfile/zipFile.json @@ -15,6 +15,12 @@ "modelName": "zipFile", "modelJavaType": "org.apache.camel.model.dataformat.ZipFileDataFormat" }, + "bodyTypes": { + "marshalIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "The content of the one entry: text in the charset of the exchange, bytes, a stream or a file. The entry name is the file name of the CamelFileName header (its whole path with preservePathElements), or the message id" }, + "marshalOut": { "carriers": [ "stream" ], "format": "binary", "description": "The zip file in the stream cache, or a byte array when stream caching is off. The CamelFileName header is the entry name with .zip" }, + "unmarshalIn": { "carriers": [ "bytes", "stream", "file" ], "format": "binary", "description": "A zip file with one entry, or with several when usingIterator" }, + "unmarshalOut": { "carriers": [ "stream" ], "byOption": [ { "option": "usingIterator", "value": "true", "carriers": [ "iterator" ], "javaType": "org.apache.camel.dataformat.zipfile.ZipIterator" } ], "description": "The content of the one entry in the stream cache, or a byte array when stream caching is off; a zip with more entries, a folder too, fails. With usingIterator, an Iterator for the split EIP: of messages with the content of one file each, in a stream cache" } + }, "properties": { "id": { "index": 0, "kind": "attribute", "displayName": "Id", "group": "common", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" }, "usingIterator": { "index": 1, "kind": "attribute", "displayName": "Using Iterator", "group": "common", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If the zip file has more than one entry, the setting this option to true, allows working with the splitter EIP, to split the data using an iterator in a streaming mode." }, diff --git a/components/camel-zipfile/src/main/docs/zipFile-dataformat.adoc b/components/camel-zipfile/src/main/docs/zipFile-dataformat.adoc index eb8970c15a581..bcf8de12fc820 100644 --- a/components/camel-zipfile/src/main/docs/zipFile-dataformat.adoc +++ b/components/camel-zipfile/src/main/docs/zipFile-dataformat.adoc @@ -69,7 +69,7 @@ The name of the Zip entry inside the created Zip file is based on the incoming `CamelFileName` message header, which is the standard message header used by the file component. Additionally, the outgoing `CamelFileName` message header is automatically set to the -value of the incoming `CamelFileName` message header, with the ".zip" +file name of the incoming `CamelFileName` message header, without its path, with the ".zip" suffix. So, for example, if the following route finds a file named "test.txt" in the input directory, the output will be a Zip file named "test.txt.zip" containing a single Zip entry named "test.txt": diff --git a/components/camel-zipfile/src/main/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormat.java b/components/camel-zipfile/src/main/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormat.java index 97b5ebef91339..0d9315abcbbc9 100644 --- a/components/camel-zipfile/src/main/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormat.java +++ b/components/camel-zipfile/src/main/java/org/apache/camel/dataformat/zipfile/ZipFileDataFormat.java @@ -25,6 +25,9 @@ import java.util.Iterator; import org.apache.camel.Exchange; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataFormatName; import org.apache.camel.spi.annotations.Dataformat; @@ -45,6 +48,23 @@ * Zip file data format. */ @Dataformat("zipFile") +@BodyTypes(marshalIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "The content of the one entry: text in the charset of the exchange, bytes, a" + + " stream or a file. The entry name is the file name of the CamelFileName" + + " header (its whole path with preservePathElements), or the message id"), + marshalOut = @BodyType(value = Carrier.STREAM, format = "binary", + description = "The zip file in the stream cache, or a byte array when stream caching is off." + + " The CamelFileName header is the entry name with .zip"), + unmarshalIn = @BodyType(value = { Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, format = "binary", + description = "A zip file with one entry, or with several when usingIterator"), + unmarshalOut = @BodyType(value = Carrier.STREAM, + byOption = @BodyType.When(option = "usingIterator", value = "true", + carriers = Carrier.ITERATOR, + javaType = "org.apache.camel.dataformat.zipfile.ZipIterator"), + description = "The content of the one entry in the stream cache, or a byte array when" + + " stream caching is off; a zip with more entries, a folder too, fails. With" + + " usingIterator, an Iterator for the split EIP: of messages with the" + + " content of one file each, in a stream cache")) public class ZipFileDataFormat extends ServiceSupport implements DataFormat, DataFormatName { /** diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java index 44b57a2428ea8..620acf8bab550 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java @@ -1156,6 +1156,49 @@ public void testTheBodyOfTextDataFormats() { .contains("route rows: to: file needs the body as text, bytes, a stream or a file")); } + @Test + public void testTheBodyOfBinaryDataFormats() { + // avro with its default library, Jackson, gives a Map, which the file producer cannot write; zipFile gives the + // content of the entry as a stream, cbor an object of a class, and fory what the data holds, which say nothing + String yaml = """ + - route: + id: avro + from: + uri: file:in + steps: + - unmarshal: + avro: {} + - to: file:out + - route: + id: zip + from: + uri: file:in + steps: + - unmarshal: + zipFile: {} + - to: file:out + - route: + id: cbor + from: + uri: file:in + steps: + - unmarshal: + cbor: + unmarshalType: com.acme.Order + - to: file:out + - route: + id: fory + from: + uri: file:in + steps: + - unmarshal: + fory: {} + - to: file:out + """; + assertThat(lines(yaml)).singleElement().satisfies(m -> assertThat(m) + .contains("route avro: to: file needs the body as text, bytes, a stream or a file")); + } + @Test public void testAnOptionTheBodyDependsOnOutweighsAnotherOption() { // xslt with output bytes gives bytes, so a field read needs an unmarshal; with a resultHandlerFactory too the From 7c24ffec7eeb333f146b66b823dab205be2b050f Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Thu, 22 Oct 2026 17:51:13 +0200 Subject: [PATCH 24/25] CAMEL-24961: Catalog body types for mail, paho, spring-rabbitmq, pulsar, nats and smpp Declares the body types of the second messaging group: the mail component (imap, imaps, pop3, pop3s, smtp and smtps), paho, spring-rabbitmq, pulsar, nats and smpp (smpp and smpps). All were checked at runtime with camel run: GreenMail for mail, camel infra for mosquitto, rabbitmq, pulsar and nats, and the jSMPP simulator for smpp. Fixes the doc prose about the body: the nats consumer replies only with exchangePattern=InOut and the producer gets the reply as bytes, the mail producer reads the body as text and sends a MimeMessage as it is, the split of mail attachments always gives their content as the body, and the smpp page and the CamelSmppEncoding header say how a body becomes the short message. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../apache/camel/catalog/components/imap.json | 5 ++ .../camel/catalog/components/imaps.json | 5 ++ .../apache/camel/catalog/components/nats.json | 6 ++ .../apache/camel/catalog/components/paho.json | 5 ++ .../apache/camel/catalog/components/pop3.json | 5 ++ .../camel/catalog/components/pop3s.json | 5 ++ .../camel/catalog/components/pulsar.json | 5 ++ .../apache/camel/catalog/components/smpp.json | 7 +- .../camel/catalog/components/smpps.json | 7 +- .../apache/camel/catalog/components/smtp.json | 5 ++ .../camel/catalog/components/smtps.json | 5 ++ .../catalog/components/spring-rabbitmq.json | 6 ++ .../camel/catalog/docs/mail-component.adoc | 17 ++-- .../camel/catalog/docs/nats-component.adoc | 7 +- .../camel/catalog/docs/smpp-component.adoc | 15 +++- .../org/apache/camel/component/mail/imap.json | 5 ++ .../apache/camel/component/mail/imaps.json | 5 ++ .../org/apache/camel/component/mail/pop3.json | 5 ++ .../apache/camel/component/mail/pop3s.json | 5 ++ .../org/apache/camel/component/mail/smtp.json | 5 ++ .../apache/camel/component/mail/smtps.json | 5 ++ .../src/main/docs/mail-component.adoc | 17 ++-- .../camel/component/mail/MailEndpoint.java | 20 +++++ .../org/apache/camel/component/nats/nats.json | 6 ++ .../src/main/docs/nats-component.adoc | 7 +- .../camel/component/nats/NatsEndpoint.java | 28 ++++++ .../org/apache/camel/component/paho/paho.json | 5 ++ .../camel/component/paho/PahoEndpoint.java | 8 ++ .../apache/camel/component/pulsar/pulsar.json | 5 ++ .../component/pulsar/PulsarEndpoint.java | 15 ++++ .../org/apache/camel/component/smpp/smpp.json | 7 +- .../apache/camel/component/smpp/smpps.json | 7 +- .../src/main/docs/smpp-component.adoc | 15 +++- .../camel/component/smpp/SmppConstants.java | 12 +-- .../camel/component/smpp/SmppEndpoint.java | 22 +++++ .../springrabbit/spring-rabbitmq.json | 6 ++ .../springrabbit/SpringRabbitMQEndpoint.java | 33 +++++++ .../dsl/yaml/validator/TextBodyFlowTest.java | 85 +++++++++++++++++++ 38 files changed, 387 insertions(+), 46 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/imap.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/imap.json index 8399bb76ec5a4..47a584bfbb93d 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/imap.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/imap.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/imaps.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/imaps.json index 183ccb7e37221..35c217ab9acdf 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/imaps.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/imaps.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/nats.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/nats.json index eca34ceb7d3c8..50696e1342789 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/nats.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/nats.json @@ -80,6 +80,12 @@ "CamelNatsDeliveryCounter": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "Number of times this message has been delivered (1 = first, 1 then message has been redelivered)", "constantName": "org.apache.camel.component.nats.NatsConstants#NATS_DELIVERY_COUNTER" }, "CamelNatsManualAck": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "org.apache.camel.component.nats.NatsManualAck", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The manual acknowledgment handle for JetStream messages (only set when manualAck=true).", "constantName": "org.apache.camel.component.nats.NatsConstants#NATS_MANUAL_ACK" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The payload of the NATS message as a byte array, empty for a message without one: convert or unmarshal it" }, + "consumerReply": { "carriers": [ "any" ], "byOption": [ { "option": "exchangePattern", "value": "InOut", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "Only with exchangePattern=InOut is a message with a reply subject answered, with the body the route ends with: text, bytes, a stream or a file. A Map, a POJO or no body sends no reply, and the requester times out" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "What converts to a byte array: text, bytes, a stream or a file. A Map or a POJO is sent as its toString(), and a List or no body fails: marshal it first" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "exchangePattern", "value": "InOut", "carriers": [ "bytes" ], "javaType": "byte[]" } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) waits for the reply, up to requestTimeout, and gets its payload as a byte array" } + }, "properties": { "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.nats.NatsConfiguration", "configurationField": "configuration", "description": "The name of topic we want to use" }, "connectionTimeout": { "index": 1, "kind": "parameter", "displayName": "Connection Timeout", "group": "common", "label": "common", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 2000, "configurationClass": "org.apache.camel.component.nats.NatsConfiguration", "configurationField": "configuration", "description": "Timeout for connection attempts. (in milliseconds)" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/paho.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/paho.json index 1ee428f6b2ebc..de99e56c6983c 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/paho.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/paho.json @@ -64,6 +64,11 @@ "CamelPahoRetained": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Retain option.", "constantName": "org.apache.camel.component.paho.PahoConstants#CAMEL_PAHO_MSG_RETAINED" }, "CamelPahoOverrideTopic": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of topic to override and send to instead of topic specified on endpoint.", "constantName": "org.apache.camel.component.paho.PahoConstants#CAMEL_PAHO_OVERRIDE_TOPIC" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The payload of the MQTT message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "What converts to a byte array: text, bytes, a stream or a file, sent as the payload. A Map, a POJO or no body fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the topic" }, "automaticReconnect": { "index": 1, "kind": "parameter", "displayName": "Automatic Reconnect", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.paho.PahoConfiguration", "configurationField": "configuration", "description": "Sets whether the client will automatically attempt to reconnect to the server if the connection is lost. If set to false, the client will not attempt to automatically reconnect to the server in the event that the connection is lost. If set to true, in the event that the connection is lost, the client will attempt to reconnect to the server. It will initially wait 1 second before it attempts to reconnect, for every failed reconnect attempt, the delay will double until it is at 2 minutes at which point the delay will stay at 2 minutes." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pop3.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pop3.json index d46e065460c7b..3c4eb46d823b3 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pop3.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pop3.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pop3s.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pop3s.json index 652f0c2be7484..0dbc734fa2968 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pop3s.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pop3s.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pulsar.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pulsar.json index edd57b05efb83..a4cce15a1aafc 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pulsar.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/pulsar.json @@ -94,6 +94,11 @@ "CamelPulsarProducerMessageDeliverAfter": { "index": 15, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deliver the message after a given delayed time (millis).", "constantName": "org.apache.camel.component.pulsar.utils.message.PulsarMessageHeaders#DELIVER_AFTER" }, "CamelPulsarProducerMessageId": { "index": 16, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.apache.pulsar.client.api.MessageId", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message id the broker assigned to the published message.", "constantName": "org.apache.camel.component.pulsar.utils.message.PulsarMessageHeaders#PRODUCER_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes", "null" ], "javaType": "byte[]", "description": "The payload of the Pulsar message as a byte array, null for a message with a null value (a tombstone), with the key and the properties in headers: convert or unmarshal it" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "What converts to a byte array: text, bytes, a stream or a file, sent as the payload. Any other body is sent with Java serialization, a Map, a List, a number and no body too, and an object that is not Serializable fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, also when the exchange expects a reply, with the id of the published message in a header" } + }, "properties": { "persistence": { "index": 0, "kind": "path", "displayName": "Persistence", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "persistent", "non-persistent" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Whether the topic is persistent or non-persistent" }, "tenant": { "index": 1, "kind": "path", "displayName": "Tenant", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The tenant" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smpp.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smpp.json index dc937fb26f6af..51702b25e413f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smpp.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smpp.json @@ -82,7 +82,7 @@ "CamelSmppDestAddrNpi": { "index": 8, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Byte", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti, CancelSm and DataSm Defines the numeric plan indicator (NPI) to be used in the SME destination address parameters. Use the URI option sourceAddrNpi values defined above. Consumer: only for DataSm Defines the numeric plan indicator (NPI) in the destination address parameters. Use the URI option sourceAddrNpi values defined above.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DEST_ADDR_NPI" }, "CamelSmppDestAddrTon": { "index": 9, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Byte", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti, CancelSm and DataSm Defines the type of number (TON) to be used in the SME destination address parameters. Use the sourceAddrTon URI option values defined above. Consumer: only for DataSm Defines the type of number (TON) in the destination address parameters. Use the sourceAddrTon URI option values defined above.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DEST_ADDR_TON" }, "CamelSmppDoneDate": { "index": 10, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for smsc DeliveryReceipt The time and date at which the short message reached it's final state. The format is as follows: YYMMDDhhmm.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DONE_DATE" }, - "CamelSmppEncoding": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and DataSm. Specifies the encoding (character set name) of the bytes in the message body. If the message body is a string then this is not relevant because Java Strings are always Unicode. If the body is a byte array then this header can be used to indicate that it is ISO-8859-1 or some other value. Default value is specified by the endpoint configuration parameter _encoding_", "constantName": "org.apache.camel.component.smpp.SmppConstants#ENCODING" }, + "CamelSmppEncoding": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and ReplaceSm. Specifies the encoding (character set name) the text of the message body is encoded in, as the short message. A byte array body is first read as text, in the charset of the exchange, unless an 8-bit data coding or alphabet header sends it as it is. Default value is specified by the endpoint configuration parameter _encoding_", "constantName": "org.apache.camel.component.smpp.SmppConstants#ENCODING" }, "CamelSmppError": { "index": 12, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String or Map>>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitMultiSm The errors which occurred by sending the short message(s) the form Map (messageID : (destAddr : address, error : errorCode)). Consumer: only for smsc DeliveryReceipt Where appropriate this may hold a Network specific error code or an SMSC error code for the attempted delivery of the message. These errors are Network or SMSC specific and are not included here.", "constantName": "org.apache.camel.component.smpp.SmppConstants#ERROR" }, "CamelSmppClass": { "index": 13, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.jsmpp.bean.ESMClass", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "the ASM class", "constantName": "org.apache.camel.component.smpp.SmppConstants#ESM_CLASS" }, "CamelSmppEsmeAddr": { "index": 14, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for AlertNotification Defines the destination ESME address. For mobile terminated messages, this is the directory number of the recipient MS.", "constantName": "org.apache.camel.component.smpp.SmppConstants#ESME_ADDR" }, @@ -114,6 +114,11 @@ "CamelSmppOptionalParameter": { "index": 40, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti and DataSm The optional parameter which are send to the SMSC. The value is converted in the following way: String - org.jsmpp.bean.OptionalParameter.COctetString, byte - org.jsmpp.bean.OptionalParameter.OctetString, Byte - org.jsmpp.bean.OptionalParameter.Byte, Integer - org.jsmpp.bean.OptionalParameter.Int, Short - org.jsmpp.bean.OptionalParameter.Short, null - org.jsmpp.bean.OptionalParameter.Null Consumer: only for DeliverSm The optional parameters send back by the SMSC. The key is the Short code for the optional parameter. The value is converted in the following way: org.jsmpp.bean.OptionalParameter.COctetString - String, org.jsmpp.bean.OptionalParameter.OctetString - byte, org.jsmpp.bean.OptionalParameter.Byte - Byte, org.jsmpp.bean.OptionalParameter.Int - Integer, org.jsmpp.bean.OptionalParameter.Short - Short, org.jsmpp.bean.OptionalParameter.Null - null", "constantName": "org.apache.camel.component.smpp.SmppConstants#OPTIONAL_PARAMETER" }, "CamelSmppSplittingPolicy": { "index": 41, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and DataSm. Specifies the policy for message splitting for this exchange. Possible values are described in the endpoint configuration parameter _splittingPolicy_", "constantName": "org.apache.camel.component.smpp.SmppConstants#SPLITTING_POLICY" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "null" ], "description": "A short message as text decoded by its data coding, or as bytes for an 8-bit data coding; the text of a delivery receipt, with its fields in headers. A data_sm or an alert notification has no body" }, + "producerIn": { "carriers": [ "text", "bytes", "file" ], "description": "The text of the short message: bytes or a file are read as text, unless an 8-bit CamelSmppDataCoding or CamelSmppAlphabet header sends bytes as they are. A stream is sent empty and no body fails: convert it to text first; a Map or a POJO is sent as its toString(). DataSm, QuerySm and CancelSm do not read the body" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "exchangePattern", "value": "InOut", "carriers": [ "null" ] } ], "description": "Unchanged, with the message ids in the CamelSmppId header. When the exchange expects a reply (InOut), a new message with no body and only the result headers" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.smpp.SmppConfiguration", "configurationField": "configuration", "description": "Hostname for the SMSC server to use." }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 2775, "configurationClass": "org.apache.camel.component.smpp.SmppConfiguration", "configurationField": "configuration", "description": "Port number for the SMSC server to use." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smpps.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smpps.json index 1adce03c7ebbb..39a2de9049af4 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smpps.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smpps.json @@ -82,7 +82,7 @@ "CamelSmppDestAddrNpi": { "index": 8, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Byte", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti, CancelSm and DataSm Defines the numeric plan indicator (NPI) to be used in the SME destination address parameters. Use the URI option sourceAddrNpi values defined above. Consumer: only for DataSm Defines the numeric plan indicator (NPI) in the destination address parameters. Use the URI option sourceAddrNpi values defined above.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DEST_ADDR_NPI" }, "CamelSmppDestAddrTon": { "index": 9, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Byte", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti, CancelSm and DataSm Defines the type of number (TON) to be used in the SME destination address parameters. Use the sourceAddrTon URI option values defined above. Consumer: only for DataSm Defines the type of number (TON) in the destination address parameters. Use the sourceAddrTon URI option values defined above.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DEST_ADDR_TON" }, "CamelSmppDoneDate": { "index": 10, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for smsc DeliveryReceipt The time and date at which the short message reached it's final state. The format is as follows: YYMMDDhhmm.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DONE_DATE" }, - "CamelSmppEncoding": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and DataSm. Specifies the encoding (character set name) of the bytes in the message body. If the message body is a string then this is not relevant because Java Strings are always Unicode. If the body is a byte array then this header can be used to indicate that it is ISO-8859-1 or some other value. Default value is specified by the endpoint configuration parameter _encoding_", "constantName": "org.apache.camel.component.smpp.SmppConstants#ENCODING" }, + "CamelSmppEncoding": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and ReplaceSm. Specifies the encoding (character set name) the text of the message body is encoded in, as the short message. A byte array body is first read as text, in the charset of the exchange, unless an 8-bit data coding or alphabet header sends it as it is. Default value is specified by the endpoint configuration parameter _encoding_", "constantName": "org.apache.camel.component.smpp.SmppConstants#ENCODING" }, "CamelSmppError": { "index": 12, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String or Map>>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitMultiSm The errors which occurred by sending the short message(s) the form Map (messageID : (destAddr : address, error : errorCode)). Consumer: only for smsc DeliveryReceipt Where appropriate this may hold a Network specific error code or an SMSC error code for the attempted delivery of the message. These errors are Network or SMSC specific and are not included here.", "constantName": "org.apache.camel.component.smpp.SmppConstants#ERROR" }, "CamelSmppClass": { "index": 13, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.jsmpp.bean.ESMClass", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "the ASM class", "constantName": "org.apache.camel.component.smpp.SmppConstants#ESM_CLASS" }, "CamelSmppEsmeAddr": { "index": 14, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for AlertNotification Defines the destination ESME address. For mobile terminated messages, this is the directory number of the recipient MS.", "constantName": "org.apache.camel.component.smpp.SmppConstants#ESME_ADDR" }, @@ -114,6 +114,11 @@ "CamelSmppOptionalParameter": { "index": 40, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti and DataSm The optional parameter which are send to the SMSC. The value is converted in the following way: String - org.jsmpp.bean.OptionalParameter.COctetString, byte - org.jsmpp.bean.OptionalParameter.OctetString, Byte - org.jsmpp.bean.OptionalParameter.Byte, Integer - org.jsmpp.bean.OptionalParameter.Int, Short - org.jsmpp.bean.OptionalParameter.Short, null - org.jsmpp.bean.OptionalParameter.Null Consumer: only for DeliverSm The optional parameters send back by the SMSC. The key is the Short code for the optional parameter. The value is converted in the following way: org.jsmpp.bean.OptionalParameter.COctetString - String, org.jsmpp.bean.OptionalParameter.OctetString - byte, org.jsmpp.bean.OptionalParameter.Byte - Byte, org.jsmpp.bean.OptionalParameter.Int - Integer, org.jsmpp.bean.OptionalParameter.Short - Short, org.jsmpp.bean.OptionalParameter.Null - null", "constantName": "org.apache.camel.component.smpp.SmppConstants#OPTIONAL_PARAMETER" }, "CamelSmppSplittingPolicy": { "index": 41, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and DataSm. Specifies the policy for message splitting for this exchange. Possible values are described in the endpoint configuration parameter _splittingPolicy_", "constantName": "org.apache.camel.component.smpp.SmppConstants#SPLITTING_POLICY" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "null" ], "description": "A short message as text decoded by its data coding, or as bytes for an 8-bit data coding; the text of a delivery receipt, with its fields in headers. A data_sm or an alert notification has no body" }, + "producerIn": { "carriers": [ "text", "bytes", "file" ], "description": "The text of the short message: bytes or a file are read as text, unless an 8-bit CamelSmppDataCoding or CamelSmppAlphabet header sends bytes as they are. A stream is sent empty and no body fails: convert it to text first; a Map or a POJO is sent as its toString(). DataSm, QuerySm and CancelSm do not read the body" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "exchangePattern", "value": "InOut", "carriers": [ "null" ] } ], "description": "Unchanged, with the message ids in the CamelSmppId header. When the exchange expects a reply (InOut), a new message with no body and only the result headers" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.smpp.SmppConfiguration", "configurationField": "configuration", "description": "Hostname for the SMSC server to use." }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 2775, "configurationClass": "org.apache.camel.component.smpp.SmppConfiguration", "configurationField": "configuration", "description": "Port number for the SMSC server to use." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smtp.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smtp.json index c2e3c9652c513..e6517c9719790 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smtp.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smtp.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smtps.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smtps.json index 4682f6a3524c6..9bd4bd00f5a11 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smtps.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smtps.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/spring-rabbitmq.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/spring-rabbitmq.json index a2afee539d79a..e2ae70cd9c83b 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/spring-rabbitmq.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/spring-rabbitmq.json @@ -78,6 +78,12 @@ "CamelSpringRabbitmqPriority": { "index": 18, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message priority.", "constantName": "org.apache.camel.component.springrabbit.SpringRabbitMQConstants#PRIORITY" }, "CamelSpringRabbitmqClusterId": { "index": 19, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The cluster id.", "constantName": "org.apache.camel.component.springrabbit.SpringRabbitMQConstants#CLUSTER_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes" ], "dependsOn": [ "messageConverter" ], "description": "A String when the content type starts with text, as for text this component sends; a byte array otherwise, JSON and Java serialized objects too, which are not deserialized" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "messageConverter" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "The reply to a message with a reply-to, converted as the producer converts a body: a Map or a POJO fails" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "messageConverter" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "Text, bytes, a stream or a file, sent as a byte array, text as text\/plain unless the CamelSpringRabbitmqContentType header says another type. A Map or a POJO fails, as it is not serialized: marshal it first" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) gets the body of the reply as the consumer gives it: a String for a text content type, a byte array otherwise" } + }, "properties": { "exchangeName": { "index": 0, "kind": "path", "displayName": "Exchange Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The exchange name determines the exchange to which the produced messages will be sent to. In the case of consumers, the exchange name determines the exchange the queue will be bound to. Note: to use default exchange then do not use empty name, but use default instead." }, "connectionFactory": { "index": 1, "kind": "parameter", "displayName": "Connection Factory", "group": "common", "label": "common", "required": false, "type": "object", "javaType": "org.springframework.amqp.rabbit.connection.ConnectionFactory", "deprecated": false, "autowired": false, "secret": false, "description": "The connection factory to be use. A connection factory must be configured either on the component or endpoint." }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mail-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mail-component.adoc index c5f952ce7317d..48d3f181e17b3 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mail-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/mail-component.adoc @@ -189,7 +189,9 @@ trust/key store files (see `SSLNOTES.txt` in JavaMail for details). Camel uses the message exchange's IN body as the http://java.sun.com/javaee/5/docs/api/javax/mail/internet/MimeMessage.html[MimeMessage] -text content. The body is converted to `String.class`. +text content. The body is converted to `String.class`: bytes, a stream or a file are read as text, so send binary +content as an attachment, and a Map or a POJO is sent as its `toString()`. A body that is a `jakarta.mail.internet.MimeMessage` +is sent as it is, with its own recipients and subject. Camel copies all of the exchange's IN headers to the http://java.sun.com/javaee/5/docs/api/javax/mail/internet/MimeMessage.html[MimeMessage] @@ -691,17 +693,8 @@ the Splitter as shown below ---- -You can also split the attachments as byte[] to -be stored as the message body. This is done by creating the expression -with boolean true - -._Java-only: programmatic `SplitAttachmentsExpression` configuration_ -[source,java] ----- -SplitAttachmentsExpression split = SplitAttachmentsExpression(true); ----- - -And then use the expression with the splitter EIP. +Each split message has the content of one attachment as its body: a byte array, or a String for a text +attachment, with the name of the attachment in the `CamelSplitAttachmentId` header. === Using custom SearchTerm diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/nats-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/nats-component.adoc index 8d11c415f0878..63d1ad3aaf22f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/nats-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/nats-component.adoc @@ -116,9 +116,12 @@ camel.component.nats.servers=scott:tiger@someserver:4222,superman:123@someothers ---- === Request/Reply support -The producer supports request/reply where it can wait for an expected reply message. +The producer supports request/reply: when the exchange pattern is InOut, it waits for the reply message, up to +`requestTimeout`, and the payload of the reply becomes the message body, as a byte array. -The consumer will, when routing the message is complete, send back the message as reply-message if required. +The consumer sends back the message body as the reply message, when routing the message is complete, if the message has a +reply subject and the consumer has `exchangePattern=InOut`. The body must convert to a byte array: text, bytes, a stream or a +file. A body that does not, such as a Map, sends no reply. == Examples diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/smpp-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/smpp-component.adoc index 02358413bb5a9..8c5525d86d6e2 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/smpp-component.adoc +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/smpp-component.adoc @@ -114,6 +114,9 @@ corresponding alphabet. When deciding which alphabet to use in the byte array, the Camel SMPP component does not consider the data coding value (header or configuration), it only considers the specified alphabet (from either the header or endpoint parameter). +The exception is an 8-bit data coding or alphabet in a header: the body is +then sent as the bytes it converts to, as they are. The same values in the +endpoint parameters do not do this, so a byte array body is read as text first. If some characters in the String cannot be represented in the chosen alphabet, they may be replaced by the question mark (`?`) symbol. @@ -121,8 +124,10 @@ Users of the API may want to consider checking if their message body can be converted to ISO-8859-1 before passing it to the component and if not, setting the alphabet header to request UCS-2 encoding. If the alphabet -and data coding options are not specified at all, then the component may -try to detect the required encoding and set the data coding for you. +and data coding options are not specified at all, the component does not +detect the required encoding or set the data coding for you: the text is +encoded for the SMSC default alphabet (`0`), in the `encoding` of the endpoint, +ISO-8859-1 by default. The list of alphabet codes is specified in the SMPP specification v3.4, section 5.2.19. One notable limitation of the SMPP specification is @@ -145,8 +150,10 @@ is completed automatically. If the GSM 3.38 alphabet is used, the component will pack up to 160 characters into the 140-byte message body. -If an 8-bit character set is used (e.g., ISO-8859-1 for Western Europe), then 140 characters will be -allowed within the 140-byte message body. +If the 8-bit alphabet (`4`) is used, then 140 bytes will be +allowed within the 140-byte message body. Text in an 8-bit character set +(e.g., ISO-8859-1 for Western Europe) is split by 140 bytes only with that +alphabet; with the default alphabet, it is split by 160 characters. If 16 bit UCS-2 encoding is used, then just 70 characters fit into each 140-byte message. diff --git a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/imap.json b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/imap.json index 8399bb76ec5a4..47a584bfbb93d 100644 --- a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/imap.json +++ b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/imap.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/imaps.json b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/imaps.json index 183ccb7e37221..35c217ab9acdf 100644 --- a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/imaps.json +++ b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/imaps.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/pop3.json b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/pop3.json index d46e065460c7b..3c4eb46d823b3 100644 --- a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/pop3.json +++ b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/pop3.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/pop3s.json b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/pop3s.json index 652f0c2be7484..0dbc734fa2968 100644 --- a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/pop3s.json +++ b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/pop3s.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/smtp.json b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/smtp.json index c2e3c9652c513..e6517c9719790 100644 --- a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/smtp.json +++ b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/smtp.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/smtps.json b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/smtps.json index 4682f6a3524c6..9bd4bd00f5a11 100644 --- a/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/smtps.json +++ b/components/camel-mail/src/generated/resources/META-INF/org/apache/camel/component/mail/smtps.json @@ -95,6 +95,11 @@ "CamelMailDelete": { "index": 9, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deletes the messages after they have been processed.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_DELETE" }, "CamelMailMessageId": { "index": 10, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message ID.", "constantName": "org.apache.camel.component.mail.MailConstants#MAIL_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "stream", "pojo" ], "dependsOn": [ "binding" ], "byOption": [ { "option": "mapMailMessage", "value": "false", "carriers": [ "pojo" ], "javaType": "jakarta.mail.Message" } ], "description": "The content of the mail an imap or pop3 consumer reads: a String for text\/plain, text\/html and text\/xml, a stream for another content type, and a jakarta.mail Multipart for a multipart mail, which converts to the text of its first text part, with the files in the attachments. The jakarta.mail.Message itself with mapMailMessage=false" }, + "producerIn": { "carriers": [ "null", "text", "bytes", "stream", "file" ], "dependsOn": [ "binding" ], "description": "The text of the mail smtp sends, in the contentType: bytes, a stream or a file are read as text, so send binary content as an attachment, and no body sends an empty text. A jakarta.mail MimeMessage is sent as it is, and a Map or a POJO as its toString(): marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, with the Message-ID of the mail in the CamelMailMessageId header" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The mail server host name" }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The port number of the mail server" }, diff --git a/components/camel-mail/src/main/docs/mail-component.adoc b/components/camel-mail/src/main/docs/mail-component.adoc index c5f952ce7317d..48d3f181e17b3 100644 --- a/components/camel-mail/src/main/docs/mail-component.adoc +++ b/components/camel-mail/src/main/docs/mail-component.adoc @@ -189,7 +189,9 @@ trust/key store files (see `SSLNOTES.txt` in JavaMail for details). Camel uses the message exchange's IN body as the http://java.sun.com/javaee/5/docs/api/javax/mail/internet/MimeMessage.html[MimeMessage] -text content. The body is converted to `String.class`. +text content. The body is converted to `String.class`: bytes, a stream or a file are read as text, so send binary +content as an attachment, and a Map or a POJO is sent as its `toString()`. A body that is a `jakarta.mail.internet.MimeMessage` +is sent as it is, with its own recipients and subject. Camel copies all of the exchange's IN headers to the http://java.sun.com/javaee/5/docs/api/javax/mail/internet/MimeMessage.html[MimeMessage] @@ -691,17 +693,8 @@ the Splitter as shown below ---- -You can also split the attachments as byte[] to -be stored as the message body. This is done by creating the expression -with boolean true - -._Java-only: programmatic `SplitAttachmentsExpression` configuration_ -[source,java] ----- -SplitAttachmentsExpression split = SplitAttachmentsExpression(true); ----- - -And then use the expression with the splitter EIP. +Each split message has the content of one attachment as its body: a byte array, or a String for a text +attachment, with the name of the attachment in the `CamelSplitAttachmentId` header. === Using custom SearchTerm diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java index 1c52a0a92ae59..45b3fb1dcb486 100644 --- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java +++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java @@ -26,6 +26,9 @@ import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.HeaderFilterStrategy; import org.apache.camel.spi.HeaderFilterStrategyAware; @@ -47,6 +50,23 @@ @UriEndpoint(firstVersion = "1.0.0", scheme = "imap,imaps,pop3,pop3s,smtp,smtps", title = "IMAP,IMAPS,POP3,POP3S,SMTP,SMTPS", syntax = "imap:host:port", alternativeSyntax = "imap:username:password@host:port", category = { Category.MAIL }, headersClass = MailConstants.class) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.STREAM, Carrier.POJO }, dependsOn = "binding", + byOption = @BodyType.When(option = "mapMailMessage", value = "false", + carriers = Carrier.POJO, javaType = "jakarta.mail.Message"), + description = "The content of the mail an imap or pop3 consumer reads: a String for" + + " text/plain, text/html and text/xml, a stream for another content type," + + " and a jakarta.mail Multipart for a multipart mail, which converts to the" + + " text of its first text part, with the files in the attachments. The" + + " jakarta.mail.Message itself with mapMailMessage=false"), + producerIn = @BodyType(value = { Carrier.NULL, Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + dependsOn = "binding", + description = "The text of the mail smtp sends, in the contentType: bytes, a stream or a" + + " file are read as text, so send binary content as an attachment, and no" + + " body sends an empty text. A jakarta.mail MimeMessage is sent as it is," + + " and a Map or a POJO as its toString(): marshal it first"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged, with the Message-ID of the mail in the CamelMailMessageId" + + " header")) public class MailEndpoint extends ScheduledPollEndpoint implements HeaderFilterStrategyAware, EndpointServiceLocation { @UriParam(defaultValue = "" + MailConsumer.DEFAULT_CONSUMER_DELAY, javaType = "java.time.Duration", diff --git a/components/camel-nats/src/generated/resources/META-INF/org/apache/camel/component/nats/nats.json b/components/camel-nats/src/generated/resources/META-INF/org/apache/camel/component/nats/nats.json index eca34ceb7d3c8..50696e1342789 100644 --- a/components/camel-nats/src/generated/resources/META-INF/org/apache/camel/component/nats/nats.json +++ b/components/camel-nats/src/generated/resources/META-INF/org/apache/camel/component/nats/nats.json @@ -80,6 +80,12 @@ "CamelNatsDeliveryCounter": { "index": 7, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "important": true, "description": "Number of times this message has been delivered (1 = first, 1 then message has been redelivered)", "constantName": "org.apache.camel.component.nats.NatsConstants#NATS_DELIVERY_COUNTER" }, "CamelNatsManualAck": { "index": 8, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "org.apache.camel.component.nats.NatsManualAck", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The manual acknowledgment handle for JetStream messages (only set when manualAck=true).", "constantName": "org.apache.camel.component.nats.NatsConstants#NATS_MANUAL_ACK" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The payload of the NATS message as a byte array, empty for a message without one: convert or unmarshal it" }, + "consumerReply": { "carriers": [ "any" ], "byOption": [ { "option": "exchangePattern", "value": "InOut", "carriers": [ "text", "bytes", "stream", "file" ] } ], "description": "Only with exchangePattern=InOut is a message with a reply subject answered, with the body the route ends with: text, bytes, a stream or a file. A Map, a POJO or no body sends no reply, and the requester times out" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "What converts to a byte array: text, bytes, a stream or a file. A Map or a POJO is sent as its toString(), and a List or no body fails: marshal it first" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "exchangePattern", "value": "InOut", "carriers": [ "bytes" ], "javaType": "byte[]" } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) waits for the reply, up to requestTimeout, and gets its payload as a byte array" } + }, "properties": { "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.nats.NatsConfiguration", "configurationField": "configuration", "description": "The name of topic we want to use" }, "connectionTimeout": { "index": 1, "kind": "parameter", "displayName": "Connection Timeout", "group": "common", "label": "common", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 2000, "configurationClass": "org.apache.camel.component.nats.NatsConfiguration", "configurationField": "configuration", "description": "Timeout for connection attempts. (in milliseconds)" }, diff --git a/components/camel-nats/src/main/docs/nats-component.adoc b/components/camel-nats/src/main/docs/nats-component.adoc index 8d11c415f0878..63d1ad3aaf22f 100644 --- a/components/camel-nats/src/main/docs/nats-component.adoc +++ b/components/camel-nats/src/main/docs/nats-component.adoc @@ -116,9 +116,12 @@ camel.component.nats.servers=scott:tiger@someserver:4222,superman:123@someothers ---- === Request/Reply support -The producer supports request/reply where it can wait for an expected reply message. +The producer supports request/reply: when the exchange pattern is InOut, it waits for the reply message, up to +`requestTimeout`, and the payload of the reply becomes the message body, as a byte array. -The consumer will, when routing the message is complete, send back the message as reply-message if required. +The consumer sends back the message body as the reply message, when routing the message is complete, if the message has a +reply subject and the consumer has `exchangePattern=InOut`. The body must convert to a byte array: text, bytes, a stream or a +file. A body that does not, such as a Map, sends no reply. == Examples diff --git a/components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsEndpoint.java b/components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsEndpoint.java index ed1aaa74511ef..2d95d008a104d 100644 --- a/components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsEndpoint.java +++ b/components/camel-nats/src/main/java/org/apache/camel/component/nats/NatsEndpoint.java @@ -31,6 +31,9 @@ import org.apache.camel.MultipleConsumersSupport; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.HeaderFilterStrategy; import org.apache.camel.spi.HeaderFilterStrategyAware; @@ -45,6 +48,31 @@ */ @UriEndpoint(firstVersion = "2.17.0", scheme = "nats", title = "Nats", syntax = "nats:topic", category = { Category.MESSAGING }, headersClass = NatsConstants.class) +@BodyTypes(consumerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]", + description = "The payload of the NATS message as a byte array, empty for a message" + + " without one: convert or unmarshal it"), + consumerReply = @BodyType(value = Carrier.ANY, + byOption = @BodyType.When(option = "exchangePattern", value = "InOut", + carriers = { + Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, + Carrier.FILE }), + description = "Only with exchangePattern=InOut is a message with a reply subject" + + " answered, with the body the route ends with: text, bytes, a stream or a" + + " file. A Map, a POJO or no body sends no reply, and the requester" + + " times out"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "What converts to a byte array: text, bytes, a stream or a file. A Map or a" + + " POJO is sent as its toString(), and a List or no body fails: marshal it" + + " first"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "exchangePattern", value = "InOnly", + carriers = Carrier.UNCHANGED), + @BodyType.When(option = "exchangePattern", value = "InOut", + carriers = Carrier.BYTES, javaType = "byte[]") }, + description = "Unchanged for a message that expects no reply (InOnly). A message that" + + " expects one (InOut) waits for the reply, up to requestTimeout, and gets" + + " its payload as a byte array")) public class NatsEndpoint extends DefaultEndpoint implements MultipleConsumersSupport, HeaderFilterStrategyAware, EndpointServiceLocation { diff --git a/components/camel-paho/src/generated/resources/META-INF/org/apache/camel/component/paho/paho.json b/components/camel-paho/src/generated/resources/META-INF/org/apache/camel/component/paho/paho.json index 1ee428f6b2ebc..de99e56c6983c 100644 --- a/components/camel-paho/src/generated/resources/META-INF/org/apache/camel/component/paho/paho.json +++ b/components/camel-paho/src/generated/resources/META-INF/org/apache/camel/component/paho/paho.json @@ -64,6 +64,11 @@ "CamelPahoRetained": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Retain option.", "constantName": "org.apache.camel.component.paho.PahoConstants#CAMEL_PAHO_MSG_RETAINED" }, "CamelPahoOverrideTopic": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The name of topic to override and send to instead of topic specified on endpoint.", "constantName": "org.apache.camel.component.paho.PahoConstants#CAMEL_PAHO_OVERRIDE_TOPIC" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes" ], "javaType": "byte[]", "description": "The payload of the MQTT message" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "What converts to a byte array: text, bytes, a stream or a file, sent as the payload. A Map, a POJO or no body fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ] } + }, "properties": { "topic": { "index": 0, "kind": "path", "displayName": "Topic", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the topic" }, "automaticReconnect": { "index": 1, "kind": "parameter", "displayName": "Automatic Reconnect", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.paho.PahoConfiguration", "configurationField": "configuration", "description": "Sets whether the client will automatically attempt to reconnect to the server if the connection is lost. If set to false, the client will not attempt to automatically reconnect to the server in the event that the connection is lost. If set to true, in the event that the connection is lost, the client will attempt to reconnect to the server. It will initially wait 1 second before it attempts to reconnect, for every failed reconnect attempt, the delay will double until it is at 2 minutes at which point the delay will stay at 2 minutes." }, diff --git a/components/camel-paho/src/main/java/org/apache/camel/component/paho/PahoEndpoint.java b/components/camel-paho/src/main/java/org/apache/camel/component/paho/PahoEndpoint.java index 48773c9848a26..619689ce1fccb 100644 --- a/components/camel-paho/src/main/java/org/apache/camel/component/paho/PahoEndpoint.java +++ b/components/camel-paho/src/main/java/org/apache/camel/component/paho/PahoEndpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -42,6 +45,11 @@ @UriEndpoint(firstVersion = "2.16.0", scheme = "paho", title = "Paho", category = { Category.MESSAGING, Category.IOT }, syntax = "paho:topic", headersClass = PahoConstants.class) @Deprecated(since = "4.21") +@BodyTypes(consumerOut = @BodyType(value = Carrier.BYTES, javaType = "byte[]", description = "The payload of the MQTT message"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "What converts to a byte array: text, bytes, a stream or a file, sent as" + + " the payload. A Map, a POJO or no body fails: marshal it first"), + producerOut = @BodyType(Carrier.UNCHANGED)) public class PahoEndpoint extends DefaultEndpoint implements EndpointServiceLocation { // Configuration members diff --git a/components/camel-pulsar/src/generated/resources/META-INF/org/apache/camel/component/pulsar/pulsar.json b/components/camel-pulsar/src/generated/resources/META-INF/org/apache/camel/component/pulsar/pulsar.json index edd57b05efb83..a4cce15a1aafc 100644 --- a/components/camel-pulsar/src/generated/resources/META-INF/org/apache/camel/component/pulsar/pulsar.json +++ b/components/camel-pulsar/src/generated/resources/META-INF/org/apache/camel/component/pulsar/pulsar.json @@ -94,6 +94,11 @@ "CamelPulsarProducerMessageDeliverAfter": { "index": 15, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Deliver the message after a given delayed time (millis).", "constantName": "org.apache.camel.component.pulsar.utils.message.PulsarMessageHeaders#DELIVER_AFTER" }, "CamelPulsarProducerMessageId": { "index": 16, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.apache.pulsar.client.api.MessageId", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message id the broker assigned to the published message.", "constantName": "org.apache.camel.component.pulsar.utils.message.PulsarMessageHeaders#PRODUCER_MESSAGE_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "bytes", "null" ], "javaType": "byte[]", "description": "The payload of the Pulsar message as a byte array, null for a message with a null value (a tombstone), with the key and the properties in headers: convert or unmarshal it" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "description": "What converts to a byte array: text, bytes, a stream or a file, sent as the payload. Any other body is sent with Java serialization, a Map, a List, a number and no body too, and an object that is not Serializable fails: marshal it first" }, + "producerOut": { "carriers": [ "unchanged" ], "description": "Unchanged, also when the exchange expects a reply, with the id of the published message in a header" } + }, "properties": { "persistence": { "index": 0, "kind": "path", "displayName": "Persistence", "group": "common", "label": "", "required": true, "type": "enum", "javaType": "java.lang.String", "enum": [ "persistent", "non-persistent" ], "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Whether the topic is persistent or non-persistent" }, "tenant": { "index": 1, "kind": "path", "displayName": "Tenant", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The tenant" }, diff --git a/components/camel-pulsar/src/main/java/org/apache/camel/component/pulsar/PulsarEndpoint.java b/components/camel-pulsar/src/main/java/org/apache/camel/component/pulsar/PulsarEndpoint.java index fd6de025b5ba4..fd5fdb1ee8c08 100644 --- a/components/camel-pulsar/src/main/java/org/apache/camel/component/pulsar/PulsarEndpoint.java +++ b/components/camel-pulsar/src/main/java/org/apache/camel/component/pulsar/PulsarEndpoint.java @@ -21,6 +21,9 @@ import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.component.pulsar.utils.message.PulsarMessageHeaders; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -37,6 +40,18 @@ @UriEndpoint(scheme = "pulsar", firstVersion = "2.24.0", title = "Pulsar", syntax = "pulsar:persistence://tenant/namespace/topic", category = { Category.MESSAGING }, headersClass = PulsarMessageHeaders.class) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.BYTES, Carrier.NULL }, javaType = "byte[]", + description = "The payload of the Pulsar message as a byte array, null for a message with" + + " a null value (a tombstone), with the key and the properties in headers:" + + " convert or unmarshal it"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + description = "What converts to a byte array: text, bytes, a stream or a file, sent as the" + + " payload. Any other body is sent with Java serialization, a Map, a List, a" + + " number and no body too, and an object that is not Serializable fails:" + + " marshal it first"), + producerOut = @BodyType(value = Carrier.UNCHANGED, + description = "Unchanged, also when the exchange expects a reply, with the id of the" + + " published message in a header")) public class PulsarEndpoint extends DefaultEndpoint implements EndpointServiceLocation { private PulsarClient pulsarClient; diff --git a/components/camel-smpp/src/generated/resources/META-INF/org/apache/camel/component/smpp/smpp.json b/components/camel-smpp/src/generated/resources/META-INF/org/apache/camel/component/smpp/smpp.json index dc937fb26f6af..51702b25e413f 100644 --- a/components/camel-smpp/src/generated/resources/META-INF/org/apache/camel/component/smpp/smpp.json +++ b/components/camel-smpp/src/generated/resources/META-INF/org/apache/camel/component/smpp/smpp.json @@ -82,7 +82,7 @@ "CamelSmppDestAddrNpi": { "index": 8, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Byte", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti, CancelSm and DataSm Defines the numeric plan indicator (NPI) to be used in the SME destination address parameters. Use the URI option sourceAddrNpi values defined above. Consumer: only for DataSm Defines the numeric plan indicator (NPI) in the destination address parameters. Use the URI option sourceAddrNpi values defined above.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DEST_ADDR_NPI" }, "CamelSmppDestAddrTon": { "index": 9, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Byte", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti, CancelSm and DataSm Defines the type of number (TON) to be used in the SME destination address parameters. Use the sourceAddrTon URI option values defined above. Consumer: only for DataSm Defines the type of number (TON) in the destination address parameters. Use the sourceAddrTon URI option values defined above.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DEST_ADDR_TON" }, "CamelSmppDoneDate": { "index": 10, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for smsc DeliveryReceipt The time and date at which the short message reached it's final state. The format is as follows: YYMMDDhhmm.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DONE_DATE" }, - "CamelSmppEncoding": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and DataSm. Specifies the encoding (character set name) of the bytes in the message body. If the message body is a string then this is not relevant because Java Strings are always Unicode. If the body is a byte array then this header can be used to indicate that it is ISO-8859-1 or some other value. Default value is specified by the endpoint configuration parameter _encoding_", "constantName": "org.apache.camel.component.smpp.SmppConstants#ENCODING" }, + "CamelSmppEncoding": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and ReplaceSm. Specifies the encoding (character set name) the text of the message body is encoded in, as the short message. A byte array body is first read as text, in the charset of the exchange, unless an 8-bit data coding or alphabet header sends it as it is. Default value is specified by the endpoint configuration parameter _encoding_", "constantName": "org.apache.camel.component.smpp.SmppConstants#ENCODING" }, "CamelSmppError": { "index": 12, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String or Map>>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitMultiSm The errors which occurred by sending the short message(s) the form Map (messageID : (destAddr : address, error : errorCode)). Consumer: only for smsc DeliveryReceipt Where appropriate this may hold a Network specific error code or an SMSC error code for the attempted delivery of the message. These errors are Network or SMSC specific and are not included here.", "constantName": "org.apache.camel.component.smpp.SmppConstants#ERROR" }, "CamelSmppClass": { "index": 13, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.jsmpp.bean.ESMClass", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "the ASM class", "constantName": "org.apache.camel.component.smpp.SmppConstants#ESM_CLASS" }, "CamelSmppEsmeAddr": { "index": 14, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for AlertNotification Defines the destination ESME address. For mobile terminated messages, this is the directory number of the recipient MS.", "constantName": "org.apache.camel.component.smpp.SmppConstants#ESME_ADDR" }, @@ -114,6 +114,11 @@ "CamelSmppOptionalParameter": { "index": 40, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti and DataSm The optional parameter which are send to the SMSC. The value is converted in the following way: String - org.jsmpp.bean.OptionalParameter.COctetString, byte - org.jsmpp.bean.OptionalParameter.OctetString, Byte - org.jsmpp.bean.OptionalParameter.Byte, Integer - org.jsmpp.bean.OptionalParameter.Int, Short - org.jsmpp.bean.OptionalParameter.Short, null - org.jsmpp.bean.OptionalParameter.Null Consumer: only for DeliverSm The optional parameters send back by the SMSC. The key is the Short code for the optional parameter. The value is converted in the following way: org.jsmpp.bean.OptionalParameter.COctetString - String, org.jsmpp.bean.OptionalParameter.OctetString - byte, org.jsmpp.bean.OptionalParameter.Byte - Byte, org.jsmpp.bean.OptionalParameter.Int - Integer, org.jsmpp.bean.OptionalParameter.Short - Short, org.jsmpp.bean.OptionalParameter.Null - null", "constantName": "org.apache.camel.component.smpp.SmppConstants#OPTIONAL_PARAMETER" }, "CamelSmppSplittingPolicy": { "index": 41, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and DataSm. Specifies the policy for message splitting for this exchange. Possible values are described in the endpoint configuration parameter _splittingPolicy_", "constantName": "org.apache.camel.component.smpp.SmppConstants#SPLITTING_POLICY" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "null" ], "description": "A short message as text decoded by its data coding, or as bytes for an 8-bit data coding; the text of a delivery receipt, with its fields in headers. A data_sm or an alert notification has no body" }, + "producerIn": { "carriers": [ "text", "bytes", "file" ], "description": "The text of the short message: bytes or a file are read as text, unless an 8-bit CamelSmppDataCoding or CamelSmppAlphabet header sends bytes as they are. A stream is sent empty and no body fails: convert it to text first; a Map or a POJO is sent as its toString(). DataSm, QuerySm and CancelSm do not read the body" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "exchangePattern", "value": "InOut", "carriers": [ "null" ] } ], "description": "Unchanged, with the message ids in the CamelSmppId header. When the exchange expects a reply (InOut), a new message with no body and only the result headers" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.smpp.SmppConfiguration", "configurationField": "configuration", "description": "Hostname for the SMSC server to use." }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 2775, "configurationClass": "org.apache.camel.component.smpp.SmppConfiguration", "configurationField": "configuration", "description": "Port number for the SMSC server to use." }, diff --git a/components/camel-smpp/src/generated/resources/META-INF/org/apache/camel/component/smpp/smpps.json b/components/camel-smpp/src/generated/resources/META-INF/org/apache/camel/component/smpp/smpps.json index 1adce03c7ebbb..39a2de9049af4 100644 --- a/components/camel-smpp/src/generated/resources/META-INF/org/apache/camel/component/smpp/smpps.json +++ b/components/camel-smpp/src/generated/resources/META-INF/org/apache/camel/component/smpp/smpps.json @@ -82,7 +82,7 @@ "CamelSmppDestAddrNpi": { "index": 8, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Byte", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti, CancelSm and DataSm Defines the numeric plan indicator (NPI) to be used in the SME destination address parameters. Use the URI option sourceAddrNpi values defined above. Consumer: only for DataSm Defines the numeric plan indicator (NPI) in the destination address parameters. Use the URI option sourceAddrNpi values defined above.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DEST_ADDR_NPI" }, "CamelSmppDestAddrTon": { "index": 9, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Byte", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti, CancelSm and DataSm Defines the type of number (TON) to be used in the SME destination address parameters. Use the sourceAddrTon URI option values defined above. Consumer: only for DataSm Defines the type of number (TON) in the destination address parameters. Use the sourceAddrTon URI option values defined above.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DEST_ADDR_TON" }, "CamelSmppDoneDate": { "index": 10, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "Date", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for smsc DeliveryReceipt The time and date at which the short message reached it's final state. The format is as follows: YYMMDDhhmm.", "constantName": "org.apache.camel.component.smpp.SmppConstants#DONE_DATE" }, - "CamelSmppEncoding": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and DataSm. Specifies the encoding (character set name) of the bytes in the message body. If the message body is a string then this is not relevant because Java Strings are always Unicode. If the body is a byte array then this header can be used to indicate that it is ISO-8859-1 or some other value. Default value is specified by the endpoint configuration parameter _encoding_", "constantName": "org.apache.camel.component.smpp.SmppConstants#ENCODING" }, + "CamelSmppEncoding": { "index": 11, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and ReplaceSm. Specifies the encoding (character set name) the text of the message body is encoded in, as the short message. A byte array body is first read as text, in the charset of the exchange, unless an 8-bit data coding or alphabet header sends it as it is. Default value is specified by the endpoint configuration parameter _encoding_", "constantName": "org.apache.camel.component.smpp.SmppConstants#ENCODING" }, "CamelSmppError": { "index": 12, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String or Map>>", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitMultiSm The errors which occurred by sending the short message(s) the form Map (messageID : (destAddr : address, error : errorCode)). Consumer: only for smsc DeliveryReceipt Where appropriate this may hold a Network specific error code or an SMSC error code for the attempted delivery of the message. These errors are Network or SMSC specific and are not included here.", "constantName": "org.apache.camel.component.smpp.SmppConstants#ERROR" }, "CamelSmppClass": { "index": 13, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.jsmpp.bean.ESMClass", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "the ASM class", "constantName": "org.apache.camel.component.smpp.SmppConstants#ESM_CLASS" }, "CamelSmppEsmeAddr": { "index": 14, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for AlertNotification Defines the destination ESME address. For mobile terminated messages, this is the directory number of the recipient MS.", "constantName": "org.apache.camel.component.smpp.SmppConstants#ESME_ADDR" }, @@ -114,6 +114,11 @@ "CamelSmppOptionalParameter": { "index": 40, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Producer: only for SubmitSm, SubmitMulti and DataSm The optional parameter which are send to the SMSC. The value is converted in the following way: String - org.jsmpp.bean.OptionalParameter.COctetString, byte - org.jsmpp.bean.OptionalParameter.OctetString, Byte - org.jsmpp.bean.OptionalParameter.Byte, Integer - org.jsmpp.bean.OptionalParameter.Int, Short - org.jsmpp.bean.OptionalParameter.Short, null - org.jsmpp.bean.OptionalParameter.Null Consumer: only for DeliverSm The optional parameters send back by the SMSC. The key is the Short code for the optional parameter. The value is converted in the following way: org.jsmpp.bean.OptionalParameter.COctetString - String, org.jsmpp.bean.OptionalParameter.OctetString - byte, org.jsmpp.bean.OptionalParameter.Byte - Byte, org.jsmpp.bean.OptionalParameter.Int - Integer, org.jsmpp.bean.OptionalParameter.Short - Short, org.jsmpp.bean.OptionalParameter.Null - null", "constantName": "org.apache.camel.component.smpp.SmppConstants#OPTIONAL_PARAMETER" }, "CamelSmppSplittingPolicy": { "index": 41, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "only for SubmitSm, SubmitMulti and DataSm. Specifies the policy for message splitting for this exchange. Possible values are described in the endpoint configuration parameter _splittingPolicy_", "constantName": "org.apache.camel.component.smpp.SmppConstants#SPLITTING_POLICY" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes", "null" ], "description": "A short message as text decoded by its data coding, or as bytes for an 8-bit data coding; the text of a delivery receipt, with its fields in headers. A data_sm or an alert notification has no body" }, + "producerIn": { "carriers": [ "text", "bytes", "file" ], "description": "The text of the short message: bytes or a file are read as text, unless an 8-bit CamelSmppDataCoding or CamelSmppAlphabet header sends bytes as they are. A stream is sent empty and no body fails: convert it to text first; a Map or a POJO is sent as its toString(). DataSm, QuerySm and CancelSm do not read the body" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "exchangePattern", "value": "InOut", "carriers": [ "null" ] } ], "description": "Unchanged, with the message ids in the CamelSmppId header. When the exchange expects a reply (InOut), a new message with no body and only the result headers" } + }, "properties": { "host": { "index": 0, "kind": "path", "displayName": "Host", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.smpp.SmppConfiguration", "configurationField": "configuration", "description": "Hostname for the SMSC server to use." }, "port": { "index": 1, "kind": "path", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 2775, "configurationClass": "org.apache.camel.component.smpp.SmppConfiguration", "configurationField": "configuration", "description": "Port number for the SMSC server to use." }, diff --git a/components/camel-smpp/src/main/docs/smpp-component.adoc b/components/camel-smpp/src/main/docs/smpp-component.adoc index 02358413bb5a9..8c5525d86d6e2 100644 --- a/components/camel-smpp/src/main/docs/smpp-component.adoc +++ b/components/camel-smpp/src/main/docs/smpp-component.adoc @@ -114,6 +114,9 @@ corresponding alphabet. When deciding which alphabet to use in the byte array, the Camel SMPP component does not consider the data coding value (header or configuration), it only considers the specified alphabet (from either the header or endpoint parameter). +The exception is an 8-bit data coding or alphabet in a header: the body is +then sent as the bytes it converts to, as they are. The same values in the +endpoint parameters do not do this, so a byte array body is read as text first. If some characters in the String cannot be represented in the chosen alphabet, they may be replaced by the question mark (`?`) symbol. @@ -121,8 +124,10 @@ Users of the API may want to consider checking if their message body can be converted to ISO-8859-1 before passing it to the component and if not, setting the alphabet header to request UCS-2 encoding. If the alphabet -and data coding options are not specified at all, then the component may -try to detect the required encoding and set the data coding for you. +and data coding options are not specified at all, the component does not +detect the required encoding or set the data coding for you: the text is +encoded for the SMSC default alphabet (`0`), in the `encoding` of the endpoint, +ISO-8859-1 by default. The list of alphabet codes is specified in the SMPP specification v3.4, section 5.2.19. One notable limitation of the SMPP specification is @@ -145,8 +150,10 @@ is completed automatically. If the GSM 3.38 alphabet is used, the component will pack up to 160 characters into the 140-byte message body. -If an 8-bit character set is used (e.g., ISO-8859-1 for Western Europe), then 140 characters will be -allowed within the 140-byte message body. +If the 8-bit alphabet (`4`) is used, then 140 bytes will be +allowed within the 140-byte message body. Text in an 8-bit character set +(e.g., ISO-8859-1 for Western Europe) is split by 140 bytes only with that +alphabet; with the default alphabet, it is split by 160 characters. If 16 bit UCS-2 encoding is used, then just 70 characters fit into each 140-byte message. diff --git a/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConstants.java b/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConstants.java index 56736b1bb880a..ddb349a4a0d59 100644 --- a/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConstants.java +++ b/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConstants.java @@ -80,12 +80,12 @@ public interface SmppConstants { javaType = "Date") String DONE_DATE = "CamelSmppDoneDate"; @Metadata(label = "producer", description = "*only for SubmitSm,\n" + - "SubmitMulti and DataSm*. Specifies the encoding (character set name) of\n" + - "the bytes in the message body. If the message body is a string then\n" + - "this is not relevant because Java Strings are always Unicode. If the\n" + - "body is a byte array then this header can be used to indicate that it is\n" + - "ISO-8859-1 or some other value. Default value is specified by the\n" + - "endpoint configuration parameter _encoding_", + "SubmitMulti and ReplaceSm*. Specifies the encoding (character set name)\n" + + "the text of the message body is encoded in, as the short message. A\n" + + "byte array body is first read as text, in the charset of the exchange,\n" + + "unless an 8-bit data coding or alphabet header sends it as it is.\n" + + "Default value is specified by the endpoint configuration parameter\n" + + "_encoding_", javaType = "String") String ENCODING = "CamelSmppEncoding"; @Metadata(description = "*Producer:* *only for SubmitMultiSm* The errors which\n" + diff --git a/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppEndpoint.java b/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppEndpoint.java index 84771fb69c4a9..584ea1f40275b 100644 --- a/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppEndpoint.java +++ b/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppEndpoint.java @@ -23,6 +23,9 @@ import org.apache.camel.ExchangePattern; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; @@ -35,6 +38,25 @@ */ @UriEndpoint(firstVersion = "2.2.0", scheme = "smpp,smpps", title = "SMPP", syntax = "smpp:host:port", category = { Category.MOBILE }, lenientProperties = true, headersClass = SmppConstants.class) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.NULL }, + description = "A short message as text decoded by its data coding, or as bytes for an" + + " 8-bit data coding; the text of a delivery receipt, with its fields in" + + " headers. A data_sm or an alert notification has no body"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.FILE }, + description = "The text of the short message: bytes or a file are read as text, unless an" + + " 8-bit CamelSmppDataCoding or CamelSmppAlphabet header sends bytes as they" + + " are. A stream is sent empty and no body fails: convert it to text first;" + + " a Map or a POJO is sent as its toString(). DataSm, QuerySm and CancelSm do" + + " not read the body"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "exchangePattern", value = "InOnly", + carriers = Carrier.UNCHANGED), + @BodyType.When(option = "exchangePattern", value = "InOut", + carriers = Carrier.NULL) }, + description = "Unchanged, with the message ids in the CamelSmppId header. When the" + + " exchange expects a reply (InOut), a new message with no body and only the" + + " result headers")) public class SmppEndpoint extends DefaultEndpoint implements EndpointServiceLocation { private SmppBinding binding; diff --git a/components/camel-spring-parent/camel-spring-rabbitmq/src/generated/resources/META-INF/org/apache/camel/component/springrabbit/spring-rabbitmq.json b/components/camel-spring-parent/camel-spring-rabbitmq/src/generated/resources/META-INF/org/apache/camel/component/springrabbit/spring-rabbitmq.json index a2afee539d79a..e2ae70cd9c83b 100644 --- a/components/camel-spring-parent/camel-spring-rabbitmq/src/generated/resources/META-INF/org/apache/camel/component/springrabbit/spring-rabbitmq.json +++ b/components/camel-spring-parent/camel-spring-rabbitmq/src/generated/resources/META-INF/org/apache/camel/component/springrabbit/spring-rabbitmq.json @@ -78,6 +78,12 @@ "CamelSpringRabbitmqPriority": { "index": 18, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "Integer", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The message priority.", "constantName": "org.apache.camel.component.springrabbit.SpringRabbitMQConstants#PRIORITY" }, "CamelSpringRabbitmqClusterId": { "index": 19, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The cluster id.", "constantName": "org.apache.camel.component.springrabbit.SpringRabbitMQConstants#CLUSTER_ID" } }, + "bodyTypes": { + "consumerOut": { "carriers": [ "text", "bytes" ], "dependsOn": [ "messageConverter" ], "description": "A String when the content type starts with text, as for text this component sends; a byte array otherwise, JSON and Java serialized objects too, which are not deserialized" }, + "consumerReply": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "messageConverter" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "The reply to a message with a reply-to, converted as the producer converts a body: a Map or a POJO fails" }, + "producerIn": { "carriers": [ "text", "bytes", "stream", "file" ], "dependsOn": [ "messageConverter" ], "byOption": [ { "option": "allowNullBody", "value": "true", "carriers": [ "null", "text", "bytes", "stream", "file" ] } ], "description": "Text, bytes, a stream or a file, sent as a byte array, text as text\/plain unless the CamelSpringRabbitmqContentType header says another type. A Map or a POJO fails, as it is not serialized: marshal it first" }, + "producerOut": { "carriers": [ "unknown" ], "byOption": [ { "option": "exchangePattern", "value": "InOnly", "carriers": [ "unchanged" ] }, { "option": "disableReplyTo", "value": "true", "carriers": [ "unchanged" ] } ], "description": "Unchanged for a message that expects no reply (InOnly). A message that expects one (InOut) gets the body of the reply as the consumer gives it: a String for a text content type, a byte array otherwise" } + }, "properties": { "exchangeName": { "index": 0, "kind": "path", "displayName": "Exchange Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The exchange name determines the exchange to which the produced messages will be sent to. In the case of consumers, the exchange name determines the exchange the queue will be bound to. Note: to use default exchange then do not use empty name, but use default instead." }, "connectionFactory": { "index": 1, "kind": "parameter", "displayName": "Connection Factory", "group": "common", "label": "common", "required": false, "type": "object", "javaType": "org.springframework.amqp.rabbit.connection.ConnectionFactory", "deprecated": false, "autowired": false, "secret": false, "description": "The connection factory to be use. A connection factory must be configured either on the component or endpoint." }, diff --git a/components/camel-spring-parent/camel-spring-rabbitmq/src/main/java/org/apache/camel/component/springrabbit/SpringRabbitMQEndpoint.java b/components/camel-spring-parent/camel-spring-rabbitmq/src/main/java/org/apache/camel/component/springrabbit/SpringRabbitMQEndpoint.java index 25343414cffe6..ba560b46b8c7f 100644 --- a/components/camel-spring-parent/camel-spring-rabbitmq/src/main/java/org/apache/camel/component/springrabbit/SpringRabbitMQEndpoint.java +++ b/components/camel-spring-parent/camel-spring-rabbitmq/src/main/java/org/apache/camel/component/springrabbit/SpringRabbitMQEndpoint.java @@ -26,6 +26,9 @@ import org.apache.camel.PollingConsumer; import org.apache.camel.Processor; import org.apache.camel.Producer; +import org.apache.camel.spi.BodyType; +import org.apache.camel.spi.BodyType.Carrier; +import org.apache.camel.spi.BodyTypes; import org.apache.camel.spi.EndpointServiceLocation; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; @@ -57,6 +60,36 @@ @UriEndpoint(firstVersion = "3.8.0", scheme = "spring-rabbitmq", title = "Spring RabbitMQ", syntax = "spring-rabbitmq:exchangeName", category = { Category.MESSAGING }, headersClass = SpringRabbitMQConstants.class) +@BodyTypes(consumerOut = @BodyType(value = { Carrier.TEXT, Carrier.BYTES }, dependsOn = "messageConverter", + description = "A String when the content type starts with text, as for text this" + + " component sends; a byte array otherwise, JSON and Java serialized objects" + + " too, which are not deserialized"), + consumerReply = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + dependsOn = "messageConverter", + byOption = @BodyType.When(option = "allowNullBody", value = "true", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE }), + description = "The reply to a message with a reply-to, converted as the producer" + + " converts a body: a Map or a POJO fails"), + producerIn = @BodyType(value = { Carrier.TEXT, Carrier.BYTES, Carrier.STREAM, Carrier.FILE }, + dependsOn = "messageConverter", + byOption = @BodyType.When(option = "allowNullBody", value = "true", + carriers = { + Carrier.NULL, Carrier.TEXT, Carrier.BYTES, + Carrier.STREAM, Carrier.FILE }), + description = "Text, bytes, a stream or a file, sent as a byte array, text as text/plain" + + " unless the CamelSpringRabbitmqContentType header says another type. A Map" + + " or a POJO fails, as it is not serialized: marshal it first"), + producerOut = @BodyType(value = Carrier.UNKNOWN, + byOption = { + @BodyType.When(option = "exchangePattern", value = "InOnly", + carriers = Carrier.UNCHANGED), + @BodyType.When(option = "disableReplyTo", value = "true", + carriers = Carrier.UNCHANGED) }, + description = "Unchanged for a message that expects no reply (InOnly). A message that" + + " expects one (InOut) gets the body of the reply as the consumer gives it:" + + " a String for a text content type, a byte array otherwise")) public class SpringRabbitMQEndpoint extends DefaultEndpoint implements AsyncEndpoint, EndpointServiceLocation { public static final String ARG_PREFIX = "arg."; diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java index 620acf8bab550..24da4237401c3 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/test/java/org/apache/camel/dsl/yaml/validator/TextBodyFlowTest.java @@ -1406,6 +1406,91 @@ public void testTheBodyOfCloudMessaging() { .anySatisfy(m -> assertThat(m).contains("to: google-pubsub needs the body as text or bytes")); } + @Test + public void testTheBodyOfMessaging() { + // the paho consumer gives bytes, so a field read needs an unmarshal; pulsar and smtp send what converts to + // bytes or text, so parsed data must be marshalled first, and so must the reply of a nats consumer that answers + // (InOut); the converter of spring-rabbitmq may be set on the component, and an imap mail may be text, a stream + // or a multipart, which say nothing + String yaml = """ + - route: + id: mqtt + from: + uri: paho:orders + steps: + - setHeader: + name: id + simple: ${body[id]} + - route: + id: publish + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: pulsar:persistent://public/default/orders + - route: + id: service + from: + uri: nats:orders + parameters: + exchangePattern: InOut + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - route: + id: listener + from: + uri: nats:events + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - route: + id: rabbit + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: spring-rabbitmq:orders + - route: + id: mail + from: + uri: timer:tick + steps: + - setBody: + constant: '{"id": 1}' + - unmarshal: + json: {} + - to: smtp://localhost?to=info@acme.com + - route: + id: inbox + from: + uri: imap://localhost + steps: + - setHeader: + name: id + simple: ${body[id]} + """; + assertThat(lines(yaml)).hasSize(4).anySatisfy(m -> assertThat(m) + .contains("route mqtt: simple reads a field of the body (${body[id]})") + .contains("the paho consumer gives it as bytes")) + .anySatisfy(m -> assertThat(m).contains("to: pulsar needs the body as text, bytes, a stream or a file")) + .anySatisfy(m -> assertThat(m) + .contains("route service:") + .contains("the body at the end of the route is the reply to the nats request")) + .anySatisfy(m -> assertThat(m) + .contains("route mail: to: smtp needs the body as text, bytes, a stream or a file")); + } + @Test public void testTheBodyOfCoreComponents() { // the stream consumer gives each line as text, so a field read needs an unmarshal, and stream:out writes text, From 5139879b2450f12225cbf8c9bb898f41e75c7c84 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Fri, 23 Oct 2026 11:42:48 +0200 Subject: [PATCH 25/25] CAMEL-24961: Regenerate the smpp endpoint DSL for the encoding header The description of the CamelSmppEncoding header changed with the body types of smpp, and the endpoint DSL holds a copy of it. Co-Authored-By: Claude Opus 5.5 (1M context) Signed-off-by: Claus Ibsen --- .../endpoint/dsl/SmppEndpointBuilderFactory.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmppEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmppEndpointBuilderFactory.java index 806c9fd636b0a..1a6b3cf79bbd8 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmppEndpointBuilderFactory.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmppEndpointBuilderFactory.java @@ -3011,13 +3011,12 @@ public String smppDoneDate() { return "CamelSmppDoneDate"; } /** - * only for SubmitSm, SubmitMulti and DataSm. Specifies the encoding - * (character set name) of the bytes in the message body. If the message - * body is a string then this is not relevant because Java Strings are - * always Unicode. If the body is a byte array then this header can be - * used to indicate that it is ISO-8859-1 or some other value. Default - * value is specified by the endpoint configuration parameter - * _encoding_. + * only for SubmitSm, SubmitMulti and ReplaceSm. Specifies the encoding + * (character set name) the text of the message body is encoded in, as + * the short message. A byte array body is first read as text, in the + * charset of the exchange, unless an 8-bit data coding or alphabet + * header sends it as it is. Default value is specified by the endpoint + * configuration parameter _encoding_. * * The option is a: {@code String} type. *