Showing posts with label Hibernate. Show all posts
Showing posts with label Hibernate. Show all posts

Saturday, April 14, 2012

Apache Axis2 Tutorial: Integrating with Spring 3 and Hibernate 3

Overview:
This article looks at how you can integrate Spring and Hibernate with Apache Axis2. Axis2 also enables making use of Spring and Hibernate mush similar to Apache CXF( Tutorial on Apache CXF with Spring and Hibernate). This is a simple but a comprehensive tutorial. We'll be testing the service's REST endpoint using CURL.

The sample code for this project can be found here.

Prerequisite:
JDK >= 1.5.x
Maven >= 2.2.x
MySQL

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


Resource structure:


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.axis2.orm.spring.service</artifactId>
<packaging>aar</packaging>
<version>1.0-SNAPSHOT</version>
<name>org.fazlan.employee.axis2.orm.spring.service</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
  <plugin>
    <groupId>org.apache.axis2</groupId>
    <artifactId>axis2-aar-maven-plugin</artifactId>
    <version>1.6.1</version>
    <!--<version>${orbit.version.axis2}</version>-->
    <extensions>true</extensions>
    <configuration>
      <aarName>org.fazlan.employee.axis2.orm.spring.service</aarName>
    </configuration>
  </plugin>
</plugins>
</build>
<dependencies>
<!-- Axis2 -->
<dependency>
  <groupId>org.apache.axis2</groupId>
  <artifactId>axis2</artifactId>
  <version>${org.apache.axis2.version}</version>
</dependency>
<dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2-spring</artifactId>
      <version>${org.apache.axis2.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>
 <!-- JUnit testing framework -->
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.8.1</version>
</dependency>
</dependencies>
<properties>
<org.apache.axis2.version>1.6.1</org.apache.axis2.version>
<org.aspectj.version>1.6.11</org.aspectj.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: Defining the POJO, DAO and Service Implementation
- Employee.java

 package org.fazlan.employee.axis2.orm.spring.service.beans;
import java.io.Serializable;
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;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Employee)) return false;
Employee employee = (Employee) o;
return !(firstName != null ? !firstName.equals(employee.firstName) : employee.firstName != null) && !(id != null ? !id.equals(employee.id) : employee.id != null) && !(lastName != null ? !lastName.equals(employee.lastName) : employee.lastName != null);
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
return result;
}
}

- DAO Interface and Implementation

IDao.java
 package org.fazlan.employee.axis2.orm.spring.service.dao;
import java.util.List;
public interface IDao<T> {
Long save(T t);
boolean update(T t);
boolean delete(T t);
T get(Long id);
List<T> getAll();
}

EmployeeDao.java

 package org.fazlan.employee.axis2.orm.spring.service.dao;
import org.fazlan.employee.axis2.orm.spring.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 boolean update(Employee employee) {
getHibernateTemplate().update(employee);
return true;
}
public boolean delete(Employee employee) {
getHibernateTemplate().delete(employee);
return true;
}
public Employee get(Long id) {
return getHibernateTemplate().get(Employee.class, id); //To change body of implemented methods use File | Settings | File Templates.
}
public List<Employee> getAll() {
return getHibernateTemplate().find("from Employee");
}
}

- Service Interface and Implementation

IService.java
 package org.fazlan.employee.axis2.orm.spring.service.services;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: fazlan
* Date: 3/9/12
* Time: 4:36 PM
* To change this template use File | Settings | File Templates.
*/
public interface IService<T> {
Long add(T t);
boolean update(T t);
boolean delete(T t);
T get(Long id);
List<T> getAll();
}

EmployeeService.java

 package org.fazlan.employee.axis2.orm.spring.service.services;
import org.fazlan.employee.axis2.orm.spring.service.beans.Employee;
import org.fazlan.employee.axis2.orm.spring.service.dao.IDao;
import java.util.List;
public class EmployeeService implements IService<Employee> {
private IDao<Employee> employeeDao;
public Long add(Employee employee) {
return employeeDao.save(employee);
}
public boolean update(Employee employee) {
employeeDao.update(employee);
return true;
}
public boolean delete(Employee employee) {
employeeDao.delete(employee);
return true;
}
public Employee get(Long id) {
return employeeDao.get(id);
}
public List<Employee> getAll() {
return employeeDao.getAll();
}
public void setEmployeeDao(IDao<Employee> employeeDao) {
this.employeeDao = employeeDao;
}
}

