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 @@
-
+