001    /*****************************************************************************
002     * Copyright (c) PicoContainer Organization. All rights reserved.            *
003     * ------------------------------------------------------------------------- *
004     * The software in this package is published under the terms of the BSD      *
005     * style license a copy of which has been included with this distribution in *
006     * the license.html file.                                                    *
007     *                                                                           *
008     * Idea by Rachel Davies, Original code by Aslak Hellesoy and Paul Hammant   *
009     *****************************************************************************/
010    
011    package org.nanocontainer.persistence.hibernate;
012    
013    import java.sql.Connection;
014    
015    import org.hibernate.HibernateException;
016    import org.hibernate.Interceptor;
017    import org.hibernate.Session;
018    import org.hibernate.SessionFactory;
019    import org.nanocontainer.persistence.ExceptionHandler;
020    
021    /**
022     * Session delegator with failover behaviour in case of hibernate exception. Old session is disposed
023     * and new one is obtained transparently. Session creation is done lazily.
024     * 
025     * @author Jose Peleteiro <juzepeleteiro@intelli.biz>
026     * @version $Revision: 2043 $
027     */
028    public class FailoverSessionDelegator extends SessionDelegator {
029    
030        private SessionFactory sessionFactory;
031        private Session session = null;
032        private Interceptor interceptor = null;
033        
034            /**
035             * @param sessionFactory session factory to obtain session from 
036             */
037        public FailoverSessionDelegator(SessionFactory sessionFactory) {
038            this.sessionFactory = sessionFactory;
039        }
040    
041            /**
042             * @param sessionFactory session factory to obtain session from 
043             * @param exceptionHandler Exception handler component to use with created session
044             */
045        public FailoverSessionDelegator(SessionFactory sessionFactory, ExceptionHandler exceptionHandler) {
046            super(exceptionHandler);
047            this.sessionFactory = sessionFactory;
048        }
049    
050            /**
051             * @param sessionFactory sessionf actory to obtain session from
052             * @param interceptor interceptor to use with created session
053             */
054        public FailoverSessionDelegator(SessionFactory sessionFactory, Interceptor interceptor) {
055            this(sessionFactory);
056            setInterceptor(interceptor);
057        }
058    
059            /**
060             * @param sessionFactory sessionf actory to obtain session from
061             * @param interceptor interceptor to use with created session
062             * @param exceptionHandler Exception handler component to use with created session
063             */
064        public FailoverSessionDelegator(SessionFactory sessionFactory, Interceptor interceptor, ExceptionHandler exceptionHandler) {
065            this(sessionFactory, exceptionHandler);
066            setInterceptor(interceptor);
067        }
068        
069        public SessionFactory getSessionFactory() {
070            return sessionFactory;
071        }
072    
073        /**
074         * Obtain hibernate session in lazy way.
075         */
076        public Session getDelegatedSession() {
077            if (session == null) {
078                try {
079                    session = interceptor == null ? sessionFactory.openSession() : sessionFactory.openSession(interceptor);
080                } catch (RuntimeException ex) {
081                    throw handleException(ex);
082                }
083            }
084    
085            return session;
086        }
087    
088        public Connection close() throws HibernateException {
089            try {
090                return getDelegatedSession().close();
091            } catch (HibernateException ex) {
092                session = null;
093                throw handleException(ex);
094            } finally {
095                session = null;
096            }
097        }
098    
099        public void invalidateDelegatedSession() throws HibernateException {
100            if (this.session != null) {
101                try {
102                    session.clear();
103                    session.close();
104                } catch (HibernateException ex) {
105                    session = null;
106                    throw handleException(ex);
107                } finally {
108                    session = null;
109                }
110            }
111        }
112    
113            public Interceptor getInterceptor() {
114                    return interceptor;
115            }
116    
117            public void setInterceptor(Interceptor interceptor) {
118                    this.interceptor = interceptor;
119            }
120    
121    }