Learn Spring By Example – Struts+Spring+Hibernate Integration

Hi friends,

Finally after a long time, we are back. Here we’ve yet another example, as the title says, it is an Integration example in which we are going to see how Struts, Spring and Hibernate are getting integrated together.

In the following example, Struts is used for view layer and also works as a controller, spring for IOC and transaction layers, hibernate for ORM (model layer).

Platform

OS: Windows XP Professional SP3.
IDE: Eclipse Juno.
Java: 1.6.0
Application Server: Apache Tomcat 6.0.37
Frameworks: Struts 2.1.8, Spring 3.2.1, Hibernate 3.2.0.
Databse: MySQL 5.1.32-community.

Ok, let’s start. The heart of the application is applicationContext.xml, where these frameworks are integrated. The file looks like this.

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:p="http://www.springframework.org/schema/p" 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.xsd">

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

	<context:annotation-config />

	<context:component-scan
		base-package="com.stringer.action,com.stringer.bo,com.stringer.dao" />

	<context:property-placeholder location="/WEB-INF/jdbc.properties" />

	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${driver}" />
		<property name="url" value="${url}" />
		<property name="username" value="${username}" />
		<property name="password" value="${password}" />
	</bean>

	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="hibernateProperties" ref="hibernateProperties" />
		<property name="packagesToScan" value="com.stringer.model"></property>
	</bean>

	<bean id="hibernateProperties"
		class="org.springframework.beans.factory.config.PropertiesFactoryBean">
		<property name="locations">
			<list>
				<value>/WEB-INF/hibernate.properties</value>
			</list>
		</property>
	</bean>

	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager"
		p:sessionFactory-ref="sessionFactory">
	</bean>

</beans>

It’s sorry to say that I’m not going to explain each and every point of the above configuration file. You can find out these definitions in every nook and corner of the web. Anyway I shall explain in brief.

<context:property-placeholder location="/WEB-INF/jdbc.properties" />

The above line tells spring to load property file from the specified location. We can also load multiple property files simultaneously like this.

<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${driver}" />
		<property name="url" value="${url}" />
		<property name="username" value="${username}" />
		<property name="password" value="${password}" />
	</bean>

The above bean definition says all about the database connection, i.e., driver, username, password, url etc.

<bean id="hibernateProperties"
		class="org.springframework.beans.factory.config.PropertiesFactoryBean">
		<property name="locations">
			<list>
				<value>/WEB-INF/hibernate.properties</value>
			</list>
		</property>
	</bean>

The above bean definition tells spring to load hibernate properties from the specified file.

<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="hibernateProperties" ref="hibernateProperties" />
		<property name="packagesToScan" value="com.stringer.model"></property>
	</bean>

The above definition creates a “sessionFactory” object using “dataSource” and “hibernateProperties”. The property “packagesToScan” specifies the path where the scanning for hibernate entities is to be performed. In this example, all model entities are encapsulated in “com.stringer.model” package.

Here comes the definition for creating a transaction manger object.

	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager"
		p:sessionFactory-ref="sessionFactory">
	</bean>

The given piece of line used to enable spring annotation.

<context:annotation-config />

Finally, the below tag is used to scan for spring components in an application. The location of where to scan for classes is also specified.

<context:component-scan
		base-package="com.stringer.action,com.stringer.bo,com.stringer.dao" />

As it is already discussed in one of the previous post, spring scans for classes that are annotated with one of the following annotations.

  • @Component
  • @Controller
  • @Repository
  • @Service
  • Any custom annotation that is itself annotated with @Component

Ok, now let’s look into property files.

jdbc.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/Stringer
username=root
password=password

hibernate.properties

hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update

Now we’ve finished spring configuration. Next we are going to see struts configuration.

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

	<package name="default" extends="struts-default" namespace="/">

		<global-results>
			<result name="StringerException" type="chain">
				<param name="actionName">StringerExceptionAction</param>
			</result>
			<result name="error">/WEB-INF/Content/error.jsp</result>
		</global-results>

		<global-exception-mappings>
			<exception-mapping exception="java.lang.Exception"
				result="StringerException" />
		</global-exception-mappings>

		<action name="StringerExceptionAction" class="com.stringer.util.StringerException">
			<result name="StringerExceptionResult">/WEB-INF/Content/error.jsp</result>
		</action>

	</package>

	<include file="struts-user.xml" />
	<include file="struts-account.xml" />
	<include file="struts-index.xml" />

</struts>

In the above file, we can see global-results and global-exceptions are mapped. Also, it includes some other action mapping files. Struts supports split the overall mappings into several mapping files. One of the mapping file is given below. The given file is used for action mappings of user module.

