com.timesoft.kaitoo.ws.hibernate.TransactionalProcessor.java Source code

Java tutorial

Introduction

Here is the source code for com.timesoft.kaitoo.ws.hibernate.TransactionalProcessor.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.timesoft.kaitoo.ws.hibernate;

import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

/**
 *
 * @author sorasaks
 */
public abstract class TransactionalProcessor {

    //~ Static fields/initializers 
    private static final ThreadLocal<List<TransactionalProcessor>> CONTEXT = new ThreadLocal<List<TransactionalProcessor>>();

    //~ Instance fields 
    private Logger logger;
    //    protected static final int DUPLICATE_CODE = 2601;
    protected static final int DUPLICATE_CODE = 2627;
    //~ Constructors 

    /**
     * Creates a new TransactionalProcessor object.
     */
    public TransactionalProcessor() {
        this(Logger.getLogger(TransactionalProcessor.class));
    }

    /**
     * Creates a new TransactionalProcessor object.
     *
     * @param logger DOCUMENT ME!
     */
    public TransactionalProcessor(final Logger logger) {
        logger.getClass(); // check null

        this.logger = logger;

        List<TransactionalProcessor> stack = CONTEXT.get();

        if (null == stack) {
            CONTEXT.set(stack = new ArrayList<TransactionalProcessor>());
        }

        stack.add(this);
    }

    //~ Methods 
    /**
     * DOCUMENT ME!
     *
     */
    public final void process() {
        SessionFactory factory = new Configuration().configure().buildSessionFactory();
        Session session = factory.openSession();
        /**
         * Session::beginTransaction() can be called twice or more, so no need
         * to check whether this is the ROOT context or not.
         */
        Transaction tx = session.beginTransaction();

        try {
            if (logger.isDebugEnabled()) {
                logger.debug("About to process user transaction.");
            }

            if (CONTEXT.get().size() == 1) {
                logger.debug("Current transaction is ROOT context, clean it up before using.");
                session.clear();
            }

            process(session, tx);

            if (logger.isDebugEnabled()) {
                logger.debug("About to commit transaction.");
            }

            session.flush();

            if (CONTEXT.get().size() == 1) {
                tx.commit();

                if (logger.isDebugEnabled()) {
                    logger.debug("Transaction committed successfully.");
                }
            } else {
                logger.debug("Current transaction is not the ROOT one, commit pending.");
            }
        } catch (final Exception e) {
            List<TransactionalProcessor> stack = CONTEXT.get();

            logger.error(e.getMessage(), e);

            if (stack.size() == 1) {
                tx.rollback();
                logger.debug("It's ROOT context, transaction rolled back.");
            }

            //            if (e instanceof JDBCException) {
            //                JDBCException x = (JDBCException) e;
            //
            //                throw x.getSQLException();
            //            }
            //
            //            throw e;
        } finally {
            List<TransactionalProcessor> stack = CONTEXT.get();

            if (stack.remove(this)) {
                if (logger.isDebugEnabled()) {
                    logger.debug(String.format("Total %1$s left on the stack: %2$d", getClass().toString(),
                            stack.size()));
                }
            } else {
                logger.warn(String.format("%1$s not found on the stack (total: %2$d).", getClass().toString(),
                        stack.size()));
            }

            if (stack.isEmpty()) {
                session.clear();
                session.close();
                logger.debug("It's ROOT context, Hibernate session cleaned up.");
            } else {
                logger.debug("Not a ROOT context, Hibernate session cleanup ignored.");
            }
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @param session DOCUMENT ME!
     * @param tx DOCUMENT ME!
     *
     * @throws Exception DOCUMENT ME!
     */
    public abstract void process(final Session session, final Transaction tx) throws Exception;
}