You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2024/01/26 10:15:05 UTC

(camel) 01/01: CAMEL-20369: camel-beanio - Bring back beanio v3

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch beanio3
in repository https://gitbox.apache.org/repos/asf/camel.git

commit c093ba2a04f3eae2562907c15db77cf8dd32c87a
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Jan 26 11:14:42 2024 +0100

    CAMEL-20369: camel-beanio - Bring back beanio v3
---
 bom/camel-bom/pom.xml                              |   5 +
 catalog/camel-allcomponents/pom.xml                |   5 +
 .../apache/camel/catalog/dataformats.properties    |   1 +
 .../apache/camel/catalog/dataformats/beanio.json   |  29 ++
 .../org/apache/camel/catalog/models.properties     |   1 +
 .../org/apache/camel/catalog/models/beanio.json    |  26 ++
 .../apache/camel/catalog/models/dataFormats.json   |   2 +-
 .../org/apache/camel/catalog/models/marshal.json   |   2 +-
 .../org/apache/camel/catalog/models/unmarshal.json |   2 +-
 .../apache/camel/catalog/schemas/camel-spring.xsd  |  97 +++++++
 components/camel-beanio/pom.xml                    |  55 ++++
 .../beanio/BeanIODataFormatConfigurer.java         |  26 ++
 .../org/apache/camel/configurer/beanio-dataformat  |   2 +
 .../org/apache/camel/dataformat.properties         |   7 +
 .../services/org/apache/camel/dataformat/beanio    |   2 +
 .../org/apache/camel/dataformat/beanio/beanio.json |  29 ++
 .../src/main/docs/beanio-dataformat.adoc           | 120 +++++++++
 .../dataformat/beanio/BeanIOConfiguration.java     | 123 +++++++++
 .../camel/dataformat/beanio/BeanIODataFormat.java  | 298 +++++++++++++++++++++
 .../dataformat/beanio/BeanIOErrorHandler.java      | 126 +++++++++
 .../camel/dataformat/beanio/BeanIOHeader.java      |  25 ++
 .../camel/dataformat/beanio/BeanIOHelper.java      |  66 +++++
 .../camel/dataformat/beanio/BeanIOIterator.java    |  81 ++++++
 .../camel/dataformat/beanio/BeanIOSplitter.java    | 211 +++++++++++++++
 .../apache/camel/dataformat/beanio/A1Record.java   |  59 ++++
 .../apache/camel/dataformat/beanio/B1Record.java   |  59 ++++
 .../beanio/BeanIODataFormatComplexTest.java        | 239 +++++++++++++++++
 ...rmatSimpleCustomBeanReaderErrorHandlerTest.java | 142 ++++++++++
 .../beanio/BeanIODataFormatSimpleTest.java         | 117 ++++++++
 ...IOSplitterCustomBeanReaderErrorHandlerTest.java | 122 +++++++++
 .../dataformat/beanio/BeanIOSplitterTest.java      |  99 +++++++
 .../beanio/BeanIOUnmarshalSingleObjectTest.java    |  68 +++++
 .../apache/camel/dataformat/beanio/Constants.java  |  26 ++
 .../apache/camel/dataformat/beanio/Employee.java   | 111 ++++++++
 .../org/apache/camel/dataformat/beanio/Header.java | 111 ++++++++
 .../apache/camel/dataformat/beanio/MyErrorDto.java |  36 +++
 .../camel/dataformat/beanio/MyErrorHandler.java    |  38 +++
 .../org/apache/camel/dataformat/beanio/Record.java |  65 +++++
 .../apache/camel/dataformat/beanio/Separator.java  |  59 ++++
 .../beanio/SpringBeanIODataFormatSimpleTest.java   |  92 +++++++
 .../apache/camel/dataformat/beanio/Trailer.java    |  59 ++++
 .../camel/dataformat/beanio/csv/CsvTest.java       | 126 +++++++++
 .../beanio/csv/CsvTestWithProperties.java          |  59 ++++
 .../src/test/resources/log4j2.properties           |  28 ++
 .../beanio/SpringBeanIODataFormatSimpleTest.xml    |  51 ++++
 .../camel/dataformat/beanio/csv/mappings.xml       |  32 +++
 .../beanio/csv/mappingsWithProperties.xml          |  32 +++
 .../apache/camel/dataformat/beanio/mappings.xml    | 116 ++++++++
 .../dataformat/beanio/single-object-mapping.xml    |  29 ++
 components/pom.xml                                 |   1 +
 .../services/org/apache/camel/model.properties     |   1 +
 .../org/apache/camel/model/dataformat/beanio.json  |  26 ++
 .../apache/camel/model/dataformat/dataFormats.json |   2 +-
 .../org/apache/camel/model/dataformat/jaxb.index   |   1 +
 .../resources/org/apache/camel/model/marshal.json  |   2 +-
 .../org/apache/camel/model/unmarshal.json          |   2 +-
 .../camel/builder/DataFormatBuilderFactory.java    |   8 +
 .../org/apache/camel/builder/DataFormatClause.java |  49 ++++
 .../org/apache/camel/model/MarshalDefinition.java  |   2 +
 .../apache/camel/model/UnmarshalDefinition.java    |   2 +
 .../camel/model/dataformat/BeanioDataFormat.java   | 296 ++++++++++++++++++++
 .../model/dataformat/DataFormatsDefinition.java    |   1 +
 .../DataFormatTransformerDefinition.java           |   2 +
 .../dataformat/BeanioDataFormatReifier.java        |  43 +++
 .../reifier/dataformat/DataFormatReifier.java      |   3 +
 .../org/apache/camel/main/dataformats.properties   |   1 +
 .../java/org/apache/camel/xml/in/ModelParser.java  |  17 ++
 .../java/org/apache/camel/xml/out/ModelWriter.java |  23 ++
 .../org/apache/camel/yaml/out/ModelWriter.java     |  23 ++
 .../modules/dataformats/examples/json/beanio.json  |   1 +
 docs/components/modules/dataformats/nav.adoc       |   1 +
 .../dataformats/pages/beanio-dataformat.adoc       |   1 +
 .../dsl/yaml/deserializers/ModelDeserializers.java | 117 ++++++++
 .../deserializers/ModelDeserializersResolver.java  |   2 +
 .../generated/resources/schema/camelYamlDsl.json   |  90 +++++++
 parent/pom.xml                                     |   6 +
 76 files changed, 4033 insertions(+), 6 deletions(-)

diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index bc8811d0800..afb94b21a99 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -326,6 +326,11 @@
         <artifactId>camel-bean-validator</artifactId>
         <version>${project.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-beanio</artifactId>
+        <version>${project.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.apache.camel</groupId>
         <artifactId>camel-bindy</artifactId>
diff --git a/catalog/camel-allcomponents/pom.xml b/catalog/camel-allcomponents/pom.xml
index cc83f21e9eb..1b06234a712 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -312,6 +312,11 @@
             <artifactId>camel-bean-validator</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-beanio</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-bindy</artifactId>
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats.properties
index e7c684944b4..ca8d6981a6e 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats.properties
@@ -3,6 +3,7 @@ avro
 avroJackson
 barcode
 base64
+beanio
 bindyCsv
 bindyFixed
 bindyKvp
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
new file mode 100644
index 00000000000..42ac42f419e
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dataformats/beanio.json
@@ -0,0 +1,29 @@
+{
+  "dataformat": {
+    "kind": "dataformat",
+    "name": "beanio",
+    "title": "BeanIO",
+    "description": "Marshal and unmarshal Java beans to and from flat files (such as CSV, delimited, or fixed length formats).",
+    "deprecated": false,
+    "firstVersion": "2.10.0",
+    "label": "dataformat,transformation,csv",
+    "javaType": "org.apache.camel.dataformat.beanio.BeanIODataFormat",
+    "supportLevel": "Stable",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-beanio",
+    "version": "4.4.0-SNAPSHOT",
+    "modelName": "beanio",
+    "modelJavaType": "org.apache.camel.model.dataformat.BeanioDataFormat"
+  },
+  "properties": {
+    "id": { "index": 0, "kind": "attribute", "displayName": "Id", "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", "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." },
+    "streamName": { "index": 2, "kind": "attribute", "displayName": "Stream Name", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the stream to use." },
+    "ignoreUnidentifiedRecords": { "index": 3, "kind": "attribute", "displayName": "Ignore Unidentified Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore unidentified records." },
+    "ignoreUnexpectedRecords": { "index": 4, "kind": "attribute", "displayName": "Ignore Unexpected Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore unexpected records." },
+    "ignoreInvalidRecords": { "index": 5, "kind": "attribute", "displayName": "Ignore Invalid Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore invalid records." },
+    "encoding": { "index": 6, "kind": "attribute", "displayName": "Encoding", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The charset to use. Is by default the JVM platform default charset." },
+    "beanReaderErrorHandlerType": { "index": 7, "kind": "attribute", "displayName": "Bean Reader Error Handler Type", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.dataformat.beanio.BeanIOErrorHandler as error handler while parsing. Configure the fully qualified class name of the error handler. Notice the options ignoreUnidentifiedRecords, [...]
+    "unmarshalSingleObject": { "index": 8, "kind": "attribute", "displayName": "Unmarshal Single Object", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "This options controls whether to unmarshal as a list of objects or as a single object only. The former is the default mode, and the latter is only intended in special use-cases where beanio maps th [...]
+  }
+}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
index 4cc5b5a08aa..18a5ae5124d 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models.properties
@@ -7,6 +7,7 @@ base64
 basicAuth
 batchConfig
 bean
+beanio
 bearerToken
 bindy
 blacklistServiceFilter
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/beanio.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/beanio.json
new file mode 100644
index 00000000000..479fc19bd14
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/beanio.json
@@ -0,0 +1,26 @@
+{
+  "model": {
+    "kind": "model",
+    "name": "beanio",
+    "title": "BeanIO",
+    "description": "Marshal and unmarshal Java beans to and from flat files (such as CSV, delimited, or fixed length formats).",
+    "deprecated": false,
+    "firstVersion": "2.10.0",
+    "label": "dataformat,transformation,csv",
+    "javaType": "org.apache.camel.model.dataformat.BeanioDataFormat",
+    "abstract": false,
+    "input": false,
+    "output": false
+  },
+  "properties": {
+    "id": { "index": 0, "kind": "attribute", "displayName": "Id", "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", "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." },
+    "streamName": { "index": 2, "kind": "attribute", "displayName": "Stream Name", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the stream to use." },
+    "ignoreUnidentifiedRecords": { "index": 3, "kind": "attribute", "displayName": "Ignore Unidentified Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore unidentified records." },
+    "ignoreUnexpectedRecords": { "index": 4, "kind": "attribute", "displayName": "Ignore Unexpected Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore unexpected records." },
+    "ignoreInvalidRecords": { "index": 5, "kind": "attribute", "displayName": "Ignore Invalid Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore invalid records." },
+    "encoding": { "index": 6, "kind": "attribute", "displayName": "Encoding", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The charset to use. Is by default the JVM platform default charset." },
+    "beanReaderErrorHandlerType": { "index": 7, "kind": "attribute", "displayName": "Bean Reader Error Handler Type", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.dataformat.beanio.BeanIOErrorHandler as error handler while parsing. Configure the fully qualified class name of the error handler. Notice the options ignoreUnidentifiedRecords, [...]
+    "unmarshalSingleObject": { "index": 8, "kind": "attribute", "displayName": "Unmarshal Single Object", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "This options controls whether to unmarshal as a list of objects or as a single object only. The former is the default mode, and the latter is only intended in special use-cases where beanio maps th [...]
+  }
+}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/dataFormats.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/dataFormats.json
index b2b8fb14fa8..e811a1de6a3 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/dataFormats.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/dataFormats.json
@@ -12,6 +12,6 @@
     "output": false
   },
   "properties": {
-    "dataFormats": { "index": 0, "kind": "element", "displayName": "Data Formats", "required": true, "type": "array", "javaType": "java.util.List<org.apache.camel.model.DataFormatDefinition>", "oneOf": [ "asn1", "avro", "barcode", "base64", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt", "swiftMx [...]
+    "dataFormats": { "index": 0, "kind": "element", "displayName": "Data Formats", "required": true, "type": "array", "javaType": "java.util.List<org.apache.camel.model.DataFormatDefinition>", "oneOf": [ "asn1", "avro", "barcode", "base64", "beanio", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt" [...]
   }
 }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/marshal.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/marshal.json
index 3f33b46e27e..55d4543bdd3 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/marshal.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/marshal.json
@@ -15,7 +15,7 @@
     "id": { "index": 0, "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
     "description": { "index": 1, "kind": "element", "displayName": "Description", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" },
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime." },
-    "dataFormatType": { "index": 3, "kind": "element", "displayName": "Data Format Type", "required": true, "type": "object", "javaType": "org.apache.camel.model.DataFormatDefinition", "oneOf": [ "asn1", "avro", "barcode", "base64", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt", "swiftMx", "sysl [...]
+    "dataFormatType": { "index": 3, "kind": "element", "displayName": "Data Format Type", "required": true, "type": "object", "javaType": "org.apache.camel.model.DataFormatDefinition", "oneOf": [ "asn1", "avro", "barcode", "base64", "beanio", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt", "swift [...]
     "variableSend": { "index": 4, "kind": "attribute", "displayName": "Variable Send", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not on the  [...]
     "variableReceive": { "index": 5, "kind": "attribute", "displayName": "Variable Receive", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not o [...]
   }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/unmarshal.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/unmarshal.json
index 202b7a8f74b..9865b2de86e 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/unmarshal.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/models/unmarshal.json
@@ -15,7 +15,7 @@
     "id": { "index": 0, "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
     "description": { "index": 1, "kind": "element", "displayName": "Description", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" },
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime." },
-    "dataFormatType": { "index": 3, "kind": "element", "displayName": "Data Format Type", "required": true, "type": "object", "javaType": "org.apache.camel.model.DataFormatDefinition", "oneOf": [ "asn1", "avro", "barcode", "base64", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt", "swiftMx", "sysl [...]
+    "dataFormatType": { "index": 3, "kind": "element", "displayName": "Data Format Type", "required": true, "type": "object", "javaType": "org.apache.camel.model.DataFormatDefinition", "oneOf": [ "asn1", "avro", "barcode", "base64", "beanio", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt", "swift [...]
     "variableSend": { "index": 4, "kind": "attribute", "displayName": "Variable Send", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not on the  [...]
     "variableReceive": { "index": 5, "kind": "attribute", "displayName": "Variable Receive", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not o [...]
     "allowNullBody": { "index": 6, "kind": "attribute", "displayName": "Allow Null Body", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Indicates whether null is allowed as value of a body to unmarshall." }
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
index 39385a5b832..a0646288dbe 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd
@@ -85,6 +85,15 @@ Calls a Java bean
       <xs:documentation xml:lang="en">
 <![CDATA[
 Spring specific DefaultCamelBeanPostProcessor which uses Spring BeanPostProcessor to post process beans.
+]]>
+      </xs:documentation>
+    </xs:annotation>
+  </xs:element>
+  <xs:element name="beanio" type="tns:beanioDataFormat">
+    <xs:annotation>
+      <xs:documentation xml:lang="en">
+<![CDATA[
+Marshal and unmarshal Java beans to and from flat files (such as CSV, delimited, or fixed length formats).
 ]]>
       </xs:documentation>
     </xs:annotation>
@@ -7095,6 +7104,7 @@ down. Default value: false
             <xs:element ref="tns:avro"/>
             <xs:element ref="tns:barcode"/>
             <xs:element ref="tns:base64"/>
+            <xs:element ref="tns:beanio"/>
             <xs:element ref="tns:bindy"/>
             <xs:element ref="tns:cbor"/>
             <xs:element ref="tns:crypto"/>
@@ -7456,6 +7466,90 @@ The line separators to use. Uses new line characters (CRLF) by default.
 <![CDATA[
 Instead of emitting '' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode operations. Decoding
 seamlessly handles both modes. Is by default false. Default value: false
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="beanioDataFormat">
+    <xs:complexContent>
+      <xs:extension base="tns:dataFormat">
+        <xs:sequence/>
+        <xs:attribute name="mapping" type="xs:string" use="required">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+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.
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="streamName" type="xs:string" use="required">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+The name of the stream to use.
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="ignoreUnidentifiedRecords" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Whether to ignore unidentified records. Default value: false
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="ignoreUnexpectedRecords" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Whether to ignore unexpected records. Default value: false
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="ignoreInvalidRecords" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+Whether to ignore invalid records. Default value: false
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="encoding" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+The charset to use. Is by default the JVM platform default charset.
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="beanReaderErrorHandlerType" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+To use a custom org.apache.camel.dataformat.beanio.BeanIOErrorHandler as error handler while parsing. Configure the
+fully qualified class name of the error handler. Notice the options ignoreUnidentifiedRecords, ignoreUnexpectedRecords,
+and ignoreInvalidRecords may not be in use when you use a custom error handler.
+]]>
+            </xs:documentation>
+          </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="unmarshalSingleObject" type="xs:string">
+          <xs:annotation>
+            <xs:documentation xml:lang="en">
+<![CDATA[
+This options controls whether to unmarshal as a list of objects or as a single object only. The former is the default
+mode, and the latter is only intended in special use-cases where beanio maps the Camel message to a single POJO bean.
+Default value: false
 ]]>
             </xs:documentation>
           </xs:annotation>
@@ -13967,6 +14061,7 @@ To type used as a target data type in the transformation.
             <xs:element ref="tns:avro"/>
             <xs:element ref="tns:barcode"/>
             <xs:element ref="tns:base64"/>
+            <xs:element ref="tns:beanio"/>
             <xs:element ref="tns:bindy"/>
             <xs:element ref="tns:cbor"/>
             <xs:element ref="tns:crypto"/>
@@ -14986,6 +15081,7 @@ Set a reference to a custom Expression to use.
         <xs:element ref="tns:avro"/>
         <xs:element ref="tns:barcode"/>
         <xs:element ref="tns:base64"/>
+        <xs:element ref="tns:beanio"/>
         <xs:element ref="tns:bindy"/>
         <xs:element ref="tns:cbor"/>
         <xs:element ref="tns:crypto"/>
@@ -16863,6 +16959,7 @@ To configure a special tag for the operations within this rest definition.
             <xs:element ref="tns:avro"/>
             <xs:element ref="tns:barcode"/>
             <xs:element ref="tns:base64"/>
+            <xs:element ref="tns:beanio"/>
             <xs:element ref="tns:bindy"/>
             <xs:element ref="tns:cbor"/>
             <xs:element ref="tns:crypto"/>
diff --git a/components/camel-beanio/pom.xml b/components/camel-beanio/pom.xml
new file mode 100644
index 00000000000..24909e5b00f
--- /dev/null
+++ b/components/camel-beanio/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>components</artifactId>
+        <version>4.4.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-beanio</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Camel :: BeanIO</name>
+    <description>Camel BeanIO data format support</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.github.beanio</groupId>
+            <artifactId>beanio</artifactId>
+            <version>${beanio-version}</version>
+        </dependency>
+
+        <!-- testing -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-spring-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+</project>
diff --git a/components/camel-beanio/src/generated/java/org/apache/camel/dataformat/beanio/BeanIODataFormatConfigurer.java b/components/camel-beanio/src/generated/java/org/apache/camel/dataformat/beanio/BeanIODataFormatConfigurer.java
new file mode 100644
index 00000000000..46b4f2aa7ef
--- /dev/null
+++ b/components/camel-beanio/src/generated/java/org/apache/camel/dataformat/beanio/BeanIODataFormatConfigurer.java
@@ -0,0 +1,26 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.dataformat.beanio;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class BeanIODataFormatConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object target, String name, Object value, boolean ignoreCase) {
+        BeanIODataFormat dataformat = (BeanIODataFormat) target;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        default: return false;
+        }
+    }
+
+}
+
diff --git a/components/camel-beanio/src/generated/resources/META-INF/services/org/apache/camel/configurer/beanio-dataformat b/components/camel-beanio/src/generated/resources/META-INF/services/org/apache/camel/configurer/beanio-dataformat
new file mode 100644
index 00000000000..2575c10de22
--- /dev/null
+++ b/components/camel-beanio/src/generated/resources/META-INF/services/org/apache/camel/configurer/beanio-dataformat
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.dataformat.beanio.BeanIODataFormatConfigurer
diff --git a/components/camel-beanio/src/generated/resources/META-INF/services/org/apache/camel/dataformat.properties b/components/camel-beanio/src/generated/resources/META-INF/services/org/apache/camel/dataformat.properties
new file mode 100644
index 00000000000..f838b89bccd
--- /dev/null
+++ b/components/camel-beanio/src/generated/resources/META-INF/services/org/apache/camel/dataformat.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+dataFormats=beanio
+groupId=org.apache.camel
+artifactId=camel-beanio
+version=4.4.0-SNAPSHOT
+projectName=Camel :: BeanIO
+projectDescription=Camel BeanIO data format support
diff --git a/components/camel-beanio/src/generated/resources/META-INF/services/org/apache/camel/dataformat/beanio b/components/camel-beanio/src/generated/resources/META-INF/services/org/apache/camel/dataformat/beanio
new file mode 100644
index 00000000000..a2c24fff7c7
--- /dev/null
+++ b/components/camel-beanio/src/generated/resources/META-INF/services/org/apache/camel/dataformat/beanio
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.dataformat.beanio.BeanIODataFormat
diff --git a/components/camel-beanio/src/generated/resources/org/apache/camel/dataformat/beanio/beanio.json b/components/camel-beanio/src/generated/resources/org/apache/camel/dataformat/beanio/beanio.json
new file mode 100644
index 00000000000..42ac42f419e
--- /dev/null
+++ b/components/camel-beanio/src/generated/resources/org/apache/camel/dataformat/beanio/beanio.json
@@ -0,0 +1,29 @@
+{
+  "dataformat": {
+    "kind": "dataformat",
+    "name": "beanio",
+    "title": "BeanIO",
+    "description": "Marshal and unmarshal Java beans to and from flat files (such as CSV, delimited, or fixed length formats).",
+    "deprecated": false,
+    "firstVersion": "2.10.0",
+    "label": "dataformat,transformation,csv",
+    "javaType": "org.apache.camel.dataformat.beanio.BeanIODataFormat",
+    "supportLevel": "Stable",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-beanio",
+    "version": "4.4.0-SNAPSHOT",
+    "modelName": "beanio",
+    "modelJavaType": "org.apache.camel.model.dataformat.BeanioDataFormat"
+  },
+  "properties": {
+    "id": { "index": 0, "kind": "attribute", "displayName": "Id", "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", "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." },
+    "streamName": { "index": 2, "kind": "attribute", "displayName": "Stream Name", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the stream to use." },
+    "ignoreUnidentifiedRecords": { "index": 3, "kind": "attribute", "displayName": "Ignore Unidentified Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore unidentified records." },
+    "ignoreUnexpectedRecords": { "index": 4, "kind": "attribute", "displayName": "Ignore Unexpected Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore unexpected records." },
+    "ignoreInvalidRecords": { "index": 5, "kind": "attribute", "displayName": "Ignore Invalid Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore invalid records." },
+    "encoding": { "index": 6, "kind": "attribute", "displayName": "Encoding", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The charset to use. Is by default the JVM platform default charset." },
+    "beanReaderErrorHandlerType": { "index": 7, "kind": "attribute", "displayName": "Bean Reader Error Handler Type", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.dataformat.beanio.BeanIOErrorHandler as error handler while parsing. Configure the fully qualified class name of the error handler. Notice the options ignoreUnidentifiedRecords, [...]
+    "unmarshalSingleObject": { "index": 8, "kind": "attribute", "displayName": "Unmarshal Single Object", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "This options controls whether to unmarshal as a list of objects or as a single object only. The former is the default mode, and the latter is only intended in special use-cases where beanio maps th [...]
+  }
+}
diff --git a/components/camel-beanio/src/main/docs/beanio-dataformat.adoc b/components/camel-beanio/src/main/docs/beanio-dataformat.adoc
new file mode 100644
index 00000000000..918fa95e037
--- /dev/null
+++ b/components/camel-beanio/src/main/docs/beanio-dataformat.adoc
@@ -0,0 +1,120 @@
+= BeanIO DataFormat
+:doctitle: BeanIO
+:shortname: beanio
+:artifactid: camel-beanio
+:description: Marshal and unmarshal Java beans to and from flat files (such as CSV, delimited, or fixed length formats).
+:since: 2.10
+:supportlevel: Stable
+:tabs-sync-option:
+//Manually maintained attributes
+:camel-spring-boot-name: beanio
+
+*Since Camel {since}*
+
+The BeanIO Data Format uses
+https://beanio.github.io/[BeanIO] to handle flat payloads (such as XML, CSV,
+delimited, or fixed length formats).
+
+BeanIO is configured using a mappings XML file where you define the mapping from the flat format to Objects
+(POJOs). This mapping file is mandatory to use.
+
+== Options
+
+// dataformat options: START
+include::partial$dataformat-options.adoc[]
+// dataformat options: END
+
+== Usage
+
+An example of a
+https://svn.apache.org/repos/asf/camel/trunk/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/mappings.xml[mapping
+file is here].
+
+=== Using Java DSL
+
+To use the `BeanIODataFormat` you need to configure the data format with
+the mapping file, as well the name of the stream.
+
+In Java DSL this can be done as shown below. The streamName is "employeeFile".
+
+[source,java]
+----
+DataFormat format = new BeanIODataFormat(
+        "org/apache/camel/dataformat/beanio/mappings.xml",
+        "employeeFile");
+
+// a route which uses the bean io data format to format a CSV data
+// to java objects
+from("direct:unmarshal")
+        .unmarshal(format)
+        // and then split the message body so we get a message for each row
+        .split(body())
+        .to("mock:beanio-unmarshal");
+
+// convert list of java objects back to flat format
+from("direct:marshal")
+        .marshal(format)
+        .to("mock:beanio-marshal");
+----
+
+Then we have two routes. The first route is for transforming CSV data
+into a `List<Employee>` Java objects. Which we then split, so the mock endpoint receives a message for each row.
+
+The 2nd route is for the reverse operation, to transform a `List<Employee>` into a stream of CSV data.
+
+The CSV data could for example be as below:
+
+[source,text]
+----
+Joe,Smith,Developer,75000,10012009
+Jane,Doe,Architect,80000,01152008
+Jon,Anderson,Manager,85000,03182007
+----
+
+=== Using XML DSL
+
+To use the BeanIO data format in XML, you need to configure it using the
+`<beanio>` XML tag as shown below. The routes are similar to the example above.
+
+[source,xml]
+----
+<route>
+    <from uri="direct:unmarshal"/>
+    <unmarshal>
+        <beanio mapping="org/apache/camel/dataformat/beanio/mappings.xml" streamName="employeeFile"/>
+    </unmarshal>
+    <split>
+        <simple>${body}</simple>
+        <to uri="mock:beanio-unmarshal"/>
+    </split>
+</route>
+
+<route>
+    <from uri="direct:marshal"/>
+    <marshal>
+        <beanio mapping="org/apache/camel/dataformat/beanio/mappings.xml" streamName="employeeFile"/>
+    </marshal>
+    <to uri="mock:beanio-marshal"/>
+</route>
+----
+
+== Dependencies
+
+To use BeanIO in your Camel routes you need to add a dependency on
+*camel-beanio* which implements this data format.
+
+If you use Maven you can just add the following to your pom.xml,
+substituting the version number for the latest & greatest release (see
+the download page for the latest versions).
+
+[source,xml]
+---------------------------------------
+<dependency>
+  <groupId>org.apache.camel</groupId>
+  <artifactId>camel-beanio</artifactId>
+  <version>4.4.0</version>
+</dependency>
+---------------------------------------
+
+
+include::spring-boot:partial$starter.adoc[]
diff --git a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOConfiguration.java b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOConfiguration.java
new file mode 100644
index 00000000000..081975dd32d
--- /dev/null
+++ b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOConfiguration.java
@@ -0,0 +1,123 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.nio.charset.Charset;
+import java.util.Properties;
+
+import org.beanio.BeanReaderErrorHandler;
+
+/**
+ * To configure the BeanIO data format, or BeanIO splitter.
+ */
+public class BeanIOConfiguration {
+
+    private String streamName;
+    private String mapping;
+    private boolean ignoreUnidentifiedRecords;
+    private boolean ignoreUnexpectedRecords;
+    private boolean ignoreInvalidRecords;
+    private Charset encoding = Charset.defaultCharset();
+    private Properties properties;
+    private BeanReaderErrorHandler beanReaderErrorHandler;
+    private String beanReaderErrorHandlerType;
+    private boolean unmarshalSingleObject;
+
+    public String getMapping() {
+        return mapping;
+    }
+
+    public void setMapping(String mapping) {
+        this.mapping = mapping;
+    }
+
+    public String getStreamName() {
+        return streamName;
+    }
+
+    public void setStreamName(String streamName) {
+        this.streamName = streamName;
+    }
+
+    public boolean isIgnoreUnidentifiedRecords() {
+        return ignoreUnidentifiedRecords;
+    }
+
+    public void setIgnoreUnidentifiedRecords(boolean ignoreUnidentifiedRecords) {
+        this.ignoreUnidentifiedRecords = ignoreUnidentifiedRecords;
+    }
+
+    public boolean isIgnoreUnexpectedRecords() {
+        return ignoreUnexpectedRecords;
+    }
+
+    public void setIgnoreUnexpectedRecords(boolean ignoreUnexpectedRecords) {
+        this.ignoreUnexpectedRecords = ignoreUnexpectedRecords;
+    }
+
+    public boolean isIgnoreInvalidRecords() {
+        return ignoreInvalidRecords;
+    }
+
+    public void setIgnoreInvalidRecords(boolean ignoreInvalidRecords) {
+        this.ignoreInvalidRecords = ignoreInvalidRecords;
+    }
+
+    public Charset getEncoding() {
+        return encoding;
+    }
+
+    public void setEncoding(Charset encoding) {
+        this.encoding = encoding;
+    }
+
+    public Properties getProperties() {
+        return properties;
+    }
+
+    public void setProperties(Properties properties) {
+        this.properties = properties;
+    }
+
+    public BeanReaderErrorHandler getBeanReaderErrorHandler() {
+        return beanReaderErrorHandler;
+    }
+
+    public void setBeanReaderErrorHandler(BeanReaderErrorHandler beanReaderErrorHandler) {
+        this.beanReaderErrorHandler = beanReaderErrorHandler;
+    }
+
+    public String getBeanReaderErrorHandlerType() {
+        return beanReaderErrorHandlerType;
+    }
+
+    public void setBeanReaderErrorHandlerType(String beanReaderErrorHandlerType) {
+        this.beanReaderErrorHandlerType = beanReaderErrorHandlerType;
+    }
+
+    public void setBeanReaderErrorHandlerType(Class<?> beanReaderErrorHandlerType) {
+        this.beanReaderErrorHandlerType = beanReaderErrorHandlerType.getName();
+    }
+
+    public boolean isUnmarshalSingleObject() {
+        return unmarshalSingleObject;
+    }
+
+    public void setUnmarshalSingleObject(boolean unmarshalSingleObject) {
+        this.unmarshalSingleObject = unmarshalSingleObject;
+    }
+}
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
new file mode 100644
index 00000000000..1ff1892f62a
--- /dev/null
+++ b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIODataFormat.java
@@ -0,0 +1,298 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Exchange;
+import org.apache.camel.NoTypeConversionAvailableException;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.DataFormatName;
+import org.apache.camel.spi.annotations.Dataformat;
+import org.apache.camel.support.ObjectHelper;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.IOHelper;
+import org.beanio.BeanReader;
+import org.beanio.BeanReaderErrorHandler;
+import org.beanio.BeanWriter;
+import org.beanio.StreamFactory;
+import org.beanio.Unmarshaller;
+
+import static org.apache.camel.dataformat.beanio.BeanIOHelper.getOrCreateBeanReaderErrorHandler;
+
+/**
+ * A <a href="http://camel.apache.org/data-format.html">data format</a> ( {@link DataFormat}) for beanio data.
+ */
+@Dataformat("beanio")
+public class BeanIODataFormat extends ServiceSupport implements DataFormat, DataFormatName, CamelContextAware {
+
+    private transient CamelContext camelContext;
+    private transient StreamFactory factory;
+    private BeanIOConfiguration configuration = new BeanIOConfiguration();
+
+    public BeanIODataFormat() {
+    }
+
+    public BeanIODataFormat(String mapping, String streamName) {
+        setMapping(mapping);
+        setStreamName(streamName);
+    }
+
+    @Override
+    public String getDataFormatName() {
+        return "beanio";
+    }
+
+    @Override
+    protected void doInit() throws Exception {
+        super.doInit();
+
+        org.apache.camel.util.ObjectHelper.notNull(getStreamName(), "Stream name not configured.");
+        if (factory == null) {
+            // Create the stream factory that will be used to read/write objects.
+            factory = StreamFactory.newInstance();
+            if (ResourceHelper.isClasspathUri(getMapping())) {
+                loadMappingResource();
+            }
+        }
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        super.doStart();
+
+        if (!ResourceHelper.isClasspathUri(getMapping())) {
+            loadMappingResource();
+        }
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        factory = null;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    StreamFactory getFactory() {
+        return factory;
+    }
+
+    @Override
+    public void marshal(Exchange exchange, Object body, OutputStream stream) throws Exception {
+        List<Object> models = getModels(exchange, body);
+        writeModels(stream, models);
+    }
+
+    @Override
+    public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
+        if (isUnmarshalSingleObject()) {
+            return readSingleModel(exchange, stream);
+        } else {
+            return readModels(exchange, stream);
+        }
+    }
+
+    private void loadMappingResource() throws Exception {
+        // Load the mapping file using the resource helper to ensure it can be loaded in OSGi and other environments
+        InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(getCamelContext(), getMapping());
+        try {
+            if (getProperties() != null) {
+                factory.load(is, getProperties());
+            } else {
+                factory.load(is);
+            }
+        } finally {
+            IOHelper.close(is);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private List<Object> getModels(Exchange exchange, Object body) {
+        List<Object> models;
+
+        if (body instanceof Map && isUnmarshalSingleObject()) {
+            models = new ArrayList<>();
+            models.add(body);
+        } else if ((models = exchange.getContext().getTypeConverter().convertTo(List.class, body)) == null) {
+            models = new ArrayList<>();
+            for (Object model : ObjectHelper.createIterable(body)) {
+                models.add(model);
+            }
+        }
+        return models;
+    }
+
+    private void writeModels(OutputStream stream, List<Object> models) {
+        BufferedWriter streamWriter = IOHelper.buffered(new OutputStreamWriter(stream, getEncoding()));
+        BeanWriter out = factory.createWriter(getStreamName(), streamWriter);
+
+        for (Object obj : models) {
+            out.write(obj);
+        }
+
+        out.flush();
+        out.close();
+    }
+
+    private List<Object> readModels(Exchange exchange, InputStream stream) throws Exception {
+        List<Object> results = new ArrayList<>();
+        BufferedReader streamReader = IOHelper.buffered(new InputStreamReader(stream, getEncoding()));
+
+        BeanReader in = factory.createReader(getStreamName(), streamReader);
+
+        BeanReaderErrorHandler errorHandler = getOrCreateBeanReaderErrorHandler(configuration, exchange, results, null);
+        in.setErrorHandler(errorHandler);
+
+        try {
+            Object readObject;
+            while ((readObject = in.read()) != null) {
+                if (readObject instanceof BeanIOHeader) {
+                    exchange.getOut().getHeaders().putAll(((BeanIOHeader) readObject).getHeaders());
+                }
+                results.add(readObject);
+            }
+        } finally {
+            in.close();
+        }
+
+        return results;
+    }
+
+    private Object readSingleModel(Exchange exchange, InputStream stream) throws NoTypeConversionAvailableException {
+        BufferedReader streamReader = IOHelper.buffered(new InputStreamReader(stream, getEncoding()));
+        try {
+            String data = exchange.getContext().getTypeConverter().mandatoryConvertTo(String.class, exchange, streamReader);
+            Unmarshaller unmarshaller = factory.createUnmarshaller(getStreamName());
+            return unmarshaller.unmarshal(data);
+        } finally {
+            IOHelper.close(stream);
+        }
+    }
+
+    public String getMapping() {
+        return configuration.getMapping();
+    }
+
+    public void setIgnoreUnexpectedRecords(boolean ignoreUnexpectedRecords) {
+        configuration.setIgnoreUnexpectedRecords(ignoreUnexpectedRecords);
+    }
+
+    public void setProperties(Properties properties) {
+        configuration.setProperties(properties);
+    }
+
+    public void setStreamName(String streamName) {
+        configuration.setStreamName(streamName);
+    }
+
+    public boolean isIgnoreUnidentifiedRecords() {
+        return configuration.isIgnoreUnidentifiedRecords();
+    }
+
+    public boolean isIgnoreInvalidRecords() {
+        return configuration.isIgnoreInvalidRecords();
+    }
+
+    public void setIgnoreInvalidRecords(boolean ignoreInvalidRecords) {
+        configuration.setIgnoreInvalidRecords(ignoreInvalidRecords);
+    }
+
+    public void setEncoding(String encoding) {
+        setEncoding(Charset.forName(encoding));
+    }
+
+    public void setEncoding(Charset encoding) {
+        if (encoding == null) {
+            throw new IllegalArgumentException("Charset encoding is null");
+        }
+        configuration.setEncoding(encoding);
+    }
+
+    public boolean isIgnoreUnexpectedRecords() {
+        return configuration.isIgnoreUnexpectedRecords();
+    }
+
+    public Properties getProperties() {
+        return configuration.getProperties();
+    }
+
+    public String getStreamName() {
+        return configuration.getStreamName();
+    }
+
+    public void setMapping(String mapping) {
+        configuration.setMapping(mapping);
+    }
+
+    public void setIgnoreUnidentifiedRecords(boolean ignoreUnidentifiedRecords) {
+        configuration.setIgnoreUnidentifiedRecords(ignoreUnidentifiedRecords);
+    }
+
+    public Charset getEncoding() {
+        return configuration.getEncoding();
+    }
+
+    public BeanReaderErrorHandler getBeanReaderErrorHandler() {
+        return configuration.getBeanReaderErrorHandler();
+    }
+
+    public void setBeanReaderErrorHandler(BeanReaderErrorHandler beanReaderErrorHandler) {
+        configuration.setBeanReaderErrorHandler(beanReaderErrorHandler);
+    }
+
+    public String getBeanReaderErrorHandlerType() {
+        return configuration.getBeanReaderErrorHandlerType();
+    }
+
+    public void setBeanReaderErrorHandlerType(String beanReaderErrorHandlerType) {
+        configuration.setBeanReaderErrorHandlerType(beanReaderErrorHandlerType);
+    }
+
+    public void setBeanReaderErrorHandlerType(Class<?> beanReaderErrorHandlerType) {
+        configuration.setBeanReaderErrorHandlerType(beanReaderErrorHandlerType);
+    }
+
+    public boolean isUnmarshalSingleObject() {
+        return configuration.isUnmarshalSingleObject();
+    }
+
+    public void setUnmarshalSingleObject(boolean unmarshalSingleObject) {
+        configuration.setUnmarshalSingleObject(unmarshalSingleObject);
+    }
+
+}
diff --git a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOErrorHandler.java b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOErrorHandler.java
new file mode 100644
index 00000000000..5764316dbdd
--- /dev/null
+++ b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOErrorHandler.java
@@ -0,0 +1,126 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.beanio.BeanReaderErrorHandler;
+import org.beanio.BeanReaderErrorHandlerSupport;
+import org.beanio.InvalidRecordException;
+import org.beanio.UnexpectedRecordException;
+import org.beanio.UnidentifiedRecordException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A {@link BeanReaderErrorHandler} to handle errors during parsing. This error handler is prototype scoped and provides
+ * access to the current {@link Exchange}. You can perform any custom initialization logic in the {@link #init()}
+ * method.
+ */
+public class BeanIOErrorHandler extends BeanReaderErrorHandlerSupport {
+
+    static final String LOG_PREFIX = "BeanIO: ";
+    static final Logger LOG = LoggerFactory.getLogger(BeanIOErrorHandler.class);
+
+    private BeanIOConfiguration configuration;
+    private Exchange exchange;
+    private List<Object> results;
+    private BeanIOIterator iterator;
+
+    public BeanIOErrorHandler() {
+    }
+
+    public void init() {
+        // any custom init code here
+    }
+
+    /**
+     * The configuration
+     */
+    public BeanIOConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(BeanIOConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    /**
+     * The current exchange
+     */
+    public Exchange getExchange() {
+        return exchange;
+    }
+
+    public void setExchange(Exchange exchange) {
+        this.exchange = exchange;
+    }
+
+    void setResults(List<Object> results) {
+        this.results = results;
+    }
+
+    void setIterator(BeanIOIterator iterator) {
+        this.iterator = iterator;
+    }
+
+    /**
+     * Sets a custom POJO as the result from handling an beanio error.
+     */
+    public void handleErrorAndAddAsResult(Object result) {
+        if (results != null) {
+            results.add(result);
+        } else if (iterator != null) {
+            iterator.setNext(result);
+        }
+    }
+
+    @Override
+    public void invalidRecord(InvalidRecordException ex) throws Exception {
+        String msg = LOG_PREFIX + "InvalidRecord: " + ex.getMessage() + ": " + ex.getRecordContext().getRecordText();
+        if (getConfiguration().isIgnoreInvalidRecords()) {
+            LOG.debug(msg);
+        } else {
+            LOG.warn(msg);
+            throw ex;
+        }
+    }
+
+    @Override
+    public void unexpectedRecord(UnexpectedRecordException ex) throws Exception {
+        String msg = LOG_PREFIX + "UnexpectedRecord: " + ex.getMessage() + ": " + ex.getRecordContext().getRecordText();
+        if (getConfiguration().isIgnoreUnexpectedRecords()) {
+            LOG.debug(msg);
+        } else {
+            LOG.warn(msg);
+            throw ex;
+        }
+    }
+
+    @Override
+    public void unidentifiedRecord(UnidentifiedRecordException ex) throws Exception {
+        String msg = LOG_PREFIX + "UnidentifiedRecord: " + ex.getMessage() + ": " + ex.getRecordContext().getRecordText();
+        if (getConfiguration().isIgnoreUnidentifiedRecords()) {
+            LOG.debug(msg);
+        } else {
+            LOG.warn(msg);
+            throw ex;
+        }
+    }
+
+}
diff --git a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOHeader.java b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOHeader.java
new file mode 100644
index 00000000000..c29e14a4dd8
--- /dev/null
+++ b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOHeader.java
@@ -0,0 +1,25 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.util.Map;
+
+public interface BeanIOHeader {
+
+    Map<String, Object> getHeaders();
+
+}
diff --git a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOHelper.java b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOHelper.java
new file mode 100644
index 00000000000..2273ef9ebac
--- /dev/null
+++ b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOHelper.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.dataformat.beanio;
+
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.util.ObjectHelper;
+import org.beanio.BeanReaderErrorHandler;
+
+/**
+ * Helper class
+ */
+public final class BeanIOHelper {
+
+    private BeanIOHelper() {
+        // utility class
+    }
+
+    public static BeanReaderErrorHandler getOrCreateBeanReaderErrorHandler(
+            BeanIOConfiguration configuration, Exchange exchange,
+            List<Object> results, BeanIOIterator iterator)
+            throws Exception {
+        BeanReaderErrorHandler answer = null;
+
+        if (ObjectHelper.isNotEmpty(configuration.getBeanReaderErrorHandlerType())) {
+            Class<?> clazz = exchange.getContext().getClassResolver()
+                    .resolveMandatoryClass(configuration.getBeanReaderErrorHandlerType());
+            Object instance = exchange.getContext().getInjector().newInstance(clazz);
+            answer = (BeanReaderErrorHandler) instance;
+        }
+        if (answer == null && ObjectHelper.isNotEmpty(configuration.getBeanReaderErrorHandler())) {
+            answer = configuration.getBeanReaderErrorHandler();
+        }
+        if (answer == null) {
+            answer = new BeanIOErrorHandler();
+        }
+        // if the error handler extends BeanIOErrorHandler then its prototype scoped
+        // and then inject the current exchange and init
+        if (answer instanceof BeanIOErrorHandler) {
+            BeanIOErrorHandler eh = (BeanIOErrorHandler) answer;
+            eh.setConfiguration(configuration);
+            eh.setExchange(exchange);
+            eh.setResults(results);
+            eh.setIterator(iterator);
+            eh.init();
+        }
+
+        return answer;
+    }
+
+}
diff --git a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOIterator.java b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOIterator.java
new file mode 100644
index 00000000000..dd1829a2ddf
--- /dev/null
+++ b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOIterator.java
@@ -0,0 +1,81 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Iterator;
+
+import org.beanio.BeanReader;
+
+public class BeanIOIterator implements Iterator<Object>, Closeable {
+
+    private BeanReader reader;
+    private transient Object next;
+    private transient Object forceNext;
+
+    public BeanIOIterator(BeanReader reader) {
+        this.reader = reader;
+        this.next = next();
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (reader != null) {
+            reader.close();
+            reader = null;
+        }
+    }
+
+    @Override
+    public boolean hasNext() {
+        return next != null;
+    }
+
+    @Override
+    public Object next() {
+        Object answer = next;
+        if (answer == null) {
+            answer = reader.read();
+            // after read we may force a next
+            if (forceNext != null) {
+                answer = forceNext;
+                forceNext = null;
+            }
+        } else {
+            next = reader.read();
+            // after read we may force a next
+            if (forceNext != null) {
+                next = forceNext;
+                forceNext = null;
+            }
+        }
+        return answer;
+    }
+
+    @Override
+    public void remove() {
+        // noop
+    }
+
+    /**
+     * Sets a custom object as the next, such as from a custom error handler
+     */
+    public void setNext(Object next) {
+        this.forceNext = next;
+    }
+}
diff --git a/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOSplitter.java b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOSplitter.java
new file mode 100644
index 00000000000..5ef9e1feafe
--- /dev/null
+++ b/components/camel-beanio/src/main/java/org/apache/camel/dataformat/beanio/BeanIOSplitter.java
@@ -0,0 +1,211 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Expression;
+import org.apache.camel.Message;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.WrappedFile;
+import org.apache.camel.support.ResourceHelper;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.beanio.BeanReader;
+import org.beanio.BeanReaderErrorHandler;
+import org.beanio.StreamFactory;
+
+import static org.apache.camel.dataformat.beanio.BeanIOHelper.getOrCreateBeanReaderErrorHandler;
+
+/**
+ * You can use {@link BeanIOSplitter} with the Camel Splitter EIP to split big payloads using a stream mode to avoid
+ * reading the entire content into memory.
+ */
+public class BeanIOSplitter implements Expression {
+
+    private BeanIOConfiguration configuration = new BeanIOConfiguration();
+    private StreamFactory factory;
+
+    public BeanIOSplitter() throws Exception {
+    }
+
+    public BeanIOSplitter(BeanIOConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    public BeanIOSplitter(String mapping, String streamName) {
+        setMapping(mapping);
+        setStreamName(streamName);
+    }
+
+    protected StreamFactory createStreamFactory(CamelContext camelContext) throws Exception {
+        ObjectHelper.notNull(getStreamName(), "Stream name not configured.");
+        // Create the stream factory that will be used to read/write objects.
+        StreamFactory answer = StreamFactory.newInstance();
+
+        // Load the mapping file using the resource helper to ensure it can be loaded in OSGi and other environments
+        InputStream is = ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, getMapping());
+        try {
+            if (getProperties() != null) {
+                answer.load(is, getProperties());
+            } else {
+                answer.load(is);
+            }
+        } finally {
+            IOHelper.close(is);
+        }
+
+        return answer;
+    }
+
+    public Object evaluate(Exchange exchange) throws Exception {
+        Message msg = exchange.getIn();
+        Object body = msg.getBody();
+
+        if (factory == null) {
+            factory = createStreamFactory(exchange.getContext());
+        }
+
+        BeanReader beanReader = null;
+        if (body instanceof WrappedFile) {
+            body = ((WrappedFile) body).getFile();
+        }
+        if (body instanceof File) {
+            File file = (File) body;
+            beanReader = factory.createReader(getStreamName(), file);
+        }
+        if (beanReader == null) {
+            Reader reader = msg.getMandatoryBody(Reader.class);
+            beanReader = factory.createReader(getStreamName(), reader);
+        }
+
+        BeanIOIterator iterator = new BeanIOIterator(beanReader);
+
+        BeanReaderErrorHandler errorHandler = getOrCreateBeanReaderErrorHandler(configuration, exchange, null, iterator);
+        beanReader.setErrorHandler(errorHandler);
+
+        return iterator;
+    }
+
+    @Override
+    public <T> T evaluate(Exchange exchange, Class<T> type) {
+        try {
+            Object result = evaluate(exchange);
+            return exchange.getContext().getTypeConverter().convertTo(type, exchange, result);
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+    }
+
+    public BeanIOConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(BeanIOConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    public StreamFactory getFactory() {
+        return factory;
+    }
+
+    public void setFactory(StreamFactory factory) {
+        this.factory = factory;
+    }
+
+    public String getMapping() {
+        return configuration.getMapping();
+    }
+
+    public void setIgnoreUnexpectedRecords(boolean ignoreUnexpectedRecords) {
+        configuration.setIgnoreUnexpectedRecords(ignoreUnexpectedRecords);
+    }
+
+    public void setProperties(Properties properties) {
+        configuration.setProperties(properties);
+    }
+
+    public void setStreamName(String streamName) {
+        configuration.setStreamName(streamName);
+    }
+
+    public boolean isIgnoreUnidentifiedRecords() {
+        return configuration.isIgnoreUnidentifiedRecords();
+    }
+
+    public boolean isIgnoreInvalidRecords() {
+        return configuration.isIgnoreInvalidRecords();
+    }
+
+    public void setIgnoreInvalidRecords(boolean ignoreInvalidRecords) {
+        configuration.setIgnoreInvalidRecords(ignoreInvalidRecords);
+    }
+
+    public void setEncoding(Charset encoding) {
+        configuration.setEncoding(encoding);
+    }
+
+    public boolean isIgnoreUnexpectedRecords() {
+        return configuration.isIgnoreUnexpectedRecords();
+    }
+
+    public Properties getProperties() {
+        return configuration.getProperties();
+    }
+
+    public String getStreamName() {
+        return configuration.getStreamName();
+    }
+
+    public void setMapping(String mapping) {
+        configuration.setMapping(mapping);
+    }
+
+    public void setIgnoreUnidentifiedRecords(boolean ignoreUnidentifiedRecords) {
+        configuration.setIgnoreUnidentifiedRecords(ignoreUnidentifiedRecords);
+    }
+
+    public Charset getEncoding() {
+        return configuration.getEncoding();
+    }
+
+    public BeanReaderErrorHandler getBeanReaderErrorHandler() {
+        return configuration.getBeanReaderErrorHandler();
+    }
+
+    public void setBeanReaderErrorHandler(BeanReaderErrorHandler beanReaderErrorHandler) {
+        configuration.setBeanReaderErrorHandler(beanReaderErrorHandler);
+    }
+
+    public String getBeanReaderErrorHandlerType() {
+        return configuration.getBeanReaderErrorHandlerType();
+    }
+
+    public void setBeanReaderErrorHandlerType(String beanReaderErrorHandlerType) {
+        configuration.setBeanReaderErrorHandlerType(beanReaderErrorHandlerType);
+    }
+
+    public void setBeanReaderErrorHandlerType(Class<?> beanReaderErrorHandlerType) {
+        configuration.setBeanReaderErrorHandlerType(beanReaderErrorHandlerType);
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/A1Record.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/A1Record.java
new file mode 100644
index 00000000000..39346a8ee81
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/A1Record.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dataformat.beanio;
+
+public class A1Record extends Record {
+    Double currentPrice;
+
+    public A1Record() {
+    }
+
+    public A1Record(String sedol, String source, Double currentPrice) {
+        super(sedol, source);
+        this.currentPrice = currentPrice;
+    }
+
+    public Double getCurrentPrice() {
+        return currentPrice;
+    }
+
+    public void setCurrentPrice(Double currentPrice) {
+        this.currentPrice = currentPrice;
+    }
+
+    @Override
+    public int hashCode() {
+        return currentPrice != null ? currentPrice.hashCode() : 0;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        } else if (obj == this) {
+            return true;
+        } else {
+            A1Record record = (A1Record) obj;
+            return super.equals(record) && this.currentPrice.doubleValue() == record.getCurrentPrice().doubleValue();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "SEDOL[" + this.sedol + "], SOURCE[" + this.source + "], PRICE[" + this.currentPrice + "]";
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/B1Record.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/B1Record.java
new file mode 100644
index 00000000000..93f496da92b
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/B1Record.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dataformat.beanio;
+
+public class B1Record extends Record {
+    String securityName;
+
+    public B1Record() {
+    }
+
+    public B1Record(String sedol, String source, String securityName) {
+        super(sedol, source);
+        this.securityName = securityName;
+    }
+
+    public String getSecurityName() {
+        return securityName;
+    }
+
+    public void setSecurityName(String securityName) {
+        this.securityName = securityName;
+    }
+
+    @Override
+    public int hashCode() {
+        return securityName != null ? securityName.hashCode() : 0;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        } else if (obj == this) {
+            return true;
+        } else {
+            B1Record record = (B1Record) obj;
+            return super.equals(record) && this.securityName.equals(record.getSecurityName());
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "SEDOL[" + this.sedol + "], SOURCE[" + this.source + "], NAME[" + this.securityName + "]";
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIODataFormatComplexTest.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIODataFormatComplexTest.java
new file mode 100644
index 00000000000..20956eb1757
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIODataFormatComplexTest.java
@@ -0,0 +1,239 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.beanio.InvalidRecordException;
+import org.beanio.UnexpectedRecordException;
+import org.beanio.UnidentifiedRecordException;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.test.junit5.TestSupport.assertIsInstanceOf;
+
+public class BeanIODataFormatComplexTest extends CamelTestSupport {
+
+    private static Locale defaultLocale;
+
+    private final String recordData = "0001917A112345.678900           " + Constants.LS
+                                      + "0002374A159303290.020           " + Constants.LS
+                                      + "0015219B1SECURITY ONE           " + Constants.LS
+                                      + "END OF SECTION 1                " + Constants.LS
+                                      + "0076647A10.0000000001           " + Constants.LS
+                                      + "0135515A1999999999999           " + Constants.LS
+                                      + "2000815B1SECURITY TWO           " + Constants.LS
+                                      + "2207122B1SECURITY THR           " + Constants.LS
+                                      + "END OF FILE 000007              " + Constants.LS;
+
+    private final String data = "0000000A1030808PRICE            " + Constants.LS
+                                + "0000000B1030808SECURITY         " + Constants.LS
+                                + "HEADER END                      " + Constants.LS
+                                + recordData;
+
+    private final String unExpectedData = "0000000A1030808PRICE            " + Constants.LS
+                                          + "0000000B1030808SECURITY         " + Constants.LS
+                                          + "0000000B1030808SECURITY         " + Constants.LS
+                                          + "HEADER END                      " + Constants.LS
+                                          + recordData;
+
+    private final String invalidData = "0000000A1030808PRICE            " + Constants.LS
+                                       + "0000000B1030808SECURITY         EXTRA DATA" + Constants.LS
+                                       + "0000000B1030808SECURITY         " + Constants.LS
+                                       + "HEADER END                      " + Constants.LS
+                                       + recordData;
+
+    private final String unidentifiedData = "0000000A1030808PRICE            " + Constants.LS
+                                            + "0000000C1030808SECURITY         " + Constants.LS
+                                            + "0000000B1030808SECURITY         " + Constants.LS
+                                            + "HEADER END                      " + Constants.LS
+                                            + recordData;
+
+    @BeforeAll
+    public static void setLocale() {
+        if (!Locale.getDefault().equals(Locale.ENGLISH)) {
+
+            // the Locale used for the number formatting of the above data is
+            // english which could be other than the default locale
+            defaultLocale = Locale.getDefault();
+            Locale.setDefault(Locale.ENGLISH);
+        }
+    }
+
+    @AfterAll
+    public static void resetLocale() {
+        if (defaultLocale != null) {
+            Locale.setDefault(defaultLocale);
+        }
+    }
+
+    @Test
+    void testMarshal() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:beanio-marshal");
+        mock.expectedBodiesReceived(data);
+
+        template.sendBody("direct:marshal", createTestData(false));
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testUnmarshal() throws Exception {
+        context.setTracing(true);
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedBodiesReceived(createTestData(false));
+
+        template.sendBody("direct:unmarshal", data);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testUnmarshalUnexpected() throws Exception {
+        Throwable ex = null;
+
+        try {
+            template.sendBody("direct:unmarshal", unExpectedData);
+        } catch (Exception e) {
+            ex = e.getCause();
+        }
+
+        assertIsInstanceOf(UnexpectedRecordException.class, ex);
+    }
+
+    @Test
+    void testUnmarshalInvalid() throws Exception {
+        Throwable ex = null;
+
+        try {
+            template.sendBody("direct:unmarshal", invalidData);
+        } catch (Exception e) {
+            ex = e.getCause();
+        }
+
+        assertIsInstanceOf(InvalidRecordException.class, ex);
+    }
+
+    @Test
+    void testUnmarshalUnidentifiedIgnore() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedBodiesReceived(createTestData(false));
+        template.sendBody("direct:unmarshal-forgiving", unidentifiedData);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testUnmarshalUnexpectedIgnore() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedBodiesReceived(createTestData(false));
+        template.sendBody("direct:unmarshal-forgiving", unExpectedData);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testUnmarshalInvalidIgnore() throws Exception {
+        context.setTracing(true);
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedBodiesReceived(createTestData(true));
+        template.sendBody("direct:unmarshal-forgiving", invalidData);
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testUnmarshalUnidentified() {
+        Throwable ex = null;
+
+        try {
+            template.sendBody("direct:unmarshal", unidentifiedData);
+        } catch (Exception e) {
+            ex = e.getCause();
+        }
+
+        assertIsInstanceOf(UnidentifiedRecordException.class, ex);
+    }
+
+    private List<Object> createTestData(boolean skipB1header) throws ParseException {
+        String source = "camel-beanio";
+        List<Object> body = new ArrayList<>();
+
+        Date date = new SimpleDateFormat("ddMMyy").parse("030808");
+        Header hFirst = new Header("A1", date, "PRICE");
+        Header hSecond = new Header("B1", date, "SECURITY");
+        Separator headerEnd = new Separator("HEADER END");
+
+        A1Record first = new A1Record("0001917", source, 12345.678900);
+        A1Record second = new A1Record("0002374", source, 59303290.020);
+        B1Record third = new B1Record("0015219", source, "SECURITY ONE");
+        Separator sectionEnd = new Separator("END OF SECTION 1");
+        A1Record fourth = new A1Record("0076647", source, 0.0000000001);
+        A1Record fifth = new A1Record("0135515", source, 999999999999d);
+        B1Record sixth = new B1Record("2000815", source, "SECURITY TWO");
+        B1Record seventh = new B1Record("2207122", source, "SECURITY THR");
+
+        body.add(hFirst);
+        if (!skipB1header) {
+            body.add(hSecond);
+        }
+        body.add(headerEnd);
+        body.add(first);
+        body.add(second);
+        body.add(third);
+        body.add(sectionEnd);
+        body.add(fourth);
+        body.add(fifth);
+        body.add(sixth);
+        body.add(seventh);
+
+        Trailer trailer = new Trailer(7);
+        body.add(trailer);
+
+        return body;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                BeanIODataFormat format
+                        = new BeanIODataFormat("org/apache/camel/dataformat/beanio/mappings.xml", "securityData");
+
+                BeanIODataFormat forgivingFormat
+                        = new BeanIODataFormat("org/apache/camel/dataformat/beanio/mappings.xml", "securityData");
+                forgivingFormat.setIgnoreInvalidRecords(true);
+                forgivingFormat.setIgnoreUnexpectedRecords(true);
+                forgivingFormat.setIgnoreUnidentifiedRecords(true);
+
+                from("direct:unmarshal").unmarshal(format).split(simple("${body}")).to("mock:beanio-unmarshal");
+
+                from("direct:unmarshal-forgiving").unmarshal(forgivingFormat).split(simple("${body}"))
+                        .to("mock:beanio-unmarshal");
+
+                from("direct:marshal").marshal(format).to("mock:beanio-marshal");
+            }
+        };
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIODataFormatSimpleCustomBeanReaderErrorHandlerTest.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIODataFormatSimpleCustomBeanReaderErrorHandlerTest.java
new file mode 100644
index 00000000000..dc278aa83d8
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIODataFormatSimpleCustomBeanReaderErrorHandlerTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class BeanIODataFormatSimpleCustomBeanReaderErrorHandlerTest extends CamelTestSupport {
+
+    // START SNIPPET: e2
+    private static final String FIXED_DATA = "Joe,Smith,Developer,75000,10012009" + Constants.LS
+                                             + "Jane,Doe,Architect,80000,01152008" + Constants.LS
+                                             + "Jon,Anderson,Manager,85000,03182007" + Constants.LS;
+    // END SNIPPET: e2
+
+    private static final String FIXED_FAIL_DATA = "Joe,Smith,Developer,75000,10012009" + Constants.LS
+                                                  + "Jane,Doe,Architect,80000,01152008" + Constants.LS
+                                                  + "Jon,Anderson,Manager,XXX,03182007" + Constants.LS;
+
+    @Test
+    void testMarshal() throws Exception {
+        List<Employee> employees = getEmployees();
+
+        MockEndpoint mock = getMockEndpoint("mock:beanio-marshal");
+        mock.expectedBodiesReceived(FIXED_DATA);
+
+        template.sendBody("direct:marshal", employees);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testUnmarshal() throws Exception {
+        List<Employee> employees = getEmployees();
+
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedBodiesReceived(employees);
+
+        template.sendBody("direct:unmarshal", FIXED_DATA);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testUnmarshalFail() throws Exception {
+        // there should be 1 splitted that failed we get also
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedMessageCount(3);
+        mock.message(0).body().isInstanceOf(Employee.class);
+        mock.message(1).body().isInstanceOf(Employee.class);
+        mock.message(2).body().isInstanceOf(MyErrorDto.class);
+
+        template.sendBody("direct:unmarshal", FIXED_FAIL_DATA);
+
+        mock.assertIsSatisfied();
+
+        assertEquals("employee", mock.getReceivedExchanges().get(2).getIn().getBody(MyErrorDto.class).getRecord());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                // START SNIPPET: e1
+                // setup beanio data format using the mapping file, loaded from the classpath
+                BeanIODataFormat format = new BeanIODataFormat(
+                        "org/apache/camel/dataformat/beanio/mappings.xml",
+                        "employeeFile");
+
+                // use our custom error handler
+                format.setBeanReaderErrorHandlerType(MyErrorHandler.class);
+
+                // a route which uses the bean io data format to format a CSV data
+                // to java objects
+                from("direct:unmarshal")
+                        .unmarshal(format)
+                        // and then split the message body so we get a message for each row
+                        .split(body())
+                        .to("mock:beanio-unmarshal");
+
+                // convert list of java objects back to flat format
+                from("direct:marshal")
+                        .marshal(format)
+                        .to("mock:beanio-marshal");
+                // END SNIPPET: e1
+            }
+        };
+    }
+
+    private List<Employee> getEmployees() throws ParseException {
+        List<Employee> employees = new ArrayList<>();
+        Employee one = new Employee();
+        one.setFirstName("Joe");
+        one.setLastName("Smith");
+        one.setTitle("Developer");
+        one.setSalary(75000);
+        one.setHireDate(new SimpleDateFormat("MMddyyyy").parse("10012009"));
+        employees.add(one);
+
+        Employee two = new Employee();
+        two.setFirstName("Jane");
+        two.setLastName("Doe");
+        two.setTitle("Architect");
+        two.setSalary(80000);
+        two.setHireDate(new SimpleDateFormat("MMddyyyy").parse("01152008"));
+        employees.add(two);
+
+        Employee three = new Employee();
+        three.setFirstName("Jon");
+        three.setLastName("Anderson");
+        three.setTitle("Manager");
+        three.setSalary(85000);
+        three.setHireDate(new SimpleDateFormat("MMddyyyy").parse("03182007"));
+        employees.add(three);
+        return employees;
+    }
+
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIODataFormatSimpleTest.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIODataFormatSimpleTest.java
new file mode 100644
index 00000000000..52ca0f73ca0
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIODataFormatSimpleTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+public class BeanIODataFormatSimpleTest extends CamelTestSupport {
+
+    // START SNIPPET: e2
+    private static final String FIXED_DATA = "Joe,Smith,Developer,75000,10012009" + Constants.LS
+                                             + "Jane,Doe,Architect,80000,01152008" + Constants.LS
+                                             + "Jon,Anderson,Manager,85000,03182007" + Constants.LS;
+    // END SNIPPET: e2
+
+    @Test
+    void testMarshal() throws Exception {
+        List<Employee> employees = getEmployees();
+
+        MockEndpoint mock = getMockEndpoint("mock:beanio-marshal");
+        mock.expectedBodiesReceived(FIXED_DATA);
+
+        template.sendBody("direct:marshal", employees);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testUnmarshal() throws Exception {
+        List<Employee> employees = getEmployees();
+
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedBodiesReceived(employees);
+
+        template.sendBody("direct:unmarshal", FIXED_DATA);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                // START SNIPPET: e1
+                // setup beanio data format using the mapping file, loaded from the classpath
+                DataFormat format = new BeanIODataFormat(
+                        "org/apache/camel/dataformat/beanio/mappings.xml",
+                        "employeeFile");
+
+                // a route which uses the bean io data format to format a CSV data
+                // to java objects
+                from("direct:unmarshal")
+                        .unmarshal(format)
+                        // and then split the message body so we get a message for each row
+                        .split(body())
+                        .to("mock:beanio-unmarshal");
+
+                // convert list of java objects back to flat format
+                from("direct:marshal")
+                        .marshal(format)
+                        .to("mock:beanio-marshal");
+                // END SNIPPET: e1
+            }
+        };
+    }
+
+    private List<Employee> getEmployees() throws ParseException {
+        List<Employee> employees = new ArrayList<>();
+        Employee one = new Employee();
+        one.setFirstName("Joe");
+        one.setLastName("Smith");
+        one.setTitle("Developer");
+        one.setSalary(75000);
+        one.setHireDate(new SimpleDateFormat("MMddyyyy").parse("10012009"));
+        employees.add(one);
+
+        Employee two = new Employee();
+        two.setFirstName("Jane");
+        two.setLastName("Doe");
+        two.setTitle("Architect");
+        two.setSalary(80000);
+        two.setHireDate(new SimpleDateFormat("MMddyyyy").parse("01152008"));
+        employees.add(two);
+
+        Employee three = new Employee();
+        three.setFirstName("Jon");
+        three.setLastName("Anderson");
+        three.setTitle("Manager");
+        three.setSalary(85000);
+        three.setHireDate(new SimpleDateFormat("MMddyyyy").parse("03182007"));
+        employees.add(three);
+        return employees;
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOSplitterCustomBeanReaderErrorHandlerTest.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOSplitterCustomBeanReaderErrorHandlerTest.java
new file mode 100644
index 00000000000..00150fbb557
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOSplitterCustomBeanReaderErrorHandlerTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class BeanIOSplitterCustomBeanReaderErrorHandlerTest extends CamelTestSupport {
+
+    // START SNIPPET: e2
+    private static final String FIXED_DATA = "Joe,Smith,Developer,75000,10012009" + Constants.LS
+                                             + "Jane,Doe,Architect,80000,01152008" + Constants.LS
+                                             + "Jon,Anderson,Manager,85000,03182007" + Constants.LS;
+    // END SNIPPET: e2
+
+    private static final String FIXED_FAIL_DATA = "Joe,Smith,Developer,75000,10012009" + Constants.LS
+                                                  + "Jane,Doe,Architect,80000,01152008" + Constants.LS
+                                                  + "Jon,Anderson,Manager,XXX,03182007" + Constants.LS;
+
+    @Test
+    void testSplit() throws Exception {
+        List<Employee> employees = getEmployees();
+
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedBodiesReceived(employees);
+
+        template.sendBody("direct:unmarshal", FIXED_DATA);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testSplitFail() throws Exception {
+        // there should be 1 splitted that failed we get also
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedMessageCount(3);
+        mock.message(0).body().isInstanceOf(Employee.class);
+        mock.message(1).body().isInstanceOf(Employee.class);
+        mock.message(2).body().isInstanceOf(MyErrorDto.class);
+
+        template.sendBody("direct:unmarshal", FIXED_FAIL_DATA);
+
+        mock.assertIsSatisfied();
+
+        assertEquals("employee", mock.getReceivedExchanges().get(2).getIn().getBody(MyErrorDto.class).getRecord());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // START SNIPPET: e1
+                // setup beanio splitter using the mapping file, loaded from the classpath
+                BeanIOSplitter splitter = new BeanIOSplitter();
+                splitter.setMapping("org/apache/camel/dataformat/beanio/mappings.xml");
+                splitter.setStreamName("employeeFile");
+                splitter.setBeanReaderErrorHandlerType(MyErrorHandler.class);
+
+                // a route which uses the bean io data format to format a CSV data
+                // to java objects
+                from("direct:unmarshal")
+                        // and then split the message body so we get a message for each row
+                        .split(splitter).streaming()
+                        .to("log:line")
+                        .to("mock:beanio-unmarshal");
+                // END SNIPPET: e1
+            }
+        };
+    }
+
+    private List<Employee> getEmployees() throws ParseException {
+        List<Employee> employees = new ArrayList<>();
+        Employee one = new Employee();
+        one.setFirstName("Joe");
+        one.setLastName("Smith");
+        one.setTitle("Developer");
+        one.setSalary(75000);
+        one.setHireDate(new SimpleDateFormat("MMddyyyy").parse("10012009"));
+        employees.add(one);
+
+        Employee two = new Employee();
+        two.setFirstName("Jane");
+        two.setLastName("Doe");
+        two.setTitle("Architect");
+        two.setSalary(80000);
+        two.setHireDate(new SimpleDateFormat("MMddyyyy").parse("01152008"));
+        employees.add(two);
+
+        Employee three = new Employee();
+        three.setFirstName("Jon");
+        three.setLastName("Anderson");
+        three.setTitle("Manager");
+        three.setSalary(85000);
+        three.setHireDate(new SimpleDateFormat("MMddyyyy").parse("03182007"));
+        employees.add(three);
+        return employees;
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOSplitterTest.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOSplitterTest.java
new file mode 100644
index 00000000000..68d5a379a72
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOSplitterTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+public class BeanIOSplitterTest extends CamelTestSupport {
+
+    // START SNIPPET: e2
+    private static final String FIXED_DATA = "Joe,Smith,Developer,75000,10012009" + Constants.LS
+                                             + "Jane,Doe,Architect,80000,01152008" + Constants.LS
+                                             + "Jon,Anderson,Manager,85000,03182007" + Constants.LS;
+    // END SNIPPET: e2
+
+    @Test
+    void testSplit() throws Exception {
+        List<Employee> employees = getEmployees();
+
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedBodiesReceived(employees);
+
+        template.sendBody("direct:unmarshal", FIXED_DATA);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // START SNIPPET: e1
+                // setup beanio splitter using the mapping file, loaded from the classpath
+                BeanIOSplitter splitter = new BeanIOSplitter();
+                splitter.setMapping("org/apache/camel/dataformat/beanio/mappings.xml");
+                splitter.setStreamName("employeeFile");
+
+                // a route which uses the bean io data format to format a CSV data
+                // to java objects
+                from("direct:unmarshal")
+                        // and then split the message body so we get a message for each row
+                        .split(splitter).streaming()
+                        .to("log:line")
+                        .to("mock:beanio-unmarshal");
+                // END SNIPPET: e1
+            }
+        };
+    }
+
+    private List<Employee> getEmployees() throws ParseException {
+        List<Employee> employees = new ArrayList<>();
+        Employee one = new Employee();
+        one.setFirstName("Joe");
+        one.setLastName("Smith");
+        one.setTitle("Developer");
+        one.setSalary(75000);
+        one.setHireDate(new SimpleDateFormat("MMddyyyy").parse("10012009"));
+        employees.add(one);
+
+        Employee two = new Employee();
+        two.setFirstName("Jane");
+        two.setLastName("Doe");
+        two.setTitle("Architect");
+        two.setSalary(80000);
+        two.setHireDate(new SimpleDateFormat("MMddyyyy").parse("01152008"));
+        employees.add(two);
+
+        Employee three = new Employee();
+        three.setFirstName("Jon");
+        three.setLastName("Anderson");
+        three.setTitle("Manager");
+        three.setSalary(85000);
+        three.setHireDate(new SimpleDateFormat("MMddyyyy").parse("03182007"));
+        employees.add(three);
+        return employees;
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOUnmarshalSingleObjectTest.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOUnmarshalSingleObjectTest.java
new file mode 100644
index 00000000000..a61f7e74d47
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/BeanIOUnmarshalSingleObjectTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class BeanIOUnmarshalSingleObjectTest extends CamelTestSupport {
+
+    private static final String NEW_LINE = "\n";
+    private static final String INPUT
+            = "1234:Content starts from here" + NEW_LINE + "then continues" + NEW_LINE + "and ends here.";
+
+    @Test
+    void testMultiLineContentUnmarshal() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:unmarshal", INPUT);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                BeanIODataFormat format = new BeanIODataFormat(
+                        "org/apache/camel/dataformat/beanio/single-object-mapping.xml", "keyValueStream");
+                // turn on single mode
+                format.setUnmarshalSingleObject(true);
+
+                from("direct:unmarshal").unmarshal(format).process(new Processor() {
+                    public void process(Exchange exchange) throws Exception {
+                        Map body = (Map) exchange.getIn().getBody();
+                        assertEquals(":", body.get("separator"));
+                        assertEquals("1234", body.get("key"));
+                        assertEquals(INPUT.substring(5), body.get("value"));
+                    }
+                }).marshal(format).to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Constants.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Constants.java
new file mode 100644
index 00000000000..2382d36f868
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Constants.java
@@ -0,0 +1,26 @@
+/*
+ * 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.dataformat.beanio;
+
+public final class Constants {
+
+    public static final String LS = System.lineSeparator();
+
+    private Constants() {
+    }
+
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Employee.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Employee.java
new file mode 100644
index 00000000000..312d2445f37
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Employee.java
@@ -0,0 +1,111 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.util.Date;
+
+public class Employee {
+
+    private String firstName;
+    private String lastName;
+    private String title;
+    private int salary;
+    private Date hireDate;
+
+    public Employee() {
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public int getSalary() {
+        return salary;
+    }
+
+    public void setSalary(int salary) {
+        this.salary = salary;
+    }
+
+    public Date getHireDate() {
+        return hireDate;
+    }
+
+    public void setHireDate(Date hireDate) {
+        this.hireDate = hireDate;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = firstName != null ? firstName.hashCode() : 0;
+        result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
+        result = 31 * result + (title != null ? title.hashCode() : 0);
+        result = 31 * result + salary;
+        result = 31 * result + (hireDate != null ? hireDate.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (object == null) {
+            return false;
+        } else if (object == this) {
+            return true;
+        } else if (!(object instanceof Employee)) {
+            return false;
+        }
+
+        Employee e = (Employee) object;
+
+        return this.getFirstName().equals(e.getFirstName())
+                && this.getLastName().equals(e.getLastName())
+                && this.getTitle().equals(e.getTitle())
+                && this.getSalary() == e.getSalary()
+                && this.getHireDate().equals(e.getHireDate());
+    }
+
+    @Override
+    public String toString() {
+        return "Employee{"
+               + "firstName='" + firstName + '\''
+               + ", lastName='" + lastName + '\''
+               + ", title='" + title + '\''
+               + ", salary=" + salary
+               + ", hireDate=" + hireDate
+               + '}';
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Header.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Header.java
new file mode 100644
index 00000000000..38bfd2d3793
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Header.java
@@ -0,0 +1,111 @@
+/*
+ * 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.dataformat.beanio;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Header implements BeanIOHeader {
+
+    String identifier;
+    String recordType;
+    Date headerDate;
+
+    public Header() {
+    }
+
+    public Header(String identifier, Date headerDate, String recordType) {
+        this.identifier = identifier;
+        this.headerDate = headerDate;
+        this.recordType = recordType;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = identifier != null ? identifier.hashCode() : 0;
+        result = 31 * result + (recordType != null ? recordType.hashCode() : 0);
+        result = 31 * result + (headerDate != null ? headerDate.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        } else if (obj == this) {
+            return true;
+        } else {
+            Header record = (Header) obj;
+            return identifier.equals(record.getIdentifier()) && recordType.equals(record.getRecordType());
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "TYPE[" + this.recordType + "], IDENTIFIER[" + this.identifier + "]";
+    }
+
+    /**
+     * @return the identifier
+     */
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    /**
+     * @param identifier the identifier to set
+     */
+    public void setIdentifier(String identifier) {
+        this.identifier = identifier;
+    }
+
+    /**
+     * @return the headerDate
+     */
+    public Date getHeaderDate() {
+        return headerDate;
+    }
+
+    /**
+     * @param headerDate the headerDate to set
+     */
+    public void setHeaderDate(Date headerDate) {
+        this.headerDate = headerDate;
+    }
+
+    /**
+     * @return the recordType
+     */
+    public String getRecordType() {
+        return recordType;
+    }
+
+    /**
+     * @param recordType the recordType to set
+     */
+    public void setRecordType(String recordType) {
+        this.recordType = recordType;
+    }
+
+    @Override
+    public Map<String, Object> getHeaders() {
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(recordType + "Date", headerDate);
+        return headers;
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/MyErrorDto.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/MyErrorDto.java
new file mode 100644
index 00000000000..e4ae0e71c4a
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/MyErrorDto.java
@@ -0,0 +1,36 @@
+/*
+ * 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.dataformat.beanio;
+
+public class MyErrorDto {
+
+    private String record;
+    private String message;
+
+    public MyErrorDto(String record, String message) {
+        this.record = record;
+        this.message = message;
+    }
+
+    public String getRecord() {
+        return record;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/MyErrorHandler.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/MyErrorHandler.java
new file mode 100644
index 00000000000..a3b0503b0c9
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/MyErrorHandler.java
@@ -0,0 +1,38 @@
+/*
+ * 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.dataformat.beanio;
+
+import org.beanio.InvalidRecordException;
+
+public class MyErrorHandler extends BeanIOErrorHandler {
+
+    public MyErrorHandler() {
+    }
+
+    @Override
+    public void invalidRecord(InvalidRecordException ex) throws Exception {
+        String id = getExchange().getExchangeId();
+        String line
+                = "ExchangeId: " + id + " Invalid record: " + ex.getMessage() + ": " + ex.getRecordContext().getRecordText();
+        LOG.warn(line);
+
+        // lets handle the error and store to the results a dummy error DTO
+        MyErrorDto dto = new MyErrorDto(ex.getRecordName(), ex.getMessage());
+        handleErrorAndAddAsResult(dto);
+    }
+
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Record.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Record.java
new file mode 100644
index 00000000000..95e0d8c6d5b
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Record.java
@@ -0,0 +1,65 @@
+/*
+ * 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.dataformat.beanio;
+
+public abstract class Record {
+    String sedol;
+    String source;
+
+    public Record() {
+    }
+
+    public Record(String sedol, String source) {
+        this.sedol = sedol;
+        this.source = source;
+    }
+
+    public String getSedol() {
+        return sedol;
+    }
+
+    public void setSedol(String sedol) {
+        this.sedol = sedol;
+    }
+
+    public String getSource() {
+        return source;
+    }
+
+    public void setSource(String source) {
+        this.source = source;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = sedol != null ? sedol.hashCode() : 0;
+        result = 31 * result + (source != null ? source.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        } else if (obj == this) {
+            return true;
+        } else {
+            Record record = (Record) obj;
+            return sedol.equals(record.getSedol()) && source.equals(record.getSource());
+        }
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Separator.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Separator.java
new file mode 100644
index 00000000000..b871adca8ca
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Separator.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dataformat.beanio;
+
+public class Separator {
+    String value;
+
+    public Separator() {
+    }
+
+    public Separator(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public int hashCode() {
+        return value != null ? value.hashCode() : 0;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        } else if (obj == this) {
+            return true;
+        } else {
+            Separator record = (Separator) obj;
+            return this.value.equals(record.getValue());
+        }
+    }
+
+    /**
+     * @return the value
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * @param value the value to set
+     */
+    public void setValue(String value) {
+        this.value = value;
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/SpringBeanIODataFormatSimpleTest.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/SpringBeanIODataFormatSimpleTest.java
new file mode 100644
index 00000000000..ac3c9d7594c
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/SpringBeanIODataFormatSimpleTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dataformat.beanio;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class SpringBeanIODataFormatSimpleTest extends CamelSpringTestSupport {
+
+    private static final String FIXED_DATA = "Joe,Smith,Developer,75000,10012009" + Constants.LS
+                                             + "Jane,Doe,Architect,80000,01152008" + Constants.LS
+                                             + "Jon,Anderson,Manager,85000,03182007" + Constants.LS;
+
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/dataformat/beanio/SpringBeanIODataFormatSimpleTest.xml");
+    }
+
+    @Test
+    void testMarshal() throws Exception {
+        List<Employee> employees = getEmployees();
+
+        MockEndpoint mock = getMockEndpoint("mock:beanio-marshal");
+        mock.expectedBodiesReceived(FIXED_DATA);
+
+        template.sendBody("direct:marshal", employees);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    void testUnmarshal() throws Exception {
+        List<Employee> employees = getEmployees();
+
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedBodiesReceived(employees);
+
+        template.sendBody("direct:unmarshal", FIXED_DATA);
+
+        mock.assertIsSatisfied();
+    }
+
+    private List<Employee> getEmployees() throws ParseException {
+        List<Employee> employees = new ArrayList<>();
+        Employee one = new Employee();
+        one.setFirstName("Joe");
+        one.setLastName("Smith");
+        one.setTitle("Developer");
+        one.setSalary(75000);
+        one.setHireDate(new SimpleDateFormat("MMddyyyy").parse("10012009"));
+        employees.add(one);
+
+        Employee two = new Employee();
+        two.setFirstName("Jane");
+        two.setLastName("Doe");
+        two.setTitle("Architect");
+        two.setSalary(80000);
+        two.setHireDate(new SimpleDateFormat("MMddyyyy").parse("01152008"));
+        employees.add(two);
+
+        Employee three = new Employee();
+        three.setFirstName("Jon");
+        three.setLastName("Anderson");
+        three.setTitle("Manager");
+        three.setSalary(85000);
+        three.setHireDate(new SimpleDateFormat("MMddyyyy").parse("03182007"));
+        employees.add(three);
+        return employees;
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Trailer.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Trailer.java
new file mode 100644
index 00000000000..aaf87681a88
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/Trailer.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dataformat.beanio;
+
+public class Trailer {
+    int numberOfRecords;
+
+    public Trailer() {
+    }
+
+    public Trailer(int numberOfRecords) {
+        this.numberOfRecords = numberOfRecords;
+    }
+
+    @Override
+    public int hashCode() {
+        return numberOfRecords;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        } else if (obj == this) {
+            return true;
+        } else {
+            Trailer record = (Trailer) obj;
+            return this.numberOfRecords == record.getNumberOfRecords();
+        }
+    }
+
+    /**
+     * @return the numberOfRecords
+     */
+    public int getNumberOfRecords() {
+        return numberOfRecords;
+    }
+
+    /**
+     * @param numberOfRecords the numberOfRecords to set
+     */
+    public void setNumberOfRecords(int numberOfRecords) {
+        this.numberOfRecords = numberOfRecords;
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/csv/CsvTest.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/csv/CsvTest.java
new file mode 100644
index 00000000000..b11818f10fb
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/csv/CsvTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.dataformat.beanio.csv;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.dataformat.beanio.BeanIODataFormat;
+import org.apache.camel.dataformat.beanio.Constants;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class CsvTest extends CamelTestSupport {
+
+    static final Logger LOG = LoggerFactory.getLogger(CsvTest.class);
+
+    private static final String FIXED_DATA = "James,Strachan,22" + Constants.LS + "Claus,Ibsen,21" + Constants.LS;
+
+    private boolean verbose;
+
+    /*
+    @Test
+    void testMarshal() throws Exception {
+        List<Employee> employees = getEmployees();
+
+        MockEndpoint mock = getMockEndpoint("mock:beanio-marshal");
+        mock.expectedBodiesReceived(FIXED_DATA);
+
+        template.sendBody("direct:marshal", employees);
+
+        mock.assertIsSatisfied();
+    }
+    */
+
+    @Test
+    void testUnmarshal() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:beanio-unmarshal");
+        mock.expectedMessageCount(2);
+
+        template.sendBody("direct:unmarshal", FIXED_DATA);
+
+        mock.assertIsSatisfied();
+
+        List<Exchange> exchanges = mock.getExchanges();
+        if (verbose) {
+            for (Exchange exchange : exchanges) {
+                Object body = exchange.getIn().getBody();
+                LOG.info("received message {} of class {}", body, body.getClass().getName());
+            }
+        }
+        List<Map> results = new ArrayList<>();
+        for (Exchange exchange : exchanges) {
+            Map body = exchange.getIn().getBody(Map.class);
+            if (body != null) {
+                results.add(body);
+            }
+        }
+        assertRecord(results, 0, "James", "Strachan", 22);
+        assertRecord(results, 1, "Claus", "Ibsen", 21);
+    }
+
+    protected static void assertRecord(
+            List<Map> results, int index, String expectedFirstName, String expectedLastName, int expectedAge) {
+        assertTrue(results.size() > index, "Not enough Map messages received: " + results.size());
+        Map map = results.get(index);
+        assertNotNull(map, "No map result found for index " + index);
+
+        String text = "bodyAsMap(" + index + ") ";
+        assertEquals(expectedFirstName, map.get("firstName"), text + "firstName");
+        assertEquals(expectedLastName, map.get("lastName"), text + "lastName");
+        assertEquals(expectedAge, map.get("age"), text + "age");
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                // START SNIPPET: e1
+                // setup beanio data format using the mapping file, loaded from the classpath
+                DataFormat format = new BeanIODataFormat(
+                        "org/apache/camel/dataformat/beanio/csv/mappings.xml",
+                        "stream1");
+
+                // a route which uses the bean io data format to format a CSV data
+                // to java objects
+                from("direct:unmarshal")
+                        .unmarshal(format)
+                        // and then split the message body so we get a message for each row
+                        .split(body())
+                        .to("mock:beanio-unmarshal");
+
+                // convert list of java objects back to flat format
+                from("direct:marshal")
+                        .marshal(format)
+                        .to("mock:beanio-marshal");
+                // END SNIPPET: e1
+            }
+        };
+    }
+}
diff --git a/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/csv/CsvTestWithProperties.java b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/csv/CsvTestWithProperties.java
new file mode 100644
index 00000000000..9e846df1c9e
--- /dev/null
+++ b/components/camel-beanio/src/test/java/org/apache/camel/dataformat/beanio/csv/CsvTestWithProperties.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dataformat.beanio.csv;
+
+import java.util.Properties;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.dataformat.beanio.BeanIODataFormat;
+
+public class CsvTestWithProperties extends CsvTest {
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                // START SNIPPET: e1
+                // setup beanio data format using the mapping file, loaded from the classpath
+                BeanIODataFormat format = new BeanIODataFormat(
+                        "org/apache/camel/dataformat/beanio/csv/mappingsWithProperties.xml",
+                        "stream1");
+                Properties properties = new Properties();
+                properties.setProperty("field1", "firstName");
+                properties.setProperty("field2", "lastName");
+
+                format.setProperties(properties);
+
+                // a route which uses the bean io data format to format a CSV data
+                // to java objects
+                from("direct:unmarshal")
+                        .unmarshal(format)
+                        // and then split the message body so we get a message for each row
+                        .split(body())
+                        .to("mock:beanio-unmarshal");
+
+                // convert list of java objects back to flat format
+                from("direct:marshal")
+                        .marshal(format)
+                        .to("mock:beanio-marshal");
+                // END SNIPPET: e1
+            }
+        };
+    }
+
+}
diff --git a/components/camel-beanio/src/test/resources/log4j2.properties b/components/camel-beanio/src/test/resources/log4j2.properties
new file mode 100644
index 00000000000..d2d50a49255
--- /dev/null
+++ b/components/camel-beanio/src/test/resources/log4j2.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+appender.console.type = Console
+appender.console.name = console
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %d %-5p %c{1} - %m %n
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-beanio-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d %-5p %c{1} - %m %n
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git a/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/SpringBeanIODataFormatSimpleTest.xml b/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/SpringBeanIODataFormatSimpleTest.xml
new file mode 100644
index 00000000000..0195688927b
--- /dev/null
+++ b/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/SpringBeanIODataFormatSimpleTest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+     http://www.springframework.org/schema/beans
+     http://www.springframework.org/schema/beans/spring-beans.xsd
+     http://camel.apache.org/schema/spring
+     http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+    <!-- START SNIPPET: e1 -->
+    <camelContext xmlns="http://camel.apache.org/schema/spring">
+        <route>
+            <from uri="direct:unmarshal"/>
+            <unmarshal>
+                <beanio mapping="org/apache/camel/dataformat/beanio/mappings.xml" streamName="employeeFile"/>
+            </unmarshal>
+            <split>
+                <simple>${body}</simple>
+                <to uri="mock:beanio-unmarshal"/>
+            </split>
+        </route>
+
+        <route>
+            <from uri="direct:marshal"/>
+            <marshal>
+                <beanio mapping="org/apache/camel/dataformat/beanio/mappings.xml" streamName="employeeFile"/>
+            </marshal>
+            <to uri="mock:beanio-marshal"/>
+        </route>
+    </camelContext>
+    <!-- END SNIPPET: e1 -->
+
+</beans>
diff --git a/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/csv/mappings.xml b/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/csv/mappings.xml
new file mode 100644
index 00000000000..4cf9b2f60ba
--- /dev/null
+++ b/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/csv/mappings.xml
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<beanio xmlns="http://www.beanio.org/2012/03"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.beanio.org/2011/01 http://www.beanio.org/2011/01/mapping.xsd">
+
+  <stream name="stream1" format="csv">
+    <!-- TODO warning - if class is ommitted then this test case just does nothing; no messages consumed and no warnings! :) -->
+    <record name="record1" class="map">
+       <field name="firstName" />
+       <field name="lastName" />
+       <field name="age" type="int"/>
+     </record>
+  </stream>
+</beanio>
\ No newline at end of file
diff --git a/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/csv/mappingsWithProperties.xml b/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/csv/mappingsWithProperties.xml
new file mode 100644
index 00000000000..456d9457a16
--- /dev/null
+++ b/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/csv/mappingsWithProperties.xml
@@ -0,0 +1,32 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<beanio xmlns="http://www.beanio.org/2012/03"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.beanio.org/2011/01 http://www.beanio.org/2011/01/mapping.xsd">
+
+  <stream name="stream1" format="csv">
+    <!-- TODO warning - if class is ommitted then this test case just does nothing; no messages consumed and no warnings! :) -->
+    <record name="record1" class="map">
+       <field name="${field1}" />
+       <field name="${field2}" />
+       <field name="age" type="int"/>
+     </record>
+  </stream>
+</beanio>
\ No newline at end of file
diff --git a/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/mappings.xml b/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/mappings.xml
new file mode 100644
index 00000000000..dc994f9183e
--- /dev/null
+++ b/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/mappings.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<beanio xmlns="http://www.beanio.org/2012/03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">
+
+  <template name="A1Record">
+    <field name="sedol" type="string" length="7"/>
+    <field name="identifier" rid="true" literal="A1" ignore="true"/>
+    <field name="currentPrice" type="double" length="12" format="0.000000####"/>
+    <field name="padding" type="string" length="11" ignore="true"/>
+    <property name="source" value="camel-beanio"/>
+  </template>
+
+  <template name="B1Record">
+    <field name="sedol" type="string" length="7"/>
+    <field name="identifier" rid="true" literal="B1" ignore="true"/>
+    <field name="securityName" type="string" length="12"/>
+    <field name="padding" type="string" length="11" ignore="true"/>
+    <property name="source" value="camel-beanio"/>
+  </template>
+
+  <stream name="employeeFile" format="csv">
+    <record name="employee" class="org.apache.camel.dataformat.beanio.Employee">
+      <field name="firstName"/>
+      <field name="lastName"/>
+      <field name="title"/>
+      <field name="salary"/>
+      <field name="hireDate" format="MMddyyyy"/>
+    </record>
+  </stream>
+
+  <stream name="securityData" format="fixedlength" strict="true">
+
+    <group name="headerGroup" minOccurs="1" maxOccurs="1" order="1">
+
+      <record name="headerA1" class="org.apache.camel.dataformat.beanio.Header" order="1" minLength="32" maxLength="32"
+              minOccurs="1" maxOccurs="1">
+        <field name="zeros" type="string" length="7" literal="0000000" ignore="true"/>
+        <field name="identifier" type="string" length="2" rid="true" literal="A1"/>
+        <field name="headerDate" type="date" length="6" format="ddMMyy"/>
+        <field name="recordType" type="string" length="17"/>
+      </record>
+
+      <record name="headerB1" class="org.apache.camel.dataformat.beanio.Header" order="2" minLength="32" maxLength="32"
+              minOccurs="1" maxOccurs="1">
+        <field name="zeros" type="string" length="7" literal="0000000" ignore="true"/>
+        <field name="identifier" type="string" length="2" rid="true" literal="B1"/>
+        <field name="headerDate" type="date" length="6" format="ddMMyy"/>
+        <field name="recordType" type="string" length="17"/>
+      </record>
+
+      <!-- Ignore the HEADER END by not setting a class -->
+      <record name="headerEnd" class="org.apache.camel.dataformat.beanio.Separator" order="3" minLength="32"
+              maxLength="32" minOccurs="1" maxOccurs="1">
+        <field name="value" rid="true" literal="HEADER END" default="HEADER END" required="true"/>
+        <field name="padding" length="22" ignore="true"/>
+      </record>
+
+    </group>
+
+    <group name="section1" minOccurs="1" maxOccurs="1" order="2">
+
+      <record name="A1" template="A1Record"
+              class="org.apache.camel.dataformat.beanio.A1Record" minOccurs="0"
+              maxOccurs="unbounded" minLength="32" maxLength="32"/>
+      <record name="B1" template="B1Record"
+              class="org.apache.camel.dataformat.beanio.B1Record" minOccurs="0"
+              maxOccurs="unbounded" minLength="32" maxLength="32"/>
+
+      <record name="endOfUk" class="org.apache.camel.dataformat.beanio.Separator" minOccurs="1" maxOccurs="1"
+              minLength="32" maxLength="32">
+        <field name="value" rid="true" literal="END OF SECTION 1"/>
+        <field name="padding" length="16" ignore="true"/>
+      </record>
+
+    </group>
+
+    <group name="section2" minOccurs="1" maxOccurs="1" order="3">
+
+      <record name="A1" template="A1Record"
+              class="org.apache.camel.dataformat.beanio.A1Record" minOccurs="0"
+              maxOccurs="unbounded" minLength="32" maxLength="32"/>
+      <record name="B1" template="B1Record"
+              class="org.apache.camel.dataformat.beanio.B1Record" minOccurs="0"
+              maxOccurs="unbounded" minLength="32" maxLength="32"/>
+
+      <record name="endOfFile" class="org.apache.camel.dataformat.beanio.Trailer" minOccurs="1" maxOccurs="1"
+              minLength="32" maxLength="32">
+        <field name="endOfFile" rid="true" literal="END OF FILE" ignore="true"/>
+        <field name="spacer" literal=" " length="1" ignore="true"/>
+        <field name="numberOfRecords" type="integer" length="6" format="000000"/>
+        <field name="padding" length="14" ignore="true"/>
+      </record>
+
+    </group>
+
+  </stream>
+
+</beanio>
diff --git a/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/single-object-mapping.xml b/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/single-object-mapping.xml
new file mode 100644
index 00000000000..8434cb8c853
--- /dev/null
+++ b/components/camel-beanio/src/test/resources/org/apache/camel/dataformat/beanio/single-object-mapping.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<beanio xmlns="http://www.beanio.org/2012/03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">
+  <stream name="keyValueStream" format="fixedlength">
+    <record name="entry" class="map" minOccurs="1">
+      <field name="key" length="4" required="true" justify="left" />
+      <field name="separator" length="1" required="true" justify="left" />
+      <field name="value" required="true" length="unbounded" justify="left" />
+    </record>
+  </stream>
+</beanio>
\ No newline at end of file
diff --git a/components/pom.xml b/components/pom.xml
index 3ebceed5928..4f69b44b936 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -89,6 +89,7 @@
         <module>camel-barcode</module>
         <module>camel-base64</module>
         <module>camel-bean-validator</module>
+        <module>camel-beanio</module>
         <module>camel-bindy</module>
         <module>camel-bonita</module>
         <module>camel-box</module>
diff --git a/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
index f1bb551c573..92d387ce540 100644
--- a/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
+++ b/core/camel-core-model/src/generated/resources/META-INF/services/org/apache/camel/model.properties
@@ -8,6 +8,7 @@ base64
 basicAuth
 batchConfig
 bean
+beanio
 bearerToken
 bindy
 blacklistServiceFilter
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/dataformat/beanio.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/dataformat/beanio.json
new file mode 100644
index 00000000000..479fc19bd14
--- /dev/null
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/dataformat/beanio.json
@@ -0,0 +1,26 @@
+{
+  "model": {
+    "kind": "model",
+    "name": "beanio",
+    "title": "BeanIO",
+    "description": "Marshal and unmarshal Java beans to and from flat files (such as CSV, delimited, or fixed length formats).",
+    "deprecated": false,
+    "firstVersion": "2.10.0",
+    "label": "dataformat,transformation,csv",
+    "javaType": "org.apache.camel.model.dataformat.BeanioDataFormat",
+    "abstract": false,
+    "input": false,
+    "output": false
+  },
+  "properties": {
+    "id": { "index": 0, "kind": "attribute", "displayName": "Id", "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", "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." },
+    "streamName": { "index": 2, "kind": "attribute", "displayName": "Stream Name", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The name of the stream to use." },
+    "ignoreUnidentifiedRecords": { "index": 3, "kind": "attribute", "displayName": "Ignore Unidentified Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore unidentified records." },
+    "ignoreUnexpectedRecords": { "index": 4, "kind": "attribute", "displayName": "Ignore Unexpected Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore unexpected records." },
+    "ignoreInvalidRecords": { "index": 5, "kind": "attribute", "displayName": "Ignore Invalid Records", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to ignore invalid records." },
+    "encoding": { "index": 6, "kind": "attribute", "displayName": "Encoding", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The charset to use. Is by default the JVM platform default charset." },
+    "beanReaderErrorHandlerType": { "index": 7, "kind": "attribute", "displayName": "Bean Reader Error Handler Type", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.dataformat.beanio.BeanIOErrorHandler as error handler while parsing. Configure the fully qualified class name of the error handler. Notice the options ignoreUnidentifiedRecords, [...]
+    "unmarshalSingleObject": { "index": 8, "kind": "attribute", "displayName": "Unmarshal Single Object", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "This options controls whether to unmarshal as a list of objects or as a single object only. The former is the default mode, and the latter is only intended in special use-cases where beanio maps th [...]
+  }
+}
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/dataformat/dataFormats.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/dataformat/dataFormats.json
index b2b8fb14fa8..e811a1de6a3 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/dataformat/dataFormats.json
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/dataformat/dataFormats.json
@@ -12,6 +12,6 @@
     "output": false
   },
   "properties": {
-    "dataFormats": { "index": 0, "kind": "element", "displayName": "Data Formats", "required": true, "type": "array", "javaType": "java.util.List<org.apache.camel.model.DataFormatDefinition>", "oneOf": [ "asn1", "avro", "barcode", "base64", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt", "swiftMx [...]
+    "dataFormats": { "index": 0, "kind": "element", "displayName": "Data Formats", "required": true, "type": "array", "javaType": "java.util.List<org.apache.camel.model.DataFormatDefinition>", "oneOf": [ "asn1", "avro", "barcode", "base64", "beanio", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt" [...]
   }
 }
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/dataformat/jaxb.index b/core/camel-core-model/src/generated/resources/org/apache/camel/model/dataformat/jaxb.index
index 7b62528f186..e2e8c68bb92 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/dataformat/jaxb.index
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/dataformat/jaxb.index
@@ -4,6 +4,7 @@ AvroDataFormat
 AvroLibrary
 BarcodeDataFormat
 Base64DataFormat
+BeanioDataFormat
 BindyDataFormat
 BindyType
 CBORDataFormat
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/marshal.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/marshal.json
index 3f33b46e27e..55d4543bdd3 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/marshal.json
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/marshal.json
@@ -15,7 +15,7 @@
     "id": { "index": 0, "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
     "description": { "index": 1, "kind": "element", "displayName": "Description", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" },
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime." },
-    "dataFormatType": { "index": 3, "kind": "element", "displayName": "Data Format Type", "required": true, "type": "object", "javaType": "org.apache.camel.model.DataFormatDefinition", "oneOf": [ "asn1", "avro", "barcode", "base64", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt", "swiftMx", "sysl [...]
+    "dataFormatType": { "index": 3, "kind": "element", "displayName": "Data Format Type", "required": true, "type": "object", "javaType": "org.apache.camel.model.DataFormatDefinition", "oneOf": [ "asn1", "avro", "barcode", "base64", "beanio", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt", "swift [...]
     "variableSend": { "index": 4, "kind": "attribute", "displayName": "Variable Send", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not on the  [...]
     "variableReceive": { "index": 5, "kind": "attribute", "displayName": "Variable Receive", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not o [...]
   }
diff --git a/core/camel-core-model/src/generated/resources/org/apache/camel/model/unmarshal.json b/core/camel-core-model/src/generated/resources/org/apache/camel/model/unmarshal.json
index 202b7a8f74b..9865b2de86e 100644
--- a/core/camel-core-model/src/generated/resources/org/apache/camel/model/unmarshal.json
+++ b/core/camel-core-model/src/generated/resources/org/apache/camel/model/unmarshal.json
@@ -15,7 +15,7 @@
     "id": { "index": 0, "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the id of this node" },
     "description": { "index": 1, "kind": "element", "displayName": "Description", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the description of this node" },
     "disabled": { "index": 2, "kind": "attribute", "displayName": "Disabled", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to disable this EIP from the route during build time. Once an EIP has been disabled then it cannot be enabled later at runtime." },
-    "dataFormatType": { "index": 3, "kind": "element", "displayName": "Data Format Type", "required": true, "type": "object", "javaType": "org.apache.camel.model.DataFormatDefinition", "oneOf": [ "asn1", "avro", "barcode", "base64", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt", "swiftMx", "sysl [...]
+    "dataFormatType": { "index": 3, "kind": "element", "displayName": "Data Format Type", "required": true, "type": "object", "javaType": "org.apache.camel.model.DataFormatDefinition", "oneOf": [ "asn1", "avro", "barcode", "base64", "beanio", "bindy", "cbor", "crypto", "csv", "custom", "fhirJson", "fhirXml", "flatpack", "grok", "gzipDeflater", "hl7", "ical", "jacksonXml", "jaxb", "json", "jsonApi", "lzf", "mimeMultipart", "parquetAvro", "pgp", "protobuf", "rss", "soap", "swiftMt", "swift [...]
     "variableSend": { "index": 4, "kind": "attribute", "displayName": "Variable Send", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not on the  [...]
     "variableReceive": { "index": 5, "kind": "attribute", "displayName": "Variable Receive", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To use a variable to store the received message body (only body, not headers). This is handy for easy access to the received message body via variables. Important: When using receive variable then the received body is stored only in this variable and not o [...]
     "allowNullBody": { "index": 6, "kind": "attribute", "displayName": "Allow Null Body", "label": "advanced", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Indicates whether null is allowed as value of a body to unmarshall." }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/DataFormatBuilderFactory.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/DataFormatBuilderFactory.java
index 8c1072e35b3..5e812f095d9 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/DataFormatBuilderFactory.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/DataFormatBuilderFactory.java
@@ -20,6 +20,7 @@ import org.apache.camel.model.dataformat.ASN1DataFormat;
 import org.apache.camel.model.dataformat.AvroDataFormat;
 import org.apache.camel.model.dataformat.BarcodeDataFormat;
 import org.apache.camel.model.dataformat.Base64DataFormat;
+import org.apache.camel.model.dataformat.BeanioDataFormat;
 import org.apache.camel.model.dataformat.BindyDataFormat;
 import org.apache.camel.model.dataformat.CBORDataFormat;
 import org.apache.camel.model.dataformat.CryptoDataFormat;
@@ -90,6 +91,13 @@ public final class DataFormatBuilderFactory {
         return new Base64DataFormat.Builder();
     }
 
+    /**
+     * Uses the BeanIO data format
+     */
+    public BeanioDataFormat.Builder beanio() {
+        return new BeanioDataFormat.Builder();
+    }
+
     /**
      * Uses the Bindy data format
      */
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/builder/DataFormatClause.java b/core/camel-core-model/src/main/java/org/apache/camel/builder/DataFormatClause.java
index 73c6d1eb97a..63f314a77b9 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/builder/DataFormatClause.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/builder/DataFormatClause.java
@@ -28,6 +28,7 @@ import org.apache.camel.model.dataformat.ASN1DataFormat;
 import org.apache.camel.model.dataformat.AvroDataFormat;
 import org.apache.camel.model.dataformat.AvroLibrary;
 import org.apache.camel.model.dataformat.Base64DataFormat;
+import org.apache.camel.model.dataformat.BeanioDataFormat;
 import org.apache.camel.model.dataformat.BindyDataFormat;
 import org.apache.camel.model.dataformat.BindyType;
 import org.apache.camel.model.dataformat.CBORDataFormat;
@@ -161,6 +162,54 @@ public class DataFormatClause<T extends ProcessorDefinition<?>> {
         return dataFormat(dataFormat);
     }
 
+    /**
+     * Uses the beanio data format
+     */
+    public T beanio(String mapping, String streamName) {
+        BeanioDataFormat dataFormat = new BeanioDataFormat();
+        dataFormat.setMapping(mapping);
+        dataFormat.setStreamName(streamName);
+        return dataFormat(dataFormat);
+    }
+
+    /**
+     * Uses the beanio data format
+     */
+    public T beanio(String mapping, String streamName, String encoding) {
+        BeanioDataFormat dataFormat = new BeanioDataFormat();
+        dataFormat.setMapping(mapping);
+        dataFormat.setStreamName(streamName);
+        dataFormat.setEncoding(encoding);
+        return dataFormat(dataFormat);
+    }
+
+    /**
+     * Uses the beanio data format
+     */
+    public T beanio(String mapping, String streamName, String encoding, boolean ignoreUnidentifiedRecords,
+                    boolean ignoreUnexpectedRecords, boolean ignoreInvalidRecords) {
+        BeanioDataFormat dataFormat = new BeanioDataFormat();
+        dataFormat.setMapping(mapping);
+        dataFormat.setStreamName(streamName);
+        dataFormat.setEncoding(encoding);
+        dataFormat.setIgnoreUnidentifiedRecords(Boolean.toString(ignoreUnidentifiedRecords));
+        dataFormat.setIgnoreUnexpectedRecords(Boolean.toString(ignoreUnexpectedRecords));
+        dataFormat.setIgnoreInvalidRecords(Boolean.toString(ignoreInvalidRecords));
+        return dataFormat(dataFormat);
+    }
+
+    /**
+     * Uses the beanio data format
+     */
+    public T beanio(String mapping, String streamName, String encoding, String beanReaderErrorHandlerType) {
+        BeanioDataFormat dataFormat = new BeanioDataFormat();
+        dataFormat.setMapping(mapping);
+        dataFormat.setStreamName(streamName);
+        dataFormat.setEncoding(encoding);
+        dataFormat.setBeanReaderErrorHandlerType(beanReaderErrorHandlerType);
+        return dataFormat(dataFormat);
+    }
+
     /**
      * Uses the Bindy data format
      *
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/MarshalDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/MarshalDefinition.java
index 75bc403dd83..365dbeeb91d 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/MarshalDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/MarshalDefinition.java
@@ -27,6 +27,7 @@ import org.apache.camel.model.dataformat.ASN1DataFormat;
 import org.apache.camel.model.dataformat.AvroDataFormat;
 import org.apache.camel.model.dataformat.BarcodeDataFormat;
 import org.apache.camel.model.dataformat.Base64DataFormat;
+import org.apache.camel.model.dataformat.BeanioDataFormat;
 import org.apache.camel.model.dataformat.BindyDataFormat;
 import org.apache.camel.model.dataformat.CBORDataFormat;
 import org.apache.camel.model.dataformat.CryptoDataFormat;
@@ -78,6 +79,7 @@ public class MarshalDefinition extends NoOutputDefinition<MarshalDefinition> imp
             @XmlElement(name = "avro", type = AvroDataFormat.class),
             @XmlElement(name = "barcode", type = BarcodeDataFormat.class),
             @XmlElement(name = "base64", type = Base64DataFormat.class),
+            @XmlElement(name = "beanio", type = BeanioDataFormat.class),
             @XmlElement(name = "bindy", type = BindyDataFormat.class),
             @XmlElement(name = "cbor", type = CBORDataFormat.class),
             @XmlElement(name = "crypto", type = CryptoDataFormat.class),
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/UnmarshalDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/UnmarshalDefinition.java
index cb603a8d004..791fde88289 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/UnmarshalDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/UnmarshalDefinition.java
@@ -27,6 +27,7 @@ import org.apache.camel.model.dataformat.ASN1DataFormat;
 import org.apache.camel.model.dataformat.AvroDataFormat;
 import org.apache.camel.model.dataformat.BarcodeDataFormat;
 import org.apache.camel.model.dataformat.Base64DataFormat;
+import org.apache.camel.model.dataformat.BeanioDataFormat;
 import org.apache.camel.model.dataformat.BindyDataFormat;
 import org.apache.camel.model.dataformat.CBORDataFormat;
 import org.apache.camel.model.dataformat.CryptoDataFormat;
@@ -78,6 +79,7 @@ public class UnmarshalDefinition extends NoOutputDefinition<UnmarshalDefinition>
             @XmlElement(name = "avro", type = AvroDataFormat.class),
             @XmlElement(name = "barcode", type = BarcodeDataFormat.class),
             @XmlElement(name = "base64", type = Base64DataFormat.class),
+            @XmlElement(name = "beanio", type = BeanioDataFormat.class),
             @XmlElement(name = "bindy", type = BindyDataFormat.class),
             @XmlElement(name = "cbor", type = CBORDataFormat.class),
             @XmlElement(name = "crypto", type = CryptoDataFormat.class),
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/BeanioDataFormat.java b/core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/BeanioDataFormat.java
new file mode 100644
index 00000000000..744b647454b
--- /dev/null
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/BeanioDataFormat.java
@@ -0,0 +1,296 @@
+/*
+ * 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.model.dataformat;
+
+import jakarta.xml.bind.annotation.XmlAccessType;
+import jakarta.xml.bind.annotation.XmlAccessorType;
+import jakarta.xml.bind.annotation.XmlAttribute;
+import jakarta.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlTransient;
+import org.apache.camel.builder.DataFormatBuilder;
+import org.apache.camel.model.DataFormatDefinition;
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Marshal and unmarshal Java beans to and from flat files (such as CSV, delimited, or fixed length formats).
+ */
+@Metadata(firstVersion = "2.10.0", label = "dataformat,transformation,csv", title = "BeanIO")
+@XmlRootElement(name = "beanio")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class BeanioDataFormat extends DataFormatDefinition {
+
+    @XmlAttribute(required = true)
+    private String mapping;
+    @XmlAttribute(required = true)
+    private String streamName;
+    @XmlAttribute
+    @Metadata(javaType = "java.lang.Boolean")
+    private String ignoreUnidentifiedRecords;
+    @XmlAttribute
+    @Metadata(javaType = "java.lang.Boolean")
+    private String ignoreUnexpectedRecords;
+    @XmlAttribute
+    @Metadata(javaType = "java.lang.Boolean")
+    private String ignoreInvalidRecords;
+    @XmlAttribute
+    @Metadata(label = "advanced")
+    private String encoding;
+    @XmlAttribute
+    @Metadata(label = "advanced")
+    private String beanReaderErrorHandlerType;
+    @XmlAttribute
+    @Metadata(label = "advanced", javaType = "java.lang.Boolean")
+    private String unmarshalSingleObject;
+
+    public BeanioDataFormat() {
+        super("beanio");
+    }
+
+    private BeanioDataFormat(BeanioDataFormat.Builder builder) {
+        this();
+        this.mapping = builder.mapping;
+        this.streamName = builder.streamName;
+        this.ignoreUnidentifiedRecords = builder.ignoreUnidentifiedRecords;
+        this.ignoreUnexpectedRecords = builder.ignoreUnexpectedRecords;
+        this.ignoreInvalidRecords = builder.ignoreInvalidRecords;
+        this.encoding = builder.encoding;
+        this.beanReaderErrorHandlerType = builder.beanReaderErrorHandlerType;
+        this.unmarshalSingleObject = builder.unmarshalSingleObject;
+    }
+
+    public String getMapping() {
+        return mapping;
+    }
+
+    /**
+     * 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.
+     */
+    public void setMapping(String mapping) {
+        this.mapping = mapping;
+    }
+
+    public String getStreamName() {
+        return streamName;
+    }
+
+    /**
+     * The name of the stream to use.
+     */
+    public void setStreamName(String streamName) {
+        this.streamName = streamName;
+    }
+
+    public String getIgnoreUnidentifiedRecords() {
+        return ignoreUnidentifiedRecords;
+    }
+
+    /**
+     * Whether to ignore unidentified records.
+     */
+    public void setIgnoreUnidentifiedRecords(String ignoreUnidentifiedRecords) {
+        this.ignoreUnidentifiedRecords = ignoreUnidentifiedRecords;
+    }
+
+    public String getIgnoreUnexpectedRecords() {
+        return ignoreUnexpectedRecords;
+    }
+
+    /**
+     * Whether to ignore unexpected records.
+     */
+    public void setIgnoreUnexpectedRecords(String ignoreUnexpectedRecords) {
+        this.ignoreUnexpectedRecords = ignoreUnexpectedRecords;
+    }
+
+    public String getIgnoreInvalidRecords() {
+        return ignoreInvalidRecords;
+    }
+
+    /**
+     * Whether to ignore invalid records.
+     */
+    public void setIgnoreInvalidRecords(String ignoreInvalidRecords) {
+        this.ignoreInvalidRecords = ignoreInvalidRecords;
+    }
+
+    public String getEncoding() {
+        return encoding;
+    }
+
+    /**
+     * The charset to use.
+     * <p/>
+     * Is by default the JVM platform default charset.
+     */
+    public void setEncoding(String encoding) {
+        this.encoding = encoding;
+    }
+
+    public String getBeanReaderErrorHandlerType() {
+        return beanReaderErrorHandlerType;
+    }
+
+    /**
+     * To use a custom org.apache.camel.dataformat.beanio.BeanIOErrorHandler as error handler while parsing. Configure
+     * the fully qualified class name of the error handler. Notice the options ignoreUnidentifiedRecords,
+     * ignoreUnexpectedRecords, and ignoreInvalidRecords may not be in use when you use a custom error handler.
+     */
+    public void setBeanReaderErrorHandlerType(String beanReaderErrorHandlerType) {
+        this.beanReaderErrorHandlerType = beanReaderErrorHandlerType;
+    }
+
+    public String getUnmarshalSingleObject() {
+        return unmarshalSingleObject;
+    }
+
+    /**
+     * This options controls whether to unmarshal as a list of objects or as a single object only. The former is the
+     * default mode, and the latter is only intended in special use-cases where beanio maps the Camel message to a
+     * single POJO bean.
+     */
+    public void setUnmarshalSingleObject(String unmarshalSingleObject) {
+        this.unmarshalSingleObject = unmarshalSingleObject;
+    }
+
+    /**
+     * {@code Builder} is a specific builder for {@link BeanioDataFormat}.
+     */
+    @XmlTransient
+    public static class Builder implements DataFormatBuilder<BeanioDataFormat> {
+
+        private String mapping;
+        private String streamName;
+        private String ignoreUnidentifiedRecords;
+        private String ignoreUnexpectedRecords;
+        private String ignoreInvalidRecords;
+        private String encoding;
+        private String beanReaderErrorHandlerType;
+        private String unmarshalSingleObject;
+
+        /**
+         * 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.
+         */
+        public BeanioDataFormat.Builder mapping(String mapping) {
+            this.mapping = mapping;
+            return this;
+        }
+
+        /**
+         * The name of the stream to use.
+         */
+        public BeanioDataFormat.Builder streamName(String streamName) {
+            this.streamName = streamName;
+            return this;
+        }
+
+        /**
+         * Whether to ignore unidentified records.
+         */
+        public BeanioDataFormat.Builder ignoreUnidentifiedRecords(String ignoreUnidentifiedRecords) {
+            this.ignoreUnidentifiedRecords = ignoreUnidentifiedRecords;
+            return this;
+        }
+
+        /**
+         * Whether to ignore unidentified records.
+         */
+        public BeanioDataFormat.Builder ignoreUnidentifiedRecords(boolean ignoreUnidentifiedRecords) {
+            this.ignoreUnidentifiedRecords = ignoreUnidentifiedRecords ? "true" : "false";
+            return this;
+        }
+
+        /**
+         * Whether to ignore unexpected records.
+         */
+        public BeanioDataFormat.Builder ignoreUnexpectedRecords(String ignoreUnexpectedRecords) {
+            this.ignoreUnexpectedRecords = ignoreUnexpectedRecords;
+            return this;
+        }
+
+        /**
+         * Whether to ignore unexpected records.
+         */
+        public BeanioDataFormat.Builder ignoreUnexpectedRecords(boolean ignoreUnexpectedRecords) {
+            this.ignoreUnexpectedRecords = ignoreUnexpectedRecords ? "true" : "false";
+            return this;
+        }
+
+        /**
+         * Whether to ignore invalid records.
+         */
+        public BeanioDataFormat.Builder ignoreInvalidRecords(String ignoreInvalidRecords) {
+            this.ignoreInvalidRecords = ignoreInvalidRecords;
+            return this;
+        }
+
+        /**
+         * Whether to ignore invalid records.
+         */
+        public BeanioDataFormat.Builder ignoreInvalidRecords(boolean ignoreInvalidRecords) {
+            this.ignoreInvalidRecords = ignoreInvalidRecords ? "true" : "false";
+            return this;
+        }
+
+        /**
+         * The charset to use.
+         * <p/>
+         * Is by default the JVM platform default charset.
+         */
+        public BeanioDataFormat.Builder encoding(String encoding) {
+            this.encoding = encoding;
+            return this;
+        }
+
+        /**
+         * To use a custom org.apache.camel.dataformat.beanio.BeanIOErrorHandler as error handler while parsing. Configure
+         * the fully qualified class name of the error handler. Notice the options ignoreUnidentifiedRecords,
+         * ignoreUnexpectedRecords, and ignoreInvalidRecords may not be in use when you use a custom error handler.
+         */
+        public BeanioDataFormat.Builder beanReaderErrorHandlerType(String beanReaderErrorHandlerType) {
+            this.beanReaderErrorHandlerType = beanReaderErrorHandlerType;
+            return this;
+        }
+
+        /**
+         * This options controls whether to unmarshal as a list of objects or as a single object only. The former is the
+         * default mode, and the latter is only intended in special use-cases where beanio maps the Camel message to a
+         * single POJO bean.
+         */
+        public BeanioDataFormat.Builder unmarshalSingleObject(String unmarshalSingleObject) {
+            this.unmarshalSingleObject = unmarshalSingleObject;
+            return this;
+        }
+
+        /**
+         * This options controls whether to unmarshal as a list of objects or as a single object only. The former is the
+         * default mode, and the latter is only intended in special use-cases where beanio maps the Camel message to a
+         * single POJO bean.
+         */
+        public BeanioDataFormat.Builder unmarshalSingleObject(boolean unmarshalSingleObject) {
+            this.unmarshalSingleObject = unmarshalSingleObject ? "true" : "false";
+            return this;
+        }
+
+        @Override
+        public BeanioDataFormat end() {
+            return new BeanioDataFormat(this);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java
index 6925e7f75f0..5e3f91d2578 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/dataformat/DataFormatsDefinition.java
@@ -43,6 +43,7 @@ public class DataFormatsDefinition {
             @XmlElement(name = "avro", type = AvroDataFormat.class),
             @XmlElement(name = "barcode", type = BarcodeDataFormat.class),
             @XmlElement(name = "base64", type = Base64DataFormat.class),
+            @XmlElement(name = "beanio", type = BeanioDataFormat.class),
             @XmlElement(name = "bindy", type = BindyDataFormat.class),
             @XmlElement(name = "cbor", type = CBORDataFormat.class),
             @XmlElement(name = "crypto", type = CryptoDataFormat.class),
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/transformer/DataFormatTransformerDefinition.java b/core/camel-core-model/src/main/java/org/apache/camel/model/transformer/DataFormatTransformerDefinition.java
index d0fbe43f752..cdca86bca14 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/transformer/DataFormatTransformerDefinition.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/transformer/DataFormatTransformerDefinition.java
@@ -27,6 +27,7 @@ import org.apache.camel.model.dataformat.ASN1DataFormat;
 import org.apache.camel.model.dataformat.AvroDataFormat;
 import org.apache.camel.model.dataformat.BarcodeDataFormat;
 import org.apache.camel.model.dataformat.Base64DataFormat;
+import org.apache.camel.model.dataformat.BeanioDataFormat;
 import org.apache.camel.model.dataformat.BindyDataFormat;
 import org.apache.camel.model.dataformat.CBORDataFormat;
 import org.apache.camel.model.dataformat.CryptoDataFormat;
@@ -80,6 +81,7 @@ public class DataFormatTransformerDefinition extends TransformerDefinition {
             @XmlElement(name = "avro", type = AvroDataFormat.class),
             @XmlElement(name = "barcode", type = BarcodeDataFormat.class),
             @XmlElement(name = "base64", type = Base64DataFormat.class),
+            @XmlElement(name = "beanio", type = BeanioDataFormat.class),
             @XmlElement(name = "bindy", type = BindyDataFormat.class),
             @XmlElement(name = "cbor", type = CBORDataFormat.class),
             @XmlElement(name = "crypto", type = CryptoDataFormat.class),
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/BeanioDataFormatReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/BeanioDataFormatReifier.java
new file mode 100644
index 00000000000..1e49560407a
--- /dev/null
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/BeanioDataFormatReifier.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.reifier.dataformat;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.model.DataFormatDefinition;
+import org.apache.camel.model.dataformat.BeanioDataFormat;
+
+import java.util.Map;
+
+public class BeanioDataFormatReifier extends DataFormatReifier<BeanioDataFormat> {
+
+    public BeanioDataFormatReifier(CamelContext camelContext, DataFormatDefinition definition) {
+        super(camelContext, (BeanioDataFormat) definition);
+    }
+
+    @Override
+    protected void prepareDataFormatConfig(Map<String, Object> properties) {
+        properties.put("mapping", definition.getMapping());
+        properties.put("streamName", definition.getStreamName());
+        properties.put("ignoreUnidentifiedRecords", definition.getIgnoreUnidentifiedRecords());
+        properties.put("ignoreUnexpectedRecords", definition.getIgnoreUnexpectedRecords());
+        properties.put("ignoreInvalidRecords", definition.getIgnoreInvalidRecords());
+        properties.put("encoding", definition.getEncoding());
+        properties.put("beanReaderErrorHandlerType", definition.getBeanReaderErrorHandlerType());
+        properties.put("unmarshalSingleObject", definition.getUnmarshalSingleObject());
+    }
+
+}
diff --git a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/DataFormatReifier.java b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/DataFormatReifier.java
index fe02153b35d..19773563cd5 100644
--- a/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/DataFormatReifier.java
+++ b/core/camel-core-reifier/src/main/java/org/apache/camel/reifier/dataformat/DataFormatReifier.java
@@ -28,6 +28,7 @@ import org.apache.camel.model.dataformat.ASN1DataFormat;
 import org.apache.camel.model.dataformat.AvroDataFormat;
 import org.apache.camel.model.dataformat.BarcodeDataFormat;
 import org.apache.camel.model.dataformat.Base64DataFormat;
+import org.apache.camel.model.dataformat.BeanioDataFormat;
 import org.apache.camel.model.dataformat.BindyDataFormat;
 import org.apache.camel.model.dataformat.CBORDataFormat;
 import org.apache.camel.model.dataformat.ContentTypeHeaderAware;
@@ -183,6 +184,8 @@ public abstract class DataFormatReifier<T extends DataFormatDefinition> extends
             return new BarcodeDataFormatReifier(camelContext, definition);
         } else if (definition instanceof Base64DataFormat) {
             return new Base64DataFormatReifier(camelContext, definition);
+        } else if (definition instanceof BeanioDataFormat) {
+            return new BeanioDataFormatReifier(camelContext, definition);
         } else if (definition instanceof BindyDataFormat) {
             return new BindyDataFormatReifier(camelContext, definition);
         } else if (definition instanceof CBORDataFormat) {
diff --git a/core/camel-main/src/generated/resources/org/apache/camel/main/dataformats.properties b/core/camel-main/src/generated/resources/org/apache/camel/main/dataformats.properties
index e7c684944b4..ca8d6981a6e 100644
--- a/core/camel-main/src/generated/resources/org/apache/camel/main/dataformats.properties
+++ b/core/camel-main/src/generated/resources/org/apache/camel/main/dataformats.properties
@@ -3,6 +3,7 @@ avro
 avroJackson
 barcode
 base64
+beanio
 bindyCsv
 bindyFixed
 bindyKvp
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
index 912733fde48..0eb3ef53b79 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/in/ModelParser.java
@@ -2166,6 +2166,22 @@ public class ModelParser extends BaseParser {
             return true;
         }, noElementHandler(), noValueHandler());
     }
+    protected BeanioDataFormat doParseBeanioDataFormat() throws IOException, XmlPullParserException {
+        return doParse(new BeanioDataFormat(), (def, key, val) -> {
+            switch (key) {
+                case "beanReaderErrorHandlerType": def.setBeanReaderErrorHandlerType(val); break;
+                case "encoding": def.setEncoding(val); break;
+                case "ignoreInvalidRecords": def.setIgnoreInvalidRecords(val); break;
+                case "ignoreUnexpectedRecords": def.setIgnoreUnexpectedRecords(val); break;
+                case "ignoreUnidentifiedRecords": def.setIgnoreUnidentifiedRecords(val); break;
+                case "mapping": def.setMapping(val); break;
+                case "streamName": def.setStreamName(val); break;
+                case "unmarshalSingleObject": def.setUnmarshalSingleObject(val); break;
+                default: return identifiedTypeAttributeHandler().accept(def, key, val);
+            }
+            return true;
+        }, noElementHandler(), noValueHandler());
+    }
     protected BindyDataFormat doParseBindyDataFormat() throws IOException, XmlPullParserException {
         return doParse(new BindyDataFormat(), (def, key, val) -> {
             switch (key) {
@@ -3593,6 +3609,7 @@ public class ModelParser extends BaseParser {
             case "avro": return doParseAvroDataFormat();
             case "barcode": return doParseBarcodeDataFormat();
             case "base64": return doParseBase64DataFormat();
+            case "beanio": return doParseBeanioDataFormat();
             case "bindy": return doParseBindyDataFormat();
             case "cbor": return doParseCBORDataFormat();
             case "crypto": return doParseCryptoDataFormat();
diff --git a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
index e1d0b43431e..6f95f059324 100644
--- a/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
+++ b/core/camel-xml-io/src/generated/java/org/apache/camel/xml/out/ModelWriter.java
@@ -631,6 +631,9 @@ public class ModelWriter extends BaseWriter {
     public void writeBase64DataFormat(Base64DataFormat def) throws IOException {
         doWriteBase64DataFormat("base64", def);
     }
+    public void writeBeanioDataFormat(BeanioDataFormat def) throws IOException {
+        doWriteBeanioDataFormat("beanio", def);
+    }
     public void writeBindyDataFormat(BindyDataFormat def) throws IOException {
         doWriteBindyDataFormat("bindy", def);
     }
@@ -1553,6 +1556,7 @@ public class ModelWriter extends BaseWriter {
                 case "AvroDataFormat" -> doWriteAvroDataFormat("avro", (AvroDataFormat) def.getDataFormatType());
                 case "BarcodeDataFormat" -> doWriteBarcodeDataFormat("barcode", (BarcodeDataFormat) def.getDataFormatType());
                 case "Base64DataFormat" -> doWriteBase64DataFormat("base64", (Base64DataFormat) def.getDataFormatType());
+                case "BeanioDataFormat" -> doWriteBeanioDataFormat("beanio", (BeanioDataFormat) def.getDataFormatType());
                 case "BindyDataFormat" -> doWriteBindyDataFormat("bindy", (BindyDataFormat) def.getDataFormatType());
                 case "CBORDataFormat" -> doWriteCBORDataFormat("cbor", (CBORDataFormat) def.getDataFormatType());
                 case "CryptoDataFormat" -> doWriteCryptoDataFormat("crypto", (CryptoDataFormat) def.getDataFormatType());
@@ -2509,6 +2513,7 @@ public class ModelWriter extends BaseWriter {
                 case "AvroDataFormat" -> doWriteAvroDataFormat("avro", (AvroDataFormat) def.getDataFormatType());
                 case "BarcodeDataFormat" -> doWriteBarcodeDataFormat("barcode", (BarcodeDataFormat) def.getDataFormatType());
                 case "Base64DataFormat" -> doWriteBase64DataFormat("base64", (Base64DataFormat) def.getDataFormatType());
+                case "BeanioDataFormat" -> doWriteBeanioDataFormat("beanio", (BeanioDataFormat) def.getDataFormatType());
                 case "BindyDataFormat" -> doWriteBindyDataFormat("bindy", (BindyDataFormat) def.getDataFormatType());
                 case "CBORDataFormat" -> doWriteCBORDataFormat("cbor", (CBORDataFormat) def.getDataFormatType());
                 case "CryptoDataFormat" -> doWriteCryptoDataFormat("crypto", (CryptoDataFormat) def.getDataFormatType());
@@ -3142,6 +3147,22 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("lineLength", def.getLineLength());
         endElement(name);
     }
+    protected void doWriteBeanioDataFormat(
+            String name,
+            BeanioDataFormat def)
+            throws IOException {
+        startElement(name);
+        doWriteIdentifiedTypeAttributes(def);
+        doWriteAttribute("mapping", def.getMapping());
+        doWriteAttribute("ignoreUnexpectedRecords", def.getIgnoreUnexpectedRecords());
+        doWriteAttribute("ignoreUnidentifiedRecords", def.getIgnoreUnidentifiedRecords());
+        doWriteAttribute("beanReaderErrorHandlerType", def.getBeanReaderErrorHandlerType());
+        doWriteAttribute("unmarshalSingleObject", def.getUnmarshalSingleObject());
+        doWriteAttribute("encoding", def.getEncoding());
+        doWriteAttribute("streamName", def.getStreamName());
+        doWriteAttribute("ignoreInvalidRecords", def.getIgnoreInvalidRecords());
+        endElement(name);
+    }
     protected void doWriteBindyDataFormat(
             String name,
             BindyDataFormat def)
@@ -3247,6 +3268,7 @@ public class ModelWriter extends BaseWriter {
                 case "AvroDataFormat" -> doWriteAvroDataFormat("avro", (AvroDataFormat) v);
                 case "BarcodeDataFormat" -> doWriteBarcodeDataFormat("barcode", (BarcodeDataFormat) v);
                 case "Base64DataFormat" -> doWriteBase64DataFormat("base64", (Base64DataFormat) v);
+                case "BeanioDataFormat" -> doWriteBeanioDataFormat("beanio", (BeanioDataFormat) v);
                 case "BindyDataFormat" -> doWriteBindyDataFormat("bindy", (BindyDataFormat) v);
                 case "CBORDataFormat" -> doWriteCBORDataFormat("cbor", (CBORDataFormat) v);
                 case "CryptoDataFormat" -> doWriteCryptoDataFormat("crypto", (CryptoDataFormat) v);
@@ -4655,6 +4677,7 @@ public class ModelWriter extends BaseWriter {
                 case "AvroDataFormat" -> doWriteAvroDataFormat("avro", (AvroDataFormat) def.getDataFormatType());
                 case "BarcodeDataFormat" -> doWriteBarcodeDataFormat("barcode", (BarcodeDataFormat) def.getDataFormatType());
                 case "Base64DataFormat" -> doWriteBase64DataFormat("base64", (Base64DataFormat) def.getDataFormatType());
+                case "BeanioDataFormat" -> doWriteBeanioDataFormat("beanio", (BeanioDataFormat) def.getDataFormatType());
                 case "BindyDataFormat" -> doWriteBindyDataFormat("bindy", (BindyDataFormat) def.getDataFormatType());
                 case "CBORDataFormat" -> doWriteCBORDataFormat("cbor", (CBORDataFormat) def.getDataFormatType());
                 case "CryptoDataFormat" -> doWriteCryptoDataFormat("crypto", (CryptoDataFormat) def.getDataFormatType());
diff --git a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
index 3991d301d87..5b39f3da0ef 100644
--- a/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
+++ b/core/camel-yaml-io/src/generated/java/org/apache/camel/yaml/out/ModelWriter.java
@@ -631,6 +631,9 @@ public class ModelWriter extends BaseWriter {
     public void writeBase64DataFormat(Base64DataFormat def) throws IOException {
         doWriteBase64DataFormat("base64", def);
     }
+    public void writeBeanioDataFormat(BeanioDataFormat def) throws IOException {
+        doWriteBeanioDataFormat("beanio", def);
+    }
     public void writeBindyDataFormat(BindyDataFormat def) throws IOException {
         doWriteBindyDataFormat("bindy", def);
     }
@@ -1553,6 +1556,7 @@ public class ModelWriter extends BaseWriter {
                 case "AvroDataFormat" -> doWriteAvroDataFormat("avro", (AvroDataFormat) def.getDataFormatType());
                 case "BarcodeDataFormat" -> doWriteBarcodeDataFormat("barcode", (BarcodeDataFormat) def.getDataFormatType());
                 case "Base64DataFormat" -> doWriteBase64DataFormat("base64", (Base64DataFormat) def.getDataFormatType());
+                case "BeanioDataFormat" -> doWriteBeanioDataFormat("beanio", (BeanioDataFormat) def.getDataFormatType());
                 case "BindyDataFormat" -> doWriteBindyDataFormat("bindy", (BindyDataFormat) def.getDataFormatType());
                 case "CBORDataFormat" -> doWriteCBORDataFormat("cbor", (CBORDataFormat) def.getDataFormatType());
                 case "CryptoDataFormat" -> doWriteCryptoDataFormat("crypto", (CryptoDataFormat) def.getDataFormatType());
@@ -2509,6 +2513,7 @@ public class ModelWriter extends BaseWriter {
                 case "AvroDataFormat" -> doWriteAvroDataFormat("avro", (AvroDataFormat) def.getDataFormatType());
                 case "BarcodeDataFormat" -> doWriteBarcodeDataFormat("barcode", (BarcodeDataFormat) def.getDataFormatType());
                 case "Base64DataFormat" -> doWriteBase64DataFormat("base64", (Base64DataFormat) def.getDataFormatType());
+                case "BeanioDataFormat" -> doWriteBeanioDataFormat("beanio", (BeanioDataFormat) def.getDataFormatType());
                 case "BindyDataFormat" -> doWriteBindyDataFormat("bindy", (BindyDataFormat) def.getDataFormatType());
                 case "CBORDataFormat" -> doWriteCBORDataFormat("cbor", (CBORDataFormat) def.getDataFormatType());
                 case "CryptoDataFormat" -> doWriteCryptoDataFormat("crypto", (CryptoDataFormat) def.getDataFormatType());
@@ -3142,6 +3147,22 @@ public class ModelWriter extends BaseWriter {
         doWriteAttribute("lineLength", def.getLineLength());
         endElement(name);
     }
+    protected void doWriteBeanioDataFormat(
+            String name,
+            BeanioDataFormat def)
+            throws IOException {
+        startElement(name);
+        doWriteIdentifiedTypeAttributes(def);
+        doWriteAttribute("mapping", def.getMapping());
+        doWriteAttribute("ignoreUnexpectedRecords", def.getIgnoreUnexpectedRecords());
+        doWriteAttribute("ignoreUnidentifiedRecords", def.getIgnoreUnidentifiedRecords());
+        doWriteAttribute("beanReaderErrorHandlerType", def.getBeanReaderErrorHandlerType());
+        doWriteAttribute("unmarshalSingleObject", def.getUnmarshalSingleObject());
+        doWriteAttribute("encoding", def.getEncoding());
+        doWriteAttribute("streamName", def.getStreamName());
+        doWriteAttribute("ignoreInvalidRecords", def.getIgnoreInvalidRecords());
+        endElement(name);
+    }
     protected void doWriteBindyDataFormat(
             String name,
             BindyDataFormat def)
@@ -3247,6 +3268,7 @@ public class ModelWriter extends BaseWriter {
                 case "AvroDataFormat" -> doWriteAvroDataFormat("avro", (AvroDataFormat) v);
                 case "BarcodeDataFormat" -> doWriteBarcodeDataFormat("barcode", (BarcodeDataFormat) v);
                 case "Base64DataFormat" -> doWriteBase64DataFormat("base64", (Base64DataFormat) v);
+                case "BeanioDataFormat" -> doWriteBeanioDataFormat("beanio", (BeanioDataFormat) v);
                 case "BindyDataFormat" -> doWriteBindyDataFormat("bindy", (BindyDataFormat) v);
                 case "CBORDataFormat" -> doWriteCBORDataFormat("cbor", (CBORDataFormat) v);
                 case "CryptoDataFormat" -> doWriteCryptoDataFormat("crypto", (CryptoDataFormat) v);
@@ -4655,6 +4677,7 @@ public class ModelWriter extends BaseWriter {
                 case "AvroDataFormat" -> doWriteAvroDataFormat("avro", (AvroDataFormat) def.getDataFormatType());
                 case "BarcodeDataFormat" -> doWriteBarcodeDataFormat("barcode", (BarcodeDataFormat) def.getDataFormatType());
                 case "Base64DataFormat" -> doWriteBase64DataFormat("base64", (Base64DataFormat) def.getDataFormatType());
+                case "BeanioDataFormat" -> doWriteBeanioDataFormat("beanio", (BeanioDataFormat) def.getDataFormatType());
                 case "BindyDataFormat" -> doWriteBindyDataFormat("bindy", (BindyDataFormat) def.getDataFormatType());
                 case "CBORDataFormat" -> doWriteCBORDataFormat("cbor", (CBORDataFormat) def.getDataFormatType());
                 case "CryptoDataFormat" -> doWriteCryptoDataFormat("crypto", (CryptoDataFormat) def.getDataFormatType());
diff --git a/docs/components/modules/dataformats/examples/json/beanio.json b/docs/components/modules/dataformats/examples/json/beanio.json
new file mode 120000
index 00000000000..9a8e425be0e
--- /dev/null
+++ b/docs/components/modules/dataformats/examples/json/beanio.json
@@ -0,0 +1 @@
+../../../../../../components/camel-beanio/src/generated/resources/org/apache/camel/dataformat/beanio/beanio.json
\ No newline at end of file
diff --git a/docs/components/modules/dataformats/nav.adoc b/docs/components/modules/dataformats/nav.adoc
index de8415029ca..053d0ae1f71 100644
--- a/docs/components/modules/dataformats/nav.adoc
+++ b/docs/components/modules/dataformats/nav.adoc
@@ -7,6 +7,7 @@
 ** xref:avroJackson-dataformat.adoc[Avro Jackson]
 ** xref:barcode-dataformat.adoc[Barcode]
 ** xref:base64-dataformat.adoc[Base64]
+** xref:beanio-dataformat.adoc[BeanIO]
 ** xref:bindy-dataformat.adoc[Bindy]
 ** xref:cbor-dataformat.adoc[CBOR]
 ** xref:crypto-dataformat.adoc[Crypto (Java Cryptographic Extension)]
diff --git a/docs/components/modules/dataformats/pages/beanio-dataformat.adoc b/docs/components/modules/dataformats/pages/beanio-dataformat.adoc
new file mode 120000
index 00000000000..a6a06a03e6d
--- /dev/null
+++ b/docs/components/modules/dataformats/pages/beanio-dataformat.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-beanio/src/main/docs/beanio-dataformat.adoc
\ No newline at end of file
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
index d91e5e3798d..aa91e1dc74e 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializers.java
@@ -135,6 +135,7 @@ import org.apache.camel.model.dataformat.ASN1DataFormat;
 import org.apache.camel.model.dataformat.AvroDataFormat;
 import org.apache.camel.model.dataformat.BarcodeDataFormat;
 import org.apache.camel.model.dataformat.Base64DataFormat;
+import org.apache.camel.model.dataformat.BeanioDataFormat;
 import org.apache.camel.model.dataformat.BindyDataFormat;
 import org.apache.camel.model.dataformat.CBORDataFormat;
 import org.apache.camel.model.dataformat.CryptoDataFormat;
@@ -1247,6 +1248,93 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
         }
     }
 
+    @YamlType(
+            nodes = "beanio",
+            types = org.apache.camel.model.dataformat.BeanioDataFormat.class,
+            order = org.apache.camel.dsl.yaml.common.YamlDeserializerResolver.ORDER_LOWEST - 1,
+            displayName = "BeanIO",
+            description = "Marshal and unmarshal Java beans to and from flat files (such as CSV, delimited, or fixed length formats).",
+            deprecated = false,
+            properties = {
+                    @YamlProperty(name = "beanReaderErrorHandlerType", type = "string", description = "To use a custom org.apache.camel.dataformat.beanio.BeanIOErrorHandler as error handler while parsing. Configure the fully qualified class name of the error handler. Notice the options ignoreUnidentifiedRecords, ignoreUnexpectedRecords, and ignoreInvalidRecords may not be in use when you use a custom error handler.", displayName = "Bean Reader Error Handler Type"),
+                    @YamlProperty(name = "encoding", type = "string", description = "The charset to use. Is by default the JVM platform default charset.", displayName = "Encoding"),
+                    @YamlProperty(name = "id", type = "string", description = "The id of this node", displayName = "Id"),
+                    @YamlProperty(name = "ignoreInvalidRecords", type = "boolean", description = "Whether to ignore invalid records.", displayName = "Ignore Invalid Records"),
+                    @YamlProperty(name = "ignoreUnexpectedRecords", type = "boolean", description = "Whether to ignore unexpected records.", displayName = "Ignore Unexpected Records"),
+                    @YamlProperty(name = "ignoreUnidentifiedRecords", type = "boolean", description = "Whether to ignore unidentified records.", displayName = "Ignore Unidentified Records"),
+                    @YamlProperty(name = "mapping", type = "string", required = true, 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.", displayName = "Mapping"),
+                    @YamlProperty(name = "streamName", type = "string", required = true, description = "The name of the stream to use.", displayName = "Stream Name"),
+                    @YamlProperty(name = "unmarshalSingleObject", type = "boolean", description = "This options controls whether to unmarshal as a list of objects or as a single object only. The former is the default mode, and the latter is only intended in special use-cases where beanio maps the Camel message to a single POJO bean.", displayName = "Unmarshal Single Object")
+            }
+    )
+    public static class BeanioDataFormatDeserializer extends YamlDeserializerBase<BeanioDataFormat> {
+        public BeanioDataFormatDeserializer() {
+            super(BeanioDataFormat.class);
+        }
+
+        @Override
+        protected BeanioDataFormat newInstance() {
+            return new BeanioDataFormat();
+        }
+
+        @Override
+        protected boolean setProperty(BeanioDataFormat target, String propertyKey,
+                String propertyName, Node node) {
+            propertyKey = org.apache.camel.util.StringHelper.dashToCamelCase(propertyKey);
+            switch(propertyKey) {
+                case "beanReaderErrorHandlerType": {
+                    String val = asText(node);
+                    target.setBeanReaderErrorHandlerType(val);
+                    break;
+                }
+                case "encoding": {
+                    String val = asText(node);
+                    target.setEncoding(val);
+                    break;
+                }
+                case "id": {
+                    String val = asText(node);
+                    target.setId(val);
+                    break;
+                }
+                case "ignoreInvalidRecords": {
+                    String val = asText(node);
+                    target.setIgnoreInvalidRecords(val);
+                    break;
+                }
+                case "ignoreUnexpectedRecords": {
+                    String val = asText(node);
+                    target.setIgnoreUnexpectedRecords(val);
+                    break;
+                }
+                case "ignoreUnidentifiedRecords": {
+                    String val = asText(node);
+                    target.setIgnoreUnidentifiedRecords(val);
+                    break;
+                }
+                case "mapping": {
+                    String val = asText(node);
+                    target.setMapping(val);
+                    break;
+                }
+                case "streamName": {
+                    String val = asText(node);
+                    target.setStreamName(val);
+                    break;
+                }
+                case "unmarshalSingleObject": {
+                    String val = asText(node);
+                    target.setUnmarshalSingleObject(val);
+                    break;
+                }
+                default: {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
     @YamlType(
             nodes = {
                     "bearer-token",
@@ -3369,6 +3457,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "avro", type = "object:org.apache.camel.model.dataformat.AvroDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "barcode", type = "object:org.apache.camel.model.dataformat.BarcodeDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "base64", type = "object:org.apache.camel.model.dataformat.Base64DataFormat", oneOf = "dataFormatType"),
+                    @YamlProperty(name = "beanio", type = "object:org.apache.camel.model.dataformat.BeanioDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "bindy", type = "object:org.apache.camel.model.dataformat.BindyDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "cbor", type = "object:org.apache.camel.model.dataformat.CBORDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "crypto", type = "object:org.apache.camel.model.dataformat.CryptoDataFormat", oneOf = "dataFormatType"),
@@ -3451,6 +3540,11 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setDataFormatType(val);
                     break;
                 }
+                case "beanio": {
+                    org.apache.camel.model.dataformat.BeanioDataFormat val = asType(node, org.apache.camel.model.dataformat.BeanioDataFormat.class);
+                    target.setDataFormatType(val);
+                    break;
+                }
                 case "bindy": {
                     org.apache.camel.model.dataformat.BindyDataFormat val = asType(node, org.apache.camel.model.dataformat.BindyDataFormat.class);
                     target.setDataFormatType(val);
@@ -3674,6 +3768,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "avro", type = "object:org.apache.camel.model.dataformat.AvroDataFormat"),
                     @YamlProperty(name = "barcode", type = "object:org.apache.camel.model.dataformat.BarcodeDataFormat"),
                     @YamlProperty(name = "base64", type = "object:org.apache.camel.model.dataformat.Base64DataFormat"),
+                    @YamlProperty(name = "beanio", type = "object:org.apache.camel.model.dataformat.BeanioDataFormat"),
                     @YamlProperty(name = "bindy", type = "object:org.apache.camel.model.dataformat.BindyDataFormat"),
                     @YamlProperty(name = "cbor", type = "object:org.apache.camel.model.dataformat.CBORDataFormat"),
                     @YamlProperty(name = "crypto", type = "object:org.apache.camel.model.dataformat.CryptoDataFormat"),
@@ -3772,6 +3867,16 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setDataFormats(existing);
                     break;
                 }
+                case "beanio": {
+                    org.apache.camel.model.dataformat.BeanioDataFormat val = asType(node, org.apache.camel.model.dataformat.BeanioDataFormat.class);
+                    java.util.List<org.apache.camel.model.DataFormatDefinition> existing = target.getDataFormats();
+                    if (existing == null) {
+                        existing = new java.util.ArrayList<>();
+                    }
+                    existing.add(val);
+                    target.setDataFormats(existing);
+                    break;
+                }
                 case "bindy": {
                     org.apache.camel.model.dataformat.BindyDataFormat val = asType(node, org.apache.camel.model.dataformat.BindyDataFormat.class);
                     java.util.List<org.apache.camel.model.DataFormatDefinition> existing = target.getDataFormats();
@@ -9023,6 +9128,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "avro", type = "object:org.apache.camel.model.dataformat.AvroDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "barcode", type = "object:org.apache.camel.model.dataformat.BarcodeDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "base64", type = "object:org.apache.camel.model.dataformat.Base64DataFormat", oneOf = "dataFormatType"),
+                    @YamlProperty(name = "beanio", type = "object:org.apache.camel.model.dataformat.BeanioDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "bindy", type = "object:org.apache.camel.model.dataformat.BindyDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "cbor", type = "object:org.apache.camel.model.dataformat.CBORDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "crypto", type = "object:org.apache.camel.model.dataformat.CryptoDataFormat", oneOf = "dataFormatType"),
@@ -9107,6 +9213,11 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setDataFormatType(val);
                     break;
                 }
+                case "beanio": {
+                    org.apache.camel.model.dataformat.BeanioDataFormat val = asType(node, org.apache.camel.model.dataformat.BeanioDataFormat.class);
+                    target.setDataFormatType(val);
+                    break;
+                }
                 case "bindy": {
                     org.apache.camel.model.dataformat.BindyDataFormat val = asType(node, org.apache.camel.model.dataformat.BindyDataFormat.class);
                     target.setDataFormatType(val);
@@ -19243,6 +19354,7 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     @YamlProperty(name = "avro", type = "object:org.apache.camel.model.dataformat.AvroDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "barcode", type = "object:org.apache.camel.model.dataformat.BarcodeDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "base64", type = "object:org.apache.camel.model.dataformat.Base64DataFormat", oneOf = "dataFormatType"),
+                    @YamlProperty(name = "beanio", type = "object:org.apache.camel.model.dataformat.BeanioDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "bindy", type = "object:org.apache.camel.model.dataformat.BindyDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "cbor", type = "object:org.apache.camel.model.dataformat.CBORDataFormat", oneOf = "dataFormatType"),
                     @YamlProperty(name = "crypto", type = "object:org.apache.camel.model.dataformat.CryptoDataFormat", oneOf = "dataFormatType"),
@@ -19332,6 +19444,11 @@ public final class ModelDeserializers extends YamlDeserializerSupport {
                     target.setDataFormatType(val);
                     break;
                 }
+                case "beanio": {
+                    org.apache.camel.model.dataformat.BeanioDataFormat val = asType(node, org.apache.camel.model.dataformat.BeanioDataFormat.class);
+                    target.setDataFormatType(val);
+                    break;
+                }
                 case "bindy": {
                     org.apache.camel.model.dataformat.BindyDataFormat val = asType(node, org.apache.camel.model.dataformat.BindyDataFormat.class);
                     target.setDataFormatType(val);
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
index 30f67d67481..a5c18edb145 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-deserializers/src/generated/java/org/apache/camel/dsl/yaml/deserializers/ModelDeserializersResolver.java
@@ -40,6 +40,8 @@ public final class ModelDeserializersResolver implements YamlDeserializerResolve
             case "org.apache.camel.model.BeanDefinition": return new ModelDeserializers.BeanDefinitionDeserializer();
             case "org.apache.camel.model.app.BeanPropertiesDefinition": return new ModelDeserializers.BeanPropertiesDefinitionDeserializer();
             case "org.apache.camel.model.app.BeanPropertyDefinition": return new ModelDeserializers.BeanPropertyDefinitionDeserializer();
+            case "beanio": return new ModelDeserializers.BeanioDataFormatDeserializer();
+            case "org.apache.camel.model.dataformat.BeanioDataFormat": return new ModelDeserializers.BeanioDataFormatDeserializer();
             case "bearer-token": return new ModelDeserializers.BearerTokenDefinitionDeserializer();
             case "bearerToken": return new ModelDeserializers.BearerTokenDefinitionDeserializer();
             case "org.apache.camel.model.rest.BearerTokenDefinition": return new ModelDeserializers.BearerTokenDefinitionDeserializer();
diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
index b0b668b9a7c..1f238aeec47 100644
--- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
+++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl.json
@@ -2700,6 +2700,8 @@
                 "required" : [ "barcode" ]
               }, {
                 "required" : [ "base64" ]
+              }, {
+                "required" : [ "beanio" ]
               }, {
                 "required" : [ "bindy" ]
               }, {
@@ -2798,6 +2800,14 @@
                 "$ref" : "#/items/definitions/org.apache.camel.model.dataformat.Base64DataFormat"
               }
             }
+          }, {
+            "type" : "object",
+            "required" : [ "beanio" ],
+            "properties" : {
+              "beanio" : {
+                "$ref" : "#/items/definitions/org.apache.camel.model.dataformat.BeanioDataFormat"
+              }
+            }
           }, {
             "type" : "object",
             "required" : [ "bindy" ],
@@ -3118,6 +3128,7 @@
           "avro" : { },
           "barcode" : { },
           "base64" : { },
+          "beanio" : { },
           "bindy" : { },
           "cbor" : { },
           "crypto" : { },
@@ -7271,6 +7282,7 @@
           "avro" : { },
           "barcode" : { },
           "base64" : { },
+          "beanio" : { },
           "bindy" : { },
           "cbor" : { },
           "crypto" : { },
@@ -7327,6 +7339,8 @@
                 "required" : [ "barcode" ]
               }, {
                 "required" : [ "base64" ]
+              }, {
+                "required" : [ "beanio" ]
               }, {
                 "required" : [ "bindy" ]
               }, {
@@ -7425,6 +7439,14 @@
                 "$ref" : "#/items/definitions/org.apache.camel.model.dataformat.Base64DataFormat"
               }
             }
+          }, {
+            "type" : "object",
+            "required" : [ "beanio" ],
+            "properties" : {
+              "beanio" : {
+                "$ref" : "#/items/definitions/org.apache.camel.model.dataformat.BeanioDataFormat"
+              }
+            }
           }, {
             "type" : "object",
             "required" : [ "bindy" ],
@@ -9796,6 +9818,60 @@
           }
         }
       },
+      "org.apache.camel.model.dataformat.BeanioDataFormat" : {
+        "title" : "BeanIO",
+        "description" : "Marshal and unmarshal Java beans to and from flat files (such as CSV, delimited, or fixed length formats).",
+        "type" : "object",
+        "additionalProperties" : false,
+        "properties" : {
+          "beanReaderErrorHandlerType" : {
+            "type" : "string",
+            "title" : "Bean Reader Error Handler Type",
+            "description" : "To use a custom org.apache.camel.dataformat.beanio.BeanIOErrorHandler as error handler while parsing. Configure the fully qualified class name of the error handler. Notice the options ignoreUnidentifiedRecords, ignoreUnexpectedRecords, and ignoreInvalidRecords may not be in use when you use a custom error handler."
+          },
+          "encoding" : {
+            "type" : "string",
+            "title" : "Encoding",
+            "description" : "The charset to use. Is by default the JVM platform default charset."
+          },
+          "id" : {
+            "type" : "string",
+            "title" : "Id",
+            "description" : "The id of this node"
+          },
+          "ignoreInvalidRecords" : {
+            "type" : "boolean",
+            "title" : "Ignore Invalid Records",
+            "description" : "Whether to ignore invalid records."
+          },
+          "ignoreUnexpectedRecords" : {
+            "type" : "boolean",
+            "title" : "Ignore Unexpected Records",
+            "description" : "Whether to ignore unexpected records."
+          },
+          "ignoreUnidentifiedRecords" : {
+            "type" : "boolean",
+            "title" : "Ignore Unidentified Records",
+            "description" : "Whether to ignore unidentified records."
+          },
+          "mapping" : {
+            "type" : "string",
+            "title" : "Mapping",
+            "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."
+          },
+          "streamName" : {
+            "type" : "string",
+            "title" : "Stream Name",
+            "description" : "The name of the stream to use."
+          },
+          "unmarshalSingleObject" : {
+            "type" : "boolean",
+            "title" : "Unmarshal Single Object",
+            "description" : "This options controls whether to unmarshal as a list of objects or as a single object only. The former is the default mode, and the latter is only intended in special use-cases where beanio maps the Camel message to a single POJO bean."
+          }
+        },
+        "required" : [ "mapping", "streamName" ]
+      },
       "org.apache.camel.model.dataformat.BindyDataFormat" : {
         "title" : "Bindy",
         "description" : "Marshal and unmarshal Java beans from and to flat payloads (such as CSV, delimited, fixed length formats, or FIX messages).",
@@ -10167,6 +10243,9 @@
           "base64" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.dataformat.Base64DataFormat"
           },
+          "beanio" : {
+            "$ref" : "#/items/definitions/org.apache.camel.model.dataformat.BeanioDataFormat"
+          },
           "bindy" : {
             "$ref" : "#/items/definitions/org.apache.camel.model.dataformat.BindyDataFormat"
           },
@@ -15403,6 +15482,8 @@
                 "required" : [ "barcode" ]
               }, {
                 "required" : [ "base64" ]
+              }, {
+                "required" : [ "beanio" ]
               }, {
                 "required" : [ "bindy" ]
               }, {
@@ -15501,6 +15582,14 @@
                 "$ref" : "#/items/definitions/org.apache.camel.model.dataformat.Base64DataFormat"
               }
             }
+          }, {
+            "type" : "object",
+            "required" : [ "beanio" ],
+            "properties" : {
+              "beanio" : {
+                "$ref" : "#/items/definitions/org.apache.camel.model.dataformat.BeanioDataFormat"
+              }
+            }
           }, {
             "type" : "object",
             "required" : [ "bindy" ],
@@ -15808,6 +15897,7 @@
           "avro" : { },
           "barcode" : { },
           "base64" : { },
+          "beanio" : { },
           "bindy" : { },
           "cbor" : { },
           "crypto" : { },
diff --git a/parent/pom.xml b/parent/pom.xml
index daa6aae2f2d..290c0346521 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -72,6 +72,7 @@
         <aws-xray-version>2.15.0</aws-xray-version>
         <azure-sdk-bom-version>1.2.20</azure-sdk-bom-version>
         <azure-storage-blob-changefeed-version>12.0.0-beta.19</azure-storage-blob-changefeed-version>
+        <beanio-version>3.0.0.M3</beanio-version>
         <bouncycastle-version>1.77</bouncycastle-version>
         <box-java-sdk-version>4.7.0</box-java-sdk-version>
         <braintree-gateway-version>3.32.0</braintree-gateway-version>
@@ -910,6 +911,11 @@
                 <artifactId>camel-bean-validator</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-beanio</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel</groupId>
                 <artifactId>camel-bindy</artifactId>