Package org.hotswap.agent.plugin.spring

Source Code of org.hotswap.agent.plugin.spring.SpringPluginTest

package org.hotswap.agent.plugin.spring;

import org.hotswap.agent.plugin.hotswapper.HotSwapper;
import org.hotswap.agent.plugin.spring.scanner.ClassPathBeanDefinitionScannerAgent;
import org.hotswap.agent.plugin.spring.testBeans.BeanPrototype;
import org.hotswap.agent.plugin.spring.testBeans.BeanRepository;
import org.hotswap.agent.plugin.spring.testBeans.BeanService;
import org.hotswap.agent.plugin.spring.testBeans.BeanServiceImpl;
import org.hotswap.agent.plugin.spring.testBeansHotswap.BeanPrototype2;
import org.hotswap.agent.plugin.spring.testBeansHotswap.BeanRepository2;
import org.hotswap.agent.plugin.spring.testBeansHotswap.BeanServiceImpl2;
import org.hotswap.agent.util.ReflectionHelper;
import org.hotswap.agent.util.test.WaitHelper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
* Hotswap class files of spring beans.
*
* See maven setup for javaagent and autohotswap settings.
*
* @author Jiri Bubnik
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SpringPluginTest {

    @Autowired
    AutowireCapableBeanFactory factory;

    /**
     * Check correct setup.
     */
    @Test
    public void basicTest() {
        assertEquals("Hello from Repository ServiceWithAspect", factory.getBean(BeanService.class).hello());
        assertEquals("Hello from Repository ServiceWithAspect Prototype", factory.getBean(BeanPrototype.class).hello());
    }


    /**
     * Switch method implementation (using bean definition or interface).
     */
    @Test
    public void hotswapSeviceTest() throws Exception {
        assertEquals("Hello from Repository ServiceWithAspect", factory.getBean(BeanServiceImpl.class).hello());
        swapClasses(BeanServiceImpl.class, BeanServiceImpl2.class.getName());
        assertEquals("Hello from ChangedRepository Service2WithAspect", factory.getBean(BeanServiceImpl.class).hello());
        // ensure that using interface is Ok as well
        assertEquals("Hello from ChangedRepository Service2WithAspect", factory.getBean(BeanService.class).hello());

        // return configuration
        swapClasses(BeanServiceImpl.class, BeanServiceImpl.class.getName());
        assertEquals("Hello from Repository ServiceWithAspect", factory.getBean(BeanServiceImpl.class).hello());
    }


    /**
     * Add new method - invoke via reflection (not available at compilation time).
     */
//    @Test
    public void hotswapSeviceAddMethodTest() throws Exception {
        swapClasses(BeanServiceImpl.class, BeanServiceImpl2.class.getName());

        String helloNewMethodIfaceVal = (String) ReflectionHelper.invoke(factory.getBean(BeanService.class),
                BeanServiceImpl.class, "helloNewMethod", new Class[] {});
        assertEquals("Hello from helloNewMethod Service2", helloNewMethodIfaceVal);

        String helloNewMethodImplVal = (String) ReflectionHelper.invoke(factory.getBean(BeanServiceImpl.class),
                BeanServiceImpl.class, "helloNewMethod", new Class[] {});
        assertEquals("Hello from helloNewMethod Service2", helloNewMethodImplVal);

        // return configuration
        swapClasses(BeanServiceImpl.class, BeanServiceImpl.class.getName());
        assertEquals("Hello from Repository ServiceWithAspect", factory.getBean(BeanServiceImpl.class).hello());
    }

    @Test
    public void hotswapRepositoryTest() throws Exception {
        assertEquals("Hello from Repository ServiceWithAspect", factory.getBean(BeanServiceImpl.class).hello());
        swapClasses(BeanRepository.class, BeanRepository2.class.getName());
        assertEquals("Hello from ChangedRepository2 ServiceWithAspect", factory.getBean(BeanServiceImpl.class).hello());

        // return configuration
        swapClasses(BeanRepository.class, BeanRepository.class.getName());
        assertEquals("Hello from Repository ServiceWithAspect", factory.getBean(BeanServiceImpl.class).hello());
    }

    @Test
    public void hotswapRepositoryNewMethodTest() throws Exception {
        assertEquals("Hello from Repository ServiceWithAspect", factory.getBean(BeanServiceImpl.class).hello());
        swapClasses(BeanRepository.class, BeanRepository2.class.getName());

        String helloNewMethodImplVal = (String) ReflectionHelper.invoke(factory.getBean(BeanRepository.class),
                BeanRepository.class, "helloNewMethod", new Class[] {});
        assertEquals("Repository new method", helloNewMethodImplVal);

        // return configuration
        swapClasses(BeanRepository.class, BeanRepository.class.getName());
        assertEquals("Hello from Repository ServiceWithAspect", factory.getBean(BeanServiceImpl.class).hello());
    }

    @Test
    public void hotswapPrototypeTest() throws Exception {
        assertEquals("Hello from Repository ServiceWithAspect Prototype", factory.getBean(BeanPrototype.class).hello());

        // swap service this prototype is dependent to
        swapClasses(BeanServiceImpl.class, BeanServiceImpl2.class.getName());
        assertEquals("Hello from ChangedRepository Service2WithAspect Prototype", factory.getBean(BeanPrototype.class).hello());

        // swap autowired field
        swapClasses(BeanPrototype.class, BeanPrototype2.class.getName());
        assertEquals("Hello from Repository Prototype2", factory.getBean(BeanPrototype.class).hello());

        // return configuration
        swapClasses(BeanServiceImpl.class, BeanServiceImpl.class.getName());
        swapClasses(BeanPrototype.class, BeanPrototype.class.getName());
        assertEquals("Hello from Repository ServiceWithAspect Prototype", factory.getBean(BeanPrototype.class).hello());
    }

    /**
     * Plugin is currently unable to reload prototype bean instance.
     */
    @Test
    public void hotswapPrototypeTestFailWhenHoldingInstance() throws Exception {
        BeanPrototype beanPrototypeInstance = factory.getBean(BeanPrototype.class);
        assertEquals("Hello from Repository ServiceWithAspect Prototype", beanPrototypeInstance.hello());

        // swap service this prototype is dependent to
        try {
            swapClasses(BeanServiceImpl.class, BeanServiceImpl2.class.getName());
            assertEquals("Hello from ChangedRepository Service2WithAspect Prototype", beanPrototypeInstance.hello());
            throw new IllegalStateException("Reload prototype bean should not be correctly initialized.");
        } catch (NullPointerException e) {
            // BeanServiceImpl2 contains reference to different repository. Because existing reference
            // is not changed, this reference is null
        }

        // return configuration
        swapClasses(BeanServiceImpl.class, BeanServiceImpl.class.getName());
        assertEquals("Hello from Repository ServiceWithAspect Prototype", factory.getBean(BeanPrototype.class).hello());
    }

    private void swapClasses(Class original, String swap) throws Exception {
        ClassPathBeanDefinitionScannerAgent.reloadFlag = true;
        HotSwapper.swapClasses(original, swap);
        assertTrue(WaitHelper.waitForCommand(new WaitHelper.Command() {
            @Override
            public boolean result() throws Exception {
                return !ClassPathBeanDefinitionScannerAgent.reloadFlag;
            }
        }));

        // TODO do not know why sleep is needed, maybe a separate thread in Spring refresh?
        Thread.sleep(100);
    }
}
TOP

Related Classes of org.hotswap.agent.plugin.spring.SpringPluginTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.