Welcome to JSF Spring Hibernate Integration example tutorial. In our last tutorial, we saw how to integrate JSF and Spring frameworks together. Today we will learn how to integrate JSF Spring Hibernate frameworks. This is a favorable combination where we are using the best choice for user interface, server side dependency injection and ORM tool.
JSF Spring Hibernate
Our goal is to create a single page user interface from which we can enter some data that goes into database. We get the same response page where we also show the data from the table, so newly added data should also be there on page submit.
Below image shows our final spring jsf hibernate integration project structure. Let’s start now with the project and see how each of the frameworks are glued together to achieve our goal.
JSF Spring Hibernate Project Setup
Create a Dynamic Web Project in Eclipse and then convert it to Maven project, so that we have basic setup ready. Now we must add required dependencies in our pom.xml file. Below is our final pom.xml file. Notice the JSF, Spring, Spring ORM and Hibernate dependencies. We are using MySQL database for our example and Apache DBCP for creating simple database connection pool.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>JSF_Spring_Hibernate</groupId> <artifactId>JSF_Spring_Hibernate</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <!-- Generic properties --> <java.version>1.6</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!-- Spring --> <spring-framework.version>4.0.3.RELEASE</spring-framework.version> <aspectj.version>1.7.4</aspectj.version> <!-- Hibernate / JPA --> <hibernate.version>4.3.5.Final</hibernate.version> <!-- JSF Version --> <jsf.version>2.2.10</jsf.version> <!-- Logging --> <logback.version>1.0.13</logback.version> <slf4j.version>1.7.5</slf4j.version> </properties> <dependencies> <!-- Spring and Transactions --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring-framework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring-framework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring-framework.version}</version> </dependency> <!-- @Inject --> <dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency> <!-- AspectJ --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> </dependency> <!-- Spring ORM support --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring-framework.version}</version> </dependency> <!-- Hibernate --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.9</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <!-- JSF Dependencies --> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-api</artifactId> <version>${jsf.version}</version> </dependency> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-impl</artifactId> <version>${jsf.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> <!-- https://repo1.maven.org/maven --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> </dependency> <dependency> <groupId>com.sun.el</groupId> <artifactId>el-ri</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <warSourceDirectory>WebContent</warSourceDirectory> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins> <finalName>${project.artifactId}</finalName> </build> </project> |
Now use below script to create the required table in database.
1 2 3 4 5 6 7 8 |
CREATE TABLE `Person` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL DEFAULT '', `country` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; |
Next we need is to add Spring Listener and JSF Controller Servlet in the web.xml file as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="https://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> </web-app> |
Next we need JSF to integrate with Spring framework, for that we need to configure SpringBeanFacesELResolver
in faces-config.xml
file. It will make sure that JSF view pages variables are mapped to the backend managed beans.
faces-config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?xml version='1.0' encoding='UTF-8'?> <faces-config version="2.2" xmlns="https://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"> <application> <el-resolver> org.springframework.web.jsf.el.SpringBeanFacesELResolver </el-resolver> </application> </faces-config> |
The last configuration we need is the spring beans configuration but we will look at that after going through the java classes.
JSF Spring Hibernate Model Classes
We have Person.java
class that is mapped with the Person table in database. Notice the use of JPA and JSF annotations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
package com.journaldev.springhibernate.model; import javax.faces.bean.ManagedBean; 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 bean with JPA annotations * Hibernate provides JPA implementation * @author pankaj * */ @Entity @Table(name="PERSON") @ManagedBean(name="person") public class Person { @Id @Column(name="id") @GeneratedValue(strategy=GenerationType.IDENTITY) private int id; private String name; private String country; 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 getCountry() { return country; } public void setCountry(String country) { this.country = country; } @Override public String toString(){ return "id="+id+", name="+name+", country="+country; } } |
Now we will move over to creating DAO classes to interact with the database tables.
JSF Spring Hibernate DAO Classes
PersonDAO.java
1 2 3 4 5 6 7 8 9 |
package com.journaldev.springhibernate.dao; import java.util.List; import com.journaldev.springhibernate.model.Person; public interface PersonDAO { public void addPerson(Person p); public List<Person> listPersons(); } |
We have two method, one to insert data into database table and another one to fetch the list of Persons to display in user interface.
Below is the implementation class for above DAO.
PersonDAOImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package com.journaldev.springhibernate.dao; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Repository; import com.journaldev.springhibernate.model.Person; @Repository public class PersonDAOImpl implements PersonDAO{ private static final Logger logger = LoggerFactory.getLogger(PersonDAOImpl.class); private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sf){ this.sessionFactory = sf; } @Override public void addPerson(Person p) { Session session = this.sessionFactory.getCurrentSession(); session.persist(p); logger.info("Person saved successfully, Person Details="+p); } @SuppressWarnings("unchecked") @Override public List<Person> listPersons() { Session session = this.sessionFactory.getCurrentSession(); List<Person> personsList = session.createQuery("from Person").list(); for(Person p : personsList){ logger.info("Person List::"+p); } return personsList; } } |
Now we will create service classes and then do the wiring.
JSF Spring Hibernate Service Classes
PersonService.java
1 2 3 4 5 6 7 8 9 |
package com.journaldev.springhibernate.service; import java.util.List; import com.journaldev.springhibernate.model.Person; public interface PersonService { public void addPerson(Person p); public List<Person> listPersons(); } |
PersonServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.journaldev.springhibernate.service; import java.util.List; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.journaldev.springhibernate.dao.PersonDAO; import com.journaldev.springhibernate.model.Person; @Service @ManagedBean(name="personService") @SessionScoped public class PersonServiceImpl implements PersonService { private PersonDAO personDAO; public void setPersonDAO(PersonDAO personDAO) { this.personDAO = personDAO; } @Override @Transactional public void addPerson(Person p) { this.personDAO.addPerson(p); } @Override @Transactional public List<Person> listPersons() { return this.personDAO.listPersons(); } } |
Notice the use of @ManagedBean
JSF annotation and @Transactional
annotation for transaction management.
Recommended Read: Spring Hibernate Integration and Spring Transaction Management
Spring Beans Configuration File
Our Spring Hibernate based backend services are ready, now we can wire them in the spring beans configuration file as shown below.
applicationContext.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="https://www.springframework.org/schema/mvc" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:beans="https://www.springframework.org/schema/beans" xmlns:context="https://www.springframework.org/schema/context" xmlns:tx="https://www.springframework.org/schema/tx" xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --> <!-- Enables the Spring MVC @Controller programming model --> <annotation-driven /> <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory --> <resources mapping="/resources/**" location="/resources/" /> <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <beans:property name="driverClassName" value="com.mysql.jdbc.Driver" /> <beans:property name="url" value="jdbc:mysql://localhost:3306/TestDB" /> <beans:property name="username" value="pankaj" /> <beans:property name="password" value="pankaj123" /> </beans:bean> <!-- Hibernate 4 SessionFactory Bean definition --> <beans:bean id="hibernate4AnnotatedSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <beans:property name="dataSource" ref="dataSource" /> <beans:property name="annotatedClasses"> <beans:list> <beans:value>com.journaldev.springhibernate.model.Person</beans:value> </beans:list> </beans:property> <beans:property name="hibernateProperties"> <beans:props> <beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect </beans:prop> <beans:prop key="hibernate.show_sql">true</beans:prop> </beans:props> </beans:property> </beans:bean> <beans:bean id="personDAO" class="com.journaldev.springhibernate.dao.PersonDAOImpl"> <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" /> </beans:bean> <beans:bean id="personService" class="com.journaldev.springhibernate.service.PersonServiceImpl"> <beans:property name="personDAO" ref="personDAO"></beans:property> </beans:bean> <context:component-scan base-package="com.journaldev" /> <tx:annotation-driven transaction-manager="transactionManager" /> <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" /> </beans:bean> </beans:beans> |
Notice the dataSource configuration, you will have to adjust them according to your setup.
JSF View Page
The last part is to write JSF view page and use the managed beans as configured above.
person.xhtml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml" xmlns:h="https://java.sun.com/jsf/html" xmlns:ui="https://java.sun.com/jsf/facelets" xmlns:c="https://java.sun.com/jsp/jstl/core"> <h:head> <title>JSF Spring Hibernate Integration</title> <style type="text/css"> .tg { border-collapse: collapse; border-spacing: 0; border-color: #ccc; } .tg td { font-family: Arial, sans-serif; font-size: 14px; padding: 10px 5px; border-style: solid; border-width: 1px; overflow: hidden; word-break: normal; border-color: #ccc; color: #333; background-color: #fff; } .tg th { font-family: Arial, sans-serif; font-size: 14px; font-weight: normal; padding: 10px 5px; border-style: solid; border-width: 1px; overflow: hidden; word-break: normal; border-color: #ccc; color: #333; background-color: #f0f0f0; } .tg .tg-4eph { background-color: #f9f9f9 } </style> </h:head> <h:body> <h1>Add a Person</h1> <h:form> <table> <tr> <td><label>Name</label></td> <td><h:inputText id="name" value="#{person.name}"></h:inputText> </td> </tr> <tr> <td><label>Country</label></td> <td><h:inputText id="country" value="#{person.country}"></h:inputText> </td> </tr> <tr> <td colspan="2"><h:commandButton action="#{personService.addPerson(person)}" value="Add Person"></h:commandButton> </td> </tr> </table> </h:form> <br> <h3>Persons List</h3> <c:if test="${!empty personService.listPersons()}"> <table class="tg"> <tr> <th width="80">Person ID</th> <th width="120">Person Name</th> <th width="120">Person Country</th> </tr> <ui:repeat value="${personService.listPersons()}" var="person"> <tr> <td>${person.id}</td> <td>${person.name}</td> <td>${person.country}</td> </tr> </ui:repeat> </table> </c:if> </h:body> </html> |
That’s it, now just deploy the application in your favorite servlet container and run it, you should get below page.
I already have some entries in the Person table and that is shown in the list above, for the first time you won’t see the list.
As always, you can download the project from below link and play around with it to learn more.