Step 4: Defining the Service class to load the Spring Context in Axis2 for this *.aar
EmployeeSpringInit.java

 package org.fazlan.employee.axis2.orm.spring.service.services;
import org.apache.axis2.engine.ServiceLifeCycle;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.AxisService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class EmployeeSpringInit implements ServiceLifeCycle {
private static Log logger = LogFactory
.getLog(EmployeeSpringInit.class);
/**
* this will be called during the deployement time of the service. irrespective
* of the service scope this method will be called
*/
public void startUp(ConfigurationContext ignore, AxisService service) {
ClassLoader classLoader = service.getClassLoader();
ClassPathXmlApplicationContext appCtx = new
  ClassPathXmlApplicationContext(new String[] {"classpath:spring/spring-app-context.xml"}, false);
appCtx.setClassLoader(classLoader);
appCtx.refresh();
if (logger.isDebugEnabled()) {
  logger.debug("\n\nstartUp() set spring classloader via axisService.getClassLoader() ... ");
}
}
/**
* this will be called during the deployement time of the service. irrespective
* of the service scope this method will be called
*/
public void shutDown(ConfigurationContext ignore, AxisService service) {
}
}

Step 5: MySQL Database Connection Properties (hibernate/hbm/db.properties)
 jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springhibernate
jdbc.username=root
jdbc.password=root123

