Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Points To Remember



Pagination in Spring Hibernate Application using Bootstrap


  • Create a Domain Person.
  • Create a Service PersonService
  • Create a Dao PersonDao.
  • Create a Controller PersonController.
  • Create a Taglib PaginationTaglib.

Person.java
package com.ekiras.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="person")
public class Person {

public Person(){};
public Person(String name,Integer age){
this.name = name;
this.age = age;
}


@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id")
private Long id;

@Column(name="name")
private String name;

@Column(name="age")
private Integer age;

// GETTERS and SETTERS

PersonService.java
package com.ekiras.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ekiras.dao.PersonDAO;
import com.ekiras.domain.Person;

@Service
public class PersonService {

@Autowired
private PersonDAO personDAO;


public List<Person> list(Integer offset, Integer maxResults){
return personDAO.list(offset, maxResults);
}

public Long count(){
return personDAO.count();
}

public void save(){
personDAO.save();
}

}

PersonDAO.java
package com.ekiras.dao;

import java.util.List;

import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.ekiras.domain.Person;

@Repository
@Transactional
public class PersonDAO {

@Autowired
private SessionFactory sessionFactory;

@SuppressWarnings("unchecked")
@Transactional
public List<Person> list(Integer offset, Integer maxResults){
return sessionFactory.openSession()
.createCriteria(Person.class)
.setFirstResult(offset!=null?offset:0)
.setMaxResults(maxResults!=null?maxResults:10)
.list();
}


public Long count(){
return (Long)sessionFactory.openSession()
.createCriteria(Person.class)
.setProjection(Projections.rowCount())
.uniqueResult();
}


public void save(){
for(int itr=1;itr <= 100 ; itr++){
Person person = new Person("Person_"+itr,Math.max(25, (itr%2)*35));
sessionFactory.openSession()
.save(person);
}



}

}

PersonController.java
package com.ekiras.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.ekiras.service.PersonService;

@Controller
@RequestMapping(value="/person")
public class PersonController {

@Autowired
private PersonService personService;

@RequestMapping(value="/list")
public String list(Model model, Integer offset, Integer maxResults){
model.addAttribute("persons", personService.list(offset, maxResults));
model.addAttribute("count", personService.count());
model.addAttribute("offset", offset);
return "/person/list";
}

@RequestMapping(value="/save")
public String save(){
personService.save();
return "/person/list";
}

}

PaginationTaglib.java
package com.ekiras.taglib;

import java.io.Writer;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class PaginationTaglib extends SimpleTagSupport {
private String uri;
private int offset;
private int count;
private int max = 10;
private int steps = 10;
private String previous = "Previous";
private String next = "Next";

private Writer getWriter() {
JspWriter out = getJspContext().getOut();
return out;
}

@Override
public void doTag() throws JspException {
Writer out = getWriter();

try {
out.write("<nav>");
out.write("<ul class=\"pagination\">");

if(offset<steps)
out.write(constructLink(1, previous, "disabled", true));
else
out.write(constructLink(offset-steps, previous, null, false));

for(int itr=0;itr<count;itr+=steps) {
if(offset==itr)
out.write(constructLink((itr/10+1)-1 *steps, String.valueOf(itr/10+1), "active", true));
else
out.write(constructLink(itr/10*steps, String.valueOf(itr/10+1), null , false));
}

if(offset+steps>=count)
out.write(constructLink(offset+steps, next, "disabled", true));
else
out.write(constructLink(offset+steps, next, null , false));


out.write("</ul>");
out.write("</nav>");
} catch (java.io.IOException ex) {
throw new JspException("Error in Paginator tag", ex);
}
}


private String constructLink(int page, String text, String className, boolean disabled) {
StringBuilder link = new StringBuilder("<li");
if (className != null) {
link.append(" class=\"");
link.append(className);
link.append("\"");
}
if(disabled)
link.append(">").append("<a href=\"#\">"+text+"</a></li>");
else
link.append(">").append("<a href=\""+uri+"?offset="+page + "\">"+text+"</a></li>");
return link.toString();
}

public String getUri() {
return uri;
}

public void setUri(String uri) {
this.uri = uri;
}

public int getOffset() {
return offset;
}

public void setOffset(int offset) {
this.offset = offset;
}

public int getCount() {
return count;
}

public void setCount(int count) {
this.count = count;
}

public int getMax() {
return max;
}

public void setMax(int max) {
this.max = max;
}

public String getPrevious() {
return previous;
}

public void setPrevious(String previous) {
this.previous = previous;
}

public String getNext() {
return next;
}

public void setNext(String next) {
this.next = next;
}

public int getSteps() {
return steps;
}

public void setSteps(int steps) {
this.steps = steps;
}

}

list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="tag" uri="/WEB-INF/taglibs/customTaglib.tld"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!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=UTF-8">
<link rel="stylesheet" type="text/css" href="/css/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="/css/font-awesome.min.css" />
<title>| Ekiras</title>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span> <span
class="icon-bar"></span> <span class="icon-bar"></span> <span
class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>

<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse"
id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
<li><a href="#">Link</a></li>
<li class="dropdown"><a href="#" class="dropdown-toggle"
data-toggle="dropdown" role="button" aria-expanded="false">Dropdown
<span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
<li class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul></li>
</ul>
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Link</a></li>
<li class="dropdown"><a href="#" class="dropdown-toggle"
data-toggle="dropdown" role="button" aria-expanded="false">Dropdown
<span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul></li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container-fluid --> </nav>

<div class="container">
<div class="well">
<strong>List of Persons</strong>
</div>
<table class="table table-stripped">
<tr>
<th>S.No</th>
<th>Name</th>
<th>Age</th>
</tr>
<c:forEach items="${persons}" var="person" varStatus="itr">
<tr>
<td>${offset + itr.index +1 }</td>
<td>${person.name }</td>
<td>${person.age }</td>
</tr>
</c:forEach>
</table>
<tag:paginate max="15" offset="${offset}" count="${count}"
uri="/person/list" next="&raquo;" previous="&laquo;" />
</div>


<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/bootstrap.min.js"></script>
</body>
</html>

This is how you can do pagination using bootstrap style in spring hibernate mvc application.


Points To Remember

You need to add the following dependencies to pom.xml

  1. spring-core
  2. spring-context
  3. spring-web
  4. spring-webmvc
  5. spring-tx
  6. spring-orm
  7. mysql-connector-java
  8. jstl
  9. hibernate 

Create  Maven Spring Hibernate Sitemesh Annotation based Hello World project

pom.xml
pom.xml should contain the following dependencies
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples.service.service</groupId>
<artifactId>ekiras</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>


<properties>
<java.version>1.7</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring.version>3.2.8.RELEASE</spring.version>
<junit.version>4.11</junit.version>
<sitemesh.version>3.0.0</sitemesh.version>
<hibernate.version>4.2.1.Final</hibernate.version>
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
<jsp.version>2.2</jsp.version>
<jstl.version>1.2</jstl.version>
<servlet.version>2.5</servlet.version>
</properties>



<dependencies>


<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>

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

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

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

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

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

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

<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.31</version>
</dependency>

<!-- jstl for jsp page -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp.version}</version>
<scope>provided</scope>
</dependency>

<!-- Sitemesh -->
<dependency>
<groupId>org.sitemesh</groupId>
<artifactId>sitemesh</artifactId>
<version>${sitemesh.version}</version>
</dependency>


<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>

<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>

<!-- Test Artifacts -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
</dependencies>
</project>

web.xml
web.xml should contain the dispatcher servlet and other config files.
<?xml version="1.0" encoding="ISO-8859-1"?>
<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>ekiras</display-name>

<!-- - Location of the XML file that defines the root application context.
- Applied by ContextLoaderListener. -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring/application-config.xml,
/WEB-INF/conf/mvc-config.xml
</param-value>
</context-param>


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



