org.openmrs.test.StartModuleExecutionListener.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.test.StartModuleExecutionListener.java

Source

/**
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 * obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
 * the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
 *
 * Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
 * graphic logo is a trademark of OpenMRS Inc.
 */
package org.openmrs.test;

import java.net.URL;
import java.util.Enumeration;
import java.util.Properties;

import org.apache.commons.lang.StringUtils;
import org.junit.Assert;
import org.openmrs.api.context.Context;
import org.openmrs.api.db.SerializedObjectDAOTest;
import org.openmrs.module.ModuleConstants;
import org.openmrs.module.ModuleFactory;
import org.openmrs.module.ModuleInteroperabilityTest;
import org.openmrs.module.ModuleUtil;
import org.openmrs.util.OpenmrsClassLoader;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.UrlResource;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;

/**
 * To use this annotation, add the @StartModule( { "/path/to/your/module.omod" } ) annotation to the
 * test class
 * 
 * @see SerializedObjectDAOTest
 * @see ModuleInteroperabilityTest
 * @see BaseContextSensitiveTest
 */
public class StartModuleExecutionListener extends AbstractTestExecutionListener {

    // stores the last class that restarted the module system because we only 
    // want it restarted once per class, not once per method
    private static String lastClassRun = "";

    /**
     * called before @BeforeTransaction methods
     * 
     * @see org.springframework.test.context.support.AbstractTestExecutionListener#prepareTestInstance(org.springframework.test.context.TestContext)
     */
    @Override
    public void prepareTestInstance(TestContext testContext) throws Exception {
        StartModule startModuleAnnotation = testContext.getTestClass().getAnnotation(StartModule.class);

        // if the developer listed some modules with the @StartModule annotation on the class
        if (startModuleAnnotation != null) {

            if (!lastClassRun.equals(testContext.getTestClass().getSimpleName())) {
                // mark this with our class so that the services are only restarted once
                lastClassRun = testContext.getTestClass().getSimpleName();

                if (!Context.isSessionOpen())
                    Context.openSession();

                ModuleUtil.shutdown();

                // load the omods that the dev defined for this class
                String modulesToLoad = StringUtils.join(startModuleAnnotation.value(), " ");

                Properties props = BaseContextSensitiveTest.runtimeProperties;
                props.setProperty(ModuleConstants.RUNTIMEPROPERTY_MODULE_LIST_TO_LOAD, modulesToLoad);
                try {
                    ModuleUtil.startup(props);
                } catch (Exception e) {
                    System.out.println("Error while starting modules: ");
                    e.printStackTrace(System.out);
                    throw e;
                }
                Assert.assertTrue(
                        "Some of the modules did not start successfully for "
                                + testContext.getTestClass().getSimpleName() + ". Only "
                                + ModuleFactory.getStartedModules().size() + " modules started instead of "
                                + startModuleAnnotation.value().length,
                        startModuleAnnotation.value().length <= ModuleFactory.getStartedModules().size());

                /*
                 * Refresh spring so the Services are recreated (aka serializer gets put into the SerializationService)
                 * To do this, wrap the applicationContext from the testContext into a GenericApplicationContext, allowing
                 * loading beans from moduleApplicationContext into it and then calling ctx.refresh()
                 * This approach ensures that the application context remains consistent
                 */
                GenericApplicationContext ctx = new GenericApplicationContext(testContext.getApplicationContext());
                XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);

                Enumeration<URL> list = OpenmrsClassLoader.getInstance()
                        .getResources("moduleApplicationContext.xml");
                while (list.hasMoreElements()) {
                    xmlReader.loadBeanDefinitions(new UrlResource(list.nextElement()));
                }

                //ensure that when refreshing, we use the openmrs class loader for the started modules.
                boolean useSystemClassLoader = Context.isUseSystemClassLoader();
                Context.setUseSystemClassLoader(false);
                try {
                    ctx.refresh();
                } finally {
                    Context.setUseSystemClassLoader(useSystemClassLoader);
                }

                // session is closed by the test framework
                //Context.closeSession();
            }
        }
    }

    @Override
    public void afterTestClass(TestContext testContext) throws Exception {
        StartModule startModuleAnnotation = testContext.getTestClass().getAnnotation(StartModule.class);

        if (startModuleAnnotation != null) {
            if (!Context.isSessionOpen()) {
                Context.openSession();
            }

            ModuleUtil.shutdown();

            Context.closeSession();
        }
    }
}