Arquitecura JSF con Hibernate

Hola, estuve aprendiendo Hibernate y apenas finalice JSF, ahora quiero integrar estos dos frameworks para un nuevo proyecto ya en forma. Quiero sus opiniones y consejos sobre como integrar estos dos frameworks para que trabajen de manera conjunta explotando de la mejor manera posible sus beneficios. Si alguien tiene algun proyecto donde trabajen con estos dos frameworks o algun manual, tutorial, etc. me seria de gran ayuda, gracias de antemano.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

Loose coupling

Idealmente, la parte de JSF no debería saber mucho acerca de Hibernate. Define interfaces para tus DAOs, luego implementa los DAOs ya sea con Hibernate puro o usando Hibernate+Spring. En JSF debes apuntar solamente a las interfaces, no a las implementaciones de los DAOs. Solamente queda cómo inyectar los DAOs en tus páginas, creo que JSF trae algo para eso (definir componentes y luego invocarlos desde cualquier página), o puedes usar un application context de Spring.

De esta forma JSF no tiene que saber nada acerca de Hibernate y Hibernate no tiene que saber nada acerca de JSF. Y si por alguna razón uno o varios de los DAOs deben cambiar a usar JDBC puro o iBatis o cualquier otra cosa en vez de Hibernate, mientras no cambies la interfaz (no deberías si la diseñas bien desde el principio), toda la GUI de tu app no se ve afectada.

OK

Hola ezamudio, gracias por contestar. Entonces lo primero que hare sera definir mis interfaces para mi dao usando Hibernate y Spring, cuando haya finalizado esta parte los publicare aqui mismo para que las revises y si hay que arreglar algo hacerlo, asi mismo podran ser de utilidad para otras personas.

Imagen de ezamudio

Ni Hibernate ni Spring

Las interfaces de los DAOs no deben ir casadas ni con Hibernate ni con Spring.

DAO

Voy a exponer mi implementacion, la clase que lo implementa y mi HibernateUtil. Cualquier error que encuentren ya sea lexico, sintactico, semantico o de logica favor de avisarme para corregirlo.

<<< HibernateUtil >>>

import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

/**
 * Hibernate Utility class with a convenient method to get Session Factory object.
 *
 * @author JavAdicto
 */

public class HibernateUtil {

    public static final SessionFactory sessionFactory;
    public static final ThreadLocal session = new ThreadLocal();

