Skip to content

TOMEE-4642 - Don't fail deployment when a servlet/filter/listener class is missing#2848

Open
jungm wants to merge 1 commit into
mainfrom
claude/tomee-4642-fix-23d281
Open

TOMEE-4642 - Don't fail deployment when a servlet/filter/listener class is missing#2848
jungm wants to merge 1 commit into
mainfrom
claude/tomee-4642-fix-23d281

Conversation

@jungm

@jungm jungm commented Jul 23, 2026

Copy link
Copy Markdown
Member

What

When a war's web.xml or annotations name a servlet, filter or listener class that is not packaged in the war, AnnotationDeployer.ProcessAnnotatedBeans.deploy(WebModule) rethrew the ClassNotFoundException/NoClassDefFoundError as an OpenEJBException. That propagates out through ConfigurationFactory.configureApplication and 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 WsDeployer throw 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 MessageFormat placeholder indices ({1}{2}{3}{0}{1}{2}) in the four related logger.debug calls, 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 (RegistrationTests naming filter AddFilterString; DefaultMappingTests naming servlet TestServlet1). Removing the corresponding entries from runner-standalone/exclusions/servlet.txt in 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

…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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant