You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2020/01/10 12:24:44 UTC

[isis] branch master updated: ISIS-2158: fix WebModules getting discovered by CDI

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 67c53cb  ISIS-2158: fix WebModules getting discovered by CDI
67c53cb is described below

commit 67c53cb264ab094f345e0f5a5fb043d36c1b5fcf
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Jan 10 13:24:35 2020 +0100

    ISIS-2158: fix WebModules getting discovered by CDI
    
    WebModules are managed by Isis and should not be discovered by any
    container.
---
 .../keycloak/webmodule/WebModuleKeycloak.java       |  7 +++----
 .../security/shiro/webmodule/WebModuleShiro.java    | 16 +++++++---------
 .../webmodule/WebModuleJaxrsResteasy4.java          |  8 +++-----
 .../wicket/viewer/webmodule/WebModuleWicket.java    |  8 +++-----
 .../org/apache/isis/webapp/modules/WebModule.java   | 11 +++++++----
 .../isis/webapp/modules/WebModuleAbstract.java      | 14 +++++++++++---
 .../isis/webapp/modules/WebModuleContext.java       | 21 +++------------------
 .../logonlog/WebModuleLogOnExceptionLogger.java     |  7 +++----
 .../templresources/WebModuleTemplateResources.java  |  7 +++----
 .../extensions/cors/webmodule/WebModuleCors.java    |  7 +++----
 .../jee_support/IsisCDIBeanScanInterceptor.java     |  2 ++
 .../sse/webmodule/WebModuleServerSentEvents.java    |  7 +++----
 12 files changed, 51 insertions(+), 64 deletions(-)

diff --git a/core/security/keycloak/src/main/java/org/apache/isis/security/keycloak/webmodule/WebModuleKeycloak.java b/core/security/keycloak/src/main/java/org/apache/isis/security/keycloak/webmodule/WebModuleKeycloak.java
index c3e70de..1ef31fe 100644
--- a/core/security/keycloak/src/main/java/org/apache/isis/security/keycloak/webmodule/WebModuleKeycloak.java
+++ b/core/security/keycloak/src/main/java/org/apache/isis/security/keycloak/webmodule/WebModuleKeycloak.java
@@ -18,8 +18,6 @@
  */
 package org.apache.isis.security.keycloak.webmodule;
 
-import java.util.List;
-
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.servlet.ServletContext;
@@ -32,6 +30,7 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.webapp.modules.WebModuleAbstract;
 
 import lombok.Getter;
@@ -56,7 +55,7 @@ public final class WebModuleKeycloak extends WebModuleAbstract {
     }
 
     @Override
