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

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

commit 420f0fdfbe68d5f6877867e52bd09c82a0b1ec3e
Author: James Netherton <[email protected]>
AuthorDate: Wed Jul 6 12:51:26 2022 +0100

    Increase JAXB extension test coverage
    
    Fixes #3896
---
 .../ROOT/pages/reference/extensions/jaxb.adoc      |  11 +
 extensions/jaxb/runtime/src/main/doc/usage.adoc    |   7 +
 integration-tests/jaxb/pom.xml                     |   4 +
 .../{model/ObjectFactory.java => JaxbHelper.java}  |  28 +-
 .../quarkus/component/jaxb/it/JaxbProducers.java   | 130 +++++++
 .../quarkus/component/jaxb/it/JaxbResource.java    | 338 +++++++++++++++---
 .../camel/quarkus/component/jaxb/it/JaxbRoute.java | 121 ++++++-
 .../jaxb/it/converter/PojoPersonConverter.java     |  44 +++
 .../quarkus/component/jaxb/it/model/Person.java    |  99 +----
 .../model/factory/FactoryInstantiatedPerson.java   |  68 ++++
 .../jaxb/it/model/{ => factory}/ObjectFactory.java |  23 +-
 .../NamespacedPerson.java}                         |  84 ++---
 .../it/model/{ => namespaced}/ObjectFactory.java   |  13 +-
 .../jaxb/it/model/{ => partial}/ObjectFactory.java |  13 +-
 .../jaxb/it/model/partial/PartClassPerson.java     |  77 ++++
 .../package-info.java}                             |  26 +-
 .../component/jaxb/it/model/pojo/PojoPerson.java   |  65 ++++
 .../jaxb/it/model/{ => simple}/ObjectFactory.java  |  22 +-
 .../{Person.java => simple/SimplePerson.java}      |  84 ++---
 .../jaxb/it/writer/CustomXmlStreamWriter.java      | 199 +++++++++++
 .../jaxb/src/main/resources/application.properties |  11 +-
 .../component/jaxb/it/model/pojo/jaxb.index}       |  10 +-
 .../jaxb/src/main/resources/person.xsd             |   7 +-
 .../camel/quarkus/component/jaxb/it/JaxbTest.java  | 397 +++++++++++++++++++--
 pom.xml                                            |   1 +
 25 files changed, 1466 insertions(+), 416 deletions(-)

diff --git a/docs/modules/ROOT/pages/reference/extensions/jaxb.adoc 
b/docs/modules/ROOT/pages/reference/extensions/jaxb.adoc
index 890d7abe76..75eca7ed99 100644
--- a/docs/modules/ROOT/pages/reference/extensions/jaxb.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/jaxb.adoc
@@ -38,3 +38,14 @@ Or add the coordinates to your existing project:
 ----
 
 Check the xref:user-guide/index.adoc[User guide] for more information about 
writing Camel Quarkus applications.
+
+== Usage
+
+=== Native mode `ObjectFactory` instantiation of non-JAXB annotated classes
+
+When performing JAXB marshal operations with a custom `ObjectFactory` to 
instantiate POJO classes that do not have JAXB annotations,
+you must register those POJO classes for reflection in order for them to be 
instantiated in native mode. E.g via the `@RegisterForReflection`
+annotation or configuration property 
`quarkus.camel.native.reflection.include-patterns`.
+
+Refer to the xref:user-guide/native-mode.adoc#reflection[Native mode] user 
guide for more information.
+
diff --git a/extensions/jaxb/runtime/src/main/doc/usage.adoc 
b/extensions/jaxb/runtime/src/main/doc/usage.adoc
new file mode 100644
index 0000000000..6e56d0fdd4
--- /dev/null
+++ b/extensions/jaxb/runtime/src/main/doc/usage.adoc
@@ -0,0 +1,7 @@
+=== Native mode `ObjectFactory` instantiation of non-JAXB annotated classes
+
+When performing JAXB marshal operations with a custom `ObjectFactory` to 
instantiate POJO classes that do not have JAXB annotations,
+you must register those POJO classes for reflection in order for them to be 
instantiated in native mode. E.g via the `@RegisterForReflection`
+annotation or configuration property 
`quarkus.camel.native.reflection.include-patterns`.
+
+Refer to the xref:user-guide/native-mode.adoc#reflection[Native mode] user 
guide for more information.
diff --git a/integration-tests/jaxb/pom.xml b/integration-tests/jaxb/pom.xml
index 6d81694e56..2be764b776 100644
--- a/integration-tests/jaxb/pom.xml
+++ b/integration-tests/jaxb/pom.xml
@@ -43,6 +43,10 @@
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-resteasy</artifactId>
         </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-rest-client-jsonb</artifactId>
+        </dependency>
 
         <!-- test dependencies -->
         <dependency>
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbHelper.java
similarity index 60%
copy from 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
copy to 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbHelper.java
index 46f83efa48..9d13549aef 100644
--- 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbHelper.java
@@ -14,24 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.jaxb.it.model;
+package org.apache.camel.quarkus.component.jaxb.it;
 
-import javax.xml.bind.annotation.XmlRegistry;
+import javax.json.Json;
+import javax.json.JsonObject;
 
