com.quakearts.webapp.hibernate.CurrentSessionContextHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.quakearts.webapp.hibernate.CurrentSessionContextHelper.java

Source

/*******************************************************************************
* Copyright (C) 2016 Kwaku Twumasi-Afriyie <kwaku.twumasi@quakearts.com>.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Kwaku Twumasi-Afriyie <kwaku.twumasi@quakearts.com> - initial API and implementation
 ******************************************************************************/
package com.quakearts.webapp.hibernate;

import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionException;
import org.hibernate.Transaction;
import org.hibernate.context.spi.CurrentSessionContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.resource.transaction.spi.TransactionStatus;

/**Base class for implementations of {@linkplain CurrentSessionContext}. This provides support for
 * {@link org.hibernate.SessionFactory SessionFactory}'s {@link org.hibernate.SessionFactory#getCurrentSession() getCurrentSession()}
 * method in non-JTA environments
 * @author kwakutwumasi-afriyie
 *
 */
public abstract class CurrentSessionContextHelper implements CurrentSessionContext {

    /**
     * 
     */
    private static final long serialVersionUID = 3927106770407518460L;
    private static final Logger log = Logger.getLogger(CurrentSessionContextHelper.class.getName());
    public static final String CURRENTSESSION = "com.quakearts.webapp.hibernate.SESSION";
    public static final String DOMAIN = "com.quakearts.webapp.hibernate.DOMAIN";

    private static final Map<String, CurrentSessionContextHelper> sessionHelperCache = new ConcurrentHashMap<>(3);
    protected static final String EMPTY = "";

    private SessionFactoryImplementor implementor;
    protected String domain;

    public CurrentSessionContextHelper(SessionFactoryImplementor implementor) {
        this.implementor = implementor;
        domain = (String) implementor.getProperties().get(DOMAIN);
        if (domain == null)
            domain = EMPTY;

        if (sessionHelperCache.containsKey(domain))
            throw new IllegalArgumentException(
                    "Domain " + domain + " has already been set up in this application context");

        sessionHelperCache.put(domain, this);
    }

    public static CurrentSessionContextHelper getInstance() {
        return sessionHelperCache.get(EMPTY);
    }

    public static CurrentSessionContextHelper getInstance(String domain) {
        return sessionHelperCache.get(domain);
    }

    @Override
    public Session currentSession() throws HibernateException {
        Session session = getCurrentSessionFromContextAttributes();

        if (session == null)
            session = createCurrentSession();

        return session;
    }

    protected abstract Session getCurrentSessionFromContextAttributes();

    protected abstract void putCurrentSessionInContextAttributes(Session session);

    protected abstract void removeCurrentSessionFromContextAttributes();

    protected String getKey() {
        return CURRENTSESSION + (domain != null ? ":" + domain : EMPTY);
    }

    private Session createCurrentSession() {
        try {
            Session session = implementor.openSession();
            session.beginTransaction();

            putCurrentSessionInContextAttributes(session);

            return session;
        } catch (HibernateException e) {
            throw new IllegalStateException(e);
        }
    }

    public static void closeOpenSessions() {

        ArrayList<Exception> exceptions = new ArrayList<>();

        for (CurrentSessionContextHelper helper : sessionHelperCache.values()) {
            Session session = helper.getCurrentSessionFromContextAttributes();

            if (session == null)
                return;

            helper.removeCurrentSessionFromContextAttributes();

            Transaction tx = session.getTransaction();

            if (tx == null)
                throw new IllegalStateException("Transaction cannot be found.");

            try {
                if (tx.getStatus() == TransactionStatus.ACTIVE) {
                    tx.commit();
                } else if (tx.getStatus() == TransactionStatus.MARKED_ROLLBACK) {
                    tx.rollback();
                } else {
                    throw new IllegalStateException("Transaction is not in an epected state");
                }
            } catch (HibernateException e) {
                exceptions.add(new Exception("Exception thrown whiles cleaning up domain: " + helper.domain, e));
            } finally {
                try {//Reclose just in case
                    session.close();
                } catch (SessionException e) {
                    //Ignore
                } catch (Exception e) {
                    exceptions
                            .add(new Exception("Exception thrown whiles cleaning up domain: " + helper.domain, e));
                }
            }
        }

        if (exceptions.size() > 0) {
            for (Exception e : exceptions) {
                log.log(Level.SEVERE, e.getMessage(), e);
            }

            throw new IllegalStateException("Error during session cleanup");
        }
    }

}