Step 6: Hibernate Mapping of Employee POJO (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.axis2.orm.spring.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 7: Defining the Spring Configuration for the Application (spring/spring-app-context.xml)

This is the Spring bean definition file in our application containing all the beans required to run the application.

The following is very important, this class and the spring bean needed to wire it could be used as an alternative to getting the ApplicationContext from the ServletContext.

 <bean id="applicationContext"
class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />

Putting all together,
 <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation= "http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="applicationContext"
class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder" />
<bean class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
<property name="location" value="classpath:hibernate/properties/db.properties"/>
</bean>
<!-- MySQL datasource -->
<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.axis2.orm.spring.service.dao.EmployeeDao">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="employeeSpringService" class="org.fazlan.employee.axis2.orm.spring.service.services.EmployeeService">
<property name="employeeDao" ref="employeeDao"/>
</bean>
</beans>

Step 8: Defining your Axis2 Service Configuration (META-INF/services.xml)

EmployeeSpringInit Service: Loading the Spring context
 <service name="EmployeeSpringInit" class="org.fazlan.employee.axis2.orm.spring.service.services.EmployeeSpringInit">
<description>
  This web service initializes Spring.
</description>
<parameter name="ServiceClass">org.fazlan.employee.axis2.orm.spring.service.services.EmployeeSpringInit
</parameter>
<parameter name="ServiceTCCL">composite</parameter>
<parameter name="load-on-startup">true</parameter>
<!--<operation name="springInit">
 <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
</operation>-->
</service>
Here, we use this service to load the Spring context at the startup of the application.

EmployeeService - The actual service definition.
 <service name="EmployeeService">
<description>
  Weather Spring POJO Axis2 AAR deployment
</description>
<parameter name="ServiceClass">org.fazlan.employee.axis2.orm.spring.service.services.EmployeeService</parameter>
<parameter name="ServiceObjectSupplier">
  org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier
</parameter>
<excludeOperations>
  <operation>setEmployeeDao</operation>
</excludeOperations>
<parameter name="SpringBeanName">employeeSpringService</parameter>
<parameter name="SpringContextLocation">spring/spring-app-context.xml</parameter>
<messageReceivers>
  <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
           class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
  <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
           class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
</service>

By default, the Axis2 Engine will look for <your.aar>/applicationContext.xml to load the Spring bean configurations.

You can change this by either defining the following property.
 <parameter name="SpringContextLocation">spring/spring-app-context.xml</parameter>

This tells the Axis2 Engine where to locate the Spring application context file for this service. This is very useful when you have multiple Spring application services in the same Axis3 Engine.
Or,
You can place the Spring configuration file alongside the service.xml as in the following format. Axis2 Engine will implicitly detect this.

META-INF/<service-name>-application-context.xml

Putting all together,
 <serviceGroup>
<service name="EmployeeSpringInit" class="org.fazlan.employee.axis2.orm.spring.service.services.EmployeeSpringInit">
<description>
  This web service initializes Spring.
</description>
<parameter name="ServiceClass">org.fazlan.employee.axis2.orm.spring.service.services.EmployeeSpringInit
</parameter>
<parameter name="ServiceTCCL">composite</parameter>
<parameter name="load-on-startup">true</parameter>
<!--<operation name="springInit">
 <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
</operation>-->
</service>
<service name="EmployeeService">
<description>
  Weather Spring POJO Axis2 AAR deployment
</description>
<parameter name="ServiceClass">org.fazlan.employee.axis2.orm.spring.service.services.EmployeeService</parameter>
<parameter name="ServiceObjectSupplier">
  org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier
</parameter>
<excludeOperations>
  <operation>setEmployeeDao</operation>
</excludeOperations>
<parameter name="SpringBeanName">employeeSpringService</parameter>
<parameter name="SpringContextLocation">spring/spring-app-context.xml</parameter>
<messageReceivers>
  <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
           class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
  <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
           class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
</service>
</serviceGroup>

Step 9: Building the Project
mvn clean install

Step 10: Deploying the Service
Now you can deploy this service on to any container. Here we'll deploy this on Tomcat server.

You need to copy the following *.jars to <TOMCAT_HOME>/axis2/WEB-INF/lib/ directory (e;i: /home/fazlan/apache-tomcat-6.0.32/webapps/axis2/WEB-INF/lib/)in your Axis2 WAR already deployed on Tomcat.

Spring 3.1.1.RELEASE jars
spring-aop-3.1.1.RELEASE.jar
spring-asm-3.1.1.RELEASE.jar
spring-beans-3.1.1.RELEASE.jar
spring-context-3.1.1.RELEASE.jar
spring-context-support-3.1.1.RELEASE.jar
spring-core-3.1.1.RELEASE.jar
spring-expression-3.1.1.RELEASE.jar
spring-jdbc-3.1.1.RELEASE.jar
spring-orm-3.1.1.RELEASE.jar
spring-tx-3.1.1.RELEASE.jar
spring-web-3.1.1.RELEASE.jar

Hibernate3 jars
hibernate-commons-annotations-3.2.0.Final.jar
hibernate-core-3.6.0.Final.jar
hibernate-entitymanager-3.6.0.Final.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar

Hibernate3 dependent jars
dom4j-1.6.1.jar
slf4j-api-1.6.1.jar
commons-collections-3.2.1.jar
javassist-3.12.0.GA.jar

This is due to the fact Axis2 Engine tries to load the classes from the jars from /axis2/WEB-INF/lib/ rather than locally in the *.aar file. Although, I tried with the following property in the services.xml, it didn't start the service.
 <parameter name="EnableChildFirstClassLoading">true</parameter>

Once, all the above *.jars are copied to /axis2/WEB-INF/lib/ on Tomcat. We are good to deploy the service and test.

Step 11: Testing the Service

Option 1: Testing the SOAP EPR with SOAP UI.

You can use SOAP UI and test the service with http://localhost:8080/axis2/services/EmployeeService?wsdl SOAP endpoint

Option 2: Testing REFTful endpoint using CURL

Install CURL
sudo apt-get install curl

Now, after successfully installing CURL, we are ready to test the services.
Issue the following commands on the terminal.

POST a Resource: Adding a new employee resource.
- Adding the new employee record in the add.xml file.
 <ns:add xmlns:ns="http://services.service.spring.orm.axis2.employee.fazlan.org">
  <ns:employee xmlns:ax21="http://beans.service.spring.orm.axis2.employee.fazlan.org/xsd"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax21:Employee">
       <ax21:firstName>My FirstName</ax21:firstName>
       <ax21:id>1</ax21:id>
       <ax21:lastName>My LastName</ax21:lastName>
  </ns:employee>
</ns:add>

 curl -v -H "Accept: application/xml" -H "Content-type: application/xml" -X POST -d @add.xml http://localhost:8080/axis2/services/EmployeeService/add

GET Resources:
- Retrieving all the employee resources.
 curl -v -H "Accept: application/xml" http://localhost:8080/axis2/services/EmployeeService/getAll

- Retrieving a employee resource for a given id(id = 1).
 curl -v -H "Accept: application/xml" http://localhost:8080/axis2/services/EmployeeService/get?id=1


PUT a Resource: Updating an existing employee resource.
- Updating an existing employee record in the update.xml file.
 <ns:update xmlns:ns="http://services.service.spring.orm.axis2.employee.fazlan.org">
  <ns:employee xmlns:ax21="http://beans.service.spring.orm.axis2.employee.fazlan.org/xsd"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax21:Employee">
       <ax21:firstName>Update FirstName</ax21:firstName>
       <ax21:id>1</ax21:id>
       <ax21:lastName>Update LastName</ax21:lastName>
  </ns:employee>
</ns:update>

 curl -v -H "Accept: application/xml" -H "Content-type: application/xml" -X PUT -d @update.xml http://localhost:8080/axis2/services/EmployeeService/update

DELETE a Resource: Deleting an employee for a given id (id=1)
- Deleting an existing employee record in the delete.xml file.
 <ns:delete xmlns:ns="http://services.service.spring.orm.axis2.employee.fazlan.org">
  <ns:employee xmlns:ax21="http://beans.service.spring.orm.axis2.employee.fazlan.org/xsd"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ax21:Employee">
       <ax21:firstName>Update FirstName</ax21:firstName>
       <ax21:id>1</ax21:id>
       <ax21:lastName>Update LastName</ax21:lastName>
  </ns:employee>
</ns:delete>

 curl -i -H "Accept: application/xml" -H "Content-type: application/xml" -X PUT -d @delete.xml http://localhost:8080/axis2/services/EmployeeService/delete

Summary:
This tutorial looked at how we can integrate Spring and Hibernate with Apache Axis2.

The sample code for this project can be found here.

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.

Tuesday, April 10, 2012

Spring: Spring ROM Support for Hibernate with MySQL Part 2

This is an article that extends the previous article Spring: Spring ROM Support for Hibernate with MySQL. I have extended that article by introducing how you can do declarative transaction management for your services. The sample code for this post can be found here.

Everything looks exactly the same as the previous post except for pom.xml and dao.xml Spring configuration file as follows.

In pom.xml I have added some aspectJ dependencies that enables AOP.
  <!--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>

In the dao.xml I have defined the beans for declarative transaction management.
 <!-- 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.spring.hibernate.service.IService.*(..))"/>
   <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperationsPC"/>
 </aop:config>

