de.hybris.platform.core.TenantRestartTest.java Source code

Java tutorial

Introduction

Here is the source code for de.hybris.platform.core.TenantRestartTest.java

Source

/*
 * [y] hybris Platform
 *
 * Copyright (c) 2000-2013 hybris AG
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of hybris
 * ("Confidential Information"). You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the
 * license agreement you entered into with hybris.
 *
 *
 */
package de.hybris.platform.core;

import de.hybris.bootstrap.annotations.IntegrationTest;
import de.hybris.platform.cache.Cache;
import de.hybris.platform.cache.InvalidationListener;
import de.hybris.platform.cache.InvalidationManager;
import de.hybris.platform.cache.InvalidationTopic;
import de.hybris.platform.jalo.ConsistencyCheckException;
import de.hybris.platform.jalo.JaloConnection;
import de.hybris.platform.jalo.JaloSession;
import de.hybris.platform.jalo.security.JaloSecurityException;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.collections.MapUtils;
import org.apache.log4j.Logger;
import org.fest.assertions.Assertions;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.ReflectionUtils;

@IntegrationTest
public class TenantRestartTest extends AbstractTenantInitializationTest {

    private static final String TABLE_NAME = "booBar";
    private static final Logger LOG = Logger.getLogger(TenantRestartTest.class.getName());
    private static final String MESSAGE_LISTENER_DEF = ""// NOPMD
            + "<beans xmlns=\"http://www.springframework.org/schema/beans\"\n"//
            + "       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"//
            + "       xsi:schemaLocation=\"http://www.springframework.org/schema/beans\n"//
            + "                            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd\">\n" //

            + "       <bean\n"//
            + "             id=\"test.tenant.startup.bean\"\n"//
            + "             class=\"" + TestAfterTenantStartupEventListener.class.getName() + "\"\n"//
            + "           >\n"//
            + "       </bean>\n"//
            + "</beans>";
    private volatile GenericApplicationContext applicationContext;
    private TestAfterTenantStartupEventListener testListener;

    @Override
    protected Collection<String> getTenantIds() {
        return java.util.Collections.singleton("t1");
    }

    @Override
    @Before
    public void setUp() throws Exception {

        final ApplicationContext parent = Registry.getCoreApplicationContext();

        applicationContext = new GenericApplicationContext();
        applicationContext.setParent(parent);

        final XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(applicationContext);
        xmlReader.loadBeanDefinitions(new ByteArrayResource(MESSAGE_LISTENER_DEF.getBytes()));

        applicationContext.refresh();

        testListener = applicationContext.getBean(TestAfterTenantStartupEventListener.class);
        Assertions.assertThat(testListener).isInstanceOf(TestAfterTenantStartupEventListener.class);
        super.setUp();

    }

    @Override
    @After
    public void tearDown() throws Exception {

        Initialization.closeSessions(getSlaveTenant("t1"));
        applicationContext.destroy();
        applicationContext = null;

        super.tearDown();
    }

    @Test
    public void testJaloSessionObsoleteAfterTenantRestart()
            throws JaloSecurityException, ConsistencyCheckException {

        final SlaveTenant localTenant = Registry.getSlaveTenants().get("t1");
        Registry.setCurrentTenant(localTenant);

        final JaloSession session = JaloConnection.getInstance().createAnonymousCustomerSession();

        Assertions.assertThat(JaloSession.getCurrentSession(localTenant)).isSameAs(session);
        Assertions.assertThat(JaloSession.assureSessionNotStale(session)).isTrue();

        localTenant.doShutDownDuringInitialization();

        //TODO remove it
        //JaloSession.getCurrentSession(); //creating anonymous jalo session in case there was no other

        Assertions.assertThat(JaloSession.assureSessionNotStale(session))
                .overridingErrorMessage("Session should be stale is from before shutdown").isFalse();
        try {
            session.activate();
            Assert.fail("Should be not able to activate the stale session");
        } catch (final IllegalStateException se) {
            //fine here
        }

        localTenant.doStartUp();

        final JaloSession otherSession = JaloConnection.getInstance().createAnonymousCustomerSession();

        Assertions.assertThat(JaloSession.getCurrentSession(localTenant)).isSameAs(otherSession);
        Assertions.assertThat(JaloSession.assureSessionNotStale(otherSession))
                .overridingErrorMessage("Session can't be stale is fresh right after startup").isTrue();

        otherSession.activate(); //activate - no harm
    }

