You are on page 1of 24

Spring Framework 1

Spring Framework

Author: Debasish Roy (Debasish_Roy@infosys.com)

Date written (MM/DD/YY): 01/20/2006

Declaration:

I hereby declare that this document is based on my personal experiences. To the


best of my knowledge, this document does not contain any material that infringes
the copyrights of any other individual or organization including the customers of
Infosys.

-- Debasish Roy.

Project Details:

• Project involved : MHSPRPOC


• Application Type : J2EE
• Project Type : Development

Target readers: Developers

Keywords: J2EE, Spring, Hibernate, JSP, Taglibs, JSTL, tld


Spring Framework 2

Introduction:

The content of this document is not a detailed description on Spring or Hibernate.


This document contains how we have used Spring and Hibernate in our project. I
have shared most of the learning experiences I have gathered during execution of
the project here. Those who have some prior knowledge on J2EE framework would
be able to understand these. Our project got executed using JBoss-3.2 server and
Hibernate as back end. We have developed our codes in Eclipse-3 platform using
Spring framework. Finally the war file was deployed in Linux and it was platform
independent.

Spring’s MVC Architecture:

Spring’s MVC framework is designed based on Dispatcher Servlet which dispatches


requests to respective request-handlers better known as controllers.
Spring can bind any object as a command object which will be available directly in
the controller class. To do any validation of the form objects, you need a validation
class which is provided by this framework. After validation, if you want to send some
data to the JSP that can be done via referenceData method.
The controller class returns a view name (the JSP name) and a model Map. The
model contains all the bean names and corresponding objects you need to send to
the view. View names and it’s location is resolved via view Resolver bean provided in
the XML mapping.

Features of Spring:

• Clear separation of roles – controller, validator, command object, form object,


model object, Dispatcher Servlet, handler mapping, view resolver etc.
separate objects for each role.
• Powerful and straightforward configuration, easy referencing across contexts
of both framework and application classes as beans.
• Separate controllers for different scenarios – plain, form, wizard, simple,
multiaction.
• Customizable binding and validation – binding of any object is possible along
with validation after submission of form.
• Customizable handler/controller mapping and view resolver – can handle
simple requests via URLs or even can intercept a URL, and view resolvers help
to locate the actual path of views.
• Map model transfer – transfer of any number of objects is possible via model
object, no need to set them as request attributes.
• Supports Theme and JSTL tags with or without Spring tags.
Spring Framework 3

Dispatcher Servlet:

Spring's web MVC framework is a request-driven web MVC framework, designed


around a servlet that dispatches requests to controllers and offers other functionality
facilitating the development of web applications. Spring's DispatcherServlet does
that.

The Spring DispatcherServlet has a couple of special beans it uses, in order to be


able to process requests and render the appropriate views. These beans are included
in the Spring framework and can be configured in the WebApplicationContext, just as
any other bean would be configured. Right now, we'll just mention some of them. For
most of the beans, defaults are provided so you don't have to worry about
configuring them.

• handler mappings – for matching the URL and send them to a controllers
• controllers – the actual controller beans
• view resolver – to find the exact location of the view (JSP)
• theme resolver – capable of resolving themes for the application
• handlerexceptionresolver – offers functionality to map different exceptions

BeanFactory and ApplicationContext:

The BeanFactory is the Spring’s bean container which loads and wires bean at the
initial time and supply them when requested for. The ApplicationContext is a
BeanFactory which does this work. You can have separate xml files for defining beans
or can have a file such as an applicationContext.xml file to define all bean definition.
We have used Spring’s Dispatcher Servlet test-servlet.xml as a bean factory which
imports all other xml into it during initialization and loads all beans into the
ApplicationContext.

Controllers:

Controllers are classes that interpret user input data or handles requests and send a
model along with the view to the client after doing some customized processing.
Every controller class actually returns a ModelAndView type of object. Controllers
even can forward or redirect the request to a URL.

Among various types of controllers we have used:


• Controller – Default and the simplest form of controllers, when no form data
is required to be handled at all
• SimpleFormController – For handling a single request by a controller
• MultiActionController – For handling different requests by a single
controller
Spring Framework 4

web.xml
Whatever request comes from the client side first reaches to web.xml. This file was
kept in WEB-INF. This file was mapped with the Spring Dispatcher Servlet named
as test-servlet.xml as in our project (You can change the first part “test”):
<servlet>
<servlet-name>test</servlet-name>
<servlet-class> org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