Summary:
This article looked at how you can do declarative transaction management with Spring.

Sunday, April 1, 2012

Spring: Spring ROM Support for Hibernate with MySQL

Overview:
This article looks at how you can use Spring3 with Hibernate3. This is a simple example that shows how you can integrate Spring with Hibernate. Also, I have used Maven3 to build the project. You can find the code here.

Prerequisite:
MySQL
Maven

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: Creating the POJO Class

public class Person implements Serializable {
private Long id;
private String firstName;
private String lastName;
public Person() {
}
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Long getId() {
return 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;
}
@Override
public String toString() {
return "[" + id + ", " +firstName+ ", " + lastName+ "]";
}
}
Step 3: Mapping the Person POJO with Hibernate.
Create resources/org/fazlan/spring/hibernate/hbm/Person.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.spring.hibernate.pojo.Person" 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 4: Creating the DAO and BO Classes
Implementation of DAO and BO.

DAO Interface:
public interface IDao<T> {
Serializable save(T t);
void update(T t);
void delete(T t);
T get(Serializable id);
}
DAO Implementation:
public class PersonDao extends HibernateDaoSupport implements IDao<Person>{
public Long save(Person person) {
return (Long) getHibernateTemplate().save(person);
}
public void update(Person person) {
getHibernateTemplate().update(person);
}
public void delete(Person person) {
getHibernateTemplate().delete(person);
}
public Person get(Serializable id) {
return (Person) getHibernateTemplate().get(Person.class, id);
}
}
BO Interface:
 public interface IService<T> {
Serializable save(T t);
void update(T t);
void delete(T t);
T get(Serializable id);
}
BO Abstract implementation using generics:
 public abstract class AbstractService<T> implements IService<T> {
private IDao dao;
public Serializable save(T t) {
return dao.save(t);
}
public void update(T t) {
dao.update(t);
}
public void delete(T t) {
dao.delete(t);
}
public T get(Serializable id) {
return (T) dao.get(id);
}
public void setDao(IDao dao) {
this.dao = dao;
}
}
BO implementation for Person:

