Sunday, 31 March 2013

ZK MVVM Form Binding CRUD with Spring and Hibernate - Part 6

Spring security 3 integration with hibernate 4

        


What’s up next !. As per the last(Part 5) article, we have successfully completed our CRUD Operation and we completely change the look and feel (I hope it looks good).

We have user details with user id and password. But where is the login screen ?. Ok that’s what we are going to see how to develop login screen for our application. We will integrate Spring security 3 to secure our application using our application.

For introduction about spring security, Please read the following article.
Introduction to Spring Security Concepts

Other Reference
1. Getting Started Spring Security
2. Understanding Spring Security
3. Configuring spring security

If you want to try to ZK with spring security, then read this step by step article.

Let us start now.
Step 1:
First we need to update our POM.XML with spring security core dependency. Spring web and spring orm version does not match with spring security version. We will use later spring web and spring security dependency, but with different version. As of this date, latest version of
spring web is 3.2.2 Release   and same for Spring ORM.  For spring security, we we will use 3.2.0.M1(You can check here and here)

So here is the updated pom.xml file content

<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ZKBeanValidation</groupId>
<artifactId>ZKBeanValidation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<zk.version>6.5.2</zk.version>
<commons-io>1.3.1</commons-io>
<maven.build.timestamp.format>yyyy-MM-dd</maven.build.timestamp.format>
<packname>-${project.version}-FL-${maven.build.timestamp}</packname>
<spring.version>3.2.2.RELEASE</spring.version>
<spring-security.version>3.2.0.M1</spring-security.version>
</properties>
<packaging>war</packaging>
<name>The ZKBeanValidation Project</name>
<description>The ZKBeanValidation Project</description>
<licenses>
<license>
<name>GNU LESSER GENERAL PUBLIC LICENSE, Version 3</name>
<url>http://www.gnu.org/licenses/lgpl.html</url>
<distribution>repo</distribution>
</license>
</licenses>
<repositories>
<repository>
<id>ZK CE</id>
<name>ZK CE Repository</name>
<url>http://mavensync.zkoss.org/maven2</url>
</repository>

<repository>
<id>repository.springsource.milestone</id>
<name>SpringSource Milestone Repository</name>
<url>http://repo.springsource.org/milestone</url>
</repository>

</repositories>
<pluginRepositories>
<pluginRepository>
<id>zkmaven</id>
<name>ZK Maven Plugin Repository</name>
<url>http://mavensync.zkoss.org/maven2/</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zkbind</artifactId>
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zul</artifactId>
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zkplus</artifactId>
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zhtml</artifactId>
<version>${zk.version}</version>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io}</version>
</dependency>

<!-- Spring framework -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency> <!-- Used for Hibernate4 LocalSessionFactoryBean -->
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring-security.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring-security.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring-security.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>


<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>

<!-- AOP dependency -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>

<!-- Persistence Management -->
<dependency> <!-- Apache BasicDataSource -->
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>

<dependency> <!-- MySQL database driver -->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.20</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>


<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.1.10.Final</version>
</dependency>
<!-- ZK 5 breeze theme <dependency> <groupId>org.zkoss.theme</groupId>
<artifactId>breeze</artifactId> <version>${zk.version}</version> <optional>true</optional>
</dependency> -->
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- Run with Jetty -->
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.10</version>
<configuration>
<scanIntervalSeconds>5</scanIntervalSeconds>
<stopKey>foo</stopKey>
<stopPort>9999</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Compile java -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<!-- Build war -->
<plugin>
<artifactId>maven-war-plugin</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<version>2.1.1</version>
</plugin>
<!-- Pack zips -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>webapp</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>ZKBeanValidation${packname}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>assembly/webapp.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

Step 2:
Next we will update our web.xml. Here is the code snippet(See the full content from the download).


.......
<!-- Spring can be easily integrated into any Java-based web framework.
All you need to do is to declare the ContextLoaderListener in your web.xml
and use a contextConfigLocation <context-param> to set which context files
to load. If you don't specify the contextConfigLocation context parameter,
the ContextLoaderListener will look for a /WEB-INF/applicationContext.xml
file to load. Once the context files are loaded, Spring creates a WebApplicationContext
object based on the bean definitions and puts it into the ServletContext. -->

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<!-- Loads the Spring web application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- A servlet filter capturing every user requests and sending them to
the configured security filters to make sure access is authorized. -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- //// -->
<!-- ZK -->
.......
 
Step 3:
As you can see in the web.xml, we are loading another xml file configuration called as “spring-security.xml”. So let us create this file under our web-inf folder as shown

image


<!-- Spring namespace-based configuration -->

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">

<!-- ====================================================== -->
<!-- For catching the @Secured annotation methods -->
<!-- Tells the Spring Security engine that we will use Spring Security's -->
<!-- pre and post invocation Java annotations (@PreFilter, @PreAuthorize, -->
<!-- @PostFilter, -->
<!-- @PostAuthorize) to secure service layer methods.. -->
<!-- Look in GFCBaseCtrl.java onEvent() method. -->
<!-- ====================================================== -->