-    public List<ServletContextListener> init(ServletContext ctx) throws ServletException {
+    public Can<ServletContextListener> init(ServletContext ctx) throws ServletException {
 
         registerFilter(ctx, KEYCLOAK_FILTER_NAME, KeycloakFilter.class)
             .ifPresent(filterReg -> {
@@ -67,7 +66,7 @@ public final class WebModuleKeycloak extends WebModuleAbstract {
 
             });
 
-        return null;
+        return Can.empty(); // registers no listeners
     }
 
 }
diff --git a/core/security/shiro/src/main/java/org/apache/isis/security/shiro/webmodule/WebModuleShiro.java b/core/security/shiro/src/main/java/org/apache/isis/security/shiro/webmodule/WebModuleShiro.java
index 90261fa..ef994b5 100644
--- a/core/security/shiro/src/main/java/org/apache/isis/security/shiro/webmodule/WebModuleShiro.java
+++ b/core/security/shiro/src/main/java/org/apache/isis/security/shiro/webmodule/WebModuleShiro.java
@@ -19,9 +19,7 @@
 package org.apache.isis.security.shiro.webmodule;
 
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 import javax.inject.Inject;
@@ -44,6 +42,7 @@ import org.springframework.util.ReflectionUtils;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal._Constants;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.webapp.modules.WebModuleAbstract;
@@ -118,13 +117,12 @@ public class WebModuleShiro extends WebModuleAbstract {
      * Adds support for dependency injection into security realms
      * @since 2.0
      */
-    @NoArgsConstructor
+    @NoArgsConstructor // don't remove, this is class is managed by Isis
     public static class EnvironmentLoaderListenerForIsis extends EnvironmentLoaderListener {
 
-        @Inject
-        private ServiceInjector serviceInjector;
+        @Inject private ServiceInjector serviceInjector;
 
-        // for testing
+        // testing support
         public EnvironmentLoaderListenerForIsis(ServiceInjector serviceInjector) {
             this.serviceInjector = serviceInjector;
         }
@@ -169,7 +167,7 @@ public class WebModuleShiro extends WebModuleAbstract {
     }
 
     @Override
-    public List<ServletContextListener> init(ServletContext ctx) throws ServletException {
+    public Can<ServletContextListener> init(ServletContext ctx) throws ServletException {
 
         registerFilter(ctx, SHIRO_FILTER_NAME, ShiroFilter.class)
             .ifPresent(filterReg -> {
@@ -184,8 +182,8 @@ public class WebModuleShiro extends WebModuleAbstract {
             ctx.setInitParameter("shiroEnvironmentClass", customShiroEnvironmentClassName);
         }
 
-        val listener = createListener(ctx, EnvironmentLoaderListenerForIsis.class);
-        return Collections.singletonList(listener);
+        val listener = createListener(EnvironmentLoaderListenerForIsis.class);
+        return Can.ofSingleton(listener);
 
     }
 
diff --git a/core/viewers/restfulobjects/jaxrs-resteasy-4/src/main/java/org/apache/isis/viewer/restfulobjects/jaxrsresteasy4/webmodule/WebModuleJaxrsResteasy4.java b/core/viewers/restfulobjects/jaxrs-resteasy-4/src/main/java/org/apache/isis/viewer/restfulobjects/jaxrsresteasy4/webmodule/WebModuleJaxrsResteasy4.java
index 92debbb..ffa3f3c 100644
--- a/core/viewers/restfulobjects/jaxrs-resteasy-4/src/main/java/org/apache/isis/viewer/restfulobjects/jaxrsresteasy4/webmodule/WebModuleJaxrsResteasy4.java
+++ b/core/viewers/restfulobjects/jaxrs-resteasy-4/src/main/java/org/apache/isis/viewer/restfulobjects/jaxrsresteasy4/webmodule/WebModuleJaxrsResteasy4.java
@@ -18,9 +18,6 @@
  */
 package org.apache.isis.viewer.restfulobjects.jaxrsresteasy4.webmodule;
 
-import java.util.Collections;
-import java.util.List;
-
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.servlet.ServletContext;
@@ -33,6 +30,7 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.config.RestEasyConfiguration;
 import org.apache.isis.viewer.restfulobjects.viewer.webmodule.IsisRestfulObjectsSessionFilter;
 import org.apache.isis.viewer.restfulobjects.viewer.webmodule.IsisTransactionFilterForRestfulObjects;
@@ -87,7 +85,7 @@ public final class WebModuleJaxrsResteasy4 extends WebModuleAbstract {
     }
 
     @Override
-    public List<ServletContextListener> init(ServletContext ctx) throws ServletException {
+    public Can<ServletContextListener> init(ServletContext ctx) throws ServletException {
 
         registerFilter(ctx, ISIS_SESSION_FILTER_FOR_RESTFUL_OBJECTS, IsisRestfulObjectsSessionFilter.class)
                 .ifPresent(filterReg -> {
@@ -123,7 +121,7 @@ public final class WebModuleJaxrsResteasy4 extends WebModuleAbstract {
             });
 
 
-        return Collections.emptyList();
+        return Can.empty(); // registers no listeners
     }
 
 
diff --git a/core/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/webmodule/WebModuleWicket.java b/core/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/webmodule/WebModuleWicket.java
index 0cc706a..79d1e42 100644
--- a/core/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/webmodule/WebModuleWicket.java
+++ b/core/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/webmodule/WebModuleWicket.java
@@ -18,8 +18,6 @@
  */
 package org.apache.isis.viewer.wicket.viewer.webmodule;
 
-import java.util.List;
-
 import static java.util.Objects.requireNonNull;
 
 import javax.inject.Inject;
@@ -35,6 +33,7 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.environment.IsisSystemEnvironment;
 import org.apache.isis.config.IsisConfiguration;
 import org.apache.isis.webapp.modules.WebModuleAbstract;
@@ -92,13 +91,12 @@ public final class WebModuleWicket extends WebModuleAbstract {
     @Override
     public void prepare(final WebModuleContext ctx) {
         super.prepare(ctx);
-        ctx.setHasBootstrapper();
         ctx.addViewer("wicket");
         ctx.addProtectedPath(this.urlPattern);
     }
 
     @Override
-    public List<ServletContextListener> init(final ServletContext ctx) throws ServletException {
+    public Can<ServletContextListener> init(final ServletContext ctx) throws ServletException {
 
         registerFilter(ctx, WICKET_FILTER_NAME, WicketFilter.class)
             .ifPresent(filterReg -> {
@@ -111,7 +109,7 @@ public final class WebModuleWicket extends WebModuleAbstract {
                         urlPattern);
             });
 
-        return null; // does not provide a listener
+        return Can.empty(); // registers no listeners
     }
 
 }
diff --git a/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModule.java b/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModule.java
index 17b9bba..0ee1a44 100644
--- a/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModule.java
+++ b/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModule.java
@@ -18,8 +18,6 @@
  */
 package org.apache.isis.webapp.modules;
 
-import java.util.List;
-
 import javax.annotation.Priority;
 import javax.servlet.Filter;
 import javax.servlet.Servlet;
@@ -73,9 +71,14 @@ public interface WebModule {
      * Sets this WebModule's {@link Filter}s, {@link Servlet}s or {@link WebListener}s 
      * up and registers them with the {@link ServletContext} as provided via {@code ctx}.
      * @param ctx ServletContext
-     * @return
+     * @return optionally any listeners to be registered
+     * @apiNote don't add {@link ServletContextListener}s to given {@code ctx} directly, because
+     * when on a JEE container, we have no means to veto it to be getting managed by the container;  
+     * {@link ServletContextListener}s should only be known to the {@link IsisWebAppContextInitializer}
+     * and not any of the containers, since the {@link IsisWebAppContextInitializer} acts as a delegator,
+     * that passes over any events to the registered {@link WebModule}s.    
      */
-    public List<ServletContextListener> init(ServletContext ctx) throws ServletException;
+    public Can<ServletContextListener> init(ServletContext ctx) throws ServletException;
 
     /**
      * Expected to be called after all WebModules had a chance to prepare the WebModuleContext.
diff --git a/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModuleAbstract.java b/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModuleAbstract.java
index 467457c..95c461f 100644
--- a/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModuleAbstract.java
+++ b/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModuleAbstract.java
@@ -29,6 +29,7 @@ import javax.servlet.ServletException;
 import javax.servlet.ServletRegistration;
 
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.internal.factory.InstanceUtil;
 
 public abstract class WebModuleAbstract implements WebModule {
 
@@ -71,11 +72,18 @@ public abstract class WebModuleAbstract implements WebModule {
         return Optional.ofNullable(servletReg);
     }
 
+    /**
+     * Instantiates a new {@link ServletContextListener}
+     * @param ctx
+     * @param listenerCls
+     * @return
+     * @throws ServletException
+     */
     protected ServletContextListener createListener(
-            final ServletContext ctx,
             final Class<? extends ServletContextListener> listenerCls) throws ServletException {
-        final ServletContextListener listener = ctx.createListener(listenerCls);
-        // we don't add the listener here, they are all added at the end.
+        
+        final ServletContextListener listener = 
+                InstanceUtil.createInstance(listenerCls, ServletContextListener.class);
         serviceInjector.injectServicesInto(listener);
         return listener;
     }
diff --git a/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModuleContext.java b/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModuleContext.java
index 7170172..37e42b1 100644
--- a/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModuleContext.java
+++ b/core/webapp/src/main/java/org/apache/isis/webapp/modules/WebModuleContext.java
@@ -45,7 +45,6 @@ import lombok.extern.log4j.Log4j2;
 @Log4j2 @RequiredArgsConstructor
 public class WebModuleContext {
 
-    private boolean hasBootstrapper = false;
     private final StringBuilder viewers = new StringBuilder();
     private final StringBuilder protectedPath = new StringBuilder();
 
@@ -57,20 +56,6 @@ public class WebModuleContext {
     private final List<ServletContextListener> activeListeners = new ArrayList<>();
 
     /**
-     * Tell other modules that a bootstrapper is present.
-     */
-    public void setHasBootstrapper() {
-        hasBootstrapper = true;
-    }
-
-    /**
-     * @return whether this context has a bootstrapper
-     */
-    public boolean hasBootstrapper() {
-        return hasBootstrapper;    
-    }
-
-    /**
      *  Adds to the list of viewer names (<tt>isis.viewers</tt> context param)
      * @param viewerName
      */
@@ -126,9 +111,9 @@ public class WebModuleContext {
     private void addListener(ServletContext servletContext, WebModule webModule) {
         log.info(String.format("Setup ServletContext, adding WebModule '%s'", webModule.getName()));
         try {
-            final List<ServletContextListener> listeners = webModule.init(servletContext);
-            if(listeners != null) {
-                activeListeners.addAll(listeners);
+            final Can<ServletContextListener> listeners = webModule.init(servletContext);
+            if(listeners != null && !listeners.isEmpty()) {
+                activeListeners.addAll(listeners.toList());
             }
         } catch (ServletException e) {
             log.error(String.format("Failed to add WebModule '%s' to the ServletContext.", webModule.getName()), e);
diff --git a/core/webapp/src/main/java/org/apache/isis/webapp/modules/logonlog/WebModuleLogOnExceptionLogger.java b/core/webapp/src/main/java/org/apache/isis/webapp/modules/logonlog/WebModuleLogOnExceptionLogger.java
index d0a4bea..e4134b1 100644
--- a/core/webapp/src/main/java/org/apache/isis/webapp/modules/logonlog/WebModuleLogOnExceptionLogger.java
+++ b/core/webapp/src/main/java/org/apache/isis/webapp/modules/logonlog/WebModuleLogOnExceptionLogger.java
@@ -18,8 +18,6 @@
  */
 package org.apache.isis.webapp.modules.logonlog;
 
-import java.util.List;
-
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.servlet.ServletContext;
@@ -32,6 +30,7 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.webapp.diagnostics.IsisLogOnExceptionFilter;
 import org.apache.isis.webapp.modules.WebModuleAbstract;
 
@@ -61,7 +60,7 @@ public final class WebModuleLogOnExceptionLogger extends WebModuleAbstract {
 
 
     @Override
-    public List<ServletContextListener> init(ServletContext ctx) throws ServletException {
+    public Can<ServletContextListener> init(ServletContext ctx) throws ServletException {
 
         registerFilter(ctx, LOGONLOGGER_FILTER_NAME, IsisLogOnExceptionFilter.class)
             .ifPresent(filterReg -> {
@@ -71,7 +70,7 @@ public final class WebModuleLogOnExceptionLogger extends WebModuleAbstract {
                         webModuleContext.getProtectedPaths().toArray(String.class));
             });
 
-        return null; // does not provide a listener
+        return Can.empty(); // registers no listeners
     }
 
 
diff --git a/core/webapp/src/main/java/org/apache/isis/webapp/modules/templresources/WebModuleTemplateResources.java b/core/webapp/src/main/java/org/apache/isis/webapp/modules/templresources/WebModuleTemplateResources.java
index bc1d831..8ae6267 100644
--- a/core/webapp/src/main/java/org/apache/isis/webapp/modules/templresources/WebModuleTemplateResources.java
+++ b/core/webapp/src/main/java/org/apache/isis/webapp/modules/templresources/WebModuleTemplateResources.java
@@ -18,8 +18,6 @@
  */
 package org.apache.isis.webapp.modules.templresources;
 
-import java.util.List;
-
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.servlet.ServletContext;
@@ -32,6 +30,7 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.webapp.modules.WebModuleAbstract;
 
 import lombok.Getter;
@@ -62,7 +61,7 @@ public final class WebModuleTemplateResources extends WebModuleAbstract {
     }
 
     @Override
-    public List<ServletContextListener> init(ServletContext ctx) throws ServletException {
+    public Can<ServletContextListener> init(ServletContext ctx) throws ServletException {
 
         registerFilter(ctx, FILTER_NAME, TemplateResourceCachingFilter.class)
             .ifPresent(filterReg -> {
@@ -81,7 +80,7 @@ public final class WebModuleTemplateResources extends WebModuleAbstract {
                 servletReg.addMapping(urlPatterns);
             });
 
-        return null; // does not provide a listener
+        return Can.empty(); // registers no listeners
     }
 
 }
diff --git a/extensions/vro/cors/impl/src/main/java/org/apache/isis/extensions/cors/webmodule/WebModuleCors.java b/extensions/vro/cors/impl/src/main/java/org/apache/isis/extensions/cors/webmodule/WebModuleCors.java
index 02d87f7..8dbc1c6 100644
--- a/extensions/vro/cors/impl/src/main/java/org/apache/isis/extensions/cors/webmodule/WebModuleCors.java
+++ b/extensions/vro/cors/impl/src/main/java/org/apache/isis/extensions/cors/webmodule/WebModuleCors.java
@@ -18,8 +18,6 @@
  */
 package org.apache.isis.extensions.cors.webmodule;
 
-import java.util.List;
-
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.servlet.ServletContext;
@@ -33,6 +31,7 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.webapp.modules.WebModuleAbstract;
 
 import lombok.Getter;
@@ -83,7 +82,7 @@ public final class WebModuleCors extends WebModuleAbstract {
     </filter-mapping>
      */
     @Override
-    public List<ServletContextListener> init(ServletContext ctx) throws ServletException {
+    public Can<ServletContextListener> init(ServletContext ctx) throws ServletException {
 
         registerFilter(ctx, CORS_FILTER_NAME, CORSFilter.class)
             .ifPresent(filterReg -> {
@@ -98,7 +97,7 @@ public final class WebModuleCors extends WebModuleAbstract {
 
             });
 
-        return null;
+        return Can.empty(); // registers no listeners
     }
 
 
diff --git a/incubator/extensions/core/microprofile/src/main/java/org/apache/isis/runtime/jee_support/IsisCDIBeanScanInterceptor.java b/incubator/extensions/core/microprofile/src/main/java/org/apache/isis/runtime/jee_support/IsisCDIBeanScanInterceptor.java
index 5f4af06..d925b00 100644
--- a/incubator/extensions/core/microprofile/src/main/java/org/apache/isis/runtime/jee_support/IsisCDIBeanScanInterceptor.java
+++ b/incubator/extensions/core/microprofile/src/main/java/org/apache/isis/runtime/jee_support/IsisCDIBeanScanInterceptor.java
@@ -26,6 +26,7 @@ import javax.enterprise.inject.spi.AfterBeanDiscovery;
 import javax.enterprise.inject.spi.BeforeBeanDiscovery;
 import javax.enterprise.inject.spi.Extension;
 import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.servlet.ServletContextListener;
 
 import org.springframework.stereotype.Component;
 
@@ -62,6 +63,7 @@ public final class IsisCDIBeanScanInterceptor implements Extension {
      */
     private static final List<Predicate<Class<?>>> vetoTests = _Lists.of(
         ExceptionRecognizer.class::isAssignableFrom,
+        ServletContextListener.class::isAssignableFrom, // seems this has no effect anyway
         type->type.getName().startsWith("org.springframework."),
         type->type.getName().startsWith("org.apache.isis."), 
         type->_Annotations.isPresent(type, Component.class));
diff --git a/valuetypes/sse/src/main/java/org/apache/isis/extensions/sse/webmodule/WebModuleServerSentEvents.java b/valuetypes/sse/src/main/java/org/apache/isis/extensions/sse/webmodule/WebModuleServerSentEvents.java
index cb33df2..8a534cf 100644
--- a/valuetypes/sse/src/main/java/org/apache/isis/extensions/sse/webmodule/WebModuleServerSentEvents.java
+++ b/valuetypes/sse/src/main/java/org/apache/isis/extensions/sse/webmodule/WebModuleServerSentEvents.java
@@ -18,8 +18,6 @@
  */
 package org.apache.isis.extensions.sse.webmodule;
 
-import java.util.List;
-
 import javax.inject.Inject;
 import javax.inject.Named;
 import javax.servlet.ServletContext;
@@ -32,6 +30,7 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.webapp.modules.WebModuleAbstract;
 
 import lombok.Getter;
@@ -59,7 +58,7 @@ public final class WebModuleServerSentEvents extends WebModuleAbstract {
 
 
     @Override
-    public List<ServletContextListener> init(ServletContext ctx) throws ServletException {
+    public Can<ServletContextListener> init(ServletContext ctx) throws ServletException {
 
         registerServlet(ctx, SERVLET_NAME, ServerSentEventsServlet.class)
             .ifPresent(servletReg -> {
@@ -67,7 +66,7 @@ public final class WebModuleServerSentEvents extends WebModuleAbstract {
                 servletReg.addMapping("/sse");
             });
 
-        return null; // does not provide a listener
+        return Can.empty(); // registers no listeners
     }