From 3faf4fcb4ce7727cd2ed0027eec8385fe73e8faa Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Thu, 23 Jul 2026 21:01:49 +0200 Subject: [PATCH 1/4] TOMEE-4642 - Don't fail deployment when a servlet/filter/listener class is missing When a war's web.xml or annotations name a servlet, filter or listener class that is not packaged in the war, ProcessAnnotatedBeans.deploy rethrew the ClassNotFoundException/NoClassDefFoundError as an OpenEJBException, which aborted startup of the whole web context. These loads only feed the annotation scanner, so a missing class simply means there is nothing to scan - it must not bring down the context. Jakarta Servlet 6.1 section 2.3.1 allows servlet loading to be delayed "until the container determines the servlet is needed to service a request", so an unresolved class is deferred, not fatal. The three paths now log a warning and continue, matching the existing tolerant handling of taglib listeners and the servlet name-fallback case. Also fixed off-by-one MessageFormat placeholder indices ({1}{2}{3} -> {0}{1}{2}) in the four related logger.debug calls, which dropped the first argument. Two Jakarta Servlet TCK deployments triggered this (RegistrationTests naming filter AddFilterString, DefaultMappingTests naming servlet TestServlet1). --- .../openejb/config/AnnotationDeployer.java | 23 +++++++---- .../config/AnnotationDeployerTest.java | 40 +++++++++++++++++++ 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java b/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java index 4326211d08b..50a4f18ac57 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java @@ -2263,10 +2263,15 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { servlet.setServletClass(servletClass); } } catch (final ClassNotFoundException | NoClassDefFoundError e) { - logger.debug("Could not load Servlet class {1} for web module {2} / {3}", + logger.debug("Could not load Servlet class {0} for web module {1} / {2}", servletClass, webModule.getJarLocation(), webModule.getFile().getName()); if (servlet.getServletClass() != null) { - throw new OpenEJBException("Unable to load servlet class: " + servletClass, e); + // The class is not available for annotation scanning, but that must not fail the + // whole context. Jakarta Servlet 6.1, section 2.3.1 "Loading and Instantiation" + // allows loading to be "delayed until the container determines the servlet is + // needed to service a request", so a servlet whose class is absent may simply + // never be used (or be registered programmatically). Let resolution happen later. + logger.warning("Unable to load servlet class: " + servletClass); } else { logger.error("servlet " + servletName + " has no servlet-class defined and is not a subclass of Application"); } @@ -2294,9 +2299,11 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { final Class clazz = classLoader.loadClass(filterClass); classes.add(clazz); } catch (final ClassNotFoundException | NoClassDefFoundError e) { - logger.debug("Could not load Servlet Filter class {1} for web module {2} / {3}", + logger.debug("Could not load Servlet Filter class {0} for web module {1} / {2}", filterClass, webModule.getJarLocation(), webModule.getFile().getName()); - throw new OpenEJBException("Unable to load servlet filter class: " + filterClass, e); + // A missing filter class must not fail the whole context; as with servlets + // (Jakarta Servlet 6.1, section 2.3.1) an unresolved class is deferred, not fatal here. + logger.warning("Unable to load servlet filter class: " + filterClass); } } } @@ -2311,9 +2318,11 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { final Class clazz = classLoader.loadClass(listenerClass); classes.add(clazz); } catch (final ClassNotFoundException | NoClassDefFoundError e) { - logger.debug("Could not load Servlet listener class {1} for web module {2} / {3}", + logger.debug("Could not load Servlet listener class {0} for web module {1} / {2}", listenerClass, webModule.getJarLocation(), webModule.getFile().getName()); - throw new OpenEJBException("Unable to load servlet listener class: " + listenerClass, e); + // A missing listener class must not fail the whole context; as with servlets + // (Jakarta Servlet 6.1, section 2.3.1) an unresolved class is deferred, not fatal here. + logger.warning("Unable to load servlet listener class: " + listenerClass); } } } @@ -2329,7 +2338,7 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { final Class clazz = classLoader.loadClass(listenerClass); classes.add(clazz); } catch (final ClassNotFoundException | NoClassDefFoundError e) { - logger.debug("Could not load TagLib listener class {1} for web module {2} / {3}", + logger.debug("Could not load TagLib listener class {0} for web module {1} / {2}", listenerClass, webModule.getJarLocation(), webModule.getFile().getName()); logger.error("Unable to load tag library servlet listener class: " + listenerClass); } diff --git a/container/openejb-core/src/test/java/org/apache/openejb/config/AnnotationDeployerTest.java b/container/openejb-core/src/test/java/org/apache/openejb/config/AnnotationDeployerTest.java index 9e547ac635f..4f1dda0ea7e 100644 --- a/container/openejb-core/src/test/java/org/apache/openejb/config/AnnotationDeployerTest.java +++ b/container/openejb-core/src/test/java/org/apache/openejb/config/AnnotationDeployerTest.java @@ -25,6 +25,9 @@ import org.apache.openejb.jee.Connector; import org.apache.openejb.jee.EjbJar; import org.apache.openejb.jee.EnterpriseBean; +import org.apache.openejb.jee.Filter; +import org.apache.openejb.jee.Listener; +import org.apache.openejb.jee.Servlet; import org.apache.openejb.jee.SessionBean; import org.apache.openejb.jee.TransactionSupportType; import org.apache.openejb.jee.WebApp; @@ -496,6 +499,43 @@ public void setMyNumber(final int myNumber) { } } + /** + * TOMEE-4642: a servlet, filter or listener class named in web.xml but not packaged in the war + * must not abort the deployment of the whole web module. + */ + @Test + public void missingServletFilterAndListenerClassesDoNotFailDeployment() throws Exception { + final WebApp webApp = new WebApp(); + webApp.setContextRoot("/"); + webApp.setId("web"); + webApp.setVersion("2.5"); + + final Servlet servlet = new Servlet(); + servlet.setServletName("TestServlet1"); + servlet.setServletClass("org.apache.openejb.config.missing.TestServlet1"); + webApp.getServlet().add(servlet); + + final Filter filter = new Filter(); + filter.setFilterName("AddFilterString"); + filter.setFilterClass("org.apache.openejb.config.missing.AddFilterString"); + webApp.getFilter().add(filter); + + final Listener listener = new Listener(); + listener.setListenerClass("org.apache.openejb.config.missing.MissingListener"); + webApp.getListener().add(listener); + + WebModule webModule = new WebModule(webApp, webApp.getContextRoot(), Thread.currentThread().getContextClassLoader(), "myapp", webApp.getId()); + webModule.setFinder(new AnnotationFinder(new ClassesArchive()).link()); + + final AnnotationDeployer annotationDeployer = new AnnotationDeployer(); + webModule = annotationDeployer.deploy(webModule); + + // the declarations are kept as-is, they are simply not resolved for annotation scanning + assertEquals(1, webModule.getWebApp().getServlet().size()); + assertEquals(1, webModule.getWebApp().getFilter().size()); + assertEquals(1, webModule.getWebApp().getListener().size()); + } + @Test public void findRestClasses() throws Exception { final WebApp webApp = new WebApp(); From e9aa3f58e39754844f70661171c3805965012c66 Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Tue, 28 Jul 2026 21:30:19 +0200 Subject: [PATCH 2/4] TOMEE-4642 - Also tolerate missing servlet classes in WsDeployer WsDeployer is added to the deployer chain whenever openejb.webservices.enabled is set (default) and wsdl4j is available, which is the case on Plus, Plume and openejb-standalone. processPorts(WebModule) loads every servlet class *before* testing JaxWsUtils.isWebService(clazz), so it is not limited to webservice endpoints: a war naming a servlet class it does not package still failed to deploy on those distributions, with an identically worded error from a different class. Fixing AnnotationDeployer alone did not fix the reported bug. Resolve the class in its own try/catch that tolerates absence and skips webservice detection for that servlet. The previous catch(Exception) would not have caught NoClassDefFoundError anyway, since that is an Error - it propagated raw. The remaining catch now only covers genuine webservice configuration failures, so its message was corrected accordingly. Review feedback also addressed: - pass the cause and the module location to the log calls instead of discarding them, so a genuinely mis-packaged war is still diagnosable - filters and listeners log at error level rather than warning: unlike servlets, Servlet 6.1 does not allow their instantiation to be deferred, so a missing class there is very likely a real packaging error - correct the servlet comment to note that skipping the class also skips @Resource/@EJB processing for it - explain why the webservice handler-chain site stays fatal Add missingServletClassDoesNotFailFullConfiguration, which drives ConfigurationFactory.configureApplication so the whole deployer chain runs. The pre-existing test drove AnnotationDeployer directly and stayed green through the WsDeployer gap; the new one fails without the WsDeployer fix. --- .../openejb/config/AnnotationDeployer.java | 30 ++++++++++---- .../org/apache/openejb/config/WsDeployer.java | 16 +++++++- .../config/AnnotationDeployerTest.java | 41 +++++++++++++++++++ 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java b/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java index 50a4f18ac57..e2ee48eecdb 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java @@ -2271,7 +2271,10 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { // allows loading to be "delayed until the container determines the servlet is // needed to service a request", so a servlet whose class is absent may simply // never be used (or be registered programmatically). Let resolution happen later. - logger.warning("Unable to load servlet class: " + servletClass); + // Note this also skips @Resource/@EJB processing for that servlet, so if the + // class does resolve later it comes up without its injections. + logger.warning("Unable to load servlet class: " + servletClass + " for web module " + + webModule.getJarLocation(), e); } else { logger.error("servlet " + servletName + " has no servlet-class defined and is not a subclass of Application"); } @@ -2301,9 +2304,14 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { } catch (final ClassNotFoundException | NoClassDefFoundError e) { logger.debug("Could not load Servlet Filter class {0} for web module {1} / {2}", filterClass, webModule.getJarLocation(), webModule.getFile().getName()); - // A missing filter class must not fail the whole context; as with servlets - // (Jakarta Servlet 6.1, section 2.3.1) an unresolved class is deferred, not fatal here. - logger.warning("Unable to load servlet filter class: " + filterClass); + // Jakarta Servlet 6.1 section 6.2.1 requires the filter to be instantiated before a + // request reaches a resource it is mapped to - i.e. later than this, but unlike a + // servlet it cannot be skipped if it is ever used. So a missing class is very likely a + // real packaging error; log it at error level, but keep it local to the filter rather + // than failing the whole application (the spec's "must fail to deploy" rules cover + // web-fragment ordering conflicts, not unresolvable component classes). + logger.error("Unable to load servlet filter class: " + filterClass + " for web module " + + webModule.getJarLocation(), e); } } } @@ -2320,9 +2328,11 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { } catch (final ClassNotFoundException | NoClassDefFoundError e) { logger.debug("Could not load Servlet listener class {0} for web module {1} / {2}", listenerClass, webModule.getJarLocation(), webModule.getFile().getName()); - // A missing listener class must not fail the whole context; as with servlets - // (Jakarta Servlet 6.1, section 2.3.1) an unresolved class is deferred, not fatal here. - logger.warning("Unable to load servlet listener class: " + listenerClass); + // A declared listener is instantiated at application startup, so - as for filters + // above - a missing class is very likely a real packaging error rather than something + // that can be deferred. Report it at error level but keep the failure local. + logger.error("Unable to load servlet listener class: " + listenerClass + " for web module " + + webModule.getJarLocation(), e); } } } @@ -2385,8 +2395,12 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { final Class clazz = classLoader.loadClass(handlerClass); classes.add(clazz); } catch (final ClassNotFoundException | NoClassDefFoundError e) { - logger.debug("Could not load web service handler class {1} for web module {2} / {3}", + logger.debug("Could not load web service handler class {0} for web module {1} / {2}", handlerClass, webModule.getJarLocation(), webModule.getFile().getName()); + // Deliberately still fatal, unlike the servlet/filter/listener sites above: + // a handler chain silently missing a handler would leave the endpoint + // running with a different (weaker) contract than declared, e.g. dropping + // a security or logging handler, rather than just disabling one component. throw new OpenEJBException("Unable to load webservice handler class: " + handlerClass, e); } } diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/WsDeployer.java b/container/openejb-core/src/main/java/org/apache/openejb/config/WsDeployer.java index 476c35a587c..a445c432762 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/WsDeployer.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/WsDeployer.java @@ -146,8 +146,19 @@ private void processPorts(final WebModule webModule) throws OpenEJBException { continue; } + // TOMEE-4642: this runs for every servlet, not just webservice endpoints, so a servlet + // class the war does not package must not fail the whole deployment here either. + // NoClassDefFoundError is an Error, so the catch below would not cover it. + final Class clazz; + try { + clazz = webModule.getClassLoader().loadClass(className); + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + logger.warning("Unable to load servlet class: " + className + " for web module " + + webModule.getJarLocation() + ", skipping webservice detection for it", e); + continue; + } + try { - final Class clazz = webModule.getClassLoader().loadClass(className); if (JaxWsUtils.isWebService(clazz)) { // add servlet mapping if not already declared ServletMapping servletMapping = servletMappings.get(servlet.getServletName()); @@ -231,7 +242,8 @@ private void processPorts(final WebModule webModule) throws OpenEJBException { } } } catch (final Exception e) { - throw new OpenEJBException("Unable to load servlet class: " + className, e); + // the class resolved fine, so this is a genuine webservice configuration problem + throw new OpenEJBException("Unable to configure webservice for servlet class: " + className, e); } } } diff --git a/container/openejb-core/src/test/java/org/apache/openejb/config/AnnotationDeployerTest.java b/container/openejb-core/src/test/java/org/apache/openejb/config/AnnotationDeployerTest.java index 4f1dda0ea7e..5cd18d21b42 100644 --- a/container/openejb-core/src/test/java/org/apache/openejb/config/AnnotationDeployerTest.java +++ b/container/openejb-core/src/test/java/org/apache/openejb/config/AnnotationDeployerTest.java @@ -20,6 +20,7 @@ import org.apache.openejb.assembler.classic.AppInfo; import org.apache.openejb.assembler.classic.Assembler; import org.apache.openejb.assembler.classic.ClientInfo; +import org.apache.openejb.assembler.classic.WebAppInfo; import org.apache.openejb.jee.AssemblyDescriptor; import org.apache.openejb.jee.ConfigProperty; import org.apache.openejb.jee.Connector; @@ -85,6 +86,7 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -536,6 +538,45 @@ public void missingServletFilterAndListenerClassesDoNotFailDeployment() throws E assertEquals(1, webModule.getWebApp().getListener().size()); } + /** + * TOMEE-4642: same as above, but driven through the whole deployer chain rather than + * AnnotationDeployer alone. WsDeployer is part of that chain whenever wsdl4j is on the + * classpath (Plus, Plume, openejb-standalone) and loads every servlet class before testing + * whether it is a webservice, so it used to fail the deployment on those distributions even + * with AnnotationDeployer fixed. + */ + @Test + public void missingServletClassDoesNotFailFullConfiguration() throws Exception { + final WebApp webApp = new WebApp(); + webApp.setContextRoot("/"); + webApp.setId("web"); + webApp.setVersion("2.5"); + + final Servlet servlet = new Servlet(); + servlet.setServletName("TestServlet1"); + servlet.setServletClass("org.apache.openejb.config.missing.TestServlet1"); + webApp.getServlet().add(servlet); + + final Filter filter = new Filter(); + filter.setFilterName("AddFilterString"); + filter.setFilterClass("org.apache.openejb.config.missing.AddFilterString"); + webApp.getFilter().add(filter); + + final Listener listener = new Listener(); + listener.setListenerClass("org.apache.openejb.config.missing.MissingListener"); + webApp.getListener().add(listener); + + final WebModule webModule = new WebModule(webApp, webApp.getContextRoot(), + Thread.currentThread().getContextClassLoader(), "myapp", webApp.getId()); + webModule.setFinder(new AnnotationFinder(new ClassesArchive()).link()); + + final WebAppInfo webAppInfo = new ConfigurationFactory().configureApplication(webModule); + + assertNotNull(webAppInfo); + assertEquals(1, webAppInfo.servlets.size()); + assertEquals("TestServlet1", webAppInfo.servlets.iterator().next().servletName); + } + @Test public void findRestClasses() throws Exception { final WebApp webApp = new WebApp(); From a6e030785ef31b8e31bcab50fe4a07d0debf2571 Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Tue, 28 Jul 2026 21:31:10 +0200 Subject: [PATCH 3/4] Fix off-by-one MessageFormat placeholders in AnnotationDeployer log messages These logger.debug calls pass three arguments but start numbering their placeholders at {1}, so the first argument - the class name that could not be loaded, which is the useful part - was never rendered. Covers the remaining occurrences after the ones touched by TOMEE-4642, so all 12 sites in this file are now consistent. --- .../apache/openejb/config/AnnotationDeployer.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java b/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java index e2ee48eecdb..cb2e7611053 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java @@ -2016,7 +2016,7 @@ public ClientModule deploy(final ClientModule clientModule) throws OpenEJBExcept buildAnnotatedRefs(client, annotationFinder, classLoader); } catch (final ClassNotFoundException | NoClassDefFoundError e) { - logger.debug("Could not load main class {1} for client module {2} / {3}", + logger.debug("Could not load main class {0} for client module {1} / {2}", className, clientModule.getJarLocation(), clientModule.getFile().getName()); /* @@ -2041,7 +2041,7 @@ public ClientModule deploy(final ClientModule clientModule) throws OpenEJBExcept clazz = classLoader.loadClass(className); remoteClients.add(clazz); } catch (final ClassNotFoundException | NoClassDefFoundError e) { - logger.debug("Could not load RemoteClient class {1} for client module {2} / {3}", + logger.debug("Could not load RemoteClient class {0} for client module {1} / {2}", className, clientModule.getJarLocation(), clientModule.getFile().getName()); throw new OpenEJBException("Unable to load RemoteClient class: " + className, e); @@ -2058,7 +2058,7 @@ public ClientModule deploy(final ClientModule clientModule) throws OpenEJBExcept try { clazz = classLoader.loadClass(className); } catch (final ClassNotFoundException | NoClassDefFoundError e) { - logger.debug("Could not load LocalClient class {1} for client module {2} / {3}", + logger.debug("Could not load LocalClient class {0} for client module {1} / {2}", className, clientModule.getJarLocation(), clientModule.getFile().getName()); throw new OpenEJBException("Unable to load LocalClient class: " + className, e); } @@ -2189,7 +2189,7 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { clazz = classLoader.loadClass(application); classes.add(clazz); } catch (final ClassNotFoundException | NoClassDefFoundError e) { - logger.debug("Could not load rest Application class {1} for module {2} / {3}", + logger.debug("Could not load rest Application class {0} for module {1} / {2}", application, webModule.getJarLocation(), webModule.getFile().getName()); throw new OpenEJBException("Unable to load Application class: " + application, e); } @@ -2365,7 +2365,7 @@ public WebModule deploy(final WebModule webModule) throws OpenEJBException { final Class clazz = classLoader.loadClass(tagClass); classes.add(clazz); } catch (final ClassNotFoundException | NoClassDefFoundError e) { - logger.debug("Could not load tag class {1} for web module {2} / {3}", + logger.debug("Could not load tag class {0} for web module {1} / {2}", tagClass, webModule.getJarLocation(), webModule.getFile().getName()); logger.error("Unable to load tag library tag class: " + tagClass); } @@ -2949,7 +2949,7 @@ public EjbModule deploy(final EjbModule ejbModule) throws OpenEJBException { try { clazz = classLoader.loadClass(realClassName(interceptor.getInterceptorClass())); } catch (final ClassNotFoundException e) { - logger.debug("Could not load interceptor class {1} for enterprise beans module {2} / {3}", + logger.debug("Could not load interceptor class {0} for enterprise beans module {1} / {2}", interceptor.getInterceptorClass(), ejbModule.getJarLocation(), ejbModule.getFile().getName()); throw new OpenEJBException("Unable to load interceptor class: " + interceptor.getInterceptorClass(), e); @@ -5716,7 +5716,7 @@ private static void addRestClassesToScannedClasses(final WebModule webModule, fi clazz = classLoader.loadClass(className); classes.add(clazz); } catch (final ClassNotFoundException e) { - logger.debug("Could not load REST class {1} for web module {2} / {3}", + logger.debug("Could not load REST class {0} for web module {1} / {2}", className, webModule.getJarLocation(), webModule.getFile().getName()); throw new OpenEJBException("Unable to load REST class: " + className, e); From 70938f47e87f632cebbba06e9560c2ea455e963f Mon Sep 17 00:00:00 2001 From: Markus Jung Date: Tue, 28 Jul 2026 21:32:41 +0200 Subject: [PATCH 4/4] TOMEE-4642 - Don't let a missing listener class break LightweightWebAppBuilder Now that the deployer no longer rejects a web module naming a listener class the war does not package, that class name reaches LightweightWebAppBuilder, where loadClass threw a raw ClassNotFoundException in the middle of createApplication - worse than the OpenEJBException callers used to get. Skip the listener that cannot be loaded, logging it at error level, so the failure stays local to that listener as it does in the deployer. --- .../apache/openejb/web/LightweightWebAppBuilder.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/container/openejb-core/src/main/java/org/apache/openejb/web/LightweightWebAppBuilder.java b/container/openejb-core/src/main/java/org/apache/openejb/web/LightweightWebAppBuilder.java index 82afeef1719..37e0c446c6b 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/web/LightweightWebAppBuilder.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/web/LightweightWebAppBuilder.java @@ -182,7 +182,16 @@ public void deployWebApps(final AppInfo appInfo, final ClassLoader appClassLoade // listeners for (final ListenerInfo listener : webAppInfo.listeners) { - final Class clazz = webContext.getClassLoader().loadClass(listener.classname); + final Class clazz; + try { + clazz = webContext.getClassLoader().loadClass(listener.classname); + } catch (final ClassNotFoundException | NoClassDefFoundError e) { + // TOMEE-4642: a listener class the war does not package is reported by the + // deployer and must not abort the rest of the application here either. + LOGGER.error("Unable to load listener class: " + listener.classname + + " for web application " + webAppInfo.contextRoot, e); + continue; + } final Object instance = webContext.newInstance(clazz); if (ServletContextListener.class.isInstance(instance)) { switchServletContextIfNeeded(sce.getServletContext(), new Runnable() {