Wednesday, April 11, 2012

Web Service: Apache CXF Web Service Tutorial

Overview:
This article looks at how to create a Web Service by using Apache CXF. Apache CXF treats Spring as its first class citizen and enables exposing of existing Spring beans as Web Services. You can find the sample code here.

Project Structure: Following is the project structure I have used (Maven WAR project).


Step 1: Maven Dependencies (pom.xml)
 <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>org.fazlan</groupId>
<artifactId>org.fazlan.employee.cxfspring.service</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>org.fazlan.employee.cxfspring.service</name>
<url>http://maven.apache.org</url>
<build>
<finalName>CXFEmployeeService</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- Spring framework -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
</dependencies>
<properties>
<org.springframework.version>3.1.1.RELEASE</org.springframework.version>
<cxf.version>2.2.3</cxf.version>
</properties>
</project>

Step 2: Creating POJO Classes and Service Implementation
Employee.java
 @XmlType(name = "Employee", namespace = "org.fazlan.employee.cxfspring.service.beans")
public class Employee implements Serializable {
private Long id;
private String firstName;
private String lastName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}

Service Interface and Implementation

IEmployeeService.java
 import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@WebService(targetNamespace = "org.fazlan.employee.cxfspring.service.services")
public interface IEmployeeService {
@WebMethod(operationName = "AddEmployee")
@WebResult(name = "id")
Long add(@WebParam(name = "employee") Employee employee);
@WebMethod(operationName = "UpdateEmployee")
void update(@WebParam(name = "employee") Employee employee);
@WebMethod(operationName = "GetEmployee")
@WebResult(name = "employee")
Employee get(@WebParam(name = "id") Long id);
@WebMethod(operationName = "GetAllEmployees")
@WebResult(name = "employee")
Employee[] getAll();
}

EmployeeService.java
 import javax.jws.WebService;
import java.util.HashMap;
import java.util.Map;
@WebService(
endpointInterface = "org.fazlan.employee.cxfspring.service.services.IEmployeeService",
targetNamespace = "org.fazlan.employee.cxfspring.service.services",
serviceName = "EmployeeService")
public class EmployeeService implements IEmployeeService {
private static final Map<Long,Employee> EMPLOYEE_MAP = new HashMap<Long,Employee>();
private static long index = 0;
public Long add(Employee employee) {
employee.setId(++index);
update(employee);
return index;
}
public void update(Employee employee) {
EMPLOYEE_MAP.put(employee.getId(), employee);
}
public Employee get(Long id) {
return EMPLOYEE_MAP.get(id);
}
public Employee[] getAll() {
return EMPLOYEE_MAP.values().toArray(new Employee[EMPLOYEE_MAP.size()]);
}
}

Step 3: Exposing the service bean as a Web Service
app-context.xml
 <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="employeeService"
implementor="org.fazlan.employee.cxfspring.service.services.EmployeeService"
address="/employeeservice"/>
</beans>

Step 4: Updating the web.xml to register CXFServlet

 <!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>CXF Web Service Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/app-context.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>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

Step 5: Building the project
mvn clean install

Step 6: Deploying the Service
Now you can deploy this service on to any container. Here we'll deploy this on Tomcat server.
After successfully deploying the service, you can access the service via
http://localhost:8080/CXFEmployeeService/employeeservice?wsdl

Step 7: Invoking the Services via SOAP UI.

You can easily test the services using SOAP UI. Use the service URL(http://localhost:8080/CXFEmployeeService/employeeservice?wsdl) and create a project on SOAP UI.


Summary:
Apache CXF is a Web Service Engine that enables us to deploy Spring beans as Web Services on any Web Container.

4 comments:

  1. hi fazlan,
    thx for ur blog....but being a novice i donno wat are d required things for maven project...i have eclipse 3.4 and java 1.6 wid me...so wat do i need to do the above steps??

    ReplyDelete
    Replies
    1. Hi Abhishek,
      Firstly, sorry for the delay in getting back to you.

      1.You need to download the Maven distribution (e.i: *.zip)
      2.Unpack the distribution on your machine(e.i: /home/foo/apache-maven-3.x.x).
      3.You need to set the M2_HOME environment variable to run maven goals. Also, make sure you have JAVA_HOME set to your 1.6.x JDK
      e.i On Linux/MAC,
      export M2_HOME="/home/foo/apache-maven-3.x.x"
      export PATH=$PATH:$M2_HOME/bin
      NOTE: If you include them to .bash_rc, make sure to run 'source .bash_rc'

      Similarly, do the corresponding on Windows

      4. Verify maven by running the following command,
      mvn --version

      5. If you have download the source code of this post, you can unzip it.
      e.i: /home/foo/org.fazlan.employee.cxfspring.service

      6. Browse to /home/foo/org.fazlan.employee.cxfspring.service folder and execute the following

      $ mvn install
      $ mvn eclipse:eclipse

      The first command will download all the dependencies, and the second would create the classpath entries for the Eclipse project.

      8. Then you can browse to the newly created Eclipse project and open as an existing project.

      I hope that helps.
      Cheers,
      Fazlan

      Delete