Wednesday, December 31, 2014

Spring4 / Hibernate4 / JSF2 / Primefaces5 jee web application skull

In this article we will try to build an entire skull of jsf2/spring4 application, welwill use hibernate4 to manage persistency, use bundles for internalization and primefaces 5 in view layer.The application will be mavenized.


The result architecture will have this behavior:



  1. First Step is to create a maven project based on webapp archtype

    mvn archetype:generate -DgroupId=com.itillusion.travel -DartifactId=travel -Dpackagename=com.itillusion.travel -DarchetypeArtifactId=maven-archetype-webapp -DarchetypeVersion=1.0 -DinteractiveMode=false
    
    (how to work with maven nad elipse ?
     this link is useful by A.Mekki)
  2. Next step is to add correct dependencies for artifacts that we'll use.to our pom.xml

    MySQL jdbc connector
    Hibernate4 (requires dbcp2)
    Spring4
    Primefaces5
    JSF 2 api/impl and servlet

    we will add also repositories
    our pom.xml will be


    
      4.0.0
      com.itillusion
      travel
      0.0.1-SNAPSHOT
      war
      
      
      4.1.3.RELEASE  
      3.2.5.RELEASE
      4.3.7.Final
      5.1
     
     
    
     
     
      
      
       mysql
       mysql-connector-java
       5.1.6
      
      
     
     
      
      
         org.hibernate
         hibernate-core
         ${hibernate.framework.version}
       
      
      
      
      
       org.primefaces
       primefaces
       ${primefaces.framework.version}
      
      
      
      
      
       org.springframework
       spring-context
       ${spring.framework.version}
      
      
       org.springframework
       spring-web
       ${spring.framework.version}
         
      
       org.springframework
       spring-orm
       ${spring.framework.version}
      
      
      
      
      
      
       com.sun.faces
       jsf-api
       2.1.2
      
      
       com.sun.faces
       jsf-impl
       2.1.2
      
      
      
      
      
       javax.servlet
       servlet-api
       2.5
       provided
      
        
      
       
      
             
           org.apache.commons
           commons-dbcp2
           2.0
       
      
      
      
      
       junit
       junit
       3.8.1
       test
      
      
    
     
    
     
     
      
      
     
     
      
       JSFRepo
       Repository for JSF2
       http://download.java.net/maven/2/
       
      
     
      
       MavenRepo
       Repository for Maven2
       http://repo1.maven.org/maven2
       
        
      
      
       prime-repo
        PrimeFaces Maven Repository
        http://repository.primefaces.org
       default
      
      
      
      
       maven-repository.dev.java.net
       Java Dev Net Repository
       http://download.java.net/maven/2
       
        true
        never
       
       
        false
       
      
      
      
       spring-milestone
       Spring Portfolio Milestone Repository
       http://s3.amazonaws.com/maven.springframework.org/milestone
       
      
      
      
       spring-snapshot
       Spring Portfolio snapshot Repository
       http://maven.springframework.org/snapshot
      
      
      
       jboss-repo
       jboss Repository
       http://repository.jboss.org/maven2
      
      
      
       java.net
       Java.net Repository for Maven2
       http://download.java.net/maven/1
      
    
      
       spring-ext
       Spring External Dependencies Repository
       https://springframework.svn.sourceforge.net/svnroot/springframework/repos/repo-ext
       
      
      
      
       
        true
       
       
        false
        never
       
       repository.jboss.com
       Jboss Repository for Maven
        http://repository.jboss.com/maven2 
       default
      
      
      
      
       jboss-public-repository-group
       JBoss Public Repository Group
       http://repository.jboss.org/nexus/content/groups/public/       
      
     
    
    

    Note here we have used version properties to make pom more evolutive
    in 
    <spring.security.version>3.2.5.RELEASE</spring.security.version>
    
    
  3. Next step is to configure web.xml (typical jsf webapp, web.xml with listner for spring)

    
      travel
      
        index.html
        index.htm
        index.jsp
        default.html
        default.htm
        default.jsp
      
      
      
       
     
      javax.faces.PROJECT_STAGE
      Development
     
     
       
     
      Faces Servlet
      javax.faces.webapp.FacesServlet
      1
     
     
      Faces Servlet
      *.jsf
      *.xhtml
      
     
     
     
     
     
     
     
      org.springframework.web.context.ContextLoaderListener
     
     
     
     
     
      contextConfigLocation
       /WEB-INF/applicationContext.xml
     
     
     
    
    

  4. Now we write our faces-config.xml, thanks to annotation, this configuration file is too light

    
        
        
        
            
                  fr
             
         
       com.itillusion.travel.internalization.language
       language
         
            
            org.springframework.web.jsf.el.SpringBeanFacesELResolver
            
        
    
    
    
    We have used here a resource-bundle to manage internalization of messages and labels:
    In this line:
    <base-name>com.itillusion.travel.internalization.language</base-name>
     we told to jsf that our file is located in package com.itillusion.travel.internalizationand its name is language.properties
      
    NB: language.properties is a resource file: it must be located under WEB-INF/classes in deployement  folder :
    here under eclipse we have configured in deployement assembly onglet  a copy of src/main/resources to WEB-INF/classes

    language.properties contains these few lines: applicationTitle=Traveler
    companyName=Itillusion
    userId=ID Utilisateur
    userName=Nom utilisateur

  5. Now we go ahead to applicationContext.xml which contains declaration of spring beans and hibernate properties.

    In order to seperate real configuration from database access configuration we will put database access informations in a separate file called  jdbc.properties under WEB-INF. folder

    We have told to spring that we will work with annotation and application beans will be in sub packages of  "com.itillusion.travel
    <context:component-scan base-package="com.itillusion.travel" />

    We have to tell hibenate where he will find models
    <property name="packagesToScan" value="com.itillusion.travel.model" />


    Here is a complete applicationContext.xml
    
            
        
         
      
     
     
     
     
      
       
        
        org.hibernate.dialect.MySQLDialect
        true
        false
       
      
      
      
      
       
      
     
     
      
      
      
      
      
      
     
     
     
     
      
       
        /WEB-INF/jdbc.properties
       
      
     
     
     
        
     
        
        
           
        
    
    
    and here is the listing of jdbc.properties
    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/travel
    jdbc.username=travel
    jdbc.password=yourpassword

  6. Now we have the choice : finish the view layer with its facelets or attack an entity to display it in th view layer.
    Personally i prefer finish the view for a simple reason :
    When a standard page of our application is displayed, then any problem that will appear in integration of any page will be the result of a programmation mistake.

    Ok, we continue,
    we start by th building of a template for the application:
      A- create a folder templates and under it a folder common.



    B- Create the commonLayout.xhtml file that will descibe the design of a common page in the application, in our casse commonLayout is composed by 3 files a header, a content and a footer  (here we have a one column deisgn).

    here is the listing of the 4 files:

    commonLayout.xhtml:
    
     
        
      
        
     
        
     
     
    commonHeader.xhtml:
    
        
         
         
          
    #{language.applicationTitle}

    commonContent.xhtml:
    
        
         
          
           

    This is default content


    
        
         
     
       
    
        
    
    

    Note that next the composition called content in the commonContent.xhtml will be overrided each time a page is shown
    C- add the index.jsp page that will redirect to a default xhtml page that will be considered a the entry point of the application.
    index.jsp under the root(webapp):
    
    

    our application will show directly a listing of users inserted previously in database.
    css and js files have to be under folder resources under webapp otherways they will not be loaded.
  7. Now we will create the different layers of the application:
    a model layer
    a dao layer
    a service layer
    a managedbeans layer to interact with jsf views

    Considering that we have a mysql 3 tables under schema travel with this descriptions:
    mysql>  show tables;
    +------------------+
    | Tables_in_travel |
    +------------------+
    | profile          |
    | user_profile     |
    | utilisateur      |
    +------------------+
    3 rows in set (3.36 sec)
    
    
    mysql> describe utilisateur;
    +-----------+-------------+------+-----+---------+----------------+
    | Field     | Type        | Null | Key | Default | Extra          |
    +-----------+-------------+------+-----+---------+----------------+
    | usr_id    | int(11)     | NO   | PRI | NULL    | auto_increment |
    | usr_login | varchar(45) | YES  |     | NULL    |                |
    | usr_pwd   | varchar(45) | YES  |     | NULL    |                |
    +-----------+-------------+------+-----+---------+----------------+
    3 rows in set (2.76 sec)
    
    mysql> desc profile;
    +---------+-------------+------+-----+---------+----------------+
    | Field   | Type        | Null | Key | Default | Extra          |
    +---------+-------------+------+-----+---------+----------------+
    | prf_id  | int(11)     | NO   | PRI | NULL    | auto_increment |
    | prf_lib | varchar(45) | NO   | UNI | NULL    |                |
    +---------+-------------+------+-----+---------+----------------+
    2 rows in set (0.28 sec)
    
    mysql> desc user_profile;
    +---------------+---------+------+-----+---------+----------------+
    | Field         | Type    | Null | Key | Default | Extra          |
    +---------------+---------+------+-----+---------+----------------+
    | usrprf_id     | int(11) | NO   | PRI | NULL    | auto_increment |
    | prf_id        | int(11) | NO   | MUL | NULL    |                |
    | usr_id        | int(11) | NO   | MUL | NULL    |                |
    | usrprf_active | int(11) | NO   |     | 0       |                |
    +---------------+---------+------+-----+---------+----------------+
    4 rows in set (2.53 sec)
    
  8. Model layer (just one class (utilisateur))

    Note we will this tree of packages and classes


    package com.itillusion.travel.model;
    
    // Generated 25 nov. 2014 14:54:59 by Hibernate Tools 3.4.0.CR1
    
    import java.util.HashSet;
    import java.util.Set;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import static javax.persistence.GenerationType.IDENTITY;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;
    
    /**
     * Utilisateur generated by hbm2java
     */
    @Entity
    @Table(name = "utilisateur", catalog = "travel")
    public class Utilisateur implements java.io.Serializable {
    
     /**
      * 
      */
     private static final long serialVersionUID = 8276067938930706574L;
     private Integer usrId;
     private String usrLogin;
     private String usrPwd;
     private Set userProfiles = new HashSet(0);
    
     public Utilisateur() {
     }
    
     public Utilisateur(String usrLogin, String usrPwd,
       Set userProfiles) {
      this.usrLogin = usrLogin;
      this.usrPwd = usrPwd;
      this.userProfiles = userProfiles;
     }
    
     @Id
     @GeneratedValue(strategy = IDENTITY)
     @Column(name = "usr_id", unique = true, nullable = false)
     public Integer getUsrId() {
      return this.usrId;
     }
    
     public void setUsrId(Integer usrId) {
      this.usrId = usrId;
     }
    
     @Column(name = "usr_login", length = 45)
     public String getUsrLogin() {
      return this.usrLogin;
     }
    
     public void setUsrLogin(String usrLogin) {
      this.usrLogin = usrLogin;
     }
    
     @Column(name = "usr_pwd", length = 45)
     public String getUsrPwd() {
      return this.usrPwd;
     }
    
     public void setUsrPwd(String usrPwd) {
      this.usrPwd = usrPwd;
     }
    
     @OneToMany(fetch = FetchType.LAZY, mappedBy = "utilisateur")
     public Set getUserProfiles() {
      return this.userProfiles;
     }
    
     public void setUserProfiles(Set userProfiles) {
      this.userProfiles = userProfiles;
     }
    
    }
    
    
  9. Dao layer, all classes under com.itillusion.travel.dao are interfaces, who knows if we will change hibernate by another orm ?
    implementations are under com.itillusion.travel.dao.impl
    First of all web begin with generic dao classes: GenericDao.java
    package com.itillusion.travel.dao;
    
    import java.io.Serializable;
    import java.util.List;
    
    
    public interface GenericDao {
        public T find(I id);
        public List findAll();
        public void delete(T obj);
        public void saveOrUpdate(T obj);
    }
    
    an implementation of this class is
    package com.itillusion.travel.dao.impl;
    
    import java.io.Serializable;
    import java.util.List;
    
    import org.hibernate.SessionFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.itillusion.travel.dao.GenericDao;
    
    
    public abstract class GenericDaoImpl implements GenericDao{
    
    
        @Autowired
         SessionFactory sessionFactory;
        
        private Class type;
        
        public GenericDaoImpl(Class type){
         this.type = type;
        }
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
        
        public SessionFactory getSessionFactory() {
            return sessionFactory;
        }
    
     @SuppressWarnings("unchecked")
     @Transactional(readOnly = true)
        @Override
        public T find(I id) {
            return (T) getSessionFactory().getCurrentSession().get(type, id);
        }
    
        
        @SuppressWarnings("unchecked")
     @Transactional(readOnly = true)
        public List findAll(){
         
         return (List) getSessionFactory().getCurrentSession().createQuery("from "+type.getName()).list();     
           
        }
        
        @Transactional
        @Override
        public void delete(T obj) {
            getSessionFactory().getCurrentSession().delete(obj);
        }
    
        @Transactional
        @Override
        public void saveOrUpdate(T obj) {
            getSessionFactory().getCurrentSession().saveOrUpdate(obj);
        }
    }
    
    NB: this class is under impl subpackage.
    @Autowired annotation is present to ensure the injection of sessionFactory bean
    Now wel will create an interface for UserDao ; here we don't need anything expect methods in GenericDao
    package com.itillusion.travel.dao;
    
    import com.itillusion.travel.model.Utilisateur;
    
    public interface UserDao extends GenericDao {
    
    }
    
    

    a possible implementation for this interface is
    package com.itillusion.travel.dao.impl;
    
    import org.springframework.stereotype.Repository;
    import com.itillusion.travel.dao.UserDao;
    import com.itillusion.travel.model.Utilisateur;
    
    @Repository
    public class UserDaoImpl extends GenericDaoImpl implements UserDao {
    
     public UserDaoImpl(){
      super(Utilisateur.class);
     }
     public UserDaoImpl(Class type) {
      super(type);
     }
    
    }
    
    Note the presence og @Repository annotation it's needed for dao bean injection in service bean
    Ok now we have set the Dao layer.
  10. We pass to service layer: same idea it will be interfaces for eache service and one/many implementation for each interface
    let's start with user interface
    package com.itillusion.travel.service;
    
    import java.util.List;
    
    import com.itillusion.travel.model.Utilisateur;
    //since we willl only display list of users
    public interface UserService {
     
     public List getUsers();
     
    
    }
    

    a possible implementation for this interface is
    package com.itillusion.travel.service.impl;
    
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import com.itillusion.travel.dao.UserDao;
    import com.itillusion.travel.model.Utilisateur;
    import com.itillusion.travel.service.UserService;
    
    @Service
    
    public class UserServiceImpl implements UserService {
    
     @Autowired
     UserDao userDao; 
     
     @Override
     public List getUsers() {
      return userDao.findAll();
      
     }
    
     public UserDao getUserDao() {
      return userDao;
     }
    
     public void setUserDao(UserDao userDao) {
      this.userDao = userDao;
     }
    
    }
    
    
    Note the presence of @Service annotation needed for service object injection in the managed bean
  11. Last step is to create our managedbean !
    package com.itillusion.travel.beans;
    
    import java.io.Serializable;
    import java.util.List;
    import javax.annotation.PostConstruct;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.SessionScoped;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import com.itillusion.travel.model.Utilisateur;
    import com.itillusion.travel.service.UserService;
     
    @Component
    @ManagedBean(name="listUsersBean")
    @SessionScoped
    
    public class ListUsersBean implements Serializable {
        
             
    
    
     /**
      * 
      */
     private static final long serialVersionUID = 6675856254221490117L;
    
     @Autowired
        private UserService authService;
        
        private List users;
         
        @PostConstruct
        public void init() {
         System.out.println(authService);
            users = authService.getUsers();
        }
    
     public List getUsers() {
      return users;
     }
    
     public void setUsers(List users) {
      this.users = users;
     }
    
     public UserService getAuthService() {
      return authService;
     }
    
     public void setAuthService(UserService authService) {
      this.authService = authService;
     }
     
        
      
    }
    
  12. We will now display all users :), then we will return to our application and we will create a folder called faces under the webapp and create our xhtml page editUsers.xhtml
    
        
     
         
        
         
          
            
         
                
                    
                        
                        
                    
         
                    
                        
                        
                    
         
                    
                        
                        
                    
         
                    
                        
                        
                    
                
         
                
                    
                        
                    
                    
                
         
                
                    
                        
                    
                    
                
         
            
        
         
         
         
         
     
        
     
    
    
  13. we have that then :

    just a remark; if you want to use primefaces themes or skins
    - go to this url -

  14. comments are welcome!

No comments:

Post a Comment