You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by ch...@apache.org on 2013/06/13 07:02:54 UTC

[05/10] git commit: Added support for HttpSession events

Added support for HttpSession events


Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/8a424606
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/8a424606
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/8a424606

Branch: refs/heads/master
Commit: 8a424606874a37395846d117a631e345a910788a
Parents: 377fc6e
Author: Christian Kaltepoth <ch...@kaltepoth.de>
Authored: Wed May 22 08:28:39 2013 +0200
Committer: Christian Kaltepoth <ch...@kaltepoth.de>
Committed: Thu Jun 13 06:53:29 2013 +0200

----------------------------------------------------------------------
 deltaspike/modules/servlet/impl/pom.xml         |   7 +
 .../deltaspike/servlet/impl/EventEmitter.java   |  43 +++++
 .../servlet/impl/ServletEventBridgeFilter.java  |  13 +-
 .../impl/ServletEventBridgeListener.java        |  48 +++++
 .../main/resources/META-INF/web-fragment.xml    |   5 +
 .../event/session/CreateSessionServlet.java     |  46 +++++
 .../event/session/DestroySessionServlet.java    |  51 ++++++
 .../event/session/SessionEventsObserver.java    |  64 +++++++
 .../impl/event/session/SessionEventsTest.java   | 177 +++++++++++++++++++
 9 files changed, 442 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8a424606/deltaspike/modules/servlet/impl/pom.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/servlet/impl/pom.xml b/deltaspike/modules/servlet/impl/pom.xml
index 03ac17c..ee2ae40 100644
--- a/deltaspike/modules/servlet/impl/pom.xml
+++ b/deltaspike/modules/servlet/impl/pom.xml
@@ -61,6 +61,13 @@
             <scope>test</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.jboss.shrinkwrap.descriptors</groupId>
+            <artifactId>shrinkwrap-descriptors-impl</artifactId>
+            <version>1.1.0-beta-1</version>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 
 </project>

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8a424606/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/EventEmitter.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/EventEmitter.java b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/EventEmitter.java
new file mode 100644
index 0000000..a9af77e
--- /dev/null
+++ b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/EventEmitter.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.deltaspike.servlet.impl;
+
+import java.lang.annotation.Annotation;
+
+import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
+
+/**
+ * Base class for classes which send servlet events to the CDI event bus. This class uses {@link BeanManagerProvider} to
+ * obtain the BeanManager.
+ * 
+ * @author Christian Kaltepoth
+ */
+abstract class EventEmitter
+{
+
+    protected void fireEvent(Object event, Annotation... qualifier)
+    {
+        /*
+         * No need to cache the BeanManager reference because the providers already does this on a context class loader
+         * level.
+         */
+        BeanManagerProvider.getInstance().getBeanManager().fireEvent(event, qualifier);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8a424606/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeFilter.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeFilter.java b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeFilter.java
index f0763dc..90cadd3 100644
--- a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeFilter.java
+++ b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeFilter.java
@@ -19,7 +19,6 @@
 package org.apache.deltaspike.servlet.impl;
 
 import java.io.IOException;
-import java.lang.annotation.Annotation;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
@@ -28,7 +27,6 @@ import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
-import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
 import org.apache.deltaspike.servlet.api.literal.DestroyedLiteral;
 import org.apache.deltaspike.servlet.api.literal.InitializedLiteral;
 import org.apache.deltaspike.servlet.api.literal.WebLiteral;
@@ -36,7 +34,7 @@ import org.apache.deltaspike.servlet.api.literal.WebLiteral;
 /**
  * @author Christian Kaltepoth
  */
-public class ServletEventBridgeFilter implements Filter
+public class ServletEventBridgeFilter extends EventEmitter implements Filter
 {
 
     @Override
@@ -71,13 +69,4 @@ public class ServletEventBridgeFilter implements Filter
         // nothing yet
     }
 
-    protected void fireEvent(Object event, Annotation... qualifier)
-    {
-        /*
-         * No need to cache the BeanManager reference because the providers already does this on a context class loader
-         * level.
-         */
-        BeanManagerProvider.getInstance().getBeanManager().fireEvent(event, qualifier);
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8a424606/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeListener.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeListener.java b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeListener.java
new file mode 100644
index 0000000..6993351
--- /dev/null
+++ b/deltaspike/modules/servlet/impl/src/main/java/org/apache/deltaspike/servlet/impl/ServletEventBridgeListener.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.deltaspike.servlet.impl;
+
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+import org.apache.deltaspike.servlet.api.literal.DestroyedLiteral;
+import org.apache.deltaspike.servlet.api.literal.InitializedLiteral;
+import org.apache.deltaspike.servlet.api.literal.WebLiteral;
+
+/**
+ * This class listens for various servlet events and forwards them to the CDI event bus.
+ * 
+ * @author Christian Kaltepoth
+ */
+public class ServletEventBridgeListener extends EventEmitter implements HttpSessionListener
+{
+
+    @Override
+    public void sessionCreated(HttpSessionEvent se)
+    {
+        fireEvent(se.getSession(), WebLiteral.INSTANCE, InitializedLiteral.INSTANCE);
+    }
+
+    @Override
+    public void sessionDestroyed(HttpSessionEvent se)
+    {
+        fireEvent(se.getSession(), WebLiteral.INSTANCE, DestroyedLiteral.INSTANCE);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8a424606/deltaspike/modules/servlet/impl/src/main/resources/META-INF/web-fragment.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/servlet/impl/src/main/resources/META-INF/web-fragment.xml b/deltaspike/modules/servlet/impl/src/main/resources/META-INF/web-fragment.xml
index 255ae66..af56b7d 100644
--- a/deltaspike/modules/servlet/impl/src/main/resources/META-INF/web-fragment.xml
+++ b/deltaspike/modules/servlet/impl/src/main/resources/META-INF/web-fragment.xml
@@ -10,6 +10,11 @@
         </before>
     </ordering>
 
+    <listener>
+        <display-name>ServletEventBridgeListener</display-name>
+        <listener-class>org.apache.deltaspike.servlet.impl.ServletEventBridgeListener</listener-class>
+    </listener>
+
     <filter>
         <display-name>ServletEventBridgeFilter</display-name>
         <filter-name>ServletEventBridgeFilter</filter-name>

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8a424606/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/CreateSessionServlet.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/CreateSessionServlet.java b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/CreateSessionServlet.java
new file mode 100644
index 0000000..1644aa1
--- /dev/null
+++ b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/CreateSessionServlet.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.deltaspike.test.servlet.impl.event.session;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * Simple servlet that creates a {@link HttpSession}
+ * 
+ * @author Christian Kaltepoth
+ */
+public class CreateSessionServlet extends HttpServlet
+{
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+    {
+        // force creation of a new session
+        req.getSession(true);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8a424606/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/DestroySessionServlet.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/DestroySessionServlet.java b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/DestroySessionServlet.java
new file mode 100644
index 0000000..bffef69
--- /dev/null
+++ b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/DestroySessionServlet.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.deltaspike.test.servlet.impl.event.session;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+/**
+ * Simple servlet that invalidates an existing session. The servlet will throw an {@link IllegalStateException} if no
+ * session exists.
+ * 
+ * @author Christian Kaltepoth
+ */
+public class DestroySessionServlet extends HttpServlet
+{
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+    {
+        HttpSession session = req.getSession(false);
+        if (session == null)
+        {
+            throw new IllegalStateException("No existing session");
+        }
+        session.invalidate();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8a424606/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/SessionEventsObserver.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/SessionEventsObserver.java b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/SessionEventsObserver.java
new file mode 100644
index 0000000..9db5be6
--- /dev/null
+++ b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/SessionEventsObserver.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.deltaspike.test.servlet.impl.event.session;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Observes;
+import javax.servlet.http.HttpSession;
+
+import org.apache.deltaspike.servlet.api.Destroyed;
+import org.apache.deltaspike.servlet.api.Initialized;
+import org.apache.deltaspike.servlet.api.Web;
+
+/**
+ * Application scoped observer which listens for {@link HttpSession} events on the CDI event bus.
+ * 
+ * @author Christian Kaltepoth
+ */
+@ApplicationScoped
+public class SessionEventsObserver
+{
+
+    private final List<String> eventLog = new ArrayList<String>();
+
+    public void sessionInitialized(@Observes @Web @Initialized HttpSession session)
+    {
+        eventLog.add("Initialized HttpSession");
+    }
+
+    public void sessionDestroyed(@Observes @Web @Destroyed HttpSession session)
+    {
+        eventLog.add("Destroyed HttpSession");
+    }
+
+    public int getEventCount()
+    {
+        return eventLog.size();
+    }
+
+    public List<String> getEventLog()
+    {
+        return Collections.unmodifiableList(eventLog);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8a424606/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/SessionEventsTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/SessionEventsTest.java b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/SessionEventsTest.java
new file mode 100644
index 0000000..e855f78
--- /dev/null
+++ b/deltaspike/modules/servlet/impl/src/test/java/org/apache/deltaspike/test/servlet/impl/event/session/SessionEventsTest.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.deltaspike.test.servlet.impl.event.session;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URL;
+
+import javax.inject.Inject;
+
+import org.apache.deltaspike.test.category.WebProfileCategory;
+import org.apache.deltaspike.test.servlet.impl.Deployments;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.params.ClientPNames;
+import org.apache.http.client.params.CookiePolicy;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.junit.InSequence;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.descriptor.api.Descriptors;
+import org.jboss.shrinkwrap.descriptor.api.spec.servlet.web.WebAppDescriptor;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+/**
+ * Test which validates that CDI events are fired when sessions are created and destroyed
+ * 
+ * @author Christian Kaltepoth
+ */
+@RunWith(Arquillian.class)
+@Category(WebProfileCategory.class)
+public class SessionEventsTest
+{
+
+    @Deployment
+    public static WebArchive getDeployment()
+    {
+        return ShrinkWrap.create(WebArchive.class, "test.war")
+                .addAsLibraries(Deployments.getDeltaSpikeCoreArchives())
+                .addAsLibraries(Deployments.getDeltaSpikeServletArchives())
+                .addAsLibraries(Deployments.getTestSupportArchives())
+                .addClass(SessionEventsObserver.class)
+                .addAsWebInfResource(new StringAsset("<beans/>"), "beans.xml")
+                .addAsWebResource(new StringAsset("foobar"), "foobar.txt")
+                .setWebXML(new StringAsset(
+                        Descriptors.create(WebAppDescriptor.class)
+                                .servlet(CreateSessionServlet.class, "/create-session")
+                                .servlet(DestroySessionServlet.class, "/destroy-session")
+                                .exportAsString()));
+
+    }
+
+    /**
+     * Needs to be static so that the client can be reused between test methods
+     */
+    private static DefaultHttpClient client;
+
+    @BeforeClass
+    public static void initHttpClient()
+    {
+        client = new DefaultHttpClient();
+        client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);
+    }
+
+    @AfterClass
+    public static void destroyHttpClient()
+    {
+        client = null;
+    }
+
+    @Inject
+    private SessionEventsObserver observer;
+
+    /**
+     * First send a request to a standard resource which won't create a user session
+     */
+    @Test
+    @RunAsClient
+    @InSequence(1)
+    public void sendStatelessRequest(@ArquillianResource URL contextPath) throws Exception
+    {
+        String url = new URL(contextPath, "foobar.txt").toString();
+        HttpResponse response = client.execute(new HttpGet(url));
+        assertEquals(200, response.getStatusLine().getStatusCode());
+        EntityUtils.consumeQuietly(response.getEntity());
+    }
+
+    /**
+     * The observer didn't any events because no session was created
+     */
+    @Test
+    @InSequence(2)
+    public void statelessRequestDoesntEmitEvents()
+    {
+        assertEquals(0, observer.getEventCount());
+    }
+
+    /**
+     * Now send a request which creates a session
+     */
+    @Test
+    @RunAsClient
+    @InSequence(3)
+    public void sendRequestToCreateSession(@ArquillianResource URL contextPath) throws Exception
+    {
+        String url = new URL(contextPath, "create-session").toString();
+        HttpResponse response = client.execute(new HttpGet(url));
+        assertEquals(200, response.getStatusLine().getStatusCode());
+        EntityUtils.consumeQuietly(response.getEntity());
+    }
+
+    /**
+     * The observer should have received a event
+     */
+    @Test
+    @InSequence(4)
+    public void shouldReceiveInitializedSessionEvent()
+    {
+        assertEquals(1, observer.getEventCount());
+        assertTrue("Didn't receive expected event",
+                observer.getEventLog().contains("Initialized HttpSession"));
+    }
+
+    /**
+     * Now send a request which creates a session
+     */
+    @Test
+    @RunAsClient
+    @InSequence(5)
+    public void sendRequestToDestroySession(@ArquillianResource URL contextPath) throws Exception
+    {
+        String url = new URL(contextPath, "destroy-session").toString();
+        HttpResponse response = client.execute(new HttpGet(url));
+        assertEquals(200, response.getStatusLine().getStatusCode());
+        EntityUtils.consumeQuietly(response.getEntity());
+    }
+
+    /**
+     * The observer should have received a event
+     */
+    @Test
+    @InSequence(6)
+    public void shouldReceiveDestroyedSessionEvent()
+    {
+        assertEquals(2, observer.getEventCount());
+        assertTrue("Didn't receive expected event",
+                observer.getEventLog().contains("Destroyed HttpSession"));
+    }
+
+}