You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ff...@apache.org on 2022/03/17 20:15:48 UTC

[camel-spring-boot] branch main updated: [CAMEL-17807]add tests in camel-jaxb-starter (#473)

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

ffang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git


The following commit(s) were added to refs/heads/main by this push:
     new 7860fca  [CAMEL-17807]add tests in camel-jaxb-starter (#473)
7860fca is described below

commit 7860fca6ce1213ffd7f01d027e5ea65d3c46346f
Author: Freeman(Yue) Fang <fr...@gmail.com>
AuthorDate: Thu Mar 17 16:14:23 2022 -0400

    [CAMEL-17807]add tests in camel-jaxb-starter (#473)
---
 .../camel/converter/jaxb/address/Address.java      | 103 +++++++
 .../converter/jaxb/address/ObjectFactory.java      |  49 ++++
 .../camel/converter/jaxb/address/package-info.java |  19 ++
 .../camel/converter/jaxb/message/Message.java      |  82 ++++++
 .../converter/jaxb/message/ObjectFactory.java      |  57 ++++
 .../camel/converter/jaxb/message/package-info.java |  18 ++
 .../camel/converter/jaxb/person/ObjectFactory.java |  49 ++++
 .../apache/camel/converter/jaxb/person/Person.java | 164 +++++++++++
 .../camel/converter/jaxb/person/package-info.java  |  19 ++
 .../converter/jaxb/springboot/CamelJaxbTest.java   | 299 +++++++++++++++++++++
 ...ncurrentJaxbDataFormatSchemaValidationTest.java | 167 ++++++++++++
 .../jaxb/springboot/DataFormatComponentTest.java   |  63 +++++
 .../converter/jaxb/springboot/DataFormatTest.java  | 136 ++++++++++
 .../springboot/DirectBeanToBeanPersonTypeTest.java |  89 ++++++
 .../ExplicitEncodingAndXMLCharFilteringTest.java   | 118 ++++++++
 .../jaxb/springboot/ExplicitFileEncodingTest.java  | 109 ++++++++
 ...lbackTypeConverterShouldThrowExceptionTest.java | 171 ++++++++++++
 .../converter/jaxb/springboot/FromFileBase.java    |  73 +++++
 .../springboot/JaxbConcurrentDataFormatTest.java   | 124 +++++++++
 .../JaxbDataFormatMultipleNamespacesTest.java      | 150 +++++++++++
 .../JaxbDataFormatPartClassHeaderTest.java         | 125 +++++++++
 .../springboot/JaxbDataFormatPartClassTest.java    | 122 +++++++++
 .../JaxbDataFormatSchemaValidationTest.java        | 189 +++++++++++++
 ...ormatSchemaValidationWithObjectFactoryTest.java | 153 +++++++++++
 .../jaxb/springboot/JaxbErrorLogTest.java          | 148 ++++++++++
 .../jaxb/springboot/RouteWithErrorHandlerTest.java | 154 +++++++++++
 .../TimerBeanToBeanNotificationTypeTest.java       |  89 ++++++
 .../converter/jaxb/springboot/UnmarshalTest.java   |  95 +++++++
 .../java/org/apache/camel/example/Address.java     |  68 +++++
 .../test/java/org/apache/camel/example/Bar.java    |  52 ++++
 .../test/java/org/apache/camel/example/Foo.java    |  43 +++
 .../camel/example/InvalidOrderException.java       |  25 ++
 .../test/java/org/apache/camel/example/Order.java  |  49 ++++
 .../java/org/apache/camel/example/Partial.java     |  81 ++++++
 .../org/apache/camel/example/PurchaseOrder.java    |  79 ++++++
 .../test/java/org/apache/camel/example/Zot.java    |  35 +++
 .../org/apache/camel/example/package-info.java     |  25 ++
 .../org/apache/camel/foo/bar/ObjectFactory.java    |  63 +++++
 .../java/org/apache/camel/foo/bar/PersonType.java  | 113 ++++++++
 .../camel/jaxb/CamelJaxbFallbackConverterTest.java | 126 +++++++++
 .../camel/jaxb/CamelJaxbNoNamespaceSchemaTest.java |  87 ++++++
 ...backTypeConverterObjectFactoryDisabledTest.java |  91 +++++++
 ...lbackTypeConverterObjectFactoryEnabledTest.java | 112 ++++++++
 ...lbackTypeConverterShouldThrowExceptionTest.java | 154 +++++++++++
 .../apache/camel/jaxb/JaxbDataFormatIssueTest.java |  91 +++++++
 .../jaxb/JaxbDataFormatMustBeJAXBElementTest.java  | 122 +++++++++
 .../jaxb/JaxbMarshalNamespacePrefixMapperTest.java | 116 ++++++++
 .../apache/camel/jaxb/MyNotificationService.java   |  39 +++
 .../org/apache/camel/jaxb/MyPersonService.java     |  41 +++
 .../org/apache/camel/jaxb/NotificationType.java    |  39 +++
 .../SplitterAndExceptionRouteTwistIssueTest.java   | 223 +++++++++++++++
 .../org/apache/camel/jaxb/TestXmlStreamWriter.java | 190 +++++++++++++
 .../src/test/resources/address.xsd                 |  32 +++
 .../src/test/resources/message.xml                 |  22 ++
 .../src/test/resources/message.xsd                 |  32 +++
 .../resources/org/apache/camel/example/jaxb.index  |  23 ++
 .../src/test/resources/person.xsd                  |  38 +++
 57 files changed, 5345 insertions(+)

diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/address/Address.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/address/Address.java
new file mode 100644
index 0000000..e20247d
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/address/Address.java
@@ -0,0 +1,103 @@
+/*
+ * 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.converter.jaxb.address;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * <p>
+ * Java class for address complex type.
+ * 
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="address">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="addressLine1" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         &lt;element name="addressLine2" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "address", propOrder = { "addressLine1", "addressLine2" })
+public class Address {
+
+    @XmlElement(required = true)
+    protected String addressLine1;
+    protected String addressLine2;
+
+    /**
+     * Gets the value of the addressLine1 property.
+     * 
+     * @return possible object is {@link String }
+     * 
+     */
+    public String getAddressLine1() {
+        return addressLine1;
+    }
+
+    /**
+     * Sets the value of the addressLine1 property.
+     * 
+     * @param value allowed object is {@link String }
+     * 
+     */
+    public void setAddressLine1(String value) {
+        this.addressLine1 = value;
+    }
+
+    /**
+     * Gets the value of the addressLine2 property.
+     * 
+     * @return possible object is {@link String }
+     * 
+     */
+    public String getAddressLine2() {
+        return addressLine2;
+    }
+
+    /**
+     * Sets the value of the addressLine2 property.
+     * 
+     * @param value allowed object is {@link String }
+     * 
+     */
+    public void setAddressLine2(String value) {
+        this.addressLine2 = value;
+    }
+
+    public Address withAddressLine1(String value) {
+        setAddressLine1(value);
+        return this;
+    }
+
+    public Address withAddressLine2(String value) {
+        setAddressLine2(value);
+        return this;
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/address/ObjectFactory.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/address/ObjectFactory.java
new file mode 100644
index 0000000..a242d01
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/address/ObjectFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.converter.jaxb.address;
+
+import javax.xml.bind.annotation.XmlRegistry;
+
+/**
+ * This object contains factory methods for each Java content interface and Java element interface generated in the
+ * org.apache.camel.converter.jaxb.address package.
+ * <p>
+ * An ObjectFactory allows you to programatically construct new instances of the Java representation for XML content.
+ * The Java representation of XML content can consist of schema derived interfaces and classes representing the binding
+ * of schema type definitions, element declarations and model groups. Factory methods for each of these are provided in
+ * this class.
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+    /**
+     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package:
+     * org.apache.camel.converter.jaxb.address
+     * 
+     */
+    public ObjectFactory() {
+    }
+
+    /**
+     * Create an instance of {@link Address }
+     * 
+     */
+    public Address createAddress() {
+        return new Address();
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/address/package-info.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/address/package-info.java
new file mode 100644
index 0000000..0e38a34
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/address/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+@javax.xml.bind.annotation.XmlSchema(namespace = "address.jaxb.converter.camel.apache.org",
+                                     elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.apache.camel.converter.jaxb.address;
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/message/Message.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/message/Message.java
new file mode 100644
index 0000000..d128104
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/message/Message.java
@@ -0,0 +1,82 @@
+/*
+ * 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.converter.jaxb.message;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * <p>
+ * Java class for anonymous complex type.
+ *
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType>
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="text" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = { "text" })
+public class Message {
+
+    @XmlElement(required = true)
+    private String text;
+
+    public Message() {
+    }
+
+    public Message(String text) {
+        this.text = text;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof Message)) {
+            return false;
+        }
+        Message message = (Message) o;
+        return getText() != null ? getText().equals(message.getText()) : message.getText() == null;
+    }
+
+    @Override
+    public int hashCode() {
+        return getText() != null ? getText().hashCode() : 0;
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/message/ObjectFactory.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/message/ObjectFactory.java
new file mode 100644
index 0000000..c1ac836
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/message/ObjectFactory.java
@@ -0,0 +1,57 @@
+/*
+ * 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.converter.jaxb.message;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+/**
+ * This object contains factory methods for each Java content interface and Java element interface generated in the
+ * org.apache.camel.converter.jaxb.message package.
+ * <p>
+ * An ObjectFactory allows you to programatically construct new instances of the Java representation for XML content.
+ * The Java representation of XML content can consist of schema derived interfaces and classes representing the binding
+ * of schema type definitions, element declarations and model groups. Factory methods for each of these are provided in
+ * this class.
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+    private static final QName MESSAGE_QNAME = new QName("message.jaxb.converter.camel.apache.org", "message");
+
+    /**
+     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package:
+     * org.apache.camel.converter.jaxb.message
+     */
+    public ObjectFactory() {
+    }
+
+    /**
+     * Create an instance of {@link Message }
+     */
+    public Message createMessage() {
+        return new Message();
+    }
+
+    @XmlElementDecl(namespace = "message.jaxb.converter.camel.apache.org", name = "message")
+    public JAXBElement<Message> createMessage(Message value) {
+        return new JAXBElement<>(MESSAGE_QNAME, Message.class, null, value);
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/message/package-info.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/message/package-info.java
new file mode 100644
index 0000000..bd5591d
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/message/package-info.java
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+@javax.xml.bind.annotation.XmlSchema(namespace = "message.jaxb.converter.camel.apache.org")
+package org.apache.camel.converter.jaxb.message;
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/person/ObjectFactory.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/person/ObjectFactory.java
new file mode 100644
index 0000000..6fdd150
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/person/ObjectFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.converter.jaxb.person;
+
+import javax.xml.bind.annotation.XmlRegistry;
+
+/**
+ * This object contains factory methods for each Java content interface and Java element interface generated in the
+ * org.apache.camel.converter.jaxb.person package.
+ * <p>
+ * An ObjectFactory allows you to programatically construct new instances of the Java representation for XML content.
+ * The Java representation of XML content can consist of schema derived interfaces and classes representing the binding
+ * of schema type definitions, element declarations and model groups. Factory methods for each of these are provided in
+ * this class.
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+    /**
+     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package:
+     * org.apache.camel.converter.jaxb.person
+     * 
+     */
+    public ObjectFactory() {
+    }
+
+    /**
+     * Create an instance of {@link Person }
+     * 
+     */
+    public Person createPerson() {
+        return new Person();
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/person/Person.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/person/Person.java
new file mode 100644
index 0000000..ebc4556
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/person/Person.java
@@ -0,0 +1,164 @@
+/*
+ * 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.converter.jaxb.person;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.camel.converter.jaxb.address.Address;
+
+/**
+ * <p>
+ * Java class for anonymous complex type.
+ * 
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType>
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="firstName" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         &lt;element name="lastName" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         &lt;element name="age" type="{http://www.w3.org/2001/XMLSchema}int"/>
+ *         &lt;element name="address" type="{address.jaxb.converter.camel.apache.org}address"/>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = { "firstName", "lastName", "age", "address" })
+@XmlRootElement(name = "person")
+public class Person {
+
+    @XmlElement(required = true)
+    protected String firstName;
+    @XmlElement(required = true)
+    protected String lastName;
+    @XmlElement(required = true, type = Integer.class, nillable = true)
+    protected Integer age;
+    @XmlElement(required = true)
+    protected Address address;
+
+    /**
+     * Gets the value of the firstName property.
+     * 
+     * @return possible object is {@link String }
+     * 
+     */
+    public String getFirstName() {
+        return firstName;
+    }
+
+    /**
+     * Sets the value of the firstName property.
+     * 
+     * @param value allowed object is {@link String }
+     * 
+     */
+    public void setFirstName(String value) {
+        this.firstName = value;
+    }
+
+    /**
+     * Gets the value of the lastName property.
+     * 
+     * @return possible object is {@link String }
+     * 
+     */
+    public String getLastName() {
+        return lastName;
+    }
+
+    /**
+     * Sets the value of the lastName property.
+     * 
+     * @param value allowed object is {@link String }
+     * 
+     */
+    public void setLastName(String value) {
+        this.lastName = value;
+    }
+
+    /**
+     * Gets the value of the age property.
+     * 
+     * @return possible object is {@link Integer }
+     * 
+     */
+    public Integer getAge() {
+        return age;
+    }
+
+    /**
+     * Sets the value of the age property.
+     * 
+     * @param value allowed object is {@link Integer }
+     * 
+     */
+    public void setAge(Integer value) {
+        this.age = value;
+    }
+
+    /**
+     * Gets the value of the address property.
+     * 
+     * @return possible object is {@link Address }
+     * 
+     */
+    public Address getAddress() {
+        return address;
+    }
+
+    /**
+     * Sets the value of the address property.
+     * 
+     * @param value allowed object is {@link Address }
+     * 
+     */
+    public void setAddress(Address value) {
+        this.address = value;
+    }
+
+    public Person withFirstName(String value) {
+        setFirstName(value);
+        return this;
+    }
+
+    public Person withLastName(String value) {
+        setLastName(value);
+        return this;
+    }
+
+    public Person withAge(Integer value) {
+        setAge(value);
+        return this;
+    }
+
+    public Person withAddress(Address value) {
+        setAddress(value);
+        return this;
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/person/package-info.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/person/package-info.java
new file mode 100644
index 0000000..512a578
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/person/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+@javax.xml.bind.annotation.XmlSchema(namespace = "person.jaxb.converter.camel.apache.org",
+                                     elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.apache.camel.converter.jaxb.person;
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/CamelJaxbTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/CamelJaxbTest.java
new file mode 100644
index 0000000..81f1df4
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/CamelJaxbTest.java
@@ -0,0 +1,299 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+import javax.xml.bind.JAXBElement;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.foo.bar.PersonType;
+import org.apache.camel.jaxb.TestXmlStreamWriter;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        CamelJaxbTest.class,
+        CamelJaxbTest.TestConfiguration.class
+    }
+)
+public class CamelJaxbTest {
+    
+    
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:result")
+    private MockEndpoint resultEndpoint;
+
+    
+    
+    @Test
+    public void testUnmarshalBadCharsWithFiltering() throws Exception {
+        resultEndpoint.reset();
+        String xml = "<Person><firstName>FOO</firstName><lastName>BAR\u0008</lastName></Person>";
+
+        PersonType expected = new PersonType();
+        expected.setFirstName("FOO");
+        expected.setLastName("BAR ");
+        
+        resultEndpoint.expectedBodiesReceived(expected);
+
+        template.sendBody("direct:unmarshalFilteringEnabled", xml);
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    @Test
+    public void testUnmarshalBadCharsNoFiltering() throws Exception {
+        String xml = "<Person><firstName>FOO</firstName><lastName>BAR\u0008</lastName></Person>";
+        assertThrows(CamelExecutionException.class, () -> template.sendBody("direct:getJAXBElementValue", xml));
+    }
+
+    @Test
+    public void testFilterNonXmlChars() throws Exception {
+        resultEndpoint.reset();
+        String xmlUTF = "<Person><firstName>FOO</firstName><lastName>BAR \u20AC </lastName></Person>";
+        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + xmlUTF;
+        PersonType expected = new PersonType();
+        expected.setFirstName("FOO");
+        expected.setLastName("BAR \u20AC ");
+        resultEndpoint.expectedBodiesReceived(expected);
+        template.sendBody("direct:unmarshalFilteringEnabled", xml);
+        resultEndpoint.assertIsSatisfied();
+
+    }
+
+    @Test
+    public void testMarshalBadCharsWithFiltering() throws Exception {
+        resultEndpoint.reset();
+        PersonType person = new PersonType();
+        person.setFirstName("foo\u0004");
+        person.setLastName("bar");
+
+        
+        resultEndpoint.expectedMessageCount(1);
+        template.sendBody("direct:marshalFilteringEnabled", person);
+        resultEndpoint.assertIsSatisfied();
+
+        String body = resultEndpoint.getReceivedExchanges().get(0).getIn().getBody(String.class);
+        assertFalse(body.contains("\u0004"), "Non-xml character wasn't replaced");
+    }
+
+    @Test
+    public void testMarshalBadCharsNoFiltering() throws Exception {
+        resultEndpoint.reset();
+        PersonType person = new PersonType();
+        person.setFirstName("foo\u0004");
+        person.setLastName("bar");
+
+        
+        resultEndpoint.expectedMessageCount(1);
+        resultEndpoint.expectedHeaderReceived(Exchange.CONTENT_TYPE, "application/xml");
+        template.sendBody("direct:marshal", person);
+        resultEndpoint.assertIsSatisfied();
+
+        String body = resultEndpoint.getReceivedExchanges().get(0).getIn().getBody(String.class);
+        assertTrue(body.contains("\u0004"), "Non-xml character unexpectedly did not get into marshalled contents");
+    }
+
+    @Test
+    public void testMarshalWithSchemaLocation() throws Exception {
+        resultEndpoint.reset();
+        PersonType person = new PersonType();
+        person.setFirstName("foo");
+        person.setLastName("bar");
+
+        
+        resultEndpoint.expectedMessageCount(1);
+        resultEndpoint.expectedHeaderReceived(Exchange.CONTENT_TYPE, "application/xml");
+        template.sendBody("direct:marshal", person);
+        resultEndpoint.assertIsSatisfied();
+
+        String body = resultEndpoint.getReceivedExchanges().get(0).getIn().getBody(String.class);
+        assertTrue(body.contains("schemaLocation=\"person.xsd\""), "We should get the schemaLocation here");
+    }
+
+    @Test
+    public void testMarshalWithoutContentType() throws Exception {
+        resultEndpoint.reset();
+        PersonType person = new PersonType();
+        person.setFirstName("foo");
+        person.setLastName("bar");
+
+        
+        resultEndpoint.expectedMessageCount(1);
+        resultEndpoint.expectedHeaderReceived(Exchange.CONTENT_TYPE, null);
+        template.sendBody("direct:marshalWithoutContentType", person);
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    @Test
+    public void testCustomXmlStreamWriter() throws InterruptedException {
+        resultEndpoint.reset();
+        PersonType person = new PersonType();
+        person.setFirstName("foo");
+        person.setLastName("bar");
+
+        
+        resultEndpoint.expectedMessageCount(1);
+        template.sendBody("direct:marshalCustomWriter", person);
+        resultEndpoint.assertIsSatisfied();
+
+        String body = resultEndpoint.getReceivedExchanges().get(0).getIn().getBody(String.class);
+        assertTrue(body.contains("-Foo"), "Body did not get processed correctly by custom filter");
+    }
+
+    @Test
+    public void testCustomXmlStreamWriterAndFiltering() throws InterruptedException {
+        resultEndpoint.reset();
+        PersonType person = new PersonType();
+        person.setFirstName("foo\u0004");
+        person.setLastName("bar");
+
+        
+        resultEndpoint.expectedMessageCount(1);
+        template.sendBody("direct:marshalCustomWriterAndFiltering", person);
+        resultEndpoint.assertIsSatisfied();
+
+        String body = resultEndpoint.getReceivedExchanges().get(0).getIn().getBody(String.class);
+        assertFalse(body.contains("\u0004"), "Non-xml character unexpectedly did not get into marshalled contents");
+        assertTrue(body.contains("-Foo"), "Body did not get processed correctly by custom filter");
+    }
+
+    @Test
+    public void testUnmarshal() throws Exception {
+        resultEndpoint.reset();
+        final String xml = "<Person><firstName>FOO</firstName><lastName>BAR</lastName></Person>";
+        PersonType expected = new PersonType();
+        expected.setFirstName("FOO");
+        expected.setLastName("BAR");
+        
+        resultEndpoint.expectedBodiesReceived(expected);
+        resultEndpoint.expectedHeaderReceived("foo", "bar");
+        template.sendBodyAndHeader("direct:getJAXBElementValue", xml, "foo", "bar");
+
+        resultEndpoint.assertIsSatisfied();
+        resultEndpoint.reset();
+        resultEndpoint.expectedMessageCount(1);
+        template.sendBody("direct:getJAXBElement", xml);
+        resultEndpoint.assertIsSatisfied();
+        assertTrue(resultEndpoint.getExchanges().get(0).getIn().getBody() instanceof JAXBElement,
+                "We should get the JAXBElement here");
+
+        resultEndpoint.reset();
+        resultEndpoint.expectedMessageCount(1);
+        resultEndpoint.expectedBodiesReceived(expected);
+        template.sendBody("direct:unmarshall", xml);
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    JaxbDataFormat dataFormat = new JaxbDataFormat("org.apache.camel.foo.bar");
+                    dataFormat.setSchemaLocation("person.xsd");
+                    dataFormat.setIgnoreJAXBElement(false);
+
+                    JaxbDataFormat dataFormatWithoutContentType = new JaxbDataFormat("org.apache.camel.foo.bar");
+                    dataFormat.setIgnoreJAXBElement(false);
+                    dataFormatWithoutContentType.setContentTypeHeader(false);
+
+                    JaxbDataFormat filterEnabledFormat = new JaxbDataFormat("org.apache.camel.foo.bar");
+                    filterEnabledFormat.setFilterNonXmlChars(true);
+
+                    JaxbDataFormat customWriterFormat = new JaxbDataFormat("org.apache.camel.foo.bar");
+                    customWriterFormat.setXmlStreamWriterWrapper(new TestXmlStreamWriter());
+
+                    JaxbDataFormat customWriterAndFilterFormat = new JaxbDataFormat("org.apache.camel.foo.bar");
+                    customWriterAndFilterFormat.setFilterNonXmlChars(true);
+                    customWriterAndFilterFormat.setXmlStreamWriterWrapper(new TestXmlStreamWriter());
+
+                    from("direct:getJAXBElementValue")
+                            .unmarshal(new JaxbDataFormat("org.apache.camel.foo.bar"))
+                            .to("mock:result");
+
+                    from("direct:getJAXBElement")
+                            .unmarshal(dataFormat)
+                            .to("mock:result");
+
+                    from("direct:unmarshalFilteringEnabled")
+                            .unmarshal(filterEnabledFormat)
+                            .to("mock:result");
+
+                    from("direct:marshal")
+                            .marshal(dataFormat)
+                            .to("mock:result");
+
+                    from("direct:marshalWithoutContentType")
+                            .marshal(dataFormatWithoutContentType)
+                            .to("mock:result");
+
+                    from("direct:marshalFilteringEnabled")
+                            .marshal(filterEnabledFormat)
+                            .to("mock:result");
+
+                    from("direct:marshalCustomWriter")
+                            .marshal(customWriterFormat)
+                            .to("mock:result");
+                    from("direct:marshalCustomWriterAndFiltering")
+                            .marshal(customWriterAndFilterFormat)
+                            .to("mock:result");
+
+                    from("direct:unmarshall")
+                            .unmarshal()
+                            .jaxb(PersonType.class.getPackage().getName())
+                            .to("mock:result");
+
+                }
+            };
+            
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/ConcurrentJaxbDataFormatSchemaValidationTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/ConcurrentJaxbDataFormatSchemaValidationTest.java
new file mode 100644
index 0000000..31e97e1
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/ConcurrentJaxbDataFormatSchemaValidationTest.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.converter.jaxb.springboot;
+
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.converter.jaxb.address.Address;
+import org.apache.camel.converter.jaxb.person.Person;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        ConcurrentJaxbDataFormatSchemaValidationTest.class,
+        ConcurrentJaxbDataFormatSchemaValidationTest.TestConfiguration.class
+    }
+)
+public class ConcurrentJaxbDataFormatSchemaValidationTest {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(ConcurrentJaxbDataFormatSchemaValidationTest.class);
+
+    private int testCount = 1000;
+    private int concurrencyLevel = 10;
+        
+    @Autowired
+    ProducerTemplate template;
+    
+    @Autowired
+    CamelContext context;
+
+    
+    @EndpointInject("mock:marshall")
+    private MockEndpoint mockMarshall;
+
+    @EndpointInject("mock:unmarshall")
+    private MockEndpoint mockUnmarshall;
+
+
+    @Test
+    public void concurrentMarshallSuccess() throws Exception {
+        mockMarshall.expectedMessageCount(testCount);
+
+        Address address = new Address();
+        address.setAddressLine1("Hauptstr. 1; 01129 Entenhausen");
+        Person person = new Person();
+        person.setFirstName("Christian");
+        person.setLastName("Mueller");
+        person.setAge(Integer.valueOf(36));
+        person.setAddress(address);
+
+        long start = System.currentTimeMillis();
+        for (int i = 0; i < testCount; i++) {
+            template.sendBody("seda:marshall", person);
+        }
+
+        mockMarshall.assertIsSatisfied();
+        LOG.info("Validation of {} messages took {} ms", testCount, System.currentTimeMillis() - start);
+
+        String payload = mockMarshall.getExchanges().get(0).getIn().getBody(String.class);
+        LOG.info(payload);
+
+        assertTrue(payload.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"));
+        assertTrue(payload.contains(
+                "<person xmlns=\"person.jaxb.converter.camel.apache.org\" xmlns:ns2=\"address.jaxb.converter.camel.apache.org\">"));
+        assertTrue(payload.contains("<firstName>Christian</firstName>"));
+        assertTrue(payload.contains("<lastName>Mueller</lastName>"));
+        assertTrue(payload.contains("<age>36</age>"));
+        assertTrue(payload.contains("<address>"));
+        assertTrue(payload.contains("<ns2:addressLine1>Hauptstr. 1; 01129 Entenhausen</ns2:addressLine1>"));
+        assertTrue(payload.contains("</address>"));
+        assertTrue(payload.contains("</person>"));
+    }
+
+    @Test
+    public void concurrentUnmarshall() throws Exception {
+        mockUnmarshall.expectedMessageCount(testCount);
+
+        String xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>")
+                .append("<person xmlns=\"person.jaxb.converter.camel.apache.org\" xmlns:ns2=\"address.jaxb.converter.camel.apache.org\">")
+                .append("<firstName>Christian</firstName>")
+                .append("<lastName>Mueller</lastName>")
+                .append("<age>36</age>")
+                .append("<address>")
+                .append("<ns2:addressLine1>Hauptstr. 1; 01129 Entenhausen</ns2:addressLine1>")
+                .append("</address>")
+                .append("</person>")
+                .toString();
+
+        long start = System.currentTimeMillis();
+        for (int i = 0; i < testCount; i++) {
+            template.sendBody("seda:unmarshall", xml);
+        }
+
+        MockEndpoint.assertIsSatisfied(context, 20, TimeUnit.SECONDS);
+        LOG.info("Validation of {} messages took {} ms", testCount, System.currentTimeMillis() - start);
+
+        Person person = mockUnmarshall.getExchanges().get(0).getIn().getBody(Person.class);
+
+        assertEquals("Christian", person.getFirstName());
+        assertEquals("Mueller", person.getLastName());
+        assertEquals(Integer.valueOf(36), person.getAge());
+    }
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
+                    jaxbDataFormat.setContextPath(Person.class.getPackage().getName());
+                    jaxbDataFormat.setSchema("classpath:person.xsd,classpath:address.xsd");
+
+                    from("seda:marshall?concurrentConsumers=" + concurrencyLevel)
+                            .marshal(jaxbDataFormat)
+                            .to("mock:marshall");
+
+                    from("seda:unmarshall?concurrentConsumers=" + concurrencyLevel)
+                            .unmarshal(jaxbDataFormat)
+                            .to("mock:unmarshall");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/DataFormatComponentTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/DataFormatComponentTest.java
new file mode 100644
index 0000000..64e00f4
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/DataFormatComponentTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        DataFormatComponentTest.class,
+        DataFormatComponentTest.TestConfiguration.class
+    }
+)
+public class DataFormatComponentTest extends DataFormatTest {
+    
+    
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:start").to("dataformat:jaxb:marshal?contextPath=org.apache.camel.example").to("direct:marshalled");
+
+                    from("direct:marshalled").to("dataformat:jaxb:unmarshal?contextPath=org.apache.camel.example")
+                            .to("mock:result");
+
+                    from("direct:prettyPrint").to("dataformat:jaxb:marshal?contextPath=org.apache.camel.foo.bar&prettyPrint=true")
+                            .to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/DataFormatTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/DataFormatTest.java
new file mode 100644
index 0000000..a0babc3
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/DataFormatTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.example.PurchaseOrder;
+import org.apache.camel.foo.bar.PersonType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        DataFormatTest.class,
+        DataFormatTest.TestConfiguration.class
+    }
+)
+public class DataFormatTest {
+    
+            
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:result")
+    private MockEndpoint resultEndpoint;
+
+    @EndpointInject("mock:unmarshall")
+    private MockEndpoint mockUnmarshall;
+
+    
+    
+
+    @Test
+    public void testMarshalThenUnmarshalBean() throws Exception {
+        resultEndpoint.reset();
+        PurchaseOrder bean = new PurchaseOrder();
+        bean.setName("Beer");
+        bean.setAmount(23);
+        bean.setPrice(2.5);
+
+        resultEndpoint.expectedBodiesReceived(bean);
+
+        template.sendBody("direct:start", bean);
+
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    @Test
+    public void testMarshalPrettyPrint() throws Exception {
+        resultEndpoint.reset();
+        
+        PersonType person = new PersonType();
+        person.setFirstName("Willem");
+        person.setLastName("Jiang");
+        resultEndpoint.expectedMessageCount(1);
+
+        template.sendBody("direct:prettyPrint", person);
+
+        resultEndpoint.assertIsSatisfied();
+
+        Exchange exchange = resultEndpoint.getExchanges().get(0);
+
+        String result = exchange.getIn().getBody(String.class);
+        assertNotNull("The result should not be null", result);
+        int indexPerson = result.indexOf("<Person>");
+        int indexFirstName = result.indexOf("<firstName>");
+
+        assertTrue(indexPerson > 0, "we should find the <Person>");
+        assertTrue(indexFirstName > 0, "we should find the <firstName>");
+        assertTrue(indexFirstName - indexPerson > 8, "There should some sapce between <Person> and <firstName>");
+    }
+
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+
+                    JaxbDataFormat example = new JaxbDataFormat("org.apache.camel.example");
+                    JaxbDataFormat person = new JaxbDataFormat("org.apache.camel.foo.bar");
+                    person.setPrettyPrint(true);
+
+                    from("direct:start").marshal(example).to("direct:marshalled");
+
+                    from("direct:marshalled").unmarshal().jaxb("org.apache.camel.example").to("mock:result");
+
+                    from("direct:prettyPrint").marshal(person).to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/DirectBeanToBeanPersonTypeTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/DirectBeanToBeanPersonTypeTest.java
new file mode 100644
index 0000000..86946f6
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/DirectBeanToBeanPersonTypeTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.foo.bar.PersonType;
+import org.apache.camel.jaxb.MyPersonService;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        DirectBeanToBeanPersonTypeTest.class,
+        DirectBeanToBeanPersonTypeTest.TestConfiguration.class
+    }
+)
+public class DirectBeanToBeanPersonTypeTest {
+    
+    
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:person")
+    private MockEndpoint mock;
+
+    @Test
+    public void testBeanToBean() throws Exception {
+        mock.expectedMessageCount(1);
+        mock.message(0).body().isInstanceOf(PersonType.class);
+
+        template.sendBody("direct:start", null);
+
+        mock.assertIsSatisfied();
+    }
+
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:start")
+                            .bean(MyPersonService.class, "createPerson")
+                            .bean(MyPersonService.class, "sendPerson");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/ExplicitEncodingAndXMLCharFilteringTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/ExplicitEncodingAndXMLCharFilteringTest.java
new file mode 100644
index 0000000..00f1c53
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/ExplicitEncodingAndXMLCharFilteringTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.example.PurchaseOrder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        ExplicitEncodingAndXMLCharFilteringTest.class,
+        ExplicitEncodingAndXMLCharFilteringTest.TestConfiguration.class
+    }
+)
+public class ExplicitEncodingAndXMLCharFilteringTest extends FromFileBase {
+    
+    
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:file")
+    private MockEndpoint result;
+
+    @EndpointInject("mock:unmarshall")
+    private MockEndpoint mockUnmarshall;
+
+
+    @Test
+    public void testIsoAndCharacterFiltering() throws Exception {
+        PurchaseOrder order = new PurchaseOrder();
+        //Data containing characters ÆØÅæøå that differ in utf-8 and iso + a spouting whale
+        String name = "\u00c6\u00d8\u00C5\u00e6\u00f8\u00e5\uD83D\uDC33\uFFFD";
+        String expected = "\u00c6\u00d8\u00C5\u00e6\u00f8\u00e5  \uFFFD"; //Spouting whale has become spaces
+        order.setName(name);
+        order.setAmount(123.45);
+        order.setPrice(2.22);
+
+        result.expectedFileExists(testFile("output.xml"));
+
+        template.sendBody("direct:start", order);
+        result.assertIsSatisfied();
+
+        JAXBContext jaxbContext = JAXBContext.newInstance("org.apache.camel.example");
+        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+        InputStream inputStream = new FileInputStream(testFile("output.xml").toFile());
+        Reader reader = new InputStreamReader(inputStream, StandardCharsets.ISO_8859_1);
+        PurchaseOrder obj = (PurchaseOrder) unmarshaller.unmarshal(reader);
+        assertEquals(expected, obj.getName());
+    }
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    JaxbDataFormat jaxb = new JaxbDataFormat("org.apache.camel.example");
+                    jaxb.setFilterNonXmlChars(true);
+                    jaxb.setEncoding("iso-8859-1");
+
+                    from("direct:start")
+                            .marshal(jaxb)
+                            .to(fileUri("?fileName=output.xml&charset=iso-8859-1"));
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/ExplicitFileEncodingTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/ExplicitFileEncodingTest.java
new file mode 100644
index 0000000..4fd252d
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/ExplicitFileEncodingTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.example.PurchaseOrder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        ExplicitFileEncodingTest.class,
+        ExplicitFileEncodingTest.TestConfiguration.class
+    }
+)
+public class ExplicitFileEncodingTest extends FromFileBase {
+    
+    
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:file")
+    private MockEndpoint result;
+
+        
+    @Test
+    public void testISOFileEncoding() throws Exception {
+        PurchaseOrder order = new PurchaseOrder();
+        //Data containing characters ÆØÅæøå that differ in utf-8 and iso
+        String name = "\u00c6\u00d8\u00C5\u00e6\u00f8\u00e5";
+        order.setName(name);
+        order.setAmount(123.45);
+        order.setPrice(2.22);
+
+        
+        result.expectedFileExists(testFile("output.txt"));
+
+        template.sendBody("direct:start", order);
+        result.assertIsSatisfied();
+
+        JAXBContext jaxbContext = JAXBContext.newInstance("org.apache.camel.example");
+        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+        PurchaseOrder obj = (PurchaseOrder) unmarshaller.unmarshal(testFile("output.txt").toFile());
+        assertEquals(obj.getName(), name);
+    }
+
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    JaxbDataFormat jaxb = new JaxbDataFormat("org.apache.camel.example");
+                    jaxb.setEncoding("iso-8859-1");
+
+                    from("direct:start")
+                            .marshal(jaxb)
+                            .to(fileUri("?fileName=output.txt&charset=iso-8859-1"));
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/FallbackTypeConverterShouldThrowExceptionTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/FallbackTypeConverterShouldThrowExceptionTest.java
new file mode 100644
index 0000000..ad44b81
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/FallbackTypeConverterShouldThrowExceptionTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.TypeConversionException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.example.Bar;
+import org.apache.camel.example.Foo;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        FallbackTypeConverterShouldThrowExceptionTest.class,
+        FallbackTypeConverterShouldThrowExceptionTest.TestConfiguration.class
+    }
+)
+public class FallbackTypeConverterShouldThrowExceptionTest {
+    
+    
+        
+    @Autowired
+    ProducerTemplate template;
+    
+    @Autowired
+    CamelContext context;
+
+    
+    @EndpointInject("mock:a")
+    private MockEndpoint mockA;
+
+    @EndpointInject("mock:b")
+    private MockEndpoint mockB;
+
+    
+    private static AtomicInteger failed = new AtomicInteger();
+    private static AtomicInteger failed2 = new AtomicInteger();
+    
+    @BeforeEach
+    public void setup() {
+        failed = new AtomicInteger();
+        failed2 = new AtomicInteger();
+    }
+    
+    @Test
+    public void testJaxbModel() throws Exception {
+        MockEndpoint.resetMocks(context);
+        Object foo = new Foo();
+        mockA.expectedBodiesReceived(foo);
+        mockB.expectedBodiesReceived(foo);
+
+        template.sendBody("direct:a", foo);
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        assertEquals(0, failed.get());
+        assertEquals(0, failed2.get());
+    }
+
+    @Test
+    public void testNoneJaxbModel() throws Exception {
+        MockEndpoint.resetMocks(context);
+        Object camel = "Camel";
+        mockA.expectedBodiesReceived(camel);
+        mockB.expectedBodiesReceived(camel);
+
+        template.sendBody("direct:a", camel);
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        assertEquals(1, failed.get());
+        assertEquals(0, failed2.get());
+    }
+
+    @Test
+    public void testAnotherJaxbModel() throws Exception {
+        MockEndpoint.resetMocks(context);
+        Object bar = new Bar();
+        mockA.expectedBodiesReceived(bar);
+        mockB.expectedBodiesReceived(bar);
+
+        template.sendBody("direct:a", bar);
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        assertEquals(1, failed.get());
+        assertEquals(0, failed2.get());
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:a").process(new Processor() {
+                        @Override
+                        public void process(Exchange exchange) throws Exception {
+                            try {
+                                exchange.getIn().getBody(Foo.class);
+                            } catch (TypeConversionException e) {
+                                failed.incrementAndGet();
+                            }
+                        }
+                    }).to("mock:a").process(new Processor() {
+                        @Override
+                        public void process(Exchange exchange) throws Exception {
+                            try {
+                                exchange.getIn().getBody(List.class);
+                            } catch (TypeConversionException e) {
+                                // there is no type converters from the POJO -> List
+                                // so we should really not fail at all at this point
+                                failed2.incrementAndGet();
+                            }
+                        }
+
+                    }).to("mock:b");
+                }
+
+            };
+            
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/FromFileBase.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/FromFileBase.java
new file mode 100644
index 0000000..5eef1ae
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/FromFileBase.java
@@ -0,0 +1,73 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+import static org.apache.camel.test.junit5.TestSupport.deleteDirectory;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class FromFileBase {
+    
+    private boolean testDirectoryCleaned;
+    
+    protected String fileUri() {
+        return "file:" + testDirectory();
+    }
+    
+    protected String fileUri(String query) {
+        return "file:" + testDirectory() + (query.startsWith("?") ? "" : "/") + query;
+    }
+    
+    protected Path testDirectory() {
+        return testDirectory(false);
+    }
+
+    protected Path testDirectory(boolean create) {
+        Class<?> testClass = getClass();
+        return testDirectory(testClass, create);
+    }
+
+    
+    
+    protected static Path testDirectory(Class<?> testClass, boolean create) {
+        Path dir = Paths.get("target", "data", testClass.getSimpleName());
+        if (create) {
+            try {
+                Files.createDirectories(dir);
+            } catch (IOException e) {
+                throw new IllegalStateException("Unable to create test directory: " + dir, e);
+            }
+        }
+        return dir;
+    }
+    
+    protected Path testFile(String dir) {
+        return testDirectory().resolve(dir);
+    }
+    
+    public void deleteTestDirectory() {
+        if (!testDirectoryCleaned) {
+            deleteDirectory(testDirectory());
+            testDirectoryCleaned = true;
+        }
+    }
+    
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbConcurrentDataFormatTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbConcurrentDataFormatTest.java
new file mode 100644
index 0000000..8f19100
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbConcurrentDataFormatTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+import static org.apache.camel.test.junit5.TestSupport.body;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.example.PurchaseOrder;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        JaxbConcurrentDataFormatTest.class,
+        JaxbConcurrentDataFormatTest.TestConfiguration.class
+    }
+)
+public class JaxbConcurrentDataFormatTest {
+    
+            
+    @Autowired
+    ProducerTemplate template;
+
+    
+    
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    
+    @Test
+    public void testNoConcurrentProducers() throws Exception {
+        doSendMessages(1, 1);
+    }
+
+    @Test
+    public void testConcurrentProducers() throws Exception {
+        doSendMessages(10, 5);
+    }
+
+    private void doSendMessages(int files, int poolSize) throws Exception {
+        result.reset();
+        result.expectedMessageCount(files);
+        result.assertNoDuplicates(body());
+
+        ExecutorService executor = Executors.newFixedThreadPool(poolSize);
+        for (int i = 0; i < files; i++) {
+            final int index = i;
+            executor.submit(new Callable<Object>() {
+                public Object call() throws Exception {
+                    PurchaseOrder bean = new PurchaseOrder();
+                    bean.setName("Beer");
+                    bean.setAmount(Double.valueOf("" + index));
+                    bean.setPrice(Double.valueOf("" + index) * 2);
+
+                    template.sendBody("direct:start", bean);
+                    return null;
+                }
+            });
+        }
+
+        result.assertIsSatisfied();
+        executor.shutdownNow();
+    }
+
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    DataFormat jaxb = new JaxbDataFormat("org.apache.camel.example");
+
+                    from("direct:start").marshal(jaxb).to("direct:marshalled");
+
+                    from("direct:marshalled").unmarshal(jaxb).to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatMultipleNamespacesTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatMultipleNamespacesTest.java
new file mode 100644
index 0000000..a5ff37a
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatMultipleNamespacesTest.java
@@ -0,0 +1,150 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+import javax.xml.bind.JAXBContext;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.example.Address;
+import org.apache.camel.example.Order;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        JaxbDataFormatMultipleNamespacesTest.class,
+        JaxbDataFormatMultipleNamespacesTest.TestConfiguration.class
+    }
+)
+public class JaxbDataFormatMultipleNamespacesTest {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(JaxbDataFormatMultipleNamespacesTest.class);
+
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:marshall")
+    private MockEndpoint mockMarshall;
+
+    @EndpointInject("mock:unmarshall")
+    private MockEndpoint mockUnmarshall;
+
+    @Test
+    public void testMarshallMultipleNamespaces() throws Exception {
+        mockMarshall.expectedMessageCount(1);
+
+        Order order = new Order();
+        order.setId("1");
+        Address address = new Address();
+        address.setStreet("Main Street");
+        address.setStreetNumber("3a");
+        address.setZip("65843");
+        address.setCity("Sulzbach");
+        order.setAddress(address);
+        template.sendBody("direct:marshall", order);
+
+        mockMarshall.assertIsSatisfied();
+
+        String payload = mockMarshall.getExchanges().get(0).getIn().getBody(String.class);
+        LOG.info(payload);
+
+        assertTrue(payload.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"));
+        assertTrue(payload.contains("<order:order"));
+        assertTrue(payload.contains("<order:id>1</order:id>"));
+        assertTrue(payload.contains("<address:address>"));
+        assertTrue(payload.contains("<address:street>Main Street</address:street>"));
+        assertTrue(payload.contains("<address:streetNumber>3a</address:streetNumber>"));
+        assertTrue(payload.contains("<address:zip>65843</address:zip>"));
+        assertTrue(payload.contains("<address:city>Sulzbach</address:city>"));
+        assertTrue(payload.contains("</address:address>"));
+        assertTrue(payload.contains("</order:order>"));
+
+        // the namespaces
+        assertTrue(payload.contains("xmlns:address=\"http://www.camel.apache.org/jaxb/example/address/1\""));
+        assertTrue(payload.contains("xmlns:order=\"http://www.camel.apache.org/jaxb/example/order/1\""));
+    }
+
+    @Test
+    public void testUnarshallMultipleNamespaces() throws Exception {
+        mockUnmarshall.expectedMessageCount(1);
+
+        String payload
+                = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><ns1:order xmlns:ns2=\"http://www.camel.apache.org/jaxb/example/address/1\""
+                  + " xmlns:ns1=\"http://www.camel.apache.org/jaxb/example/order/1\"><ns1:id>1</ns1:id><ns2:address><ns2:street>Main Street</ns2:street>"
+                  + "<ns2:streetNumber>3a</ns2:streetNumber><ns2:zip>65843</ns2:zip><ns2:city>Sulzbach</ns2:city></ns2:address></ns1:order>";
+        template.sendBody("direct:unmarshall", payload);
+
+        mockUnmarshall.assertIsSatisfied();
+
+        Order order = (Order) mockUnmarshall.getExchanges().get(0).getIn().getBody();
+        Address address = order.getAddress();
+        assertEquals("1", order.getId());
+        assertEquals("Main Street", address.getStreet());
+        assertEquals("3a", address.getStreetNumber());
+        assertEquals("65843", address.getZip());
+        assertEquals("Sulzbach", address.getCity());
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    JaxbDataFormat jaxbDataFormat = new JaxbDataFormat(JAXBContext.newInstance(Order.class, Address.class));
+
+                    from("direct:marshall")
+                            .marshal(jaxbDataFormat)
+                            .to("mock:marshall");
+
+                    from("direct:unmarshall")
+                            .unmarshal(jaxbDataFormat)
+                            .to("mock:unmarshall");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatPartClassHeaderTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatPartClassHeaderTest.java
new file mode 100644
index 0000000..b98db57
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatPartClassHeaderTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+import javax.xml.namespace.QName;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbConstants;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.example.Address;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        JaxbDataFormatPartClassHeaderTest.class,
+        JaxbDataFormatPartClassHeaderTest.TestConfiguration.class
+    }
+)
+public class JaxbDataFormatPartClassHeaderTest {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(JaxbDataFormatPartClassHeaderTest.class);
+
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:marshall")
+    private MockEndpoint mockMarshall;
+
+
+
+    @Test
+    public void testMarshallIfPartClassSetInHeaders() throws Exception {
+        mockMarshall.expectedMessageCount(1);
+
+        Address address = new Address();
+        address.setStreet("Main Street");
+        address.setStreetNumber("3a");
+        address.setZip("65843");
+        address.setCity("Sulzbach");
+        template.sendBody("direct:marshall", address);
+
+        mockMarshall.assertIsSatisfied();
+
+        String payload = mockMarshall.getExchanges().get(0).getIn().getBody(String.class);
+        LOG.info(payload);
+
+        assertTrue(payload.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"));
+        assertTrue(payload.contains("<address:address"));
+        assertTrue(payload.contains("<address:street>Main Street</address:street>"));
+        assertTrue(payload.contains("<address:streetNumber>3a</address:streetNumber>"));
+        assertTrue(payload.contains("<address:zip>65843</address:zip>"));
+        assertTrue(payload.contains("<address:city>Sulzbach</address:city>"));
+        assertTrue(payload.contains("</address:address>"));
+
+        // the namespaces
+        assertTrue(payload.contains("xmlns:address=\"http://www.camel.apache.org/jaxb/example/address/1\""));
+        assertTrue(payload.contains("xmlns:order=\"http://www.camel.apache.org/jaxb/example/order/1\""));
+    }
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
+                    jaxbDataFormat.setContextPath(Address.class.getPackage().getName());
+                    jaxbDataFormat.setPartNamespace(
+                            new QName("http://www.camel.apache.org/jaxb/example/address/123", "addressToBeOverriden"));
+                    jaxbDataFormat.setPrettyPrint(true);
+
+                    from("direct:marshall")
+                            .setHeader(JaxbConstants.JAXB_PART_CLASS, simple("org.apache.camel.example.Address"))
+                            .setHeader(JaxbConstants.JAXB_PART_NAMESPACE,
+                                    simple("{http://www.camel.apache.org/jaxb/example/address/1}address"))
+                            .marshal(jaxbDataFormat)
+                            .to("mock:marshall");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatPartClassTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatPartClassTest.java
new file mode 100644
index 0000000..a9e8829
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatPartClassTest.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.converter.jaxb.springboot;
+
+
+import javax.xml.namespace.QName;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.example.Address;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        JaxbDataFormatPartClassTest.class,
+        JaxbDataFormatPartClassTest.TestConfiguration.class
+    }
+)
+public class JaxbDataFormatPartClassTest {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(JaxbDataFormatPartClassTest.class);
+
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:marshall")
+    private MockEndpoint mockMarshall;
+
+
+
+    
+    @Test
+    public void testMarshallMultipleNamespaces() throws Exception {
+        mockMarshall.expectedMessageCount(1);
+
+        Address address = new Address();
+        address.setStreet("Main Street");
+        address.setStreetNumber("3a");
+        address.setZip("65843");
+        address.setCity("Sulzbach");
+        template.sendBody("direct:marshall", address);
+
+        mockMarshall.assertIsSatisfied();
+
+        String payload = mockMarshall.getExchanges().get(0).getIn().getBody(String.class);
+        LOG.info(payload);
+
+        assertTrue(payload.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"));
+        assertTrue(payload.contains("<address:address"));
+        assertTrue(payload.contains("<address:street>Main Street</address:street>"));
+        assertTrue(payload.contains("<address:streetNumber>3a</address:streetNumber>"));
+        assertTrue(payload.contains("<address:zip>65843</address:zip>"));
+        assertTrue(payload.contains("<address:city>Sulzbach</address:city>"));
+        assertTrue(payload.contains("</address:address>"));
+
+        // the namespaces
+        assertTrue(payload.contains("xmlns:address=\"http://www.camel.apache.org/jaxb/example/address/1\""));
+        assertTrue(payload.contains("xmlns:order=\"http://www.camel.apache.org/jaxb/example/order/1\""));
+    }
+
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
+                    jaxbDataFormat.setContextPath(Address.class.getPackage().getName());
+                    jaxbDataFormat.setPartClass(Address.class);
+                    jaxbDataFormat.setPartNamespace(new QName("http://www.camel.apache.org/jaxb/example/address/1", "address"));
+                    jaxbDataFormat.setPrettyPrint(true);
+
+                    from("direct:marshall")
+                            .marshal(jaxbDataFormat)
+                            .to("mock:marshall");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatSchemaValidationTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatSchemaValidationTest.java
new file mode 100644
index 0000000..b67f323
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatSchemaValidationTest.java
@@ -0,0 +1,189 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+import static org.apache.camel.test.junit5.TestSupport.assertIsInstanceOf;
+
+import java.io.IOException;
+
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.converter.jaxb.address.Address;
+import org.apache.camel.converter.jaxb.person.Person;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        JaxbDataFormatSchemaValidationTest.class,
+        JaxbDataFormatSchemaValidationTest.TestConfiguration.class
+    }
+)
+public class JaxbDataFormatSchemaValidationTest {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(JaxbDataFormatSchemaValidationTest.class);
+
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:marshall")
+    private MockEndpoint mockMarshall;
+
+    @EndpointInject("mock:unmarshall")
+    private MockEndpoint mockUnmarshall;
+
+
+    @Test
+    public void testMarshallSuccess() throws Exception {
+        mockMarshall.expectedMessageCount(1);
+
+        Address address = new Address();
+        address.setAddressLine1("Hauptstr. 1; 01129 Entenhausen");
+        Person person = new Person();
+        person.setFirstName("Christian");
+        person.setLastName("Mueller");
+        person.setAge(Integer.valueOf(36));
+        person.setAddress(address);
+
+        template.sendBody("direct:marshall", person);
+
+        mockMarshall.assertIsSatisfied();
+
+        String payload = mockMarshall.getExchanges().get(0).getIn().getBody(String.class);
+        LOG.info(payload);
+
+        assertTrue(payload.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"));
+        assertTrue(payload.contains(
+                "<person xmlns=\"person.jaxb.converter.camel.apache.org\" xmlns:ns2=\"address.jaxb.converter.camel.apache.org\">"));
+        assertTrue(payload.contains("<firstName>Christian</firstName>"));
+        assertTrue(payload.contains("<lastName>Mueller</lastName>"));
+        assertTrue(payload.contains("<age>36</age>"));
+        assertTrue(payload.contains("<address>"));
+        assertTrue(payload.contains("<ns2:addressLine1>Hauptstr. 1; 01129 Entenhausen</ns2:addressLine1>"));
+        assertTrue(payload.contains("</address>"));
+        assertTrue(payload.contains("</person>"));
+    }
+
+    @Test
+    public void testMarshallWithValidationException() {
+        Person person = new Person();
+
+        Exception ex = assertThrows(CamelExecutionException.class,
+                () -> template.sendBody("direct:marshall", person));
+
+        Throwable cause = ex.getCause();
+        assertIsInstanceOf(IOException.class, cause);
+        assertTrue(cause.getMessage().contains("javax.xml.bind.MarshalException"));
+        assertTrue(cause.getMessage().contains("org.xml.sax.SAXParseException"));
+        assertTrue(cause.getMessage().contains("cvc-complex-type.2.4.a"));
+    }
+
+    @Test
+    public void testUnmarshallSuccess() throws Exception {
+        mockUnmarshall.expectedMessageCount(1);
+
+        String xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>")
+                .append("<person xmlns=\"person.jaxb.converter.camel.apache.org\" xmlns:ns2=\"address.jaxb.converter.camel.apache.org\">")
+                .append("<firstName>Christian</firstName>")
+                .append("<lastName>Mueller</lastName>")
+                .append("<age>36</age>")
+                .append("<address>")
+                .append("<ns2:addressLine1>Hauptstr. 1; 01129 Entenhausen</ns2:addressLine1>")
+                .append("</address>")
+                .append("</person>")
+                .toString();
+        template.sendBody("direct:unmarshall", xml);
+
+        mockUnmarshall.assertIsSatisfied();
+
+        Person person = mockUnmarshall.getExchanges().get(0).getIn().getBody(Person.class);
+
+        assertEquals("Christian", person.getFirstName());
+        assertEquals("Mueller", person.getLastName());
+        assertEquals(Integer.valueOf(36), person.getAge());
+    }
+
+    @Test
+    public void testUnmarshallWithValidationException() throws Exception {
+        String xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>")
+                .append("<person xmlns=\"person.jaxb.converter.camel.apache.org\" />")
+                .toString();
+
+        Exception ex = assertThrows(CamelExecutionException.class,
+                () -> template.sendBody("direct:unmarshall", xml));
+
+        Throwable cause = ex.getCause();
+        assertIsInstanceOf(IOException.class, cause);
+        assertTrue(cause.getMessage().contains("javax.xml.bind.UnmarshalException"));
+        assertTrue(cause.getMessage().contains("org.xml.sax.SAXParseException"));
+        assertTrue(cause.getMessage().contains("cvc-complex-type.2.4.b"));
+    }
+
+    
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
+                    jaxbDataFormat.setContextPath(Person.class.getPackage().getName());
+                    jaxbDataFormat.setSchema("classpath:person.xsd,classpath:address.xsd");
+
+                    from("direct:marshall")
+                            .marshal(jaxbDataFormat)
+                            .to("mock:marshall");
+
+                    from("direct:unmarshall")
+                            .unmarshal(jaxbDataFormat)
+                            .to("mock:unmarshall");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatSchemaValidationWithObjectFactoryTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatSchemaValidationWithObjectFactoryTest.java
new file mode 100644
index 0000000..292e9ae
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbDataFormatSchemaValidationWithObjectFactoryTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+import static org.apache.camel.test.junit5.TestSupport.assertIsInstanceOf;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.converter.jaxb.message.Message;
+import org.apache.camel.converter.jaxb.message.ObjectFactory;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        JaxbDataFormatSchemaValidationWithObjectFactoryTest.class,
+        JaxbDataFormatSchemaValidationWithObjectFactoryTest.TestConfiguration.class
+    }
+)
+public class JaxbDataFormatSchemaValidationWithObjectFactoryTest {
+    
+    
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:marshall")
+    private MockEndpoint mockMarshall;
+
+    @EndpointInject("mock:unmarshall")
+    private MockEndpoint mockUnmarshall;
+
+    private JAXBContext jbCtx;
+    
+    @BeforeEach
+    public void setUp() throws Exception {
+
+
+        XmlRootElement xmlRootElementAnnotation = Message.class.getAnnotation(XmlRootElement.class);
+        assertNull(xmlRootElementAnnotation);
+
+        jbCtx = JAXBContext.newInstance(Message.class);
+    }
+
+    @Test
+    public void testMarshallOfNonRootElementWithValidationException() {
+        Message message = new Message();
+        Exception ex = Assertions.assertThrows(CamelExecutionException.class,
+                () -> template.sendBody("direct:marshall", message));
+
+        Throwable cause = ex.getCause();
+        assertIsInstanceOf(IOException.class, cause);
+        assertTrue(cause.getMessage().contains("javax.xml.bind.MarshalException"));
+        assertTrue(cause.getMessage().contains("org.xml.sax.SAXParseException"));
+        assertTrue(cause.getMessage().contains("cvc-complex-type.2.4.b"));
+    }
+
+    @Test
+    public void testUnmarshallOfNonRootWithValidationException() throws Exception {
+        JAXBElement<Message> message = new ObjectFactory().createMessage(new Message());
+
+        String xml;
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+            jbCtx.createMarshaller().marshal(message, baos);
+            xml = new String(baos.toByteArray(), "UTF-8");
+        }
+
+        Exception ex = Assertions.assertThrows(CamelExecutionException.class,
+                () -> template.sendBody("direct:unmarshall", xml));
+
+        Throwable cause = ex.getCause();
+        assertIsInstanceOf(IOException.class, cause);
+        assertTrue(cause.getMessage().contains("javax.xml.bind.UnmarshalException"));
+        assertTrue(cause.getMessage().contains("org.xml.sax.SAXParseException"));
+        assertTrue(cause.getMessage().contains("cvc-complex-type.2.4.b"));
+    }
+
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    JaxbDataFormat jaxbDataFormat = new JaxbDataFormat();
+                    jaxbDataFormat.setContextPath(Message.class.getPackage().getName());
+                    jaxbDataFormat.setSchema("classpath:message.xsd");
+                    // if the following is removed the lookup of an object factory method which can create the element
+                    // won't be done and the object won'T get marshalled
+                    jaxbDataFormat.setObjectFactory(true);
+
+                    from("direct:marshall")
+                            .marshal(jaxbDataFormat)
+                            .to("mock:marshall");
+
+                    from("direct:unmarshall")
+                            .unmarshal(jaxbDataFormat)
+                            .to("mock:unmarshall");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbErrorLogTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbErrorLogTest.java
new file mode 100644
index 0000000..7f42175
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/JaxbErrorLogTest.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.converter.jaxb.springboot;
+
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.Body;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Handler;
+import org.apache.camel.Message;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        JaxbErrorLogTest.class,
+        JaxbErrorLogTest.TestConfiguration.class
+    }
+)
+public class JaxbErrorLogTest {
+    
+    
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:end")
+    private MockEndpoint mock;
+
+
+    
+    @Test
+    public void testErrorHandling() throws Exception {
+        // the 2nd message is set to fail, but the 4 others should be routed
+        mock.expectedMessageCount(4);
+
+        // FailingBean will cause message at index 2 to throw exception
+        for (int i = 0; i < 5; i++) {
+            CannotMarshal obj = new CannotMarshal(i);
+            template.send("seda:test", exchange -> {
+                Message in = exchange.getIn();
+                in.setBody(obj);
+            });
+            
+        }
+
+        mock.assertIsSatisfied();
+    }
+
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("seda:test")
+                            .bean(new FailingBean())
+                            .to("log:end", "mock:end");
+                }
+            };
+        }
+    }
+    
+    public static final class FailingBean {
+        @Handler
+        public void handle(@Body CannotMarshal body) {
+            if (body.getMessageNo() == 2) {
+                // fail on second message
+                throw new RuntimeCamelException("Kaboom");
+            }
+        }
+    }
+
+    /**
+     * This class will throw RuntimeException on JAXB marshal
+     */
+    @XmlRootElement
+    public static final class CannotMarshal {
+
+        private int messageNo;
+
+        public CannotMarshal() {
+        }
+
+        public CannotMarshal(int messageNo) {
+            this.messageNo = messageNo;
+        }
+
+        public int getMessageNo() {
+            return messageNo;
+        }
+
+        public void setMessageNo(int messageNo) {
+            this.messageNo = messageNo;
+        }
+
+        public void setUhoh(String name) {
+        }
+
+        public String getUhoh() {
+            throw new RuntimeCamelException("Can't marshal this");
+        }
+
+        @Override
+        public String toString() {
+            return "MessageNo. " + messageNo;
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/RouteWithErrorHandlerTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/RouteWithErrorHandlerTest.java
new file mode 100644
index 0000000..592f640
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/RouteWithErrorHandlerTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.example.InvalidOrderException;
+import org.apache.camel.example.PurchaseOrder;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        RouteWithErrorHandlerTest.class,
+        RouteWithErrorHandlerTest.TestConfiguration.class
+    }
+)
+public class RouteWithErrorHandlerTest {
+    
+    @Autowired
+    CamelContext context;
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:wine")
+    private MockEndpoint mockWine;
+
+    @EndpointInject("mock:invalid")
+    private MockEndpoint mockInvalid;
+    
+    @EndpointInject("mock:result")
+    private MockEndpoint mockResult;
+    
+    @EndpointInject("mock:error")
+    private MockEndpoint mockError;
+
+    
+    @Test
+    public void testOk() throws Exception {
+        MockEndpoint.resetMocks(context);
+        PurchaseOrder order = new PurchaseOrder();
+        order.setName("Wine");
+        order.setAmount(123.45);
+        order.setPrice(2.22);
+
+        
+        mockWine.expectedBodiesReceived(order);
+
+        template.sendBody("direct:start", "<purchaseOrder name='Wine' amount='123.45' price='2.22'/>");
+
+        mockWine.assertIsSatisfied();
+    }
+
+    @Test
+    public void testUnmarshalError() throws Exception {
+        MockEndpoint.resetMocks(context);
+        mockError.expectedMessageCount(1);
+        mockError.message(0).body(String.class).contains("<foo");
+        mockInvalid.expectedMessageCount(0);
+        mockResult.expectedMessageCount(0);
+
+        template.sendBody("direct:start", "<foo/>");
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    @Test
+    public void testNotWine() throws Exception {
+        MockEndpoint.resetMocks(context);
+        PurchaseOrder order = new PurchaseOrder();
+        order.setName("Beer");
+        order.setAmount(2);
+        order.setPrice(1.99);
+
+        
+        mockInvalid.expectedBodiesReceived(order);
+        mockError.expectedMessageCount(0);
+        mockResult.expectedMessageCount(0);
+
+        template.sendBody("direct:start", "<purchaseOrder name='Beer' amount='2.0' price='1.99'/>");
+
+        MockEndpoint.assertIsSatisfied(context);
+    }
+
+    
+    public static boolean isWine(PurchaseOrder order) {
+        return "Wine".equalsIgnoreCase(order.getName());
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    errorHandler(deadLetterChannel("mock:error").redeliveryDelay(0));
+
+                    onException(InvalidOrderException.class).maximumRedeliveries(0).handled(true)
+                            .to("mock:invalid");
+
+                    DataFormat jaxb = new JaxbDataFormat("org.apache.camel.example");
+
+                    from("direct:start")
+                            .unmarshal(jaxb)
+                            .choice()
+                                .when().method(RouteWithErrorHandlerTest.class, "isWine").to("mock:wine")
+                                .otherwise().throwException(new InvalidOrderException("We only like wine"))
+                            .end();
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/TimerBeanToBeanNotificationTypeTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/TimerBeanToBeanNotificationTypeTest.java
new file mode 100644
index 0000000..aa99acf
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/TimerBeanToBeanNotificationTypeTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.jaxb.MyNotificationService;
+import org.apache.camel.jaxb.NotificationType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        TimerBeanToBeanNotificationTypeTest.class,
+        TimerBeanToBeanNotificationTypeTest.TestConfiguration.class
+    }
+)
+public class TimerBeanToBeanNotificationTypeTest {
+    
+    
+        
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:notify")
+    private MockEndpoint notify;
+
+    @Test
+    public void testBeanToBean() throws Exception {
+        notify.expectedMessageCount(1);
+        notify.message(0).body().isInstanceOf(NotificationType.class);
+
+        notify.assertIsSatisfied();
+    }
+
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("timer:foo?delay=500&repeatCount=1")
+                            .log("Timer triggered")
+                            .bean(MyNotificationService.class, "createNotification")
+                            .bean(MyNotificationService.class, "sendNotification");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/UnmarshalTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/UnmarshalTest.java
new file mode 100644
index 0000000..30280d1
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/converter/jaxb/springboot/UnmarshalTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.converter.jaxb.springboot;
+
+
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.example.PurchaseOrder;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.junit.jupiter.api.Test;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        UnmarshalTest.class,
+        UnmarshalTest.TestConfiguration.class
+    }
+)
+public class UnmarshalTest {
+    
+           
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:result")
+    private MockEndpoint resultEndpoint;
+
+    @EndpointInject("mock:unmarshall")
+    private MockEndpoint mockUnmarshall;
+
+    @Test
+    public void testSendXmlAndUnmarshal() throws Exception {
+        PurchaseOrder expected = new PurchaseOrder();
+        expected.setName("Wine");
+        expected.setAmount(123.45);
+        expected.setPrice(2.22);
+
+        resultEndpoint.expectedBodiesReceived(expected);
+
+        template.sendBody("direct:start", "<purchaseOrder name='Wine' amount='123.45' price='2.22'/>");
+
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    DataFormat jaxb = new JaxbDataFormat("org.apache.camel.example");
+
+                    from("direct:start").unmarshal(jaxb).to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Address.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Address.java
new file mode 100644
index 0000000..6918ef2
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Address.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.example;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Address")
+public class Address {
+
+    @XmlElement(namespace = "http://www.camel.apache.org/jaxb/example/address/1")
+    private String street;
+    @XmlElement(namespace = "http://www.camel.apache.org/jaxb/example/address/1")
+    private String streetNumber;
+    @XmlElement(namespace = "http://www.camel.apache.org/jaxb/example/address/1")
+    private String zip;
+    @XmlElement(namespace = "http://www.camel.apache.org/jaxb/example/address/1")
+    private String city;
+
+    public String getStreet() {
+        return street;
+    }
+
+    public String getStreetNumber() {
+        return streetNumber;
+    }
+
+    public String getZip() {
+        return zip;
+    }
+
+    public String getCity() {
+        return city;
+    }
+
+    public void setStreet(String street) {
+        this.street = street;
+    }
+
+    public void setStreetNumber(String streetNumber) {
+        this.streetNumber = streetNumber;
+    }
+
+    public void setZip(String zip) {
+        this.zip = zip;
+    }
+
+    public void setCity(String city) {
+        this.city = city;
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Bar.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Bar.java
new file mode 100644
index 0000000..d4a42da
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Bar.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Bar {
+
+    @XmlAttribute
+    private String name;
+    @XmlAttribute
+    private String value;
+
+    public Bar() {
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Foo.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Foo.java
new file mode 100644
index 0000000..b91d9f6
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Foo.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.example;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Foo {
+    @XmlElements({
+            @XmlElement(name = "bar", type = Bar.class, required = false),
+            @XmlElement(name = "zot", type = Zot.class, required = false) })
+    List<Bar> barRefs = new ArrayList<>();
+
+    public List<Bar> getBarRefs() {
+        return barRefs;
+    }
+
+    public void setBarRefs(List<Bar> bars) {
+        barRefs = bars;
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/InvalidOrderException.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/InvalidOrderException.java
new file mode 100644
index 0000000..8499333
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/InvalidOrderException.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.example;
+
+public class InvalidOrderException extends Exception {
+    private static final long serialVersionUID = 383958238537555588L;
+
+    public InvalidOrderException(String message) {
+        super(message);
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Order.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Order.java
new file mode 100644
index 0000000..7d54dcc
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Order.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(namespace = "http://www.camel.apache.org/jaxb/example/order/1")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Order {
+
+    @XmlElement(namespace = "http://www.camel.apache.org/jaxb/example/order/1")
+    private String id;
+
+    @XmlElement(namespace = "http://www.camel.apache.org/jaxb/example/address/1")
+    private Address address;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public Address getAddress() {
+        return address;
+    }
+
+    public void setAddress(Address address) {
+        this.address = address;
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Partial.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Partial.java
new file mode 100644
index 0000000..94fa0b7
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Partial.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.example;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * Partial element without XmlRootElement annotation for partial testing.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Partial")
+public class Partial {
+
+    @XmlAttribute
+    private String name;
+
+    @XmlElement
+    private String location;
+
+    public final String getName() {
+        return name;
+    }
+
+    public final void setName(String name) {
+        this.name = name;
+    }
+
+    public final String getLocation() {
+        return location;
+    }
+
+    public final void setLocation(String location) {
+        this.location = location;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        Partial partial = (Partial) o;
+
+        if (location != null ? !location.equals(partial.location) : partial.location != null) {
+            return false;
+        }
+        if (name != null ? !name.equals(partial.name) : partial.name != null) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = name != null ? name.hashCode() : 0;
+        result = 31 * result + (location != null ? location.hashCode() : 0);
+        return result;
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/PurchaseOrder.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/PurchaseOrder.java
new file mode 100644
index 0000000..c3612a3
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/PurchaseOrder.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.util.ObjectHelper;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class PurchaseOrder {
+    @XmlAttribute
+    private String name;
+    @XmlAttribute
+    private double price;
+    @XmlAttribute
+    private double amount;
+
+    @Override
+    public String toString() {
+        return "PurchaseOrder[name: " + name + " amount: " + amount + " price: " + price + "]";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof PurchaseOrder) {
+            PurchaseOrder that = (PurchaseOrder) o;
+            return ObjectHelper.equal(this.name, that.name) && ObjectHelper.equal(this.amount, that.amount)
+                    && ObjectHelper.equal(this.price, that.price);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return name.hashCode() + (int) Math.round(price * 100) + (int) Math.round(amount * 100);
+    }
+
+    public double getAmount() {
+        return amount;
+    }
+
+    public void setAmount(double amount) {
+        this.amount = amount;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public double getPrice() {
+        return price;
+    }
+
+    public void setPrice(double price) {
+        this.price = price;
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Zot.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Zot.java
new file mode 100644
index 0000000..cfb62d2
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/Zot.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Zot extends Bar {
+    private String otherValue;
+
+    public void setOtherValue(String value) {
+        otherValue = value;
+    }
+
+    public String getOtherValue() {
+        return otherValue;
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/package-info.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/package-info.java
new file mode 100644
index 0000000..560bb80
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/example/package-info.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.
+ */
+@XmlSchema(
+           xmlns = {
+                   @XmlNs(prefix = "order", namespaceURI = "http://www.camel.apache.org/jaxb/example/order/1"),
+                   @XmlNs(prefix = "address", namespaceURI = "http://www.camel.apache.org/jaxb/example/address/1")
+           })
+package org.apache.camel.example;
+
+import javax.xml.bind.annotation.XmlNs;
+import javax.xml.bind.annotation.XmlSchema;
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/foo/bar/ObjectFactory.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/foo/bar/ObjectFactory.java
new file mode 100644
index 0000000..dd848b7
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/foo/bar/ObjectFactory.java
@@ -0,0 +1,63 @@
+/*
+ * 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.foo.bar;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+/**
+ * This object contains factory methods for each Java content interface and Java element interface generated in the
+ * org.apache.camel.foo.bar package.
+ * <p>
+ * An ObjectFactory allows you to programatically construct new instances of the Java representation for XML content.
+ * The Java representation of XML content can consist of schema derived interfaces and classes representing the binding
+ * of schema type definitions, element declarations and model groups. Factory methods for each of these are provided in
+ * this class.
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+    private final QName personQNAME = new QName("", "Person");
+
+    /**
+     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package:
+     * com.foo.bar
+     * 
+     */
+    public ObjectFactory() {
+    }
+
+    /**
+     * Create an instance of {@link PersonType }
+     * 
+     */
+    public PersonType createPersonType() {
+        return new PersonType();
+    }
+
+    /**
+     * Create an instance of {@link JAXBElement }{@code <}{@link PersonType }{@code >}}
+     */
+
+    @XmlElementDecl(namespace = "", name = "Person")
+    public JAXBElement<PersonType> createPerson(PersonType value) {
+        return new JAXBElement<>(personQNAME, PersonType.class, null, value);
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/foo/bar/PersonType.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/foo/bar/PersonType.java
new file mode 100644
index 0000000..a78ebc2
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/foo/bar/PersonType.java
@@ -0,0 +1,113 @@
+/*
+ * 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.foo.bar;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * <p>
+ * Java class for PersonType complex type.
+ * 
+ * <p>
+ * The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="PersonType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="firstName" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         &lt;element name="lastName" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ */
+@XmlRootElement(name = "Person")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "PersonType", propOrder = { "firstName", "lastName" })
+public class PersonType {
+
+    @XmlElement(required = true)
+    protected String firstName;
+    @XmlElement(required = true)
+    protected String lastName;
+
+    /**
+     * Gets the value of the firstName property.
+     * 
+     * @return possible object is {@link String }
+     * 
+     */
+    public String getFirstName() {
+        return firstName;
+    }
+
+    /**
+     * Sets the value of the firstName property.
+     * 
+     * @param value allowed object is {@link String }
+     * 
+     */
+    public void setFirstName(String value) {
+        this.firstName = value;
+    }
+
+    /**
+     * Gets the value of the lastName property.
+     * 
+     * @return possible object is {@link String }
+     * 
+     */
+    public String getLastName() {
+        return lastName;
+    }
+
+    /**
+     * Sets the value of the lastName property.
+     * 
+     * @param value allowed object is {@link String }
+     * 
+     */
+    public void setLastName(String value) {
+        this.lastName = value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof PersonType) {
+            PersonType that = (PersonType) o;
+            return ObjectHelper.equal(this.firstName, that.firstName)
+                    && ObjectHelper.equal(this.lastName, that.lastName);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return firstName.hashCode() + lastName.hashCode() * 100;
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/CamelJaxbFallbackConverterTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/CamelJaxbFallbackConverterTest.java
new file mode 100644
index 0000000..bbc40f0
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/CamelJaxbFallbackConverterTest.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.jaxb;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConversionException;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.example.Bar;
+import org.apache.camel.example.Foo;
+import org.apache.camel.foo.bar.PersonType;
+import org.apache.camel.support.DefaultExchange;
+import org.apache.camel.test.junit5.ExchangeTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class CamelJaxbFallbackConverterTest extends ExchangeTestSupport {
+
+    @Test
+    public void testFallbackConverterWithoutObjectFactory() throws Exception {
+        TypeConverter converter = context.getTypeConverter();
+        Foo foo = converter.convertTo(Foo.class, exchange,
+                "<foo><zot name=\"bar1\" value=\"value\" otherValue=\"otherValue\"/></foo>");
+        assertNotNull(foo, "foo should not be null");
+        assertEquals("value", foo.getBarRefs().get(0).getValue());
+
+        foo.getBarRefs().clear();
+        Bar bar = new Bar();
+        bar.setName("myName");
+        bar.setValue("myValue");
+        foo.getBarRefs().add(bar);
+
+        Exchange exchange = new DefaultExchange(context);
+        exchange.setProperty(Exchange.CHARSET_NAME, "UTF-8");
+
+        String value = converter.convertTo(String.class, exchange, foo);
+
+        assertTrue(value.indexOf("<bar name=\"myName\" value=\"myValue\"/>") > 0, "Should get a right marshalled string");
+    }
+
+    @Test
+    public void testFallbackConverterUnmarshalWithNonJAXBComplaintValue() throws Exception {
+        TypeConverter converter = context.getTypeConverter();
+
+        try {
+            converter.convertTo(Foo.class, "Not every String is XML");
+            fail("Should have thrown exception");
+        } catch (TypeConversionException e) {
+            // expected
+        }
+
+        try {
+            converter.convertTo(Bar.class, "<bar></bar");
+            fail("Should have thrown exception");
+        } catch (TypeConversionException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testConverter() throws Exception {
+        TypeConverter converter = context.getTypeConverter();
+        PersonType person = converter.convertTo(PersonType.class, exchange,
+                "<Person><firstName>FOO</firstName><lastName>BAR</lastName></Person>");
+        assertNotNull(person, "Person should not be null");
+        assertEquals("FOO", person.getFirstName(), "Get the wrong first name");
+        assertEquals("BAR", person.getLastName(), "Get the wrong second name");
+        Exchange exchange = new DefaultExchange(context);
+        exchange.setProperty(Exchange.CHARSET_NAME, "UTF-8");
+
+        String value = converter.convertTo(String.class, exchange, person);
+        assertTrue(value.indexOf("<lastName>BAR</lastName>") > 0, "Should get a right marshalled string");
+
+        byte[] buffers = "<Person><firstName>FOO</firstName><lastName>BAR\u0008</lastName></Person>".getBytes("UTF-8");
+        InputStream is = new ByteArrayInputStream(buffers);
+        try {
+            converter.convertTo(PersonType.class, exchange, is);
+            fail("Should have thrown exception");
+        } catch (TypeConversionException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testFilteringConverter() throws Exception {
+        byte[] buffers = "<Person><firstName>FOO</firstName><lastName>BAR\u0008</lastName></Person>".getBytes("UTF-8");
+        InputStream is = new ByteArrayInputStream(buffers);
+        Exchange exchange = new DefaultExchange(context);
+        exchange.setProperty(Exchange.CHARSET_NAME, "UTF-8");
+        exchange.setProperty(Exchange.FILTER_NON_XML_CHARS, true);
+        TypeConverter converter = context.getTypeConverter();
+        PersonType person = converter.convertTo(PersonType.class, exchange, is);
+        assertNotNull(person, "Person should not be null ");
+        assertEquals("FOO", person.getFirstName(), "Get the wrong first name");
+        assertEquals("BAR ", person.getLastName(), "Get the wrong second name");
+
+        person.setLastName("BAR\u0008\uD8FF");
+        String value = converter.convertTo(String.class, exchange, person);
+        assertTrue(value.indexOf("<lastName>BAR  </lastName>") > 0, "Didn't filter the non-xml chars");
+
+        exchange.setProperty(Exchange.FILTER_NON_XML_CHARS, false);
+
+        value = converter.convertTo(String.class, exchange, person);
+        assertTrue(value.indexOf("<lastName>BAR\uD8FF</lastName>") > 0, "Should not filter the non-xml chars");
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/CamelJaxbNoNamespaceSchemaTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/CamelJaxbNoNamespaceSchemaTest.java
new file mode 100644
index 0000000..a71dae0
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/CamelJaxbNoNamespaceSchemaTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.jaxb;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.foo.bar.PersonType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        CamelJaxbNoNamespaceSchemaTest.class
+    }
+)
+public class CamelJaxbNoNamespaceSchemaTest  {
+    
+    @Autowired
+    ProducerTemplate template;
+
+    
+    @EndpointInject("mock:result")
+    private MockEndpoint resultEndpoint;
+
+
+    @Test
+    public void testMarshalWithNoNamespaceSchemaLocation() throws Exception {
+        PersonType person = new PersonType();
+        person.setFirstName("foo");
+        person.setLastName("bar");
+
+        
+        resultEndpoint.expectedMessageCount(1);
+        template.sendBody("direct:marshal", person);
+        resultEndpoint.assertIsSatisfied();
+
+        String body = resultEndpoint.getReceivedExchanges().get(0).getIn().getBody(String.class);
+        assertTrue(body.contains("noNamespaceSchemaLocation=\"person-no-namespace.xsd\""),
+                "We should get the noNamespaceSchemaLocation here");
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+
+            public void configure() throws Exception {
+                JaxbDataFormat dataFormat = new JaxbDataFormat("org.apache.camel.foo.bar");
+                dataFormat.setNoNamespaceSchemaLocation("person-no-namespace.xsd");
+                dataFormat.setIgnoreJAXBElement(false);
+
+                from("direct:marshal")
+                        .marshal(dataFormat)
+                        .to("mock:result");
+
+            }
+        };
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/FallbackTypeConverterObjectFactoryDisabledTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/FallbackTypeConverterObjectFactoryDisabledTest.java
new file mode 100644
index 0000000..2a00d8d
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/FallbackTypeConverterObjectFactoryDisabledTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.jaxb;
+
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.FallbackTypeConverter;
+import org.apache.camel.converter.jaxb.message.Message;
+import org.apache.camel.impl.converter.CoreTypeConverterRegistry;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        FallbackTypeConverterObjectFactoryDisabledTest.class
+    }
+)
+public class FallbackTypeConverterObjectFactoryDisabledTest {
+    
+    @Autowired
+    ProducerTemplate template;
+    
+    @Autowired
+    CamelContext context;
+    
+   
+    @EndpointInject("mock:a")
+    private MockEndpoint resultEndpoint;
+
+    @Test
+    public void testObjectFactoryFalse() throws Exception {
+        Message in = new Message("Hello World");
+        resultEndpoint.expectedBodiesReceived(in);
+
+        assertThrows(CamelExecutionException.class, () -> template.sendBody("direct:a", in));
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        List<CoreTypeConverterRegistry.FallbackTypeConverter> list = ((CoreTypeConverterRegistry)context.getTypeConverterRegistry()).
+            getFallbackConverters();
+        for (CoreTypeConverterRegistry.FallbackTypeConverter fallback : list) {
+            if (fallback.getFallbackTypeConverter().getClass().getName()
+                .contains("SpringTypeConverter")) {
+                list.remove(fallback);
+            }
+        }
+        context.getGlobalOptions().put(FallbackTypeConverter.OBJECT_FACTORY, "false");
+        return new RouteBuilder(context) {
+
+            @Override
+            public void configure() throws Exception {
+                from("direct:a").convertBodyTo(String.class).to("direct:b");
+                from("direct:b").convertBodyTo(Message.class).to("mock:a");
+            }
+
+        };
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/FallbackTypeConverterObjectFactoryEnabledTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/FallbackTypeConverterObjectFactoryEnabledTest.java
new file mode 100644
index 0000000..07bbf9e
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/FallbackTypeConverterObjectFactoryEnabledTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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.jaxb;
+
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.FallbackTypeConverter;
+import org.apache.camel.converter.jaxb.message.Message;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.impl.converter.CoreTypeConverterRegistry;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import org.junit.jupiter.api.Test;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        FallbackTypeConverterObjectFactoryEnabledTest.class,
+        FallbackTypeConverterObjectFactoryEnabledTest.TestConfiguration.class
+    }
+)
+public class FallbackTypeConverterObjectFactoryEnabledTest {
+    
+    @Autowired
+    ProducerTemplate template;
+    
+   
+    @EndpointInject("mock:a")
+    private MockEndpoint resultEndpoint;
+
+    @Test
+    public void testObjectFactoryTrue() throws Exception {
+        
+        Message in = new Message("Hello World");
+        resultEndpoint.expectedBodiesReceived(in);
+
+        template.sendBody("direct:a", in);
+
+        resultEndpoint.assertIsSatisfied();
+    }
+
+        
+    @Configuration
+    public class TestConfiguration {
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:a").convertBodyTo(String.class).to("direct:b");
+                    from("direct:b").convertBodyTo(Message.class).to("mock:a");
+                }
+            };
+        }
+    }
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //hack way to remove the SpringTypeConverter as its the first fallback converter
+                //but we expect to use the org.apache.camel.converter.jaxb.FallbackTypeConverter
+                //from SimpleTypeConverter in this test case.
+                List<CoreTypeConverterRegistry.FallbackTypeConverter> list = ((CoreTypeConverterRegistry)context.getTypeConverterRegistry()).
+                    getFallbackConverters();
+                for (CoreTypeConverterRegistry.FallbackTypeConverter fallback : list) {
+                    if (fallback.getFallbackTypeConverter().getClass().getName()
+                        .contains("SpringTypeConverter")) {
+                        list.remove(fallback);
+                    }
+                }
+                context.getGlobalOptions().put(FallbackTypeConverter.OBJECT_FACTORY, "true");
+            }
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here
+            }
+
+        };
+    }
+
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/FallbackTypeConverterShouldThrowExceptionTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/FallbackTypeConverterShouldThrowExceptionTest.java
new file mode 100644
index 0000000..0bbc7d6
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/FallbackTypeConverterShouldThrowExceptionTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.jaxb;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.TypeConversionException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.example.Bar;
+import org.apache.camel.example.Foo;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        FallbackTypeConverterShouldThrowExceptionTest.class
+    }
+)
+public class FallbackTypeConverterShouldThrowExceptionTest  {
+
+    private static AtomicInteger failed = new AtomicInteger();
+    private static AtomicInteger failed2 = new AtomicInteger();
+    
+    @Autowired
+    ProducerTemplate template;
+    
+    @Autowired
+    CamelContext context;
+    
+   
+    @EndpointInject("mock:a")
+    private MockEndpoint mockA;
+    
+    @EndpointInject("mock:b")
+    private MockEndpoint mockB;
+    
+    @BeforeEach
+    private void setup() {
+        failed = new AtomicInteger();
+        failed2 = new AtomicInteger();
+    }
+
+    @Test
+    public void testJaxbModel() throws Exception {
+        MockEndpoint.resetMocks(context);
+        Object foo = new Foo();
+        mockA.expectedBodiesReceived(foo);
+        mockB.expectedBodiesReceived(foo);
+
+        template.sendBody("direct:a", foo);
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        assertEquals(0, failed.get());
+        assertEquals(0, failed2.get());
+    }
+
+    @Test
+    public void testNoneJaxbModel() throws Exception {
+        MockEndpoint.resetMocks(context);
+        Object camel = "Camel";
+        mockA.expectedBodiesReceived(camel);
+        mockB.expectedBodiesReceived(camel);
+
+        template.sendBody("direct:a", camel);
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        assertEquals(1, failed.get());
+        assertEquals(0, failed2.get());
+    }
+
+    @Test
+    public void testAnotherJaxbModel() throws Exception {
+        MockEndpoint.resetMocks(context);
+        Object bar = new Bar();
+        mockA.expectedBodiesReceived(bar);
+        mockB.expectedBodiesReceived(bar);
+
+        template.sendBody("direct:a", bar);
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        assertEquals(1, failed.get());
+        assertEquals(0, failed2.get());
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder(context) {
+
+            @Override
+            public void configure() throws Exception {
+                from("direct:a").process(new Processor() {
+                    @Override
+                    public void process(Exchange exchange) throws Exception {
+                        try {
+                            exchange.getIn().getBody(Foo.class);
+                        } catch (TypeConversionException e) {
+                            failed.incrementAndGet();
+                        }
+                    }
+                }).to("mock:a").process(new Processor() {
+                    @Override
+                    public void process(Exchange exchange) throws Exception {
+                        try {
+                            exchange.getIn().getBody(List.class);
+                        } catch (TypeConversionException e) {
+                            // there is no type converters from the POJO -> List
+                            // so we should really not fail at all at this point
+                            failed2.incrementAndGet();
+                        }
+                    }
+
+                }).to("mock:b");
+            }
+
+        };
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/JaxbDataFormatIssueTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/JaxbDataFormatIssueTest.java
new file mode 100644
index 0000000..0ad49ae
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/JaxbDataFormatIssueTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.jaxb;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+import org.junit.jupiter.api.Test;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        JaxbDataFormatIssueTest.class
+    }
+)
+public class JaxbDataFormatIssueTest {
+    
+    @Autowired
+    ProducerTemplate template;
+    
+   
+    @EndpointInject("mock:result")
+    private MockEndpoint mock;
+
+
+    @Test
+    public void testJaxbMarshalling() throws InterruptedException {
+        mock.expectedMessageCount(1);
+        mock.message(0).body().endsWith("<foo><bar>Hello Bar</bar></foo>");
+
+        Foo foo = new Foo();
+        foo.setBar("Hello Bar");
+        template.sendBody("direct:start", foo);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                JaxbDataFormat jaxb = new JaxbDataFormat(JAXBContext.newInstance(Foo.class));
+                jaxb.setPrettyPrint(false);
+
+                from("direct:start").marshal(jaxb).to("log:xml", "mock:result");
+            }
+        };
+    }
+
+    @XmlRootElement
+    public static class Foo {
+        private String bar;
+
+        public String getBar() {
+            return bar;
+        }
+
+        public void setBar(String bar) {
+            this.bar = bar;
+        }
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/JaxbDataFormatMustBeJAXBElementTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/JaxbDataFormatMustBeJAXBElementTest.java
new file mode 100644
index 0000000..352ce3f
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/JaxbDataFormatMustBeJAXBElementTest.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.jaxb;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.test.junit5.TestSupport.assertIsInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.fail;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        JaxbDataFormatMustBeJAXBElementTest.class
+    }
+)
+public class JaxbDataFormatMustBeJAXBElementTest {
+    
+    @Autowired
+    ProducerTemplate template;
+    
+   
+    @EndpointInject("mock:result")
+    private MockEndpoint mock;
+
+    @Test
+    public void testJaxbMarshalling() throws InterruptedException {
+        mock.reset();
+        mock.expectedMessageCount(1);
+        mock.message(0).body().endsWith("<foo><bar>Hello Bar</bar></foo>");
+
+        template.sendBody("direct:start", "<foo><bar>Hello Bar</bar></foo>");
+
+        mock.assertIsSatisfied();
+    }
+
+    @Test
+    public void testJaxbMarshalling2() throws InterruptedException {
+        mock.reset();
+        mock.expectedMessageCount(0);
+
+        try {
+            template.sendBody("direct:start2", "<foo><bar>Hello Bar</bar></foo>");
+            fail("Should have thrown exception");
+        } catch (CamelExecutionException e) {
+            InvalidPayloadException ipe = assertIsInstanceOf(InvalidPayloadException.class, e.getCause().getCause());
+            assertNotNull(ipe);
+            assertEquals(JAXBElement.class, ipe.getType());
+        }
+
+        mock.assertIsSatisfied();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                JaxbDataFormat jaxb = new JaxbDataFormat(JAXBContext.newInstance(Foo.class));
+                jaxb.setPrettyPrint(false);
+                jaxb.setMustBeJAXBElement(false);
+
+                from("direct:start").marshal(jaxb).to("log:xml", "mock:result");
+
+                JaxbDataFormat jaxb2 = new JaxbDataFormat(JAXBContext.newInstance(Foo.class));
+                jaxb2.setPrettyPrint(false);
+                jaxb2.setMustBeJAXBElement(true);
+
+                from("direct:start2").marshal(jaxb2).to("log:xml", "mock:result2");
+            }
+        };
+    }
+
+    @XmlRootElement
+    public static class Foo {
+        private String bar;
+
+        public String getBar() {
+            return bar;
+        }
+
+        public void setBar(String bar) {
+            this.bar = bar;
+        }
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/JaxbMarshalNamespacePrefixMapperTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/JaxbMarshalNamespacePrefixMapperTest.java
new file mode 100644
index 0000000..c22dce2
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/JaxbMarshalNamespacePrefixMapperTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.jaxb;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.example.Address;
+import org.apache.camel.example.Order;
+import org.apache.camel.model.dataformat.JaxbDataFormat;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ *
+ */
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        JaxbMarshalNamespacePrefixMapperTest.class
+    }
+)
+public class JaxbMarshalNamespacePrefixMapperTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(JaxbMarshalNamespacePrefixMapperTest.class);
+    
+    @Autowired
+    ProducerTemplate template;
+    
+   
+    @EndpointInject("mock:result")
+    private MockEndpoint mock;
+
+    @Bean("myPrefix")
+    public Map<String, String> addMap() throws Exception {
+        Map<String, String> map = new HashMap<>();
+        map.put("http://www.camel.apache.org/jaxb/example/order/1", "o");
+        map.put("http://www.camel.apache.org/jaxb/example/address/1", "a");
+
+        return map;
+    }
+
+    @Test
+    public void testNamespacePrefix() throws Exception {
+        mock.expectedMessageCount(1);
+
+        Order order = new Order();
+        order.setId("1");
+        Address address = new Address();
+        address.setStreet("Main Street");
+        address.setStreetNumber("3a");
+        address.setZip("65843");
+        address.setCity("Sulzbach");
+        order.setAddress(address);
+
+        template.sendBody("direct:start", order);
+
+        mock.assertIsSatisfied();
+
+        String xml = mock.getExchanges().get(0).getIn().getBody(String.class);
+        LOG.info(xml);
+
+        assertTrue(xml.contains("xmlns:a=\"http://www.camel.apache.org/jaxb/example/address/1\""));
+        assertTrue(xml.contains("xmlns:o=\"http://www.camel.apache.org/jaxb/example/order/1\""));
+        assertTrue(xml.contains("<o:id>1</o:id>"));
+        assertTrue(xml.contains("<a:street>Main Street</a:street>"));
+        assertTrue(xml.contains("</o:order>"));
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                JaxbDataFormat df = new JaxbDataFormat();
+                df.setContextPath("org.apache.camel.example");
+                df.setNamespacePrefixRef("myPrefix");
+
+                from("direct:start")
+                        .marshal(df)
+                        .to("mock:result");
+
+            }
+        };
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/MyNotificationService.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/MyNotificationService.java
new file mode 100644
index 0000000..eafb3a9
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/MyNotificationService.java
@@ -0,0 +1,39 @@
+/*
+ * 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.jaxb;
+
+import org.apache.camel.Exchange;
+
+/**
+ * NotificationType does not have any JAXB ObjectFactory so we should test you can still route using that
+ */
+public class MyNotificationService {
+
+    public void createNotification(Exchange exchange) {
+        NotificationType notification = new NotificationType();
+        notification.setEvent("Hello");
+
+        exchange.getMessage().setBody(notification);
+    }
+
+    public void sendNotification(Exchange exchange) {
+        NotificationType notification = (NotificationType) exchange.getIn().getBody();
+
+        exchange.getContext().createProducerTemplate().sendBody("mock:notify", notification);
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/MyPersonService.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/MyPersonService.java
new file mode 100644
index 0000000..d80d6f0
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/MyPersonService.java
@@ -0,0 +1,41 @@
+/*
+ * 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.jaxb;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.foo.bar.PersonType;
+
+/**
+ *
+ */
+public class MyPersonService {
+
+    public void createPerson(Exchange exchange) {
+        PersonType person = new PersonType();
+        person.setFirstName("Homer");
+        person.setLastName("Simpson");
+
+        exchange.getMessage().setBody(person);
+    }
+
+    public void sendPerson(Exchange exchange) {
+        PersonType person = (PersonType) exchange.getIn().getBody();
+
+        exchange.getContext().createProducerTemplate().sendBody("mock:person", person);
+    }
+
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/NotificationType.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/NotificationType.java
new file mode 100644
index 0000000..4e92756
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/NotificationType.java
@@ -0,0 +1,39 @@
+/*
+ * 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.jaxb;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(name = "Notification")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "NotificationType", propOrder = { "event" })
+public class NotificationType {
+    @XmlElement(required = true)
+    protected String event;
+
+    public String getEvent() {
+        return event;
+    }
+
+    public void setEvent(String event) {
+        this.event = event;
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/SplitterAndExceptionRouteTwistIssueTest.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/SplitterAndExceptionRouteTwistIssueTest.java
new file mode 100644
index 0000000..950cd36
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/SplitterAndExceptionRouteTwistIssueTest.java
@@ -0,0 +1,223 @@
+/*
+ * 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.jaxb;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.Processor;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.annotation.DirtiesContext;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ */
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        SplitterAndExceptionRouteTwistIssueTest.class
+    }
+)
+
+public class SplitterAndExceptionRouteTwistIssueTest {
+    
+    @Autowired
+    CamelContext context;
+
+    @Produce("direct:error")
+    protected ProducerTemplate templateError;
+
+    @Produce("direct:error2")
+    protected ProducerTemplate templateError2;
+
+    @EndpointInject("mock:mockReject")
+    protected MockEndpoint mockRejectEndpoint;
+
+    @EndpointInject("mock:mock_output")
+    protected MockEndpoint mockOutput;
+
+    @Test
+    public void testErrorHandlingJaxb() throws Exception {
+        MockEndpoint.resetMocks(context);
+        String correctExample = "abcdef";
+        String errorExample = "myerror\u0010";
+
+        mockRejectEndpoint.expectedMessageCount(1);
+        mockOutput.expectedMessageCount(4);
+
+        templateError.sendBody(correctExample);
+        templateError.sendBody(errorExample);
+        templateError.sendBody(correctExample);
+        templateError.sendBody(correctExample);
+        templateError.sendBody(correctExample);
+
+        mockRejectEndpoint.assertIsSatisfied();
+        mockOutput.assertIsSatisfied();
+    }
+
+    @Test
+    public void testErrorHandlingPlumber() throws Exception {
+        MockEndpoint.resetMocks(context);
+        String correctExample = "abcdef";
+        String errorExample = "myerror\u0010";
+
+        mockRejectEndpoint.expectedMessageCount(1);
+        mockOutput.expectedMessageCount(4);
+
+        templateError2.sendBody(correctExample);
+        templateError2.sendBody(errorExample);
+        templateError2.sendBody(correctExample);
+        templateError2.sendBody(correctExample);
+        templateError2.sendBody(correctExample);
+
+        mockRejectEndpoint.assertIsSatisfied();
+        mockOutput.assertIsSatisfied();
+    }
+
+    @Bean
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+
+            @Override
+            public void configure() throws Exception {
+
+                errorHandler(
+                        deadLetterChannel(mockRejectEndpoint)
+                                .useOriginalMessage()
+                                .maximumRedeliveries(0)
+                                .retryAttemptedLogLevel(LoggingLevel.WARN)
+                                .logExhausted(true)
+                                .logStackTrace(true)
+                                .logRetryStackTrace(true));
+
+                from("direct:error")
+                        .convertBodyTo(String.class, "UTF-8")
+                        .process(new Processor() {
+                            @Override
+                            public void process(Exchange exchange) throws Exception {
+                                String text = (String) exchange.getIn().getBody();
+                                Twits twits = new Twits();
+
+                                Twit twit1 = new Twit();
+                                twit1.setText(text);
+                                twits.getTwits().add(twit1);
+
+                                exchange.getIn().setBody(twits);
+                            }
+                        })
+                        .split().xpath("//twits/twit").streaming()
+                        .to(mockOutput);
+
+                from("direct:error2")
+                        .convertBodyTo(String.class, "UTF-8")
+                        .process(new Processor() {
+                            @Override
+                            public void process(Exchange exchange) throws Exception {
+                                String text = (String) exchange.getIn().getBody();
+
+                                StringBuilder twits = new StringBuilder();
+                                twits.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>");
+
+                                twits.append("<twits>");
+                                twits.append("<twit>");
+                                twits.append(text);
+                                twits.append("</twit>");
+                                twits.append("</twits>");
+
+                                exchange.getIn().setBody(twits.toString());
+                            }
+                        })
+                        .split().xpath("//twits/twit").streaming()
+                        .to(mockOutput);
+            }
+        };
+    }
+}
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = { "twits" })
+@XmlRootElement(name = "twits")
+class Twits implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @XmlElement(name = "twit", required = true)
+    protected List<Twit> twits;
+
+    public List<Twit> getTwits() {
+        if (twits == null) {
+            twits = new ArrayList<>();
+        }
+        return this.twits;
+    }
+
+    @Override
+    public String toString() {
+        if (twits == null || twits.isEmpty()) {
+            return super.toString();
+        }
+        return super.toString() + "[" + twits.get(0).toString() + "]";
+    }
+}
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Twit", propOrder = { "text" })
+@XmlRootElement(name = "twit")
+class Twit implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @XmlElement(required = true)
+    protected String text;
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String value) {
+        this.text = value;
+    }
+
+    @Override
+    public String toString() {
+        return text;
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/TestXmlStreamWriter.java b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/TestXmlStreamWriter.java
new file mode 100644
index 0000000..37151a9
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/java/org/apache/camel/jaxb/TestXmlStreamWriter.java
@@ -0,0 +1,190 @@
+/*
+ * 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.jaxb;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.camel.converter.jaxb.JaxbXmlStreamWriterWrapper;
+
+public class TestXmlStreamWriter implements JaxbXmlStreamWriterWrapper {
+    @Override
+    public XMLStreamWriter wrapWriter(final XMLStreamWriter writer) {
+        return new XMLStreamWriter() {
+            @Override
+            public void writeStartElement(String s) throws XMLStreamException {
+                writer.writeStartElement(s + "-Foo");
+            }
+
+            @Override
+            public void writeStartElement(String s, String s2) throws XMLStreamException {
+                writer.writeStartElement(s, s2 + "-Foo");
+            }
+
+            @Override
+            public void writeStartElement(String s, String s2, String s3) throws XMLStreamException {
+                writer.writeStartElement(s, s2 + "-Foo", s3);
+            }
+
+            @Override
+            public void writeEmptyElement(String s, String s2) throws XMLStreamException {
+                writer.writeEmptyElement(s, s2);
+            }
+
+            @Override
+            public void writeEmptyElement(String s, String s2, String s3) throws XMLStreamException {
+                writer.writeEmptyElement(s, s2, s3);
+            }
+
+            @Override
+            public void writeEmptyElement(String s) throws XMLStreamException {
+                writer.writeEmptyElement(s);
+            }
+
+            @Override
+            public void writeEndElement() throws XMLStreamException {
+                writer.writeEndElement();
+            }
+
+            @Override
+            public void writeEndDocument() throws XMLStreamException {
+                writer.writeEndDocument();
+            }
+
+            @Override
+            public void close() throws XMLStreamException {
+                writer.close();
+            }
+
+            @Override
+            public void flush() throws XMLStreamException {
+                writer.flush();
+            }
+
+            @Override
+            public void writeAttribute(String s, String s2) throws XMLStreamException {
+                writer.writeAttribute(s, s2);
+            }
+
+            @Override
+            public void writeAttribute(String s, String s2, String s3, String s4) throws XMLStreamException {
+                writer.writeAttribute(s, s2, s3, s4);
+            }
+
+            @Override
+            public void writeAttribute(String s, String s2, String s3) throws XMLStreamException {
+                writer.writeAttribute(s, s2, s3);
+            }
+
+            @Override
+            public void writeNamespace(String s, String s2) throws XMLStreamException {
+                writer.writeNamespace(s, s2);
+            }
+
+            @Override
+            public void writeDefaultNamespace(String s) throws XMLStreamException {
+                writer.writeDefaultNamespace(s);
+            }
+
+            @Override
+            public void writeComment(String s) throws XMLStreamException {
+                writer.writeComment(s);
+            }
+
+            @Override
+            public void writeProcessingInstruction(String s) throws XMLStreamException {
+                writer.writeProcessingInstruction(s);
+            }
+
+            @Override
+            public void writeProcessingInstruction(String s, String s2) throws XMLStreamException {
+                writer.writeProcessingInstruction(s, s2);
+            }
+
+            @Override
+            public void writeCData(String s) throws XMLStreamException {
+                writer.writeCData(s);
+            }
+
+            @Override
+            public void writeDTD(String s) throws XMLStreamException {
+                writer.writeDTD(s);
+            }
+
+            @Override
+            public void writeEntityRef(String s) throws XMLStreamException {
+                writer.writeEntityRef(s);
+            }
+
+            @Override
+            public void writeStartDocument() throws XMLStreamException {
+                writer.writeStartDocument();
+            }
+
+            @Override
+            public void writeStartDocument(String s) throws XMLStreamException {
+                writer.writeStartDocument(s);
+            }
+
+            @Override
+            public void writeStartDocument(String s, String s2) throws XMLStreamException {
+                writer.writeStartDocument(s, s2);
+            }
+
+            @Override
+            public void writeCharacters(String s) throws XMLStreamException {
+                writer.writeCharacters(s);
+            }
+
+            @Override
+            public void writeCharacters(char[] chars, int i, int i2) throws XMLStreamException {
+                writer.writeCharacters(chars, i, i2);
+            }
+
+            @Override
+            public String getPrefix(String s) throws XMLStreamException {
+                return writer.getPrefix(s);
+            }
+
+            @Override
+            public void setPrefix(String s, String s2) throws XMLStreamException {
+                writer.setPrefix(s, s2);
+            }
+
+            @Override
+            public void setDefaultNamespace(String s) throws XMLStreamException {
+                writer.setDefaultNamespace(s);
+            }
+
+            @Override
+            public void setNamespaceContext(NamespaceContext namespaceContext) throws XMLStreamException {
+                writer.setNamespaceContext(namespaceContext);
+            }
+
+            @Override
+            public NamespaceContext getNamespaceContext() {
+                return writer.getNamespaceContext();
+            }
+
+            @Override
+            public Object getProperty(String s) throws IllegalArgumentException {
+                return writer.getProperty(s);
+            }
+        };  //To change body of implemented methods use File | Settings | File Templates.
+    }
+}
diff --git a/components-starter/camel-jaxb-starter/src/test/resources/address.xsd b/components-starter/camel-jaxb-starter/src/test/resources/address.xsd
new file mode 100644
index 0000000..3cc6cef
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/resources/address.xsd
@@ -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.
+
+-->
+<xs:schema attributeFormDefault="unqualified"
+           elementFormDefault="qualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:p="org.person"
+           targetNamespace="address.jaxb.converter.camel.apache.org">
+
+    <xs:complexType name="address">
+        <xs:sequence>
+            <xs:element name="addressLine1" type="xs:string" minOccurs="1" />
+            <xs:element name="addressLine2" type="xs:string" minOccurs="0"/>
+        </xs:sequence>
+    </xs:complexType>
+</xs:schema>
\ No newline at end of file
diff --git a/components-starter/camel-jaxb-starter/src/test/resources/message.xml b/components-starter/camel-jaxb-starter/src/test/resources/message.xml
new file mode 100644
index 0000000..6afe321
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/resources/message.xml
@@ -0,0 +1,22 @@
+<?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.
+
+-->
+<tns:message xmlns:tns="address.jaxb.converter.camel.apache.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="address.jaxb.converter.camel.apache.org message.xsd ">
+  <tns:text>tns:text</tns:text>
+</tns:message>
diff --git a/components-starter/camel-jaxb-starter/src/test/resources/message.xsd b/components-starter/camel-jaxb-starter/src/test/resources/message.xsd
new file mode 100644
index 0000000..a7c0a6d
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/resources/message.xsd
@@ -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.
+
+-->
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+	targetNamespace="message.jaxb.converter.camel.apache.org"
+	xmlns:tns="message.jaxb.converter.camel.apache.org"
+	elementFormDefault="qualified">
+
+	<element name="message" type="tns:Message"></element>
+
+	<complexType name="Message">
+		<sequence>
+			<element name="text" minOccurs="1" type="string" />
+		</sequence>
+	</complexType>
+</schema>
\ No newline at end of file
diff --git a/components-starter/camel-jaxb-starter/src/test/resources/org/apache/camel/example/jaxb.index b/components-starter/camel-jaxb-starter/src/test/resources/org/apache/camel/example/jaxb.index
new file mode 100644
index 0000000..39a554c
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/resources/org/apache/camel/example/jaxb.index
@@ -0,0 +1,23 @@
+## ------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ------------------------------------------------------------------------
+Address
+Order
+PurchaseOrder
+Partial
+Foo
+Bar
+Zot
\ No newline at end of file
diff --git a/components-starter/camel-jaxb-starter/src/test/resources/person.xsd b/components-starter/camel-jaxb-starter/src/test/resources/person.xsd
new file mode 100644
index 0000000..2413511
--- /dev/null
+++ b/components-starter/camel-jaxb-starter/src/test/resources/person.xsd
@@ -0,0 +1,38 @@
+<?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.
+
+-->
+<xs:schema attributeFormDefault="unqualified"
+           elementFormDefault="qualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           xmlns:a="address.jaxb.converter.camel.apache.org"
+           targetNamespace="person.jaxb.converter.camel.apache.org">
+
+    <xs:import schemaLocation="address.xsd" namespace="address.jaxb.converter.camel.apache.org" />
+
+    <xs:element name="person">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="firstName" type="xs:string" minOccurs="1" />
+                <xs:element name="lastName" type="xs:string" minOccurs="1"/>
+                <xs:element name="age" type="xs:int" nillable="true" minOccurs="1"/>
+                <xs:element name="address" type="a:address" minOccurs="1" />
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+</xs:schema>
\ No newline at end of file