Professional Documents
Culture Documents
Unit-5 - Web Technology Ece
Unit-5 - Web Technology Ece
UNIT- V
MVC Architecture
In this section, you will get an overview of MVC architecture. The MVC
architectural pattern has existed for a long time in software engineering. All
most all the languages use MVC with slight variation, but conceptually it
remains the same.
MVC stands for Model, View and Controller. MVC separates application into
three components - Model, View and Controller.
Model: Model represents shape of the data and business logic. It maintains
the data of the application. Model objects retrieve and store model state in a
database.
View: View is a user interface. View display data using model to the user
and also enables them to modify the data.
Controller: Controller handles the user request. Typically, user interact with
View, which in-turn raises appropriate URL request, this request will be
handled by a controller. The controller renders the appropriate view with the
model data as a response.
The following figure illustrates the interaction between Model, View and
Controller.
MVC Architecture
The following figure illustrates the flow of the user's request in ASP.NET
MVC.
Request/Re
sponse in MVC Architecture
As per the above figure, when the user enters a URL in the browser, it goes
to the server and calls appropriate controller. Then, the Controller uses the
appropriate View and Model and creates the response and sends it back to
the user. We will see the details of the interaction in the next few sections.
Points to Remember :
1. MVC stands for Model, View and Controller.
2. Model is responsible for maintaining application data and business
logic.
Benefits
JSF reduces the effort in creating and maintaining applications, which will run on a
Java application server and will render application UI on to a target client. JSF
facilitates Web application development by −
1 Model
Carries Data and login
2 View
Shows User Interface
Controller
3
Handles processing of an application.
The purpose of MVC design pattern is to separate model and presentation enabling
developers to focus on their core skills and collaborate more clearly.
Web designers have to concentrate only on view layer rather than model and controller
layer. Developers can change the code for model and typically need not change view
layer. Controllers are used to process user actions. In this process, layer model and
views may be changed.
JSF Architecture
JSF application is similar to any other Java technology-based web application; it runs
in a Java servlet container, and contains −
JavaBeans components as models containing application-specific functionality and data
A custom tag library for representing event handlers and validators
A custom tag library for rendering UI components
UI components represented as stateful objects on the server
Server-side helper classes
Validators, event handlers, and navigation handlers
Application configuration resource file for configuring application resources
There are controllers which can be used to perform user actions. UI can be created by
web page authors and the business logic can be utilized by managed beans.
JSF provides several mechanisms for rendering an individual component. It is upto the
web page designer to pick the desired representation, and the application developer
doesn't need to know which mechanism was used to render a JSF UI component.
JSF provides a standard HTML tag library. These tags get rendered into corresponding
html output.
For these tags you need to use the following namespaces of URI in html node.
<html
xmlns = "http://www.w3.org/1999/xhtml"
xmlns:h = "http://java.sun.com/jsf/html">
Following are the important Basic Tags in JSF 2.0.
h:inputText
1
Renders a HTML input of type="text", text box.
h:inputSecret
2
Renders a HTML input of type="password", text box.
h:inputTextarea
3
Renders a HTML textarea field.
h:inputHidden
4
Renders a HTML input of type="hidden".
h:selectBooleanCheckbox
5
Renders a single HTML check box.
h:selectManyCheckbox
6
Renders a group of HTML check boxes.
h:selectOneRadio
7
Renders a single HTML radio button.
h:selectOneListbox
8
Renders a HTML single list box.
h:selectManyListbox
9
Renders a HTML multiple list box.
h:selectOneMenu
10
Renders a HTML combo box.
h:outputText
11
Renders a HTML text.
h:outputFormat
12
Renders a HTML text. It accepts parameters.
h:graphicImage
13
Renders an image.
14 h:outputStylesheet
Includes a CSS style sheet in HTML output.
h:outputScript
15
Includes a script in HTML output.
h:commandButton
16
Renders a HTML input of type="submit" button.
h:Link
17
Renders a HTML anchor.
h:commandLink
18
Renders a HTML anchor.
h:outputLink
19
Renders a HTML anchor.
h:panelGrid
20
Renders an HTML Table in form of grid.
h:message
21
Renders message for a JSF UI Component.
h:messages
22
Renders all message for JSF UI Components.
f:param
23
Pass parameters to JSF UI Component.
f:attribute
24
Pass attribute to a JSF UI Component.
f:setPropertyActionListener
25
Sets value of a managed bean's property.
JSF - Facelets Tags
JSF provides special tags to create common layout for a web application called
facelets tags. These tags provide flexibility to manage common parts of multiple pages
at one place.
For these tags, you need to use the following namespaces of URI in html node.
<html
xmlns = "http://www.w3.org/1999/xhtml"
xmlns:ui = "http://java.sun.com/jsf/facelets">
Following are important Facelets Tags in JSF 2.0.
Templates
1 <ui:insert>
<ui:define>
<ui:include>
<ui:composition>
Parameters
We'll demonstrate how to pass parameters to a template file using the following tag
2
<ui:param>
Custom
3
We'll demonstrate how to create custom tags
Remove
4
We'll demonstrate capability to remove JSF code from generated HTML page
f:convertNumber
1
Converts a String into a Number of desired format
f:convertDateTime
2
Converts a String into a Date of desired format
Custom Convertor
3
Creating a custom convertor
f:validateLength
1
Validates the length of a string
f:validateLongRange
2
Validates the range of a numeric value
f:validateDoubleRange
3
Validates the range of a float value
f:validateRegex
4
Validates JSF component with a given regular expression
Custom Validator
5
Creates a custom validator
Step Description
1 composite:interface
Declares configurable values to be used in composite:implementation.
2 composite:attribute
Configuration values are declared using this tag.
composite:implementation
3
Declares JSF component. Can access the configurable values defined in composite:interface using
#{cc.attrs.attribute-name} expression.
<composite:interface>
<composite:attribute name = "usernameLabel" />
<composite:attribute name = "usernameValue" />
</composite:interface>
<composite:implementation>
<h:form>
#{cc.attrs.usernameLabel} :
<h:inputText id = "username" value = "#{cc.attrs.usernameValue}"
/>
</h:form>
Step Description
Create a xhtml file and use custom component's namespace. Namespace will
2a the http://java.sun.com/jsf/<folder-name> where folder-name is folder in resources directory containing the
custom component
Example Application
Let us create a test JSF application to test the custom component in JSF.
Step Description
Create a project with a name helloworld under a package com.tutorialspoint.test as explained in the JSF -
1
First Application chapter.
6 Modify home.xhtml as explained below. Keep the rest of the files unchanged.
7 Compile and run the application to make sure the business logic is working as per the requirements.
8 Finally, build the application in the form of war file and deploy it in Apache Tomcat Webserver.
9 Launch your web application using appropriate URL as explained below in the last step.
loginComponent.xhtml
<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<composite:interface>
<composite:attribute name = "usernameLabel" />
<composite:attribute name = "usernameValue" />
<composite:attribute name = "passwordLabel" />
<composite:attribute name = "passwordValue" />
<composite:attribute name = "loginButtonLabel" />
<composite:attribute name = "loginButtonAction"
method-signature = "java.lang.String login()" />
</composite:interface>
<composite:implementation>
<h:form>
<h:message for = "loginPanel" style = "color:red;" />
UserData.java
package com.tutorialspoint.test;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
home.xhtml
<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<h:head>
<title>JSF tutorial</title>
</h:head>
<h:body>
<h2>Custom Component Example</h2>
<h:form>
<tp:loginComponent
usernameLabel = "Enter User Name: "
usernameValue = "#{userData.name}"
passwordLabel = "Enter Password: "
passwordValue = "#{userData.password}"
loginButtonLabel = "Login"
loginButtonAction = "#{userData.login}" />
</h:form>
</h:body>
</html>
Once you are ready with all the changes done, let us compile and run the application
as we did in JSF - First Application chapter. If everything is fine with your application,
this will produce the following result.
1. As we all are well aware of the fact that each application we develop has a
deployment descriptor i.e. WEB-INF/web.xml. This is the file which the
container reads. This file has all the configuration information which we
have defined for our web application. The configuration information
includes the index file, the default welcome page, the mapping of our
servlets including path and the extension name, any init parameters,
information related to the context elements.
In the file WEB-INF/web.xml of struts application we need to configure the
Struts ActionServlet which handles all the request made by the web
browsers to a given mapping. ActionServlet is the central component of
the Struts controller. This servlet extends the HttpServlet. This servlet
basically performs two important things. First is : When the container gets
start, it reads the Struts Configuration files and loads it into memory in
the init() method. You will know more about the Struts Configuration files
below. Second point is: It intercepts the HTTP request in
the doGet() and doPost() method and handles it appropriately.
3. For each action we also have to configure Struts with the names of the
resulting pages that will be shown as a result of that action. In our
application there can be more than one view which depends on the result
of an action. One can be for a success and the other for the failure. If the
result action is "success" then the action tells the ActionServlet that the
action has been successfully accomplished or vice- versa. The struts
knows how to forward the specific page to the concerned destination. The
model which we want to use is entirely to you, the model is called from
within the controller components.
4. Action can also get associate with a JavaBean in our Struts configuration
file. Java bean is nothing but a class having getter and setter methods that
can be used to communicate between the view and the controller layer.
These java beans are validated by invoking the validate() method on
the ActionForm by the help of the Struts system. The client sends the
request by the normal form submission by using Get or Post method, and
the Struts system updates that data in the Bean before calling the
controller components.
5. The view we use in the struts can be either Jsp page, Velocity templates,
XSLT pages etc. In struts there are set of JSP tags which has been
bundled with the struts distribution, but it is not mandatory to use only Jsp
tags, even plain HTML files can be used within our Struts application but
the disadvantage of using the html is that it can't take the full advantage
of all the dynamic features provided in the struts framework.
The framework includes a set of custom tag libraries that facilitate in
creating the user interfaces that can interact gracefully with ActionForm
beans. The struts Jsp taglibs has a number of generic and struts specific
tags tags which helps you to use dynamic data in your view. These tags
helps us to interact with your controller without writing much java code
inside your jsp. These tags are used create forms, internally forward to
other pages by interacting with the bean and helps us to invoke other
actions of the web application.
There are many tags provided to you in the struts frameworks which helps
you in sending error messages, internationalization etc.
Note: The points we have described above will be in effect if and only if when the
ActionServlet is handling the request. When the request is submitted to the
container which call the ActionServlet, make sure that the extension of the file
which we want to access should have the extension .do.
Struts working:
Process flow:
web.xml : Whenever the container gets start up the first work it does is to check
the web.xml file and determine what struts action Servlets exist. The container
is responsible for mapping all the file request to the correct action Servlet.
A Request : This is the second step performed by the container after checking
the web.xml file. In this the user submits a form within a browser and the request
is intercepted by the controller.
The Controller : This is the heart of the container. Most Struts application will
have only one controller that is ActionServlet which is responsible for directing
several Actions. The controller determines what action is required and sends the
information to be processed by an action Bean. The key advantage of having a
controller is its ability to control the flow of logic through the highly controlled,
centralized points.
Model : The model is basically a business logic part which takes the response
from the user and stores the result for the duration of the process. This is a great
place to perform the preprocessing of the data received from request. It is
possible to reuse the same model for many page requests. Struts provides the
ActionForm and the Action classes which can be extended to create the model
objects.
View : The view in struts framework is mainly a jsp page which is responsible for
producing the output to the user.
Struts tag libraries : These are struts components helps us to integrate the
struts framework within the project's logic. These struts tag libraries are used
within the JSP page. This means that the controller and the model part can't
make use of the tag library but instead use the struts class library for strut
process control.
Property file : It is used to store the messages that an object or page can use.
Properties files can be used to store the titles and other string data. We can
create many property files to handle different languages.
Business objects : It is the place where the rules of the actual project exists.
These are the modules which just regulate the day- to- day site activities.
Components of Struts
1. Model Components:
- Many application’s focus is on the view. The processing required for each
submitted form / request by keeping the model’s perspective in view.
- In general the focus for handling the model components is done by the
creation of java beans that support the functionality requirements. The scope
concept is related to the beans is used first.
2. View Components:
- Struts supports the interacting input forms and used for building
internationalized applications.
- Some files are uploaded by using HTML forms. Most of the browsers support
the uploading of files through a input tag like <input type=”file”>. This
generates a file browse button. Struts handles these kind of forms in a way
that is identical to building normal forms.
3. Controller Components:
As we can see, there are three components that involve in handling form in Struts application: Struts
form, JavaBean and Action class. The relationship between these components is clearly described in
the above picture: Fields in the form are mapped to properties of a JavaBean which is an attribute of
the action class that handles the form submission. In Struts, we don’t have to read values of the
form’s fields through a HTTP request object like in traditional JSP/Servlet. Instead, Struts will
automatically fetch values of form’s fields into the mapped JavaBean object. Then in the action
class, we can access the form’s fields just like accessing JavaBean properties. Thus this approach
simplifies form handling.
This tag will create a HTML-equivalent <form> tag. Typically we would use this tag as follows:
Inside the <s:form> tag we put tags to create HTML form fields in the following form:
o Default submit button: <s:submit />
o Submit button with custom label: <s:submit label="Login" />
And we have complete code of the form page (LoginForm.jsp) as follows:
1 <%@ page language="java" contentType="text/html; charset=UTF-8"
2 pageEncoding="UTF-8"%>
13 <h2>Please login</h2>
1 package net.codejava.struts;
6
public String getEmail() {
7
return email;
8
}
9
10
this.email = email;
12
}
13
14
public String getPassword() {
15
return password;
16
}
17
18
public void setPassword(String password) {
19
this.password = password;
20 }
21 }
22
The properties email and password must match the properties defined in the login
form: userBean.email and userBean.password, respectively.
When the form is submitted, Struts will create an instance of this JavaBean class using the default,
no-arguments constructor. So make sure there’s always a no-arguments constructor in the class:
o If there’s no explicit constructor, then the compiler will generate a default, no-
argument constructor. In this case, we don’t have to do anything.
o If we declare a constructor has an argument like this:
1 public User(String email) {
2 this.email = email;
3 }
2 }
1 package net.codejava.struts;
3 import com.opensymphony.xwork2.ActionSupport;
4
public class LoginAction extends ActionSupport {
5
6
private User userBean;
7
8
public String execute() {
9
System.out.println("email: " + userBean.getEmail());
10
System.out.println("pass: " + userBean.getPassword());
11
12
// add your login procedure here...
13
14
return SUCCESS;
15 }
16
18 return userBean;
19 }
20
this.userBean = userBean;
22
}
23
24 }
25
Here we have to declare a member variable of type User called userBean to match with
the userBean name defined in the login form, with appropriate getter and setter methods.
Then in the action method execute(), we can access the email and password of the login form just
like reading properties of the userBean. Because before executing the action method, Struts
creates an instance of the User class and passes values of form’s fields into the appropriate setter
methods.
Inside the execute() method, we simply print out the email and password to the server’s console.
In reality, you may validate the email and password against a database, depending on how the login
function would be implemented.
1
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
"http://www.w3.org/TR/html4/loose.dtd">
3 <html>
4 <head>
6 <title>Login Success</title>
7 </head>
<body>
8
<h2 align="center">Welcome, you have logged in successfully!</h2>
9
</body>
10
</html>
11
This is a simple HTML page that displays a welcome message to the user. By convention, the
framework will show up this page when the action class returns SUCCESS view.
2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
3
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
4
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
5
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
6
id="WebApp_ID" version="3.0">
7
8
<display-name>Struts2FormHandling</display-name>
9
10 <filter>
11 <filter-name>struts2</filter-name>
12 <filter-class>
13 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
14 </filter-class>
</filter>
15
16
<filter-mapping>
17
<filter-name>struts2</filter-name>
18
<url-pattern>/*</url-pattern>
19
</filter-mapping>
20
</web-app>
21
22
We don’t use the struts.xml file in this application. Instead, we use the default naming convention
implied by Struts. The following table shows how the framework will interpret the action URL and
view file:
Thanks to the Convention Plugin to make this possible. Remember to put the convention plugin’s jar
file into the classpath, e.g. struts2-convention-plugin-VERSION.jar.
For more information about this naming convention, see the tutorial: Struts beginner tutorial with
Convention Plugin.
If you build this application in Eclipse IDE, the project would have the following structure:
6. Testing the Struts From Handling application
Let’s deploy the application on Tomcat server with the context path /Struts2FormHandling. Type the
following URL into browser to show the login page:
http://localhost:8080/Struts2FormHandling/LoginForm.jsp
The login form appears:
Enter e-mail and password then hit Login button, the welcome page appears:
Look at the server’s console, we’ll see the entered e-mail and password are printed out.
Spring: Framework
Spring framework is an open source Java platform that provides comprehensive
infrastructure support for developing robust Java applications very easily and very
rapidly. Spring framework was initially written by Rod Johnson and was first released
under the Apache 2.0 license in June 2003. This tutorial has been written based on
Spring Framework version 4.1.6 released in Mar 2015.
Applications of Spring
Following is the list of few of the great benefits of using Spring Framework −
POJO Based - Spring enables developers to develop enterprise-class applications using
POJOs. The benefit of using only POJOs is that you do not need an EJB container product
such as an application server but you have the option of using only a robust servlet
container such as Tomcat or some commercial product.
Modular - Spring is organized in a modular fashion. Even though the number of packages
and classes are substantial, you have to worry only about the ones you need and ignore the
rest.
Integration with existing frameworks - Spring does not reinvent the wheel, instead it truly
makes use of some of the existing technologies like several ORM frameworks, logging
frameworks, JEE, Quartz and JDK timers, and other view technologies.
Testablity - Testing an application written with Spring is simple because environment-
dependent code is moved into this framework. Furthermore, by using JavaBeanstyle
POJOs, it becomes easier to use dependency injection for injecting test data.
Web MVC - Spring's web framework is a well-designed web MVC framework, which
provides a great alternative to web frameworks such as Struts or other over-engineered or
less popular web frameworks.
Central Exception Handling - Spring provides a convenient API to translate technology-
specific exceptions (thrown by JDBC, Hibernate, or JDO, for example) into consistent,
unchecked exceptions.
Lightweight - Lightweight IoC containers tend to be lightweight, especially when compared
to EJB containers, for example. This is beneficial for developing and deploying applications
on computers with limited memory and CPU resources.
Transaction management - Spring provides a consistent transaction management
interface that can scale down to a local transaction (using a single database, for example)
and scale up to global transactions (using JTA, for example).
JdbcTemplate Class
The JDBC Template class executes SQL queries, updates statements, stores
procedure calls, performs iteration over ResultSets, and extracts returned parameter
values. It also catches JDBC exceptions and translates them to the generic, more
informative, exception hierarchy defined in the org.springframework.dao package.
Instances of the JdbcTemplate class are threadsafe once configured. So you can
configure a single instance of a JdbcTemplate and then safely inject this shared
reference into multiple DAOs.
A common practice when using the JDBC Template class is to configure
a DataSource in your Spring configuration file, and then dependency-inject that shared
DataSource bean into your DAO classes, and the JdbcTemplate is created in the setter
for the DataSource.
Now we need to supply a DataSource to the JDBC Template so it can configure itself to
get database access. You can configure the DataSource in the XML file with a piece of
code as shown in the following code snippet −
<bean id = "dataSource"
class =
"org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name = "driverClassName" value =
"com.mysql.jdbc.Driver"/>
<property name = "url" value =
"jdbc:mysql://localhost:3306/TEST"/>
<property name = "username" value = "root"/>
<property name = "password" value = "password"/>
</bean>
return student;
}
}
return student;
}
}
jdbcTemplateObject.execute( SQL );
This example will explain how to write a simple JDBC-based Spring application.
Learn how to call SQL stored procedure while using JDBC in Spring.
The DispatcherServlet
The Spring Web model-view-controller (MVC) framework is designed around
a DispatcherServlet that handles all the HTTP requests and responses. The request
processing workflow of the Spring Web MVC DispatcherServlet is illustrated in the
following diagram −
Following is the sequence of events corresponding to an incoming HTTP request
to DispatcherServlet −
After receiving an HTTP request, DispatcherServlet consults the HandlerMapping to call the
appropriate Controller.
The Controller takes the request and calls the appropriate service methods based on used
GET or POST method. The service method will set model data based on defined business
logic and returns view name to the DispatcherServlet.
The DispatcherServlet will take help from ViewResolver to pickup the defined view for the
request.
Once view is finalized, The DispatcherServlet passes the model data to the view which is
finally rendered on the browser.
All the above-mentioned components, i.e. HandlerMapping, Controller, and
ViewResolver are parts of WebApplicationContext w which is an extension of the
plainApplicationContext with some extra features necessary for web applications.
Required Configuration
You need to map requests that you want the DispatcherServlet to handle, by using a
URL mapping in the web.xml file. The following is an example to show declaration and
mapping for HelloWeb DispatcherServlet example −
<web-app id = "WebApp_ID" version = "2.4"
xmlns = "http://java.sun.com/xml/ns/j2ee"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring MVC Application</display-name>
<servlet>
<servlet-name>HelloWeb</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloWeb</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
</web-app>
The web.xml file will be kept in the WebContent/WEB-INF directory of your web
application. Upon initialization of HelloWeb DispatcherServlet, the framework will try to
load the application context from a file named [servlet-name]-servlet.xml located in
the application's WebContent/WEB-INFdirectory. In this case, our file will
be HelloWebservlet.xml.
Next, <servlet-mapping> tag indicates what URLs will be handled by which
DispatcherServlet. Here all the HTTP requests ending with .jsp will be handled by
the HelloWeb DispatcherServlet.
If you do not want to go with default filename as [servlet-name]-servlet.xml and default
location as WebContent/WEB-INF, you can customize this file name and location by
adding the servlet listener ContextLoaderListener in your web.xml file as follows −
<web-app...>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
Now, let us check the required configuration for HelloWeb-servlet.xml file, placed in
your web application's WebContent/WEB-INF directory −
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:context = "http://www.springframework.org/schema/context"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation =
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-
3.0.xsd">
<bean class =
"org.springframework.web.servlet.view.InternalResourceViewResolver"
>
<property name = "prefix" value = "/WEB-INF/jsp/" />
<property name = "suffix" value = ".jsp" />
</bean>
</beans>
Defining a Controller
The DispatcherServlet delegates the request to the controllers to execute the
functionality specific to it. The @Controllerannotation indicates that a particular class
serves the role of a controller. The @RequestMapping annotation is used to map a
URL to either an entire class or a particular handler method.
@Controller
@RequestMapping("/hello")
public class HelloController {
@RequestMapping(method = RequestMethod.GET)
public String printHello(ModelMap model) {
model.addAttribute("message", "Hello Spring MVC Framework!");
return "hello";
}
}
The @Controller annotation defines the class as a Spring MVC controller. Here, the
first usage of @RequestMapping indicates that all handling methods on this controller
are relative to the /hello path. Next annotation@RequestMapping(method =
RequestMethod.GET) is used to declare theprintHello() method as the controller's
default service method to handle HTTP GET request. You can define another method
to handle any POST request at the same URL.
You can write the above controller in another form where you can add additional
attributes in @RequestMapping as follows −
@Controller
public class HelloController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String printHello(ModelMap model) {
model.addAttribute("message", "Hello Spring MVC Framework!");
return "hello";
}
}
The value attribute indicates the URL to which the handler method is mapped and
the method attribute defines the service method to handle HTTP GET request. The
following important points are to be noted about the controller defined above −
You will define required business logic inside a service method. You can call another method
inside this method as per requirement.
Based on the business logic defined, you will create a model within this method. You can
use setter different model attributes and these attributes will be accessed by the view to
present the final result. This example creates a model with its attribute "message".
A defined service method can return a String, which contains the name of the view to be
used to render the model. This example returns "hello" as logical view name.
<body>
<h2>${message}</h2>
</body>
</html>
Here ${message} is the attribute which we have set up inside the Controller. You can
have multiple attributes to be displayed inside your view.
Hibernate
Hibernate - Configuration Settings
Hibernate requires to know in advance — where to find the mapping information that
defines how your Java classes relate to the database tables. Hibernate also requires a
set of configuration settings related to database and other related parameters. All such
information is usually supplied as a standard Java properties file
called hibernate.properties, or as an XML file named hibernate.cfg.xml.
I will consider XML formatted file hibernate.cfg.xml to specify required Hibernate
properties in my examples. Most of the properties take their default values and it is not
required to specify them in the property file unless it is really required. This file is kept
in the root directory of your application's classpath.
Hibernate Properties
Following is the list of important properties, you will be required to configure for a databases in
a standalone situation −
1
hibernate.dialect
This property makes Hibernate generate the appropriate SQL for the chosen database.
2
hibernate.connection.driver_class
The JDBC driver class.
3
hibernate.connection.url
The JDBC URL to the database instance.
4
hibernate.connection.username
The database username.
5
hibernate.connection.password
The database password.
6
hibernate.connection.pool_size
Limits the number of connections waiting in the Hibernate database connection pool.
7
hibernate.connection.autocommit
Allows autocommit mode to be used for the JDBC connection.
If you are using a database along with an application server and JNDI, then you would
have to configure the following properties −
1
hibernate.connection.datasource
The JNDI name defined in the application server context, which you are using for the application.
2
hibernate.jndi.class
The InitialContext class for JNDI.
3
hibernate.jndi.<JNDIpropertyname>
Passes any JNDI property you like to the JNDI InitialContext.
4
hibernate.jndi.url
Provides the URL for JNDI.
5
hibernate.connection.username
The database username.
6
hibernate.connection.password
The database password.
Hibernate with MySQL Database
MySQL is one of the most popular open-source database systems available today. Let
us create hibernate.cfg.xml configuration file and place it in the root of your
application's classpath. You will have to make sure that you have testdb database
available in your MySQL database and you have a user test available to access the
database.
The XML configuration file must conform to the Hibernate 3 Configuration DTD, which
is available at http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd.
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
</session-factory>
</hibernate-configuration>
The above configuration file includes <mapping> tags, which are related to
hibernatemapping file and we will see in next chapter what exactly a hibernate
mapping file is and how and why do we use it?
Following is the list of various important databases dialect property type −
Sr.No. Database & Dialect Property
1
DB2
org.hibernate.dialect.DB2Dialect
2
HSQLDB
org.hibernate.dialect.HSQLDialect
3
HypersonicSQL
org.hibernate.dialect.HSQLDialect
4
Informix
org.hibernate.dialect.InformixDialect
5
Ingres
org.hibernate.dialect.IngresDialect
6
Interbase
org.hibernate.dialect.InterbaseDialect
7
Microsoft SQL Server 2000
org.hibernate.dialect.SQLServerDialect
8
Microsoft SQL Server 2005
org.hibernate.dialect.SQLServer2005Dialect
9
Microsoft SQL Server 2008
org.hibernate.dialect.SQLServer2008Dialect
10
MySQL
org.hibernate.dialect.MySQLDialect
11
Oracle (any version)
org.hibernate.dialect.OracleDialect
12
Oracle 11g
org.hibernate.dialect.Oracle10gDialect
13
Oracle 10g
org.hibernate.dialect.Oracle10gDialect
14
Oracle 9i
org.hibernate.dialect.Oracle9iDialect
15
PostgreSQL
org.hibernate.dialect.PostgreSQLDialect
16
Progress
org.hibernate.dialect.ProgressDialect
17
SAP DB
org.hibernate.dialect.SAPDBDialect
18
Sybase
org.hibernate.dialect.SybaseDialect
19
Sybase Anywhere
org.hibernate.dialect.SybaseAnywhereDialect
public Employee() {}
public Employee(String fname, String lname, int salary) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
}
Any application with persistent state must interact with the persistence service
whenever it needs to propagate state held in memory to the database (or vice versa). In
other words, you have to call Hibernate (or the Java Persistence) interfaces to store and
load objects.
When interacting with the persistence mechanism in that way, it’s necessary for the
application to concern itself with the state and lifecycle of an object with respect to
persistence. We refer to this as the persistence lifecycle: the states an object goes
through during its life. We also use the term unit of work: a set of operations you
consider one (usually atomic) group. Another piece of the puzzle is the persistence
context provided by the persistence service. Think of the persistence context as a cache
that remembers all the modifications and state changes you made to objects in a
particular unit of work (this is somewhat simplified, but it’s a good starting point).
We now dissect all these terms: object and entity states, persistence contexts, and
managed scope. You’re probably more accustomed to thinking about what statements
you have to manage to get stuff in and out of the database (via JDBC and SQL).
However, one of the key factors of your success with Hibernate (and Java Persistence)
is your understanding of state management, so stick with us through this section.
Object states
Different ORM solutions use different terminology and define different states and
state transitions for the persistence lifecycle. Moreover, the object states used internally
may be different from those exposed to the client application. Hibernate defines only
four states, hiding the complexity of its internal implementation from the client code.
The object states defined by Hibernate and their transitions in a state chart are shown in
figure 9.1. You can also see the method calls to the persistence manager API that
trigger transitions. This API in Hibernate is the Session. We discuss this chart in this
topic; refer to it whenever you need an overview.
We’ve also included the states ofJava Persistence entity instances in figure 9.1. As you
can see, they’re almost equivalent to Hibernate’s, and most methods of the Session
have a counterpart on the EntityManager API (shown in italics). We say that Hibernate
is a superset of the functionality provided by the subset standardized in Java
Persistence.
Some methods are available on both APIs; for example, the Session has a per-sist()
operation with the same semantics as the EntityManager’s counterpart. Others, like
load() and getReference(), also share semantics, with a different method name.
During its life, an object can transition from a transient object to a persistent object to a
detached object. Let’s explore the states and transitions in more detail.
Figure 9.1 Object states and their transitions as triggered by persistence manager
operations
Transient objects
Objects instantiated using the new operator aren’t immediately persistent. Their state is
transient, which means they aren’t associated with any database table row and so their
state is lost as soon as they’re no longer referenced by any other object. These objects
have a lifespan that effectively ends at that time, and they become inaccessible and
available for garbage collection. Java Persistence doesn’t include a term for this state;
entity objects you just instantiated are new. We’ll continue to refer to them as transient
to emphasize the potential for these instances to become managed by a persistence
service.
Objects that are referenced only by other transient instances are, by default, also
transient. For an instance to transition from transient to persistent state, to become
managed, requires either a call to the persistence manager or the creation of a
reference from an already persistent instance.
Persistent objects
A persistent instance is an entity instance with a database identity, as defined.
“Mapping entities with identity.” That means a persistent and managed instance has a
primary key value set as its database identifier. (There are some variations to when this
identifier is assigned to a persistent instance.)
Persistent instances may be objects instantiated by the application and then made
persistent by calling one of the methods on the persistence manager. They may even
be objects that became persistent when a reference was created from another
persistent object that is already managed. Alternatively, a persistent instance may be an
instance retrieved from the database by execution of a query, by an identifier lookup, or
by navigating the object graph starting from another persistent instance.
Persistent instances are always associated with a persistence context. Hibernate
caches them and can detect whether they have been modified by the application.
There is much more to be said about this state and how an instance is managed in a
persistence context. We’ll get back to this later in this topic.
Removed objects
You can delete an entity instance in several ways: For example, you can remove it with
an explicit operation of the persistence manager. It may also become available for
deletion if you remove all references to it, a feature available only in Hibernate or in
Java Persistence with a Hibernate extension setting (orphan deletion for entities).
An object is in the removed state if it has been scheduled for deletion at the end of a
unit of work, but it’s still managed by the persistence context until the unit of work
completes. In other words, a removed object shouldn’t be reused because it will be
deleted from the database as soon as the unit of work completes. You should also
discard any references you may hold to it in the application (of course, after you finish
working with it—for example, after you’ve rendered the removal-confirmation screen
your users see).
Detached objects
To understand detached objects, you need to consider a typical transition of an
instance: First it’s transient, because it just has been created in the application. Now
you make it persistent by calling an operation on the persistence manager. All of this
happens in a single unit of work, and the persistence context for this unit of work is
synchronized with the database at some point (when an SQL INSERT occurs).
The unit of work is now completed, and the persistence context is closed. But the
application still has a handle: a reference to the instance that was saved. As long as the
persistence context is active, the state of this instance is persistent. At the end of a unit
of work, the persistence context closes. What is the state of the object you’re holding a
reference to now, and what can you do with it?
We refer to these objects as detached, indicating that their state is no longer
guaranteed to be synchronized with database state; they’re no longer attached to a
persistence context. They still contain persistent data (which may soon be stale). You
can continue working with a detached object and modify it. However, at some point you
probably want to make those changes persistent—in other words, bring the detached
instance back into persistent state.
Hibernate offers two operations, reattachment and merging, to deal with this
situation. Java Persistence only standardizes merging. These features have a deep
impact on how multitiered applications may be designed. The ability to return objects
from one persistence context to the presentation layer and later reuse them in a new
persistence context is a main selling point of Hibernate and Java Persistence. It enables
you to create long units of work that span user think-time. We call this kind of long-
running unit of work a conversation. We’ll get back to detached objects and
conversations soon.
You should now have a basic understanding of object states and how transitions occur.
Our next topic is the persistence context and the management of objects it provides.
All these points are also valid for Java Persistence providers. Let’s look at each feature.
Later in this topic, we’ll show you how objects are added to this cache (basically,
whenever they become persistent) and how you can manage this cache (by detaching
objects manually from the persistence context, or by clearing the persistence context).
The last two items on our list of benefits of a persistence context, the guaranteed scope
of identity and the possibility to extend the persistence context to span a conversation,
are closely related concepts. To understand them, you need to take a step back and
consider objects in detached state from a different perspective.
First-level Cache
The first-level cache is the Session cache and is a mandatory cache through which all
requests must pass. The Session object keeps an object under its own power before
committing it to the database.
If you issue multiple updates to an object, Hibernate tries to delay doing the update as
long as possible to reduce the number of update SQL statements issued. If you close
the session, all the objects being cached are lost and either persisted or updated in the
database.
Second-level Cache
Second level cache is an optional cache and first-level cache will always be consulted
before any attempt is made to locate an object in the second-level cache. The second
level cache can be configured on a per-class and per-collection basis and mainly
responsible for caching objects across sessions.
Any third-party cache can be used with Hibernate.
An org.hibernate.cache.CacheProvider interface is provided, which must be
implemented to provide Hibernate with a handle to the cache implementation.
Query-level Cache
Hibernate also implements a cache for query resultsets that integrates closely with the
second-level cache.
This is an optional feature and requires two additional physical cache regions that hold
the cached query results and the timestamps when a table was last updated. This is
only useful for queries that are run frequently with the same parameters.
Concurrency Strategies
A concurrency strategy is a mediator, which is responsible for storing items of data in
the cache and retrieving them from the cache. If you are going to enable a second-
level cache, you will have to decide, for each persistent class and collection, which
cache concurrency strategy to use.
Transactional − Use this strategy for read-mostly data where it is critical to prevent stale
data in concurrent transactions, in the rare case of an update.
Read-write − Again use this strategy for read-mostly data where it is critical to prevent stale
data in concurrent transactions, in the rare case of an update.
Nonstrict-read-write − This strategy makes no guarantee of consistency between the
cache and the database. Use this strategy if data hardly ever changes and a small
likelihood of stale data is not of critical concern.
Read-only − A concurrency strategy suitable for data, which never changes. Use it for
reference data only.
If we are going to use second-level caching for our Employee class, let us add the
mapping element required to tell Hibernate to cache Employee instances using read-
write strategy.
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
</class>
</hibernate-mapping>
Cache Provider
Your next step after considering the concurrency strategies, you will use your cache candidate
classes to pick a cache provider. Hibernate forces you to choose a single cache provider for the
whole application.
1
EHCache
It can cache in memory or on disk and clustered caching and it supports the optional Hibernate query
result cache.
2
OSCache
Supports caching to memory and disk in a single JVM with a rich set of expiration policies and query
cache support.
3
warmCache
A cluster cache based on JGroups. It uses clustered invalidation, but doesn't support the Hibernate
query cache.
4
JBoss Cache
A fully transactional replicated clustered cache also based on the JGroups multicast library. It supports
replication or invalidation, synchronous or asynchronous communication, and optimistic and pessimistic
locking. The Hibernate query cache is supported.
Every cache provider is not compatible with every concurrency strategy. The following
compatibility matrix will help you choose an appropriate combination.
EHCache X X X
OSCache X X X
SwarmCache X X
JBoss Cache X X
</session-factory>
</hibernate-configuration>
Now, you need to specify the properties of the cache regions. EHCache has its own
configuration file, ehcache.xml, which should be in the CLASSPATH of the application.
A cache configuration in ehcache.xml for the Employee class may look like this −
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory = "1000"
eternal = "false"
timeToIdleSeconds = "120"
timeToLiveSeconds = "120"
overflowToDisk = "true"
/>
That's it, now we have second-level caching enabled for the Employee class and
Hibernate, now hits the second-level cache whenever you navigate to an Employee or
when you load an Employee by identifier.
You should analyze your all the classes and choose appropriate caching strategy for
each of the classes. Sometime, second-level caching may downgrade the performance
of the application. So, it is recommended to benchmark your application first, without
enabling caching and later on enable your well suited caching and check the
performance. If caching is not improving system performance, then there is no point in
enabling any type of caching.
Hibernate also supports very fine-grained cache support through the concept of a
cache region. A cache region is part of the cache that's given a name.
Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
query.setCacheRegion("employee");
List users = query.list();
SessionFactory.closeSession();
This code uses the method to tell Hibernate to store and look for the query in the
employee area of the cache.
Hibernate does not lock objects in memory. Your application can expect the behavior as defined
by the isolation level of your database transactions. Through Session, which is also a transaction-
scoped cache, Hibernate provides repeatable reads for lookup by identifier and entity queries and
not reporting queries that return scalar values.
In addition to versioning for automatic optimistic concurrency control, Hibernate also offers,
using the SELECT FOR UPDATE syntax, a (minor) API for pessimistic locking of rows.
Optimistic concurrency control and this API are discussed later in this chapter.
A Session is an inexpensive, non-threadsafe object that should be used once and then discarded
for: a single request, a conversation or a single unit of work. A Session will not obtain a
JDBC Connection, or a Datasource, unless it is needed. It will not consume any resources until
used.
In order to reduce lock contention in the database, a database transaction has to be as short as
possible. Long database transactions will prevent your application from scaling to a highly
concurrent load. It is not recommended that you hold a database transaction open during user
think time until the unit of work is complete.
What is the scope of a unit of work? Can a single Hibernate Session span several database
transactions, or is this a one-to-one relationship of scopes? When should you open and close
a Session and how do you demarcate the database transaction boundaries? These questions are
addressed in the following sections.
First, let's define a unit of work. A unit of work is a design pattern described by Martin Fowler as
“ [maintaining] a list of objects affected by a business transaction and coordinates the writing out
of changes and the resolution of concurrency problems. ”[PoEAA] In other words, its a series of
operations we wish to carry out against the database together. Basically, it is a transaction,
though fulfilling a unit of work will often span multiple physical database transactions
(see Section 11.1.2, “Long conversations”). So really we are talking about a more abstract notion
of a transaction. The term "business transaction" is also sometimes used in lieu of unit of work.
Do not use the session-per-operation antipattern: do not open and close a Session for every
simple database call in a single thread. The same is true for database transactions. Database calls
in an application are made using a planned sequence; they are grouped into atomic units of work.
This also means that auto-commit after every single SQL statement is useless in an application as
this mode is intended for ad-hoc SQL console work. Hibernate disables, or expects the
application server to disable, auto-commit mode immediately. Database transactions are never
optional. All communication with a database has to occur inside a transaction. Auto-commit
behavior for reading data should be avoided, as many small transactions are unlikely to perform
better than one clearly defined unit of work. The latter is also more maintainable and extensible.
The challenge lies in the implementation. Hibernate provides built-in management of the
"current session" to simplify this pattern. Start a transaction when a server request has to be
processed, and end the transaction before the response is sent to the client. Common solutions
are ServletFilter, AOP interceptor with a pointcut on the service methods, or a proxy/interception
container. An EJB container is a standardized way to implement cross-cutting aspects such as
transaction demarcation on EJB session beans, declaratively with CMT. If you use programmatic
transaction demarcation, for ease of use and code portability use the Hibernate Transaction API
shown later in this chapter.
Your application code can access a "current session" to process the request by
calling sessionFactory.getCurrentSession(). You will always get a Session scoped to the current
database transaction. This has to be configured for either resource-local or JTA environments,
see Section 2.5, “Contextual sessions”.
You can extend the scope of a Session and database transaction until the "view has been
rendered". This is especially useful in servlet applications that utilize a separate rendering phase
after the request has been processed. Extending the database transaction until view rendering, is
achieved by implementing your own interceptor. However, this will be difficult if you rely on
EJBs with container-managed transactions. A transaction will be completed when an EJB method
returns, before rendering of any view can start. See the Hibernate website and forum for tips and
examples relating to this Open Session in View pattern.
The session-per-request pattern is not the only way of designing units of work. Many business
processes require a whole series of interactions with the user that are interleaved with database
accesses. In web and enterprise applications, it is not acceptable for a database transaction to
span a user interaction. Consider the following example:
o The first screen of a dialog opens. The data seen by the user has been loaded in a
particular Session and database transaction. The user is free to modify the objects.
o The user clicks "Save" after 5 minutes and expects their modifications to be made
persistent. The user also expects that they were the only person editing this information
and that no conflicting modification has occurred.
From the point of view of the user, we call this unit of work a long-
running conversation or application transaction. There are many ways to implement this in your
application.
A first naive implementation might keep the Session and database transaction open during user
think time, with locks held in the database to prevent concurrent modification and to guarantee
isolation and atomicity. This is an anti-pattern, since lock contention would not allow the
application to scale with the number of concurrent users.
You have to use several database transactions to implement the conversation. In this case,
maintaining isolation of business processes becomes the partial responsibility of the application
tier. A single conversation usually spans several database transactions. It will be atomic if only
one of these database transactions (the last one) stores the updated data. All others simply read
data (for example, in a wizard-style dialog spanning several request/response cycles). This is
easier to implement than it might sound, especially if you utilize some of Hibernate's features:
An application can concurrently access the same persistent state in two different Sessions.
However, an instance of a persistent class is never shared between two Session instances. It is for
this reason that there are two different notions of identity:
Database Identity
foo.getId().equals( bar.getId() )
JVM Identity
foo==bar
For objects attached to a particular Session (i.e., in the scope of a Session), the two
notions are equivalent and JVM identity for database identity is guaranteed by
Hibernate. While the application might concurrently access the "same" (persistent
identity) business object in two different sessions, the two instances will actually be
"different" (JVM identity). Conflicts are resolved using an optimistic approach and
automatic versioning at flush/commit time.
This approach leaves Hibernate and the database to worry about concurrency. It also
provides the best scalability, since guaranteeing identity in single-threaded units of
work means that it does not need expensive locking or other means of synchronization.
The application does not need to synchronize on any business object, as long as it
maintains a single thread per Session. Within a Session the application can safely
use == to compare objects.
However, it is often desirable to keep your persistence layer portable between non-
managed resource-local environments, and systems that can rely on JTA but use BMT
instead of CMT. In both cases use programmatic transaction demarcation. Hibernate
offers a wrapper API called Transaction that translates into the native transaction
system of your deployment environment. This API is actually optional, but we strongly
encourage its use unless you are in a CMT session bean.
We discussed Flushing the session earlier, so we will now have a closer look at
transaction demarcation and exception handling in both managed and non-managed
environments.
// do some work
...
tx.commit();
}
catch (RuntimeException e) {
if (tx != null) tx.rollback();
throw e; // or display error message
}
finally {
sess.close();
}
You do not have to flush() the Session explicitly: the call to commit() automatically
triggers the synchronization depending on the FlushMode for the session. A call
to close() marks the end of a session. The main implication of close() is that the JDBC
connection will be relinquished by the session. This Java code is portable and runs in
both non-managed and JTA environments.
factory.getCurrentSession().getTransaction().commit();
}
catch (RuntimeException e) {
factory.getCurrentSession().getTransaction().rollback();
throw e; // or display error message
}
You will not see these code snippets in a regular application; fatal (system) exceptions
should always be caught at the "top". In other words, the code that executes Hibernate
calls in the persistence layer, and the code that handles RuntimeException (and usually
can only clean up and exit), are in different layers. The current context management by
Hibernate can significantly simplify this design by accessing a SessionFactory.
Exception handling is discussed later in this chapter.
If your persistence layer runs in an application server (for example, behind EJB session
beans), every datasource connection obtained by Hibernate will automatically be part
of the global JTA transaction. You can also install a standalone JTA implementation
and use it without EJB. Hibernate offers two strategies for JTA integration.
If you use bean-managed transactions (BMT), Hibernate will tell the application server
to start and end a BMT transaction if you use the Transaction API. The transaction
management code is identical to the non-managed environment.
// BMT idiom
Session sess = factory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();
// do some work
...
tx.commit();
}
catch (RuntimeException e) {
if (tx != null) tx.rollback();
throw e; // or display error message
}
finally {
sess.close();
}
tx.begin();
tx.commit();
}
catch (RuntimeException e) {
tx.rollback();
throw e; // or display error message
}
// CMT idiom
Session sess = factory.getCurrentSession();
// do some work
...
The HibernateException, which wraps most of the errors that can occur in a Hibernate
persistence layer, is an unchecked exception. It was not in older versions of Hibernate.
In our opinion, we should not force the application developer to catch an unrecoverable
exception at a low layer. In most systems, unchecked and fatal exceptions are handled
in one of the first frames of the method call stack (i.e., in higher layers) and either an
error message is presented to the application user or some other appropriate action is
taken. Note that Hibernate might also throw other unchecked exceptions that are not
a HibernateException. These are not recoverable and appropriate action should be
taken.
// do some work
...
sess.getTransaction().commit()
}
catch (RuntimeException e) {
sess.getTransaction().rollback();
throw e; // or display error message
}
finally {
sess.close();
}
The only approach that is consistent with high concurrency and high scalability, is
optimistic concurrency control with versioning. Version checking uses version
numbers, or timestamps, to detect conflicting updates and to prevent lost updates.
Hibernate provides three possible approaches to writing application code that uses
optimistic concurrency. The use cases we discuss are in the context of long
conversations, but version checking also has the benefit of preventing lost updates in
single database transactions.
In an implementation without much help from Hibernate, each interaction with the
database occurs in a new Session and the developer is responsible for reloading all
persistent instances from the database before manipulating them. The application is
forced to carry out its own version checking to ensure conversation transaction
isolation. This approach is the least efficient in terms of database access. It is the
approach most similar to entity EJBs.
t.commit();
session.close();
The version property is mapped using <version>, and Hibernate will automatically
increment it during flush if the entity is dirty.
Manual version checking is only feasible in trivial circumstances and not practical for
most applications. Often not only single instances, but complete graphs of modified
objects, have to be checked. Hibernate offers automatic version checking with either an
extended Session or detached instances as the design paradigm.
11.3.2. Extended session and automatic versioning
A single Session instance and its persistent instances that are used for the whole
conversation are known as session-per-conversation. Hibernate checks instance
versions at flush time, throwing an exception if concurrent modification is detected. It
is up to the developer to catch and handle this exception. Common options are the
opportunity for the user to merge changes or to restart the business conversation with
non-stale data.
The Session is disconnected from any underlying JDBC connection when waiting for
user interaction. This approach is the most efficient in terms of database access. The
application does not version check or reattach detached instances, nor does it have to
reload instances in every database transaction.
foo.setProperty("bar");
The foo object knows which Session it was loaded in. Beginning a new database
transaction on an old session obtains a new connection and resumes the session.
Committing a database transaction disconnects a session from the JDBC connection
and returns the connection to the pool. After reconnection, to force a version check on
data you are not updating, you can call Session.lock() with LockMode.READ on any
objects that might have been updated by another transaction. You do not need to lock
any data that you are updating. Usually you would set FlushMode.MANUAL on an
extended Session, so that only the last database transaction cycle is allowed to actually
persist all modifications made in this conversation. Only this last database transaction
will include the flush() operation, and then close() the session to end the conversation.
This pattern is problematic if the Session is too big to be stored during user think time
(for example, an HttpSession should be kept as small as possible). As the Session is
also the first-level cache and contains all loaded objects, we can probably use this
strategy only for a few request/response cycles. Use a Session only for a single
conversation as it will soon have stale data.
Note
Earlier versions of Hibernate required explicit disconnection and reconnection of
a Session. These methods are deprecated, as beginning and ending a transaction has the
same effect.
Keep the disconnected Session close to the persistence layer. Use an EJB stateful
session bean to hold the Session in a three-tier environment. Do not transfer it to the
web layer, or even serialize it to a separate tier, to store it in the HttpSession.
Each interaction with the persistent store occurs in a new Session. However, the same
persistent instances are reused for each interaction with the database. The application
manipulates the state of detached instances originally loaded in another Session and
then reattaches them using Session.update(), Session.saveOrUpdate(),
or Session.merge().
Again, Hibernate will check instance versions during flush, throwing an exception if
conflicting updates occurred.
You can also call lock() instead of update(), and use LockMode.READ (performing a
version check and bypassing all caches) if you are sure that the object has not been
modified.
You can disable Hibernate's automatic version increment for particular properties and
collections by setting the optimistic-lock mapping attribute to false. Hibernate will then
no longer increment versions if the property is dirty.
Legacy database schemas are often static and cannot be modified. Or, other
applications might access the same database and will not know how to handle version
numbers or even timestamps. In both cases, versioning cannot rely on a particular
column in a table. To force a version check with a comparison of the state of all fields
in a row but without a version or timestamp property mapping, turn on optimistic-
lock="all" in the <class> mapping. This conceptually only works if Hibernate can
compare the old and the new state (i.e., if you use a single long Session and not
session-per-request-with-detached-objects).
Concurrent modification can be permitted in instances where the changes that have
been made do not overlap. If you set optimistic-lock="dirty" when mapping
the <class>, Hibernate will only compare dirty fields during flush.
It is not intended that users spend much time worrying about locking strategies. It is
usually enough to specify an isolation level for the JDBC connections and then simply
let the database do all the work. However, advanced users may wish to obtain
exclusive pessimistic locks or re-obtain locks at the start of a new transaction.
Hibernate will always use the locking mechanism of the database; it never lock objects
in memory.
The LockMode class defines the different lock levels that can be acquired by
Hibernate. A lock is obtained by the following mechanisms:
If the requested lock mode is not supported by the database, Hibernate uses an
appropriate alternate mode instead of throwing an exception. This ensures that
applications are portable.
One of the legacies of Hibernate 2.x JDBC connection management meant that
a Session would obtain a connection when it was first required and then maintain that
connection until the session was closed. Hibernate 3.x introduced the notion of
connection release modes that would instruct a session how to handle its JDBC
connections. The following discussion is pertinent only to connections provided
through a configured ConnectionProvider. User-supplied connections are outside the
breadth of this discussion. The different release modes are identified by the enumerated
values of org.hibernate.ConnectionReleaseMode:
o auto (the default): this choice delegates to the release mode returned by
the org.hibernate.transaction.TransactionFactory.getDefaultReleaseMode() met
hod. For JTATransactionFactory, this returns
ConnectionReleaseMode.AFTER_STATEMENT; for JDBCTransactionFactory,
this returns ConnectionReleaseMode.AFTER_TRANSACTION. Do not
change this default behavior as failures due to the value of this setting tend to
indicate bugs and/or invalid assumptions in user code.
o on_close: uses ConnectionReleaseMode.ON_CLOSE. This setting is left for
backwards compatibility, but its use is discouraged.
o after_transaction: uses ConnectionReleaseMode.AFTER_TRANSACTION.
This setting should not be used in JTA environments. Also note that with
ConnectionReleaseMode.AFTER_TRANSACTION, if a session is considered
to be in auto-commit mode, connections will be released as if the release mode
were AFTER_STATEMENT.
o after_statement: uses ConnectionReleaseMode.AFTER_STATEMENT.
Additionally, the configured ConnectionProvider is consulted to see if it
supports this setting (supportsAggressiveRelease()). If not, the release mode is
reset to ConnectionReleaseMode.AFTER_TRANSACTION. This setting is
only safe in environments where we can either re-acquire the same underlying
JDBC connection each time you make a call
into ConnectionProvider.getConnection() or in auto-commit environments
where it does not matter if we re-establish the same connection.
Spring Controller
Spring Controller annotation can be applied on classes only. It’s used to mark a class as a web
request handler. It’s mostly used with Spring MVC application.
Spring RestController
Let’s create a simple spring application where we will implement standard MVC controller as
well as REST controller.
Create a “Dynamic Web Project” in Eclipse and then convert it to Maven project. This will
provide us with maven based web application structure and we can build our application on top
of it.
Below image shows the final project structure of our Spring MVC Controller application.
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Finally, we have following spring context file. Here we are configuring our application to be
annotation-based and providing root package for scanning spring components. We are also
configuring InternalResourceViewResolver bean and providing details of view pages.
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
</beans:beans>
Our configuration XML files are ready, let’s move on to the Controller class now.
package com.journaldev.spring.controller;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/hello")
public String home(Locale locale, Model model) {
Date date = new Date();
DateFormat dateFormat =
DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate);
return "home";
}
We have defined a single request handler method, it’s accepting GET requests with URI “/hello”
and returning “home.jsp” page as the response. Notice that we are setting an attribute to the
model, which will be used in the home.jsp page.
</body>
</html>
Our conventional servlet based Spring MVC application with a simple controller is ready, just
export it as the WAR file and deploy on Tomcat or any other servlet container.
Now let’s extend our application to expose REST APIs too. Create a model class that will be sent
as JSON response.
package com.journaldev.spring.model;
package com.journaldev.spring.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.journaldev.spring.model.Person;
@RestController
public class PersonRESTController {
@RequestMapping("/rest")
public String healthCheck() {
return "OK";
}
@RequestMapping("/rest/person/get")
public Person getPerson(@RequestParam(name = "name", required = false,
defaultValue = "Unknown") String name) {
Person person = new Person();
person.setName(name);
return person;
}