From 0c813862e130d24ec89c3e178fd909bd470c6a6e Mon Sep 17 00:00:00 2001 From: John Blum Date: Mon, 10 Aug 2015 19:13:12 -0700 Subject: [PATCH] SGF-425 - Allow early initialization and re-initialization of LazyWiringDeclarableSupport instances. Fixed test failures associated with changes to LazyWiringDeclarableSupport passing the ApplicationContext onApplicationEvents (ContextRefreshedEvent) directly rather than the ApplicationContext's ConfigurableListableBeanFactory required by BeanConfigurerSupport. (cherry picked from commit be6a3aac3e5281fdb2c77ad8b88200c92c0b7883) Signed-off-by: John Blum --- .../gemfire/LazyWiringDeclarableSupport.java | 16 +++++-- .../GemfireBeanFactoryLocatorTest.java | 34 ++++++++++----- .../LazyWiringDeclarableSupportTest.java | 42 +++++++++++++++---- ...stenceExceptionTranslationTest-context.xml | 2 +- 4 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/springframework/data/gemfire/LazyWiringDeclarableSupport.java b/src/main/java/org/springframework/data/gemfire/LazyWiringDeclarableSupport.java index 7f3f0c50..9040c296 100644 --- a/src/main/java/org/springframework/data/gemfire/LazyWiringDeclarableSupport.java +++ b/src/main/java/org/springframework/data/gemfire/LazyWiringDeclarableSupport.java @@ -25,9 +25,11 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport; import org.springframework.beans.factory.wiring.BeanWiringInfo; import org.springframework.beans.factory.wiring.BeanWiringInfoResolver; import org.springframework.context.ApplicationListener; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import com.gemstone.gemfire.cache.Declarable; @@ -41,7 +43,9 @@ import com.gemstone.gemfire.cache.Declarable; * @see org.springframework.beans.factory.DisposableBean * @see org.springframework.beans.factory.wiring.BeanConfigurerSupport * @see org.springframework.beans.factory.wiring.BeanWiringInfo + * @see org.springframework.beans.factory.wiring.BeanWiringInfoResolver * @see org.springframework.context.ApplicationListener + * @see org.springframework.context.ConfigurableApplicationContext * @see org.springframework.context.event.ContextRefreshedEvent * @see org.springframework.data.gemfire.DeclarableSupport * @see org.springframework.data.gemfire.WiringDeclarableSupport @@ -50,8 +54,8 @@ import com.gemstone.gemfire.cache.Declarable; * @since 1.3.4 */ @SuppressWarnings("unused") -public abstract class LazyWiringDeclarableSupport implements ApplicationListener, - Declarable, DisposableBean { +public abstract class LazyWiringDeclarableSupport implements ApplicationListener, Declarable, + DisposableBean { // name of the template bean defined in the Spring context for wiring this Declarable instance. protected static final String BEAN_NAME_PARAMETER = "bean-name"; @@ -287,8 +291,12 @@ public abstract class LazyWiringDeclarableSupport implements ApplicationListener */ @Override public final void onApplicationEvent(final ContextRefreshedEvent event) { - Assert.notNull(event.getApplicationContext(), "The Spring ApplicationContext must not be null"); - doInit(event.getApplicationContext(), nullSafeGetParameters()); + Assert.isTrue(event.getApplicationContext() instanceof ConfigurableApplicationContext, String.format( + "The Spring ApplicationContext (%1$s) must be an instance of ConfigurableApplicationContext", + ObjectUtils.nullSafeClassName(event.getApplicationContext()))); + + doInit(((ConfigurableApplicationContext) event.getApplicationContext()).getBeanFactory(), + nullSafeGetParameters()); } /** diff --git a/src/test/java/org/springframework/data/gemfire/GemfireBeanFactoryLocatorTest.java b/src/test/java/org/springframework/data/gemfire/GemfireBeanFactoryLocatorTest.java index 16182836..c1f198a5 100644 --- a/src/test/java/org/springframework/data/gemfire/GemfireBeanFactoryLocatorTest.java +++ b/src/test/java/org/springframework/data/gemfire/GemfireBeanFactoryLocatorTest.java @@ -16,33 +16,43 @@ package org.springframework.data.gemfire; -import static org.junit.Assert.assertNotNull; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.access.BeanFactoryReference; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; -import org.springframework.data.gemfire.GemfireBeanFactoryLocator; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Costin Leau + * @author John Blum */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "locatorContext.xml" }) +@SuppressWarnings("unused") public class GemfireBeanFactoryLocatorTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Autowired private ApplicationContext applicationContext; private GemfireBeanFactoryLocator locator1, locator2; + private String INSTANCE_1 = "instance1"; private String INSTANCE_2 = "instance2"; @@ -122,16 +132,18 @@ public class GemfireBeanFactoryLocatorTest { } @Test - public void testFactoryLocatorContract() throws Exception { + public void factoryLocatorContract() throws Exception { BeanFactoryReference factory1 = locator1.useBeanFactory(INSTANCE_1); - assertNotNull(factory1.getFactory()); + + assertThat(factory1.getFactory(), is(notNullValue())); factory1.release(); - try { - factory1.getFactory(); - fail("should have received exception"); - } catch (IllegalArgumentException e) { - // it's okay - } + + expectedException.expect(IllegalStateException.class); + expectedException.expectCause(is(nullValue(Throwable.class))); + expectedException.expectMessage("The BeanFactory has already been released or closed"); + + factory1.getFactory(); } -} \ No newline at end of file + +} diff --git a/src/test/java/org/springframework/data/gemfire/LazyWiringDeclarableSupportTest.java b/src/test/java/org/springframework/data/gemfire/LazyWiringDeclarableSupportTest.java index 16bfb72e..201d4c81 100644 --- a/src/test/java/org/springframework/data/gemfire/LazyWiringDeclarableSupportTest.java +++ b/src/test/java/org/springframework/data/gemfire/LazyWiringDeclarableSupportTest.java @@ -24,6 +24,8 @@ import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.sameInstance; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.Properties; @@ -34,7 +36,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.springframework.beans.factory.BeanFactory; -import org.springframework.context.ApplicationContext; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer; @@ -224,7 +227,13 @@ public class LazyWiringDeclarableSupportTest { @Test public void onApplicationEvent() { - ApplicationContext mockApplicationContext = mock(ApplicationContext.class, "MockApplicationContext"); + ConfigurableApplicationContext mockApplicationContext = mock(ConfigurableApplicationContext.class, + "MockConfigurableApplicationContext"); + + ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class, + "MockConfigurableListableBeanFactory"); + + when(mockApplicationContext.getBeanFactory()).thenReturn(mockBeanFactory); final AtomicBoolean doPostInitCalled = new AtomicBoolean(false); @@ -242,11 +251,13 @@ public class LazyWiringDeclarableSupportTest { try { declarable.init(parameters); declarable.onApplicationEvent(new ContextRefreshedEvent(mockApplicationContext)); - declarable.assertBeanFactory(mockApplicationContext); + declarable.assertBeanFactory(mockBeanFactory); declarable.assertParameters(parameters); assertThat(declarable.isInitialized(), is(true)); assertThat(doPostInitCalled.get(), is(true)); + + verify(mockApplicationContext, times(1)).getBeanFactory(); } finally { SpringContextBootstrappingInitializer.unregister(declarable); @@ -264,7 +275,7 @@ public class LazyWiringDeclarableSupportTest { expectedException.expect(IllegalArgumentException.class); expectedException.expectCause(is(nullValue(Throwable.class))); - expectedException.expectMessage("The Spring ApplicationContext must not be null"); + expectedException.expectMessage("The Spring ApplicationContext (null) must be an instance of ConfigurableApplicationContext"); declarable.onApplicationEvent(mockContextRefreshedEvent); } @@ -279,7 +290,13 @@ public class LazyWiringDeclarableSupportTest { @Test public void fullLifecycleOnApplicationEventToDestroy() throws Exception { - ApplicationContext mockApplicationContext = mock(ApplicationContext.class, "MockApplicationContext"); + ConfigurableApplicationContext mockApplicationContext = mock(ConfigurableApplicationContext.class, + "MockConfigurableApplicationContext"); + + ConfigurableListableBeanFactory mockBeanFactory = mock(ConfigurableListableBeanFactory.class, + "MockConfigurableListableBeanFactory"); + + when(mockApplicationContext.getBeanFactory()).thenReturn(mockBeanFactory); final AtomicBoolean doPostInitCalled = new AtomicBoolean(false); @@ -307,7 +324,7 @@ public class LazyWiringDeclarableSupportTest { assertThat(declarable.isInitialized(), is(true)); assertThat(doPostInitCalled.get(), is(true)); - declarable.assertBeanFactory(mockApplicationContext); + declarable.assertBeanFactory(mockBeanFactory); declarable.assertParameters(parameters); doPostInitCalled.set(false); @@ -322,6 +339,8 @@ public class LazyWiringDeclarableSupportTest { assertThat(declarable.isInitialized(), is(false)); assertThat(declarable.nullSafeGetParameters(), is(not(sameInstance(parameters)))); assertThat(doPostInitCalled.get(), is(false)); + + verify(mockApplicationContext, times(1)).getBeanFactory(); } finally { initializer.onApplicationEvent(new ContextClosedEvent(mockApplicationContext)); @@ -330,10 +349,15 @@ public class LazyWiringDeclarableSupportTest { @Test public void initThenOnApplicationEventThenInitWhenInitialized() { - ApplicationContext mockApplicationContext = mock(ApplicationContext.class, "MockApplicationContext"); - BeanFactory mockBeanFactory = mock(BeanFactory.class, "MockBeanFactory"); + ConfigurableApplicationContext mockApplicationContext = mock(ConfigurableApplicationContext.class, "MockApplicationContext"); + + ConfigurableListableBeanFactory mockConfigurableListableBeanFactory = mock(ConfigurableListableBeanFactory.class, + "MockConfigurableListableBeanFactory"); + + when(mockApplicationContext.getBeanFactory()).thenReturn(mockConfigurableListableBeanFactory); + GemfireBeanFactoryLocator locator = new GemfireBeanFactoryLocator(); locator.setBeanName("MockBeanFactory"); locator.setBeanFactory(mockBeanFactory); @@ -389,6 +413,8 @@ public class LazyWiringDeclarableSupportTest { assertThat(declarable.isInitialized(), is(true)); assertThat(declarable.nullSafeGetParameters(), is(sameInstance(parameters))); assertThat(doPostInitCalled.get(), is(true)); + + verify(mockApplicationContext, times(1)).getBeanFactory(); } finally { locator.destroy(); diff --git a/src/test/resources/org/springframework/data/gemfire/support/GemfirePersistenceExceptionTranslationTest-context.xml b/src/test/resources/org/springframework/data/gemfire/support/GemfirePersistenceExceptionTranslationTest-context.xml index dfc9f745..55bed3cd 100644 --- a/src/test/resources/org/springframework/data/gemfire/support/GemfirePersistenceExceptionTranslationTest-context.xml +++ b/src/test/resources/org/springframework/data/gemfire/support/GemfirePersistenceExceptionTranslationTest-context.xml @@ -14,7 +14,7 @@ GemfirePersistenceExceptionTranslation 0 - config + warning