SGF-382 - Add logging to the SpringContextBootstrappingInitializer init method to capture any Spring context/GemFire errors on startup.
This commit is contained in:
@@ -19,7 +19,10 @@ package org.springframework.data.gemfire.support;
|
||||
import java.util.Arrays;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@@ -68,6 +71,8 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
|
||||
/* package-private */ static volatile ContextRefreshedEvent contextRefreshedEvent;
|
||||
|
||||
protected final Log logger = initLogger();
|
||||
|
||||
/**
|
||||
* Gets a reference to the Spring ApplicationContext constructed, configured and initialized inside the GemFire
|
||||
* Server-based JVM process.
|
||||
@@ -147,6 +152,17 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
return listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization method for the logger used to log important messages from this initializer.
|
||||
*
|
||||
* @return a Apache Commons Log used to log messages from this initializer
|
||||
* @see org.apache.commons.logging.LogFactory#getLog(Class)
|
||||
* @see org.apache.commons.logging.Log
|
||||
*/
|
||||
protected Log initLogger() {
|
||||
return LogFactory.getLog(getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -257,6 +273,8 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
* @param parameters a Properties object containing the configuration parameters and settings defined in the
|
||||
* GemFire cache.xml <initializer> block for the declared SpringContextBootstrappingInitializer
|
||||
* GemFire Declarable object.
|
||||
* @throws org.springframework.context.ApplicationContextException if the Spring ApplicationContext could not be
|
||||
* successfully created, configured and initialized.
|
||||
* @see #createApplicationContext(String[], String[])
|
||||
* @see #initApplicationContext(org.springframework.context.ConfigurableApplicationContext)
|
||||
* @see #refreshApplicationContext(org.springframework.context.ConfigurableApplicationContext)
|
||||
@@ -264,31 +282,38 @@ public class SpringContextBootstrappingInitializer implements Declarable, Applic
|
||||
*/
|
||||
@Override
|
||||
public void init(final Properties parameters) {
|
||||
synchronized (SpringContextBootstrappingInitializer.class) {
|
||||
if (applicationContext == null || !applicationContext.isActive()) {
|
||||
String basePackages = parameters.getProperty(BASE_PACKAGES_PARAMETER);
|
||||
String contextConfigLocations = parameters.getProperty(CONTEXT_CONFIG_LOCATIONS_PARAMETER);
|
||||
try {
|
||||
synchronized (SpringContextBootstrappingInitializer.class) {
|
||||
if (applicationContext == null || !applicationContext.isActive()) {
|
||||
String basePackages = parameters.getProperty(BASE_PACKAGES_PARAMETER);
|
||||
String contextConfigLocations = parameters.getProperty(CONTEXT_CONFIG_LOCATIONS_PARAMETER);
|
||||
|
||||
Assert.isTrue(StringUtils.hasText(basePackages) || StringUtils.hasText(contextConfigLocations),
|
||||
"Either 'basePackages' or the 'contextConfigLocations' parameter must be specified.");
|
||||
Assert.isTrue(StringUtils.hasText(basePackages) || StringUtils.hasText(contextConfigLocations),
|
||||
"Either 'basePackages' or the 'contextConfigLocations' parameter must be specified.");
|
||||
|
||||
String[] basePackagesArray = StringUtils.delimitedListToStringArray(basePackages,
|
||||
COMMA_DELIMITER, CHARS_TO_DELETE);
|
||||
String[] basePackagesArray = StringUtils.delimitedListToStringArray(basePackages,
|
||||
COMMA_DELIMITER, CHARS_TO_DELETE);
|
||||
|
||||
String[] contextConfigLocationsArray = StringUtils.delimitedListToStringArray(contextConfigLocations,
|
||||
COMMA_DELIMITER, CHARS_TO_DELETE);
|
||||
String[] contextConfigLocationsArray = StringUtils.delimitedListToStringArray(contextConfigLocations,
|
||||
COMMA_DELIMITER, CHARS_TO_DELETE);
|
||||
|
||||
ConfigurableApplicationContext localApplicationContext = refreshApplicationContext(
|
||||
initApplicationContext(createApplicationContext( basePackagesArray, contextConfigLocationsArray)));
|
||||
ConfigurableApplicationContext localApplicationContext = refreshApplicationContext(
|
||||
initApplicationContext(createApplicationContext(basePackagesArray, contextConfigLocationsArray)));
|
||||
|
||||
Assert.state(localApplicationContext.isRunning(), String.format(
|
||||
"The Spring ApplicationContext (%1$s) failed to be properly initialized with the context config files (%2$s) or base packages (%3$s)!",
|
||||
nullSafeGetApplicationContextId(applicationContext), Arrays.toString(contextConfigLocationsArray),
|
||||
Arrays.toString(basePackagesArray)));
|
||||
Assert.state(localApplicationContext.isRunning(), String.format(
|
||||
"The Spring ApplicationContext (%1$s) failed to be properly initialized with the context config files (%2$s) or base packages (%3$s)!",
|
||||
nullSafeGetApplicationContextId(localApplicationContext), Arrays.toString(contextConfigLocationsArray),
|
||||
Arrays.toString(basePackagesArray)));
|
||||
|
||||
applicationContext = localApplicationContext;
|
||||
applicationContext = localApplicationContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable cause) {
|
||||
String message = "Failed to bootstrap the Spring ApplicationContext!";
|
||||
logger.error(message, cause);
|
||||
throw new ApplicationContextException(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,9 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.same;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -29,10 +32,12 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
@@ -274,46 +279,88 @@ public class SpringContextBootstrappingInitializerTest {
|
||||
|
||||
try {
|
||||
new SpringContextBootstrappingInitializer().init(createParameters(createParameters(
|
||||
SpringContextBootstrappingInitializer.CONTEXT_CONFIG_LOCATIONS_PARAMETER, ""),
|
||||
SpringContextBootstrappingInitializer.BASE_PACKAGES_PARAMETER, ""));
|
||||
SpringContextBootstrappingInitializer.CONTEXT_CONFIG_LOCATIONS_PARAMETER, ""),
|
||||
SpringContextBootstrappingInitializer.BASE_PACKAGES_PARAMETER, ""));
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
catch (ApplicationContextException expected) {
|
||||
assertTrue(expected.getMessage().contains("Failed to bootstrap the Spring ApplicationContext!"));
|
||||
assertTrue(expected.getCause() instanceof IllegalArgumentException);
|
||||
assertEquals("Either 'basePackages' or the 'contextConfigLocations' parameter must be specified.",
|
||||
expected.getMessage());
|
||||
throw expected;
|
||||
expected.getCause().getMessage());
|
||||
throw (IllegalArgumentException) expected.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testInitWhenApplicationContextIsNotRunning() {
|
||||
assertNull(SpringContextBootstrappingInitializer.applicationContext);
|
||||
try {
|
||||
assertNull(SpringContextBootstrappingInitializer.applicationContext);
|
||||
|
||||
final ConfigurableApplicationContext mockApplicationContext = mock(ConfigurableApplicationContext.class,
|
||||
"testInitWhenApplicationContextIsNotRunning");
|
||||
final ConfigurableApplicationContext mockApplicationContext = mock(ConfigurableApplicationContext.class,
|
||||
"testInitWhenApplicationContextIsNotRunning");
|
||||
|
||||
when(mockApplicationContext.getId()).thenReturn("testInitWhenApplicationContextIsNotRunning");
|
||||
when(mockApplicationContext.isRunning()).thenReturn(false);
|
||||
when(mockApplicationContext.getId()).thenReturn("testInitWhenApplicationContextIsNotRunning");
|
||||
when(mockApplicationContext.isRunning()).thenReturn(false);
|
||||
|
||||
SpringContextBootstrappingInitializer initializer = new SpringContextBootstrappingInitializer() {
|
||||
@Override
|
||||
protected ConfigurableApplicationContext createApplicationContext(final String[] basePackages,
|
||||
final String[] configLocations) {
|
||||
return mockApplicationContext;
|
||||
}
|
||||
};
|
||||
|
||||
initializer.init(createParameters(SpringContextBootstrappingInitializer.CONTEXT_CONFIG_LOCATIONS_PARAMETER,
|
||||
"/path/to/spring/application/context.xml"));
|
||||
|
||||
verify(mockApplicationContext, times(1)).addApplicationListener(same(initializer));
|
||||
verify(mockApplicationContext, times(1)).registerShutdownHook();
|
||||
verify(mockApplicationContext, times(1)).refresh();
|
||||
|
||||
SpringContextBootstrappingInitializer.getApplicationContext();
|
||||
}
|
||||
catch (ApplicationContextException expected) {
|
||||
assertTrue(expected.getMessage().contains("Failed to bootstrap the Spring ApplicationContext!"));
|
||||
assertTrue(expected.getCause() instanceof IllegalStateException);
|
||||
assertEquals("The Spring ApplicationContext (testInitWhenApplicationContextIsNotRunning) failed to be properly initialized with the context config files ([/path/to/spring/application/context.xml]) or base packages ([])!",
|
||||
expected.getCause().getMessage());
|
||||
throw (IllegalStateException) expected.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testInitLogsErrors() throws Throwable {
|
||||
final Log mockLogger = mock(Log.class, "testInitLogsErrors.MockLog");
|
||||
|
||||
SpringContextBootstrappingInitializer initializer = new SpringContextBootstrappingInitializer() {
|
||||
@Override
|
||||
protected ConfigurableApplicationContext createApplicationContext(final String[] basePackages,
|
||||
@Override protected Log initLogger() {
|
||||
return mockLogger;
|
||||
}
|
||||
|
||||
@Override protected ConfigurableApplicationContext createApplicationContext(final String[] basePackages,
|
||||
final String[] configLocations) {
|
||||
return mockApplicationContext;
|
||||
throw new IllegalStateException("TEST");
|
||||
}
|
||||
};
|
||||
|
||||
initializer.init(createParameters(SpringContextBootstrappingInitializer.CONTEXT_CONFIG_LOCATIONS_PARAMETER,
|
||||
"/path/to/spring/application/context.xml"));
|
||||
|
||||
verify(mockApplicationContext, times(1)).addApplicationListener(same(initializer));
|
||||
verify(mockApplicationContext, times(1)).registerShutdownHook();
|
||||
verify(mockApplicationContext, times(1)).refresh();
|
||||
|
||||
SpringContextBootstrappingInitializer.getApplicationContext();
|
||||
try {
|
||||
initializer.init(createParameters(SpringContextBootstrappingInitializer.CONTEXT_CONFIG_LOCATIONS_PARAMETER,
|
||||
"classpath/to/spring/application/context.xml"));
|
||||
}
|
||||
catch (ApplicationContextException expected) {
|
||||
assertTrue(expected.getMessage().contains("Failed to bootstrap the Spring ApplicationContext!"));
|
||||
assertTrue(expected.getCause() instanceof IllegalStateException);
|
||||
assertEquals("TEST", expected.getCause().getMessage());
|
||||
throw expected.getCause();
|
||||
}
|
||||
finally {
|
||||
verify(mockLogger, times(1)).error(eq("Failed to bootstrap the Spring ApplicationContext!"),
|
||||
any(RuntimeException.class));
|
||||
}
|
||||
}
|
||||
|
||||
protected static void assertNotifiedWithEvent(final TestApplicationListener listener, final ContextRefreshedEvent expectedEvent) {
|
||||
Assert.assertTrue(listener.isNotified());
|
||||
assertTrue(listener.isNotified());
|
||||
Assert.assertSame(expectedEvent, listener.getActualEvent());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user