Workshop 4
Workshop 4
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public Contact(int id, String name, String email, String address, String
telephone) {
super();
this.id = id;
this.name = name;
this.email = email;
this.address = address;
this.telephone = telephone;
}
6. Create ContactDAO.java inside ch4.crud.dao package and paste following lines of code
inside it:
package ch4.crud.dao;
import java.util.List;
import ch4.crud.model.Contact;
public interface ContactDAO {
public int insert(Contact contact);
public List<Contact> displayAllContacts();
public String deleteContact(int id) ;
public Contact getContact(int id);
public String updateContact(int id,String name, String email,String address,String
telephone);
}
7. Create ContactDAOImpl.java inside ch4.crud.dao and paste following lines of code
inside it:
package ch4.crud.dao;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.dao.DataAccessException;
import ch4.crud.model.Contact;
@Override
public int insert(Contact contact) {
// TODO Auto-generated method stub
String name=contact.getName();
String email=contact.getEmail();
String address=contact.getAddress();
String telephone=contact.getTelephone();
//System.out.println("Name="+name+"\nEmail="+email+"\
nAddresss="+address+"\nTelephone="+telephone);
int rows = jdbcTemplate.update("insert into
contact(name,email,address,telephone) values(?,?,?,?)", name,email, address,telephone);
return rows;
}
@Override
public List<Contact> displayAllContacts() {
// TODO Auto-generated method stub
String query="select * from contact";
List<Map<String,Object>> rows=jdbcTemplate.queryForList(query);
}
return htmlrows;
}
@Override
public String deleteContact(int id)
{
//int s=3;
// TODO Auto-generated method stub
int s=jdbcTemplate.update("Delete from Contact where contact_id="+id);
if(s>=1)
{
return "ok";
}
else
{
return "nok";
}
@Override
public Contact getContact(int id) {
// TODO Auto-generated method stub
String query="select * from contact where contact_id="+id;
List<Map<String,Object>> rows=jdbcTemplate.queryForList(query);
Map<String,Object> r =rows.get(0);
Contact contact=new Contact();
contact.setId(Integer.parseInt(String.valueOf(r.get("contact_id"))));
contact.setName(String.valueOf(r.get("name")));
contact.setEmail(String.valueOf(r.get("email")));
contact.setAddress(String.valueOf(r.get("address")));
contact.setTelephone(String.valueOf(r.get("telephone")));
return contact;
}
@Transactional
@Override
public String updateContact(int id, String name, String email, String address, String
telephone) {
// TODO Auto-generated method stub
int s = jdbcTemplate.update("update contact set
name=?,email=?,address=?,telephone=? where contact_id=?", name,email,
address,telephone,id);
if(s>=1)
{
return "ok";
}
else
{
return "nok";
}
}
}
8. Create Status.java inside ch4.crud.util package and paste following lines of code inside it:
package ch4.crud.util;
this.status=status;
return status;
}
public void setStatus(String status) {
this.status = status;
9. Create a folder named views inside WebContent folder and create files namely main.jsp,
addContact.jsp,editForm.jsp and status.jsp inside it.
10. Paste following lines of code inside main.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3> <a href="/MVCCRUD/displayAddRecordPage"> Click Here to Add Record</a></h3>
<table border="1">
<th>No</th>
<th>Name</th>
<th>Email</th>
<th>Address</th>
<th>Telephone</th>
<th>Option</th>
</tr>
</c:forEach>
</table>
</body>
</html>
11. Paste following lines of code inside editForm.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form method="POST" action="/MVCCRUD/editRecord">
<table>
<tr>
<td>ID:<td><td><input type="text" id ="id" name="id" value="${data.id}"></td>
</tr>
<tr>
<td>Name:<td><td><input type="text" id="name" name="name" value="${data.name}"></td>
</tr>
<tr>
<td>Email:<td><td><input type="text" id="email" name="email" value="$
{data.email}"></td>
</tr>
<tr>
<td>Address:<td><td><input type="text" id="address" name="address" value="$
{data.address}"></td>
</tr>
<tr>
<td>Telephone:<td><td><input type="text" id="telephone" name="telephone" value="$
{data.telephone}"></td>
</tr>
<tr>
<td><input type="submit" name="updateBtn" id="updateBtn" value="UPDATE"></td>
</tr>
</table>
</form>
</body>
</html>
14. Inside WEB-INF Directory create a servlet context file named mvccrudserv-servlet.xml
and put following lines of code inside it:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="ch4.crud.controller" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
</beans>
15. Inside web.xml directory, put following lines of code :
contact.setId(Integer.parseInt(String.valueOf(r.get("contact_id"))));
contact.setName(String.valueOf(r.get("name")));
contact.setEmail(String.valueOf(r.get("email")));
contact.setAddress(String.valueOf(r.get("address")));
contact.setTelephone(String.valueOf(r.get("telephone")));
htmlrows.add(contact);
}
return htmlrows;
}
In order to save records into multiple rows at once, following code is used:
@Override
public void saveMultipleRows(List<Contact> lists) {
String query="insert into contact(name,email,address,telephone)
values(?,?,?,?)";
List<Object[]> rows=new ArrayList<Object[]>();
for(Contact contact: lists)
{
rows.add(new Object[]
{contact.getName(),contact.getEmail(),contact.getAddress(),contact.getTelephone()});
}
jdbcTemplate.batchUpdate(query, rows) ;
}
Updating/Deleting object
In order to update record into the database, following lines of code is used:
@Transactional
public String updateContact(int id, String name, String email, String address, String
telephone) {
// TODO Auto-generated method stub
int s = jdbcTemplate.update("update contact set
name=?,email=?,address=?,telephone=? where contact_id=?", name,email,
address,telephone,id);
if(s>=1)
{
return "ok";
}
else
{
return "nok";
}
}
In order to delete record from database, following lines of code is used:
public String deleteContact(int id)
{
//int s=3;
// TODO Auto-generated method stub
int s=jdbcTemplate.update("Delete from Contact where contact_id="+id);
if(s>=1)
{
return "ok";
}
else
{
return "nok";
}
Some database modifications involve several SQL queries, for instance, inserting a particular
attribute across different columns in different tables. If one of the queries fails, we would want to
undo any previous ones that were successful. In order to make a DAO method transactional, we
have to put @Transactional annotation in front of DAO method as shown above.
hiberNateCfgFileName=hibernate.cfg.xml
3. hibernate.cfg.xml contains database credentials and mapping file name and has following
code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD
3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property
name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property
name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property
name="hibernate.connection.url">jdbc:mysql://localhost:3306/springdb</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">opmcm6718</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">none</property>
<mapping resource="Contact.hbm.xml" />
</session-factory>
</hibernate-configuration>
4. Contact.hbml.xml contains mapping code for mapping model class fields and database
columns.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="ch4.crud.model.Contact" table="contact">
<id name="id" type="integer" column="contact_id">
<generator class="assigned" />
</id>
</hibernate-mapping>
5. Create a file called DBConnector.java and put below codes to establish connectivity with
backed MySQL Database as shown below:
package ch4.crud.util;
import java.io.InputStream;
import java.util.Properties;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;;
static {
try {
// sessionFactory = new
Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
InputStream inputStream =
DBConnector.class.getClassLoader().getResourceAsStream( "/hibernate.properties" );
Properties properties = new Properties();
properties.load( inputStream );
String hbcfg = properties.getProperty( "hiberNateCfgFileName" );
sessionFactory =new Configuration().configure(hbcfg).buildSessionFactory();
// System.out.println("Mapping Completed");
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
session = DBConnector.openSession();
tx=session.beginTransaction();
System.out.println("List Size="+list.size());
tx.commit();
catch(Exception e)
tx.rollback();
e.printStackTrace();
finally
session.close();
return list;
Note: You have to declare following variables in order for above code to work:
Transaction tx = null;
Session session;
List<Contact> list;
MyBatis
Unlike ORM frameworks, MyBatis does not map Class fields to database tables, but maps
methods to SQL statements. Methods can be mapped to SQL statements either using
annotation based approach or using XML file. To use MyBatis for database operation you
have to follow below steps:
1. Create a file named jdbc.properties where you place database connectivity information as
shown below:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springdb
jdbc.username=root
jdbc.password=opmcm6718
2. Create a file named mybatis-config.xml inside src folder where you actually write code
for database connectivity based on information provided in jdbc.properties file.
Moreover, in this file, you specify name and location of ContactMapper.xml file where
you will map methods to SQL statements. Code for this file is shown below:
3. Create a file named ContactMapper.xml which contains code to map methods to SQL
statements as shown below:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ch4.crud.dao.ContactMapper">
<!-- Instead of referencing Fully Qualified Class Names we can register
Aliases in mybatis-config.xml and use Alias names. -->
<resultMap type="Contact" id="ContactResult">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="email" column="email"/>
<result property="address" column="address"/>
<result property="telephone" column="telephone"/>
</resultMap>
Note: All above three files should be placed inside src directory.
4. All the method name that has to perform database operation, we will specify inside an
interface called ContactMapper.java. This interface file should be placed inside
ch4.crud.dao package and contains below lines of code:
5. For establishing database connectivity using MyBatis, you have to specify codes inside
MyBatisConnector file as shown below:
package ch4.crud.util;
import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
private MyBatisConnector() {
}
static
{
Reader reader = null;
try {
reader = Resources.getResourceAsReader("mybatis-config.xml");
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
factory = new SqlSessionFactoryBuilder().build(reader);
}
public static SqlSessionFactory getSqlSessionFactory()
{
return factory;
}
}
6. You can perform database operation using MyBatis by specifying following methods
inside ContactDAOImpl.java as shown below:
Note: if you have any column or primary key which is auto incremented, then you have to
perform some extra work. For more information, refer:
http://sivalabs.in/2012/10/mybatis-tutorial-part1-crud-operations/
1. Create a Dynamic Project named CacheSecurityDemo, add all spring jar files ,
com.springsource.org.aopalliance-1.0.0.jar file both in Java Build Path and Deployment
Assembly.
2. Add a Dispatcher Servlet named CacheDemo to your project.
3. Create 3 packages namely ch4.model,ch4.dao and ch4.controller inside src folder.
4. Put person.java inside ch4.model as shown below:
package ch4.model;
}
public Person(int id, String name) {
super();
this.id = id;
this.name = name;
}
import java.util.HashMap;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import ch4.model.Person;
public class PersonDAOImpl implements PersonDAO {
Person person;
HashMap<Integer,Person> map;
public PersonDAOImpl()
{
map=new HashMap<Integer,Person>();
}
@Override
@Cacheable(value="employeeCache", key = "#id", condition="#id < 10")
public Person getPerson(int id) {
System.out.println("method called");
return map.get(id);
}
@Override
@CacheEvict(value="employeeCache", key = "#id", condition="#id < 10",
allEntries = true,beforeInvocation=true)
public void savePerson(int id,Person p) {
map.put(id, p);
// TODO Auto-generated method stub
}
7. Put MyController.java inside ch4.controller as shown below:
package ch4.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import ch4.dao.PersonDAO;
import ch4.dao.PersonDAOImpl;
import ch4.model.Person;
@Controller
public class MyController {
@Autowired
PersonDAO pdao;
@RequestMapping(value="/",method=RequestMethod.GET)
public String displayPage()
{
//return new ModelAndView("status","data");
return "mainpage";
}
@RequestMapping(value="/showResult",method=RequestMethod.GET)
public String mainmethod()
{
pdao.savePerson(pdao.getPerson().getId(),pdao.getPerson());
Person p1=pdao.getPerson(1);
System.out.println("Person Id="+p1.getId());
System.out.println("Person1 Name="+p1.getName());
System.out.println("Person1 Name="+pdao.getPerson(1).getName());
System.out.println("Person1 Name="+pdao.getPerson(1).getName());
pdao.savePerson(2, new Person(2,"Manisha Regmi"));
Person p2=pdao.getPerson(2);
System.out.println("Person2 Name="+p2.getName());
System.out.println("Person2 Name="+pdao.getPerson(2).getName());
System.out.println("Person1 Name="+pdao.getPerson(1).getName());
return "result";
}
8. Create a folder named views inside WebContent directory and create two jsp pages
namely mainpage.jsp and result.jsp as shown below:
9. mainpage.jsp should contain following code :
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h1>This is Demo Project</h1>
<a href="/CacheSecurityDemo/showResult">Click Here for Demo</a>
</body>
</html>
11. Create a file named CacheDemo-servlet.xml inside WEB-INF directory and place
following code over there:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="ch4.controller" />
<cache:annotation-driven />
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="personObj" class="ch4.model.Person">
<property name="id">
<value type="java.lang.Integer">1</value>
</property>
<property name="name" value="Mukesh" />
</bean>
<bean id="pdao" class="ch4.dao.PersonDAOImpl">
<property name="person" ref="personObj" />
</bean>
<bean id="cacheManager"
class="org.springframework.cache.support.SimpleCacheManager" >
<property name="caches">
<set>
<bean
class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
p:name="employeeCache"/>
</set>
</property>
</bean>
</beans>
Important Notes:
1. In Controller class, we have to specify code to autowire interface not the concrete
class i.e. implementation( We have to declare PersonDAO not PersonDAOImpl).
2. However, from the dispatcher servlet context file (i.e.CacheDemo-servlet-xml),
we can inject concrete class PersonDAOImpl as shown below:
<bean id="pdao" class="ch4.dao.PersonDAOImpl">
<property name="person" ref="personObj" />
</bean>
Note: The complete code of CacheDemo-servlet.xml is shown in above steps:
3. The reason for doing this is: spring will create a proxy object if we are using the
caching mechanism and we can cache only a function that is inside a singleton
object(Autowired bean i.e. PersonDAO)
Analysis of Output:
Methods where we have implemented caching logic are located inside PersonDAOImpl class as
shown below:
We are going to keep Person object will id as key in Hashmap in above application.
In above code, we have defined the caching logic through @Cachable annotation. Name
of the cache is employeeCache, key to index items on cash is id and the value from
cache will be fetched ony when id is less than 10; otherwise method itself will be
called.
And
@CacheEvict(value="employeeCache", key = "#id", condition="#id < 10", allEntries =
true,beforeInvocation=true)
public void savePerson(int id,Person p) {
map.put(id, p);
Name of the cache is employeeCache, key to index items on cash is id and the cache is cleared
only when id is less than 10. All entries of cache will be cleared before method is executed.
a) method called
Line no 2 of Controller code will produce above output because id is less than 1 and actual
method[getPerson(id)] will be called and hence the output produced. Note: getPerson(1) will
return an object with an id=1 as we have injected a Person object with id=1 through
dispatcher servlet context file.
b) Person Id=1
Line no 3 is responsible for producing this output. With returned object from Line no 2,
we will print the corresponding id.
c) Person1 Name=Mukesh
Line no 4 is responsible for producing this output. With returned object from Line no 2,
we will print the corresponding name.
d) Person1 Name=Mukesh
Line no 5 is responsible for this output. This output is the proof of caching logic being
implemented as you can see "method called" is not displayed here even while calling
getPerson(1). This is because, person with id=1 is already in cache and hence it is
retrieved from there not from the method.
e) Person1 Name=Mukesh
Line no 6 is responsible for this output. This output is again the confirmation of the proof of
caching logic being implemented as you can see "method called" is not displayed here again.
This is because, person with id=1 is already in cache and hence it is retrieved from there not
from the method.
f) method called
Line no 8 is responsible for this output. Here, "method called" is displayed because, Line
no 7 had cleared the cache before saving any object and as the cache is now
empty[ nothing to retrieve from cache] and hence getPerson(2) method is called.
g) Person2 Name=Manisha Regmi
Line no 9 is responsible for this output. This output is the proof of caching logic being
implemented as you can see "method called" is not displayed here even while calling
getPerson(2). This is because, person with id=2 is already in cache and hence it is
retrieved from cache not from the method.
h) Person2 Name=Manisha Regmi
Line no 10 is responsible for this output. This output is again the confirmation of the proof
of caching logic being implemented as you can see "method called" is not displayed here
again. This is because, person with id=2 is already in cache and hence it is retrieved from
there not from the method.
i) method called
In Line no 7, cache was cleared before calling savePerson() method and hence cache is
emptied by Line no 7 before method invocation. After savePerson() method is called, it will
keep an item[i.e. Person Class Object] with id=2 in the cache. As there is not any item in the
cache with id=1 pdao.getPerson(1) in Line no 11 is responsible for producing this output. It
means getPerson(1) actual method is called and person object is returned from it.
j) Person1 Name=Mukesh
Code responsible for producing above output is written inside MyController as shown below:
@RequestMapping(value="/showResult",method=RequestMethod.GET)
public String mainmethod()
{
1. pdao.savePerson(pdao.getPerson().getId(),pdao.getPerson());
2. Person p1=pdao.getPerson(1);
3. System.out.println("Person Id="+p1.getId());
4. System.out.println("Person1 Name="+p1.getName());
5. System.out.println("Person1 Name="+pdao.getPerson(1).getName());
6. System.out.println("Person1 Name="+pdao.getPerson(1).getName());
7. pdao.savePerson(2, new Person(2,"Manisha Regmi"));
8. Person p2=pdao.getPerson(2);
9. System.out.println("Person2 Name="+p2.getName());
10. System.out.println("Person2 Name="+pdao.getPerson(2).getName());
11. System.out.println("Person1 Name="+pdao.getPerson(1).getName());
return "result";
}
In above examples, we have used SimpleCacheManager for managing cache. There are many
other CacheManager available to manage cache. One of them is EhCacheCache Manager. To use
EhCacheManager, follow below steps:
1. Add jar files namely ehcache-2.7.0.jar,sl4j-api-1.7.21.jar in both Java Build Path and
Deployment Assembly.
2. Create a file named ehcache.xml inside WEB-INF and put following codes inside it.
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
<cache name="employeeCache"
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU" >
</cache>
</ehcache>
<bean id="cache.provider.ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="/WEB-INF/ehcache.xml" />
</bean>
References:
1. https://mytechrepo.wordpress.com/2015/07/23/caching-data-with-spring-3-1-1-
and-ehcache-demo/
2. http://www.javacreed.com/caching-made-easy-with-spring/
3. https://java2practice.com/2013/03/23/spring-cacheable-and-cacheevict-
explained-in-simple-terms/
Securing Methods
Securing methods means controlling which particular user or which particular user having
particular roles is allowed to access a method. Spring methods can be secured by applying
different types of annotations.
@Secured
@RolesAllowed
@PreAuthorize,@PostAuthorize,@PreFilter,@PostFilter
Sample Application:
1. Create a Dynamic Project named SecurityDemo and add dispatcher servlet named
security for it.
2. For Spring security, you need to add 5 more jar files namely spring-dao-2.0.3.jar, spring-
security-config-3.0.3.RELEASE.jar, spring-security-core-3.0.3.RELEASE.jar, spring-
security-taglibs-3.0.3.RELEASE.jar, spring-security-web-3.0.3.RELEASE.jar [ Both in
Java Build Path and Deployment Assembly]
3. Create a folder named ch4.security.controller inside src folder and create a java file
named MyController inside it. MyController.java should contain following codes:
package ch4.security.controller;
import javax.annotation.security.RolesAllowed;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MyController {
@Secured("ROLE_USER")
@RequestMapping(value="/main", method = RequestMethod.GET)
public String printWelcome( ) {
return "main_page";
}
@Secured("ROLE_ADMIN")
@RequestMapping(value="/userPage", method = RequestMethod.GET)
public String displayUserPage( ) {
return "user";
}
@PreAuthorize("hasRole('ROLE_USER') AND hasRole('ROLE_DBA')")
@RequestMapping(value="/prePage", method = RequestMethod.GET)
public String displayPrePage( ) {
return "preauthorize";
}
@RequestMapping(value="/loginError", method = RequestMethod.GET)
public String loginerror() {
return "login";
}
@RequestMapping(value="/login", method = RequestMethod.GET)
public String login() {
System.out.println("Hello adasd");
return "login";
}
@Secured({"ROLE_REGULAR_USER","ROLE_ADMIN"})
@RequestMapping(value="/common", method = RequestMethod.GET)
public String common(ModelMap model) {
return "common_page";
}
@RolesAllowed("ROLE_ADMIN")
@RequestMapping(value="/admin", method = RequestMethod.GET)
public String admin(ModelMap model) {
return "admin_page";
}
}
4. Create context file for dispatcher servlet named security-servlet.xml inside WEB-INF
directory and place following code inside it:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
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.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
<context:component-scan base-package="ch4.security.controller"/>
<security:global-method-security secured-annotations="enabled" pre-post-
annotations="enabled" jsr250-annotations="enabled"/>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans:beans>
Note:
i) Spring security jar files should be version 3.0.3 otherwise you have to
modify the schema-location URL.
ii) <security:global-method-security secured-annotations="enabled" pre-post-
annotations="enabled" jsr250-annotations="enabled"/> must be placed in
this file not in other files. secured-annotations="enabled" will allow
@Secured annotation to be used on our application. pre-post-
annotations="enabled" allows us to use @PreAuthorize and @PostAuthorize
annotation on our application. Similarly, jsr250-annotations="enabled"
allows us to use @RolesAllowed annotation to be used in our application.
5. Create a file named application-security.xml inside WEB-INF directory and put
following codes inside it:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
<http auto-config="false" use-expressions="false">
<intercept-url pattern="/main*" access="ROLE_ADMIN,ROLE_USER" />
<form-login login-page="/login" default-target-url="/main"
authentication-failure-url="/loginError" />
<logout logout-success-url="/logout" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="mukesh" password="password" authorities="ROLE_USER"
/>
<user name="admin" password="password"
authorities="ROLE_DBA,ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
Note: i) if you closely look at above file, you can see that you have defined two users
namely mukesh and admin. "mukesh" user has role named "ROLE_USER". Similarly,
admin user has two different roles namely ROLE_DBA and ROLE_ADMIN.
ii) To access login page, the URL is /login and if login is successful, it will be
redirected to URL namely /main and if login is not successful, it will be redirected
to URL namely /loginError
6. Your web.xml file which is also located inside WEB-INF should contain following code:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID"
version="2.5">
<display-name>SecurityDemo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>security</display-name>
<servlet-name>security</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</
servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>security</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</
filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</
listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/security-servlet.xml
/WEB-INF/application-security.xml
</param-value>
</context-param>
</web-app>
Note:
<table>
<tr>
<td>User:</td>
<td><input type='text' name='j_username' value=''>
</td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='j_password' />
</td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit"
value="submit" />
</td>
<td colspan='2'><input name="reset" type="reset" />
</td>
</tr>
</table>
</form>
</body>
</html>
Analysis:
1. Both users "mukesh" and "admin" whenever tries to access /login URL, and if login is
successful, they will be redirected to /main URL. Even though in application-
security.xml we have mentioned that /main URL can be accessed by users which has
ROLE_ADMIN and ROLE_USER privileges, but in corresponding Controller method
which deals with /main URL[i.e. printWelcome() method] we have specified
@Secured("ROLE_USER") annotation, it means the above mentioned method can only
be accessed by user having ROLE_USER privilege. Hence, login will be successful in
case of user "mukesh" only. If login is successful, main_page.jsp will be displayed as
shown below:
2. If the same user tries to click "Click here for User Page" link above, then it is not
allowed because in the corresponding Controller method that deals with the above URL
click is displayUserPage( ) [ mapping is done for URL: /userPage] we have specified
@Secured("ROLE_ADMIN") annotation. Since the user "mukesh" does not have
ROLE_ADMIN privilege, he is not allowed to click on above link.
3. If the same user tries to click "Click here for Accessing Pre Authorize Page" link above,
then it is not allowed because in the corresponding Controller method that deals with the
above URL click is displayPrePage( ) [ mapping is done for URL: /prePage] we have
specified @PreAuthorize("hasRole('ROLE_USER') AND hasRole('ROLE_DBA')")
annotation. Since the user "mukesh" does not have ROLE_DBA only has ROLE_USER
privilege, he is not allowed to click on above link.
4. If the same user tries to click "Click here for Accessing Admin Page" link above, then it
is not allowed because in the corresponding Controller method that deals with the above
URL click is di admin(ModelMap model) [ mapping is done for URL: /admin] we have
specified @RolesAllowed("ROLE_ADMIN") annotation. Since the user "mukesh" does
not have ROLE_ADMIN privilege, he is not allowed to click on above link.
References
1. http://www.studytrails.com/frameworks/spring/spring-security-method-level.jsp
2. http://howtodoinjava.com/spring/spring-security/login-form-based-spring-3-
security-example/
3. http://howtodoinjava.com/spring/spring-security/spring-3-method-level-
security-example-using-preauthorize-and-secured/
JDO
JDO called Java Data Objects is a java standard for persisting the Java POJOs. It offers facilities
such as object-level querying and transparent persistence through automatic change detection. It
uses query called JDOL's programmatic query objects with sub-expressions rather than HQL for
Hibernate.
Apache OJB
It is an Object/Relational mapping tool that allows mapping between Java Objects and relational
database. It uses XML based O/R mapping.
TopLink
TopLink is an advanced object-persitance and object-transformation framework owned by
Oracle. It provides a framework for storing Java objects in a relational database or for converting
Java objects to XML documents.
TopLink provides a rich user interface through the TopLink Mapping Workbench. The Mapping Workbench allows for
graphical mapping of an object model to a data model, as allows for generation of a data model from an object model,
and generation of an object model from a data model, and auto-mapping of an existing object and data model.
References:
1. https://en.wikibooks.org/wiki/Java_Persistence/TopLink
2. http://docs.oracle.com/cd/B32110_01/web.1013/b28218/undtl.htm#JITDG00004
3. http://docs.oracle.com/cd/E21764_01/web.1111/b32441/undtl.htm#JITDG91123
Cayenne
Cayenne is an open source persistence framework that provides ORM and remoting facilities.
Developers of the open source Cayene O/R mapping project has also developed Spring support
for their product. Cayenne binds one or more database schemas directly to Java objects,
managing atomic commit and rollbacks, SQL generation, joins, sequences, and more. With
Cayenne's Remote Object Persistence, those Java objects can even be persisted out to clients
via Web Services. Or, with native XML serialization, objects can be further persisted to non-Java
clients—such as an Ajax-capable browser.
Cayenne supports other features, including caching, a complete object query syntax, relationship
pre-fetching, on-demand object and relationship faulting, object inheritance, database auto-
detection, and generic persisted objects. Most importantly, Cayenne can scale up or down to
virtually any project size.
References
1. https://en.wikipedia.org/wiki/Apache_Cayenne
JSR-220 Persistence
Spring can be integrated with additional or emerging persistence technologies for e.g. POJO
persistence specification delivered by JSR-220(EJB 3.0) expert group. Similarly, Spring can be
integrated with other persistent framework as well.