net.krotscheck.jersey2.hibernate.factory.HibernateSessionFactoryFactory.java Source code

Java tutorial

Introduction

Here is the source code for net.krotscheck.jersey2.hibernate.factory.HibernateSessionFactoryFactory.java

Source

/*
 * Copyright (c) 2014 Michael Krotscheck
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy
 * of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.krotscheck.jersey2.hibernate.factory;

import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.api.PerThread;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostCommitDeleteEventListener;
import org.hibernate.event.spi.PostCommitInsertEventListener;
import org.hibernate.event.spi.PostCommitUpdateEventListener;
import org.hibernate.event.spi.PostDeleteEventListener;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.event.spi.PreDeleteEventListener;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.event.spi.PreUpdateEventListener;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.service.ServiceRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import javax.inject.Inject;

/**
 * This factory provides a singleton Hibernate SessionFactory for your
 * application context. You may use this to generate your own sessions if you
 * are not in an explicit request context, however if you do so please make sure
 * to clean up after yourself and call session.close().
 *
 * Furthermore, this injector will search through the ServiceLocator context to
 * determine if there are any Hibernate Event Listeners injected from other
 * features. It will gather those and automatically register them against the
 * hibernate factory.
 *
 * @author Michael Krotscheck
 */
public final class HibernateSessionFactoryFactory implements Factory<SessionFactory> {

    /**
     * Logger instance.
     */
    private static Logger logger = LoggerFactory.getLogger(HibernateSessionFactoryFactory.class);

    /**
     * Create a new factory factory.
     *
     * @param hibernateConfig The Hibernate Config
     * @param serviceLocator  The service locator from which to resolve event
     *                        handlers.
     */
    @Inject
    public HibernateSessionFactoryFactory(final Configuration hibernateConfig,
            final ServiceLocator serviceLocator) {
        this.configuration = hibernateConfig;
        this.locator = serviceLocator;
    }

    /**
     * Injected hibernate configuration.
     */
    private Configuration configuration;

    /**
     * The service locator.
     */
    private ServiceLocator locator;

    /**
     * Provide a singleton instance of the hibernate session factory.
     *
     * @return A session factory.
     */
    @Override
    public SessionFactory provide() {
        logger.trace("Creating hibernate session factory.");

        // Build the service registry.
        ServiceRegistry registry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties())
                .build();

        SessionFactory factory = configuration.buildSessionFactory(registry);

        // Register our event listeners.
        injectEventListeners(((SessionFactoryImpl) factory).getServiceRegistry());

        return factory;
    }

    /**
     * Dispose of the hibernate session.
     *
     * @param sessionFactory The session to dispose.
     */
    @Override
    public void dispose(final SessionFactory sessionFactory) {
        if (sessionFactory != null && !sessionFactory.isClosed()) {
            logger.info("Disposing of hibernate session factory.");
            sessionFactory.close();
        }
    }

    /**
     * This method automatically adds discovered hibernate event listeners into
     * the hibernate service registry.
     *
     * @param registry The service registry.
     */
    private void injectEventListeners(final ServiceRegistry registry) {

        EventListenerRegistry eventRegistry = registry.getService(EventListenerRegistry.class);

        List<PostInsertEventListener> postInsertEvents = locator.getAllServices(PostInsertEventListener.class);
        for (PostInsertEventListener piEventListener : postInsertEvents) {
            logger.trace("Registering PostInsert: " + piEventListener.getClass().getCanonicalName());
            eventRegistry.appendListeners(EventType.POST_INSERT, piEventListener);
        }

        List<PostUpdateEventListener> postUpdateEvents = locator.getAllServices(PostUpdateEventListener.class);
        for (PostUpdateEventListener puEventListener : postUpdateEvents) {
            logger.trace("Registering PostUpdate: " + puEventListener.getClass().getCanonicalName());
            eventRegistry.appendListeners(EventType.POST_UPDATE, puEventListener);
        }

        List<PostDeleteEventListener> postDeleteEvents = locator.getAllServices(PostDeleteEventListener.class);
        for (PostDeleteEventListener pdEventListener : postDeleteEvents) {
            logger.trace("Registering PostDelete: " + pdEventListener.getClass().getCanonicalName());
            eventRegistry.appendListeners(EventType.POST_DELETE, pdEventListener);
        }

        List<PreInsertEventListener> preInsertEvents = locator.getAllServices(PreInsertEventListener.class);
        for (PreInsertEventListener piEventListener : preInsertEvents) {
            logger.trace("Registering PreInsert: " + piEventListener.getClass().getCanonicalName());
            eventRegistry.appendListeners(EventType.PRE_INSERT, piEventListener);
        }

        List<PreUpdateEventListener> preUpdateEvents = locator.getAllServices(PreUpdateEventListener.class);
        for (PreUpdateEventListener puEventListener : preUpdateEvents) {
            logger.trace("Registering PreUpdate: " + puEventListener.getClass().getCanonicalName());
            eventRegistry.appendListeners(EventType.PRE_UPDATE, puEventListener);
        }

        List<PreDeleteEventListener> preDeleteEvents = locator.getAllServices(PreDeleteEventListener.class);
        for (PreDeleteEventListener pdEventListener : preDeleteEvents) {
            logger.trace("Registering PreDelete: " + pdEventListener.getClass().getCanonicalName());
            eventRegistry.appendListeners(EventType.PRE_DELETE, pdEventListener);
        }

        List<PostCommitInsertEventListener> pciEvents = locator.getAllServices(PostCommitInsertEventListener.class);
        for (PostCommitInsertEventListener cpiEventListener : pciEvents) {
            logger.trace("Registering PostCommitInsert: " + cpiEventListener.getClass().getCanonicalName());
            eventRegistry.appendListeners(EventType.POST_COMMIT_INSERT, cpiEventListener);
        }

        List<PostCommitUpdateEventListener> pcuEvents = locator.getAllServices(PostCommitUpdateEventListener.class);
        for (PostCommitUpdateEventListener cpuEventListener : pcuEvents) {
            logger.trace("Registering PostCommitUpdate: " + cpuEventListener.getClass().getCanonicalName());
            eventRegistry.appendListeners(EventType.POST_COMMIT_UPDATE, cpuEventListener);
        }

        List<PostCommitDeleteEventListener> pcdEvents = locator.getAllServices(PostCommitDeleteEventListener.class);
        for (PostCommitDeleteEventListener cpdEventListener : pcdEvents) {
            logger.trace("Registering PostCommitDelete: " + cpdEventListener.getClass().getCanonicalName());
            eventRegistry.appendListeners(EventType.POST_COMMIT_DELETE, cpdEventListener);
        }
    }

    /**
     * HK2 Binder for our injector context.
     */
    public static final class Binder extends AbstractBinder {

        @Override
        protected void configure() {
            bindFactory(HibernateSessionFactoryFactory.class).to(SessionFactory.class).in(PerThread.class);
        }
    }
}