-@XmlRegistry
-public class ObjectFactory {
+import org.apache.camel.quarkus.component.jaxb.it.model.Person;
 
-    /**
-     * 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() {
+public final class JaxbHelper {
+
+    private JaxbHelper() {
+        // Utility class
     }
 
-    /**
-     * Create an instance of {@link Person }
-     */
-    public Person createPerson() {
-        return new Person();
+    public static JsonObject personToJson(Person person) {
+        return Json.createObjectBuilder()
+                .add("firstName", person.getFirstName())
+                .add("lastName", person.getLastName())
+                .add("age", person.getAge())
+                .build();
     }
 }
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbProducers.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbProducers.java
new file mode 100644
index 0000000000..956d76c255
--- /dev/null
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbProducers.java
@@ -0,0 +1,130 @@
+/*
+ * 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.quarkus.component.jaxb.it;
+
+import java.util.Map;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.xml.bind.Marshaller;
+import javax.xml.namespace.QName;
+
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import 
org.apache.camel.quarkus.component.jaxb.it.model.namespaced.NamespacedPerson;
+import 
org.apache.camel.quarkus.component.jaxb.it.model.partial.PartClassPerson;
+import org.apache.camel.quarkus.component.jaxb.it.model.pojo.PojoPerson;
+import org.apache.camel.quarkus.component.jaxb.it.model.simple.SimplePerson;
+import org.apache.camel.quarkus.component.jaxb.it.writer.CustomXmlStreamWriter;
+
+public class JaxbProducers {
+
+    @Singleton
+    @Named("jaxbDefault")
+    public JaxbDataFormat defaultJaxbDataFormat() {
+        JaxbDataFormat dataFormat = new JaxbDataFormat();
+        dataFormat.setContextPath(SimplePerson.class.getPackageName());
+        dataFormat.setFragment(true);
+        dataFormat.setIgnoreJAXBElement(false);
+        dataFormat.setPrettyPrint(false);
+        dataFormat.setSchema("classpath:person.xsd");
+        dataFormat.setSchemaSeverityLevel(2);
+        return dataFormat;
+    }
+
+    @Singleton
+    @Named("jaxbWithNamespacePrefix")
+    public JaxbDataFormat jaxbDataFormatWithNamespacePrefix() {
+        JaxbDataFormat dataFormat = new JaxbDataFormat();
+        dataFormat.setContextPath(NamespacedPerson.class.getPackageName());
+        dataFormat.setNamespacePrefix(Map.of("https://example.com/a";, "test"));
+        return dataFormat;
+    }
+
+    @Singleton
+    @Named("jaxbWithEncoding")
+    public JaxbDataFormat jaxbDataFormatWithCustomCharset() {
+        JaxbDataFormat dataFormat = new JaxbDataFormat();
+        dataFormat.setContextPath(SimplePerson.class.getPackageName());
+        dataFormat.setEncoding("ISO-8859-1");
+        dataFormat.setFilterNonXmlChars(true);
+        return dataFormat;
+    }
+
+    @Singleton
+    @Named("jaxbWithMustBeJAXBElementFalse")
+    public JaxbDataFormat jaxbDataFormatWithMustBeJAXBElementFalse() {
+        JaxbDataFormat dataFormat = new JaxbDataFormat();
+        dataFormat.setMustBeJAXBElement(false);
+        return dataFormat;
+    }
+
+    @Singleton
+    @Named("jaxbWithPartClass")
+    public JaxbDataFormat jaxbWithPartClass() {
+        JaxbDataFormat dataFormat = new JaxbDataFormat();
+        dataFormat.setContextPath(PartClassPerson.class.getPackageName());
+        dataFormat.setPartClass(PartClassPerson.class);
+        dataFormat.setPartNamespace(new QName(PartClassPerson.NAMESPACE, 
"person"));
+        return dataFormat;
+    }
+
+    @Singleton
+    @Named("jaxbWithIgnoreElement")
+    public JaxbDataFormat jaxbWithIgnoreElement() {
+        JaxbDataFormat dataFormat = new JaxbDataFormat();
+        dataFormat.setContextPath(PartClassPerson.class.getPackageName());
+        dataFormat.setIgnoreJAXBElement(false);
+        dataFormat.setPartClass(PartClassPerson.class);
+        dataFormat.setPartNamespace(new QName(PartClassPerson.NAMESPACE, 
"person"));
+        return dataFormat;
+    }
+
+    @Singleton
+    @Named("jaxbWithCustomProperties")
+    public JaxbDataFormat jaxbWithCustomProperties() {
+        String packages = String.format("%s:%s",
+                SimplePerson.class.getPackageName(),
+                NamespacedPerson.class.getPackageName());
+        JaxbDataFormat dataFormat = new JaxbDataFormat(packages);
+        
dataFormat.setJaxbProviderProperties(Map.of(Marshaller.JAXB_FORMATTED_OUTPUT, 
Boolean.FALSE));
+        return dataFormat;
+    }
+
+    @Singleton
+    @Named("jaxbWithCustomStreamWriter")
+    public JaxbDataFormat jaxbWithCustomStreamWriter() {
+        JaxbDataFormat dataFormat = new 
JaxbDataFormat(SimplePerson.class.getPackageName());
+        dataFormat.setXmlStreamWriterWrapper(new CustomXmlStreamWriter());
+        return dataFormat;
+    }
+
+    @Singleton
+    @Named("jaxbWithoutObjectFactory")
+    public JaxbDataFormat jaxbWithoutObjectFactory() {
+        JaxbDataFormat dataFormat = new 
JaxbDataFormat(PojoPerson.class.getPackageName());
+        dataFormat.setObjectFactory(false);
+        return dataFormat;
+    }
+
+    @Singleton
+    @Named("jaxbWithNoNamespaceSchemaLocation")
+    public JaxbDataFormat jaxbWithNoNamespaceSchemaLocation() {
+        JaxbDataFormat dataFormat = new 
JaxbDataFormat(SimplePerson.class.getPackageName());
+        dataFormat.setNoNamespaceSchemaLocation("person-no-namespace.xsd");
+        return dataFormat;
+    }
+}
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbResource.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbResource.java
index 6c37679dcf..b876e4d8f1 100644
--- 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbResource.java
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbResource.java
@@ -16,87 +16,321 @@
  */
 package org.apache.camel.quarkus.component.jaxb.it;
 
-import java.net.URI;
-
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
 import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import javax.xml.bind.JAXBElement;
 
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.quarkus.component.jaxb.it.model.Person;
-import org.jboss.logging.Logger;
+import 
org.apache.camel.quarkus.component.jaxb.it.model.factory.FactoryInstantiatedPerson;
+import 
org.apache.camel.quarkus.component.jaxb.it.model.namespaced.NamespacedPerson;
+import 
org.apache.camel.quarkus.component.jaxb.it.model.partial.PartClassPerson;
+import org.apache.camel.quarkus.component.jaxb.it.model.pojo.PojoPerson;
+import org.apache.camel.quarkus.component.jaxb.it.model.simple.SimplePerson;
+import org.apache.camel.util.ObjectHelper;
+
+import static 
org.apache.camel.quarkus.component.jaxb.it.JaxbHelper.personToJson;
 
 @Path("/jaxb")
 @ApplicationScoped
 public class JaxbResource {
 
-    private static final Logger LOG = Logger.getLogger(JaxbResource.class);
-
     @Inject
     ProducerTemplate producerTemplate;
 
-    @Path("/unmarshal-lastname")
+    @Path("/marshal")
+    @GET
+    @Produces(MediaType.APPLICATION_XML)
+    public Response marshal(
+            @QueryParam("firstName") String firstName,
+            @QueryParam("lastName") String lastName,
+            @QueryParam("age") int age) {
+
+        Person person = new SimplePerson();
+        person.setFirstName(firstName);
+        person.setLastName(lastName);
+        person.setAge(age);
+
+        Exchange result = producerTemplate.request("direct:marshal", new 
Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getMessage().setBody(person);
+            }
+        });
+
+        Exception exception = result.getException();
+        if (exception != null) {
+            String xml = String.format("<error>%s</error>", 
exception.getMessage());
+            return Response.serverError().entity(xml).build();
+        }
+
+        Message message = result.getMessage();
+        String contentType = message.getHeader(Exchange.CONTENT_TYPE, 
String.class);
+        String xml = message.getBody(String.class);
+
+        if (ObjectHelper.isEmpty(contentType) || 
!contentType.equals("application/xml")) {
+            throw new IllegalStateException("Expected content type 
application/xml but got " + contentType);
+        }
+
+        if (xml.startsWith("<?xml")) {
+            throw new IllegalStateException("XML prolog was not expected as 
JaxbDataFormat.fragment = true");
+        }
+
+        return Response.ok(xml).build();
+    }
+
+    @Path("/unmarshal")
     @POST
     @Consumes(MediaType.APPLICATION_XML)
-    @Produces(MediaType.TEXT_PLAIN)
-    public Response unmarshalLastNameFromXml(String message) throws Exception {
-        LOG.infof("Sending to jaxb: %s", message);
-        final Person response = 
producerTemplate.requestBody("direct:unmarshal", message, Person.class);
-        LOG.infof("Got response from jaxb: %s", response);
-        return Response
-                .created(new URI("https://camel.apache.org/";))
-                .entity(response.getLastName())
-                .build();
-    }
-
-    @Path("/unmarshal-firstname")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response unmarshal(String xml) {
+        Exchange result = producerTemplate.request("direct:unmarshal", new 
Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getMessage().setBody(xml);
+            }
+        });
+
+        Exception exception = result.getException();
+        if (exception != null) {
+            String errorXml = String.format("{\"error\": \"%s\"}", 
exception.getMessage());
+            return Response.serverError().entity(errorXml).build();
+        }
+
+        Person person = result.getMessage().getBody(SimplePerson.class);
+        return Response.ok(personToJson(person)).build();
+    }
+
+    @Path("/marshal/dsl")
+    @GET
+    @Produces(MediaType.APPLICATION_XML)
+    public Response marshalWithJaxbDsl(
+            @QueryParam("firstName") String firstName,
+            @QueryParam("lastName") String lastName,
+            @QueryParam("age") int age) {
+
+        Person person = new SimplePerson();
+        person.setFirstName(firstName);
+        person.setLastName(lastName);
+        person.setAge(age);
+
+        String xml = producerTemplate.requestBody("direct:marshalJaxbDsl", 
person, String.class);
+
+        return Response.ok(xml).build();
+    }
+
+    @Path("/unmarshal/dsl")
     @POST
     @Consumes(MediaType.APPLICATION_XML)
-    @Produces(MediaType.TEXT_PLAIN)
-    public Response unmarshalFirstNameFromXml(String message) throws Exception 
{
-        LOG.infof("Sending to jaxb: %s", message);
-        final Person response = 
producerTemplate.requestBody("direct:unmarshal-2", message, Person.class);
-        LOG.infof("Got response from jaxb: %s", response);
-        return Response
-                .created(new URI("https://camel.apache.org/";))
-                .entity(response.getFirstName())
-                .build();
-    }
-
-    @Path("/marshal-firstname")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response unmarshalWithJaxbDsl(String xml) {
+        Person person = 
producerTemplate.requestBody("direct:unmarshalJaxbDsl", xml, Person.class);
+        return Response.ok(personToJson(person)).build();
+    }
+
+    @Path("/marshal/namespace/prefix")
+    @GET
+    @Produces(MediaType.APPLICATION_XML)
+    public Response marshalWithNamespacePrefix(
+            @QueryParam("firstName") String firstName,
+            @QueryParam("lastName") String lastName,
+            @QueryParam("age") int age) {
+
+        Person person = new NamespacedPerson();
+        person.setFirstName(firstName);
+        person.setLastName(lastName);
+        person.setAge(age);
+
+        String xml = 
producerTemplate.requestBody("direct:marshalNamespacePrefix", person, 
String.class);
+
+        return Response.ok(xml).build();
+    }
+
+    @Path("/unmarshal/namespace/prefix")
     @POST
