diff --git a/core/src/main/java/org/acegisecurity/ui/session/HttpSessionEventPublisher.java b/core/src/main/java/org/acegisecurity/ui/session/HttpSessionEventPublisher.java index 6b7e6c38ab..4970ed0741 100644 --- a/core/src/main/java/org/acegisecurity/ui/session/HttpSessionEventPublisher.java +++ b/core/src/main/java/org/acegisecurity/ui/session/HttpSessionEventPublisher.java @@ -21,25 +21,27 @@ import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; -import org.springframework.util.Assert; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; +import javax.servlet.ServletContext; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; /** * Declared in web.xml as
- * <listener>
- * <listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class>
- * </listener>
- *
Publishes HttpSessionApplicationEvents to the Spring - * Root WebApplicationContext.
+ *
+ * <listener>
+ * <listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class>
+ * </listener>
+ * 
+ * Publishes HttpSessionApplicationEvents to the Spring + * Root WebApplicationContext. * Maps javax.servlet.http.HttpSessionListener.sessionCreated() to {@link - * HttpSessionCreatedEvent}.
+ * HttpSessionCreatedEvent}. * Maps javax.servlet.http.HttpSessionListener.sessionDestroyed() to {@link - * HttpSessionDestroyedEvent}.
+ * HttpSessionDestroyedEvent}. * * @author Ray Krueger */ @@ -51,7 +53,8 @@ public class HttpSessionEventPublisher implements HttpSessionListener, //~ Instance fields ======================================================== - private ApplicationContext context; + private ApplicationContext appContext; + private ServletContext servletContext = null; //~ Methods ================================================================ @@ -64,22 +67,28 @@ public class HttpSessionEventPublisher implements HttpSessionListener, /** * Handled internally by a call to {@link - * org.springframework.web.context.support.WebApplicationContextUtils#getRequiredWebApplicationContext(javax.servlet.ServletContext)} + * org.springframework.web.appContext.support.WebApplicationContextUtils#getRequiredWebApplicationContext(javax.servlet.ServletContext)} * * @param event the ServletContextEvent passed in by the container, * event.getServletContext() will be used to get the * WebApplicationContext */ public void contextInitialized(ServletContextEvent event) { - if (log.isDebugEnabled()) - log.debug("Received ServletContextEvent: " + event); - setContext(WebApplicationContextUtils.getRequiredWebApplicationContext( - event.getServletContext())); + log.debug("Received ServletContextEvent: " + event); + + appContext = WebApplicationContextUtils.getWebApplicationContext( + event.getServletContext()); + + if(appContext == null) { + log.warn("Web application context is null. Will delay initialization until it's first used."); + servletContext = event.getServletContext(); + } + } /** * Handles the HttpSessionEvent by publishing a {@link - * HttpSessionCreatedEvent} to the application context. + * HttpSessionCreatedEvent} to the application appContext. * * @param event HttpSessionEvent passed in by the container */ @@ -94,7 +103,7 @@ public class HttpSessionEventPublisher implements HttpSessionListener, /** * Handles the HttpSessionEvent by publishing a {@link - * HttpSessionDestroyedEvent} to the application context. + * HttpSessionDestroyedEvent} to the application appContext. * * @param event The HttpSessionEvent pass in by the container */ @@ -107,19 +116,11 @@ public class HttpSessionEventPublisher implements HttpSessionListener, getContext().publishEvent(e); } - /** - * Package level method for testing and internal usage - * - * @param context The ApplicationContext this class will use to publish - * events - */ - void setContext(ApplicationContext context) { - this.context = context; - log.debug("Using context: " + context); - } - ApplicationContext getContext() { - Assert.notNull(context, "setContext(...) never called, ApplicationContext must not be null"); - return context; + if(appContext == null) { + appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); + } + + return appContext; } } diff --git a/core/src/test/java/org/acegisecurity/ui/session/HttpSessionEventPublisherTests.java b/core/src/test/java/org/acegisecurity/ui/session/HttpSessionEventPublisherTests.java index 1ecdda61b3..b6debd5a28 100644 --- a/core/src/test/java/org/acegisecurity/ui/session/HttpSessionEventPublisherTests.java +++ b/core/src/test/java/org/acegisecurity/ui/session/HttpSessionEventPublisherTests.java @@ -20,13 +20,10 @@ import junit.framework.TestCase; import org.springframework.mock.web.MockServletContext; import org.springframework.mock.web.MockHttpSession; import org.springframework.web.context.support.StaticWebApplicationContext; -import org.springframework.context.ConfigurableApplicationContext; import javax.servlet.ServletContextEvent; import javax.servlet.http.HttpSessionEvent; -import org.acegisecurity.MockApplicationContext; - /** * The HttpSessionEventPublisher tests @@ -39,9 +36,8 @@ public class HttpSessionEventPublisherTests extends TestCase { /** * It's not that complicated so we'll just run it straight through here. - * @throws Exception */ - public void testPublisher() throws Exception { + public void testPublisher() { HttpSessionEventPublisher publisher = new HttpSessionEventPublisher(); StaticWebApplicationContext context = new StaticWebApplicationContext(); @@ -77,21 +73,29 @@ public class HttpSessionEventPublisherTests extends TestCase { publisher.contextDestroyed(new ServletContextEvent(servletContext)); } - public void testContext() throws Exception { - HttpSessionEventPublisher pub = new HttpSessionEventPublisher(); - ConfigurableApplicationContext c = MockApplicationContext.getContext(); - pub.setContext(c); - assertEquals(c, pub.getContext()); + + public void testDelayedContextInitializationSucceeds() { + HttpSessionEventPublisher publisher = new HttpSessionEventPublisher(); + MockServletContext servletContext = new MockServletContext(); + + // shouldn't fail, even with null context + publisher.contextInitialized(new ServletContextEvent(servletContext)); + + + StaticWebApplicationContext context = new StaticWebApplicationContext(); + context.setServletContext(servletContext); + + } - public void testNullContextCheck() throws Exception { - HttpSessionEventPublisher pub = new HttpSessionEventPublisher(); + public void testGetContextThrowsExceptionIfContextNotSet() { + HttpSessionEventPublisher publisher = new HttpSessionEventPublisher(); + publisher.contextInitialized(new ServletContextEvent(new MockServletContext())); try { - pub.getContext(); - fail("IllegalArgumentException expected, the context is null"); - } catch (IllegalArgumentException e) { - assertTrue(true); + publisher.getContext(); + fail("IllegalStateException expected when no context set"); + } catch (IllegalStateException expected) { } } }