You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ja...@apache.org on 2023/06/21 09:36:42 UTC

[camel-quarkus-examples] branch 2.13.x updated: Provide example for CXF SOAP

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

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


The following commit(s) were added to refs/heads/2.13.x by this push:
     new 3ae40bc  Provide example for CXF SOAP
3ae40bc is described below

commit 3ae40bc0b7e1f6f4afabc63ea26e6110969e0fb9
Author: llowinge <ll...@redhat.com>
AuthorDate: Wed Jun 21 11:36:37 2023 +0200

    Provide example for CXF SOAP
---
 cxf-soap/README.adoc                               | 204 ++++++++++++
 cxf-soap/eclipse-formatter-config.xml              | 276 ++++++++++++++++
 cxf-soap/pom.xml                                   | 360 +++++++++++++++++++++
 .../org/acme/cxf/soap/adapter/DataTypeAdapter.java |  75 +++++
 .../org/acme/cxf/soap/pojo/MyPojoRouteBuilder.java |  50 +++
 .../org/acme/cxf/soap/pojo/service/Address.java    | 101 ++++++
 .../org/acme/cxf/soap/pojo/service/Contact.java    |  79 +++++
 .../acme/cxf/soap/pojo/service/ContactService.java |  35 ++
 .../acme/cxf/soap/pojo/service/ContactType.java    |  26 ++
 .../org/acme/cxf/soap/pojo/service/Contacts.java   |  48 +++
 .../soap/pojo/service/NoSuchContactException.java  |  46 +++
 .../service/impl/ContactServiceInMemoryImpl.java   |  73 +++++
 .../org/acme/cxf/soap/wsdl/MyWsdlRouteBuilder.java |  90 ++++++
 .../soap/wsdl/repository/CustomerRepository.java   |  73 +++++
 cxf-soap/src/main/resources/application.properties |  41 +++
 cxf-soap/src/main/resources/binding.xml            |  27 ++
 .../src/main/resources/requests/contact/add.xml    |  33 ++
 .../src/main/resources/requests/contact/getAll.xml |  24 ++
 .../main/resources/requests/customer/getByName.xml |  26 ++
 .../src/main/resources/wsdl/CustomerService.wsdl   | 122 +++++++
 .../src/test/java/org/acme/cxf/soap/BaseTest.java  |  30 ++
 .../java/org/acme/cxf/soap/PojoClientTest.java     |  71 ++++
 .../java/org/acme/cxf/soap/PojoClientTestIT.java   |  23 ++
 .../java/org/acme/cxf/soap/WsdlClientTest.java     | 104 ++++++
 .../java/org/acme/cxf/soap/WsdlClientTestIT.java   |  23 ++
 docs/modules/ROOT/attachments/examples.json        |   5 +
 26 files changed, 2065 insertions(+)

