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

Java tutorial

Introduction

Here is the source code for net.krotscheck.jersey2.hibernate.factory.HibernateSessionFactoryFactoryTest.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 net.krotscheck.test.UnitTest;
import org.glassfish.hk2.api.PerThread;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ApplicationHandler;
import org.glassfish.jersey.server.ResourceConfig;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.event.service.spi.EventListenerGroup;
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.PostDeleteEvent;
import org.hibernate.event.spi.PostDeleteEventListener;
import org.hibernate.event.spi.PostInsertEvent;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.event.spi.PostUpdateEvent;
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.event.spi.PreDeleteEvent;
import org.hibernate.event.spi.PreDeleteEventListener;
import org.hibernate.event.spi.PreInsertEvent;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.event.spi.PreUpdateEvent;
import org.hibernate.event.spi.PreUpdateEventListener;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.service.ServiceRegistry;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;

/**
 * Unit test for our hibernate session factory factory.
 *
 * @author Michael Krotscheck
 */
@Category(UnitTest.class)
public final class HibernateSessionFactoryFactoryTest {

    /**
     * The jersey application handler.
     */
    private ApplicationHandler handler;

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

    /**
     * Setup the application handler for this test.
     */
    @Before
    public void setup() {
        ResourceConfig config = new ResourceConfig();
        config.register(TestFeature.class);
        handler = new ApplicationHandler(config);
        locator = handler.getServiceLocator();
    }

    /**
     * Teardown the application handler.
     */
    @After
    public void teardown() {
        locator.shutdown();
        locator = null;
        handler = null;
    }

    /**
     * Test provide and dispose.
     */
    @Test
    public void testProvideDispose() {
        Configuration config = locator.getService(Configuration.class);
        HibernateSessionFactoryFactory factoryFactory = new HibernateSessionFactoryFactory(config, locator);
        SessionFactory factory = locator.getService(SessionFactory.class);

        // Assert that the factory is open.
        Assert.assertFalse(factory.isClosed());

        // Make sure that we can create a session.
        Session session = factory.openSession();
        Assert.assertNotNull(session);
        Assert.assertTrue(session.isOpen());

        // Make sure we can dispose of the factory.
        factoryFactory.dispose(factory);
        Assert.assertTrue(factory.isClosed());
        Assert.assertFalse(session.isOpen());

        // Make sure doing it twice won't fail.
        factoryFactory.dispose(factory);

        // Make sure passing null doesn't fail
        factoryFactory.dispose(null);
    }

    /**
     * Test the application binder.
     */
    @Test
    public void testBinder() {

        // Create a fake application.
        SessionFactory factoryFactory = locator.getService(SessionFactory.class);
        Assert.assertNotNull(factoryFactory);

        // Make sure it's reading from the same place.
        Assert.assertFalse(factoryFactory.isClosed());

        // Make sure it's a singleton...
        SessionFactory factoryFactory2 = handler.getServiceLocator().getService(SessionFactory.class);
        Assert.assertSame(factoryFactory, factoryFactory2);
    }

