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

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

commit 5322d41dbec2c4a0efd118b7830979d963cf70b4
Author: Croway <federico.mariani.1...@gmail.com>
AuthorDate: Mon Sep 19 12:40:56 2022 +0200

    ✨ SOAP CXF Example
---
 README.adoc                                        |   2 +
 pom.xml                                            |   1 +
 soap-cxf/README.adoc                               |  46 +++++
 soap-cxf/pom.xml                                   | 172 +++++++++++++++++
 .../src/main/java/sample/camel/Application.java    |  32 ++++
 .../sample/camel/ContactServiceInMemoryImpl.java   |  74 ++++++++
 .../main/java/sample/camel/MyPojoRouteBuilder.java |  47 +++++
 .../main/java/sample/camel/MyWsdlRouteBuilder.java |  87 +++++++++
 .../java/sample/camel/adapter/DataTypeAdapter.java |  75 ++++++++
 .../camel/repository/CustomerRepository.java       |  72 ++++++++
 .../main/java/sample/camel/service/Address.java    |  93 ++++++++++
 .../main/java/sample/camel/service/Contact.java    |  68 +++++++
 .../java/sample/camel/service/ContactRequest.java  |  29 +++
 .../java/sample/camel/service/ContactService.java  |  31 ++++
 .../java/sample/camel/service/ContactType.java     |  21 +++
 .../sample/camel/service/GetContactsResponse.java  |  31 ++++
 .../camel/service/NoSuchContactException.java      |  46 +++++
 soap-cxf/src/main/resources/META-INF/LICENSE.txt   | 203 +++++++++++++++++++++
 soap-cxf/src/main/resources/META-INF/NOTICE.txt    |  11 ++
 soap-cxf/src/main/resources/application.properties |  25 +++
 soap-cxf/src/main/resources/binding.xml            |  27 +++
 .../src/main/resources/wsdl/CustomerService.wsdl   | 122 +++++++++++++
 .../src/test/java/sample/camel/PojoClientTest.java |  73 ++++++++
 .../src/test/java/sample/camel/WsdlClientTest.java | 116 ++++++++++++
 24 files changed, 1504 insertions(+)

diff --git a/README.adoc b/README.adoc
index fa3634b..18eadf2 100644
--- a/README.adoc
+++ b/README.adoc
@@ -76,6 +76,8 @@ Number of Examples: 49 (0 deprecated)
 
 | link:webhook/readme.adoc[Webhook] (webhook) | Cloud | Example on how to use 
the Camel Webhook component
 
+| link:soap-cxf/README.adoc[Spring Boot SOAP CXF] (cxf-soap) | CXF | An 
example showing how to work with Camel SOAP CXF and Spring Boot
+
 | link:master/readme.adoc[Master] (master) | Clustering | An example showing 
how to work with Camel's Master component and Spring Boot
 
 | link:arangodb/README.adoc[Arangodb] (arangodb) | Database | An example 
showing the Camel ArangoDb component with Spring Boot
diff --git a/pom.xml b/pom.xml
index 8d63595..7983887 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,6 +74,7 @@
                <module>route-reload</module>
                <module>routes-configuration</module>
                <module>saga</module>
+               <module>soap-cxf</module>
                <module>supervising-route-controller</module>
                <module>twitter-salesforce</module>
                <module>type-converter</module>