@Override
public class PersonService extends AbstractService<Person>{
public Long save(Person person) {
return (Long) super.save(person);
}
} 
Step 5: Configuring Database properties.
Create the properties file resources/properties/database.properties
 jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springhibernate
jdbc.username=root
jdbc.password=root123
Step 6: Wiring the DAO and BO using Spring Configuration.
Configuring the datasource and the seessionfactory.
Create file resources/org/fazlan/spring/hibernate/spring/spring-conf-dao.xml
 <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>properties/database.properties</value>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<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="mappingResources">
<list>
<value>org/fazlan/spring/hibernate/hbm/Person.hbm.xml</value>
</list>
</property>
</bean>
</beans>
Wiring the DAO and BA entities.
Create file resources/org/fazlan/spring/hibernate/spring/spring-conf-person.xml
 <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="personDao"
class="org.fazlan.spring.hibernate.dao.PersonDao">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="personService"
class="org.fazlan.spring.hibernate.service.PersonService">
<property name="dao" ref="personDao"/>
</bean>
</beans>
Combining all the configuration into a single file (as a best practice).
Create file resources/org/fazlan/spring/hibernate/spring/spring-conf-application.xml
 <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="spring-conf-dao.xml" />
<import resource="spring-conf-person.xml" />
</beans>
Step 7: Create an application to test the functionality.
 public class Main {
 public static void main(String... args) {
   ApplicationContext context =
       new ClassPathXmlApplicationContext("org/fazlan/spring/hibernate/spring/spring-conf-application.xml");
   IService service = (IService) context.getBean("personService");
   Person p1 = new Person("Fazlan" , "Sabar");
   Serializable id = service.save(p1);
   p1 = (Person) service.get(id);
   p1.setFirstName("Updated FirstName");
   p1.setLastName("Updated LastName");
   service.update(p1);
 }
}
You can find the code here.


Summary:
This article briefed how you can use Spring's ROM support to integrate with Hibernate.

Wednesday, January 25, 2012

Hibernate: Dealing with Optimistic Locking

Overview:
This article looks at ways of you can deal with optimistic locking in Hibernate.

Optimistic Locking:
Technique used to avoid concurrent access to change a persistant entity. For long transactions or invocations that span several database transactions, it is useful to store versioned data to ensure that if the same entity is updated by two conversations, the last to commit changes will be informed and not override the other conversation's work.

There are two ways to achieve this.
  • Version numbers
  • Timestamp
Version numbers
To use version numbers, you need to define a numeric field in the entity class to enable this as follows,
 public class Person {
private int version;
. . .
}
Then, in the Hibernate mapping file you need to designate this field as the versioning field as follows,
 <hibernate-mapping>
<class name="Person" table="PERSON">
<version name="version" column="VERSION_ID" access="field" />
. . .
</class>
</hibernate-mapping>
Hibernate will handle the versioning each time the persistent entity is loaded.

NOTE
: Here, we limit the access to 'field'. The reason being, we don't want this to be exposed using getters/setters because this is ONLY for the purpose of versioning but nothing to do with the application's logic. Since we don't have getters/setters, we need to tell Hibenate to access this using the field.