struts-user.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

	<package name="User" extends="default" namespace="/User">

		<action name="*" method="{1}" class="UserAction">
			<result name="success">/WEB-INF/Content/User/home.jsp</result>
			<result name="input">/WEB-INF/Content/User/login.jsp</result>
			<result name="list">/WEB-INF/Content/User/list.jsp</result>
			<result name="profile">/WEB-INF/Content/User/profile.jsp</result>
			<result name="home">/WEB-INF/Content/User/home.jsp</result>
			<result name="create">/WEB-INF/Content/User/register.jsp</result>
			<result name="redirect" type="redirect">list.htm</result>
		</action>

	</package>

</struts>

Just look into the highlighted line given above, where we can see an attribute namely “class” and its value “UserAction”. Here, it’s not the class name actually, but the name of a spring bean. Just scroll up to the UserAction.java and we can see that the class has been annotated(@Controller) as a Controller and the controller’s name is given as “UserAction”. When we annotate a class as a controller, it becomes a spring component and we can reuse it anywhere in the application. How we could use it in this way because we add struts-spring integration plugin to the application and it helps us out.

struts.properties

struts.action.extension=htm
struts.ognl.allowStaticMethodAccess=true
struts.objectFactory= org.apache.struts2.spring.StrutsSpringObjectFactory
struts.objectFactory.spring.autoWire=type
struts.convention.result.path=/WEB-INF/content/
struts.devMode=true
struts.custom.i18n.resources=global

Here some of the struts properties defined, in which struts objectFactory and spring autowire default mode are notable. Here, we set default autowire mode as “type”. It allows a property to be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown. You can get to know more about spring autowiring from here.

This is for logging, which is optional.

log4j.properties

log4j.rootLogger = INFO, FILE
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=C://log.out
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=#[%d{dd/MMM/yyyy HH:mm:ss}] - File[%F] - Method[%M] - Line[%L] - Priority[%p] - Message[%m]%n

And the following two files stand for struts internationalization(i18n) or localization(i10n) purpose.

package.properties

lbl.user.fname=First Name
lbl.user.lname=Last Name
lbl.user.age=Age
lbl.user.place=Place
lbl.user.uname=Username
lbl.user.pwd=Password
lbl.acc.no=Account Number
lbl.acc.name=Account Name
lbl.acc.desc=Account Description
lbl.acc.type=Account Type
lbl.acc.opbal=Opening Balance
btn.login=Login
btn.reg=Register
btn.sou=Save / Update
btn.home=Home

global.properties

msg.user.invalid=Invalid Username or Password !
msg.user.notfound=A User with username "$1" not found !

Finally, the most indispensable configuration.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>Stringer</display-name>
	<welcome-file-list>
		<welcome-file>/redirect.jsp</welcome-file>
	</welcome-file-list>

	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>

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

<listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>
<listener>
    <listener-class>
      com.stringer.util.StringerListener
    </listener-class>
  </listener>
  
  <session-config>
  <session-timeout>600</session-timeout>
  </session-config>
  
</web-app>

Please note how struts filter and spring listener are configured up here. We could see a user defined listener, namely StringerListener, which has also been set up there.

Ok, finally all the configurations come to an end. Next we shall go to the source. First off, let’s see the welcome page.

redirect.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<META HTTP-EQUIV="Refresh" CONTENT="0;URL=index.htm">

Here, we are going to discuss the complete flow of user registration.

register.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Register</title>
</head>
<body>
	<fieldset style="width: 20%; background-color: lightyellow">
		<s:form action="saveOrUpdate" namespace="/User">
			<s:hidden name="user.id" />
			<s:hidden name="user.version" />
			<s:textfield name="user.firstName" key="lbl.user.fname" />
			<s:textfield name="user.lastName" key="lbl.user.lname" />
			<s:textfield name="user.userName" key="lbl.user.uname" />
			<s:password name="user.password" key="lbl.user.pwd" />
			<s:textfield name="user.age" key="lbl.user.age" />
			<s:textfield name="user.place" key="lbl.user.place" />
			<s:submit key="btn.sou" />
		</s:form>
	</fieldset>
</body>
</html>

UserPOJO.java

package com.stringer.pojo;

import com.opensymphony.xwork2.conversion.annotations.TypeConversion;

public class UserPOJO {
	private String firstName, lastName, userName, password, place;
	private int age;
	private Long id, salt, version;
	private Boolean isObsolete;

	public Boolean getIsObsolete() {
		return isObsolete;
	}