    @Test
    public void testAfterStartupMessageSendAfterRestart() throws JaloSecurityException, ConsistencyCheckException {
        Registry.unsetCurrentTenant();
        Registry.unregisterShutdownTenant("t1");

        Assertions.assertThat(testListener.getEventsRecoreded().isEmpty()).isTrue();

        final SlaveTenant localTenant = new TestSlaveTenantStub(Registry.getSlaveTenants().get("t1"),
                applicationContext);

        //here to activate injected tenant
        Registry.setCurrentTenantInternal(localTenant);
        localTenant.doStartUp(); //no event on  start up

        Registry.setCurrentTenant(localTenant);

        Registry.destroyAndForceStartup(); //event on restart

        Assertions.assertThat(testListener.getEventsRecoreded().isEmpty());
        Assertions.assertThat(testListener.getEventsRecoreded().size()).isEqualTo(1);

    }

    @Test
    public void testFetchAccurateHybrisDataSourceAfterTenantRestart()
            throws JaloSecurityException, ConsistencyCheckException {
        String tableName = null;
        final SlaveTenant localTenant = Registry.getSlaveTenants().get("t1");
        try {
            Registry.setCurrentTenant(localTenant);

            tableName = localTenant.getDatabaseTablePrefix() == null ? TABLE_NAME
                    : localTenant.getDatabaseTablePrefix() + TABLE_NAME;

            final DataSource springBasedDataSourceBefore = Registry.getCoreApplicationContext()
                    .getBean(DataSource.class);
            Assert.assertSame("We should get the consistence data source vis spring factory  ",
                    springBasedDataSourceBefore, Registry.getCoreApplicationContext().getBean(DataSource.class));
            Assert.assertSame("We should get the same data source via spring or jalo ", springBasedDataSourceBefore,
                    Registry.getCurrentTenant().getDataSource());

            final JdbcTemplate springTemplateBefore = new JdbcTemplate(springBasedDataSourceBefore);
            createTable(springTemplateBefore, tableName);

            assertTableExistsTimes(springBasedDataSourceBefore, tableName);
            assertTableExistsTimes(Registry.getCurrentTenant().getDataSource(), tableName);

            localTenant.doShutDownDuringInitialization();

            final DataSource springBasedDataSourceAfter = Registry.getCoreApplicationContext()
                    .getBean(DataSource.class);
            Assert.assertSame("We should get the consistence data source vis spring factory  ",
                    springBasedDataSourceAfter, Registry.getCoreApplicationContext().getBean(DataSource.class));
            Assert.assertSame("We should get the same data source via spring or jalo ", springBasedDataSourceAfter,
                    Registry.getCurrentTenant().getDataSource());

            assertTableExistsTimes(springBasedDataSourceBefore, tableName);
            assertTableExistsTimes(springBasedDataSourceAfter, tableName);

        } finally {
            if (tableName != null) {
                dropTable(localTenant.getDataSource(), tableName);
            }
        }

    }