Timestamp
Here, for the field you use a Date field in the entity class.
 import java.util.Date; 
public class Person {
private Date lastUpdatedTimestamp;
. . .
}
Following is the corresponding Hibernate mapping file,
 <hibernate-mapping>  
<class name="Person" table="PERSON">
<timestamp name="lastUpdatedTimestamp" column="LASTUPDATED_TIMESTAMP" access="field" />
. . .
</class>
</hibernate-mapping>

Hibernate : Identifiers

Overview:
In Hibernate there are various ways of defining identifiers for table mapping. However, the following two are the most commonly and widely used strategies based on the underlying database.
identity

  • supported by DB2, MySQL, MS SQL Server, Sybase and HypersonicSQL.

  • The returned identifier is of type long, short or int.
sequence
  • supported by DB2, PostgreSQL, Oracle.

  • The returned identifier is of type long, short or int.

Hibernate : Component Mapping

Overview:
This article looks at how you can map data in a given table across several POJOs treated as components of another POJO.

Association Diagram
__________
|Person |
----------
|
____|_____
|Address |
----------

The above relationship corresponds into the following Class Diagram, which indicates that a given Person has a single Address associated.
 
----------------
|Person |
|----------------|
|id:long |
|name:String |
|address:Address |
----------------

----------------
|Address |
|----------------|
|line1:String |
|line2:String |
|city:String |
|state:String |
|zipCode:String |
----------------
However, we will store both the above entities in a single table. And the database structure is as follows,
 CREATE TABLE PERSON (
person_id INTEGER NOT NULL,
name VARCHAR(50),
line1 VARCHAR(50),
line2 VARCHAR(50),
city VARCHAR(25),
state VARCHAR(25),
zip-code VARCHAR(25),
);
Lets look at the Hibernate mapping that involves in mapping both the entities into a single table.
 <?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.Person" table="PERSON">
<id name="id" column="person_id">
<generator class="increment" />
</id>
<property name="name"/>
<component name="address" class="org.fazlan.Address">
<proeprty name="line1" />
<proeprty name="line2" />
<proeprty name="city" />
<proeprty name="state" />
<proeprty name="zipCode" column="zip-code"/>
</component>
</class>
</hibernate-mapping>


That's all about it!

Monday, January 23, 2012

Hibernate: Mapping Many-to-Many Associations

Overview:
This article will look at different ways of how you can map many-to-many associations in Hibernate.

Approach1: Mapping as many-to-one associations without an association entity.
Approach2: Mapping as many-to-one associations with an association entity as many-to-one.
Approach3: Mapping as many-to-one associations using composite-elements.

Approach1:
Mapping as many-to-one associations without an association entity. This approach is one of the most common ways of mapping a many-to-many association, there will be NO separate entity class to model the association between a Player and a Club.
Association Diagram
__________
|    Club         |
-----------------
       |*
       |
