{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.
The "WSDL first" approach presupposes writing the WSDL file manually at the beginning of the SOAP service design.
Then we can use 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 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 Java from WSDL chapter of Quarkus CXF documentation. |
For illustrating how other wsdl2java
options could be applied via quarkus.cxf.codegen.wsdl2java.additional-params
, we have added a custom binding defined in binding.xml.
It instructs CXF to use LocalDate
(more common in Java world) instead of default XML Date representation XMLGregorianCalendar
.
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 WSDL from Java chapter of Quarkus CXF documentation. |
$ 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 Camel Quarkus User guide for more details. |
We can first try to add a contact with:
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:
$ 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:
<?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:
$ 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
as the name in the SOAPBody
part in src/main/resources/requests/customer/getByName.xml
as follows:
<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:
<?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>
The last thing which could be tested, is trying to get a non-existent customer (which t
was obviously as well, but now we will pass it through schema validation). So change the name to Non existent
and see result with NoSuchCustomer
:
<?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:
$ curl "http://localhost:8080/cxf/services/contact?wsdl"
$ curl "http://localhost:8080/cxf/services/customer?wsdl"
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 Camel Quarkus User guide |
Important
|
Native mode requires having GraalVM and other tools installed. Please check the Prerequisites section of Camel Quarkus User guide. |
To prepare a native executable using GraalVM, run the following command:
$ mvn clean package -Pnative
$ ./target/*-runner
$ mvn clean package -DskipTests -Dquarkus.kubernetes.deploy=true -Dkubernetes
You should see one pod running:
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:
$ 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 the port-forwarding terminal and shutdown the Kubernetes cluster.
Please report bugs and propose improvements via GitHub issues of Camel Quarkus project.