	public void setIsObsolete(Boolean isObsolete) {
		this.isObsolete = isObsolete;
	}

	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;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getPlace() {
		return place;
	}

	public void setPlace(String place) {
		this.place = place;
	}

	public int getAge() {
		return age;
	}

	@TypeConversion(converter = "com.stringer.util.IntegerConverter")
	public void setAge(int age) {
		this.age = age;
	}

	public Long getVersion() {
		return version;
	}

	public void setVersion(Long version) {
		this.version = version;
	}

	public Long getSalt() {
		return salt;
	}

	public void setSalt(Long salt) {
		this.salt = salt;
	}
}

There’s another class, namely UserDTO.java, which is used to transfer values between action and service.

UserDTO.java

package com.stringer.dto;

public class UserDTO {
	private String firstName, lastName, userName, password, place;
	private int age;
	private Long id, salt, version;
	private Boolean isObsolete;

	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;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getPlace() {
		return place;
	}

	public void setPlace(String place) {
		this.place = place;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public Long getVersion() {
		return version;
	}

	public void setVersion(Long version) {
		this.version = version;
	}

	public Long getSalt() {
		return salt;
	}

	public void setSalt(Long salt) {
		this.salt = salt;
	}

	public Boolean getIsObsolete() {
		return isObsolete;
	}

	public void setIsObsolete(Boolean isObsolete) {
		this.isObsolete = isObsolete;
	}

}

UserAction.java

package com.stringer.action;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.stringer.bo.UserBO;
import com.stringer.dto.UserDTO;
import com.stringer.pojo.FetchType;
import com.stringer.pojo.SortBy;
import com.stringer.pojo.SortOrder;
import com.stringer.pojo.UserPOJO;
import com.stringer.util.ApplicationUtils;

@Controller("UserAction")
@Scope("prototype")
public class UserAction extends BaseAction {

	private UserPOJO user = null;
	private UserDTO userDto = null;
	private @Autowired
	UserBO userBO;

	public UserPOJO getUser() {
		return user;
	}

	public void setUser(UserPOJO user) {
		this.user = user;
	}

	public String Register() {
		return CREATE;
	}

	public String Login() {
		return INPUT;
	}

	public String saveOrUpdate() throws StrutsActionException {
		try {
			userDto = ApplicationUtils.copyProperties(user, UserDTO.class);
			userBO.saveOrUpdate(userDto);
			if (isNull(session.get("loggedUser"))) {
				session.put("loggedUser", userDto);
			}
			return HOME;
		} catch (Exception e) {
			throw new StrutsActionException(e);
		}
	}

}

Here, UserAction.java works as a controller; see the highlighted line.

UserBO.java

package com.stringer.bo;

import com.stringer.dto.UserDTO;

public interface UserBO extends BaseBO {

	public void saveOrUpdate(final UserDTO userDTO) throws BOException;

}

It provides an interface to the Service layer.

UserBOImpl.java

package com.stringer.bo;

import java.io.Serializable;
import java.util.Collection;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.stringer.dao.UserDAO;
import com.stringer.dto.UserDTO;
import com.stringer.model.Account;
import com.stringer.model.User;
import com.stringer.pojo.FetchType;
import com.stringer.pojo.GenericPojo;
import com.stringer.pojo.SortBy;
import com.stringer.pojo.SortOrder;
import com.stringer.util.ApplicationUtils;

@Service("userBO")
@Transactional(value = "transactionManager", timeout = 30, readOnly = true, propagation = Propagation.REQUIRED, isolation = Isolation.SERIALIZABLE, rollbackFor = java.lang.Exception.class)
public class UserBOImpl extends BaseBOImpl implements UserBO {

	private User user = null;
	private @Autowired
	BaseDAO baseDAO;

	@Override
	@Transactional(readOnly = false)
	public void saveOrUpdate(final UserDTO userDTO) throws BOException {
		try {
			user = isNull(userDTO.getId()) ? ApplicationUtils
					.createInstance(User.class) : (User) userDAO
					.findEntityById(User.class, userDTO.getId());
			ApplicationUtils.copyProperties(userDTO, user);
			Long salt = ApplicationUtils.salt();
			user.setPassword(ApplicationUtils.uniquePassword(
					userDTO.getPassword(), salt));
			user.setSalt(salt);
			user.setIsObsolete(Boolean.FALSE);
			baseDAO.saveOrUpdate(user);
		} catch (Exception e) {
			throw new BOException(e);
		}
	}

}

This is the implementation class of UserBO.java.

BaseDAO.java

package com.stringer.dao;

package com.stringer.dao;

public interface BaseDAO {

	public <T> void saveOrUpdate(final T entity) throws DAOException;

}

}