diff --git a/soap-cxf/README.adoc b/soap-cxf/README.adoc
new file mode 100644
index 0000000..23bdb84
--- /dev/null
+++ b/soap-cxf/README.adoc
@@ -0,0 +1,46 @@
+== Camel SOAP CXF example
+
+This example shows how to serve a SOAP CXF service with the help of Camel SOAP 
CXF component.
+
+The example is a standalone Spring Boot application that expose SOAP services 
that let you interact with a list of contact, you can run it with:
+
+....
+$ mvn spring-boot:run
+....
+
+Or by packaging it and running it using `+java+` CLI:
+
+....
+$ mvn package
+$ java -jar target/camel-example-spring-boot-soap-cxf-*.jar
+....
+
+=== Java to WSDL Service
+
+The example expose the wsdl which is generated from the `ContactService.java` 
by camel-soap-cxf:
+
+....
+$ curl http://localhost:8080/services/contact\?wsdl
+....
+
+In order to interact with the application a SOAP client like SoapUI can be 
used, or you can use the PojoClientTest as a reference to use the CXF client 
programmatically.
+
+=== WSDL to Java Service
+
+The example expose another SOAP service which is generated starting from the 
`CustomerService.wsdl`:
+
+....
+$ curl http://localhost:8080/services/customers\?wsdl
+....
+
+In order to interact with the application a SOAP client like SoapUI can be 
used, or you can use the WsdlClientTest as a reference to use the CXF client 
programmatically.
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/support.html[let us know].
+
+We also love contributors, so
+https://camel.apache.org/contributing.html[get involved] :-)
+
+The Camel riders!
diff --git a/soap-cxf/pom.xml b/soap-cxf/pom.xml
new file mode 100644
index 0000000..66e8340
--- /dev/null
+++ b/soap-cxf/pom.xml
@@ -0,0 +1,172 @@
+<?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 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
https://maven.apache.org/xsd/maven-4.0.0.xsd"; 
xmlns="http://maven.apache.org/POM/4.0.0";
+               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.apache.camel.springboot.example</groupId>
+               <artifactId>examples</artifactId>
+               <version>3.19.0-SNAPSHOT</version>
+       </parent>
+
+       <artifactId>camel-example-spring-boot-soap-cxf</artifactId>
+       <name>Camel SB Examples :: SOAP CXF</name>
+       <description>An example showing the Camel SOAP CXF</description>
+
+       <properties>
+               <category>CXF</category>
+               
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+               
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+       </properties>
+
+       <dependencyManagement>
+               <dependencies>
+                       <dependency>
+                               <groupId>org.springframework.boot</groupId>
+                               
<artifactId>spring-boot-dependencies</artifactId>
+                               <version>${spring-boot-version}</version>
+                               <type>pom</type>
+                               <scope>import</scope>
+                       </dependency>
+                       <dependency>
+                               <groupId>org.apache.camel.springboot</groupId>
+                               <artifactId>camel-spring-boot-bom</artifactId>
+                               <version>${project.version}</version>
+                               <type>pom</type>
+                               <scope>import</scope>
+                       </dependency>
+
+                       <dependency>
+                               <groupId>org.apache.cxf</groupId>
+                               <artifactId>cxf-bom</artifactId>
+                               <version>${cxf-version}</version>
+                               <type>pom</type>
+                               <scope>import</scope>
+                       </dependency>
+               </dependencies>
+       </dependencyManagement>
+       <dependencies>
+               <dependency>
+                       <groupId>org.apache.camel.springboot</groupId>
+                       <artifactId>camel-spring-boot-starter</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-web</artifactId>
+                       <exclusions>
+                               <exclusion>
+                                       
<groupId>org.springframework.boot</groupId>
+                                       
<artifactId>spring-boot-starter-tomcat</artifactId>
+                               </exclusion>
+                       </exclusions>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-undertow</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-actuator</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.camel.springboot</groupId>
+                       <artifactId>camel-bean-validator-starter</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.camel.springboot</groupId>
+                       <artifactId>camel-cxf-soap-starter</artifactId>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.apache.camel.springboot</groupId>
+                       <artifactId>camel-servlet-starter</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.camel.springboot</groupId>
+                       <artifactId>camel-jackson-starter</artifactId>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.apache.cxf</groupId>
+                       <artifactId>cxf-spring-boot-starter-jaxws</artifactId>
+                       <exclusions>
+                               <exclusion>
+                                       
<groupId>org.springframework.boot</groupId>
+                                       
<artifactId>spring-boot-starter-tomcat</artifactId>
+                               </exclusion>
+                       </exclusions>
+               </dependency>
+
+               <dependency>
+                       <groupId>org.springframework.boot</groupId>
+                       <artifactId>spring-boot-starter-test</artifactId>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.awaitility</groupId>
+                       <artifactId>awaitility</artifactId>
+                       <version>${awaitility-version}</version>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.springframework.boot</groupId>
+                               
<artifactId>spring-boot-maven-plugin</artifactId>
+                               <version>${spring-boot-version}</version>
+                               <executions>
+                                       <execution>
+                                               <goals>
+                                                       <goal>repackage</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.cxf</groupId>
+                               <artifactId>cxf-codegen-plugin</artifactId>
+                               <version>${cxf-version}</version>
+                               <executions>
+                                       <execution>
+                                               <id>generate-sources</id>
+                                               <phase>generate-sources</phase>
+                                               <configuration>
+                                                       
<sourceRoot>${project.build.directory}/generated-sources/cxf</sourceRoot>
+                                                       <wsdlOptions>
+                                                               <wsdlOption>
+                                                                       
<wsdl>src/main/resources/wsdl/CustomerService.wsdl</wsdl>
+                                                                       
<faultSerialVersionUID>1</faultSerialVersionUID>
+                                                                       
<bindingFiles>
+                                                                               
<bindingFile>src/main/resources/binding.xml</bindingFile>
+                                                                       
</bindingFiles>
+                                                               </wsdlOption>
+                                                       </wsdlOptions>
+                                               </configuration>
+                                               <goals>
+                                                       <goal>wsdl2java</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+</project>
diff --git a/soap-cxf/src/main/java/sample/camel/Application.java 
b/soap-cxf/src/main/java/sample/camel/Application.java
new file mode 100644
index 0000000..e23d3c2
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/Application.java
@@ -0,0 +1,32 @@
+/*
+ * 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 sample.camel;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+    /**
+     * A main method to start this application.
+     */
+    public static void main(String[] args) {
+        SpringApplication.run(Application.class, args);
+    }
+
+}
diff --git 
a/soap-cxf/src/main/java/sample/camel/ContactServiceInMemoryImpl.java 
b/soap-cxf/src/main/java/sample/camel/ContactServiceInMemoryImpl.java
new file mode 100644
index 0000000..0866228
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/ContactServiceInMemoryImpl.java
@@ -0,0 +1,74 @@
+/*
+ * 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 sample.camel;
+
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import sample.camel.service.Contact;
+import sample.camel.service.ContactService;
+import sample.camel.service.GetContactsResponse;
+import sample.camel.service.NoSuchContactException;
+
+@Service("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 GetContactsResponse getContacts() {
+               GetContactsResponse result = new GetContactsResponse();
+               result.setContacts(contacts.values());
+
+               return result;
+       }
+
+       @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/soap-cxf/src/main/java/sample/camel/MyPojoRouteBuilder.java 
b/soap-cxf/src/main/java/sample/camel/MyPojoRouteBuilder.java
new file mode 100644
index 0000000..629f667
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/MyPojoRouteBuilder.java
@@ -0,0 +1,47 @@
+/*
+ * 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 sample.camel;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.cxf.jaxws.CxfEndpoint;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+import sample.camel.service.ContactService;
+
+/**
+ * This class demonstrate how to expose a SOAP endpoint starting from java 
classes
+ */
+@Component
+public class MyPojoRouteBuilder extends RouteBuilder {
+
+       @Bean
+       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/soap-cxf/src/main/java/sample/camel/MyWsdlRouteBuilder.java 
b/soap-cxf/src/main/java/sample/camel/MyWsdlRouteBuilder.java
new file mode 100644
index 0000000..ab5c2b5
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/MyWsdlRouteBuilder.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package sample.camel;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.cxf.jaxws.CxfEndpoint;
+import org.apache.cxf.message.MessageContentsList;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+import com.example.customerservice.Customer;
+import com.example.customerservice.CustomerService;
+import com.example.customerservice.NoSuchCustomer;
+import com.example.customerservice.NoSuchCustomerException;
+
+import java.util.HashMap;
+import java.util.List;
+
+import sample.camel.repository.CustomerRepository;
+
+/**
+ * This class demonstrate how to expose a SOAP endpoint starting from a wsdl, 
using the cxf-codegen-plugin
+ */
+@Component
+public class MyWsdlRouteBuilder extends RouteBuilder {
+
+       private final CustomerRepository customerRepository;
+
+       public MyWsdlRouteBuilder(CustomerRepository customerRepository) {
+               this.customerRepository = customerRepository;
+       }
+
+       @Bean
+       CxfEndpoint customers() {
+               CxfEndpoint customersEndpoint = new CxfEndpoint();
+               customersEndpoint.setWsdlURL("wsdl/CustomerService.wsdl");
+               customersEndpoint.setServiceClass(CustomerService.class);
+               customersEndpoint.setAddress("/customers");
+               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 cxf-codegen-plugin during 
the build
+               from("cxf:bean:customers")
+                               
.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/soap-cxf/src/main/java/sample/camel/adapter/DataTypeAdapter.java 
b/soap-cxf/src/main/java/sample/camel/adapter/DataTypeAdapter.java
new file mode 100644
index 0000000..e335586
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/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 sample.camel.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/soap-cxf/src/main/java/sample/camel/repository/CustomerRepository.java 
b/soap-cxf/src/main/java/sample/camel/repository/CustomerRepository.java
new file mode 100644
index 0000000..94de123
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/repository/CustomerRepository.java
@@ -0,0 +1,72 @@
+/*
+ * 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 sample.camel.repository;
+
+import org.springframework.stereotype.Repository;
+
+import com.example.customerservice.Customer;
+import com.example.customerservice.CustomerType;
+
+import javax.annotation.PostConstruct;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Repository
+public class CustomerRepository {
+       List<Customer> customers = new ArrayList<>();
+
+       @PostConstruct
+       private void init() {
+               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() {
+               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/soap-cxf/src/main/java/sample/camel/service/Address.java 
b/soap-cxf/src/main/java/sample/camel/service/Address.java
new file mode 100644
index 0000000..104fc0c
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/service/Address.java
@@ -0,0 +1,93 @@
+/*
+ * 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 sample.camel.service;
+
+import javax.validation.constraints.Pattern;
+
+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/soap-cxf/src/main/java/sample/camel/service/Contact.java 
b/soap-cxf/src/main/java/sample/camel/service/Contact.java
new file mode 100644
index 0000000..58008f7
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/service/Contact.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package sample.camel.service;
+
+import javax.validation.Valid;
+import javax.validation.constraints.Size;
+
+import java.util.Objects;
+
+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/soap-cxf/src/main/java/sample/camel/service/ContactRequest.java 
b/soap-cxf/src/main/java/sample/camel/service/ContactRequest.java
new file mode 100644
index 0000000..1d086ff
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/service/ContactRequest.java
@@ -0,0 +1,29 @@
+/*
+ * 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 sample.camel.service;
+
+public class ContactRequest {
+       private Contact contact;
+
+       public Contact getContact() {
+               return contact;
+       }
+
+       public void setContact(Contact contact) {
+               this.contact = contact;
+       }
+}
diff --git a/soap-cxf/src/main/java/sample/camel/service/ContactService.java 
b/soap-cxf/src/main/java/sample/camel/service/ContactService.java
new file mode 100644
index 0000000..8683fdc
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/service/ContactService.java
@@ -0,0 +1,31 @@
+/*
+ * 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 sample.camel.service;
+
+public interface ContactService {
+
+       void addContact(Contact contact);
+
+       Contact getContact(String name) throws NoSuchContactException;
+
+       GetContactsResponse getContacts();
+
+       void updateContact(String name, Contact contact)
+                       throws NoSuchContactException;
+
+       void removeContact(String name) throws NoSuchContactException;
+}
diff --git a/soap-cxf/src/main/java/sample/camel/service/ContactType.java 
b/soap-cxf/src/main/java/sample/camel/service/ContactType.java
new file mode 100644
index 0000000..c5cc16b
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/service/ContactType.java
@@ -0,0 +1,21 @@
+/*
+ * 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 sample.camel.service;
+
+public enum ContactType {
+       PERSONAL, WORK, OTHER,
+}
diff --git 
a/soap-cxf/src/main/java/sample/camel/service/GetContactsResponse.java 
b/soap-cxf/src/main/java/sample/camel/service/GetContactsResponse.java
new file mode 100644
index 0000000..e36d9b0
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/service/GetContactsResponse.java
@@ -0,0 +1,31 @@
+/*
+ * 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 sample.camel.service;
+
+import java.util.Collection;
+
+public class GetContactsResponse {
+       private Collection<Contact> contacts;
+
+       public Collection<Contact> getContacts() {
+               return contacts;
+       }
+
+       public void setContacts(Collection<Contact> contacts) {
+               this.contacts = contacts;
+       }
+}
diff --git 
a/soap-cxf/src/main/java/sample/camel/service/NoSuchContactException.java 
b/soap-cxf/src/main/java/sample/camel/service/NoSuchContactException.java
new file mode 100644
index 0000000..1f5bc46
--- /dev/null
+++ b/soap-cxf/src/main/java/sample/camel/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 sample.camel.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/soap-cxf/src/main/resources/META-INF/LICENSE.txt 
b/soap-cxf/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/soap-cxf/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
diff --git a/soap-cxf/src/main/resources/META-INF/NOTICE.txt 
b/soap-cxf/src/main/resources/META-INF/NOTICE.txt
new file mode 100644
index 0000000..2e215bf
--- /dev/null
+++ b/soap-cxf/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,11 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.
diff --git a/soap-cxf/src/main/resources/application.properties 
b/soap-cxf/src/main/resources/application.properties
new file mode 100644
index 0000000..e68dfe1
--- /dev/null
+++ b/soap-cxf/src/main/resources/application.properties
@@ -0,0 +1,25 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+# the name of Camel
+camel.springboot.name = MyCamel
+camel.springboot.main-run-controller=true
+
+# logging.level.root=TRACE
+
+management.endpoint.metrics.enabled=true
+management.endpoints.web.exposure.include=*
diff --git a/soap-cxf/src/main/resources/binding.xml 
b/soap-cxf/src/main/resources/binding.xml
new file mode 100644
index 0000000..f736f76
--- /dev/null
+++ b/soap-cxf/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="sample.camel.adapter.DataTypeAdapter.parseDateTime" 
printMethod="sample.camel.adapter.DataTypeAdapter.printDateTime"/>
+                       <jxb:javaType name="java.time.LocalDate" 
xmlType="xs:date" parseMethod="sample.camel.adapter.DataTypeAdapter.parseDate" 
printMethod="sample.camel.adapter.DataTypeAdapter.printDate"/>
+               </jxb:globalBindings>
+       </jaxws:bindings>
+</jaxws:bindings>
diff --git a/soap-cxf/src/main/resources/wsdl/CustomerService.wsdl 
b/soap-cxf/src/main/resources/wsdl/CustomerService.wsdl
new file mode 100644
index 0000000..06787a7
--- /dev/null
+++ b/soap-cxf/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/soap-cxf/src/test/java/sample/camel/PojoClientTest.java 
b/soap-cxf/src/test/java/sample/camel/PojoClientTest.java
new file mode 100644
index 0000000..b493564
--- /dev/null
+++ b/soap-cxf/src/test/java/sample/camel/PojoClientTest.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 sample.camel;
+
+import org.apache.cxf.frontend.ClientProxyFactoryBean;
+
+import org.junit.jupiter.api.Test;
+
+import org.assertj.core.api.Assertions;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.server.LocalServerPort;
+
+import sample.camel.service.Address;
+import sample.camel.service.Contact;
+import sample.camel.service.ContactService;
+import sample.camel.service.ContactType;
+import sample.camel.service.NoSuchContactException;
+
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class PojoClientTest {
+
+       @LocalServerPort
+       private int port;
+
+       protected ContactService createCXFClient() {
+               String URL = "http://localhost:"; + port + "/services/contact";
+
+               ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
+               factory.setServiceClass(ContactService.class);
+               factory.setAddress(URL);
+
+               return (ContactService) factory.create();
+       }
+
+       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.assertThat(cxfClient.getContacts().getContacts()).hasSize(1);
+
+               
Assertions.assertThat(cxfClient.getContact("Croway")).isNotNull();
+
+               Assertions.assertThatThrownBy(() -> cxfClient.getContact("Non 
existent")).isInstanceOf(NoSuchContactException.class);
+       }
+}
diff --git a/soap-cxf/src/test/java/sample/camel/WsdlClientTest.java 
b/soap-cxf/src/test/java/sample/camel/WsdlClientTest.java
new file mode 100644
index 0000000..2e428b2
--- /dev/null
+++ b/soap-cxf/src/test/java/sample/camel/WsdlClientTest.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package sample.camel;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import org.apache.cxf.ext.logging.LoggingFeature;
+import org.apache.cxf.frontend.ClientProxyFactoryBean;
+import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.assertj.core.api.Assertions;
+import org.awaitility.Awaitility;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.server.LocalServerPort;
+
+import com.example.customerservice.Customer;
+import com.example.customerservice.CustomerService;
+import com.example.customerservice.NoSuchCustomerException;
+
+import javax.xml.ws.soap.SOAPFaultException;
+
+import java.time.Duration;
+import java.time.LocalDate;
+import java.util.List;
+
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class WsdlClientTest {
+
+       @LocalServerPort
+       private int port;
+
+       CustomerService cxfClient;
+
+       protected CustomerService createCustomerClient() {
+               String URL = "http://localhost:"; + port + "/services/customers";
+
+               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.assertThatThrownBy(() -> 
cxfClient.getCustomersByName("Non existent"))
+                               .isInstanceOf(NoSuchCustomerException.class);
+       }
+
+       @Test
+       public void testInvalidRequest() {
+               Assertions.assertThatThrownBy(() -> 
cxfClient.getCustomersByName("a"))
+                               .isInstanceOf(SOAPFaultException.class);
+       }
+
+       @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);
+                               });
+       }
+}

Reply via email to