Web services are a very popular way to introduce communication between heterogeneous IT systems. Probably the most common type of web services in the industry are WSDL (Web Services Description Language) ones. This recipe will guide you through the process of creating and deploying a WSDL web service into the ServiceMix container.
ServiceMix uses Apache CXF as the preferred engine for its web service stack. In this recipe, we will use the Maven Archetype mechanism to generate a new OSGI module with CXF support enabled. The module with CXF support is the one that starts the CXF endpoint exposing in our service. Before we start our CXF module, we will again use Maven, this time to generate the Java code from the WSDL file.
As you can see, Maven is an essential tool to complete this task, so make sure that you have this useful utility properly installed in your system.
We will also assume that your ServiceMix instance is already installed and running.
Create a CXF project using the Maven Archetype called
org.apache.servicemix.tooling:servicemix-cxf-wsdl-first-osgi-bundle
.Add the WSDL file containing your contract to the project.
Generate the sources from the WSDL file using the
mvn generate-sources
Maven command.Add business logic implementation to the generated Java classes.
Build and deploy the module. (If you don't remember how to build and deploy modules to ServiceMix, please refer to the Creating and deploying a new Camel route (Must know) recipe
A web service created from the WSDL file is called a contract-first web service. Web service created as a Java POJO with WSDL generated from it is called a code-first web service. In this recipe, we will focus on the contract-first services.
At the beginning of this recipe, you should generate the code-first CXF module you will work on. We will use the Maven archetype mechanism (http://maven.apache.org/archetype/maven-archetype-plugin) for this purpose.
The following Maven command can be used to generate a new CXF WSDL-first project:
mvn archetype:generate -DarchetypeGroupId=org.apache.servicemix.tooling -DarchetypeArtifactId=servicemix-cxf-wsdl-first-osgi-bundle -DgroupId=com.packtpub.servicemixhowto -DartifactId=cxf-wsdl-first-example -Dversion=1.0-SNAPSHOT
We use the servicemix-cxf-wsdl-first-osgi-bundle
Maven archetype from the org.apachemix.tooling
group as a template for our module. We name our project cxf-wsdl-first-example
. We will create our example in the Maven group namespaced as com.packtpub.servicemix
and assign it the 1.0-SNAPSHOT
version.
The stub of the contract-first module we have just generated with Maven contains the following WSDL file under cxf-code-first-example/src/main/resources/wsdl/person.wsdl
path.
This file defines the very simple WSDL contract that exposes the person service to the world. The person service can be used to generate friendly messages for the given name. The fragment of the person service WSDL file should look as the following snippet:
<wsdl:message name="GetPersonRequest"> <wsdl:part name="payload" element="typens:GetPerson"/> </wsdl:message> <wsdl:message name="GetPersonResponse"> <wsdl:part name="payload" element="typens:GetPersonResponse"/> </wsdl:message> <wsdl:message name="UnknownPersonFault"> <wsdl:part name="payload" element="typens:UnknownPersonFault"/> </wsdl:message> <wsdl:portType name="Person"> <wsdl:operation name="GetPerson"> <wsdl:input message="tns:GetPersonRequest"/> <wsdl:output message="tns:GetPersonResponse"/> <wsdl:fault name="UnknownPerson" message="tns:UnknownPersonFault"/> </wsdl:operation> </wsdl:portType> <wsdl:service name="PersonService"> <wsdl:port binding="tns:PersonSOAPBinding" name="soap"> <soap:address location="http://localhost:8080/cxf/PersonService" /> </wsdl:port> </wsdl:service>
As you can see, a WSDL contract, even for the tiniest service, can be pretty long.
We started by generating the stub of the CXF project from the Maven archetype. The template of the project from which the module is built contains a sample WSDL file with a web service contract. What is important to us is that the generated project comes with the Maven CXF plugin configuration and basic Spring context bootstraping CXF endpoint.
Now we can generate classes from the WSDL file provided by us. The CXF Maven plugin will create the stub implementation of the service for us. Execute the following command to create Java classes from the WSDL contract, compile the source, and create a deployable ServiceMix module:
mvn install
If you deploy a JAR created by the preceding command to ServiceMix (cxf-code-first-example /target/cxf-code-first-example-1.0-SNAPSHOT.jar
), the person service will be exposed under the http://localhost:8080/cxf/PersonService
URL.
You are probably wondering why you should consider using contract-first web services in favor of the code-first approach, and how to deal with WSDL maintenance. The following tips may be useful for you, as they throw some light on these issues.
You may be wondering why you should bother with the contract-first approach to web service development instead of using a code-first approach, in which we just need to annotate the implementation of the service. While this approach may be tempting, the contract-first web service development is perceived as safer from the contract point of view. Web services are usually exposed to be consumed by some third-party clients. As a service exposer, you should be always sure that the exposed contract looks exactly as you want it to be. In code-first approach, the contract file is generated, so you basically cannot guarantee that the WSDL file imported by the clients defines your public API exactly as you expected.
Creating a WSDL contract from scratch is almost impossible as it is a very verbose XML document with a very complex schema. If you plan to stick to the contract-first approach, try the WSDL editor for the Eclipse IDE (http://wiki.eclipse.org/index.php/Introduction_to_the_WSDL_Editor). We strongly discourage you from creating or modifying the WSDL file without a proper tool unless you are web service expert.