This is an interface to the DAO layer.

BaseDAOImpl.java

package com.stringer.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;


@Repository("baseDAO")
public class BaseDAOImpl implements BaseDAO {

	private @Autowired
	SessionFactory sessionFactory;

	protected final Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	@Override
	public <T> void saveOrUpdate(final T obj) throws DAOException {
		try {
			getSession().saveOrUpdate(obj);
		} catch (Exception e) {
			throw new DAOException(e);
		}
	}

}

This is the implementation class of BaseDAO.java.

Finally the hibernate entity class,

User.java

package com.stringer.model;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Version;
import com.stringer.util.ApplicationConstants;

@Entity
@Table(name = ApplicationConstants.USER_TABLE, catalog = ApplicationConstants.CATALOG)
public class User implements Serializable {

	private String firstName, lastName, place, userName, password;
	private Integer age;
	private Long salt, id, version;
	private Boolean isObsolete;

	public void setIsObsolete(Boolean isObsolete) {
		this.isObsolete = isObsolete;
	}

	public Boolean getIsObsolete() {
		return isObsolete;
	}

	@Column(unique = true, nullable = false)
	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	@Column(unique = true, nullable = false)
	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Column(unique = true, nullable = false)
	public Long getSalt() {
		return salt;
	}

	public void setSalt(Long salt) {
		this.salt = salt;
	}

	@TableGenerator(name = ApplicationConstants.GENERATOR_NAME, table = ApplicationConstants.GENERATOR_TABLE, pkColumnName = ApplicationConstants.GENERATOR_PK_COLUMN_NAME, valueColumnName = ApplicationConstants.GENERATOR_VALUE_COLUMN_NAME, pkColumnValue = ApplicationConstants.USER_TABLE, allocationSize = ApplicationConstants.USER_ALOC_SIZE, initialValue = ApplicationConstants.USER_INIT_VALUE)
	@GeneratedValue(strategy = GenerationType.TABLE, generator = ApplicationConstants.GENERATOR_NAME)
	@Id
	@Column(unique = true, nullable = false, updatable = false)
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	@Column(nullable = false)
	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	@Column
	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	@Column
	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Column
	public String getPlace() {
		return place;
	}

	public void setPlace(String place) {
		this.place = place;
	}

	@Version
	public Long getVersion() {
		return version;
	}

	public void setVersion(Long version) {
		this.version = version;
	}
}

The folder structure and the list of libraries used are given below.

Stringer_1
Stringer_2

  • antlr-2.7.6
  • aopalliance
  • asm-3.2
  • asm-attrs
  • cglib-2.2.3
  • commons-beanutils-1.8.3
  • commons-collections-2.1.1
  • commons-fileupload-1.2.1
  • commons-io-1.3.2
  • commons-lang3-3.1
  • commons-logging-1.0.4
  • commons-logging-1.1.1
  • dom4j-1.6.1
  • ehcache-1.2.3
  • ejb3-persistence
  • freemarker-2.3.15
  • hibernate3
  • hibernate-annotations
  • hibernate-commons-annotations
  • hibernate-entitymanager
  • hibernate-tools
  • javassist
  • jdbc2_0-stdext
  • jta
  • log4j-1.2.14
  • mysql-connector-java-5.1.6-bin
  • ognl-2.7.3
  • spring-aop-3.2.1.RELEASE
  • spring-aspects-3.2.1.RELEASE
  • spring-beans-3.2.1.RELEASE
  • spring-build-src-3.2.1.RELEASE
  • spring-context-3.2.1.RELEASE
  • spring-context-support-3.2.1.RELEASE
  • spring-core-3.2.1.RELEASE
  • spring-expression-3.2.1.RELEASE
  • spring-instrument-3.2.1.RELEASE
  • spring-instrument-tomcat-3.2.1.RELEASE
  • spring-jdbc-3.2.1.RELEASE
  • spring-jms-3.2.1.RELEASE
  • spring-orm-3.2.1.RELEASE
  • spring-oxm-3.2.1.RELEASE
  • spring-struts-3.2.1.RELEASE
  • spring-test-3.2.1.RELEASE
  • spring-tx-3.2.1.RELEASE
  • spring-web-3.2.1.RELEASE
  • spring-webmvc-3.2.1.RELEASE
  • spring-webmvc-portlet-3.2.1.RELEASE
  • struts2-core-2.1.8.1
  • struts2-spring-plugin-2.1.8
  • xwork-core-2.1.6

Conclusion

So far we were going through an example which integrates struts, spring and hibernate frameworks. I hope all of you get to know the example well and expected to try out this.

Thanks.