TOMEE-4642 - Don't fail deployment when a servlet/filter/listener class is missing - #2848
TOMEE-4642 - Don't fail deployment when a servlet/filter/listener class is missing#2848jungm wants to merge 1 commit into
Conversation
…ss 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).
|
The direction is right and the codebase already agrees with you — But the reported bug is not actually fixed on half the distributions:
Consequently the test can't do the job it's meant to do:
Other things:
|
What
When a war's
web.xmlor annotations name a servlet, filter or listener class that is not packaged in the war,AnnotationDeployer.ProcessAnnotatedBeans.deploy(WebModule)rethrew theClassNotFoundException/NoClassDefFoundErroras anOpenEJBException. That propagates out throughConfigurationFactory.configureApplicationand aborts startup of the whole web context.This changes the servlet, filter and listener paths to log a warning and continue instead of failing.
Why
These
classLoader.loadClass(...)calls exist only to feed the annotation scanner. A class that cannot be loaded simply contributes nothing to scan — it should not bring the context down.The old behaviour was also internally inconsistent: the taglib-listener loop right below, and the servlet name-fallback case, already only logged and continued. Only the explicit-class servlet/filter/listener paths were fatal.
Jakarta Servlet 6.1 §2.3.1 ("Loading and Instantiation") permits servlet loading to be "delayed until the container determines the servlet is needed to service a request", so deferring an unresolved class rather than failing eagerly at deploy time is spec-compliant. If such a component is actually used, Tomcat still surfaces the missing class per-component.
The
WsDeployerthrow for webservice servlet classes was intentionally left as-is, since a WS endpoint genuinely cannot be built without its class.Also
Fixed off-by-one
MessageFormatplaceholder indices ({1}{2}{3}→{0}{1}{2}) in the four relatedlogger.debugcalls, which were dropping the first argument from the message.Testing
Added
AnnotationDeployerTest.missingServletFilterAndListenerClassesDoNotFailDeployment, using the class names from the ticket (TestServlet1,AddFilterString, plus a missing listener). Verified it is a real regression test: reverting the servlet fix makes it fail with exactly the reported error (OpenEJBException: Unable to load servlet class: ...TestServlet1), and it passes with the fix.This is the TomEE-side fix for the two Jakarta Servlet TCK deployments that triggered the abort (
RegistrationTestsnaming filterAddFilterString;DefaultMappingTestsnaming servletTestServlet1). Removing the corresponding entries fromrunner-standalone/exclusions/servlet.txtin the apache/tomee-tck harness and confirming both classes pass is a follow-up in that separate repo.Jira: https://issues.apache.org/jira/browse/TOMEE-4642
🤖 Generated with Claude Code