    @Test
    public void testTheSameInvalidationListenersAfterRestart()
            throws JaloSecurityException, ConsistencyCheckException {

        final SlaveTenant localTenant = Registry.getSlaveTenants().get("t1");
        try {
            Registry.setCurrentTenant(localTenant);

            final InvalidationManager invManagerBefore = InvalidationManager.getInstance();

            final InvalidationTopic topicBefore = InvalidationManager.getInstance()
                    .getInvalidationTopic(new String[] { Cache.CACHEKEY_HJMP, Cache.CACHEKEY_ENTITY });

            localTenant.doShutDownDuringInitialization();
            localTenant.startUp();

            Assert.assertSame("invalidation manager should remain the same", invManagerBefore,
                    InvalidationManager.getInstance());
            Assert.assertSame("invalidation topic should remain the same", topicBefore,
                    InvalidationManager.getInstance()
                            .getInvalidationTopic(new String[] { Cache.CACHEKEY_HJMP, Cache.CACHEKEY_ENTITY }));
            assertEqualListeners(topicBefore, InvalidationManager.getInstance()
                    .getInvalidationTopic(new String[] { Cache.CACHEKEY_HJMP, Cache.CACHEKEY_ENTITY }));
        } finally {
            //
        }

    }

    private void assertEqualListeners(final InvalidationTopic topicAfter, final InvalidationTopic topicBefore) {
        final List<InvalidationListener> listenersBefore = getListenersViaReflection(topicBefore);
        final List<InvalidationListener> listenersAfter = getListenersViaReflection(topicAfter);

        Assertions.assertThat(listenersAfter.size()).isEqualTo(listenersBefore.size());

        final List<InvalidationListener> copyBefore = new ArrayList<InvalidationListener>(listenersBefore);
        for (final InvalidationListener before : listenersBefore) {
            final int hashBefore = System.identityHashCode(before);
            for (final InvalidationListener after : listenersAfter) {
                final int hashAfter = System.identityHashCode(after);
                if (hashAfter == hashBefore) {
                    copyBefore.remove(before);
                    break;
                }
            }

        }

        Assert.assertTrue(copyBefore.isEmpty());
    }

    private List<InvalidationListener> getListenersViaReflection(final InvalidationTopic topic) {
        final Field listeners = ReflectionUtils.findField(InvalidationTopic.class, "listeners");
        Assertions.assertThat(listeners).isNotNull();
        listeners.setAccessible(true);
        return (List<InvalidationListener>) ReflectionUtils.getField(listeners, topic);
    }

    private void assertTableExistsTimes(final DataSource dataSource, final String tableName) {
        for (int i = 0; i < 100; i++) {
            assertTableExists(new JdbcTemplate(dataSource), tableName);
        }

    }

    private void assertTableExists(final JdbcTemplate template, final String tableName) {
        template.queryForList("SELECT ID  FROM " + tableName);

    }

    private void createTable(final JdbcTemplate template, final String tableName) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Create table " + tableName + " for tenant " + Registry.getCurrentTenantNoFallback());
        }
        template.execute("CREATE TABLE " + tableName + " ( ID VARCHAR(10))");
    }

    private void dropTable(final DataSource dataSource, final String tableName) {

        try {
            final JdbcTemplate create = new JdbcTemplate(dataSource);
            create.execute("DROP TABLE " + tableName);
        } catch (final DataAccessException e) {
            if (LOG.isDebugEnabled()) {
                LOG.debug(e);
            }
        }
    }

    static class TestSlaveTenantStub extends SlaveTenant {
        //private final SlaveTenant wrapped;
        private final GenericApplicationContext localApplicationContext;

        TestSlaveTenantStub(final SlaveTenant wrapped, final GenericApplicationContext applicationContext) {
            super(wrapped.getTenantID(), MapUtils.toProperties(wrapped.getOwnConfig().getAllParameters()));
            this.localApplicationContext = applicationContext;
        }

        @Override
        List<TenantListener> getTenantListeners() {
            return Collections.EMPTY_LIST;
        }

        @Override
        GenericApplicationContext getApplicationContext() {
            return this.localApplicationContext;
        }

        //internal
        @Override
        GenericApplicationContext createCoreApplicationContext() {
            return this.localApplicationContext;
        }
    }

}