-    @Consumes(MediaType.TEXT_PLAIN)
+    @Consumes(MediaType.APPLICATION_XML)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response unmarshalWithNamespacePrefix(String xml) {
+        Person person = 
producerTemplate.requestBody("direct:unmarshalNamespacePrefix", xml, 
NamespacedPerson.class);
+        return Response.ok(personToJson(person)).build();
+    }
+
+    @Path("/marshal/encoding")
+    @GET
     @Produces(MediaType.APPLICATION_XML)
-    public Response marshallFirstName(String name) throws Exception {
-        Person p = new Person();
-        p.setFirstName(name);
+    public Response marshalWithEncoding(
+            @QueryParam("firstName") String firstName,
+            @QueryParam("lastName") String lastName,
+            @QueryParam("age") int age) {
+
+        Person person = new SimplePerson();
+        person.setFirstName(firstName);
+        person.setLastName(lastName);
+        person.setAge(age);
+
+        String xml = producerTemplate.requestBody("direct:marshalEncoding", 
person, String.class);
+
+        return Response.ok(xml).build();
+    }
 
-        String response = producerTemplate.requestBody("direct:marshal", p, 
String.class);
-        LOG.infof("Got response from jaxb=>: %s", response);
-        return Response
-                .created(new URI("https://camel.apache.org/";))
-                .entity(response)
-                .build();
+    @Path("/unmarshal/encoding")
+    @POST
+    @Consumes(MediaType.APPLICATION_XML)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response unmarshalWithEncoding(String xml) {
+        Person person = 
producerTemplate.requestBody("direct:unmarshalEncoding", xml, 
SimplePerson.class);
+        return Response.ok(personToJson(person)).build();
     }
 
-    @Path("/marshal-lastname")
+    @Path("/marshal/xml")
     @POST
-    @Consumes(MediaType.TEXT_PLAIN)
+    @Consumes(MediaType.APPLICATION_XML)
     @Produces(MediaType.APPLICATION_XML)
-    public Response marshallLastName(String name) throws Exception {
-        Person p = new Person();
-        p.setLastName(name);
-
-        String response = producerTemplate.requestBody("direct:marshal-2", p, 
String.class);
-        LOG.infof("Got response from jaxb=>: %s", response);
-        return Response
-                .created(new URI("https://camel.apache.org/";))
-                .entity(response)
-                .build();
+    public Response marshalWithExistingXmlPayload(String xml) {
+        String response = 
producerTemplate.requestBody("direct:marshalWithMustBeJAXBElementFalse", xml, 
String.class);
+        return Response.ok(response).build();
+    }
+
+    @Path("/marshal/part/class")
+    @GET
+    @Produces(MediaType.APPLICATION_XML)
+    public Response marshalPartial(
+            @QueryParam("firstName") String firstName,
+            @QueryParam("lastName") String lastName,
+            @QueryParam("age") int age,
+            @QueryParam("useHeader") boolean useHeader) {
+
+        Person person = new PartClassPerson();
+        person.setFirstName(firstName);
+        person.setLastName(lastName);
+        person.setAge(age);
+
+        String uri = useHeader ? "direct:marshalPartClassFromHeader" : 
"direct:marshalPartClass";
+
+        String response = producerTemplate.requestBody(uri, person, 
String.class);
+        return Response.ok(response).build();
+    }
+
+    @Path("/unmarshal/part/class")
+    @POST
+    @Consumes(MediaType.APPLICATION_XML)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response unmarshalPartial(@QueryParam("useHeader") boolean 
useHeader, String xml) {
+        String uri = useHeader ? "direct:unmarshalPartClassFromHeader" : 
"direct:unmarshalPartClass";
+
+        Person person = producerTemplate.requestBody(uri, xml, 
PartClassPerson.class);
+        return Response.ok(personToJson(person)).build();
+    }
+
+    @Path("/unmarshal/ignore/element")
+    @POST
+    @Consumes(MediaType.APPLICATION_XML)
+    @Produces(MediaType.APPLICATION_JSON)
+    @SuppressWarnings("unchecked")
+    public Response unmarshalWithIgnoreJaxbElement(String xml) {
+        JAXBElement<Person> element = 
producerTemplate.requestBody("direct:unmarshalIgnoreJaxbElement", xml, 
JAXBElement.class);
+        Person person = element.getValue();
+        return Response.ok(personToJson(person)).build();
+    }
+
+    @Path("/marshal/custom/properties")
+    @GET
+    @Produces(MediaType.APPLICATION_XML)
+    public Response marshalWithCustomProperties(
+            @QueryParam("firstName") String firstName,
+            @QueryParam("lastName") String lastName,
+            @QueryParam("age") int age) {
+
+        Person person = new SimplePerson();
+        person.setFirstName(firstName);
+        person.setLastName(lastName);
+        person.setAge(age);
+
+        String xml = 
producerTemplate.requestBody("direct:marshalCustomProperties", person, 
String.class);
+
+        return Response.ok(xml).build();
+    }
+
+    @Path("/marshal/custom/stream/writer")
+    @GET
+    @Produces(MediaType.APPLICATION_XML)
+    public Response marshalWithCustomStreamWriter(
+            @QueryParam("firstName") String firstName,
+            @QueryParam("lastName") String lastName,
+            @QueryParam("age") int age) {
+
+        Person person = new SimplePerson();
+        person.setFirstName(firstName);
+        person.setLastName(lastName);
+        person.setAge(age);
+
+        String xml = 
producerTemplate.requestBody("direct:marshalCustomStreamWriter", person, 
String.class);
+
+        return Response.ok(xml).build();
+    }
+
+    @Path("/marshal/with/object/factory")
+    @GET
+    @Produces(MediaType.APPLICATION_XML)
+    public Response marshalWithObjectFactory(
+            @QueryParam("firstName") String firstName,
+            @QueryParam("lastName") String lastName,
+            @QueryParam("age") int age) {
+
+        Person person = new FactoryInstantiatedPerson();
+        person.setFirstName(firstName);
+        person.setLastName(lastName);
+        person.setAge(age);
+
+        String xml = 
producerTemplate.requestBody("direct:marshalWithObjectFactory", person, 
String.class);
+
+        return Response.ok(xml).build();
+    }
+
+    @Path("/marshal/without/object/factory")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response marshalWithoutObjectFactory(
+            @QueryParam("firstName") String firstName,
+            @QueryParam("lastName") String lastName,
+            @QueryParam("age") int age) {
+
+        Person person = new PojoPerson();
+        person.setFirstName(firstName);
+        person.setLastName(lastName);
+        person.setAge(age);
+
+        String json = 
producerTemplate.requestBody("direct:marshalWithoutObjectFactory", person, 
String.class);
+
+        return Response.ok(json).build();
+    }
+
+    @Path("/marshal/non/namespace/schema/location")
+    @GET
+    @Produces(MediaType.APPLICATION_XML)
+    public Response marshalWithNoNamespaceSchemaLocation(
+            @QueryParam("firstName") String firstName,
+            @QueryParam("lastName") String lastName,
+            @QueryParam("age") int age) {
+
+        Person person = new SimplePerson();
+        person.setFirstName(firstName);
+        person.setLastName(lastName);
+        person.setAge(age);
+
+        String xml = 
producerTemplate.requestBody("direct:marshalNoNamespaceSchemaLocation", person, 
String.class);
+
+        return Response.ok(xml).build();
     }
 }
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbRoute.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbRoute.java
index 6c64560d66..bde02e28e8 100644
--- 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbRoute.java
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/JaxbRoute.java
@@ -16,38 +16,121 @@
  */
 package org.apache.camel.quarkus.component.jaxb.it;
 
-import java.util.Map;
-
-import javax.xml.bind.JAXBContext;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.inject.Named;
 
 import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.converter.jaxb.JaxbConstants;
 import org.apache.camel.converter.jaxb.JaxbDataFormat;
-import org.apache.camel.quarkus.component.jaxb.it.model.Person;
+import 
org.apache.camel.quarkus.component.jaxb.it.model.factory.FactoryInstantiatedPerson;
+import 
org.apache.camel.quarkus.component.jaxb.it.model.partial.PartClassPerson;
+import org.apache.camel.quarkus.component.jaxb.it.model.simple.SimplePerson;
 
+@ApplicationScoped
 public class JaxbRoute extends RouteBuilder {
 
-    @Override
-    public void configure() throws Exception {
+    @Inject
+    @Named("jaxbDefault")
+    JaxbDataFormat defaultJaxbDataFormat;
 
-        JaxbDataFormat xml = new JaxbDataFormat();
-        JAXBContext context = JAXBContext.newInstance(Person.class);
-        xml.setContext(context);
-        xml.setNamespacePrefix(Map.of("http://example.com/a";, "test"));
+    @Inject
+    @Named("jaxbWithNamespacePrefix")
+    JaxbDataFormat jaxbDataFormatWithNamespacePrefix;
 
-        JaxbDataFormat jaxbFromScheme = new JaxbDataFormat();
-        jaxbFromScheme.setSchema("classpath:person.xsd");
+    @Inject
+    @Named("jaxbWithEncoding")
+    JaxbDataFormat jaxbDataFormatWithEncoding;
 
-        from("direct:unmarshal")
-                
.unmarshal().jaxb("org.apache.camel.quarkus.component.jaxb.it.model");
+    @Inject
+    @Named("jaxbWithMustBeJAXBElementFalse")
+    JaxbDataFormat jaxbDataFormatWithMustBeJAXBElementFalse;
+
+    @Inject
+    @Named("jaxbWithPartClass")
+    JaxbDataFormat jaxbDataFormatWithPartClass;
+
+    @Inject
+    @Named("jaxbWithIgnoreElement")
+    JaxbDataFormat jaxbDataFormatIgnoreElement;
+
+    @Inject
+    @Named("jaxbWithCustomProperties")
+    JaxbDataFormat jaxbDataFormatCustomProperties;
+
+    @Inject
+    @Named("jaxbWithCustomStreamWriter")
+    JaxbDataFormat jaxbDataFormatCustomStreamWriter;
 
-        from("direct:unmarshal-2")
-                .unmarshal(xml);
+    @Inject
+    @Named("jaxbWithoutObjectFactory")
+    JaxbDataFormat jaxbDataFormatWithoutObjectFactory;
 
+    @Inject
+    @Named("jaxbWithNoNamespaceSchemaLocation")
+    JaxbDataFormat jaxbDataFormatNoNamespaceSchemaLocation;
+
+    @Override
+    public void configure() {
         from("direct:marshal")
-                .marshal(jaxbFromScheme);
+                .marshal(defaultJaxbDataFormat);
+
+        from("direct:unmarshal")
+                .unmarshal(defaultJaxbDataFormat);
+
+        from("direct:marshalJaxbDsl")
+                .marshal().jaxb(SimplePerson.class.getPackageName());
+
+        from("direct:unmarshalJaxbDsl")
+                .unmarshal().jaxb(SimplePerson.class.getPackageName());
+
+        from("direct:marshalNamespacePrefix")
+                .marshal(jaxbDataFormatWithNamespacePrefix);
+
+        from("direct:unmarshalNamespacePrefix")
+                .unmarshal(jaxbDataFormatWithNamespacePrefix);
+
+        from("direct:marshalEncoding")
+                .marshal(jaxbDataFormatWithEncoding);
+
+        from("direct:unmarshalEncoding")
+                .unmarshal(jaxbDataFormatWithEncoding);
+
+        from("direct:marshalWithMustBeJAXBElementFalse")
+                .marshal(jaxbDataFormatWithMustBeJAXBElementFalse);
+
+        from("direct:marshalPartClass")
+                .marshal(jaxbDataFormatWithPartClass);
+
+        from("direct:marshalPartClassFromHeader")
+                .setHeader(JaxbConstants.JAXB_PART_CLASS, 
constant(PartClassPerson.class.getName()))
+                .setHeader(JaxbConstants.JAXB_PART_NAMESPACE, 
constant(String.format("{%s}person", PartClassPerson.NAMESPACE)))
+                .marshal().jaxb(PartClassPerson.class.getPackageName());
+
+        from("direct:unmarshalPartClass")
+                .unmarshal(jaxbDataFormatWithPartClass);
+
+        from("direct:unmarshalPartClassFromHeader")
+                .setHeader(JaxbConstants.JAXB_PART_CLASS, 
constant(PartClassPerson.class.getName()))
+                .setHeader(JaxbConstants.JAXB_PART_NAMESPACE, 
constant(String.format("{%s}person", PartClassPerson.NAMESPACE)))
+                .unmarshal().jaxb(PartClassPerson.class.getPackageName());
+
+        from("direct:unmarshalIgnoreJaxbElement")
+                .unmarshal(jaxbDataFormatIgnoreElement);
+
+        from("direct:marshalCustomProperties")
+                .marshal(jaxbDataFormatCustomProperties);
+
+        from("direct:marshalCustomStreamWriter")
+                .marshal(jaxbDataFormatCustomStreamWriter);
+
+        from("direct:marshalWithoutObjectFactory")
+                .marshal(jaxbDataFormatWithoutObjectFactory);
 
-        from("direct:marshal-2")
-                .marshal(xml);
+        from("direct:marshalNoNamespaceSchemaLocation")
+                .marshal(jaxbDataFormatNoNamespaceSchemaLocation);
 
+        from("direct:marshalWithObjectFactory")
+                
.marshal().jaxb(FactoryInstantiatedPerson.class.getPackageName());
     }
 }
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/converter/PojoPersonConverter.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/converter/PojoPersonConverter.java
new file mode 100644
index 0000000000..cf32fe34f0
--- /dev/null
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/converter/PojoPersonConverter.java
@@ -0,0 +1,44 @@
+/*
+ * 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.quarkus.component.jaxb.it.converter;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+
+import javax.json.Json;
+
+import org.apache.camel.Converter;
+import org.apache.camel.quarkus.component.jaxb.it.model.pojo.PojoPerson;
+
+import static 
org.apache.camel.quarkus.component.jaxb.it.JaxbHelper.personToJson;
+
+/**
+ * Enables type conversion fallback to {@link InputStream} when 
JaxbDataFormat.setObjectFactory(false).
+ */
+@Converter
+public class PojoPersonConverter {
+
+    @Converter
+    public static InputStream toInputStream(PojoPerson person) {
+        StringWriter writer = new StringWriter();
+        Json.createWriter(writer).write(personToJson(person));
+        byte[] json = writer.toString().getBytes(StandardCharsets.UTF_8);
+        return new ByteArrayInputStream(json);
+    }
+}
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/Person.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/Person.java
index 24e3567f1a..8af0e06ba5 100644
--- 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/Person.java
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/Person.java
@@ -16,101 +16,16 @@
  */
 package org.apache.camel.quarkus.component.jaxb.it.model;
 
-import javax.xml.bind.annotation.*;
+public interface Person {
+    String getFirstName();
 
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "", propOrder = { "firstName", "lastName", "age" })
-@XmlRootElement(name = "person")
-public class Person {
+    void setFirstName(String value);
 
-    @XmlElement(required = true, namespace = "http://example.com/a";)
-    protected String firstName = "John";
-    @XmlElement(required = true, namespace = "http://example.com/a";)
-    protected String lastName = "Doe";
-    @XmlElement(required = true, type = Integer.class, nillable = true)
-    protected Integer age = 33;
+    String getLastName();
 
-    /**
-     * Gets the value of the firstName property.
-     *
-     * @return possible object is
-     *         {@link String }
-     */
-    public String getFirstName() {
-        return firstName;
-    }
+    void setLastName(String value);
 
-    /**
-     * Sets the value of the firstName property.
-     *
-     * @param value allowed object is
-     *              {@link String }
-     */
-    public void setFirstName(String value) {
-        this.firstName = value;
-    }
+    Integer getAge();
 
-    /**
-     * 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;
-    }
-
-    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;
-    }
-
-    @Override
-    public String toString() {
-        return "Person{" +
-                "firstName='" + firstName + '\'' +
-                ", lastName='" + lastName + '\'' +
-                ", age=" + age +
-                '}';
-    }
+    void setAge(Integer value);
 }
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/factory/FactoryInstantiatedPerson.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/factory/FactoryInstantiatedPerson.java
new file mode 100644
index 0000000000..b422f3e7af
--- /dev/null
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/factory/FactoryInstantiatedPerson.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.quarkus.component.jaxb.it.model.factory;
+
+import io.quarkus.runtime.annotations.RegisterForReflection;
+import org.apache.camel.quarkus.component.jaxb.it.model.Person;
+
+@RegisterForReflection(fields = false)
+public class FactoryInstantiatedPerson implements Person {
+    public static final String NAMESPACE = "https://example.com/person";;
+
+    protected String firstName;
+    protected String lastName;
+    protected Integer age;
+
+    @Override
+    public String getFirstName() {
+        return firstName;
+    }
+
+    @Override
+    public void setFirstName(String value) {
+        this.firstName = value;
+    }
+
+    @Override
+    public String getLastName() {
+        return lastName;
+    }
+
+    @Override
+    public void setLastName(String value) {
+        this.lastName = value;
+    }
+
+    @Override
+    public Integer getAge() {
+        return age;
+    }
+
+    @Override
+    public void setAge(Integer value) {
+        this.age = value;
+    }
+
+    @Override
+    public String toString() {
+        return "FactoryInstantiatedPerson{" +
+                "firstName='" + firstName + '\'' +
+                ", lastName='" + lastName + '\'' +
+                ", age=" + age +
+                '}';
+    }
+}
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/factory/ObjectFactory.java
similarity index 60%
copy from 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
copy to 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/factory/ObjectFactory.java
index 46f83efa48..c5199b3052 100644
--- 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/factory/ObjectFactory.java
@@ -14,24 +14,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.jaxb.it.model;
+package org.apache.camel.quarkus.component.jaxb.it.model.factory;
 
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
 import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
 
 @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();
+    public FactoryInstantiatedPerson createFactoryInstantiatedPerson() {
+        return new FactoryInstantiatedPerson();
+    }
+
+    @XmlElementDecl(namespace = "", name = "person")
+    public JAXBElement<FactoryInstantiatedPerson> 
createPerson(FactoryInstantiatedPerson value) {
+        return new JAXBElement<>(new 
QName(FactoryInstantiatedPerson.NAMESPACE, "person"), 
FactoryInstantiatedPerson.class,
+                null, value);
     }
 }
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/Person.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/namespaced/NamespacedPerson.java
similarity index 51%
copy from 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/Person.java
copy to 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/namespaced/NamespacedPerson.java
index 24e3567f1a..8457f36cbf 100644
--- 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/Person.java
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/namespaced/NamespacedPerson.java
@@ -14,100 +14,62 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.jaxb.it.model;
+package org.apache.camel.quarkus.component.jaxb.it.model.namespaced;
 
-import javax.xml.bind.annotation.*;
+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.quarkus.component.jaxb.it.model.Person;
 
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name = "", propOrder = { "firstName", "lastName", "age" })
 @XmlRootElement(name = "person")
-public class Person {
+public class NamespacedPerson implements Person {
 
-    @XmlElement(required = true, namespace = "http://example.com/a";)
-    protected String firstName = "John";
-    @XmlElement(required = true, namespace = "http://example.com/a";)
-    protected String lastName = "Doe";
-    @XmlElement(required = true, type = Integer.class, nillable = true)
-    protected Integer age = 33;
+    public static final String NAMESPACE = "https://example.com/a";;
+    @XmlElement(required = true, namespace = NAMESPACE)
+    protected String firstName;
+    @XmlElement(required = true, namespace = NAMESPACE)
+    protected String lastName;
+    @XmlElement(required = true, type = Integer.class, nillable = true, 
namespace = NAMESPACE)
+    protected Integer age;
 
-    /**
-     * Gets the value of the firstName property.
-     *
-     * @return possible object is
-     *         {@link String }
-     */
+    @Override
     public String getFirstName() {
         return firstName;
     }
 
-    /**
-     * Sets the value of the firstName property.
-     *
-     * @param value allowed object is
-     *              {@link String }
-     */
+    @Override
     public void setFirstName(String value) {
         this.firstName = value;
     }
 
-    /**
-     * Gets the value of the lastName property.
-     *
-     * @return possible object is
-     *         {@link String }
-     */
+    @Override
     public String getLastName() {
         return lastName;
     }
 
-    /**
-     * Sets the value of the lastName property.
-     *
-     * @param value allowed object is
-     *              {@link String }
-     */
+    @Override
     public void setLastName(String value) {
         this.lastName = value;
     }
 
-    /**
-     * Gets the value of the age property.
-     *
-     * @return possible object is
-     *         {@link Integer }
-     */
+    @Override
     public Integer getAge() {
         return age;
     }
 
-    /**
-     * Sets the value of the age property.
-     *
-     * @param value allowed object is
-     *              {@link Integer }
-     */
+    @Override
     public void setAge(Integer value) {
         this.age = 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;
-    }
-
     @Override
     public String toString() {
-        return "Person{" +
+        return "NamespacedPerson{" +
                 "firstName='" + firstName + '\'' +
                 ", lastName='" + lastName + '\'' +
                 ", age=" + age +
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/namespaced/ObjectFactory.java
similarity index 72%
copy from 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
copy to 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/namespaced/ObjectFactory.java
index 46f83efa48..ec0c67a903 100644
--- 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/namespaced/ObjectFactory.java
@@ -14,24 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.jaxb.it.model;
+package org.apache.camel.quarkus.component.jaxb.it.model.namespaced;
 
 import javax.xml.bind.annotation.XmlRegistry;
 
 @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();
+    public NamespacedPerson createNamespacedPerson() {
+        return new NamespacedPerson();
     }
 }
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/partial/ObjectFactory.java
similarity index 72%
copy from 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
copy to 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/partial/ObjectFactory.java
index 46f83efa48..5c418d2048 100644
--- 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/partial/ObjectFactory.java
@@ -14,24 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.jaxb.it.model;
+package org.apache.camel.quarkus.component.jaxb.it.model.partial;
 
 import javax.xml.bind.annotation.XmlRegistry;
 
 @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();
+    public PartClassPerson createPartClassPerson() {
+        return new PartClassPerson();
     }
 }
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/partial/PartClassPerson.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/partial/PartClassPerson.java
new file mode 100644
index 0000000000..eaba91b868
--- /dev/null
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/partial/PartClassPerson.java
@@ -0,0 +1,77 @@
+/*
+ * 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.quarkus.component.jaxb.it.model.partial;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.camel.quarkus.component.jaxb.it.model.Person;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Person")
+public class PartClassPerson implements Person {
+
+    public static final String NAMESPACE = "https://example.com/b";;
+
+    @XmlElement(namespace = NAMESPACE)
+    protected String firstName;
+    @XmlElement(namespace = NAMESPACE)
+    protected String lastName;
+    @XmlElement(namespace = NAMESPACE)
+    protected Integer age;
+
+    @Override
+    public String getFirstName() {
+        return firstName;
+    }
+
+    @Override
+    public void setFirstName(String value) {
+        this.firstName = value;
+    }
+
+    @Override
+    public String getLastName() {
+        return lastName;
+    }
+
+    @Override
+    public void setLastName(String value) {
+        this.lastName = value;
+    }
+
+    @Override
+    public Integer getAge() {
+        return age;
+    }
+
+    @Override
+    public void setAge(Integer value) {
+        this.age = value;
+    }
+
+    @Override
+    public String toString() {
+        return "PartClassPerson{" +
+                "firstName='" + firstName + '\'' +
+                ", lastName='" + lastName + '\'' +
+                ", age=" + age +
+                '}';
+    }
+}
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/partial/package-info.java
similarity index 61%
copy from 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
copy to 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/partial/package-info.java
index 46f83efa48..be71be0b12 100644
--- 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/partial/package-info.java
@@ -14,24 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.jaxb.it.model;
+@XmlSchema(xmlns = {
+        @XmlNs(prefix = "person", namespaceURI = PartClassPerson.NAMESPACE)
+})
+package org.apache.camel.quarkus.component.jaxb.it.model.partial;
 
-import javax.xml.bind.annotation.XmlRegistry;
-
-@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();
-    }
-}
+import javax.xml.bind.annotation.XmlNs;
+import javax.xml.bind.annotation.XmlSchema;
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/pojo/PojoPerson.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/pojo/PojoPerson.java
new file mode 100644
index 0000000000..ed7b950dde
--- /dev/null
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/pojo/PojoPerson.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.jaxb.it.model.pojo;
+
+import org.apache.camel.quarkus.component.jaxb.it.model.Person;
+
+public class PojoPerson implements Person {
+
+    protected String firstName;
+    protected String lastName;
+    protected Integer age;
+
+    @Override
+    public String getFirstName() {
+        return firstName;
+    }
+
+    @Override
+    public void setFirstName(String value) {
+        this.firstName = value;
+    }
+
+    @Override
+    public String getLastName() {
+        return lastName;
+    }
+
+    @Override
+    public void setLastName(String value) {
+        this.lastName = value;
+    }
+
+    @Override
+    public Integer getAge() {
+        return age;
+    }
+
+    @Override
+    public void setAge(Integer value) {
+        this.age = value;
+    }
+
+    @Override
+    public String toString() {
+        return "PojoPerson{" +
+                "firstName='" + firstName + '\'' +
+                ", lastName='" + lastName + '\'' +
+                ", age=" + age +
+                '}';
+    }
+}
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/simple/ObjectFactory.java
similarity index 64%
rename from 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
rename to 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/simple/ObjectFactory.java
index 46f83efa48..c70f4cc74b 100644
--- 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/ObjectFactory.java
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/simple/ObjectFactory.java
@@ -14,24 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.jaxb.it.model;
+package org.apache.camel.quarkus.component.jaxb.it.model.simple;
 
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
 import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
 
 @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();
+    public SimplePerson createSimplePerson() {
+        return new SimplePerson();
+    }
+
+    @XmlElementDecl(namespace = "", name = "Person")
+    public JAXBElement<SimplePerson> createPerson(SimplePerson value) {
+        return new JAXBElement<>(new QName(SimplePerson.NAMESPACE, "person"), 
SimplePerson.class, null, value);
     }
 }
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/Person.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/simple/SimplePerson.java
similarity index 50%
copy from 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/Person.java
copy to 
integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/simple/SimplePerson.java
index 24e3567f1a..67f3824961 100644
--- 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/Person.java
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/model/simple/SimplePerson.java
@@ -14,100 +14,62 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.jaxb.it.model;
+package org.apache.camel.quarkus.component.jaxb.it.model.simple;
 
-import javax.xml.bind.annotation.*;
+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.quarkus.component.jaxb.it.model.Person;
 
 @XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "", propOrder = { "firstName", "lastName", "age" })
+@XmlType(name = "person", propOrder = { "firstName", "lastName", "age" })
 @XmlRootElement(name = "person")
-public class Person {
+public class SimplePerson implements Person {
+    public static final String NAMESPACE = "https://example.com/person";;
 
-    @XmlElement(required = true, namespace = "http://example.com/a";)
-    protected String firstName = "John";
-    @XmlElement(required = true, namespace = "http://example.com/a";)
-    protected String lastName = "Doe";
+    @XmlElement(required = true)
+    protected String firstName;
+    @XmlElement(required = true)
+    protected String lastName;
     @XmlElement(required = true, type = Integer.class, nillable = true)
-    protected Integer age = 33;
+    protected Integer age;
 
-    /**
-     * Gets the value of the firstName property.
-     *
-     * @return possible object is
-     *         {@link String }
-     */
+    @Override
     public String getFirstName() {
         return firstName;
     }
 
-    /**
-     * Sets the value of the firstName property.
-     *
-     * @param value allowed object is
-     *              {@link String }
-     */
+    @Override
     public void setFirstName(String value) {
         this.firstName = value;
     }
 
-    /**
-     * Gets the value of the lastName property.
-     *
-     * @return possible object is
-     *         {@link String }
-     */
+    @Override
     public String getLastName() {
         return lastName;
     }
 
-    /**
-     * Sets the value of the lastName property.
-     *
-     * @param value allowed object is
-     *              {@link String }
-     */
+    @Override
     public void setLastName(String value) {
         this.lastName = value;
     }
 
-    /**
-     * Gets the value of the age property.
-     *
-     * @return possible object is
-     *         {@link Integer }
-     */
+    @Override
     public Integer getAge() {
         return age;
     }
 
-    /**
-     * Sets the value of the age property.
-     *
-     * @param value allowed object is
-     *              {@link Integer }
-     */
+    @Override
     public void setAge(Integer value) {
         this.age = 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;
-    }
-
     @Override
     public String toString() {
-        return "Person{" +
+        return "SimplePerson{" +
                 "firstName='" + firstName + '\'' +
                 ", lastName='" + lastName + '\'' +
                 ", age=" + age +
diff --git 
a/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/writer/CustomXmlStreamWriter.java
 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/writer/CustomXmlStreamWriter.java
new file mode 100644
index 0000000000..fd7d44af73
--- /dev/null
+++ 
b/integration-tests/jaxb/src/main/java/org/apache/camel/quarkus/component/jaxb/it/writer/CustomXmlStreamWriter.java
@@ -0,0 +1,199 @@
+/*
+ * 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.quarkus.component.jaxb.it.writer;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.camel.converter.jaxb.JaxbXmlStreamWriterWrapper;
+
+/**
+ * Custom {@link JaxbXmlStreamWriterWrapper} that appends a suffix to all XML 
tags.
+ */
+public class CustomXmlStreamWriter implements JaxbXmlStreamWriterWrapper {
+    private static final String MODIFIED_XML_TAG_SUFFIX = "-modified";
+
+    @Override
+    public XMLStreamWriter wrapWriter(XMLStreamWriter writer) {
+        return new XMLStreamWriter() {
+            @Override
+            public void writeStartElement(String localName) throws 
XMLStreamException {
+                writer.writeStartElement(localName + MODIFIED_XML_TAG_SUFFIX);
+            }
+
+            @Override
+            public void writeStartElement(String namespaceURI, String 
localName) throws XMLStreamException {
+                writer.writeStartElement(namespaceURI, localName + 
MODIFIED_XML_TAG_SUFFIX);
+
+            }
+
+            @Override
+            public void writeStartElement(String prefix, String localName, 
String namespaceURI) throws XMLStreamException {
+                writer.writeStartElement(prefix, localName + 
MODIFIED_XML_TAG_SUFFIX, namespaceURI);
+            }
+
+            @Override
+            public void writeEmptyElement(String namespaceURI, String 
localName) throws XMLStreamException {
+                writer.writeEmptyElement(namespaceURI, localName);
+            }
+
+            @Override
+            public void writeEmptyElement(String prefix, String localName, 
String namespaceURI) throws XMLStreamException {
+                writer.writeEmptyElement(prefix, localName, namespaceURI);
+            }
+
+            @Override
+            public void writeEmptyElement(String localName) throws 
XMLStreamException {
+                writer.writeEmptyElement(localName);
+            }
+
+            @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 localName, String value) throws 
XMLStreamException {
+                writer.writeAttribute(localName, value);
+            }
+
+            @Override
+            public void writeAttribute(String prefix, String namespaceURI, 
String localName, String value)
+                    throws XMLStreamException {
+                writer.writeAttribute(prefix, namespaceURI, localName, value);
+
+            }
+
+            @Override
+            public void writeAttribute(String namespaceURI, String localName, 
String value) throws XMLStreamException {
+                writer.writeAttribute(namespaceURI, localName, value);
+            }
+
+            @Override
+            public void writeNamespace(String prefix, String namespaceURI) 
throws XMLStreamException {
+                writer.writeNamespace(prefix, namespaceURI);
+            }
+
+            @Override
+            public void writeDefaultNamespace(String namespaceURI) throws 
XMLStreamException {
+                writer.writeDefaultNamespace(namespaceURI);
+            }
+
+            @Override
+            public void writeComment(String data) throws XMLStreamException {
+                writer.writeComment(data);
+            }
+
+            @Override
+            public void writeProcessingInstruction(String target) throws 
XMLStreamException {
+                writer.writeProcessingInstruction(target);
+            }
+
+            @Override
+            public void writeProcessingInstruction(String target, String data) 
throws XMLStreamException {
+                writer.writeProcessingInstruction(target, data);
+
+            }
+
+            @Override
+            public void writeCData(String data) throws XMLStreamException {
+                writer.writeCData(data);
+            }
+
+            @Override
+            public void writeDTD(String dtd) throws XMLStreamException {
+                writer.writeDTD(dtd);
+            }
+
+            @Override
+            public void writeEntityRef(String name) throws XMLStreamException {
+                writer.writeEntityRef(name);
+            }
+
+            @Override
+            public void writeStartDocument() throws XMLStreamException {
+                writer.writeStartDocument();
+            }
+
+            @Override
+            public void writeStartDocument(String version) throws 
XMLStreamException {
+                writer.writeStartDocument(version);
+            }
+
+            @Override
+            public void writeStartDocument(String encoding, String version) 
throws XMLStreamException {
+                writer.writeStartDocument(encoding, version);
+            }
+
+            @Override
+            public void writeCharacters(String text) throws XMLStreamException 
{
+                writer.writeCharacters(text);
+            }
+
+            @Override
+            public void writeCharacters(char[] text, int start, int len) 
throws XMLStreamException {
+                writer.writeCharacters(text, start, len);
+            }
+
+            @Override
+            public String getPrefix(String uri) throws XMLStreamException {
+                return writer.getPrefix(uri);
+            }
+
+            @Override
+            public void setPrefix(String prefix, String uri) throws 
XMLStreamException {
+                writer.setPrefix(prefix, uri);
+            }
+
+            @Override
+            public void setDefaultNamespace(String uri) throws 
XMLStreamException {
+                writer.setDefaultNamespace(uri);
+            }
+
+            @Override
+            public void setNamespaceContext(NamespaceContext context) throws 
XMLStreamException {
+                writer.setNamespaceContext(context);
+            }
+
+            @Override
+            public NamespaceContext getNamespaceContext() {
+                return writer.getNamespaceContext();
+            }
+
+            @Override
+            public Object getProperty(String name) throws 
IllegalArgumentException {
+                return writer.getProperty(name);
+            }
+        };
+    }
+}
diff --git a/integration-tests/jaxb/src/main/resources/application.properties 
b/integration-tests/jaxb/src/main/resources/application.properties
index ff14981f09..f1efc6a7e8 100644
--- a/integration-tests/jaxb/src/main/resources/application.properties
+++ b/integration-tests/jaxb/src/main/resources/application.properties
@@ -16,10 +16,7 @@
 ## limitations under the License.
 ## ---------------------------------------------------------------------------
 
-#
-# Quarkus
-#
-
-## include xml routes and scheme
-quarkus.native.resources.includes = person.xsd
-
+# Note: jaxb.index for the 'pojo' package is added manually since PojoPerson 
is a slight edge case test
+# where it does not have any JAXB annotations. Thus quarkus-jaxb cannot auto 
create
+# the jaxb.index for the native image
+quarkus.native.resources.includes = 
person.xsd,org/apache/camel/quarkus/component/jaxb/it/model/pojo/jaxb.index
diff --git a/integration-tests/jaxb/src/main/resources/application.properties 
b/integration-tests/jaxb/src/main/resources/org/apache/camel/quarkus/component/jaxb/it/model/pojo/jaxb.index
similarity index 90%
copy from integration-tests/jaxb/src/main/resources/application.properties
copy to 
integration-tests/jaxb/src/main/resources/org/apache/camel/quarkus/component/jaxb/it/model/pojo/jaxb.index
index ff14981f09..ca127c55aa 100644
--- a/integration-tests/jaxb/src/main/resources/application.properties
+++ 
b/integration-tests/jaxb/src/main/resources/org/apache/camel/quarkus/component/jaxb/it/model/pojo/jaxb.index
@@ -1,4 +1,3 @@
-
 ## ---------------------------------------------------------------------------
 ## Licensed to the Apache Software Foundation (ASF) under one or more
 ## contributor license agreements.  See the NOTICE file distributed with
@@ -15,11 +14,4 @@
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
 ## ---------------------------------------------------------------------------
-
-#
-# Quarkus
-#
-
-## include xml routes and scheme
-quarkus.native.resources.includes = person.xsd
-
+PojoPerson
\ No newline at end of file
diff --git a/integration-tests/jaxb/src/main/resources/person.xsd 
b/integration-tests/jaxb/src/main/resources/person.xsd
index eb83a4684d..908fe068d9 100644
--- a/integration-tests/jaxb/src/main/resources/person.xsd
+++ b/integration-tests/jaxb/src/main/resources/person.xsd
@@ -17,12 +17,7 @@
     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:schema elementFormDefault="qualified" 
xmlns:xs="http://www.w3.org/2001/XMLSchema";>
     <xs:element name="person">
         <xs:complexType>
             <xs:sequence>
diff --git 
a/integration-tests/jaxb/src/test/java/org/apache/camel/quarkus/component/jaxb/it/JaxbTest.java
 
b/integration-tests/jaxb/src/test/java/org/apache/camel/quarkus/component/jaxb/it/JaxbTest.java
index 73bfac1993..a136d312ed 100644
--- 
a/integration-tests/jaxb/src/test/java/org/apache/camel/quarkus/component/jaxb/it/JaxbTest.java
+++ 
b/integration-tests/jaxb/src/test/java/org/apache/camel/quarkus/component/jaxb/it/JaxbTest.java
@@ -16,59 +16,390 @@
  */
 package org.apache.camel.quarkus.component.jaxb.it;
 
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
 import io.restassured.http.ContentType;
+import org.apache.camel.quarkus.component.jaxb.it.model.Person;
+import 
org.apache.camel.quarkus.component.jaxb.it.model.namespaced.NamespacedPerson;
+import org.apache.camel.quarkus.component.jaxb.it.model.simple.SimplePerson;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
-import static org.assertj.core.api.Assertions.assertThat;
+import static io.restassured.config.XmlConfig.xmlConfig;
+import static 
org.apache.camel.quarkus.component.jaxb.it.model.namespaced.NamespacedPerson.NAMESPACE;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.is;
 
 @QuarkusTest
 class JaxbTest {
 
+    private static final String PERSON_FIRST_NAME = "John";
+    private static final String PERSON_LAST_NAME = "Doe";
+    private static final int PERSON_AGE = 25;
+
+    @Test
+    public void marshall() {
+        RestAssured.given()
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("lastName", PERSON_LAST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .get("/jaxb/marshal")
+                .then()
+                .statusCode(200)
+                .body(
+                        "person.firstName", is(PERSON_FIRST_NAME),
+                        "person.lastName", is(PERSON_LAST_NAME),
+                        "person.age", is(String.valueOf(PERSON_AGE)));
+    }
+
     @Test
-    public void testUnmarshalLastName() {
-        String response = RestAssured.given().contentType(ContentType.XML)
-                .body(getPersonXml("Foo", "Bar", 22))
-                .post("/jaxb/unmarshal-lastname")
-                .then().statusCode(201).extract().asString();
-        assertThat(response).isEqualTo("Bar");
+    public void unmarshall() {
+        Person person = new SimplePerson();
+        person.setFirstName(PERSON_FIRST_NAME);
+        person.setLastName(PERSON_LAST_NAME);
+        person.setAge(PERSON_AGE);
+
+        String xml = getPersonXml(person);
+        RestAssured.given()
+                .contentType(ContentType.XML)
+                .body(xml)
+                .post("/jaxb/unmarshal")
+                .then()
+                .statusCode(200)
+                .body(
+                        "firstName", is(PERSON_FIRST_NAME),
+                        "lastName", is(PERSON_LAST_NAME),
+                        "age", is(PERSON_AGE));
     }
 
     @Test
-    public void testUnmarshalFirstName() {
-        String response = RestAssured.given().contentType(ContentType.XML)
-                .body(getPersonXml("Foo", "Bar", 22))
-                .post("/jaxb/unmarshal-firstname")
-                .then().statusCode(201).extract().asString();
-        assertThat(response).isEqualTo("Foo");
+    public void marshallWithoutMandatoryField() {
+        RestAssured.given()
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .get("/jaxb/marshal")
+                .then()
+                .statusCode(500)
+                .body("error", containsString("'{lastName}' is expected"));
     }
 
     @Test
-    public void testMarshallFirstName() {
-        String name = RestAssured.given().contentType(ContentType.TEXT)
-                .body("Foo")
-                .post("/jaxb/marshal-firstname")
-                .then().statusCode(201).extract().asString();
-        assertThat(name).contains("<ns2:firstName>Foo</ns2:firstName>");
+    public void unmarshallWithoutMandatoryField() {
+        Person person = new SimplePerson();
+        person.setFirstName(PERSON_FIRST_NAME);
+        person.setAge(PERSON_AGE);
+
+        String xml = getPersonXml(person);
+        RestAssured.given()
+                .contentType(ContentType.XML)
+                .body(xml)
+                .post("/jaxb/unmarshal")
+                .then()
+                .statusCode(500)
+                .body("error", containsString("'{lastName}' is expected"));
+    }
+
+    @Test
+    public void marshallWithJaxbDsl() {
+        RestAssured.given()
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("lastName", PERSON_LAST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .get("/jaxb/marshal/dsl")
+                .then()
+                .statusCode(200)
+                .body(
+                        "person.firstName", is(PERSON_FIRST_NAME),
+                        "person.lastName", is(PERSON_LAST_NAME),
+                        "person.age", is(String.valueOf(PERSON_AGE)));
+    }
+
+    @Test
+    public void unmarshallWithJaxbDsl() {
+        Person person = new SimplePerson();
+        person.setFirstName(PERSON_FIRST_NAME);
+        person.setLastName(PERSON_LAST_NAME);
+        person.setAge(PERSON_AGE);
+
+        String xml = getPersonXml(person);
+        RestAssured.given()
+                .contentType(ContentType.XML)
+                .body(xml)
+                .post("/jaxb/unmarshal/dsl")
+                .then()
+                .statusCode(200)
+                .body(
+                        "firstName", is(PERSON_FIRST_NAME),
+                        "lastName", is(PERSON_LAST_NAME),
+                        "age", is(PERSON_AGE));
+    }
+
+    @Test
+    public void marshallWithNamespacePrefix() {
+        RestAssured.given()
+                
.config(RestAssured.config().xmlConfig(xmlConfig().declareNamespace("test", 
NAMESPACE)))
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("lastName", PERSON_LAST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .get("/jaxb/marshal/namespace/prefix")
+                .then()
+                .statusCode(200)
+                .body(
+                        "person.firstName", is(PERSON_FIRST_NAME),
+                        "person.lastName", is(PERSON_LAST_NAME),
+                        "person.age", is(String.valueOf(PERSON_AGE)));
+    }
+
+    @Test
+    public void unmarshallWithNamespacePrefix() {
+        Person person = new NamespacedPerson();
+        person.setFirstName(PERSON_FIRST_NAME);
+        person.setLastName(PERSON_LAST_NAME);
+        person.setAge(PERSON_AGE);
+
+        String xml = getPersonXml(person);
+        RestAssured.given()
+                .contentType(ContentType.XML)
+                .body(xml)
+                .post("/jaxb/unmarshal/namespace/prefix")
+                .then()
+                .statusCode(200)
+                .body(
+                        "firstName", is(PERSON_FIRST_NAME),
+                        "lastName", is(PERSON_LAST_NAME),
+                        "age", is(PERSON_AGE));
+    }
+
+    @Test
+    public void marshallWithEncoding() {
+        String firstName = PERSON_FIRST_NAME.replace("o", "ø");
+        // Add some invalid characters that the filterNonXmlChars option will 
replace with spaces
+        String lastName = PERSON_LAST_NAME + " \uD83D\uDC33";
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .queryParam("firstName", firstName)
+                .queryParam("lastName", lastName)
+                .queryParam("age", PERSON_AGE)
+                .get("/jaxb/marshal/encoding")
+                .then()
+                .statusCode(200)
+                .body(
+                        "person.firstName", endsWith(firstName),
+                        "person.lastName", is(PERSON_LAST_NAME + "   "),
+                        "person.age", is(String.valueOf(PERSON_AGE)));
+    }
+
+    @Test
+    public void unmarshallWithEncoding() {
+        String firstName = PERSON_FIRST_NAME.replace("o", "ø");
+        Person person = new SimplePerson();
+        person.setFirstName(firstName);
+        person.setLastName(PERSON_LAST_NAME);
+        person.setAge(PERSON_AGE);
+
+        String xml = getPersonXml(person, "ISO-8859-1");
+        RestAssured.given()
+                .contentType(ContentType.XML)
+                .body(xml)
+                .post("/jaxb/unmarshal/encoding")
+                .then()
+                .statusCode(200)
+                .body(
+                        "firstName", is(firstName),
+                        "lastName", is(PERSON_LAST_NAME),
+                        "age", is(PERSON_AGE));
     }
 
     @Test
-    public void testMarshallLasttName() {
-        String name = RestAssured.given().contentType(ContentType.TEXT)
-                .body("Bar")
-                .post("/jaxb/marshal-lastname")
-                .then().statusCode(201).extract().asString();
-        assertThat(name).contains("<test:lastName>Bar</test:lastName>");
+    public void marshalWithExistingXmlPayload() {
+        Person person = new SimplePerson();
+        person.setFirstName(PERSON_FIRST_NAME);
+        person.setLastName(PERSON_LAST_NAME);
+        person.setAge(PERSON_AGE);
+
+        String xml = getPersonXml(person);
+        RestAssured.given()
+                .contentType(ContentType.XML)
+                .body(xml)
+                .post("/jaxb/marshal/xml")
+                .then()
+                .statusCode(200)
+                .body(
+                        "person.firstName", is(PERSON_FIRST_NAME),
+                        "person.lastName", is(PERSON_LAST_NAME),
+                        "person.age", is(String.valueOf(PERSON_AGE)));
+    }
+
+    @ParameterizedTest
+    @ValueSource(booleans = { false, true })
+    public void marshalWithPartClass(boolean useHeader) {
+        RestAssured.given()
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("lastName", PERSON_LAST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .queryParam("useHeader", useHeader)
+                .get("/jaxb/marshal/part/class")
+                .then()
+                .statusCode(200)
+                .body(
+                        "person.firstName", is(PERSON_FIRST_NAME),
+                        "person.lastName", is(PERSON_LAST_NAME),
+                        "person.age", is(String.valueOf(PERSON_AGE)));
+    }
+
+    @ParameterizedTest
+    @ValueSource(booleans = { false, true })
+    public void unmarshalWithPartClass(boolean useHeader) {
+        String personXml = RestAssured.given()
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("lastName", PERSON_LAST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .queryParam("useHeader", useHeader)
+                .get("/jaxb/marshal/part/class")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .asString();
+
+        RestAssured.given()
+                .queryParam("useHeader", useHeader)
+                .contentType(ContentType.XML)
+                .body(personXml)
+                .post("/jaxb/unmarshal/part/class")
+                .then()
+                .statusCode(200)
+                .body(
+                        "firstName", is(PERSON_FIRST_NAME),
+                        "lastName", is(PERSON_LAST_NAME),
+                        "age", is(PERSON_AGE));
+    }
+
+    @Test
+    public void unmarshalWithIgnoreJaxbElement() {
+        String personXml = RestAssured.given()
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("lastName", PERSON_LAST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .queryParam("useHeader", false)
+                .get("/jaxb/marshal/part/class")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .asString();
+
+        RestAssured.given()
+                .contentType(ContentType.XML)
+                .body(personXml)
+                .post("/jaxb/unmarshal/ignore/element")
+                .then()
+                .statusCode(200)
+                .body(
+                        "firstName", is(PERSON_FIRST_NAME),
+                        "lastName", is(PERSON_LAST_NAME),
+                        "age", is(PERSON_AGE));
+    }
+
+    @Test
+    public void marshallWithCustomProperties() {
+        String[] lines = RestAssured.given()
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("lastName", PERSON_LAST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .get("/jaxb/marshal/custom/properties")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body()
+                .asString()
+                .split(System.lineSeparator());
+
+        // Pretty printing is disabled so we should have only one line
+        Assertions.assertEquals(1, lines.length);
+    }
+
+    @Test
+    public void marshalWithCustomStreamWriter() {
+        RestAssured.given()
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("lastName", PERSON_LAST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .get("/jaxb/marshal/custom/stream/writer")
+                .then()
+                .statusCode(200)
+                .body(
+                        "person-modified.firstName-modified", 
is(PERSON_FIRST_NAME),
+                        "person-modified.lastName-modified", 
is(PERSON_LAST_NAME),
+                        "person-modified.age-modified", 
is(String.valueOf(PERSON_AGE)));
+    }
+
+    @Test
+    public void marshalWithObjectFactory() {
+        RestAssured.given()
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("lastName", PERSON_LAST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .get("/jaxb/marshal/with/object/factory")
+                .then()
+                .log().body()
+                .statusCode(200)
+                .body(
+                        "person.firstName", is(PERSON_FIRST_NAME),
+                        "person.lastName", is(PERSON_LAST_NAME),
+                        "person.age", is(String.valueOf(PERSON_AGE)));
+    }
+
+    @Test
+    public void marshalWithoutObjectFactory() {
+        RestAssured.given()
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("lastName", PERSON_LAST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .get("/jaxb/marshal/without/object/factory")
+                .then()
+                .statusCode(200)
+                .body(
+                        "firstName", is(PERSON_FIRST_NAME),
+                        "lastName", is(PERSON_LAST_NAME),
+                        "age", is(PERSON_AGE));
+    }
+
+    @Test
+    public void marshalWithNoNamespaceSchemaLocation() {
+        RestAssured.given()
+                .queryParam("firstName", PERSON_FIRST_NAME)
+                .queryParam("lastName", PERSON_LAST_NAME)
+                .queryParam("age", PERSON_AGE)
+                .get("/jaxb/marshal/non/namespace/schema/location")
+                .then()
+                .statusCode(200)
+                
.body(containsString("noNamespaceSchemaLocation=\"person-no-namespace.xsd\""));
+    }
+
+    private static String getPersonXml(Person person) {
+        return getPersonXml(person, "UTF-8");
     }
 
-    private static String getPersonXml(String name, String lastName, Integer 
age) {
-        return String.format(
-                "<person xmlns:ns2=\"http://example.com/a\";>" +
-                        "<ns2:firstName>%s</ns2:firstName>" +
-                        "<ns2:lastName>%s</ns2:lastName>" +
-                        "<age>%d</age>" +
-                        "</person>",
-                name, lastName, age);
+    private static String getPersonXml(Person person, String encoding) {
+        try {
+            StringWriter writer = new StringWriter();
+            JAXBContext context = JAXBContext.newInstance(person.getClass());
+            Marshaller marshaller = context.createMarshaller();
+            marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
+            marshaller.marshal(person, writer);
+            return writer.toString();
+        } catch (JAXBException e) {
+            throw new RuntimeException(e);
+        }
     }
 }
diff --git a/pom.xml b/pom.xml
index 879776b669..83190693b7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -525,6 +525,7 @@
                             <ds>SLASHSTAR_STYLE</ds>
                             <groovy>SLASHSTAR_STYLE</groovy>
                             <java>SLASHSTAR_STYLE</java>
+                            <jaxb.index>CAMEL_PROPERTIES_STYLE</jaxb.index>
                             <Jenkinsfile>SLASHSTAR_STYLE</Jenkinsfile>
                             
<Jenkinsfile.quarkus>SLASHSTAR_STYLE</Jenkinsfile.quarkus>
                             <properties>CAMEL_PROPERTIES_STYLE</properties>

Reply via email to