Even you can set the context configuration inside test-servlet.xml as:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/test-servlet.xml</param-value>
</context-param>

<listener>
<listener-class> org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

Next is how the web.xml will handle different types of request. This can be mapped
as:
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
The syntax says that any request which ends with .do will be handled by test-
servlet that is described by test-servlet.xml.

To set the index file, the first jsp to be loaded from the application, can be set as:
<welcome-file-list>
<welcome-file>
index.jsp
</welcome-file>
</welcome-file-list>
In the above case index.jsp file is to be placed directly under the application folder.
This jsp redirects the url to another request as:
<%--
Redirected because we can't set the welcome page to a virtual URL.
--%>
<core:redirect url="./login.do"/>
Spring Framework 5

To include the taglibs (Java Standard Tag Library) into your jsp first add the
following lines into the web-xml:
<taglib>
<taglib-uri>http://java.sun.com/jstl/fmt</taglib-uri>
<taglib-location>/WEB-INF/fmt.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>http://java.sun.com/jstl/core-rt</taglib-uri>
<taglib-location>/WEB-INF/c-rt.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>http://java.sun.com/jstl/sql</taglib-uri>
<taglib-location>/WEB-INF/sql.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>http://java.sun.com/jstl/sql-rt</taglib-uri>
<taglib-location>/WEB-INF/sql-rt.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>http://java.sun.com/jstl/x</taglib-uri>
<taglib-location>/WEB-INF/x.tld</taglib-location>
</taglib>

<taglib>
<taglib-uri>http://java.sun.com/jstl/x-rt</taglib-uri>
<taglib-location>/WEB-INF/x-rt.tld</taglib-location>
</taglib>

To include spring tags include the following lines:


<taglib>
<taglib-uri>/spring</taglib-uri>
<taglib-location>/WEB-INF/spring.tld</taglib-location>
</taglib>

We have used only a few of them in our project (core and fmt tags). Before you use
this tags in your jsp, you must place those .tld files in WEB-INF.
Spring Framework 6

Spring’s Dispatcher Servlet: test-servlet.xml


You can break your xml files as you wish and can import all of them in test-
servlet.xml so that during initialization of the application all of them will be loaded by
the server as:
<import resource="/service.xml"/>
<import resource= "classpath:/com/test/testproject/spring/admin/xyz.xml"/>

You have to give the url Mappings for different request types you want to handle by
this servlet as:
<bean id="urlMapping1" class=
"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="*Login.do">loginController</prop>
</props>
</property>
</bean>

The above syntax means, whatever request comes containing text Login.do will be
handled by the bean loginController. Bean loginController can be defined there as
<bean id="loginController" class=
"com.test.testproject.spring.common.LoginController">
<property name="methodNameResolver">
<ref bean="loginMethodNameResolver"/>
</property>
<property name="commonUtil">
<ref bean="commonUtil"/>
</property>
</bean>

<bean id="loginMethodNameResolver" class=


"org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<prop key="/Login.do">login</prop>
<prop key="/LoginSubmit.do">formSubmit</prop>
</props>
</property>
</bean>

In this definition, bean id is the name of the bean which should be unique among
all application xml files. Class signifies the location of the actual java file.
There are mainly two types of controllers which can process request in Spring –
SimpleFormController and MultiActionController. SimpleFormControllers are the
controllers can handle only one type of request where as MultiActionControllers can
handle different types of request. Here loginController, which extends
MultiActionController, is a MultiActionControllers. In a MultiActionController like
loginController there are different methods to handle different requests. To map
between them a property provided by Spring “methodNameResolver“ is there which
tells the Controller which method is to be invoked for a given request. Here that
method name resolver bean is “loginMethodNameResolver”. It tells that if request
type is “/Login.do” then go to “login” method in the loginController and for
“/LoginSubmit.do” request go to “formSubmit” method.
Spring Framework 7

There are a lot of mappings of this kind which we have placed in other xml files and
then all of them are imported in this test-servlet.xml. This type of break up will help
in maintaining the changes in these files.

We have discussed mapping required for MultiActionController above. Following is the