<!-- Enable the @Secured annotation to secure service layer methods -->
<global-method-security secured-annotations="enabled" />

<http auto-config="true">

<!-- ====================================================== -->
<!-- If we have our own LoginPage. So we must -->
<!-- tell Spring the name and the place. -->
<!-- In our case we take the same page -->
<!-- for a error message by a failure. -->
<!-- Further the page after a successfully login. -->
<!-- ====================================================== -->
<form-login login-page="/login.zul"
authentication-failure-url="/login.zul?login_error=1"
default-target-url="/main.zul" always-use-default-target="true" />
<intercept-url pattern="/login.zul" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/*.zul" access="IS_AUTHENTICATED_REMEMBERED" />
</http>

<authentication-manager>
<authentication-provider user-service-ref="myUserDetailsService">

</authentication-provider>
</authentication-manager>

<beans:bean id="myUserDetailsService" class="zkexample.service.MyUserDetailsService" />


</beans:beans>



Step 4:
As you can see in the security xml file, we have said we will have our login (login.zul) form instead of spring default login page. So let us create our login page. Everybody want to create stylish login page for their application. There are lot of free login page available with CSS. So I will be using one of them. You can check Here.

So under the webapp folder, create one more zul file and name as login.zul and under the webapp->css folder, create one more css file as login.css as shown.

image

You can copy the login.zul and login.css source from the download which is available at the bottom of this post. Please don’t forget to add this new css file in our ZKAddon.xml as shown here.



<?xml version="1.0" encoding="UTF-8"?>
<language-addon>
<addon-name>myaddon</addon-name>
<language-name>xul/html</language-name>
<stylesheet href="/css/login.css" type="text/css" />
<stylesheet href="/css/style.css" type="text/css" />
<stylesheet href="/css/ThemeStyle.css" type="text/css" />

</language-addon>

Step 5:
Next we will need to update our dao and service layer by adding one more method to execute named query.

CRUDDao.



<T> T GetUniqueEntityByNamedQuery(String query, Object... params);

CRUDDaoImpl.java


@SuppressWarnings("unchecked")
public <T> T GetUniqueEntityByNamedQuery(String query, Object... params) {

Query q = getCurrentSession().getNamedQuery(query);
int i = 0;

for (Object o : params) {
q.setParameter(i, o);
}

List<T> results = q.list();

T foundentity = null;
if (!results.isEmpty()) {
// ignores multiple results
foundentity = results.get(0);
}
return foundentity;
}



CRUDService.java



<T> T GetUniqueEntityByNamedQuery(String query, Object... params);

CRUDServiceImpl.java


@Transactional
public <T> T GetUniqueEntityByNamedQuery(String query, Object... params) {
return CRUDDao.GetUniqueEntityByNamedQuery(query, params);
}

In the domain object, let us add the named query in the top
UserProfile.java


@Entity
@Table(name = "userprofile")
@NamedQuery(name = "UserProfile.findUserByUserID", query = "SELECT usr FROM UserProfile as usr WHERE usr.userLoginID = ?")
public class UserProfile implements Serializable {

------Other Code-----


Step 6:
Next we will create our custom authentication by extending spring UserDetailsService interface. Select the “service” package, right click, select new->Other->Class and enter the class name as “MyUserDetailsService”.
image



package zkexample.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import zkexample.domain.UserProfile;

public class MyUserDetailsService implements UserDetailsService {

@Autowired
private CRUDService CRUDService;

/*
* You just have to make sure that the user-by-username-query returns three
* fields. 1) the userName 2) the password 3) boolean for is the user
* active. If you don't have an active field, make your query always return
* true for that third field.
*/
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {

// Declare a null Spring User
UserDetails user = null;

try {

// Search database for a user that matches the specified username
// You can provide a custom DAO to access your persistence layer
// Or use JDBC to access your database
// DbUser is our custom domain user. This is not the same as
// Spring's User

UserProfile dbUser = CRUDService.GetUniqueEntityByNamedQuery(
"UserProfile.findUserByUserID", username);

// Populate the Spring User object with details from the dbUser
// Here we just pass the username, password, and access level
// getAuthorities() will translate the access level to the correct
// role type

user = new User(dbUser.getUserLoginID(), dbUser.getPassword()
.toLowerCase(), true, true, true, true,
getAuthorities());

} catch (Exception e) {
throw new UsernameNotFoundException("Error in retrieving user");
}

// Return user to Spring for processing.
// Take note we're not the one evaluating whether this user is
// authenticated or valid
// We just merely retrieve a user that matches the specified username

return user;
}

/**
* Retrieves the correct ROLE type depending on the access level, where
* access level is an Integer. Basically, this interprets the access value
* whether it's for a regular user or admin.
*
* @param access
* an integer value representing the access of the user
* @return collection of granted authorities
*/
public Collection<GrantedAuthority> getAuthorities() {
// Create a list of grants for this user
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);

// All users are granted with ROLE_USER access
// Therefore this user gets a ROLE_USER by default
authList.add(new GrantedAuthorityImpl("ROLE_USER"));
// User has admin access
authList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));