diff --git a/cxf-soap/README.adoc b/cxf-soap/README.adoc
new file mode 100644
index 0000000..b163d37
--- /dev/null
+++ b/cxf-soap/README.adoc
@@ -0,0 +1,204 @@
+= Camel Quarkus CXF SOAP example
+:cq-example-description: An example that shows how to use Camel CXF SOAP component.
+
+{cq-description}
+
+In this example we will create two SOAP webservices with two different approaches. Both services will use Camel routes as service implementation exposed via CXF component.
+
+== WSDL first
+
+The "WSDL first" approach presupposes writing the link:src/main/resources/wsdl/CustomerService.wsdl[WSDL file] manually at the beginning of the SOAP service design.
+Then we can use link:pom.xml#L231[the `generate-code` goal] of `quarkus-maven-plugin` to generate the Java classes for us.
+The `wsdl2java` tool is used under the hood and its configuration can be found in link:src/main/resources/application.properties#L28[application.properties].
+
+The customer web service is exposed via Camel route endpoint `cxf:bean:customer`.
+Its logic is implemented directly in the route by delegating to `org.acme.cxf.soap.wsdl.repository.CustomerRepository`.
+The endpoint supports two SOAP operations: `getCustomersByName` and `updateCustomer`.
+
+NOTE: Most modern IDEs will be able to discover the generared classes automatically.
+You may want to check some occurrences of those in `org.acme.cxf.soap.wsdl.repository.CustomerRepository`.
+
+TIP: More information about generating Java classes from WSDL can be found in https://quarkiverse.github.io/quarkiverse-docs/quarkus-cxf/1.5/user-guide/generate-java-from-wsdl.html[Java from WSDL] chapter of Quarkus CXF documentation.
+
+=== Binding (Advanced)
+
+For illustrating how other `wsdl2java` options could be applied via link:src/main/resources/application.properties#L29[`quarkus.cxf.codegen.wsdl2java.additional-params`], we have added a custom binding defined in link:src/main/resources/binding.xml[binding.xml].
+It instructs CXF to use `LocalDate` (more common in Java world) instead of default XML Date representation `XMLGregorianCalendar`.
+
+== Java first
+
+If you don't have the WSDL file upfront, you can create your SOAP service from Java classes annotated with JAX-WS annotations.
+Check the `org.acme.cxf.soap.pojo.service.ContactService` interface as an example.
+Again, we implement the service interface in a Camel fashion, this time through a bean
+- see `org.acme.cxf.soap.pojo.service.impl.ContactServiceInMemoryImpl`.
+
+The exposed contact web service will enable five operations - `addContact`, `getContact`, `getContacts`, `updateContact` and `removeContact`.
+
+TIP: If you would like to only generate WSDL from Java, you can follow the https://quarkiverse.github.io/quarkiverse-docs/quarkus-cxf/1.5/user-guide/generate-wsdl-from-java.html[WSDL from Java] chapter of Quarkus CXF documentation.
+
+== Start in the Development mode
+
+[source,shell]
+----
+$ mvn clean compile quarkus:dev
+----
+
+The above command compiles the project, starts the application and lets the Quarkus tooling watch for changes in your
+workspace. Any modifications in your project will automatically take effect in the running application.
+
+TIP: Please refer to the Development mode section of
+https://camel.apache.org/camel-quarkus/latest/first-steps.html#_development_mode[Camel Quarkus User guide] for more details.
+
+[[playground]]
+== Playground
+
+We can first try to add some contact with:
+[source,shell]
+----
+curl -X POST -H "Content-Type: text/xml;charset=UTF-8" -d @src/main/resources/requests/contact/add.xml http://localhost:8080/cxf/services/contact
+----
+Then verify it was added with:
+[source,shell]
+----
+$ curl -X POST -H "Content-Type: text/xml;charset=UTF-8" -d @src/main/resources/requests/contact/getAll.xml http://localhost:8080/cxf/services/contact
+----
+Which should return:
+
+[source,xml]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
+  <soap:Body>
+    <ns2:getContactsResponse xmlns:ns2="http://camel.apache.org/test/ContactService">
+      <return>
+        <contacts>
+          <name>Lukas</name>
+          <address>
+            <city>New York</city>
+            <street>Sky 1234</street>
+          </address>
+          <type>PERSONAL</type>
+        </contacts>
+      </return>
+    </ns2:getContactsResponse>
+  </soap:Body>
+</soap:Envelope>
+----
+
+We can also test our customer service:
+
+[source,shell]
+----
+$ curl -X POST -H "Content-Type: text/xml;charset=UTF-8" -d @src/main/resources/requests/customer/getByName.xml http://localhost:8080/cxf/services/customer
+----
+
+You can observe that we have hardcoded `test` name at SOAPBody part in `src/main/resources/requests/customer/getByName.soap` as follows:
+[source, xml]
+----
+<cus:getCustomersByName>
+  <name>test</name>
+</cus:getCustomersByName>
+----
+
+We can try to alter it to non-valid request (the validation is enabled with `schema-validation-enabled=true` in `org.acme.cxf.soap.wsdl.MyWsdlRouteBuilder`).
+For example, you can change `test` to `t`.
+Once you invoke the service again, you should see the following exception:
+
+[source, xml]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
+  <soap:Body>
+    <soap:Fault>
+      <faultcode>soap:Client</faultcode>
+      <faultstring>Unmarshalling Error: cvc-minLength-valid: Value 't' with length = '1' is not facet-valid with respect to minLength '2' for type '#AnonType_namegetCustomersByName'.</faultstring>
+    </soap:Fault>
+  </soap:Body>
+</soap:Envelope>
+----
+
+Last thing which could be tested, is trying to get non-existent customer (which `t` was obviously as well, but now we will pass through schema validation). So change the name to eg. `Non existent` and see result with `NoSuchCustomer`:
+
+[source, xml]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
+  <soap:Body>
+    <soap:Fault>
+      <faultcode>soap:Server</faultcode>
+      <faultstring>Customer not found</faultstring>
+      <detail>
+        <ns2:NoSuchCustomer xmlns:ns2="http://customerservice.example.com/">
+          <customerName>Non existent</customerName>
+        </ns2:NoSuchCustomer>
+      </detail>
+    </soap:Fault>
+  </soap:Body>
+</soap:Envelope>
+----
+
+TIP: To obtain WSDLs for any exposed CXF service, you can query URL `http://<hostname>/<cxf-path>?wsdl`. It can be handy in tools like _SoapUI_.
+
+To discover WSDLs of our services, you can use:
+[source, shell]
+----
+$ curl "http://localhost:8080/cxf/services/contact?wsdl"
+$ curl "http://localhost:8080/cxf/services/customer?wsdl"
+----
+
+== Package and run the application
+
+Once you are done with playing/developing you may want to package and run the application for production usage.
+
+TIP: Find more details about the JVM mode and Native mode in the Package and run section of
+https://camel.apache.org/camel-quarkus/latest/first-steps.html#_package_and_run_the_application[Camel Quarkus User guide]
+
+=== JVM mode
+
+[source,shell]
+----
+$ mvn clean package
+$ java -jar target/quarkus-app/quarkus-run.jar
+----
+
+=== Native mode
+
+IMPORTANT: Native mode requires having GraalVM and other tools installed. Please check the Prerequisites section
+of https://camel.apache.org/camel-quarkus/latest/first-steps.html#_prerequisites[Camel Quarkus User guide].
+
+To prepare a native executable using GraalVM, run the following command:
+
+[source,shell]
+----
+$ mvn clean package -Pnative
+$ ./target/*-runner
+----
+
+== Kubernetes
+==== Deploy
+[source,shell]
+----
+$ mvn clean package -DskipTests -Dquarkus.kubernetes.deploy=true -Dkubernetes
+----
+
+You should see one pod running:
+
+[source,shell]
+----
+camel-quarkus-examples-cxf-soap-cd9477f94-qb8vv   1/1     Running   0          43s
+----
+
+Then use following command to redirect the localhost network to the Kubernetes network:
+
+[source,shell]
+----
+$ kubectl port-forward service/camel-quarkus-examples-cxf-soap 8080:8080
+----
+
+Open another terminal and then follow instructions from <<playground>>.
+
+To stop it you can CTRL+C the process in port-forwarding terminal and shutdown the Kubernetes cluster.
+
+== Feedback
+
+Please report bugs and propose improvements via https://github.com/apache/camel-quarkus/issues[GitHub issues of Camel Quarkus] project.
diff --git a/cxf-soap/eclipse-formatter-config.xml b/cxf-soap/eclipse-formatter-config.xml
new file mode 100644
index 0000000..2248b2b
--- /dev/null
+++ b/cxf-soap/eclipse-formatter-config.xml
@@ -0,0 +1,276 @@
+<?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.
+
+-->
+<profiles version="8">
+    <profile name="Camel Java Conventions" version="8" kind="CodeFormatterProfile">
+        <setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+        <setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_comments" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.indent_return_description" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
+        <setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
+        <setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
+        <setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.indentation.size" value="8"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+        <setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.lineSplit" value="128"/>
+        <setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+        <setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+        <setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
+        <setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
+        <setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
+        <setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
+        <setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="CHECKSTYLE:OFF"/>
+        <setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="CHECKSTYLE:ON"/>
+    </profile>
+</profiles>
diff --git a/cxf-soap/pom.xml b/cxf-soap/pom.xml
new file mode 100644
index 0000000..6b1385e
--- /dev/null
+++ b/cxf-soap/pom.xml
@@ -0,0 +1,360 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>camel-quarkus-examples-cxf-soap</artifactId>
+    <groupId>org.apache.camel.quarkus.examples</groupId>
+    <version>2.13.3</version>
+
+    <name>Camel Quarkus :: Examples :: CXF SOAP</name>
+    <description>Camel Quarkus Example :: CXF SOAP</description>
+
+    <properties>
+        <quarkus.platform.version>2.13.8.Final</quarkus.platform.version>
+        <camel-quarkus.platform.version>${quarkus.platform.version}</camel-quarkus.platform.version>
+
+        <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
+        <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
+        <camel-quarkus.platform.group-id>${quarkus.platform.group-id}</camel-quarkus.platform.group-id>
+        <camel-quarkus.platform.artifact-id>quarkus-camel-bom</camel-quarkus.platform.artifact-id>
+
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <maven.compiler.target>11</maven.compiler.target>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.testTarget>${maven.compiler.target}</maven.compiler.testTarget>
+        <maven.compiler.testSource>${maven.compiler.source}</maven.compiler.testSource>
+
+        <formatter-maven-plugin.version>2.17.1</formatter-maven-plugin.version>
+        <impsort-maven-plugin.version>1.3.2</impsort-maven-plugin.version>
+        <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
+        <maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
+        <maven-resources-plugin.version>3.1.0</maven-resources-plugin.version>
+        <maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
+        <mycila-license.version>3.0</mycila-license.version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <!-- Import BOM -->
+            <dependency>
+                <groupId>${quarkus.platform.group-id}</groupId>
+                <artifactId>${quarkus.platform.artifact-id}</artifactId>
+                <version>${quarkus.platform.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>${camel-quarkus.platform.group-id}</groupId>
+                <artifactId>${camel-quarkus.platform.artifact-id}</artifactId>
+                <version>${camel-quarkus.platform.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-log</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-direct</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-bean</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-cxf-soap</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-hibernate-validator</artifactId>
+        </dependency>
+        <!-- Test -->
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.rest-assured</groupId>
+            <artifactId>rest-assured</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.awaitility</groupId>
+            <artifactId>awaitility</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+
+                <plugin>
+                    <groupId>net.revelc.code.formatter</groupId>
+                    <artifactId>formatter-maven-plugin</artifactId>
+                    <version>${formatter-maven-plugin.version}</version>
+                    <configuration>
+                        <configFile>${maven.multiModuleProjectDirectory}/eclipse-formatter-config.xml</configFile>
+                        <lineEnding>LF</lineEnding>
+                    </configuration>
+                </plugin>
+
+                <plugin>
+                    <groupId>net.revelc.code</groupId>
+                    <artifactId>impsort-maven-plugin</artifactId>
+                    <version>${impsort-maven-plugin.version}</version>
+                    <configuration>
+                        <groups>java.,javax.,org.w3c.,org.xml.,junit.</groups>
+                        <removeUnused>true</removeUnused>
+                        <staticAfter>true</staticAfter>
+                        <staticGroups>java.,javax.,org.w3c.,org.xml.,junit.</staticGroups>
+                    </configuration>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>${maven-compiler-plugin.version}</version>
+                    <configuration>
+                        <showDeprecation>true</showDeprecation>
+                        <showWarnings>true</showWarnings>
+                        <compilerArgs>
+                            <arg>-Xlint:unchecked</arg>
+                        </compilerArgs>
+                    </configuration>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>${maven-surefire-plugin.version}</version>
+                    <configuration>
+                        <failIfNoTests>false</failIfNoTests>
+                        <systemProperties>
+                            <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
+                        </systemProperties>
+                    </configuration>
+                </plugin>
+
+                <plugin>
+                    <groupId>${quarkus.platform.group-id}</groupId>
+                    <artifactId>quarkus-maven-plugin</artifactId>
+                    <version>${quarkus.platform.version}</version>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-failsafe-plugin</artifactId>
+                    <version>${maven-surefire-plugin.version}</version>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-jar-plugin</artifactId>
+                    <version>${maven-jar-plugin.version}</version>
+                </plugin>
+
+                <plugin>
+                    <groupId>com.mycila</groupId>
+                    <artifactId>license-maven-plugin</artifactId>
+                    <version>${mycila-license.version}</version>
+                    <configuration>
+                        <failIfUnknown>true</failIfUnknown>
+                        <header>${maven.multiModuleProjectDirectory}/header.txt</header>
+                        <excludes>
+                            <exclude>**/*.adoc</exclude>
+                            <exclude>**/*.txt</exclude>
+                            <exclude>**/LICENSE.txt</exclude>
+                            <exclude>**/LICENSE</exclude>
+                            <exclude>**/NOTICE.txt</exclude>
+                            <exclude>**/NOTICE</exclude>
+                            <exclude>**/README</exclude>
+                            <exclude>**/pom.xml.versionsBackup</exclude>
+                        </excludes>
+                        <mapping>
+                            <java>SLASHSTAR_STYLE</java>
+                            <properties>CAMEL_PROPERTIES_STYLE</properties>
+                            <wsdl>XML_STYLE</wsdl>
+                        </mapping>
+                        <headerDefinitions>
+                            <headerDefinition>${maven.multiModuleProjectDirectory}/license-properties-headerdefinition.xml
+                            </headerDefinition>
+                        </headerDefinitions>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+
+        <plugins>
+            <plugin>
+                <groupId>${quarkus.platform.group-id}</groupId>
+                <artifactId>quarkus-maven-plugin</artifactId>
+                <version>${quarkus.platform.version}</version>
+                <extensions>true</extensions><!-- Workaround for https://github.com/quarkusio/quarkus/issues/21718 -->
+                <executions>
+                    <execution>
+                        <id>build</id>
+                        <goals>
+                            <goal>build</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>generate-code</id>
+                        <goals>
+                            <goal>generate-code</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>net.revelc.code.formatter</groupId>
+                <artifactId>formatter-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>format</id>
+                        <goals>
+                            <goal>format</goal>
+                        </goals>
+                        <phase>process-sources</phase>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>net.revelc.code</groupId>
+                <artifactId>impsort-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>sort-imports</id>
+                        <goals>
+                            <goal>sort</goal>
+                        </goals>
+                        <phase>process-sources</phase>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>native</id>
+            <activation>
+                <property>
+                    <name>native</name>
+                </property>
+            </activation>
+            <properties>
+                <quarkus.package.type>native</quarkus.package.type>
+            </properties>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <quarkus.package.type>${quarkus.package.type}</quarkus.package.type>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>kubernetes</id>
+            <activation>
+                <property>
+                    <name>kubernetes</name>
+                </property>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>io.quarkus</groupId>
+                    <artifactId>quarkus-kubernetes</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>io.quarkus</groupId>
+                    <artifactId>quarkus-container-image-jib</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>io.quarkus</groupId>
+                    <artifactId>quarkus-kubernetes-client</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-microprofile-health</artifactId>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
+            <id>openshift</id>
+            <activation>
+                <property>
+                    <name>openshift</name>
+                </property>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>io.quarkus</groupId>
+                    <artifactId>quarkus-openshift</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>io.quarkus</groupId>
+                    <artifactId>quarkus-kubernetes-client</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.camel.quarkus</groupId>
+                    <artifactId>camel-quarkus-microprofile-health</artifactId>
+                </dependency>
+            </dependencies>
+        </profile>
+        <profile>
+            <id>skip-testcontainers-tests</id>
+            <activation>
+                <property>
+                    <name>skip-testcontainers-tests</name>
+                </property>
+            </activation>
+            <properties>
+                <skipTests>true</skipTests>
+            </properties>
+        </profile>
+    </profiles>
+
+</project>
diff --git a/cxf-soap/src/main/java/org/acme/cxf/soap/adapter/DataTypeAdapter.java b/cxf-soap/src/main/java/org/acme/cxf/soap/adapter/DataTypeAdapter.java
new file mode 100644
index 0000000..a4f4b61
--- /dev/null
+++ b/cxf-soap/src/main/java/org/acme/cxf/soap/adapter/DataTypeAdapter.java
@@ -0,0 +1,75 @@
+/*
+ * 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.acme.cxf.soap.adapter;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+
+public class DataTypeAdapter {
+
+    private DataTypeAdapter() {
+    }
+
+    public static LocalDate parseDate(String s) {
+        if (s == null) {
+            return null;
+        }
+        return LocalDate.parse(s);
+    }
+
+    public static String printDate(LocalDate dt) {
+        if (dt == null) {
+            return null;
+        }
+
+        return dt.format(DateTimeFormatter.ISO_LOCAL_DATE);
+    }
+
+    public static LocalTime parseTime(String s) {
+        if (s == null) {
+            return null;
+        }
+
+        return LocalTime.parse(s);
+    }
+
+    public static String printTime(LocalTime dt) {
+        if (dt == null) {
+            return null;
+        }
+
+        return dt.format(DateTimeFormatter.ISO_LOCAL_TIME);
+    }
+
+    public static LocalDateTime parseDateTime(String s) {
+        if (s == null) {
+            return null;
+        }
+
+        return LocalDateTime.parse(s);
+    }
+
+    public static String printDateTime(LocalDateTime dt) {
+        if (dt == null) {
+            return null;
+        }
+
+        return dt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
+    }
+}
diff --git a/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/MyPojoRouteBuilder.java b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/MyPojoRouteBuilder.java
new file mode 100644
index 0000000..5972288
--- /dev/null
+++ b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/MyPojoRouteBuilder.java
@@ -0,0 +1,50 @@
+/*
+ * 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.acme.cxf.soap.pojo;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.SessionScoped;
+import javax.enterprise.inject.Produces;
+import javax.inject.Named;
+
+import org.acme.cxf.soap.pojo.service.ContactService;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.cxf.jaxws.CxfEndpoint;
+
+/**
+ * This class demonstrate how to expose a SOAP endpoint starting from java classes
+ */
+@ApplicationScoped
+public class MyPojoRouteBuilder extends RouteBuilder {
+
+    @Produces
+    @SessionScoped
+    @Named
+    CxfEndpoint contact() {
+        CxfEndpoint contactEndpoint = new CxfEndpoint();
+        contactEndpoint.setServiceClass(ContactService.class);
+        contactEndpoint.setAddress("/contact");
+
+        return contactEndpoint;
+    }
+
+    @Override
+    public void configure() throws Exception {
+        from("cxf:bean:contact")
+                .recipientList(simple("bean:inMemoryContactService?method=${header.operationName}"));
+    }
+}
diff --git a/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/Address.java b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/Address.java
new file mode 100644
index 0000000..8a0a444
--- /dev/null
+++ b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/Address.java
@@ -0,0 +1,101 @@
+/*
+ * 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.acme.cxf.soap.pojo.service;
+
+import javax.validation.constraints.Pattern;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Address", propOrder = {
+        "city",
+        "street"
+})
+public class Address {
+
+    private String city;
+    @Pattern(regexp = "\\w+ \\d+")
+    private String street;
+
+    public Address() {
+    }
+
+    public Address(String city, String street) {
+        this.city = city;
+        this.street = street;
+    }
+
+    public String getCity() {
+        return city;
+    }
+
+    public void setCity(String city) {
+        this.city = city;
+    }
+
+    public String getStreet() {
+        return street;
+    }
+
+    public void setStreet(String street) {
+        this.street = street;
+    }
+
+    @Override
+    public String toString() {
+        return "Address [city=" + city + ", street=" + street + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((city == null) ? 0 : city.hashCode());
+        result = prime * result + ((street == null) ? 0 : street.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof Address)) {
+            return false;
+        }
+        final Address other = (Address) obj;
+        if (city == null) {
+            if (other.city != null) {
+                return false;
+            }
+        } else if (!city.equals(other.city)) {
+            return false;
+        }
+        if (street == null) {
+            if (other.street != null) {
+                return false;
+            }
+        } else if (!street.equals(other.street)) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/Contact.java b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/Contact.java
new file mode 100644
index 0000000..2621b65
--- /dev/null
+++ b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/Contact.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.acme.cxf.soap.pojo.service;
+
+import java.util.Objects;
+
+import javax.validation.Valid;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Contact", propOrder = {
+        "name",
+        "address",
+        "type"
+})
+public class Contact {
+
+    @Size(min = 1, max = 50)
+    private String name;
+    @Valid
+    private Address address;
+    private ContactType type;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Address getAddress() {
+        return address;
+    }
+
+    public void setAddress(Address address) {
+        this.address = address;
+    }
+
+    public ContactType getType() {
+        return type;
+    }
+
+    public void setType(ContactType type) {
+        this.type = type;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+        Contact contact = (Contact) o;
+        return Objects.equals(name, contact.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name);
+    }
+}
diff --git a/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/ContactService.java b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/ContactService.java
new file mode 100644
index 0000000..15568e4
--- /dev/null
+++ b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/ContactService.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.acme.cxf.soap.pojo.service;
+
+import javax.jws.WebService;
+
+@WebService(name = "ContactService", serviceName = "ContactService", targetNamespace = ContactService.TARGET_NS)
+public interface ContactService {
+    public static final String TARGET_NS = "http://camel.apache.org/test/ContactService";
+
+    void addContact(Contact contact);
+
+    Contact getContact(String name) throws NoSuchContactException;
+
+    Contacts getContacts();
+
+    void updateContact(String name, Contact contact)
+            throws NoSuchContactException;
+
+    void removeContact(String name) throws NoSuchContactException;
+}
diff --git a/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/ContactType.java b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/ContactType.java
new file mode 100644
index 0000000..51bcfe0
--- /dev/null
+++ b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/ContactType.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acme.cxf.soap.pojo.service;
+
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(name = "ContactType")
+@XmlEnum
+public enum ContactType {
+    PERSONAL, WORK, OTHER,
+}
diff --git a/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/Contacts.java b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/Contacts.java
new file mode 100644
index 0000000..ee10ecd
--- /dev/null
+++ b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/Contacts.java
@@ -0,0 +1,48 @@
+/*
+ * 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.acme.cxf.soap.pojo.service;
+
+import java.util.Collection;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Contacts", propOrder = {
+        "contacts"
+})
+public class Contacts {
+
+    private Collection<Contact> contacts;
+
+    public Contacts() {
+    }
+
+    public Contacts(Collection<Contact> contacts) {
+        super();
+        this.contacts = contacts;
+    }
+
+    public Collection<Contact> getContacts() {
+        return contacts;
+    }
+
+    public void setContacts(Collection<Contact> contacts) {
+        this.contacts = contacts;
+    }
+}
diff --git a/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/NoSuchContactException.java b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/NoSuchContactException.java
new file mode 100644
index 0000000..3c525d4
--- /dev/null
+++ b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/NoSuchContactException.java
@@ -0,0 +1,46 @@
+/*
+ * 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.acme.cxf.soap.pojo.service;
+
+import javax.xml.ws.WebFault;
+
+@WebFault(name = "NoSuchContact")
+public class NoSuchContactException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    private String faultInfo;
+
+    public NoSuchContactException(String name) {
+        super("Contact \"" + name + "\" does not exist.");
+        this.faultInfo = "Contact \"" + name + "\" does not exist.";
+    }
+
+    public NoSuchContactException(String message, String faultInfo) {
+        super(message);
+        this.faultInfo = faultInfo;
+    }
+
+    public NoSuchContactException(String message, String faultInfo, Throwable cause) {
+        super(message, cause);
+        this.faultInfo = faultInfo;
+    }
+
+    public String getFaultInfo() {
+        return this.faultInfo;
+    }
+}
diff --git a/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/impl/ContactServiceInMemoryImpl.java b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/impl/ContactServiceInMemoryImpl.java
new file mode 100644
index 0000000..a06a0f9
--- /dev/null
+++ b/cxf-soap/src/main/java/org/acme/cxf/soap/pojo/service/impl/ContactServiceInMemoryImpl.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.acme.cxf.soap.pojo.service.impl;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Named;
+
+import org.acme.cxf.soap.pojo.service.Contact;
+import org.acme.cxf.soap.pojo.service.ContactService;
+import org.acme.cxf.soap.pojo.service.Contacts;
+import org.acme.cxf.soap.pojo.service.NoSuchContactException;
+
+@ApplicationScoped
+@Named("inMemoryContactService")
+public class ContactServiceInMemoryImpl implements ContactService {
+
+    private Map<String, Contact> contacts = new ConcurrentHashMap<>();
+
+    @Override
+    public void addContact(Contact contact) {
+        contacts.put(contact.getName(), contact);
+    }
+
+    @Override
+    public Contact getContact(String name) throws NoSuchContactException {
+        if (!contacts.containsKey(name)) {
+            throw new NoSuchContactException(name);
+        }
+
+        return contacts.get(name);
+    }
+
+    @Override
+    public Contacts getContacts() {
+        return new Contacts(contacts.values());
+    }
+
+    @Override
+    public void updateContact(String name, Contact contact) throws NoSuchContactException {
+        if (!contacts.containsKey(name)) {
+            throw new NoSuchContactException(name);
+        }
+        if (!contacts.get(name).equals(contact.getName())) {
+            contacts.remove(name);
+        }
+        contacts.put(contact.getName(), contact);
+    }
+
+    @Override
+    public void removeContact(String name) throws NoSuchContactException {
+        if (!contacts.containsKey(name)) {
+            throw new NoSuchContactException(name);
+        }
+        contacts.remove(name);
+    }
+}
diff --git a/cxf-soap/src/main/java/org/acme/cxf/soap/wsdl/MyWsdlRouteBuilder.java b/cxf-soap/src/main/java/org/acme/cxf/soap/wsdl/MyWsdlRouteBuilder.java
new file mode 100644
index 0000000..7fac1ab
--- /dev/null
+++ b/cxf-soap/src/main/java/org/acme/cxf/soap/wsdl/MyWsdlRouteBuilder.java
@@ -0,0 +1,90 @@
+/*
+ * 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.acme.cxf.soap.wsdl;
+
+import java.util.HashMap;
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.SessionScoped;
+import javax.enterprise.inject.Produces;
+import javax.inject.Named;
+
+import com.example.customerservice.Customer;
+import com.example.customerservice.CustomerService;
+import com.example.customerservice.NoSuchCustomer;
+import com.example.customerservice.NoSuchCustomerException;
+import org.acme.cxf.soap.wsdl.repository.CustomerRepository;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.cxf.jaxws.CxfEndpoint;
+import org.apache.cxf.message.MessageContentsList;
+
+/**
+ * This class demonstrate how to expose a SOAP endpoint starting from a wsdl, using the
+ * quarkus-maven-plugin:generate-code
+ */
+@ApplicationScoped
+public class MyWsdlRouteBuilder extends RouteBuilder {
+
+    private final CustomerRepository customerRepository;
+
+    public MyWsdlRouteBuilder(CustomerRepository customerRepository) {
+        this.customerRepository = customerRepository;
+    }
+
+    @Produces
+    @SessionScoped
+    @Named
+    CxfEndpoint customer() {
+        CxfEndpoint customersEndpoint = new CxfEndpoint();
+        customersEndpoint.setWsdlURL("wsdl/CustomerService.wsdl");
+        customersEndpoint.setServiceClass(CustomerService.class);
+        customersEndpoint.setAddress("/customer");
+        customersEndpoint.setProperties(new HashMap<>());
+        // Request validation will be executed, in particular the name validation in getCustomersByName
+        customersEndpoint.getProperties().put("schema-validation-enabled", "true");
+
+        return customersEndpoint;
+    }
+
+    @Override
+    public void configure() throws Exception {
+        // CustomerService is generated with quarkus-maven-plugin:generate-code during the build
+        from("cxf:bean:customer")
+                .recipientList(simple("direct:${header.operationName}"));
+
+        from("direct:getCustomersByName").process(exchange -> {
+            String name = exchange.getIn().getBody(String.class);
+
+            MessageContentsList resultList = new MessageContentsList();
+            List<Customer> customersByName = customerRepository.getCustomersByName(name);
+
+            if (customersByName.isEmpty()) {
+                NoSuchCustomer noSuchCustomer = new NoSuchCustomer();
+                noSuchCustomer.setCustomerName(name);
+
+                throw new NoSuchCustomerException("Customer not found", noSuchCustomer);
+            }
+
+            resultList.add(customersByName);
+            exchange.getMessage().setBody(resultList);
+        });
+
+        from("direct:updateCustomer")
+                .process(exchange -> customerRepository.updateCustomer(exchange.getIn().getBody(Customer.class)));
+    }
+}
diff --git a/cxf-soap/src/main/java/org/acme/cxf/soap/wsdl/repository/CustomerRepository.java b/cxf-soap/src/main/java/org/acme/cxf/soap/wsdl/repository/CustomerRepository.java
new file mode 100644
index 0000000..d559fee
--- /dev/null
+++ b/cxf-soap/src/main/java/org/acme/cxf/soap/wsdl/repository/CustomerRepository.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.acme.cxf.soap.wsdl.repository;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.xml.datatype.DatatypeConfigurationException;
+
+import com.example.customerservice.Customer;
+import com.example.customerservice.CustomerType;
+
+@ApplicationScoped
+public class CustomerRepository {
+    List<Customer> customers = new ArrayList<>();
+
+    @PostConstruct
+    private void init() throws DatatypeConfigurationException {
+        populateCustomers();
+    }
+
+    public List<Customer> getCustomersByName(String name) {
+        return getCustomersStreamByName(name)
+                .collect(Collectors.toList());
+    }
+
+    private Stream<Customer> getCustomersStreamByName(String name) {
+        return customers.stream().filter(c -> c.getName().equals(name));
+    }
+
+    public void updateCustomer(Customer customer) {
+        getCustomersStreamByName(customer.getName())
+                .forEach(storedCustomer -> {
+                    storedCustomer.setRevenue(customer.getRevenue());
+                    storedCustomer.setCustomerId(customer.getCustomerId());
+                    storedCustomer.setNumOrders(customer.getNumOrders());
+                    storedCustomer.setType(customer.getType());
+                    storedCustomer.setTest(customer.getTest());
+                    storedCustomer.setBirthDate(customer.getBirthDate());
+                });
+    }
+
+    private void populateCustomers() throws DatatypeConfigurationException {
+        Customer a = new Customer();
+        a.setCustomerId(1);
+        a.setName("test");
+        a.setType(CustomerType.PRIVATE);
+        a.setNumOrders(1);
+        a.setBirthDate(LocalDate.now());
+
+        customers.add(a);
+    }
+
+}
diff --git a/cxf-soap/src/main/resources/application.properties b/cxf-soap/src/main/resources/application.properties
new file mode 100644
index 0000000..a5bd905
--- /dev/null
+++ b/cxf-soap/src/main/resources/application.properties
@@ -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.
+## ---------------------------------------------------------------------------
+#
+# Quarkus
+#
+quarkus.banner.enabled = false
+quarkus.log.file.enable = true
+quarkus.log.file.rotation.max-backup-index = 0
+
+#
+# CXF
+#
+quarkus.cxf.path=/cxf/services
+quarkus.cxf.codegen.wsdl2java.includes = wsdl/CustomerService.wsdl
+quarkus.cxf.codegen.wsdl2java.additional-params = -b,src/main/resources/binding.xml
+
+#
+# Camel
+#
+camel.context.name = camel-quarkus-examples-cxf-soap
+
+#
+# Kubernetes
+#
+# https://github.com/quarkusio/quarkus/issues/29209
+quarkus.kubernetes.image-pull-policy=IfNotPresent
+quarkus.kubernetes.ports."http".host-port=8080
\ No newline at end of file
diff --git a/cxf-soap/src/main/resources/binding.xml b/cxf-soap/src/main/resources/binding.xml
new file mode 100644
index 0000000..01e72a6
--- /dev/null
+++ b/cxf-soap/src/main/resources/binding.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+
+    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.
+
+-->
+<jaxws:bindings xmlns:jaxws="http://java.sun.com/xml/ns/jaxws" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" wsdlLocation="wsdl/CustomerService.wsdl">
+	<jaxws:bindings node="wsdl:definitions/wsdl:types/xs:schema">
+		<jxb:globalBindings>
+			<jxb:javaType name="java.time.LocalDateTime" xmlType="xs:dateTime" parseMethod="org.acme.cxf.soap.adapter.DataTypeAdapter.parseDateTime" printMethod="org.acme.cxf.soap.adapter.DataTypeAdapter.printDateTime"/>
+			<jxb:javaType name="java.time.LocalDate" xmlType="xs:date" parseMethod="org.acme.cxf.soap.adapter.DataTypeAdapter.parseDate" printMethod="org.acme.cxf.soap.adapter.DataTypeAdapter.printDate"/>
+		</jxb:globalBindings>
+	</jaxws:bindings>
+</jaxws:bindings>
diff --git a/cxf-soap/src/main/resources/requests/contact/add.xml b/cxf-soap/src/main/resources/requests/contact/add.xml
new file mode 100644
index 0000000..523711a
--- /dev/null
+++ b/cxf-soap/src/main/resources/requests/contact/add.xml
@@ -0,0 +1,33 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:con="http://camel.apache.org/test/ContactService">
+   <soapenv:Header/>
+   <soapenv:Body>
+      <con:addContact>
+         <arg0>
+            <name>Lukas</name>
+            <address>
+               <city>New York</city>
+               <street>Sky 1234</street>
+            </address>
+            <type>PERSONAL</type>
+         </arg0>
+      </con:addContact>
+   </soapenv:Body>
+</soapenv:Envelope>
\ No newline at end of file
diff --git a/cxf-soap/src/main/resources/requests/contact/getAll.xml b/cxf-soap/src/main/resources/requests/contact/getAll.xml
new file mode 100644
index 0000000..be2ff67
--- /dev/null
+++ b/cxf-soap/src/main/resources/requests/contact/getAll.xml
@@ -0,0 +1,24 @@
+<!--
+
+    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.
+
+-->
+<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:con="http://camel.apache.org/test/ContactService">
+   <soapenv:Header/>
+   <soapenv:Body>
+      <con:getContacts/>
+   </soapenv:Body>
+</soapenv:Envelope>
\ No newline at end of file
diff --git a/cxf-soap/src/main/resources/requests/customer/getByName.xml b/cxf-soap/src/main/resources/requests/customer/getByName.xml
new file mode 100644
index 0000000..7070171
--- /dev/null
+++ b/cxf-soap/src/main/resources/requests/customer/getByName.xml
@@ -0,0 +1,26 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cus="http://customerservice.example.com/">
+   <soapenv:Header/>
+   <soapenv:Body>
+      <cus:getCustomersByName>
+         <name>Non existent</name>
+      </cus:getCustomersByName>
+   </soapenv:Body>
+</soapenv:Envelope>
\ No newline at end of file
diff --git a/cxf-soap/src/main/resources/wsdl/CustomerService.wsdl b/cxf-soap/src/main/resources/wsdl/CustomerService.wsdl
new file mode 100644
index 0000000..78acd4d
--- /dev/null
+++ b/cxf-soap/src/main/resources/wsdl/CustomerService.wsdl
@@ -0,0 +1,122 @@
+<?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.
+
+-->
+<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://customerservice.example.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="CustomerServiceService" targetNamespace="http://customerservice.example.com/">
+	<wsdl:types>
+		<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://customerservice.example.com/" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://customerservice.example.com/">
+			<xs:element name="getCustomersByName" type="tns:getCustomersByName"/>
+			<xs:element name="getCustomersByNameResponse" type="tns:getCustomersByNameResponse"/>
+			<xs:element name="updateCustomer" type="tns:updateCustomer"/>
+			<xs:complexType name="updateCustomer">
+				<xs:sequence>
+					<xs:element minOccurs="0" name="customer" type="tns:customer"/>
+				</xs:sequence>
+			</xs:complexType>
+			<xs:complexType name="customer">
+				<xs:sequence>
+					<xs:element name="customerId" type="xs:int"/>
+					<xs:element minOccurs="0" name="name" type="xs:string"/>
+					<xs:element maxOccurs="unbounded" minOccurs="0" name="address" nillable="true" type="xs:string"/>
+					<xs:element minOccurs="0" name="numOrders" type="xs:int"/>
+					<xs:element name="revenue" type="xs:double"/>
+					<xs:element minOccurs="0" name="test" type="xs:decimal"/>
+					<xs:element minOccurs="0" name="birthDate" type="xs:date"/>
+					<xs:element minOccurs="0" name="type" type="tns:customerType"/>
+				</xs:sequence>
+			</xs:complexType>
+			<xs:complexType name="getCustomersByName">
+				<xs:sequence>
+					<xs:element name="name">
+						<xs:simpleType>
+							<xs:restriction base="xs:string">
+								<xs:minLength value="2"/>
+								<xs:maxLength value="15"/>
+							</xs:restriction>
+						</xs:simpleType>
+					</xs:element>
+				</xs:sequence>
+			</xs:complexType>
+			<xs:complexType name="getCustomersByNameResponse">
+				<xs:sequence>
+					<xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="tns:customer"/>
+				</xs:sequence>
+			</xs:complexType>
+			<xs:simpleType name="customerType">
+				<xs:restriction base="xs:string">
+					<xs:enumeration value="PRIVATE"/>
+					<xs:enumeration value="BUSINESS"/>
+				</xs:restriction>
+			</xs:simpleType>
+			<xs:element name="NoSuchCustomer" type="tns:NoSuchCustomer"/>
+			<xs:complexType name="NoSuchCustomer">
+				<xs:sequence>
+					<xs:element name="customerName" nillable="true" type="xs:string"/>
+				</xs:sequence>
+			</xs:complexType>
+		</xs:schema>
+	</wsdl:types>
+	<wsdl:message name="getCustomersByNameResponse">
+		<wsdl:part name="parameters" element="tns:getCustomersByNameResponse"/>
+	</wsdl:message>
+	<wsdl:message name="getCustomersByName">
+		<wsdl:part name="parameters" element="tns:getCustomersByName"/>
+	</wsdl:message>
+	<wsdl:message name="updateCustomer">
+		<wsdl:part name="parameters" element="tns:updateCustomer"/>
+	</wsdl:message>
+	<wsdl:message name="NoSuchCustomerException">
+		<wsdl:part name="NoSuchCustomerException" element="tns:NoSuchCustomer"/>
+	</wsdl:message>
+	<wsdl:portType name="CustomerService">
+		<wsdl:operation name="updateCustomer">
+			<wsdl:input name="updateCustomer" message="tns:updateCustomer"/>
+		</wsdl:operation>
+		<wsdl:operation name="getCustomersByName">
+			<wsdl:input name="getCustomersByName" message="tns:getCustomersByName"/>
+			<wsdl:output name="getCustomersByNameResponse" message="tns:getCustomersByNameResponse"/>
+			<wsdl:fault name="NoSuchCustomerException" message="tns:NoSuchCustomerException"/>
+		</wsdl:operation>
+	</wsdl:portType>
+	<wsdl:binding name="CustomerServiceServiceSoapBinding" type="tns:CustomerService">
+		<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+		<wsdl:operation name="updateCustomer">
+			<soap:operation soapAction="" style="document"/>
+			<wsdl:input name="updateCustomer">
+				<soap:body use="literal"/>
+			</wsdl:input>
+		</wsdl:operation>
+		<wsdl:operation name="getCustomersByName">
+			<soap:operation soapAction="" style="document"/>
+			<wsdl:input name="getCustomersByName">
+				<soap:body use="literal"/>
+			</wsdl:input>
+			<wsdl:output name="getCustomersByNameResponse">
+				<soap:body use="literal"/>
+			</wsdl:output>
+			<wsdl:fault name="NoSuchCustomerException">
+				<soap:fault name="NoSuchCustomerException" use="literal"/>
+			</wsdl:fault>
+		</wsdl:operation>
+	</wsdl:binding>
+	<wsdl:service name="CustomerServiceService">
+		<wsdl:port name="CustomerServicePort" binding="tns:CustomerServiceServiceSoapBinding">
+			<soap:address location="http://localhost:8080/services/customers"/>
+		</wsdl:port>
+	</wsdl:service>
+</wsdl:definitions>
\ No newline at end of file
diff --git a/cxf-soap/src/test/java/org/acme/cxf/soap/BaseTest.java b/cxf-soap/src/test/java/org/acme/cxf/soap/BaseTest.java
new file mode 100644
index 0000000..445afe6
--- /dev/null
+++ b/cxf-soap/src/test/java/org/acme/cxf/soap/BaseTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.acme.cxf.soap;
+
+import io.quarkus.runtime.LaunchMode;
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+
+public class BaseTest {
+    protected String getServerUrl() {
+        Config config = ConfigProvider.getConfig();
+        final int port = LaunchMode.current().equals(LaunchMode.TEST) ? config.getValue("quarkus.http.test-port", Integer.class)
+                : config.getValue("quarkus.http.port", Integer.class);
+        return String.format("http://localhost:%d", port);
+    }
+}
diff --git a/cxf-soap/src/test/java/org/acme/cxf/soap/PojoClientTest.java b/cxf-soap/src/test/java/org/acme/cxf/soap/PojoClientTest.java
new file mode 100644
index 0000000..c682828
--- /dev/null
+++ b/cxf-soap/src/test/java/org/acme/cxf/soap/PojoClientTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.acme.cxf.soap;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.Service;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.acme.cxf.soap.pojo.service.Address;
+import org.acme.cxf.soap.pojo.service.Contact;
+import org.acme.cxf.soap.pojo.service.ContactService;
+import org.acme.cxf.soap.pojo.service.ContactType;
+import org.acme.cxf.soap.pojo.service.NoSuchContactException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+public class PojoClientTest extends BaseTest {
+
+    protected ContactService createCXFClient() {
+        try {
+            final URL serviceUrl = new URL(getServerUrl() + "/cxf/services/contact?wsdl");
+            final QName qName = new QName(ContactService.TARGET_NS, ContactService.class.getSimpleName());
+            final Service service = Service.create(serviceUrl, qName);
+            return service.getPort(ContactService.class);
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected static Contact createContact() {
+        Contact contact = new Contact();
+        contact.setName("Croway");
+        contact.setType(ContactType.OTHER);
+        Address address = new Address();
+        address.setCity("Rome");
+        address.setStreet("Test Street");
+        contact.setAddress(address);
+
+        return contact;
+    }
+
+    @Test
+    public void testBasic() throws NoSuchContactException {
+        ContactService cxfClient = createCXFClient();
+
+        cxfClient.addContact(createContact());
+        Assertions.assertSame(1, cxfClient.getContacts().getContacts().size(), "We should have one contact.");
+
+        Assertions.assertNotNull(cxfClient.getContact("Croway"), "We haven't found contact.");
+
+        Assertions.assertThrows(NoSuchContactException.class, () -> cxfClient.getContact("Non existent"));
+    }
+}
diff --git a/cxf-soap/src/test/java/org/acme/cxf/soap/PojoClientTestIT.java b/cxf-soap/src/test/java/org/acme/cxf/soap/PojoClientTestIT.java
new file mode 100644
index 0000000..c57df86
--- /dev/null
+++ b/cxf-soap/src/test/java/org/acme/cxf/soap/PojoClientTestIT.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acme.cxf.soap;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+public class PojoClientTestIT extends PojoClientTest {
+}
diff --git a/cxf-soap/src/test/java/org/acme/cxf/soap/WsdlClientTest.java b/cxf-soap/src/test/java/org/acme/cxf/soap/WsdlClientTest.java
new file mode 100644
index 0000000..f5c9ad2
--- /dev/null
+++ b/cxf-soap/src/test/java/org/acme/cxf/soap/WsdlClientTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.acme.cxf.soap;
+
+import java.time.Duration;
+import java.time.LocalDate;
+import java.util.List;
+
+import javax.xml.ws.soap.SOAPFaultException;
+
+import com.example.customerservice.Customer;
+import com.example.customerservice.CustomerService;
+import com.example.customerservice.NoSuchCustomerException;
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.cxf.ext.logging.LoggingFeature;
+import org.apache.cxf.frontend.ClientProxyFactoryBean;
+import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
+import org.awaitility.Awaitility;
+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.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+@QuarkusTest
+public class WsdlClientTest extends BaseTest {
+
+    CustomerService cxfClient;
+
+    protected CustomerService createCustomerClient() {
+        String URL = getServerUrl() + "/cxf/services/customer";
+
+        ClientProxyFactoryBean factory = new JaxWsProxyFactoryBean();
+        factory.setServiceClass(CustomerService.class);
+        factory.setAddress(URL);
+        factory.getFeatures().add(new LoggingFeature());
+        return (CustomerService) factory.create();
+    }
+
+    @BeforeEach
+    public void before() {
+        cxfClient = createCustomerClient();
+    }
+
+    @Test
+    public void testGetCustomer() throws Exception {
+        List<Customer> customers = cxfClient.getCustomersByName("test");
+        assertEquals(customers.get(0).getName(), "test");
+        assertEquals(customers.get(0).getCustomerId(), 1);
+    }
+
+    @Test
+    public void testNonExistentCustomer() throws Exception {
+        Assertions.assertThrows(NoSuchCustomerException.class, () -> cxfClient.getCustomersByName("Non existent"));
+    }
+
+    @Test
+    public void testInvalidRequest() {
+        Assertions.assertThrows(SOAPFaultException.class, () -> cxfClient.getCustomersByName("a"));
+    }
+
+    @Test
+    public void testUpdateCustomer() throws Exception {
+        double revenue = 9999;
+        LocalDate birthDate = LocalDate.parse("1990-03-13");
+
+        List<Customer> customers = cxfClient.getCustomersByName("test");
+
+        assertNotEquals(customers.get(0).getRevenue(), revenue);
+        assertNotEquals(customers.get(0).getBirthDate(), birthDate);
+
+        Customer customer = customers.get(0);
+        customer.setRevenue(revenue);
+        customer.setBirthDate(birthDate);
+
+        // void method are async by default
+        cxfClient.updateCustomer(customer);
+
+        Awaitility.await().atMost(Duration.ofSeconds(5))
+                .until(() -> {
+                    List<Customer> updatedCustomers = cxfClient.getCustomersByName("test");
+
+                    return updatedCustomers.get(0).getName().equals("test") &&
+                            updatedCustomers.get(0).getCustomerId() == 1 &&
+                            updatedCustomers.get(0).getRevenue() == revenue &&
+                            updatedCustomers.get(0).getBirthDate().equals(birthDate);
+                });
+    }
+}
diff --git a/cxf-soap/src/test/java/org/acme/cxf/soap/WsdlClientTestIT.java b/cxf-soap/src/test/java/org/acme/cxf/soap/WsdlClientTestIT.java
new file mode 100644
index 0000000..172917c
--- /dev/null
+++ b/cxf-soap/src/test/java/org/acme/cxf/soap/WsdlClientTestIT.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.acme.cxf.soap;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+public class WsdlClientTestIT extends WsdlClientTest {
+}
diff --git a/docs/modules/ROOT/attachments/examples.json b/docs/modules/ROOT/attachments/examples.json
index d920897..cb219ca 100644
--- a/docs/modules/ROOT/attachments/examples.json
+++ b/docs/modules/ROOT/attachments/examples.json
@@ -1,4 +1,9 @@
 [
+  {
+    "title": "Camel Quarkus CXF SOAP example",
+    "description": "Shows how to use Camel CXF SOAP component.",
+    "link": "https://github.com/apache/camel-quarkus-examples/tree/main/cxf-soap"
+  },
   {
     "title": "Connecting to a JDBC DataSource",
     "description": "Shows how to connect to a Database using Datastores.",