3

JSF, RichFaces, Spring, Hibernate – lets make development easy.

Posted by JOKe on 8/19/2009 11:44:00 AM

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&amp;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.














|

3 Comments


Congrats dude,

in general i hate blogs,
but yours is the second which i put in favorites.
I find it very useful, keep going the same way.

Best .. Yasen


Hi

could you link to this article an archive with maven project ready to import in eclipse?
It would be very helpful, for someone like me ,who is very new to spring and all Java technologies :)

thank you
Chris


Thank you.

Looks very well organized I really heat the old approach using the faces-context to register the managed beans.

Copyright © 2009 JOKe's Blog All rights reserved. Theme based on the Theme by Laptop Geek with changes by JOKe. | Bloggerized by FalconHive.