In this short tutorial let us discuss how to develop a contract first webservice using Apache CXF.
Let us consider the scenario where the webservice accepts employee id and the year as input and returns the employee name and the number of hours the employee has worked in the year[which is as input] . So we come up with the empworkhours.wsdl below.
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="EmpWorkHours" targetNamespace="http://ts.com/empwork"
xmlns:tns="http://ts.com/empwork"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:emp="http://ts.com/empwork/types"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema targetNamespace="http://ts.com/empwork/types"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://ts.com/empwork/types"
elementFormDefault="qualified">
<xsd:element name="EmpWorkHoursRequest" type="emp:EmpWorkHoursRequestType"/>
<xsd:element name="EmpWorkHoursResponse" type="emp:EmpWorkHoursResultType"/>
<xsd:complexType name="EmpWorkHoursRequestType">
<xsd:sequence>
<xsd:element name="empid" type="xsd:string"/>
<xsd:element name="year" type="xsd:integer"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="EmpWorkHoursResultType">
<xsd:sequence>
<xsd:element name="empid" type="xsd:string"/>
<xsd:element name="year" type="xsd:integer"/>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="workhours" type="xsd:integer"/>
</xsd:sequence>
</xsd:complexType>
</schema>
</wsdl:types>
<wsdl:message name="request">
<wsdl:part element="emp:EmpWorkHoursRequest" name="in"/>
</wsdl:message>
<wsdl:message name="response">
<wsdl:part element="emp:EmpWorkHoursResponse" name="out"/>
</wsdl:message>
<wsdl:portType name="EmpWorkHours">
<wsdl:operation name="getWorkHours">
<wsdl:input message="tns:request" name="workHoursRequest"/>
<wsdl:output message="tns:response" name="workHoursResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="EmpWorkHours_SOAPBinding" type="tns:EmpWorkHours">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getWorkHours">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="workHoursRequest">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="workHoursResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SOAPService">
<wsdl:port binding="tns:EmpWorkHours_SOAPBinding" name="EmpWorkHoursWS">
<soap:address location="http://localhost:8090/cxfcontractfirstwebapp/services/EmpWorkHoursWS"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Now let us create a Maven web application with the pom.xml given below.
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.thea</groupId>
<artifactId>cxfcontractfirstwebapp</artifactId>
<packaging>war</packaging>
<version>0.1</version>
<name>cxfcontractfirstwebapp Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.1.2</version>
</dependency>
<!-- Jetty is needed if you're are not using the CXFServlet -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>2.1.2</version>
</dependency>
</dependencies>
<build>
<finalName>cxfcontractfirstwebapp</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<!-- wsdl generator plugin-->
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>./src/main/java</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>E:\javacode\nbcodepart2\cxfcontractfirstwebapp\src\main\wsdl\empworkhours.wsdl</wsdl>
<extraargs>
<extraarg>-server</extraarg>
<extraarg>-impl</extraarg>
</extraargs>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Now let us generate the server and implementation Java files from the wsdl using the command mvn generate-sources.
Now edit EmpWorkHoursImpl.java to remove name in the WebService annotation. Also include the desired logic to fetch the hours worked by the employee in the given year from a datasource. After modification the file should look as below.
package com.ts.empwork;
import java.math.BigInteger;
import java.util.logging.Logger;
@javax.jws.WebService(serviceName = "SOAPService",
portName = "EmpWorkHoursWS",
targetNamespace = "http://ts.com/empwork",
wsdlLocation = "file:/E:/javacode/nbcodepart2/cxfcontractfirstwebapp/src/main/wsdl/empworkhours.wsdl",
endpointInterface = "com.ts.empwork.EmpWorkHours")
public class EmpWorkHoursImpl implements EmpWorkHours {
private static final Logger LOG = Logger.getLogger(EmpWorkHoursImpl.class.getName());
/* (non-Javadoc)
* @see com.ts.empwork.EmpWorkHours#getWorkHours(com.ts.empwork.types.EmpWorkHoursRequestType in )*
*/
public com.ts.empwork.types.EmpWorkHoursResultType getWorkHours(com.ts.empwork.types.EmpWorkHoursRequestType in) {
LOG.info("Executing operation getWorkHours");
System.out.println(in);
try {
com.ts.empwork.types.EmpWorkHoursResultType _return = new com.ts.empwork.types.EmpWorkHoursResultType();
//The below data will be fetched from a datasource. To keep the example simple
//we set hard coded values here
_return.setEmpid(in.getEmpid());
_return.setYear(in.getYear());
_return.setName("Karthik");
_return.setWorkhours(new BigInteger("1800"));
return _return;
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
}
So far we have generated the server and implementation files. Now let us generate the client Java files [which are required to consume the webservice] into yet another simple Java project by introducing <extraarg>-client</extraarg> in the pom.xml. [You may comment server and impl extraargs as they are not needed in a client].
Now as we have generated both the client and server side Java files form wsdl, comment the wsdl generator plugin in the pom.xml of both the server and client projects. [It is not required until we need to regenerate files for any change in wsdl]. This is as a precaution so that we do not accidentally override the implementation files.
Now edit the web.xml of the Maven web application. The content of the final web.xml is as below.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>cxfcontractfirstwebapp</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:cxf.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
Then let us create a file called cxf.xml under resources folder of Maven structure [that is under projectroot/src/main/resources]. The content of cxf.xml is as below.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint id="EmpWorkHours"
implementor="com.ts.empwork.EmpWorkHoursImpl"
address="/EmpWorkHoursWS">
<jaxws:properties>
</jaxws:properties>
</jaxws:endpoint>
</beans>
Package the web application using Maven and deploy it on the desired server like Tomcat or GlassFish.
For the given example you may verify the successful installation by checking that the service is listed as an available service when you type http://localhost:8090/cxfcontractfirstwebapp/services in the browser. [Note: Please change the port number and the server as required]
Now let us concentrate on the client side which will consume the deployed web service. Find EmpWorkHours_EmpWorkHoursWS_Client.java [a generated file and modify the content as below].
package com.ts.empwork;
import java.io.File;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
public final class EmpWorkHours_EmpWorkHoursWS_Client {
private static final QName SERVICE_NAME = new QName("http://ts.com/empwork", "SOAPService");
private EmpWorkHours_EmpWorkHoursWS_Client() {
}
public static void main(String args[]) throws Exception {
URL wsdlURL = SOAPService.WSDL_LOCATION;
if (args.length > 0) {
File wsdlFile = new File(args[0]);
try {
if (wsdlFile.exists()) {
wsdlURL = wsdlFile.toURI().toURL();
} else {
wsdlURL = new URL(args[0]);
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
SOAPService ss = new SOAPService(wsdlURL, SERVICE_NAME);
EmpWorkHours port = ss.getEmpWorkHoursWS();
{
System.out.println("Invoking getWorkHours...");
com.ts.empwork.types.EmpWorkHoursRequestType _getWorkHours_in = new com.ts.empwork.types.EmpWorkHoursRequestType();
_getWorkHours_in.setEmpid("1001");
_getWorkHours_in.setYear(new BigInteger("2008"));
com.ts.empwork.types.EmpWorkHoursResultType _getWorkHours__return = port.getWorkHours(_getWorkHours_in);
System.out.println("getWorkHours.result=" + _getWorkHours__return.getWorkhours());
}
System.exit(0);
}
}
Then run it to verify that it prints the work hours as 1800 [which was set in the server]. I used Netbeans to run and the output is as in the screenshot. [I had the client Java application that consumes the web service built by Maven ]

For beginners in web services, there are two approaches to develop a
webservice. Approach 1 is contract first - we start with a wsdl file
and Approach 2 - code first - we start with Java class(es) [assuming
the programming language is Java] and expose them as webservice [for
which XFire and CXF are famous for].

Posted by kakach on October 07, 2008 at 07:57 AM CDT #
Posted by karthikeyan c on October 09, 2008 at 11:45 PM CDT #