// Return list of granted authorities
return authList;
}
}

Step 7:
Next we will add logout option in the userlist.zul file as follows. Just add one more button next add new button


	<div style="float:right">
<button label="Add New" onClick="@command('onAddNew')"
mold="trendy" sclass="mybutton button blue small" />
<button label="Logout" mold="trendy" id="btnlogout"
sclass="mybutton button blue small" onClick="@command('Logout')" />
</div>

And also, add the following code in the VM.


	@Command
public void Logout()
{
Executions.sendRedirect("/j_spring_security_logout");
}


Now you select the Project->Right Click –>Select Run as –> Run on Server.
image

Video Demo
http://screencast.com/t/HXSul1abLlf

In the next part 7, We will add some more features to our listing page.
You can download the source here.

        

ZK composite component Example

Left hugThanks to benbai for helping me in the ZK Forum to complete this example.

This example shows how to create our own component using ZK Composite Component method.

Use case : Why and what is the ZK Composite Component. Well, assume that, in your project, there are similar screens and in each screen at the top , you need a display caption on the left hand side and on the right end corner, you need buttons such as “Save,” Cancel”, “Back”, etc.

Step 1: If you are new to ZK, then setup the Development environment by following this document.

Step 2:
Create a ZK Project and name as CompositeComp

image

image

image

Step 3:
Before creating our own component, let us see what we need to create and how should be our output. Copy the below code and paste in the index.zul file


<window>

<style>

.sectionTitleLabel.z-label {
font-size: 18px;
font-weight: bolder;
color: #0C6BA8;
}

.sectionTitle {
float: left;
padding-left: 20px;
}

.sectionSeperator {
margin-bottom: 18px;
padding-bottom: 0.25em;
margin-left: 20px;
border-bottom: 4px solid #DFDFDF
}

.mybutton.z-button .z-button-cm {
background-image: none;
color: white;
font-weight: bolder;
}

.mybutton.z-button .z-button-tm,.z-button .z-button-bm {
background-image: none;
}

.mybutton.z-button .z-button-cl,.z-button .z-button-cr {
background-image: none;
}

.mybutton.z-button .z-button-tl {
background-image: none;
}

.mybutton.z-button .z-button-bl {
background-image: none;
}

.mybutton.z-button .z-button-tr {
background-image: none;
}

.mybutton.z-button .z-button-br {
background-image: none;
}

.button {
display: inline-block;
zoom: 1; /* zoom and *display = ie7 hack for display:inline-block */
*display: inline;
vertical-align: baseline;
margin: 0 2px;
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
font: 14px/100% Arial, Helvetica, sans-serif;
padding: .5em 2em .55em;
text-shadow: 0 1px 1px rgba(0, 0, 0, .3);
-webkit-border-radius: .5em;
-moz-border-radius: .5em;
border-radius: .5em;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
}

.button:hover {
text-decoration: none;
}

.button:active {
position: relative;
top: 1px;
}

.small {
font-size: 11px;
padding: .2em 1em .275em;
}