    static {
        try {
            // Create the SessionFactory from standard (hibernate.cfg.xml)
            // config file.
            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Log the exception.
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static Session currentSession() throws HibernateException
    {
        Session s = (Session) session.get();
        //Abre una nueva session en un nuevo hilo
        if (s == null) {
            s = sessionFactory.openSession();
            //Almacenalo en la variable del hilo local
            session.set(s);
        }
        return s;
    }

    public static void closeSession() throws HibernateException
    {
        Session s = (Session) session.get();
        if (s != null)
            s.close();

        session.set(null);
    }
}

<<< Generico >>>

package dao;

/**
 *
 * @author JavAdicto
 */

import java.util.List;

public interface Generico {

    public void guardar(Object obj);
    public void actualizar( Object obj);
    public void borrar(Object obj);
    public void borrarPorId(Class<?> clase, java.io.Serializable id);

    public Object buscarPorId( Class<?> clase, java.io.Serializable id);    
    public List buscarTodos(Class clase);

    public void inicializar(Object obj);    
    public void inicializarColeccion(java.util.Collection coleccion);

    public void guardarColeccion(java.util.Collection coleccion);
    public void flush();
    public void merge(Object obj);
}

<<< PersonaDao>>>

package dao;

/**
 *
 * @author JavAdicto
 */

import java.util.Iterator;
import java.util.List;
import org.hibernate.Hibernate;
import org.springframework.orm.hibernate3.HibernateQueryException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class PersonaDao extends HibernateDaoSupport implements Generico
{
    public PersonaDao(){
        }

    public void guardar(Object obj)
    {
        try
        {
            getHibernateTemplate().saveOrUpdate(obj);
        }
        catch( HibernateQueryException e )
        {
            e.printStackTrace();
        }
        catch( RuntimeException e )
        {
            e.printStackTrace();
        }
    }

    public void actualizar(Object obj)
    {        
        try
        {
            getHibernateTemplate().update(obj);
        }
        catch( HibernateQueryException e )
        {
            e.printStackTrace();
        }
        catch( RuntimeException e )
        {
            e.printStackTrace();
        }
    }

    public void borrar(Object obj)
    {
        try
        {
            getHibernateTemplate().delete(obj);
        }
        catch( HibernateQueryException e )
        {
            e.printStackTrace();
        }
        catch( RuntimeException e )
        {
            e.printStackTrace();
        }
    }

    public Object buscarPorId(Class<?> clase, java.io.Serializable id)
    {
        Object instance = null;

        try
        {
            instance = getHibernateTemplate().get(clase, id);            
        }
        catch( HibernateQueryException e )
        {
            e.printStackTrace();
        }
        catch( RuntimeException e )
        {
            e.printStackTrace();
        }

        return instance;
    }

    public Object find( Class clazz, Long id )
    {
        return getHibernateTemplate().load(clazz, id);
    }

    public void borrarPorId(Class<?> clase, java.io.Serializable id)
    {
        try
        {
            Object object2 = this.buscarPorId(clase, id);
            getHibernateTemplate().delete(object2);            
        }
        catch( HibernateQueryException e )
        {
            e.printStackTrace();
        }
        catch( RuntimeException e )
        {
            e.printStackTrace();
        }
    }

    public List buscarTodos(Class clase)
    {
        List list = null;

        try
        {
            list =  getHibernateTemplate().find("from " + clase.getSimpleName());
        }
        catch( HibernateQueryException e )
        {
            e.printStackTrace();
        }
        catch( RuntimeException e )
        {
            e.printStackTrace();
        }
        return list;
    }  

    public void inicializarColeccion(java.util.Collection collection)
    {
        try
        {
            Hibernate.initialize(collection);
            Iterator it=collection.iterator();

            while(it.hasNext())
            {
                Hibernate.initialize(it.next());
            }
        }
        catch( HibernateQueryException e )
        {
            e.printStackTrace();
        }
        catch( RuntimeException e )
        {
            e.printStackTrace();
        }
    }

    public void inicializar(Object obj)
    {
        Hibernate.initialize(obj);
    }
   

    public void guardarColeccion(java.util.Collection coleccion)
    {
        try
        {
            java.util.Iterator it=coleccion.iterator();

            while(it.hasNext())
            {
                getHibernateTemplate().save(it.next());
            }
        }
        catch( HibernateQueryException e )
        {
            e.printStackTrace();
        }
        catch( RuntimeException e )
        {
            e.printStackTrace();
        }
    }

    public void flush()
    {
        try
        {
            getHibernateTemplate().flush();
        }
        catch( HibernateQueryException e )
        {
            e.printStackTrace();
        }
        catch( RuntimeException e )
        {
            e.printStackTrace();
        }
    }    

    public void merge(Object object)
    {
        try
        {
            getHibernateTemplate().merge(object);
        }
        catch(HibernateQueryException e )
        {
            e.printStackTrace();
        }
        catch( RuntimeException e )
        {
            e.printStackTrace();
        }
    }
}

Integrar JSF y SPRING

Que tal javadicto

Ahora solo te falta integrar Spring con JSF, para esto debes de tener mucho cuidado ya que son 2 contextos diferentes, donde viven tus managed beans y tu Application Context de Spring. El alcanze de tus Beans puede ser diferente en cada contexto (OJO) por default Spring maneja un alcanze Singleton para los Beans que se alambran en el contexto. Para hacer esta integracion Spring tiene un Helper que te ayudara a manejar la integracion, solo tienes que incluir en tu archivo faces-config.xml el siguiente fracmento de codigo

<application>
    <variable-resolver>
        org.springframework.web.jsf.DelegatingVariableResolver
    </variable-resolver>
</application>

Ahora solo tienes que mapear tu Beans en ambos contextos, e inyectar en el contecto de Spring las dependencias de tus Beans. Inyectando la implementaciones a las interfaces que definiste, yo no te recomendaría inyectar directamente el DAO en el Managed Bean, si no un Service que encapsule mas y separe en una nueva capa la presentación de la persistencia, claro que seria una implementacion de un Service previa definicion de su interface.

Saludos

Hola josebetomex

Que bueno es conocer gente como tu, gracias por tu comentario. Si de hecho me falta la parte de Spring donde debo hacer uso del HibernateTemplate y es exactamente ahi donde debo generar un nuevo paquete para los servicios, lo estuve consultando pero me revolvi un poco ya que de Spring no se mucho, de hecho casi nada. Solo estudiado Hibernate y JSF, lo que pretendia en un inicio era integrar solo estos dos frameworks para desarrollar mi aplicacion, pero Ezamudio me recomendo usar un poco de Spring para facilitar la integracion haciendo uso del "HibernateDaoSupport", pero como te comento, de Spring no se mucho y ya me revolvi al intentar hacerlo con los tres.

Imagen de ezamudio

Managed beans

Entonces no uses Spring por el momento. Si ya definiste tus interfaces de DAOs, y por otra parte tienes las implementaciones de los mismos (usando Hibernate o lo que sea), entonces puedes declarar tus DAOs (las implementaciones) como managed beans en tu app de JSF y desde ahi los invocas.

Busca algo del patrón open-session-in-view para JSF, seguramente hay algo con Hibernate, pero la idea es mantener el acoplamiento bajo, es decir, que tu código dentro de la parte de JSF no esté lleno de llamadas a cosas específicas de Hibernate. Por eso la definición de interfaces para los DAOs; si a la mera hora deciden usar otra cosa o cambiar de versión de Hibernate y cambia el API, etc etc, los cambios los harás en las implementaciones de los DAOs pero no tienes que mover nada en JSF.

JSF Hibernate Managed beans

Saludos, me encuentro en una situación parecida, se utlizar JSF y estoy aprendiendo Hibernate pero no se como integrar las dos (sin Spring) .
Segun entiendo lo que debo hacer es declarar los DAOs como managed beans.

- que tipo de managed bean debo utilizar?
- como accedo a ellos?
- es esta una solución adecuada para un entorno de producción?.

Podrian ayudarme con un pequeño diagrama o código. Agradesco desde ya su oportuna ayuda.