diff --git a/extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/sessioncontext/ObservingBean.java b/extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/sessioncontext/ObservingBean.java new file mode 100644 index 0000000000000..971e8ecf1ad3b --- /dev/null +++ b/extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/sessioncontext/ObservingBean.java @@ -0,0 +1,46 @@ +package io.quarkus.undertow.test.sessioncontext; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.BeforeDestroyed; +import jakarta.enterprise.context.Destroyed; +import jakarta.enterprise.context.Initialized; +import jakarta.enterprise.context.SessionScoped; +import jakarta.enterprise.event.Observes; + +@ApplicationScoped +public class ObservingBean { + + int timesInitObserved = 0; + int timesBeforeDestroyedObserved = 0; + int timesDestroyedObserved = 0; + + public int getTimesInitObserved() { + return timesInitObserved; + } + + public int getTimesBeforeDestroyedObserved() { + return timesBeforeDestroyedObserved; + } + + public int getTimesDestroyedObserved() { + return timesDestroyedObserved; + } + + public void observeInit(@Observes @Initialized(SessionScoped.class) Object event) { + timesInitObserved++; + } + + public void observeBeforeDestroyed(@Observes @BeforeDestroyed(SessionScoped.class) Object event) { + timesBeforeDestroyedObserved++; + } + + public void observeDestroyed(@Observes @Destroyed(SessionScoped.class) Object event) { + timesDestroyedObserved++; + } + + public void resetState() { + this.timesInitObserved = 0; + this.timesBeforeDestroyedObserved = 0; + this.timesDestroyedObserved = 0; + } +} diff --git a/extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/sessioncontext/SessionContextTestCase.java b/extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/sessioncontext/SessionContextTestCase.java index 949133763a83a..acc52ce3e5494 100644 --- a/extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/sessioncontext/SessionContextTestCase.java +++ b/extensions/undertow/deployment/src/test/java/io/quarkus/undertow/test/sessioncontext/SessionContextTestCase.java @@ -5,9 +5,11 @@ import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +import io.quarkus.arc.Arc; import io.quarkus.test.QuarkusUnitTest; import io.restassured.response.Response; @@ -15,7 +17,7 @@ public class SessionContextTestCase { @RegisterExtension static QuarkusUnitTest runner = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar.addClasses(TestServlet.class, Foo.class)); + .withApplicationRoot((jar) -> jar.addClasses(TestServlet.class, Foo.class, ObservingBean.class)); @Test public void testServlet() { @@ -30,4 +32,18 @@ public void testServlet() { response.then().statusCode(200).body(is("count=1")); } + @Test + public void testContextEvents() { + ObservingBean observingBean = Arc.container().select(ObservingBean.class).get(); + + // make sure we start with zero events to keep this test method independent + observingBean.resetState(); + + // following request creates a session and also destroys it by enforcing invalidation + when().get("/foo?destroy=true").then().statusCode(200); + Assertions.assertEquals(1, observingBean.getTimesInitObserved()); + Assertions.assertEquals(1, observingBean.getTimesBeforeDestroyedObserved()); + Assertions.assertEquals(1, observingBean.getTimesDestroyedObserved()); + } + } diff --git a/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/HttpSessionContext.java b/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/HttpSessionContext.java index 388d1665d0984..15337ec507f9d 100644 --- a/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/HttpSessionContext.java +++ b/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/HttpSessionContext.java @@ -6,10 +6,14 @@ import java.util.Objects; import java.util.stream.Collectors; +import jakarta.enterprise.context.BeforeDestroyed; import jakarta.enterprise.context.ContextNotActiveException; +import jakarta.enterprise.context.Destroyed; +import jakarta.enterprise.context.Initialized; import jakarta.enterprise.context.SessionScoped; import jakarta.enterprise.context.spi.Contextual; import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.event.Event; import jakarta.servlet.annotation.WebListener; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; @@ -205,12 +209,20 @@ public boolean equals(Object obj) { @Override public void sessionDestroyed(HttpSessionEvent se) { HttpSession session = se.getSession(); + Event event = Arc.container().beanManager().getEvent(); + event.select(HttpSession.class, BeforeDestroyed.Literal.SESSION).fire(session); try { DESTRUCT_SESSION.set(session); destroy(session); + event.select(HttpSession.class, Destroyed.Literal.SESSION).fire(session); } finally { DESTRUCT_SESSION.remove(); } } + @Override + public void sessionCreated(HttpSessionEvent se) { + Arc.container().beanManager().getEvent().select(HttpSession.class, Initialized.Literal.SESSION).fire(se.getSession()); + } + }