The goal of this article is to show you how you can use Hibernate, Spring and JSF 1.2 in the most easiest way.
Used technologies :
- maven 2
- JSF 1.2 (MyFaces)
- Spring 2.5.6
- Hibernate 3.2.1.GA
In the example I will use mysql just for the configuration. You can use whatever you want. The goal that we want is to use Spring for management of transactions and as IoC container. The beast way for us is to make everything spring beans. In typical application we will have Services, DAOs, Entity objects and JSF managed beans. We will make all of them spring beans and use @Autowired annotation (included in Spring). We will use GenericDAO implementation which is explained in this article: http://gochev.blogspot.com/2009/08/hibernate-generic-dao.html.
First lets create a maven 2 project and add replace update it’s pom.xml to looks like this, note that the pom is big we will explain important sections after the whole content.
<?xml version=“1.0” encoding=“UTF-8”?>
<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/maven-v4_0_0.xsd”>
<modelVersion>4.0.0</modelVersion>
<groupId>myproject-web</groupId>
<artifactId>myproject-web</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>A custom project using myfaces</name>
<url>http://www.myorganization.org</url>
<build>
<finalName>myproject-web</finalName>
<plugins>
<plugin>
<!–This plugin allows to run the example using mvn jetty:run –>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.8</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<wtpversion>2.0</wtpversion>
<wtpapplicationxml>true</wtpapplicationxml>
<wtpmanifest>true</wtpmanifest>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<manifest>${basedir}/src/main/resources/META-INF/MANIFEST.MF</manifest>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>apache-maven-snapshots</id>
<url>http://people.apache.org/repo/m2-snapshot-repository</url>
</repository>
<repository>
<id>java.net</id>
<url>http://download.java.net/maven/1</url>
<layout>legacy</layout>
</repository>
<repository>
<id>java.net2</id>
<url>http://download.java.net/maven/2</url>
<layout>legacy</layout>
</repository>
<repository>
<id>repository.jboss.com</id>
<url>http://repository.jboss.com/maven2/</url>
<layout>default</layout>
</repository>
<repository>
<id>repo1</id>
<name>repo1</name>
<url>http://repo1.maven.org/maven2/</url>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</repository>
</repositories>
<!– Project dependencies –>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.2.1.GA</version>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>1.2.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-impl</artifactId>
<version>1.2.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.myfaces.tomahawk</groupId>
<artifactId>tomahawk</artifactId>
<version>1.1.6</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.sun.facelets</groupId>
<artifactId>jsf-facelets</artifactId>
<version>1.1.14</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.richfaces.framework</groupId>
<artifactId>richfaces-impl</artifactId>
<version>3.2.2.SR1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.richfaces.ui</groupId>
<artifactId>richfaces-ui</artifactId>
<version>3.2.2.SR1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
</dependencies>
</project>
Most of you don’t need explanation but for the rest I will explain the most strange sections. Starting from last one c3p0 – I use it because sometimes mysql closes my idle connection which are in the connection pool. The c3p0 is used to execute test query every X minutes like SELECT 1. The dependancy javax.servlet you dont need it because you deploy on web container but I’ve added it because sometimes I need to cast somethink to HttpServletRequest or HttpSession and I want to have it in my eclipse classpath. Log4j is a must for every project that’s why it is included here. The other dependancies are richfaces, jsf, facelets, hibernate and spring I don’t see something strange there so if you don’t understand something post a comment.
Next we will use Spring right ? so lets paste the applicationContext.xml ( note that it is not big because we will use @Autowired and @Component to autowire and to register our spring beans ).
<?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:context=“http://www.springframework.org/schema/context”
xmlns:tx=“http://www.springframework.org/schema/tx”
xsi:schemaLocation=“http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd”
default-autowire=“byName”>
<context:annotation-config/>
<tx:annotation-driven proxy-target-class=“true” />
<bean id=“transactionManager” class=“org.springframework.orm.hibernate3.HibernateTransactionManager”>
</bean>
<context:component-scan base-package=“org.joke.myproject”>
</context:component-scan>
<bean id=“dataSource” class=“com.mchange.v2.c3p0.ComboPooledDataSource”>
<property name=“jdbcUrl”><value>jdbc:mysql://localhost:3306/asomtsp?autoReconnect=true&characterEncoding=utf8</value></property>
<property name=“driverClass”><value>com.mysql.jdbc.Driver</value></property>
<property name=“user”><value>root</value></property>
<property name=“password”><value>12345678</value></property>
<property name=“maxStatements”><value>0</value></property>
<property name=“maxIdleTime”><value>1800</value></property>
<property name=“minPoolSize”><value>5</value></property>
<property name=“maxPoolSize”><value>150</value></property>
<property name=“initialPoolSize”><value>20</value></property>
<property name=“acquireIncrement”><value>5</value></property>
<property name=“numHelperThreads”><value>10</value></property>
<property name=“idleConnectionTestPeriod”><value>3600</value></property>
<property name=“preferredTestQuery”><value>select 1;</value></property>
</bean>
<bean id=“sessionFactory”
class=“org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean”>
<property name=“configLocation” value=“classpath:hibernate.cfg.xml”>
</property>
<property name=“dataSource” ref=“dataSource”></property>
</bean>
</beans>
The default-autowire=“byName” attribute is used because I don’t want to tell ref bean ref bean for each bean :).
The tag ‘context:annotation-config’ tells spring to go the annotation way.
The tag ‘context:component-scan’ tells spring to look for annotated classes in the specified package. Once you put this tag you do not need the ‘context:annotation-config’ tag.
Sometimes when we auto wire by type there may be multiple beans of the same type (or inherited type). One case is if you define multiple datsasources. How do you tell your bean in that case which one to pick. In this case use @Qualifier(“beanid”) to select the specific one.
I don’t think I have to explain something about transactionManager and dataSource. If you have questions feel free to post a comment.
Next the hibernate.cfg.xml. Since all my database related configurations are in the applicationContext.xml the hibernate.cfg.xml contains only all my mapped classes needed for sessionFactory.
<?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>
<!– SQL dialect –>
<property name=“dialect”>org.hibernate.dialect.MySQLDialect</property>
<!– Enable formatted SQL in the logs –>
<property name=“format_sql”>true</property>
<!– Hibernate mappings references –>
<mapping class=“org.joke.myproject.entity.Message” />
</session-factory>
</hibernate-configuration>
I have only one entity called Messages and I’ve used annotations for mappings not another xml file. You can use whatever you want annotations or mapping.xml file. If you are using xml file for mappings you will have <mapping resource=”Messages.hbm.xml”/> instead of mapping class.
Almost finished. Lets integrate now Spring with JSF. We will want to use spring container for creating a JSF managed beans. So open faces-config.xml and add the fallowing lines in the application tag. Full example looks like :
<?xml version=“1.0” encoding=“UTF-8”?>
<faces-config xmlns=“http://java.sun.com/xml/ns/javaee”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd”
version=“1.2”>
<!—navigation rules goes here –>
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
</faces-config>
After adding the SpringBeanFacesELResolver lets do the final step : web.xml
<?xml version=“1.0”?>
<!–
* Licensed to the Apache Software Foundation (ASF) under one * or more
contributor license agreements. See the NOTICE file * distributed with
this work for additional information * regarding copyright ownership.
The ASF licenses this file * to you under the Apache License, Version
2.0 (the * “License”); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at * *
http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by
applicable law or agreed to in writing, * software distributed under
the License is distributed on an * “AS IS” BASIS, WITHOUT WARRANTIES
OR CONDITIONS OF ANY * KIND, either express or implied. See the
License for the * specific language governing permissions and
limitations * under the License.
–>
<web-app 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”
version=“2.4”>
<description>myproject web.xml</description>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<context-param>
<param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name>
<param-value>true</param-value>
</context-param>
<!–
Configure tomahawk taglib <context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/tomahawk.taglib.xml</param-value>
</context-param>
–>
<!– Use Documents Saved as *.xhtml –>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<!– Special Debug Output for Development –>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name>
<param-value>20</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.PRETTY_HTML</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.SECRET</param-name>
<param-value>NzY1NDMyMTA=</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.VALIDATE</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.READONLY_AS_DISABLED_FOR_SELECTS</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.ADD_RESOURCE_CLASS</param-name>
<param-value>
org.apache.myfaces.renderkit.html.util.DefaultAddResource
</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.RESOURCE_VIRTUAL_PATH</param-name>
<param-value>/faces/myFacesExtensionResource</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.CHECK_EXTENSIONS_FILTER</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING_METHOD</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>blueSky</param-value>
</context-param>
<context-param>
<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
<param-value>com.sun.facelets.FaceletViewHandler</param-value>
</context-param>
<filter>
<display-name>RichFaces Filter</display-name>
<filter-name>richfaces</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<!– Extensions Filter –>
<filter>
<filter-name>extensionsFilter</filter-name>
<filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
<init-param>
<param-name>uploadMaxFileSize</param-name>
<param-value>100m</param-value>
</init-param>
<init-param>
<param-name>uploadThresholdSize</param-name>
<param-value>100k</param-value>
</init-param>
</filter>
<filter>
<filter-name>sessionFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sessionFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>richfaces</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<url-pattern>/faces/*</url-pattern>
</filter-mapping>
<!– Listener, to allow Jetty serving MyFaces apps –>
<listener>
<listener-class>
org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
<!– spring integration –>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!– Faces Servlet –>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!– Faces Servlet Mapping –>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<!– Welcome files –>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Most of the parts are from the myfaces implementation. The important aspects are :
RichFaces integration using
org.richfaces.SKIN param and richfaces filter (org.ajax4jsf.Filter).
You can read about richfaces integration here:http://docs.jboss.org/richfaces/3.3.1.GA/en/devguide/html_single/
For jetty+myfaces we need to use this listener : org.apache.myfaces.webapp.StartupServletContextListener
And for Spring integration we need this two listeners : org.springframework.web.context.ContextLoaderListener and org.springframework.web.context.request.RequestContextListener
Thats ALL!
Now Lets start coding 🙂
Our Managed Beans will dont need any XML configuration they will look like this :
@Component
@Scope(“request”)
public class MessagesBean {
…
@Autowired
private MessagesService messagesService;
//use messagesService for what you want
…
}
The services are spring beans ( have @Component annotation) and are autowired in JSF Managed Beans/ Backing Beans. Our services looks like this the @Transaction annotation is used for creating transaction. You can read about it at http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html part : 9.5.6. Using @Transactional.
@Component
public class MessagesService {
…
@Autowired
private MessagesDAO messagesDAO;
@Transactional
public List<Message> listMessages() {
List<Message> messages = messagesDAO.findAll();
return messages;
}
//use messagesDao for what you want
…
}
Our DAOs look like this (they are spring beans again and are autowired in service layer).
@Component
public class MessagesDAO extends GenericDaoImpl<Message, Integer> {
@Override
protected Class<Message> getEntityClass() {
return Message.class;
}
//add additional dao methods if you want
…
}
Finally ! Thats all. After playing a while with project like this you will notice how fast is to create new service, dao, backing bean/managed bean because you don’t need to type any XML.
Feel free to post comments and questions.
The goal of this article is to show you how you can use Hibernate, Spring and JSF 1.2 in the most easiest way.
Used technologies :
- maven 2
- JSF 1.2 (MyFaces)
- Spring 2.5.6
- Hibernate 3.2.1.GA
In the example I will use mysql just for the configuration. You can use whatever you want. The goal that we want is to use Spring for management of transactions and as IoC container. The beast way for us is to make everything spring beans. In typical application we will have Services, DAOs, Entity objects and JSF managed beans. We will make all of them spring beans and use @Autowired annotation (included in Spring). We will use GenericDAO implementation which is explained in this article: http://gochev.blogspot.com/2009/08/hibernate-generic-dao.html.
First lets create a maven 2 project and add replace update it’s pom.xml to looks like this, note that the pom is big we will explain important sections after the whole content.
<?xml version=“1.0” encoding=“UTF-8”?>
<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/maven-v4_0_0.xsd”>
<modelVersion>4.0.0</modelVersion>
<groupId>myproject-web</groupId>
<artifactId>myproject-web</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>A custom project using myfaces</name>
<url>http://www.myorganization.org</url>
<build>
<finalName>myproject-web</finalName>
<plugins>
<plugin>
<!–This plugin allows to run the example using mvn jetty:run –>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.8</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<wtpversion>2.0</wtpversion>
<wtpapplicationxml>true</wtpapplicationxml>
<wtpmanifest>true</wtpmanifest>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<manifest>${basedir}/src/main/resources/META-INF/MANIFEST.MF</manifest>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>apache-maven-snapshots</id>
<url>http://people.apache.org/repo/m2-snapshot-repository</url>
</repository>
<repository>
<id>java.net</id>
<url>http://download.java.net/maven/1</url>
<layout>legacy</layout>
</repository>
<repository>
<id>java.net2</id>
<url>http://download.java.net/maven/2</url>
<layout>legacy</layout>
</repository>
<repository>
<id>repository.jboss.com</id>
<url>http://repository.jboss.com/maven2/</url>
<layout>default</layout>
</repository>
<repository>
<id>repo1</id>
<name>repo1</name>
<url>http://repo1.maven.org/maven2/</url>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</repository>
</repositories>
<!– Project dependencies –>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.2.1.GA</version>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>1.2.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-impl</artifactId>
<version>1.2.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.myfaces.tomahawk</groupId>
<artifactId>tomahawk</artifactId>
<version>1.1.6</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.sun.facelets</groupId>
<artifactId>jsf-facelets</artifactId>
<version>1.1.14</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.richfaces.framework</groupId>
<artifactId>richfaces-impl</artifactId>
<version>3.2.2.SR1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.richfaces.ui</groupId>
<artifactId>richfaces-ui</artifactId>
<version>3.2.2.SR1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
</dependencies>
</project>
Most of you don’t need explanation but for the rest I will explain the most strange sections. Starting from last one c3p0 – I use it because sometimes mysql closes my idle connection which are in the connection pool. The c3p0 is used to execute test query every X minutes like SELECT 1. The dependancy javax.servlet you dont need it because you deploy on web container but I’ve added it because sometimes I need to cast somethink to HttpServletRequest or HttpSession and I want to have it in my eclipse classpath. Log4j is a must for every project that’s why it is included here. The other dependancies are richfaces, jsf, facelets, hibernate and spring I don’t see something strange there so if you don’t understand something post a comment.
Next we will use Spring right ? so lets paste the applicationContext.xml ( note that it is not big because we will use @Autowired and @Component to autowire and to register our spring beans ).
<?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:context=“http://www.springframework.org/schema/context”
xmlns:tx=“http://www.springframework.org/schema/tx”
xsi:schemaLocation=“http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd”
default-autowire=“byName”>
<context:annotation-config/>
<tx:annotation-driven proxy-target-class=“true” />
<bean id=“transactionManager” class=“org.springframework.orm.hibernate3.HibernateTransactionManager”>
</bean>
<context:component-scan base-package=“org.joke.myproject”>
</context:component-scan>
<bean id=“dataSource” class=“com.mchange.v2.c3p0.ComboPooledDataSource”>
<property name=“jdbcUrl”><value>jdbc:mysql://localhost:3306/asomtsp?autoReconnect=true&characterEncoding=utf8</value></property>
<property name=“driverClass”><value>com.mysql.jdbc.Driver</value></property>
<property name=“user”><value>root</value></property>
<property name=“password”><value>12345678</value></property>
<property name=“maxStatements”><value>0</value></property>
<property name=“maxIdleTime”><value>1800</value></property>
<property name=“minPoolSize”><value>5</value></property>
<property name=“maxPoolSize”><value>150</value></property>
<property name=“initialPoolSize”><value>20</value></property>
<property name=“acquireIncrement”><value>5</value></property>
<property name=“numHelperThreads”><value>10</value></property>
<property name=“idleConnectionTestPeriod”><value>3600</value></property>
<property name=“preferredTestQuery”><value>select 1;</value></property>
</bean>
<bean id=“sessionFactory”
class=“org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean”>
<property name=“configLocation” value=“classpath:hibernate.cfg.xml”>
</property>
<property name=“dataSource” ref=“dataSource”></property>
</bean>
</beans>
The default-autowire=“byName” attribute is used because I don’t want to tell ref bean ref bean for each bean :).
The tag ‘context:annotation-config’ tells spring to go the annotation way.
The tag ‘context:component-scan’ tells spring to look for annotated classes in the specified package. Once you put this tag you do not need the ‘context:annotation-config’ tag.
Sometimes when we auto wire by type there may be multiple beans of the same type (or inherited type). One case is if you define multiple datsasources. How do you tell your bean in that case which one to pick. In this case use @Qualifier(“beanid”) to select the specific one.
I don’t think I have to explain something about transactionManager and dataSource. If you have questions feel free to post a comment.
Next the hibernate.cfg.xml. Since all my database related configurations are in the applicationContext.xml the hibernate.cfg.xml contains only all my mapped classes needed for sessionFactory.
<?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>
<!– SQL dialect –>
<property name=“dialect”>org.hibernate.dialect.MySQLDialect</property>
<!– Enable formatted SQL in the logs –>
<property name=“format_sql”>true</property>
<!– Hibernate mappings references –>
<mapping class=“org.joke.myproject.entity.Message” />
</session-factory>
</hibernate-configuration>
I have only one entity called Messages and I’ve used annotations for mappings not another xml file. You can use whatever you want annotations or mapping.xml file. If you are using xml file for mappings you will have <mapping resource=”Messages.hbm.xml”/> instead of mapping class.
Almost finished. Lets integrate now Spring with JSF. We will want to use spring container for creating a JSF managed beans. So open faces-config.xml and add the fallowing lines in the application tag. Full example looks like :
<?xml version=“1.0” encoding=“UTF-8”?>
<faces-config xmlns=“http://java.sun.com/xml/ns/javaee”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd”
version=“1.2”>
<!—navigation rules goes here –>
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
</faces-config>
After adding the SpringBeanFacesELResolver lets do the final step : web.xml
<?xml version=“1.0”?>
<!–
* Licensed to the Apache Software Foundation (ASF) under one * or more
contributor license agreements. See the NOTICE file * distributed with
this work for additional information * regarding copyright ownership.
The ASF licenses this file * to you under the Apache License, Version
2.0 (the * “License”); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at * *
http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by
applicable law or agreed to in writing, * software distributed under
the License is distributed on an * “AS IS” BASIS, WITHOUT WARRANTIES
OR CONDITIONS OF ANY * KIND, either express or implied. See the
License for the * specific language governing permissions and
limitations * under the License.
–>
<web-app 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”
version=“2.4”>
<description>myproject web.xml</description>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<context-param>
<param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name>
<param-value>true</param-value>
</context-param>
<!–
Configure tomahawk taglib <context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/tomahawk.taglib.xml</param-value>
</context-param>
–>
<!– Use Documents Saved as *.xhtml –>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<!– Special Debug Output for Development –>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name>
<param-value>20</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.PRETTY_HTML</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.SECRET</param-name>
<param-value>NzY1NDMyMTA=</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.VALIDATE</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.READONLY_AS_DISABLED_FOR_SELECTS</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.ADD_RESOURCE_CLASS</param-name>
<param-value>
org.apache.myfaces.renderkit.html.util.DefaultAddResource
</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.RESOURCE_VIRTUAL_PATH</param-name>
<param-value>/faces/myFacesExtensionResource</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.CHECK_EXTENSIONS_FILTER</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING_METHOD</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>org.richfaces.SKIN</param-name>
<param-value>blueSky</param-value>
</context-param>
<context-param>
<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
<param-value>com.sun.facelets.FaceletViewHandler</param-value>
</context-param>
<filter>
<display-name>RichFaces Filter</display-name>
<filter-name>richfaces</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<!– Extensions Filter –>
<filter>
<filter-name>extensionsFilter</filter-name>
<filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
<init-param>
<param-name>uploadMaxFileSize</param-name>
<param-value>100m</param-value>
</init-param>
<init-param>
<param-name>uploadThresholdSize</param-name>
<param-value>100k</param-value>
</init-param>
</filter>
<filter>
<filter-name>sessionFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sessionFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>richfaces</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>extensionsFilter</filter-name>
<url-pattern>/faces/*</url-pattern>
</filter-mapping>
<!– Listener, to allow Jetty serving MyFaces apps –>
<listener>
<listener-class>
org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
<!– spring integration –>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<!– Faces Servlet –>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!– Faces Servlet Mapping –>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<!– Welcome files –>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Most of the parts are from the myfaces implementation. The important aspects are :
RichFaces integration using
org.richfaces.SKIN param and richfaces filter (org.ajax4jsf.Filter).
You can read about richfaces integration here:http://docs.jboss.org/richfaces/3.3.1.GA/en/devguide/html_single/
For jetty+myfaces we need to use this listener : org.apache.myfaces.webapp.StartupServletContextListener
And for Spring integration we need this two listeners : org.springframework.web.context.ContextLoaderListener and org.springframework.web.context.request.RequestContextListener
Thats ALL!
Now Lets start coding 🙂
Our Managed Beans will dont need any XML configuration they will look like this :
@Component
@Scope(“request”)
public class MessagesBean {
…
@Autowired
private MessagesService messagesService;
//use messagesService for what you want
…
}
The services are spring beans ( have @Component annotation) and are autowired in JSF Managed Beans/ Backing Beans. Our services looks like this the @Transaction annotation is used for creating transaction. You can read about it at http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html part : 9.5.6. Using @Transactional.
@Component
public class MessagesService {
…
@Autowired
private MessagesDAO messagesDAO;
@Transactional
public List<Message> listMessages() {
List<Message> messages = messagesDAO.findAll();
return messages;
}
//use messagesDao for what you want
…
}
Our DAOs look like this (they are spring beans again and are autowired in service layer).
@Component
public class MessagesDAO extends GenericDaoImpl<Message, Integer> {
@Override
protected Class<Message> getEntityClass() {
return Message.class;
}
//add additional dao methods if you want
…
}
Finally ! Thats all. After playing a while with project like this you will notice how fast is to create new service, dao, backing bean/managed bean because you don’t need to type any XML.
Feel free to post comments and questions.
Recent Comments