Friday, April 13, 2012

Web Service: Apache CXF Integration with Hibernate Tutorial

Overview:
This tutorial will look at how you can integrate Hibernate with Apache CXF. This article is an extension of both Web Service: Apache CXF Web Service Tutorial and Spring: Spring ROM Support for Hibernate with MySQL articles.

You can find the sample source code here.

Prerequisite:
MySQL
Maven
JDK >= 1.5.x

Project Structure: This is how the project structure looks like (Click on the image to view)


Step 1: Creating the Database Table
 CREATE TABLE PERSON (
   PERSON_ID BIGINT AUTO_INCREMENT,
   FIRST_NAME VARCHAR(30),
   LAST_NAME VARCHAR(30),
   PRIMARY KEY (PERSON_ID)
)

Step 2: 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>CXFEmployeeHBMService</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>  
     <!-- JUnit testing framework -->  
     <dependency>  
       <groupId>junit</groupId>  
       <artifactId>junit</artifactId>  
       <version>4.8.1</version>  
     </dependency>  
     <!-- CXF dependencies -->  
     <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>  
     <!-- Spring framework -->  
     <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-core</artifactId>  
       <version>${org.springframework.version}</version>  
     </dependency>  
     <!--<dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-context</artifactId>  
       <version>${org.springframework.version}</version>  
     </dependency>-->  
     <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-aop</artifactId>  
       <version>${org.springframework.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-beans</artifactId>  
       <version>${org.springframework.version}</version>  
     </dependency>  
     <!--<dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-context-support</artifactId>  
       <version>${org.springframework.version}</version>  
     </dependency>-->  
     <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-tx</artifactId>  
       <version>${org.springframework.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-jdbc</artifactId>  
       <version>${org.springframework.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.springframework</groupId>  
       <artifactId>spring-orm</artifactId>  
       <version>${org.springframework.version}</version>  
     </dependency>  
     <!-- MySQL database driver -->  
     <dependency>  
       <groupId>mysql</groupId>  
       <artifactId>mysql-connector-java</artifactId>  
       <version>5.1.9</version>  
     </dependency>  
     <!-- Hibernate framework -->  
     <dependency>  
       <groupId>org.hibernate</groupId>  
       <artifactId>hibernate-core</artifactId>  
       <version>${org.hibernate.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.hibernate</groupId>  
       <artifactId>hibernate-entitymanager</artifactId>  
       <version>${org.hibernate.version}</version>  
     </dependency>  
     <!-- Hibernate library dependecy start -->  
     <!--<dependency>  
       <groupId>dom4j</groupId>  
       <artifactId>dom4j</artifactId>  
       <version>1.6.1</version>  
     </dependency>  
     <dependency>  
       <groupId>commons-logging</groupId>  
       <artifactId>commons-logging</artifactId>  
       <version>1.1.1</version>  
     </dependency>  
     <dependency>  
       <groupId>commons-collections</groupId>  
       <artifactId>commons-collections</artifactId>  
       <version>3.2.1</version>  
     </dependency>  
     <dependency>  
       <groupId>antlr</groupId>  
       <artifactId>antlr</artifactId>  
       <version>2.7.7</version>  
     </dependency>-->  
     <!-- Hibernate library dependency end -->  
     <!--AspectJ dependency-->  
     <dependency>  
       <groupId>org.aspectj</groupId>  
       <artifactId>aspectjrt</artifactId>  
       <version>${org.aspectj.version}</version>  
     </dependency>  
     <dependency>  
       <groupId>org.aspectj</groupId>  
       <artifactId>aspectjweaver</artifactId>  
       <version>${org.aspectj.version}</version>  
     </dependency>  
   </dependencies>  
   <properties>  
     <org.apache.axis2.version>1.6.1</org.apache.axis2.version>  
     <org.aspectj.version>1.6.11</org.aspectj.version>  
     <cxf.version>2.2.3</cxf.version>  
     <org.hibernate.version>3.6.0.Final</org.hibernate.version>  
     <org.springframework.version>3.1.1.RELEASE</org.springframework.version>  
   </properties>  
 </project>  

Step 3: Creating POJO Classes and Service Implementation
Employee.java
 package org.fazlan.employee.cxf.hibernate.service.beans;  
 import javax.xml.bind.annotation.XmlRootElement;  
 import javax.xml.bind.annotation.XmlType;  
 import java.io.Serializable;  
 @XmlType(  
     name = "EmployeeType",  
     namespace = "org.fazlan.employee.cxf.hibernate.service.beans",  
     propOrder = {"id", "firstName", "lastName"})  
 @XmlRootElement(name = "Employee")  
 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;  
   }  
 }  

EmployeeCollection.java - This is used to hold a collection object of Employee.java
 package org.fazlan.employee.cxf.hibernate.service.beans;  
 import javax.xml.bind.annotation.XmlElement;  
 import javax.xml.bind.annotation.XmlElementWrapper;  
 import javax.xml.bind.annotation.XmlRootElement;  
 import javax.xml.bind.annotation.XmlType;  
 import java.util.List;  
 @XmlType(  
     name = "EmployeeCollectionType",  
     namespace = "org.fazlan.employee.cxf.hibernate.service.beans")  
 @XmlRootElement(name = "EmployeeCollection")  
 public class EmployeeCollection {  
   private List<Employee> employees;  
   public EmployeeCollection() {  
   }  
   public EmployeeCollection(List<Employee> employees) {  
     this.employees = employees;  
   }  
   @XmlElementWrapper(name = "employees")  
   @XmlElement(name = "employee")  
   public List<Employee> getEmployees() {  
     return employees;  
   }  
 }  

IDao.java - DAO Interface
 package org.fazlan.employee.cxf.hibernate.service.dao;  
 import java.util.List;  
 public interface IDao<T> {  
   Long save(T t);  
   void update(T t);  
   void delete(T t);  
   T get(Long id);  
   List<T> getAll();  
 }  

EmployeeDao.java - The implementation of employee DAO using HibernateDao support.
 package org.fazlan.employee.cxf.hibernate.service.dao;  
 import org.fazlan.employee.cxf.hibernate.service.beans.Employee;  
 import org.springframework.orm.hibernate3.support.HibernateDaoSupport;  
 import java.util.List;  
 public class EmployeeDao extends HibernateDaoSupport implements IDao<Employee>{  
   public Long save(Employee employee) {  
     return (Long) getHibernateTemplate().save(employee);  
   }  
   public void update(Employee employee) {  
     getHibernateTemplate().update(employee);  
   }  
   public void delete(Employee employee) {  
     getHibernateTemplate().delete(employee);  
   }  
   public Employee get(Long id) {  
     return getHibernateTemplate().get(Employee.class, id);  
   }  
   public List<Employee> getAll() {  
     return getHibernateTemplate().find("from Employee");  
   }  
 }  

IEmployeeService.java - Service Interface.
 package org.fazlan.employee.cxf.hibernate.service.services;  
 import org.fazlan.employee.cxf.hibernate.service.beans.Employee;  
 import org.fazlan.employee.cxf.hibernate.service.beans.EmployeeCollection;  
 import javax.jws.WebMethod;  
 import javax.jws.WebParam;  
 import javax.jws.WebResult;  
 import javax.jws.WebService;  
 @WebService(targetNamespace = "org.fazlan.employee.cxf.hibernate.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")  
   EmployeeCollection getAll();  
 }  

EmployeeService.java - Implementation of the service
 package org.fazlan.employee.cxf.hibernate.service.services;  
 import org.fazlan.employee.cxf.hibernate.service.beans.Employee;  
 import org.fazlan.employee.cxf.hibernate.service.beans.EmployeeCollection;  
 import org.fazlan.employee.cxf.hibernate.service.dao.IDao;  
 import javax.jws.WebMethod;  
 import javax.jws.WebService;  
 @WebService(  
     endpointInterface = "org.fazlan.employee.cxf.hibernate.service.services.IEmployeeService",  
     targetNamespace = "org.fazlan.employee.cxf.hibernate.service.services",  
     serviceName = "EmployeeService")  
 public class EmployeeService implements IEmployeeService {  
   private IDao<Employee> employeeDao;  
   public Long add(Employee employee) {  
     return employeeDao.save(employee);  
   }  
   public void update(Employee employee) {  
     employeeDao.update(employee);  
   }  
   public Employee get(Long id) {  
     return employeeDao.get(id);  
   }  
   public EmployeeCollection getAll() {  
     return new EmployeeCollection(employeeDao.getAll());  
   }  
   @WebMethod(exclude = true)  
   public void setEmployeeDao(IDao<Employee> employeeDao) {  
     this.employeeDao = employeeDao;  
   }  
 }  

Step 4: Mapping the POJO classes using Hibernate (hibernate/hbm/Employee.hbm.xml)
 <?xml version="1.0"?>  
 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
 <hibernate-mapping>  
   <class name="org.fazlan.employee.cxf.hibernate.service.beans.Employee" table="PERSON">  
     <id name="id" column="PERSON_ID" type="long" access="field">  
       <generator class="increment" />  
     </id>  
     <property name="firstName" type="string">  
       <column name="FIRST_NAME" />  
     </property>  
     <property name="lastName" type="string">  
       <column name="LAST_NAME" />  
     </property>  
   </class>  
 </hibernate-mapping>  

Step 5: Defining the database properties (hibernate/properties/db.properties)
 jdbc.driverClassName=com.mysql.jdbc.Driver  
 jdbc.url=jdbc:mysql://localhost:3306/springhibernate  
 jdbc.username=root  
 jdbc.password=root123  

Step 6: Spring Configuration (spring/spring-emp-*.xml) 

spring/spring-emp-dao.xml - Contains the Spring configuration for the DataSource, SessionFactory, EmployeeDao and Transaction Management.
 <beans xmlns="http://www.springframework.org/schema/beans"  
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
     xmlns:aop="http://www.springframework.org/schema/aop"  
     xmlns:tx="http://www.springframework.org/schema/tx"  
     xsi:schemaLocation="  
 http://www.springframework.org/schema/beans  
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
 http://www.springframework.org/schema/tx  
 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
 http://www.springframework.org/schema/aop  
 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">  
   <bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">  
     <property name="location" value="classpath:hibernate/properties/db.properties"/>  
   </bean>  
   <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
     <property name="url" value="${jdbc.url}"/>  
     <property name="driverClassName" value="${jdbc.driverClassName}"/>  
     <property name="username" value="${jdbc.username}"/>  
     <property name="password" value="${jdbc.password}"/>  
   </bean>  
   <!-- Hibernate session factory -->  
   <bean id="sessionFactory"  
      class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
     <property name="dataSource">  
       <ref bean="dataSource"/>  
     </property>  
     <property name="hibernateProperties">  
       <props>  
         <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
         <prop key="hibernate.show_sql">true</prop>  
       </props>  
     </property>  
     <property name="mappingLocations">  
         <value>classpath:hibernate/hbm/Employee.hbm.xml</value>  
     </property>  
   </bean>  
   <bean id="employeeDao" class="org.fazlan.employee.cxf.hibernate.service.dao.EmployeeDao" >  
       <property name="sessionFactory" ref="sessionFactory" />  
   </bean>  
   <!-- transaction management -->  
   <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
     <property name="sessionFactory" ref="sessionFactory"/>  
   </bean>  
   <tx:advice id="txAdvice" transaction-manager="txManager">  
     <tx:attributes>  
       <tx:method name="get" read-only="true"/>  
       <tx:method name="*"/>  
     </tx:attributes>  
   </tx:advice>  
   <aop:config>  
     <aop:pointcut id="serviceOperationsPC"  
            expression="execution(* org.fazlan.employee.cxf.hibernate.service.services.IEmployeeService.*(..))"/>  
     <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperationsPC"/>  
   </aop:config>  
 </beans>  

spring/spring-emp-app-context.xml - Contains the Spring configuration for the Service and it's endpoint.
 <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-3.0.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"/>  
   <import resource="classpath:spring/spring-emp-dao.xml"/>  
   <jaxws:endpoint id="employeeServiceEPR" implementor="#employeeService" address="/employeeservice"/>  
   <bean id="employeeService" class="org.fazlan.employee.cxf.hibernate.service.services.EmployeeService">  
     <property name="employeeDao" ref="employeeDao"/>  
   </bean>  
 </beans>  

Step 7: Updating the web.xml to Register the CXF Servlet.
 <!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/spring-emp-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 8: Building the Project
    mvn clean install
Step 9: Deploying the Service
Now you can deploy this service on to any container. Here we'll deploy this on Tomcat server.

Step 10: Testing the Web Service
After successfully deploying the service, you can access the service via http://localhost:8080/CXFEmployeeHBMService/employeeservice?wsdl

Use this URL to create a SOAP Project as follows.

 
Summary:
With Apache CXF, you can easily integrate Hibernate with a matter of minutes. This is one of the advantages Apache CXF has over Apache Axis2 when it comes to integrating Hibernate with Spring.
You can find the sample source code here.

7 comments:

  1. Web Designing

    Why spend more if you can get the same quality, productivity and performance from an offshore partner.

    ReplyDelete
  2. Hi,

    You could either use WS Testing tool such as SoapUI or curl to send requests to add an employee.

    Please refer to the Step7 and after in this[1] post

    [1] http://fazlansabar.blogspot.com.au/2012/04/part-1-restful-ws-with-apache-cxf-xml.html

    ReplyDelete
  3. Good one!!! It is working for me.
    Thanks,
    Shereef

    ReplyDelete
  4. You may also be interested in Spring Data. It makes life easier when it comes to data access layer.

    ReplyDelete
  5. nice article........please upload some webservice security also.

    ReplyDelete
  6. Hi, download the code, but it did not work, antencion in pom.xml, Hibernate dependencies are inactive.
    Greetings, great tutorial

    ReplyDelete