____|*____
|    Player     |
----------------
Class Diagram
___________
|Player             |
-------------------
|id:long            |
|name:String    |
|clubs:Set         |
-------------------
__________________
|Club                             |
------------------------------
|id:long                          |
|name:String                  |
|contractedPlayers:Set   |
------------------------------
Following is the database structure,
CREATE TABLE CLUB (
  club_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE PLAYER (
  player_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE CONTRACT (
  club_id,
  player_id,
  PRIMARY KEY (club_id, player_id),
  FOREIGN KEY (club_id) REFERENCES CLUB(club_id),
  FOREIGN KEY (player_id) REFERENCES PLAYER(player_id),
);  
Following is the hibernate mapping involved,
<?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.beans.Club">
     <id name="id" column="club_id">
        <generator class="increment" />
     </id>
     <property name="name" />
     <set name="contractedPlayers" table="contract" inverse="true">
        <key column="club_id" />
        <many-to-many class="Player" column="player_id"/>
     </set>
  </class>
  <class name="org.fazlan.beans.Player">
     <id name="id" column="player_id">
        <generator class="increment" />
     </id>
     <property name="name" />
     <set name="clubs" table="contract">
        <key column="player_id" />
        <many-to-many class="Club" column="club_id" />
     </set>
  </class>
</hibernate-mapping>
However, with this approach, we cannot model data specific to the association with the contract(e.i: start-date and end-date of the contract). The next approach will look at how we can model such many-to-many associations.

Approach2:
Mapping as many-to-one associations with an association entity. With this way, we can easily model additional data related to the association. This is achieved by having an entity class to model the association as many-to-one.

Association Diagram
_______________
|    Club       |
-----------------
|
______|*_______
|    Contract   |
-----------------
|*
______|________
|    Player     |
-----------------

Class Diagram
_______________
|Player         |
-----------------
|id:long        |
|name:String    |
-----------------
_______________
|Club           |
-----------------
|id:long        |
|name:String    |
-----------------
______________________________
|Contract                      |
--------------------------------
|contract_id:long              |
|club:Club                     |
|player:Player                 |
|startDate:Date                |
|endDate:Date                  |
--------------------------------
Here, the association between a Player and a Club will be represented using an association entity, namely Contract. Following is the database structure,
CREATE TABLE CLUB (
  club_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE PLAYER (
  player_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE CONTRACT (
  contract_id INTEGER NOT NULL,
  club_id,
  player_id,
  start_date Date,
  end_date Date,
  PRIMARY KEY (contract_id),
  FOREIGN KEY (club_id) REFERENCES CLUB(club_id),
  FOREIGN KEY (player_id) REFERENCES PLAYER(player_id),
); 
Following is the Hibernate mapping involved,
<?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.beans.Club">
     <id name="id" column="club_id">
        <generator class="increment" />
     </id>
     <property name="name" />
  </class>
  <class name="org.fazlan.beans.Player">
     <id name="id" column="club_id">
        <generator class="increment" />
     </id>
    <property name="name" />
  </class>
  <class name="org.fazlan.beans.Contract">
     <id name="id" column="contract_id">
        <generator class="increment" />
     </id>
     <property name="startDate" column="start_date"/>
     <property name="endDate" column="end_date"/>
     <many-to-one name="club" column="club_id" not-null="true" />
     <many-to-one name="player" column="player_id" not-null="true" />
  </class>
</hibernate-mapping>
Alternatively, you can model the many-to-many relationship using an composite-element. The next section looks at this.

Approach3:
Mapping as many-to-one associations using composite-elements.
Association Diagram
_______________
|    Club       |
-----------------
    |
______|*_______
|    Contract   |
-----------------
    |*
______|________
|    Player     |
-----------------

Class Diagram
_______________
|Player         |
-----------------
|id:long        |
|name:String    |
-----------------
_______________
|Club           |
-----------------
|id:long        |
|name:String    |
|contracts:List |
-----------------
______________________________
|Contract                      |
--------------------------------
|id:long              |
|player:Player                 |
|startDate:Date                |
|endDate:Date                  |
--------------------------------
Following is the database structure,
CREATE TABLE CLUB (
  club_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE PLAYER (
  player_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE CONTRACT (
  contract_id INTEGER NOT NULL,
  club_id,
  player_id,
  start_date Date,
  end_date Date,
  PRIMARY KEY (contract_id),
  FOREIGN KEY (club_id) REFERENCES CLUB(club_id),
  FOREIGN KEY (player_id) REFERENCES PLAYER(player_id),
);
Following is the Hibernate mapping involved,
<?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.beans.Club">
     <id name="id" column="club_id">
        <generator class="increment" />
     </id>
     <property name="name" />
     <list name="contracts" table="contract">
        <key column="club_id" />
        <index-column column="contract_id" />        
        <composite-element class="org.fazlan.beans.Contract">
             <property name="startDate" column="start_date"/>
             <property name="endDate" column="end_date"/>
             <many-to-one name="player" column="player_id">
        </composite-element>
     </list>
  </class>
  <class name="org.fazlan.beans.Player">
     <id name="id" column="player_id">
        <generator class="increment" />
     </id>
     <property name="name" />
  </class>
</hibernate-mapping>
Summary:
This article looked at how you can map many-to-many associations in different ways depending on the data you need to capture.