Hey Folks,

Tomcat version: 10.1.26
JDK:                   "21.0.3" 2024-04-16 LTS
OS:                     Macos Sonoma 14.5

I'm looking for clarification on what annotations will be supported when
calling ServletContext.createServlet() after the context has been
initialized.

Some background; I have a tool that inspects a web application where for
each discovered Servlet (either declared in the {web,web-fragment}.xml or
via annotations) will wrap that Servlet which performs additional logic
during init and service before calling through to the actual delegate that
we wrapped.  When this wrapper's init() is first called by the container,
we will instantiate the delegate using ServletContext.createServlet().  The
Servlet 6.0 specification states the following:

-----------------------------------------------------
4.4.1.5. <T extends Servlet> T createServlet(Class<T> clazz)

This method instantiates the given Servlet class. The method must support
all the annotations applicable to servlets except @WebServlet. The returned
Servlet instance may be further customized before it is registered with the
ServletContext via a call to addServlet(String, Servlet) as defined above.
The given Servlet class must define a zero argument constructor, which is
used to instantiate it.
-----------------------------------------------------

This works fine for cases such as @Inject or @Resource, however, I've found
the behavior in the case of @ServletSecurity to differ between containers.
For example, Tomcat, Jetty, and Wildlfy appear to ignore @ServletSecurity
when calling createServlet() from the wrappers init() method.

However, section 13.4.1 has the following constraint on @ServletSecurity:
-----------------------------------------------------
When metadata-complete=true is defined for a portable deployment
descriptor, the @ServletSecurity annotation does not apply to any of the
url-patterns mapped to (any servlet mapped to) the annotated class in the
deployment descriptor.
-----------------------------------------------------

In my test case, the descriptor containing the original Servlet has the
metadata-complete attribute set to true.  If I set it to false, I find that
the security constraints are applied, but only when running with Jetty;
Tomcat and Wildfly continue to ignore the desired constraints.

Going back to section 4.4 for a moment which states:
-----------------------------------------------------
The following methods are provided on the ServletContext interface to
enable programmatic definition of servlets, filters and the url pattern(s)
that they map to. These methods can only be called during the
initialization of the application either from the contexInitialized method
of a ServletContextListener implementation or from the onStartup method of
a ServletContainerInitializer implementation.
------------------------------------------------------

The javadocs for ServletContext.createServlet() don't impose any
restrictions on when it may be called unlike the javadocs for the various
dynamic registration methods.

I'm curious to see what the devs lurking here think.  What should the
behavior be?  It seems like the spec could use some tightening here either
way.

Thanks for your time.

Reply via email to