diff --git a/src/main/java/org/springframework/data/gemfire/LazyWiringDeclarableSupport.java b/src/main/java/org/springframework/data/gemfire/LazyWiringDeclarableSupport.java index 51988441..50a72ed4 100644 --- a/src/main/java/org/springframework/data/gemfire/LazyWiringDeclarableSupport.java +++ b/src/main/java/org/springframework/data/gemfire/LazyWiringDeclarableSupport.java @@ -19,6 +19,7 @@ package org.springframework.data.gemfire; import java.util.Properties; import java.util.concurrent.atomic.AtomicReference; +import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.wiring.BeanConfigurerSupport; import org.springframework.beans.factory.wiring.BeanWiringInfo; @@ -38,6 +39,7 @@ import com.gemstone.gemfire.cache.Declarable; * for wiring GemFire components with Spring bean dependencies defined in the Spring context. *

* @author John Blum + * @see org.springframework.beans.factory.DisposableBean * @see org.springframework.context.ApplicationListener * @see org.springframework.context.event.ContextRefreshedEvent * @see org.springframework.data.gemfire.DeclarableSupport @@ -46,7 +48,8 @@ import com.gemstone.gemfire.cache.Declarable; * @since 1.3.4 */ @SuppressWarnings("unused") -public abstract class LazyWiringDeclarableSupport implements ApplicationListener, Declarable { +public abstract class LazyWiringDeclarableSupport implements ApplicationListener, + Declarable, DisposableBean { // The name of the template bean defined in the Spring context for wiring this Declarable instance. protected static final String BEAN_NAME_PARAMETER = "bean-name"; @@ -201,4 +204,17 @@ public abstract class LazyWiringDeclarableSupport implements ApplicationListener doInit(((ConfigurableApplicationContext) event.getApplicationContext()).getBeanFactory(), parameters); } + /** + * When this bean gets destroyed by the Spring container, make sure this component gets unregistered from the + * SpringContextBootstrappingInitializer. + *

+ * @throws Exception if bean destruction is unsuccessful. + * @see org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer#unregister( + * org.springframework.context.ApplicationListener) + */ + @Override + public void destroy() throws Exception { + SpringContextBootstrappingInitializer.unregister(this); + } + } diff --git a/src/main/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializer.java b/src/main/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializer.java index 6e4cd9dd..1fb8b571 100644 --- a/src/main/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializer.java +++ b/src/main/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializer.java @@ -22,11 +22,13 @@ import java.util.Properties; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.event.ApplicationEventMulticaster; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.SimpleApplicationEventMulticaster; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import com.gemstone.gemfire.cache.Declarable; @@ -41,21 +43,27 @@ import com.gemstone.gemfire.cache.Declarable; * @author John Blum * @see org.springframework.context.ApplicationContext * @see org.springframework.context.ApplicationListener + * @see org.springframework.context.ConfigurableApplicationContext + * @see org.springframework.context.annotation.AnnotationConfigApplicationContext * @see org.springframework.context.event.ApplicationEventMulticaster * @see org.springframework.context.event.ContextRefreshedEvent * @see org.springframework.context.event.SimpleApplicationEventMulticaster - * @see org.springframework.context.ConfigurableApplicationContext * @see org.springframework.context.support.ClassPathXmlApplicationContext * @see com.gemstone.gemfire.cache.Declarable * @since 1.3.4 * @link http://pubs.vmware.com/vfabric53/topic/com.vmware.vfabric.gemfire.7.0/basic_config/the_cache/setting_cache_initializer.html + * @link https://jira.springsource.org/browse/SGF-248 */ @SuppressWarnings("unused") public class SpringContextBootstrappingInitializer implements Declarable, ApplicationListener { + public static final String BASE_PACKAGES_PARAMETER = "basePackages"; public static final String CONTEXT_CONFIG_LOCATIONS_PARAMETER = "contextConfigLocations"; - /* package-private */ static ConfigurableApplicationContext applicationContext; + protected static final String CHARS_TO_DELETE = " \n\t"; + protected static final String COMMA_DELIMITER = ","; + + /* package-private */ static volatile ConfigurableApplicationContext applicationContext; // TODO consider whether I should register a TaskExecutor to perform the event notifications in a separate Thread??? private static ApplicationEventMulticaster eventNotifier = new SimpleApplicationEventMulticaster(); @@ -110,18 +118,61 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic } /** - * Creates (constructs and initializes) a ConfigurableApplicationContext instance based on the specified locations - * of the context configuration meta-data files and indicates whether ApplicationContext.refresh should happen - * automatically during creation. This method allows subclasses to override the type of - * ConfigurableApplicationContext created; by default, a ClassPathXmlApplicationContext is created. + * Creates (constructs and configures) a ConfigurableApplicationContext instance based on the specified locations + * of the context configuration meta-data files. The created ConfigurableApplicationContext is not automatically + * "refreshed" and therefore must be "refreshed" by the caller manually. *

- * @param configLocations a String array indicating the locations of the context configuration meta-data files. - * @param refresh a boolean value indicating whether the ApplicationContext is refreshed on creation. - * @return a newly constructed and initialized instance of a ConfigurableApplicationContext. + * @param configLocations a String array indicating the locations of the context configuration meta-data files + * used to configure the ConfigurableApplicationContext instance. + * @return a newly constructed and configured instance of the ConfigurableApplicationContext class. Note, the + * "refresh" method must be called manually before using the context. + * @throws IllegalArgumentException if the configLocations parameter argument is null or empty. + * @see #createApplicationContext(String[], String[]) * @see org.springframework.context.support.ClassPathXmlApplicationContext */ - protected ConfigurableApplicationContext createApplicationContext(final String[] configLocations, final boolean refresh) { - return new ClassPathXmlApplicationContext(configLocations, refresh); + protected ConfigurableApplicationContext createApplicationContext(final String[] configLocations) { + Assert.notEmpty(configLocations, "The configLocations must be specified to construct an instance" + + " of the ClassPathXmlApplicationContext."); + return createApplicationContext(null, configLocations); + } + + /** + * Creates (constructs and configures) an instance of the ConfigurableApplicationContext based on either the + * specified base packages containing @Configuration, @Component or JSR 330 annotated classes to scan, or the + * specified locations of context configuration meta-data files used to configure the context. The created + * ConfigurableApplicationContext is not automatically "refreshed" and therefore must be "refreshed" + * by the caller manually. + *

+ * When basePackages are specified, an instance of AnnotationConfigApplicationContext is returned; otherwise + * an instance of the ClassPathXmlApplicationContext is initialized with the configLocations and returned. + * This method prefers the ClassPathXmlApplicationContext to the AnnotationConfigApplicationContext when both + * basePackages and configLocations are specified. + *

+ * @param basePackages the base application packages to scan for application @Components and @Configuration classes. * + * @param configLocations a String array indicating the locations of the context configuration meta-data files + * used to configure the ConfigurableApplicationContext instance. + * @return an instance of ConfigurableApplicationContext configured and initialized with either configLocations + * or the basePackages when configLocations is unspecified. Note, the "refresh" method must be called manually + * before using the context. + * @throws IllegalArgumentException if both the basePackages and configLocation parameter arguments + * are null or empty. + * @see #createApplicationContext(String[]) + * @see org.springframework.context.annotation.AnnotationConfigApplicationContext + * @see org.springframework.context.annotation.AnnotationConfigApplicationContext#scan(String...) + * @see org.springframework.context.support.ClassPathXmlApplicationContext + */ + protected ConfigurableApplicationContext createApplicationContext(final String[] basePackages, + final String[] configLocations) { + if (!ObjectUtils.isEmpty(configLocations)) { + return new ClassPathXmlApplicationContext(configLocations, false); + } + else { + Assert.notEmpty(basePackages, "Either 'basePackages' or 'configLocations' must be specified" + + " to construct an instance of the ConfigurableApplicationContext."); + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); + applicationContext.scan(basePackages); + return applicationContext; + } } /** @@ -130,25 +181,29 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic *

* @param parameters a Properties object containing the configuration parameters and settings defined in the * GemFire cache.xml >initializer/< element. - * @see #createApplicationContext(String[], boolean) + * @see #createApplicationContext * @see java.util.Properties */ @Override public void init(final Properties parameters) { + String basePackages = parameters.getProperty(BASE_PACKAGES_PARAMETER); String contextConfigLocations = parameters.getProperty(CONTEXT_CONFIG_LOCATIONS_PARAMETER); - Assert.hasText(contextConfigLocations, "The contextConfigLocations parameter is required."); + Assert.isTrue(StringUtils.hasText(basePackages) || StringUtils.hasText(contextConfigLocations), + "Either 'basePackages' or the 'contextConfigLocations' parameter must be specified."); - String[] configLocations = contextConfigLocations.split(","); + String[] basePackagesArray = StringUtils.delimitedListToStringArray(basePackages, + COMMA_DELIMITER, CHARS_TO_DELETE); - StringUtils.trimArrayElements(configLocations); + String[] configLocations = StringUtils.delimitedListToStringArray(contextConfigLocations, + COMMA_DELIMITER, CHARS_TO_DELETE); synchronized (SpringContextBootstrappingInitializer.class) { Assert.state(applicationContext == null, String.format( "A Spring application context with ID (%1$s) has already been created.", nullSafeGetApplicationContextId(applicationContext))); - applicationContext = createApplicationContext(configLocations, false); + applicationContext = createApplicationContext(basePackagesArray, configLocations); applicationContext.addApplicationListener(this); applicationContext.registerShutdownHook(); applicationContext.refresh(); diff --git a/src/test/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializerIntegrationTest.java b/src/test/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializerIntegrationTest.java index ab926a3d..a76cf30e 100644 --- a/src/test/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializerIntegrationTest.java +++ b/src/test/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializerIntegrationTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.Calendar; import java.util.HashMap; @@ -29,18 +30,21 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import javax.sql.DataSource; +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.data.gemfire.LazyWiringDeclarableSupport; import org.springframework.data.gemfire.config.GemfireConstants; import org.springframework.data.gemfire.repository.sample.User; +import org.springframework.data.gemfire.support.sample.TestUserDao; +import org.springframework.data.gemfire.support.sample.TestUserService; import org.springframework.data.gemfire.test.support.DataSourceAdapter; -import org.springframework.stereotype.Repository; -import org.springframework.stereotype.Service; import org.springframework.util.Assert; import com.gemstone.gemfire.cache.Cache; +import com.gemstone.gemfire.cache.CacheClosedException; import com.gemstone.gemfire.cache.CacheFactory; import com.gemstone.gemfire.cache.CacheLoader; import com.gemstone.gemfire.cache.CacheLoaderException; @@ -53,28 +57,101 @@ import com.gemstone.gemfire.cache.Region; *

* @author John Blum * @see org.junit.Test + * @see org.springframework.context.ConfigurableApplicationContext + * @see org.springframework.data.gemfire.LazyWiringDeclarableSupport * @see org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer + * @see com.gemstone.gemfire.cache.Cache + * @see com.gemstone.gemfire.cache.CacheFactory + * @see com.gemstone.gemfire.cache.CacheLoader + * @see com.gemstone.gemfire.cache.Region * @since 1.3.4 (Spring Data GemFire) * @since 7.0.1 (GemFire) */ @SuppressWarnings("unused") public class SpringContextBootstrappingInitializerIntegrationTest { + private static final long CACHE_CLOSE_TIMEOUT = 15000l; // 15 seconds + + private static final Object MUTEX_LOCK = new Object(); + protected static final String GEMFIRE_LOCATORS = "localhost[11235]"; protected static final String GEMFIRE_LOG_LEVEL = "config"; protected static final String GEMFIRE_MCAST_PORT = "0"; protected static final String GEMFIRE_NAME = "SpringContextBootstrappingInitializationTest"; protected static final String GEMFIRE_START_LOCATORS = "localhost[11235]"; - @Test - public void testSpringContextBootstrappingInitialization() { + @Before + public void setup() { + setupBeforeCacheCreate(); + } + + private void setupBeforeCacheCreate() { + try { + long timeout = (System.currentTimeMillis() + CACHE_CLOSE_TIMEOUT); + + while (CacheFactory.getAnyInstance() != null && System.currentTimeMillis() < timeout) { + synchronized (MUTEX_LOCK) { + try { + System.out.printf("Waiting in setup...%n"); + MUTEX_LOCK.wait(500l); + } + catch (InterruptedException ignore) { + } + } + } + + fail(String.format("The Cache instance was not properly closed and shutdown by the timeout of %1$d seconds!%n", + (CACHE_CLOSE_TIMEOUT / 1000))); + } + catch (CacheClosedException ignore) { + } + } + + @After + public void tearDown() { + SpringContextBootstrappingInitializer.applicationContext = null; + UserDataStoreCacheLoader.INSTANCE.set(null); + tearDownCache(); + } + + private void tearDownCache() { + try { + Cache cache = CacheFactory.getAnyInstance(); + + if (cache != null) { + System.out.printf("Closing Cache...%n"); + cache.close(); + + // Now, wait for the GemFire Hog to shutdown, OIY! + synchronized (MUTEX_LOCK) { + while (!cache.isClosed()) { + try { + System.out.printf("Waiting in tearDown..."); + MUTEX_LOCK.wait(500l); + } + catch (InterruptedException ignore) { + } + } + + MUTEX_LOCK.notifyAll(); + } + } + } + catch (CacheClosedException ignore) { + // CacheClosedExceptions happen when the Cache reference returned by GemFireCacheImpl.getInstance() + // inside the CacheFactory.getAnyInstance() is null, or the Cache is already closed with calling + // Cache.close(); + } + } + + protected void doSpringContextBootstrappingInitializationTest(final String cacheXmlFile) { Cache gemfireCache = new CacheFactory() - .set("cache-xml-file", "cache-with-spring-context-bootstrap-initializer.xml") - .set("locators", GEMFIRE_LOCATORS) + .set("cache-xml-file", cacheXmlFile) + //.set("locators", GEMFIRE_LOCATORS) .set("log-level", GEMFIRE_LOG_LEVEL) .set("mcast-port", GEMFIRE_MCAST_PORT) .set("name", GEMFIRE_NAME) - .set("start-locator", GEMFIRE_LOCATORS) + //.set("start-locator", GEMFIRE_LOCATORS) .create(); assertNotNull("The GemFire Cache was not properly created or initialized!", gemfireCache); @@ -124,39 +201,20 @@ public class SpringContextBootstrappingInitializerIntegrationTest { assertEquals(3, users.size()); } + @Test + public void testSpringContextBootstrappingInitialization() { + doSpringContextBootstrappingInitializationTest("cache-with-spring-context-bootstrap-initializer.xml"); + } + + @Test + public void testSpringContextBootstrappingInitializationUsingBasePackages() { + doSpringContextBootstrappingInitializationTest( + "cache-with-spring-context-bootstrap-initializer-using-base-packages.xml"); + } + public static final class TestDataSource extends DataSourceAdapter { } - @Repository - public static interface UserDao { - } - - public static final class TestUserDao implements UserDao { - - @Autowired - private DataSource userDataSource; - - protected DataSource getDataSource() { - Assert.state(userDataSource != null, "A reference to the Users DataSource as not properly configured!"); - return userDataSource; - } - } - - @Service - public static interface UserService { - } - - public static final class TestUserService implements UserService { - - @Autowired - private UserDao userDao; - - protected UserDao getUserDao() { - Assert.state(userDao != null, "A reference to the UserDao was not properly configured!"); - return userDao; - } - } - public static final class UserDataStoreCacheLoader extends LazyWiringDeclarableSupport implements CacheLoader { private static final AtomicReference INSTANCE = new AtomicReference(); @@ -207,7 +265,6 @@ public class SpringContextBootstrappingInitializerIntegrationTest { @Override public void close() { - USER_DATA.clear(); userDataSource = null; } diff --git a/src/test/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializerTest.java b/src/test/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializerTest.java index 3fec4ba1..5e236b7b 100644 --- a/src/test/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializerTest.java +++ b/src/test/java/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializerTest.java @@ -64,6 +64,30 @@ public class SpringContextBootstrappingInitializerTest { SpringContextBootstrappingInitializer.applicationContext = null; } + @Test(expected = IllegalArgumentException.class) + public void testCreateApplicationContextWhenBasePackagesAndConfigLocationsAreBothUnspecified() { + try { + new SpringContextBootstrappingInitializer().createApplicationContext(null, null); + } + catch (IllegalArgumentException expected) { + assertEquals("Either 'basePackages' or 'configLocations' must be specified to construct an instance of the ConfigurableApplicationContext.", + expected.getMessage()); + throw expected; + } + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateClassPathXmlApplicationContextWhenConfigLocationsAreUnspecified() { + try { + new SpringContextBootstrappingInitializer().createApplicationContext(null); + } + catch (IllegalArgumentException expected) { + assertEquals("The configLocations must be specified to construct an instance of the ClassPathXmlApplicationContext.", + expected.getMessage()); + throw expected; + } + } + @Test(expected = IllegalArgumentException.class) public void testInitWithUnspecifiedContextConfigLocationsParameter() { try { @@ -71,7 +95,8 @@ public class SpringContextBootstrappingInitializerTest { SpringContextBootstrappingInitializer.CONTEXT_CONFIG_LOCATIONS_PARAMETER, "")); } catch (IllegalArgumentException expected) { - assertEquals("The contextConfigLocations parameter is required.", expected.getMessage()); + assertEquals("Either 'basePackages' or the 'contextConfigLocations' parameter must be specified.", + expected.getMessage()); throw expected; } } @@ -98,11 +123,11 @@ public class SpringContextBootstrappingInitializerTest { } @Test(expected = IllegalStateException.class) - public void testInitWithNonActiveApplicationConstruct() { + public void testInitWithNonActiveApplicationContext() { final ConfigurableApplicationContext mockApplicationContext = mock(ConfigurableApplicationContext.class, "testInitWithNonActiveApplicationConstruct"); - when(mockApplicationContext.getId()).thenReturn("testInitWithNonActiveApplicationConstruct"); + when(mockApplicationContext.getId()).thenReturn("testInitWithNonActiveApplicationContext"); when(mockApplicationContext.isActive()).thenReturn(false); SpringContextBootstrappingInitializer initializer = null; @@ -110,7 +135,8 @@ public class SpringContextBootstrappingInitializerTest { try { initializer = new SpringContextBootstrappingInitializer() { @Override - protected ConfigurableApplicationContext createApplicationContext(final String[] configLocations, final boolean refresh) { + protected ConfigurableApplicationContext createApplicationContext(final String[] basePackages, + final String[] configLocations) { return mockApplicationContext; } }; @@ -119,7 +145,7 @@ public class SpringContextBootstrappingInitializerTest { "/path/to/spring/context/configuration/file.xml")); } catch (IllegalStateException expected) { - assertEquals("The Spring application context (testInitWithNonActiveApplicationConstruct) has failed to be properly initialized with the following config files ([/path/to/spring/context/configuration/file.xml])!", + assertEquals("The Spring application context (testInitWithNonActiveApplicationContext) has failed to be properly initialized with the following config files ([/path/to/spring/context/configuration/file.xml])!", expected.getMessage()); throw expected; } @@ -140,7 +166,8 @@ public class SpringContextBootstrappingInitializerTest { SpringContextBootstrappingInitializer initializer = new SpringContextBootstrappingInitializer() { @Override - protected ConfigurableApplicationContext createApplicationContext(final String[] configLocations, final boolean refresh) { + protected ConfigurableApplicationContext createApplicationContext(final String[] basePackages, + final String[] configLocations) { return mockApplicationContext; } }; diff --git a/src/test/java/org/springframework/data/gemfire/support/sample/TestUserDao.java b/src/test/java/org/springframework/data/gemfire/support/sample/TestUserDao.java new file mode 100644 index 00000000..febdfc51 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/support/sample/TestUserDao.java @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2013 the original author or authors. + * + * 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 org.springframework.data.gemfire.support.sample; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; +import org.springframework.util.Assert; + +/** + * The TestUserDao class is an implementation of the UserDao Data Access Object (DAO) interface for performing + * data access and persistence operations on Users. + *

+ * @author John Blum + * @see org.springframework.data.gemfire.repository.sample.User + * @see org.springframework.data.gemfire.support.sample.UserDao + * @see org.springframework.stereotype.Repository + * @since 1.3.4 + */ +@Repository("userDao") +@SuppressWarnings("unused") +public class TestUserDao implements UserDao { + + @Autowired + private DataSource userDataSource; + + public DataSource getDataSource() { + Assert.state(userDataSource != null, "A reference to the Users DataSource was not properly configured!"); + return userDataSource; + } +} diff --git a/src/test/java/org/springframework/data/gemfire/support/sample/TestUserService.java b/src/test/java/org/springframework/data/gemfire/support/sample/TestUserService.java new file mode 100644 index 00000000..899e39f1 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/support/sample/TestUserService.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2013 the original author or authors. + * + * 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 org.springframework.data.gemfire.support.sample; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +/** + * The TestUserService class is an implementation of the UserService service interface for performing service operations + * on Users. + *

+ * @author John Blum + * @see org.springframework.data.gemfire.repository.sample.User + * @see org.springframework.data.gemfire.support.sample.UserService + * @see org.springframework.stereotype.Service + * @since 1.3.4 + */ +@Service("userService") +@SuppressWarnings("unused") +public class TestUserService implements UserService { + + @Autowired + private UserDao userDao; + + public UserDao getUserDao() { + Assert.state(userDao != null, "A reference to the UserDao was not properly configured!"); + return userDao; + } +} diff --git a/src/test/java/org/springframework/data/gemfire/support/sample/UserApplicationConfiguration.java b/src/test/java/org/springframework/data/gemfire/support/sample/UserApplicationConfiguration.java new file mode 100644 index 00000000..ccb7945f --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/support/sample/UserApplicationConfiguration.java @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2013 the original author or authors. + * + * 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 org.springframework.data.gemfire.support.sample; + +import javax.sql.DataSource; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.data.gemfire.support.SpringContextBootstrappingInitializerIntegrationTest; + +/** + * The UserApplicationConfiguration class is a configuration component for confguring the user's application. + *

+ * @author John Blum + * @see org.springframework.context.annotation.Bean + * @see org.springframework.context.annotation.Configuration + * @see org.springframework.context.annotation.ImportResource + * @since 1.3.4 + */ +@Configuration +@ImportResource({ "classpath:org/springframework/data/gemfire/support/sample/initializer-gemfire-context.xml" }) +@SuppressWarnings("unused") +public class UserApplicationConfiguration { + + @Bean + public DataSource userDataSource() { + return new SpringContextBootstrappingInitializerIntegrationTest.TestDataSource(); + } + +} diff --git a/src/test/java/org/springframework/data/gemfire/support/sample/UserDao.java b/src/test/java/org/springframework/data/gemfire/support/sample/UserDao.java new file mode 100644 index 00000000..8664b58f --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/support/sample/UserDao.java @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2013 the original author or authors. + * + * 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 org.springframework.data.gemfire.support.sample; + +/** + * The UserDao interface is a contract for implementing objects containing data access functionality for Users. + *

+ * @author John Blum + * @see org.springframework.data.gemfire.repository.sample.User + * @since 1.3.4 + */ +public interface UserDao { +} diff --git a/src/test/java/org/springframework/data/gemfire/support/sample/UserService.java b/src/test/java/org/springframework/data/gemfire/support/sample/UserService.java new file mode 100644 index 00000000..0a08dcbf --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/support/sample/UserService.java @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2013 the original author or authors. + * + * 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 org.springframework.data.gemfire.support.sample; + +/** + * The UserService interface is a contract for implementing objects to service Users. + *

+ * @author John Blum + * @see org.springframework.data.gemfire.repository.sample.User + * @since 1.3.4 + */ +public interface UserService { +} diff --git a/src/test/resources/cache-with-spring-context-bootstrap-initializer-using-base-packages.xml b/src/test/resources/cache-with-spring-context-bootstrap-initializer-using-base-packages.xml new file mode 100644 index 00000000..cdfc177e --- /dev/null +++ b/src/test/resources/cache-with-spring-context-bootstrap-initializer-using-base-packages.xml @@ -0,0 +1,22 @@ + + + + + + java.lang.String + org.springframework.data.gemfire.repository.sample.User + + org.springframework.data.gemfire.support.SpringContextBootstrappingInitializerIntegrationTest$UserDataStoreCacheLoader + + + + + org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer + + + org.springframework.data.gemfire.support.sample + + + + diff --git a/src/test/resources/cache-with-spring-context-bootstrap-initializer.xml b/src/test/resources/cache-with-spring-context-bootstrap-initializer.xml index d73a5305..ad5baec0 100644 --- a/src/test/resources/cache-with-spring-context-bootstrap-initializer.xml +++ b/src/test/resources/cache-with-spring-context-bootstrap-initializer.xml @@ -15,9 +15,9 @@ org.springframework.data.gemfire.support.SpringContextBootstrappingInitializer - classpath:org/springframework/data/gemfire/support/initializer-gemfire-context.xml, - classpath:org/springframework/data/gemfire/support/initializer-dao-context.xml, - classpath:org/springframework/data/gemfire/support/initializer-services-context.xml + classpath:org/springframework/data/gemfire/support/sample/initializer-gemfire-context.xml, + classpath:org/springframework/data/gemfire/support/sample/initializer-dao-context.xml, + classpath:org/springframework/data/gemfire/support/sample/initializer-services-context.xml diff --git a/src/test/resources/org/springframework/data/gemfire/support/initializer-dao-context.xml b/src/test/resources/org/springframework/data/gemfire/support/sample/initializer-dao-context.xml similarity index 91% rename from src/test/resources/org/springframework/data/gemfire/support/initializer-dao-context.xml rename to src/test/resources/org/springframework/data/gemfire/support/sample/initializer-dao-context.xml index 66396e57..4bad00d3 100644 --- a/src/test/resources/org/springframework/data/gemfire/support/initializer-dao-context.xml +++ b/src/test/resources/org/springframework/data/gemfire/support/sample/initializer-dao-context.xml @@ -10,6 +10,6 @@ - + diff --git a/src/test/resources/org/springframework/data/gemfire/support/initializer-gemfire-context.xml b/src/test/resources/org/springframework/data/gemfire/support/sample/initializer-gemfire-context.xml similarity index 81% rename from src/test/resources/org/springframework/data/gemfire/support/initializer-gemfire-context.xml rename to src/test/resources/org/springframework/data/gemfire/support/sample/initializer-gemfire-context.xml index 1e652bdc..52c5e8d3 100644 --- a/src/test/resources/org/springframework/data/gemfire/support/initializer-gemfire-context.xml +++ b/src/test/resources/org/springframework/data/gemfire/support/sample/initializer-gemfire-context.xml @@ -1,4 +1,5 @@ + - + diff --git a/src/test/resources/org/springframework/data/gemfire/support/initializer-services-context.xml b/src/test/resources/org/springframework/data/gemfire/support/sample/initializer-services-context.xml similarity index 87% rename from src/test/resources/org/springframework/data/gemfire/support/initializer-services-context.xml rename to src/test/resources/org/springframework/data/gemfire/support/sample/initializer-services-context.xml index 7a4c8caf..2c0c64ec 100644 --- a/src/test/resources/org/springframework/data/gemfire/support/initializer-services-context.xml +++ b/src/test/resources/org/springframework/data/gemfire/support/sample/initializer-services-context.xml @@ -9,6 +9,6 @@ - +