    /**
     * Test the application event injectors.
     */
    @Test
    public void testEventInjection() {

        // Create a fake application.
        SessionFactory factoryFactory = locator.getService(SessionFactory.class);
        Assert.assertNotNull(factoryFactory);

        ServiceRegistry serviceRegistry = ((SessionFactoryImpl) factoryFactory).getServiceRegistry();
        EventListenerRegistry eventRegistry = serviceRegistry.getService(EventListenerRegistry.class);

        EventListenerGroup<PreInsertEventListener> priGroup = eventRegistry
                .getEventListenerGroup(EventType.PRE_INSERT);
        assertContainsListener(priGroup);

        EventListenerGroup<PostInsertEventListener> poiGroup = eventRegistry
                .getEventListenerGroup(EventType.POST_INSERT);
        assertContainsListener(poiGroup);

        EventListenerGroup<PreUpdateEventListener> pruGroup = eventRegistry
                .getEventListenerGroup(EventType.PRE_UPDATE);
        assertContainsListener(pruGroup);

        EventListenerGroup<PostUpdateEventListener> pouGroup = eventRegistry
                .getEventListenerGroup(EventType.POST_UPDATE);
        assertContainsListener(pouGroup);

        EventListenerGroup<PreDeleteEventListener> prdGroup = eventRegistry
                .getEventListenerGroup(EventType.PRE_DELETE);
        assertContainsListener(prdGroup);

        EventListenerGroup<PostDeleteEventListener> podGroup = eventRegistry
                .getEventListenerGroup(EventType.POST_DELETE);
        assertContainsListener(podGroup);

        EventListenerGroup<PostInsertEventListener> pciGroup = eventRegistry
                .getEventListenerGroup(EventType.POST_COMMIT_INSERT);
        assertContainsListener(pciGroup);

        EventListenerGroup<PostUpdateEventListener> pcuGroup = eventRegistry
                .getEventListenerGroup(EventType.POST_COMMIT_UPDATE);
        assertContainsListener(pcuGroup);

        EventListenerGroup<PostDeleteEventListener> pcdGroup = eventRegistry
                .getEventListenerGroup(EventType.POST_COMMIT_DELETE);
        assertContainsListener(pcdGroup);
    }

    /**
     * Helper method that asserts that our event listener is in the passed
     * group.
     *
     * @param group The event listener group in question.
     */
    private void assertContainsListener(final EventListenerGroup group) {

        for (Object listener : group.listeners()) {
            if (listener instanceof TestEventListener) {
                return;
            }
        }

        Assert.assertFalse(true);
    }

    /**
     * A private class to test our feature injection.
     */
    private static class TestFeature implements Feature {

        @Override
        public boolean configure(final FeatureContext context) {
            context.register(new HibernateConfigurationFactory.Binder());
            context.register(new HibernateSessionFactoryFactory.Binder());
            context.register(new TestEventListener.Binder());
            return true;
        }
    }

    /**
     * A test event listener to ensure that the session factory can read them
     * from the injection context.
     */
    public static final class TestEventListener implements PreInsertEventListener, PostInsertEventListener,
            PreUpdateEventListener, PostUpdateEventListener, PreDeleteEventListener, PostDeleteEventListener,
            PostCommitInsertEventListener, PostCommitUpdateEventListener, PostCommitDeleteEventListener {

        @Override
        public void onPostDelete(final PostDeleteEvent event) {

        }

        @Override
        public void onPostInsert(final PostInsertEvent event) {

        }

        @Override
        public void onPostUpdate(final PostUpdateEvent event) {

        }

        @Override
        public boolean requiresPostCommitHanding(final EntityPersister persister) {
            return false;
        }

        @Override
        public boolean onPreDelete(final PreDeleteEvent event) {
            return false;
        }

        @Override
        public boolean onPreInsert(final PreInsertEvent event) {
            return false;
        }

        @Override
        public boolean onPreUpdate(final PreUpdateEvent event) {
            return false;
        }

        @Override
        public void onPostDeleteCommitFailed(final PostDeleteEvent event) {

        }

        @Override
        public void onPostInsertCommitFailed(final PostInsertEvent event) {

        }

        @Override
        public void onPostUpdateCommitFailed(final PostUpdateEvent event) {

        }

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

            @Override
            protected void configure() {
                bind(TestEventListener.class).to(PostDeleteEventListener.class).to(PreDeleteEventListener.class)
                        .to(PreInsertEventListener.class).to(PostInsertEventListener.class)
                        .to(PreUpdateEventListener.class).to(PostUpdateEventListener.class)
                        .to(PostCommitInsertEventListener.class).to(PostCommitUpdateEventListener.class)
                        .to(PostCommitDeleteEventListener.class).in(PerThread.class);
            }
        }
    }
}