<!-- ****************** Servlet Dispatcher ********************** -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/conf/mvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/resources/css/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/resources/js/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/resources/images/*</url-pattern>
</servlet-mapping>





<!-- ****************** Sitemesh ********************** -->

<filter>
<filter-name>sitemesh</filter-name>
<filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>
<!-- Changing default sitemsh xml file name and path -->
<init-param>
<param-name>configFile</param-name>
<param-value>/WEB-INF/conf/sitemesh.xml</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


<!-- ****************** ERROR PAGES ********************** -->

<error-page>
<error-code>400</error-code>
<location>/400</location>
</error-page>

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

<error-page>
<error-code>500</error-code>
<location>/500</location>
</error-page>

<error-page>
<error-code>503</error-code>
<location>/503</location>
</error-page>


</web-app>
mvc-config.xml
mcv config should contain the configurations related to web properties and database properties.
<?xml version="1.0" encoding="UTF-8"?>

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


<context:property-placeholder location="/WEB-INF/conf/jdbc.properties" />
<context:component-scan base-package="com.ekiras" />


<mvc:annotation-driven />
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>



<mvc:resources location="/resources/css/" mapping="/css/**" />
<mvc:resources location="/resources/js/" mapping="/js/**" />

<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- **************** HIBERNATE PROPERTIES ******************** -->

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

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

<!-- **************** END HIBERNATE PROPERTIES **************** -->
</beans>
database.properties
database.properties should contain all the database relates configurations
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test_db
jdbc.username=root
jdbc.password=password

All the other project structure is available in the downloadable example below. It contains the project structure based on best practices.


Points To Remember

  1. You need to first add the errors in the web.xml and redirect them to a url.
  2. Then you need to map these url to controller to handle them and take necessary actions. 

Custom Error Pages

Here in this example we are going to create custom error pages in our spring mvc application. So will first of all configure the error codes in web.xml like the following.

web.xml
 <error-page>
<error-code>400</error-code>
<location>/400</location>
</error-page>

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

<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
Now when we have configured the error codes and mapped then with the respective url's, we will now create a Controller that will map these error code url's like the following.

HTTPErrorHandler.java
package com.ekiras.util;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HTTPErrorHandler{

String path = "/error";

@RequestMapping(value="/400")
public String error400(){
System.out.println("custom error handler");
return path+"/400";
}

@RequestMapping(value="/404")
public String error404(){
System.out.println("custom error handler");
return path+"/404";
}

@RequestMapping(value="/500")
public String error500(){
System.out.println("custom error handler");
return path+"/500";
}


}
So now our Controller will handle the error code url's and will redirect them to the custom error page url's.

What is Spring Roo ?
Spring Roo is a spring productivity tool that simply reduces the pain of a developer by doing all the configuration related stuff for a project. Spring Roo does not require any extra knowledge  expect java. Roo makes it fast and easy to build full Java applications in minutes.

Why Use Spring Roo ?
Following are the points why we should use Spring Roo.
  • Higher Productivity - We can get started with the java project just in minutes and the roo follows the best practice standard methods to create the application for us
  • Stock Standard Java - Roo works perfectly with all the versions of java from Java 5.0 and above. So you need not to upgrade your java versions. Roo works perfectly with projects for Spring, JSP's ,  JPA like Hibernate etc. So working with Roo will be very easy and familiar for a developer.
  • Usable and Learnable - 
  • No Engineering Tradeoffs - Roo is not a part of Production code, hence Roo in no way can have any trade-off effects on the code. It will neither effect the uptime of the application nor it will comsume CPU time or any sort of emory.
  • Easy Roo Removal -   Since Roo is not a part of the runtime code. Thus in any case, if you want to get rid of roo, you can do that without changing anything from the production code. It can also be removed with few easy steps.
Points To Remember
  • Spring Roo is not a runtime. It means that it is not involved in anyway in the production code, no classes, no annotations, no dependencies.
  • Roo is not an IDE plugin. You can access the Roo in the roo terminal.
  • Roo is not an annotation processing library.
  • Roo works perfetly with java 5.0+.
Getting Started.
Installing and Getting started with Spring Roo