0

zk hibernate session per conversation

asked 2013-02-27 15:08:51 +0800

motti gravatar image motti
0

I started to use hibernate combined with zk framework.

  • hibernate 3.6.10.final
  • zk 5.0.11

I'm intensivly using both first level caches and lazy loading so I deduced that OpenSessionInView pattern didn't fill my needs so I switched to session per conversation.

Attached at the end of this thread you'll find a simple implementation of this pattern where I decided to bind hibernate session directly to the zk desktop.

I read around that this solution can lead to some known problems:

  1. hiberante session may grow indefinitely
  2. zk desktop close event may be lost
  3. ...

SessionHolder class is a session factory that creates (through an hibernate Sessionfactory) and keeps a reference to the session. It is bound to the zk desktop using attribute HIBERNATE_SESSION_HOLDER_DESKTOP_ATTR_NAME on zk execution start (ExecutionInit).

EventThreadInit.init() and EventThreadCleanup.cleanup() will do the binding and unbinding of the hibernate session kept inside the SessionHolder (on zk event thread, using ThreadLocalSessionContext.bind and ThreadLocalSessionContext.unbind()). This way, and since I set hibernate.current_session_context_class to thread, any subsequent call to SessionFactory.currentSession() will return the session bound to the zk desktop via SessionHolder and won't create any new session by itself.

When the desktop is disposed (DesktopCleanup.cleanup()) SessionHolder will be realeased (SessionHolder.realease()) closing the hibernate session.

I also defined a static method startNewWorkUnit() to recreate the hibernate session (it opens a new one and closes the previouse, if necessary) so as to release the session memory and avoid memory growth issue.

I'm wondering if I could face other issues... Can someone give me any advices on this ?


public class ZKHibernateIntegration implements ExecutionInit, ExecutionCleanup,
        EventThreadInit, EventThreadCleanup, DesktopCleanup {

    private static final String HIBERNATE_SESSION_HOLDER_DESKTOP_ATTR_NAME = "_hibernateSessionHolder";

    public ZKHibernateIntegration() {
    }

    /*
     * ExecutionInit, ExecutionCleanup
     */

    // -- ExecutionInit --//
    public void init(Execution exec, Execution parent) {
        if (parent != null) { // the root execution
            return;
        }
        Desktop desktop = exec.getDesktop();
        getSessionHolder(desktop, true);
    }

    // -- ExecutionCleanup --//
    public void cleanup(Execution exec, Execution parent,
            @SuppressWarnings("rawtypes") List errs) {
        if (parent != null) { // the root execution
            return;
        }

        Desktop desktop = exec.getDesktop();
        SessionHolder sh = getSessionHolder(desktop, false);
        if (sh != null) {
            freeSessionResource(sh.getSession());
        }
    }

    /*
     * EventThreadInit, EventThreadCleanup
     */

    // -- EventThreadInit -- //
    @Override
    public boolean init(Component comp, Event event) throws Exception {

        if (!enabled || comp == null) {
            return true;
        }
        Desktop desktop = Executions.getCurrent().getDesktop();
        SessionHolder sh = getSessionHolder(desktop, false);
        // Bind
        ThreadLocalSessionContext.bind(sh.getSession());

        return true;
    }

    // -- EventThreadCleanup -- //
    @Override
    @SuppressWarnings("rawtypes")
    public void cleanup(Component comp, Event evt, List errs) throws Exception {
        if (!enabled || comp == null) {
            return;
        }
        Desktop desktop = Executions.getCurrent().getDesktop();
        SessionHolder sh = getSessionHolder(desktop, false);
        if (sh == null) {
            return;
        }
        // hibernate session unbind inside event thread di zk
        ThreadLocalSessionContext.unbind(sh.getSession().getSessionFactory());
    }

    @Override
    public void complete(Component comp, Event evt) throws Exception {
    }

    @Override
    public void prepare(Component comp, Event event) throws Exception {
    }

    /*
     * DesktopCleanup
     */

    public void cleanup(Desktop desktop) throws Exception {
        cleanupSessionHolder(desktop);
    }

    public static void startNewWorkUnit() {
           Desktop desktop = Executions.getCurrent().getDesktop();
        SessionHolder sh = getSessionHolder(desktop, false);
        if (sh != null) {
            cleanupSessionHolder(Executions.getCurrent().getDesktop());
            sh = getSessionHolder(desktop, true);
        }
        Session session = sh.getSession();
        // hibernate session bind inside zk event thread
        ThreadLocalSessionContext.bind(session);
    }

    /*
     * Implementation
     */

    private void freeSessionResource(Session session) {
        if (session.getTransaction().isActive()) {
            session.getTransaction().rollback();
        }
        session.disconnect();
    }

    private static SessionHolder getSessionHolder(Desktop desktop,
            boolean create) {
        SessionHolder sh = (SessionHolder) desktop
                .getAttribute(HIBERNATE_SESSION_HOLDER_DESKTOP_ATTR_NAME);
        if (sh != null || !create) {
            return sh;
        }

        SessionHolderFactory shf = createSessionHolderFactory();
        sh = createSessionHolder(desktop, shf);
        return sh;
    }

    private static void cleanupSessionHolder(Desktop desktop) {
        SessionHolder sh = getSessionHolder(desktop, false);
        if (sh == null) {
            return;
        }

        try {
            Session session = sh.getSession();

            // hibernate session unbind inside event thread
            ThreadLocalSessionContext.unbind(session.getSessionFactory());
        } catch (Throwable e) {
            log.error("Exception in cleanup [desktop=" + desktop.getId() + "]",
                    e);
        } finally {
            if (sh != null) {
                try {
                    sh.release();
                } catch (Exception e) {
                    log.error("Exception in cleanup sessionHolder", e);
                }
            }
            desktop.setAttribute(HIBERNATE_SESSION_HOLDER_DESKTOP_ATTR_NAME,
                    null);
        }
    }

    private static SessionHolderFactory createSessionHolderFactory() {
        // code omitted
        //creates ALWAYS a new session holder factory
    }

    private static SessionHolder createSessionHolder(Desktop desktop,
            SessionHolderFactory shf) {
        SessionHolder sh = shf.create();
        desktop.setAttribute(HIBERNATE_SESSION_HOLDER_DESKTOP_ATTR_NAME, sh);
        return sh;
    }
}
delete flag offensive retag edit
Be the first one to answer this question!
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow
3 followers

RSS

Stats

Asked: 2013-02-27 15:08:51 +0800

Seen: 13 times

Last updated: Feb 27 '13

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More