.blue {
color: #d9eef7;
border: solid 1px #0076a3;
background: #0095cd;
background: -webkit-gradient(linear, left top, left bottom, from(#00adee),
to(#0078a5) );
background: -moz-linear-gradient(top, #00adee, #0078a5);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee',
endColorstr='#0078a5' );
}

.blue:hover {
background: #007ead;
background: -webkit-gradient(linear, left top, left bottom, from(#0095cc),
to(#00678e) );
background: -moz-linear-gradient(top, #0095cc, #00678e);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0095cc',
endColorstr='#00678e' );
}

.blue:active {
color: #80bed6;
background: -webkit-gradient(linear, left top, left bottom, from(#0078a5),
to(#00adee) );
background: -moz-linear-gradient(top, #0078a5, #00adee);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0078a5',
endColorstr='#00adee' );
}

</style>
<div width="96%">
<span width="100%">
<div sclass="sectionTitle">
<separator />
<label value="Registration" sclass="sectionTitleLabel" />
<separator />
</div>
</span>
<div style="float:right;margin-top:6px;">
<button mold="trendy" label="Cancel" sclass="mybutton button blue small " />
<button mold="trendy" label="Save" sclass="mybutton button blue small"/>
</div>
<div style="clear: both;"></div>
<div sclass="sectionSeperator"></div>
</div>
</window>

Now let us run the index.zul and the following is the output.
image

So as per our use case, we need to write the same set of code in each zul file to achieve the output. Instead of writing whole bunch of code again and again, let us create our component with necessary attributes.

Step 4:
First let us create the zul file called “header.zul” as shown in the figure.


image

image


Here is the content of the header.zul file



<div width="96%">

<style>

.sectionTitleLabel.z-label { font-size: 18px; font-weight:
bolder; color: #0C6BA8; }

.sectionTitle { float: left; padding-left: 20px; }

.sectionSeperator { margin-bottom: 18px; padding-bottom: 0.25em;
margin-left: 20px; border-bottom: 4px solid #DFDFDF }

.mybutton.z-button .z-button-cm { background-image: none; color:
white; font-weight: bolder; }

.mybutton.z-button .z-button-tm,.z-button .z-button-bm {
background-image: none; }

.mybutton.z-button .z-button-cl,.z-button .z-button-cr {
background-image: none; }

.mybutton.z-button .z-button-tl { background-image: none; }

.mybutton.z-button .z-button-bl { background-image: none; }

.mybutton.z-button .z-button-tr { background-image: none; }

.mybutton.z-button .z-button-br { background-image: none; }

.button { display: inline-block; zoom: 1; /* zoom and *display =
ie7 hack for display:inline-block */ *display: inline;
vertical-align: baseline; margin: 0 2px; outline: none; cursor:
pointer; text-align: center; text-decoration: none; font:
14px/100% Arial, Helvetica, sans-serif; padding: .5em 2em .55em;
text-shadow: 0 1px 1px rgba(0, 0, 0, .3); -webkit-border-radius:
.5em; -moz-border-radius: .5em; border-radius: .5em;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, .2); box-shadow: 0 1px
2px rgba(0, 0, 0, .2); }

.button:hover { text-decoration: none; }

.button:active { position: relative; top: 1px; }

.small { font-size: 11px; padding: .2em 1em .275em; }

.blue { color: #d9eef7; border: solid 1px #0076a3; background:
#0095cd; background: -webkit-gradient(linear, left top, left
bottom, from(#00adee), to(#0078a5) ); background:
-moz-linear-gradient(top, #00adee, #0078a5); filter:
progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee',
endColorstr='#0078a5' ); }

.blue:hover { background: #007ead; background:
-webkit-gradient(linear, left top, left bottom, from(#0095cc),
to(#00678e) ); background: -moz-linear-gradient(top, #0095cc,
#00678e); filter:
progid:DXImageTransform.Microsoft.gradient(startColorstr='#0095cc',
endColorstr='#00678e' ); }

.blue:active { color: #80bed6; background:
-webkit-gradient(linear, left top, left bottom, from(#0078a5),
to(#00adee) ); background: -moz-linear-gradient(top, #0078a5,
#00adee); filter:
progid:DXImageTransform.Microsoft.gradient(startColorstr='#0078a5',
endColorstr='#00adee' ); }

</style>
<span width="100%">
<div sclass="sectionTitle">
<separator />
<label id="lcaption" sclass="sectionTitleLabel" />
<separator />
</div>
</span>
<div id="buttonsDiv" style="float:right;margin-top:6px;">

</div>
<div style="clear: both;"></div>
<div sclass="sectionSeperator"></div>
</div>



As you can see, now we have removed the label caption (Left hand side) and also we have removed the buttons on the right hand side. We will pass what will be caption and what will be buttons to be display from the client zul file.

Step 5:
Next we will create the java class to support our own component. Create a class called “Header.java” in the package org.zkoss.zul.


package org.zkoss.zul;

import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.IdSpace;
import org.zkoss.zk.ui.ext.AfterCompose;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Wire;

public class Header extends Div implements IdSpace, AfterCompose {

/**
*
*/
private static final long serialVersionUID = 1L;

@Wire
private Label lcaption;

@Wire
private Div buttonsDiv;

private String _buttons;

public Header() {
Executions.createComponents("header.zul", this, null);
Selectors.wireComponents(this, this, false);
Selectors.wireEventListeners(this, this);
}

@Override
public void afterCompose() {
createButtons();

}

public void createButtons() {
buttonsDiv.getChildren().clear();
for (String btn : _buttons.split(",")) {
Button button = new Button(btn.trim());
button.addForward("onClick", this, "onButtonsClick", btn.trim());
button.setParent(buttonsDiv);
button.setMold("trendy");
button.setSclass("mybutton button blue small");
Space space = new Space();
space.setSpacing("3px");
space.setParent(buttonsDiv);

}
}

public void setButtons(String buttons) {
_buttons = buttons;
}

public String getLcaption() {
return lcaption.getValue();
}

public void setLcaption(String lcaption) {
this.lcaption.setValue(lcaption);
}

}

As you can see, we have only two attributes such as What caption has to display in the left and how many buttons to be display on the right hand side. In the aftercompose, we are creating the buttons and also we are registering the event for those buttons.

That’s all, Now we are ready to use our own component.

Step 6:
Now we will use this newly created component in our index.zul file . Here is the simplified code of index.zul

<?page title="Auto Generated index.zul"?>
<!-- Composite component -->
<?component name="header" class="org.zkoss.zul.Header" ?>
<window apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('org.zkoss.zul.CompositeTestVM')">
<header lcaption="Registration" buttons="Cancel,Save" onButtonsClick="@command('buttonsClick')"></header>
</window>

And also using MVVM, we will handle button click event as follows



package org.zkoss.zul;

import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.zk.ui.event.ForwardEvent;

public class CompositeTestVM {

@Command
public void buttonsClick(
@ContextParam(ContextType.TRIGGER_EVENT) ForwardEvent event) {
Messagebox.show(" Button Clicked " + event.getData() + " " + event.getOrigin().getTarget() + " " + ((Button) event.getOrigin().getTarget()).getLabel());
}
}

Now you can run the index.zul to get the same output as follows
image


You can download the source here

Saturday, 30 March 2013

ZK MVVM Form Binding CRUD with Spring and Hibernate - Part 5

Change Look and Feel

        


In the previous part 4, we have created UI presentation layer (i.e) two files userlist.zul and userCRUD.zul file. If you look more closely, we have used sclass for each component. There is no impact on the look and feel. Now we will create CSS Classes for all those sclass names and change the look and feel.

Before going into detail, first we will change the layout for our application. We will use border layout with four area such north, west, center and south. In the north/south/west, we will show some images to beautify the application. In the center area, we will display all our zul files.

At the end of this part 5, our application will look as follows

image

image

Step 1:
In order to display all our screens, we will design our main page where we will have border layout as said before and center area is our container to display our screens.

Under the webapp folder, create a zul file called main.zul as shown

image

Here is the code :

<?page title="Main" contentType="text/html;charset=UTF-8"?>
<zk>
<window id="main" border="none" width="100%" height="100%"
apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('zkexample.zkoss.MainVM')">
<borderlayout id="mainlayout" height="100%">
<north id="north" height="19%" border="0">
<div>
<image sclass="fimgtopbkg"></image>
<image sclass="fimgsidetop"></image>
</div>
</north>
<west id="west" size="7%" border="0">
<div width="100%" height="100%">
<image sclass="fimgsidemid"></image>
<image sclass="fimgsidebgk"></image>
</div>
</west>
<center id="center" border="0">
<include src="userList.zul" />
</center>
<south id="south" border="0" size="4%">
<image sclass="fimgbottom"></image>
</south>
</borderlayout>
</window>
</zk>

And also we will create our viewmodel(MainVM) for the above main.zul as shown

image

package zkexample.zkoss;

import java.util.HashMap;

import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.Borderlayout;
import org.zkoss.zul.Center;

public class MainVM {

@Wire("#mainlayout")
private Borderlayout borderLayout;

/**
* This method will be called after host component composition has been done
* (AfterCompose)
*
* @param view
* Root Component of the ZUL File.
*/

@AfterCompose
public void initSetup(@ContextParam(ContextType.VIEW) Component view) {

final HashMap<String, Object> map = new HashMap<String, Object>();

Selectors.wireComponents(view, this, false);

/* get an instance of the searched CENTER layout area */
Center c1 = borderLayout.getCenter();

/* clear the center child */
c1.getChildren().clear();

map.put("centerArea", c1);
/* Load the left navigation menu for patient cases */
Executions.createComponents("userList.zul", c1, map);
}
}


Step 2:
Let us create CSS and Images in the application. Under the webapp folder, create two folders called CSS and images.
image
Under the CSS Folder, create two css files such as style.css and ThemeStyle.css.  You can copy the CSS Content from the source which is available for download at the bottom of this post. 

The reason for having two css files as follows
1. If you look closely in the css files, both the css files will contain the same class name, but in the style.css, it will contain only alignment related properties, but all the color and images under the same class name are coded in the Themestyle.css. By this way, we can have build the different theme for each user. We will see this in the later part of this series.

Next from the downloaded source, copy all the images into image folder. Finally, the structure will look as follows
image



Since now we are going to display all our screens in the center area of the borderlayout, so I modified all the following files. No change in the business logic, just changed the way to accommodate the borderlayout.

All these following files are modifier. Please refer the source
userList.zul
UserCRUD.zul
UserListVM.java
UserCRUDVM.java

Now you can select the main.zul and run using tomcat server and observe the output.

Video Demo (It will take some to show)
http://screencast.com/t/eo4XUdj6GI

In the next part 6, We will see how to apply Spring security 3 integration with hibernate 4
You can download the source code here.



        

Thursday, 28 March 2013

ZK MVVM Form Binding CRUD with Spring and Hibernate - Part 4

Presentation Layer using ZK Framework

        


In part 3, We have completed Spring integration with hibernate. In this post, we will design our presentation layer using ZK Framework.

Step 1:
We will first design our listing screens which will show all the users in the database with typical CRUD Operation as shown here.
image 

Under the webapp folder, create a zul file and name as userList.zul as shown.
image

<?page title="Users List" contentType="text/html;charset=UTF-8"?>
<zk>
<window id="userList" border="none"
apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('zkexample.zkoss.UserListVM')">
<separator />
<separator />
<div width="100%">
<div sclass="sectionTitle">
<separator />
<label value="Users" sclass="sectionTitleLabel" />
<separator />
</div>
<div style="float:right">
<button label="Add New" onClick="@command('onAddNew')"
mold="trendy" sclass="mybutton button blue small" />
</div>
<div style="clear: both;"></div>
<div sclass="sectionSeperator"></div>
</div>
<separator />
<listbox id="" mold="paging" pageSize="11" pagingPosition="top"
sclass="mylist" selectedItem="@bind(vm.selectedItem)"
model="@load(vm.dataSet)">
<listhead sizable="true">
<listheader label="First Name" sortDirection="ascending"
sort="auto(firstName)" />
<listheader label="last Name" sort="auto(lastName)" />
<listheader label="Email" sort="auto(email)" />
<listheader label="Login ID" sort="auto(userLoginID)" />
<listheader label="Action" />
</listhead>
<template name="model" var="p1">
<listitem>
<listcell label="@load(p1.firstName)" />
<listcell label="@load(p1.lastName)" />
<listcell label="@load(p1.email)" />
<listcell label="@load(p1.userLoginID)" />
<listcell>
<hbox spacing="20px">
<button label="Edit"
onClick="@command('onEdit',userRecord=p1)">
</button>
<button label="View"
onClick="@command('openAsReadOnly',userRecord=p1)">
</button>
<button label="Delete"
onClick="@command('onDelete',userRecord=p1)">
</button>
</hbox>
</listcell>
</listitem>
</template>
</listbox>
</window>
</zk>


1. We are using MVVM as design pattern.
2. And also, to display the values, we are using MVVM Data binding concept.
3. For event handling, we are using MVVM Command Binding.
4. We are using ZK List box to show the record from the DB.
5. We will display the records using MVVM View Modal

Now let us create the view model to support the view. Create one more package named as zkoss under the existing package zkexample as shown.
image

Under the package, create a class called UserListVM
image



package zkexample.zkoss;

import java.util.HashMap;
import java.util.List;

import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zkplus.spring.SpringUtil;
import org.zkoss.zul.Messagebox;

import zkexample.domain.UserProfile;
import zkexample.service.CRUDService;

public class UserListVM {

@WireVariable
private CRUDService CRUDService;

private UserProfile selectedItem;
private List<UserProfile> allReordsInDB = null;

public UserProfile getSelectedItem() {
return selectedItem;
}

public void setSelectedItem(UserProfile selectedItem) {
this.selectedItem = selectedItem;
}

@AfterCompose
public void initSetup(@ContextParam(ContextType.VIEW) Component view) {
Selectors.wireComponents(view, this, false);
CRUDService = (CRUDService) SpringUtil.getBean("CRUDService");
allReordsInDB = CRUDService.getAll(UserProfile.class);
}

public List<UserProfile> getDataSet() {
return allReordsInDB;
}

@Command
public void onAddNew() {
final HashMap<String, Object> map = new HashMap<String, Object>();
map.put("selectedRecord", null);
map.put("recordMode", "NEW");
Sessions.getCurrent().setAttribute("allmyvalues", map);
Executions.sendRedirect("UserCRUD.zul");
}

@Command
public void onEdit(@BindingParam("userRecord") UserProfile userProfile) {

final HashMap<String, Object> map = new HashMap<String, Object>();
map.put("selectedRecord", userProfile);
map.put("recordMode", "EDIT");
Sessions.getCurrent().setAttribute("allmyvalues", map);
Executions.sendRedirect("UserCRUD.zul");
}

@Command
public void openAsReadOnly(
@BindingParam("userRecord") UserProfile userProfile) {

final HashMap<String, Object> map = new HashMap<String, Object>();
map.put("selectedRecord", userProfile);
map.put("recordMode", "READ");
Sessions.getCurrent().setAttribute("allmyvalues", map);
Executions.sendRedirect("UserCRUD.zul");
}

@SuppressWarnings({ "rawtypes", "unchecked" })
@Command
public void onDelete(@BindingParam("userRecord") UserProfile userProfile) {
int OkCancel;
this.selectedItem = userProfile;
String str = "The Selected \"" + userProfile.getUserLoginID()
+ "\" will be deleted.";
OkCancel = Messagebox.show(str, "Confirm", Messagebox.OK
| Messagebox.CANCEL, Messagebox.QUESTION);
if (OkCancel == Messagebox.CANCEL) {
return;
}

str = "The \""
+ userProfile.getUserLoginID()
+ "\" will be permanently deleted and the action cannot be undone.";

Messagebox.show(str, "Confirm", Messagebox.OK | Messagebox.CANCEL,
Messagebox.QUESTION, new EventListener() {
public void onEvent(Event event) throws Exception {
if (((Integer) event.getData()).intValue() == Messagebox.OK) {

CRUDService.delete(selectedItem);
allReordsInDB.remove(allReordsInDB
.indexOf(selectedItem));
BindUtils.postNotifyChange(null, null,
UserListVM.this, "dataSet");

}
}
});
}

}


Step 2:
Next we will design our CRUD Page where we can add new users and Edit existing users. This CRUD ZUL will be called from userList.zul when user click on Add/Edit/View buttons.
image



Create UserCRUD.Zul file under the webapp folder as shown.

image



<?page title="" contentType="text/html;charset=UTF-8"?>
<zk>
<window id="userCRUD" border="none"
apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('zkexample.zkoss.UserCRUDVM')">
<div
form="@id('fx') @load(vm.selectedRecord) @save(vm.selectedRecord, before='saveThis')">
<separator />
<div width="96%">
<span width="100%">
<div sclass="sectionTitle">
<separator />
<label id="lcaption" sclass="sectionTitleLabel"
value="Add/Edit Users" />
<label id="readonly" sclass="sectionTitleLabel"
value="(ReadOnly)" visible="@load(vm.makeAsReadOnly)" />
<image
src="@load(fxStatus.dirty?'images/unsaved32x32.png':'')" />
<separator />
</div>
</span>
<div id="buttonsDiv"
style="float:right;margin-top:6px;">
<button label="Save and Close" mold="trendy"
visible="@load(not vm.makeAsReadOnly)"
onClick="@command('saveThis', action=0)"
sclass="mybutton button blue small">
</button>
<button label="Save and Add" mold="trendy"
visible="@load(not vm.makeAsReadOnly)"
onClick="@command('saveThis', action=1)"
sclass="mybutton button blue small">
</button>
<button
label="@load(vm.makeAsReadOnly ?'Close':'Cancel')" mold="trendy"
onClick="@command('cancel')"
sclass="mybutton button blue small">
</button>
</div>
<div style="clear: both;"></div>
<div sclass="sectionSeperator"></div>
</div>

<span width="100%">
<div sclass="sectionTitle">
<separator />
<label value="Personel Information"
sclass="sectionTitleLabel" />
<separator />
</div>
</span>

<panel width="95%" sclass="sectionPanel">
<panelchildren>
<separator />
<grid sclass="vgrid">
<columns>
<column hflex="10%"></column>
<column hflex="10%"></column>
<column hflex="10%"></column>
<column hflex="10%"></column>
</columns>
<rows>
<row>
<vlayout>
<label value="User Account No"
sclass="flabel" />
<textbox id="accountNo"
readonly="@load(vm.makeAsReadOnly)" mold="rounded" hflex="1"
value="@bind(fx.userAccountNumber)" />
</vlayout>
<vlayout>
<label value="Last Name"
sclass="flabel" />
<textbox id="lastname"
readonly="@load(vm.makeAsReadOnly)" mold="rounded" hflex="1"
value="@bind(fx.lastName)" />
</vlayout>
<vlayout>
<label value="First Name"
sclass="flabel" />
<textbox id="firstname"
readonly="@load(vm.makeAsReadOnly)" mold="rounded" hflex="1"
value="@bind(fx.firstName)" />
</vlayout>
<vlayout>
<label value="Middle Name"
sclass="flabel" />
<textbox id="middleName"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.middleName)" />
</vlayout>

</row>
<row>

<vlayout>
<label value="Email"
sclass="flabel" />
<textbox id="email" hflex="1"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.email)" />
</vlayout>
<cell colspan="2">
<hbox>
<vlayout>
<label value="SSN"
sclass="flabel" />
<textbox id="SSN"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
width="115%" value="@bind(fx.SSN)" />
</vlayout>
<vlayout>
<label value="DOB"
sclass="flabel" />
<textbox id="DOB"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
width="115%" value="@bind(fx.DOB)" />
</vlayout>
</hbox>
</cell>
</row>
</rows>
</grid>
</panelchildren>
</panel>
<separator />
<separator />
<separator />
<span width="100%">
<div sclass="sectionTitle">
<separator />
<label value="Address Information"
sclass="sectionTitleLabel" />
<separator />
</div>
</span>
<panel width="95%" sclass="sectionPanel">
<panelchildren>
<grid sclass="vgrid">
<columns>
<column hflex="1"></column>
<column hflex="1"></column>
<column hflex="1"></column>
</columns>
<rows>
<row>
<cell colspan="2">
<vlayout>
<label value="Address"
sclass="flabel" />
<textbox id="address1" hflex="2"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.address1)" />
</vlayout>
</cell>
</row>
<row>
<cell colspan="2">
<vlayout>
<textbox id="address2" hflex="2"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.address2)" />
</vlayout>
</cell>
</row>
<row>
<vlayout>
<label value="City" sclass="flabel" />
<textbox id="City" hflex="1"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.city)" />
</vlayout>
<vlayout>
<grid>
<columns>
<column width="60%"></column>
<column></column>
</columns>
<rows>
<row>
<vlayout>
<label value="State"
sclass="flabel" />
<textbox id="State"
readonly="@load(vm.makeAsReadOnly)" hflex="1"
mold="rounded" value="@bind(fx.state)" />
</vlayout>
<vlayout>
<label
value="ZipCode" sclass="flabel" />
<textbox
id="zipcode" hflex="1" mold="rounded"
readonly="@load(vm.makeAsReadOnly)"
value="@bind(fx.zipCode)" />
</vlayout>
</row>
</rows>
</grid>
</vlayout>
</row>
</rows>
</grid>
</panelchildren>
</panel>
<separator />
<separator />
<separator />
<span width="100%">
<div sclass="sectionTitle">
<separator />
<label value="Login information"
sclass="sectionTitleLabel" />
<separator />
</div>
</span>
<panel width="95%" sclass="sectionPanel">
<panelchildren>
<separator />
<grid sclass="vgrid">
<columns>
<column width="20%"></column>
<column width="24%"></column>
</columns>
<rows>
<row>
<vlayout>
<label value="Login ID"
sclass="flabel" />
<textbox id="loginid" hflex="1"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.userLoginID)" />
</vlayout>
<vlayout>
<label value="Password"
sclass="flabel" />
<textbox id="password" hflex="1"
readonly="@load(vm.makeAsReadOnly)" mold="rounded"
value="@bind(fx.password)" />
</vlayout>
</row>
</rows>
</grid>
</panelchildren>
</panel>
</div>
</window>
</zk>

We have used MVVM Form binding Method to build our CRUD Page.
Next we will add View Model to control the above zul file. Under the zkexample.zkoss package, create a class called UserCRUDVM

package zkexample.zkoss;

import java.util.HashMap;

import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zkplus.spring.SpringUtil;

import zkexample.domain.UserProfile;
import zkexample.service.CRUDService;

public class UserCRUDVM {

@WireVariable
private CRUDService CRUDService;

private UserProfile selectedRecord;
private String recordMode;
private boolean makeAsReadOnly;

public UserProfile getSelectedRecord() {
return selectedRecord;
}

public void setSelectedRecord(UserProfile selectedRecord) {
this.selectedRecord = selectedRecord;
}

public String getRecordMode() {
return recordMode;
}

public void setRecordMode(String recordMode) {
this.recordMode = recordMode;
}

public boolean isMakeAsReadOnly() {
return makeAsReadOnly;
}

public void setMakeAsReadOnly(boolean makeAsReadOnly) {
this.makeAsReadOnly = makeAsReadOnly;
}

@SuppressWarnings("unchecked")
@AfterCompose
public void initSetup(@ContextParam(ContextType.VIEW) Component view) {

UserProfile userProfile;
Selectors.wireComponents(view, this, false);

final HashMap<String, Object> map = (HashMap<String, Object>) Sessions
.getCurrent().getAttribute("allmyvalues");
this.recordMode = (String) map.get("recordMode");
userProfile = (UserProfile) map.get("selectedRecord");
CRUDService = (CRUDService) SpringUtil.getBean("CRUDService");

if (recordMode.equals("NEW")) {
this.selectedRecord = new UserProfile();
}

if (recordMode.equals("EDIT")) {
this.selectedRecord = userProfile;
}

if (recordMode == "READ") {
setMakeAsReadOnly(true);
this.selectedRecord = userProfile;
}
}

@Command
public void saveThis(@BindingParam("action") Integer action) {
CRUDService.Save(this.selectedRecord);
if (action==0)
{
Executions.sendRedirect("userList.zul");
}
if (action==1)
{
this.selectedRecord = new UserProfile();
BindUtils.postNotifyChange(null, null, UserCRUDVM.this,"selectedRecord");

}
}

@Command
public void cancel()
{
Executions.sendRedirect("userList.zul");
}

}


So we have completed our CRUD operation. Now you can select the userList.zul and Run using tomcat server.

You can download source here.



Video Demo
http://screencast.com/t/dYgpCAGGUqu1



In the next part 5, We will change the look and feel using CSS



        

Wednesday, 27 March 2013

ZK MVVM Form Binding CRUD with Spring and Hibernate - Part 3

Spring Integration with Hibernate

        


In Part 2, we have created our domain, DAO and service Layer. In this part 3, we will see how to integrate spring and Hibernate. There are different way you can integrate. In this example, I am going to show by using Hibernate API. For more information, please check here.

Step 1:
First let us update our web.xml under the web-inf folder. Just add the following section in the top of the web.xml file.

<!-- Spring can be easily integrated into any Java-based web framework. 
All you need to do is to declare the ContextLoaderListener in your web.xml
and use a contextConfigLocation <context-param> to set which context files
to load. If you don't specify the contextConfigLocation context parameter,
the ContextLoaderListener will look for a /WEB-INF/applicationContext.xml
file to load. Once the context files are loaded, Spring creates a WebApplicationContext
object based on the bean definitions and puts it into the ServletContext. -->

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<!-- Loads the Spring web application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Step 2:
Next we will create applicationContext.xml under web-inf folder.
image


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" 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/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/addressbook" />
<property name="username" value="root" />
<property name="password" value="1234" />
</bean>


<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="zkexample.domain" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.zeroDateTimeBehavior">convertToNull</prop>
</props>
</property>
</bean>

<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<context:annotation-config />
<context:component-scan base-package="zkexample" />

<tx:annotation-driven transaction-manager="transactionManager" />

<!-- This will ensure that hibernate or jpa exceptions are automatically
translated into Spring's generic DataAccessException hierarchy for those
classes annotated with Repository -->

<bean
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

<bean id="CRUDService" class="zkexample.service.CRUDServiceImpl" />

</beans>

Reference
1. MIGRATING TO SPRING 3.1 AND HIBERNATE 4.1
2. Spring Integration with Hibernate
3. Object Relational Mapping (ORM) data access
4. Spring and Hibernate ORM Framework Integration
5. The Persistence Layer with Spring 3.1 and Hibernate


In the next part 4, we will create UI for our CRUD operation using ZK.