example of a SimpleFormController mapping:
<bean id="urlMapping5" class=
"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="test/update.do">updateController</prop>
</props>
</property>
</bean>
This controller, which extends SimpleFormController, handles request
“test/update.do” only.

Below is the example of a Controller, other than SimpleFormController and


MultiAction Controller:
<bean id="urlMapping11" class=
"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="ForgotPassword.do">forgotPasswordController</prop>
</props>
</property>
</bean>

<bean id="forgotPasswordController" class=


"com.test.testproject.spring.common.ForgotPasswordController">
</bean>
This “forgotPasswordController” handles only one request ”ForgotPassword.do”. This
controller, which implements Controller Interface, only redirects the request to
another controller or returns a simple model which contains nothing. We will see this
Controller class later.
Spring Framework 8

Inversion of Control (IOC):


The basic concept of Inversion of Control is, you don't create your objects, and you
describe how they should be created. You don't directly connect your components
and services together in code, you describe which services are needed by which
components, and the container is responsible for hooking it all together. The
container creates all the objects, wires them together by setting the necessary
properties, and determines when methods are invoked. Nowadays this is known as
Dependency Injection.
[http://jakarta.apache.org/hivemind/ioc.html]

There are three main styles of dependency injection. The names used for them are
Constructor Injection, Setter Injection, and Interface Injection.
[http://www.martinfowler.com/articles/injection.html]

CommonUtil is a class defined by the bean named as commonUtil and is a property


of the class LoginController as:
<bean id="loginController" class=
"com.test.testproject.spring.common.LoginController">
<property name="methodNameResolver">
<ref bean="loginMethodNameResolver"/>
</property>
<property name="commonUtil">
<ref bean="commonUtil"/>
</property>
</bean>

To get an instance of this class, this class is defined in the loginController as:
private CommonUtil commonUtil;
There is a setter method also to set this as:
public void setCommonUtil (CommonUtil paramCommonUtil)
{
this.commonUtil = paramCommonUtil;
}
After this we can refer to any method of this class from loginController. This is known
as InversionOfControl (IOC). The bean CommonUtil is defined in another xml as:
<bean id="commonUtil" class= "com.test.testproject.spring.common.CommonUtil" >
</bean>
You can set this class as singleton by writing singleton=true or if you don’t want
then write singleton=false. By default it is a singleton class. Singleton means, only
one instance of this class will be created and will be shared by all other classes.
Another thing is that, suppose CommonUtil is an Interface and it is implemented by
two classes ClassA and ClassB. In that case if you want to invoke methods defined in
ClassA you can do it by changing the bean commonUtil as following:
<bean id="commonUtil" class= "com.test.testproject.spring.common.ClassA" >
</bean>
You need not change your Java Class where from you are accessing the ClassA. So
powerful is Spring IOC.
Spring Framework 9

The various layers used in the project were mainly divided into:

Layered Architecture

Spring Support Services

Data
Presentation Business
Servlet

Access
(Spring MVC) Services
Objects
Controller Service DAO

Data Objects

Spring Persistence Framework

Hibernate ORM
Spring Framework 10

Flow among different Layers:


Controller  Service  BusinessComponent (BC) 
DataAccessObject(HibernateDao).
Service will implement Interface of Service. HibernateDao implements Interface of
Dao. DataObject s (DOs) are classes which actually used as beans and contains
actual data from one layer to another. A DO is a structure like class having some user
defined attributes or properties along with their setter-getter methods.

Controller will invoke a method of any Service Interface by IOC (IAdminService). This
is necessary for invoking Declarative Transaction in Spring.
[http://www.springframework.org/docs/reference/transaction.html]

The multi action controller can be defined as:


<bean id="testViewController" class=
"com.test.testproject.spring.controller.TestViewController">
<property name="methodNameResolver">
<ref bean="testMethodNameResolver"/>
</property>
<property name="testService" ref="TestServiceTx"/>
<property name="commonUtil" ref="commonUtil"/>
</bean>

<bean id="testMethodNameResolver" class=


"org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<prop key="/test/viewRole.do">loadRoleView</prop>
<prop key="/test/viewAdmin.do">loadAdminView</prop>
</props>
</property>
</bean>

In the above sample code, testService is defined in the TestViewController as an


ITestService Interface. The property names as “target” is the actual class
(TestService) which implements the ITestService Interface. The TestServiceTX is the
bean required for Declarative Transaction which can be defined as:
<bean id="TestServiceTx" class=
"org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>
com.test.testproject.service.ITestService
</value>
</list>
</property>
<property name="proxyTargetClass"><value>true</value></property>
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref=
"com.test.testproject.service.AdminService"/>
<property name="transactionAttributes">
<props>
<prop key="create*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
Spring Framework 11

<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED, readOnly</prop>
</props>
</property>
</bean>

When a method of interface ITestService gets called, it checks for the method name.
If the method name starts with create then it behaves accordingly. You can set that
property as your requirement. PROPAGATION_REQUIRED is done for methods having
database related operations. Otherwise it is readOnly mode. When you invoke a
method of the ITestService interface, it will go to the TestService Class. This class will
call a method of the Business Component (BC) by IOC.
TestService bean is defined as:
<bean id="com.test.testproject.service.TestService"
class="com.test.testproject.service.TestService">
<property name="testBC">
<ref bean="com.test.testproject.service.TestBC"/>
</property>
</bean>

TestBC is defined as:


<bean id="com.test.testproject.service.TestBC"
class="com.test.testproject.service.AdminBC">
<property name="daoRegistry">
<ref bean="testDaoRegistry"/>
</property>
</bean>

AdminBC invokes respective HibernateDao. But instead of calling a method of a


HibernateDao directly, it does so using IOC as:
<bean id="testDaoRegistry"
class="com.testproject.common.orm.SimpleDaoRegistry">
<property name="registry">
<map>
<entry key="com.test.testproject.data.dao.ITestDao">
<ref bean="com.test.testproject.data.dao.TestHibernateDao"/>
</entry>
</map>
</property>
</bean>

Where as the TestHibernateDao bean can be defined as:


<bean id="com.test.testproject.data.dao.TestHibernateDao"
class="com.test.testproject.data.dao.TestHibernateDao">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>

Session Factory will be discussed later.


TestBC defines a property and its getter-setter method as:
private DaoRegistry daoRegistry;
public DaoRegistry getDaoRegistry()
Spring Framework 12

{
return daoRegistry;
}
public void setDaoRegistry(DaoRegistry paramDaoRegistry)
{
this.daoRegistry = paramDaoRegistry;
}

TestBC calls a method of a HibernateDao as:


public ArrayList getUserList() throws NoRecordsFoundException
{
ITestDao testHibernateDao = (ITestDao) getDaoRegistry().
getDao(ITestDao.class.getName());
return testHibernateDao.getUserList();
}

Inside HibernateDao you can write a method as:


private static final String IS_ACTIVE_TRUE = "Y";
private static final String IS_ACTIVE_FALSE = "N";
private static final String DATA_CLASS_NAME = TestDO.class.getName();
private static final String GET_ALL_QUERY = "from " + DATA_CLASS_NAME +
" as testDO where testDO.isActive = '"+ IS_ACTIVE_TRUE +"'";
private static final String ORDER_BY_USERID = " order by testDO.userId";
private static final String DELETE_USER = "update "+DATA_CLASS_NAME+" set " +
" isActive = :strSetIsActive where userId = :strUserId and isActive = :strIsActive";

public ArrayList getUserList() throws NoRecordsFoundException


{
//Getting list of all the Users
ArrayList listUsers = (ArrayList) getHibernateTemplate().find (GET_ALL_QUERY
+ ORDER_BY_USERID);

//If No User Found throw Exception else returning the User List
if (listUsers.size() == 0)
{
Collection context = new Vector();
context.add(GET_ALL_QUERY + ORDER_BY_USERID);
throw new NoRecordsFoundException(
ErrorConstants.EXCEPTION_NO_USER_RECORD_FOUND, context);
}
else
{
return listUsers;
}
}

public boolean deleteUser(TestDO testDO)


{
//Declaring a hibernate Session and Beginning a Transaction
Session session = getSession();

//Query To be Executed
Query hqlQuery = null;
Spring Framework 13

//Query for Updating the User Record


hqlQuery = session.createQuery(DELETE_USER);

//Setting Parameters to Update Query


hqlQuery.setString ("strSetIsActive", IS_ACTIVE_FALSE);
hqlQuery.setString ("strUserId", userDO.getUserId());
hqlQuery.setString ("strIsActive", IS_ACTIVE_TRUE);

//Executing the Update Query


int updatedEntries = hqlQuery.executeUpdate();

switch(updatedEntries)
{
case 0: return false;
default: return true;
}
}

The TestDO class is defined as:


private String userId;
private String password;
private String userName;
private String providerId;
Other parameters are also there and also their setter-getter methods.

TestDO class is mapped in Test.hbm.xml as following:


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.test.testproject.data.dataobject.TestDO" table="TEST_TABLE"
dynamic-update="true" optimistic-lock="all" select-before-update="true">
<cache usage="read-write"/>
<id name="userId" column="USER_ID"><generator class="assigned"/></id>
<property name="userName" column="USER_NAME"/>
<property name="password" column="PASSWORD"/>
<property name="roleId" column="ROLE_ID"/>
<property name="isActive" column="IS_ACTIVE"/>
<property name="createdBy" column="CREATED_BY"/>
<property name="createdDate">
<column name="CREATED_DATE" sql-type="Date"/>
</property>
<property name="lastModifiedBy" column="LAST_MODIFIED_BY"/>
<property name="lastModifiedDate">
<column name="LAST_MODIFIED_DATE" sql-type="Date"/>
</property>
</class>
</hibernate-mapping>

To generate an hbm.xml file open Hibernator view from Show View and right click
there and click to save it.
Spring Framework 14

Service.xml:
This xml has some common components which are required across all the modules in
the application. This contains information regarding
bootstrapConfigFactory as:
<bean id="bootstrapConfigFactory" class=
"com.test.common.config.BootstrapConfigFactory"/>
<bean id="bootstrapConfig" factory-bean="bootstrapConfigFactory" factory-
method="getConfig"/>

ConnectionPoolName as:
<bean id="defaultConnectionPoolName" class=
"com.test.common.sql.ConnectionPoolManager" factory-method=
"getDefaultPoolName">
<constructor-arg>
<ref bean="bootstrapConfig"/>
</constructor-arg>
</bean>

DataSource as:
<bean id="dataSource" class= "com.test.common.sql.ConnectionPoolManager"
factory-method= "getConnectionPool" destroy-method="close">
<constructor-arg>
<ref bean="defaultConnectionPoolName"/>
</constructor-arg>
</bean>

SessionFactory as:
<bean id="sessionFactory" class=
"com.test.common.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource"><ref bean="dataSource"/></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key= "hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>
/com/test/testproject/data/dataobject/Test.hbm.xml
</value>
<value>
/com/test/testproject/data/dataobject/Testabc.hbm.xml
</value>
</list>
</property>
</bean>
Spring Framework 15

Mapping Resources are the mapped hibernate xml files which are mapped with the
database and which are required to gather data from database. Those xml files
contain the mapping that is how a data object is mapped with a database table.

TransactionManager as:
<bean id="transactionManager" class=
"org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>

Declarative Transaction as:


[http://www.springframework.org/docs/reference/transaction.html]
<bean id="TestServiceTx" class=
"org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>
com.test.testproject.service.ITestService
</value>
</list>
</property>
<property name="proxyTargetClass"><value>true</value></property>
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref=
"com.test.testproject.service.AdminService"/>
<property name="transactionAttributes">
<props>
<prop key="create*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>

View Resolver as:


<bean id="viewResolver" class=
"org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
<property name="prefix"><value>/WEB-INF/jsp/</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean>
ViewResolver Property is necessary for mapping proper jsp from the controller. For
the above example, suppose the controller returns a view as
“common/ForgotPassword”. This means the actual location of the jsp is:
/WEB-INF/jsp/ common/ForgotPassword.jsp
Thus the controller gets the actual location of a jsp.
Spring Framework 16

Controller:
This controller only redirects the request to another controller or returns a simple
model which contains nothing:
public class ForgotPasswordController implements Controller
{
public ModelAndView handleRequest(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws Exception
{
return new ModelAndView("common/ForgotPassword");
}
}

MultiActionController:
public class TestViewController extends MultiActionController
{
private ITestService testService;
private CommonUtil commonUtil;

public void setTestService (TestService paramTestService)


{
this.testService = paramTestService;
}

public void setCommonUtil (CommonUtil paramCommonUtil)


{
this.commonUtil = paramCommonUtil;
}

public ModelAndView loadAdminView(HttpServletRequest httpServletRequest,


HttpServletResponse httpServletResponse) throws Exception
{
//Declaring variables
Map model = new HashMap();
ArrayList listUsers = new ArrayList();

//Getting user list from Database


listUsers = testService.getUserList();

//Adding variables to Model and Setting into Request


model.put("listUsers", listUsers);

//Getting ModelAndView
ModelAndView modelAndView = commonUtil.getModelAndView(model,
httpServletRequest, PresentationConstants.SID_ADMINISTRATOR,
PresentationConstants.JSP_ADMIN_MAIN);

//Returning ModelAndView
return modelAndView;
}
}

ModelAndView is the object which will contain the JSP name and a hash map which
will contain the parameters you want to send to the view object i.e., to the JSP.
Spring Framework 17

You can redirect to another url instead of returning a ModelAndView as:


//Returning ModelAndView
return new ModelAndView("redirect: ./viewABC.do",
"message", message);

The url mapping for this controller is as:


<bean id="urlMapping3" class=
"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/test/view*.do">testViewController</prop>
<prop key="/test/delete*.do">testViewController</prop>
</props>
</property>
</bean>

The bean definition for this controller is as:


<bean id="testViewController" class=
"com.test.testproject.spring.controller.TestViewController">
<property name="methodNameResolver">
<ref bean="testMethodNameResolver"/>
</property>
<property name="testService" ref="TestServiceTx"/>
<property name="commonUtil" ref="commonUtil"/>
</bean>

<bean id="adminMethodNameResolver" class=


"org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<prop key="/test/viewRole.do">loadRoleView</prop>
<prop key="/test/viewAdmin.do">loadAdminView</prop>
</props>
</property>
</bean>
Spring Framework 18

SimpleFormController:
public class UpdateController extends SimpleFormController
{
//default Constructor
public UpdateController()
{
setValidateOnBinding(false);
setSessionForm(true);
setBindOnNewForm(true);
}
private ITestService testService;
public void setTestService(ITestService paramTestService)
{
this.testService = paramTestService;
}
protected ModelAndView onSubmit(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Object command,
BindException bindException) throws Exception
{
//Binding elements with request object
TestDO testDO = (TestDO) command;
//Update Operation
String message = updateTestDO(testDO);
//Adding variables to Model and Setting into Request
model.put("message", message);

//Returning ModelAndView
ModelAndView modelAndView = commonUtil.getModelAndView(model,
httpServletRequest, screenId, PresentationConstants.JSP_VIEW_USER);
return modelAndView;
}
}

There are some things to understand here. First is the use of Command Object and
Form Validator in Spring. The command object will contain all the values of an
object which is bound by Spring’s bind tag. We’ll discuss how to bind an object
later. In the above piece of code, the bind object was testDO and so we have type
casted command object into TestDO. We have to mention the command object and
its class in the bean definition of the Controller.

The Validator class will validate each and every form elements of the form submitted.
If any one of the validation fails, then it will go to the form view of the Controller
else it will go to the success view.
The url mapping for this controller is as:
<bean id="urlMapping5" class=
"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="test/update.do">updateController</prop>
</props>
</property>
</bean>
Spring Framework 19

The bean definition for the above simple form controller along with its Validator class
is as following:
<bean id="updateController" class=
"com.test.testproject.spring.controller.UpdateController">
<property name="sessionForm"><value>true</value></property>
<property name="commandName"><value>testDO</value></property>
<property name="commandClass">
<value>com.test.testproject.data.dataobject.TestDO</value>
</property>
<property name="validator" ref="testValidator"/>
<property name="formView">
<value>test/testFormView</value>
</property>
<property name="successView">
<value>test/testSucessView</value>
</property>
<property name="testService" ref="TestServiceTx"/>
<property name="commonUtil" ref="commonUtil"/>
</bean>

<bean id="testValidator" class=


"com.test.testproject.spring.common.validator.TestValidator">
</bean>

The Validator class may be look like:


public class TestValidator implements Validator
{
public boolean supports(Class clazz)
{
return clazz.equals(TestDO.class);
}
public void validate(Object object, Errors errors)
{
TestDO testDO = (TestDO) object;
commonUtil commonUtil = commonUtil.getInstance();

//Checking whether any mandatory field is blank or not


ValidationUtils.rejectIfEmptyOrWhitespace(errors, "userId",
"required.userId", PresentationConstants.
ERROR_EMPTY_USER_ID);
//Checking for special characters in UserID
if (presentationUtil.containsSpecialChar(testDO.getUserId()))
{
errors.reject("userId",
PresentationConstants.ERROR_SPECIAL_CHAR_IN_USERID);
}
}
}

If you want to validate something which is not present in the object you are sending
in validate method of the Validator class then also you can put that validation in the
method onBindAndValidate. From this method you have to call the Validator. After
that you can put additional validations also as following:
Spring Framework 20

protected void onBindAndValidate(HttpServletRequest httpServletRequest,


Object command, BindException bindException) throws Exception
{
//Binding Command object
TestDO testDO = (TestDO) command;

//Declaring Variables
String validatePassword = (String) httpServletRequest.
getParameter("validatePassword");

//Calling Validator class for Validating TestDO


getValidator().validate(command, bindException);
bindException.setNestedPath("");
//Checking whether password and validatePassword are same
if (null != testDO.getPassword() && null !=
validatePassword && !testDO.getPassword().trim().
equals(validatePassword.trim()))
{
bindException.reject
("password", PresentationConstants.ERROR_PASSWORD_MISMATCH);
}

super.onBindAndValidate(httpServletRequest, command, bindException);


}

If any error is there after validation, still then if you want to send some data in the
form view then you can put that in the referenceData method which will be called
after validation if there is some error present as:
protected Map referenceData(HttpServletRequest httpServletRequest,
Object command, Errors errors) throws Exception
{
//Binding elements with request object
TestDO testDO = (TestDO) command;
String message = PresentationConstants.MSG_USER_UPDATE_FAILED;

//Declaring variables
Map model = new HashMap();
ArrayList roleList = new ArrayList();

//Getting and Setting List of Roles


roleList = (ArrayList) adminService.getRoleList();

//Adding variables to Model and Setting into Request


model.put("message", message);
model.put("roleList", roleList);
httpServletRequest.setAttribute("testDO", testDO);

//Setting model into session


httpServletRequest.setAttribute("model", model);
return super.referenceData(httpServletRequest, command, errors);
}
Spring Framework 21

Spring’s Bind and Special JSP Tags:


Use of Spring’s bind tag in Simple as well as Multi Action Controller is the next
interesting thing. You can bind an object of your own (any Class for example TestDO)
in the JSP using bind tag. Binding an object means you will directly get the values of
the attributes of the bind object in the controller, you don’t have to do
getParameter() for getting those values. For this, the object you want to bind must
be set in the HttpServletRequest so that it will be available in the jsp as:
//Setting bind object into request
httpServletRequest.setAttribute("testDO", testDO);
To bind some or each fields of this object in the jsp what you have to do is:

<spring:bind path="testDO.userId">
<input type="text" class="normalinput" name="userId" size="22" maxlength="15"
value="<core:out value="${status.value}"/>">
</spring:bind>

<spring:bind path="testDO.password">
<input type="password" class="normalinput" name="password" size="22"
maxlength="15" value="<core:out value="${status.value}"/>">
</spring:bind>

<spring:bind path="testDO.userName">
<input type="text" class="normalinput" name="userName" size="22"
maxlength="50" value="<core:out value="${status.value}"/>">
</spring:bind>

Where “<core:out value="${status.value}"/>” is the value coming from the testDO.


Whatever value is being entered from this jsp into those fields, will be available in
the bind object as testDO.

To print the errors in the jsp, coming after validation you can give:

<spring:bind path="testDO.*">
<table class="normal" width="40%" align="center">
<core:forEach var="error" items="${status.errorMessages}">
<tr><td class="warn" height="20px">
<fmt:message key="${error}"/>
</td></tr>
</core:forEach>
</table>
</spring:bind>

Where “<core:out value="${status.errorMessages}"/>” is the error messages which


we are setting in a local variable error.
The tag <fmt:message key="${error}"/> is used to print some text, which is
mapped in the message.properties file. Suppose, we want to print “User ID can not
be blank” message in the jsp. We can put the message with a key word in the
message.properties file as:
error.emptyuserid=User ID can not be blank
And when you find this error in the Validator, you can put the error code
error.emptyuserid instead of full error message, in the Errors or Exception object
which will be sent to the jsp. The tag will be responsible for getting the full message
Spring Framework 22

based on the key as error. So you can change the message in the properties file if
you want.

Respective mapping for message.properties, which is placed in the application


folder directly, is done in Dispatcher Servlet as:
<bean id="messageSource" class=
"org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename"><value>messages</value></property>
</bean>
Value specifies the file name (messages in this case) which contains all messages.

If you want to print all the validations besides each field, it can also be possible as:

<spring:bind path="testDO.userName">
<input type="text" class="normalinput" name="userName" size="22"
maxlength="50" value="<core:out value="${status.value}"/>">
<core:if test="${not empty status.errorMessage}">
<font class="warn"><b>
<core:out value="${status.errorMessage}"/>
</b></font>
</core:if>
</spring:bind>

Before using this in your JSP, you have to include all the tags as:
<%@ taglib prefix="core" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

The tag core:out is used to print some value in the jsp. The syntax should be
followed exactly as it is. The tag core:if is used to check some if-else condition. If
test=true, then it will execute the inner code. You can do looping, for example to
print a select dropdown box as following:

<select name="Role">
<option value="0"> Select </option>
<core:forEach items="${model.roleList}" var="roleDO">
<core:choose>
<core:when test="${testDO.roleId == roleDO.roleId}">
<option value="<core:out value="${roleDO.roleId}"/>" selected>
<core:out value="${roleDO.roleName}"/>
</option>
</core:when>
<core:otherwise>
<option value="<core:out value="${roleDO.roleId}"/>">
<core:out value="${roleDO.roleName}"/>
</option>
</core:otherwise>
</core:choose>
</core:forEach>
</select>
Spring Framework 23

To explain this I have to start from the controller. We have returned a ModelAndView
object where there is a model object in it which we have sent to the jsp. We have set
the roleList in the model after getting the ArrayList of roles from database.
//Getting and Setting List of Roles
ArrayList roleList = (ArrayList) adminService.getRoleList();

//Adding variables to Model and Setting into Request


model.put("roleList", roleList);

In the jsp, we are getting the roleList as model.roleList. No need to do


model.get(“roleList”) to get the roleList.

To format a given quantity, which as date we can use the fmt tag as following:
<fmt:formatDate value="${model.serviceDate}" pattern="MM/dd/yyyy"
type="date"/>
This way you can try other patterns also, not only date but also currency, integer etc
also you can format.

Themes:

You can keep your css, images in a single folder spring which is to be placed inside
another folder themes. The folder themes was placed in the application folder
directly. To use those images and to include the css you need a property file called
spring.properties which will contain the links for each images you want to use and
the css file you want to include as:
css=/themes/standard.css
img-Login=/themes/login.gif
img-Alert=/themes/alert.gif

Finally, to include the css in your jsp you have to do:


<core:set var="css"><spring:theme code="css"/></core:set>
<core:if test="${not empty css}">
<link rel="stylesheet" href="<core:url value="${css}"/>" type="text/css"
/></core:if>

You can import multiple css and change the variable name “css” of course if you
want. You can use the images in your jsp as below:
<core:set var="alert"><spring:theme code="img-Alert"/></core:set>
<img src=<core:url value="${alert}"/>>

Respective mapping for spring.properties, which is placed in the application folder


directly, is done in Dispatcher Servlet as:
<bean id="themeResolver" class=
"org.springframework.web.servlet.theme.CookieThemeResolver">
<property name="defaultThemeResolver" value=spring/>
</bean>
Value specifies the folder name (spring in this case) which is inside the themes
folder.
Spring Framework 24

Error JSP:

You can customize your error.jsp page for error code 404, 500 etc. To set this put
your error.jsp page in your application and add the following lines into web.xml:
<error-page>
<error-code>500</error-code>
<location>/error.jsp</location>
</error-page>

<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>

In the above case error.jsp file is to be placed directly under the application folder.
One more thing is that, your error.jsp should be at least of 512 bytes, otherwise
it will not work. Add this line in the error.jsp:
<%@ page isErrorPage="true" %>

To get the application path you can use <%=request.getContextPath()%> to get


the application root directory in the jsp.

Click here to download the application.

Reference: http://www.springframework.org/docs/reference/

You might also like