"The servlet context has already been initialized" error in Application.log of Undertow deployments
Description
Environment
Activity
Brad Wood 8 April 2025 at 16:39
Thanks for the info. I actually had seen that ticket the other day, but the comment on it just said “log is with level INFO” which indicated the fix was simply to remove the log message, not actually fix it. Since I had linked someone in Slack to this ticket, I just wanted to clarify that the Servlet spec does indeed support Undertow's behavior.
Using the destroy()
method in the Servlet to shutdown Lucee is a much better approach for sure.
Zac Spitzer 8 April 2025 at 06:35
this was already addressed in 6.2.0 as per the linked task
https://github.com/lucee/Lucee/commit/18328cdab9328125c7bb9d864bc2bc8b92260625
Brad Wood 8 April 2025 at 02:48
This came up again today in Slack. To answer your question, the servlet spec does state that the servletcontext will be initialized BEFORE any servlets are created. Firstly, the ServletConfig
object (which contains the ServletContext
object) is passed to the servlet’s init() method, meaning they are already created. And secondly, this section of the servlet spec:
https://jakarta.ee/specifications/servlet/5.0/jakarta-servlet-spec-5.0#web-application-deployment
states that the ServletContextListener
’s will have their contextInitialized()
method called before filters and servlets are created.
And then finally the java docs for the addListener()
method state that it will throw an IllegalStateException
“if this ServletContext has already been initialized”.
https://jakarta.ee/specifications/servlet/5.0/apidocs/jakarta/servlet/servletcontext#addListener(T)
So basically, it is illegal to try and add listeners to the servlet context in the init of any servlet as it’s too late in the process. The methods exist because there are other lifecycle ways to accomplish this before the servlets are created. Undertow is following the spec, and Tomcat seemingly is not. Lucee needs to use a <listener>
declaration in the web.xml
or a service loader registration to be able to contextDestroyed()
listener prior to the servlet being created.
Michael Offner 6 May 2022 at 08:59
@Brad Wood Only because undertow throws this exception does not mean that is part of the server specification. like is said other servlet engines are fine with it.
Again when i cannot call that method as part of the init process of the servlet, why does that method exist in the ServletContext interface in the first place and does not define any limitation in it’s javadoc? “Lucee is clearly breaking the servlet spec here“ show me that spec, i don’t care about an exception message from undertow, they don’t define the spec.
Believe me there are better reasons than this to update the loader, i have to go through a lot of pain to avoid it. But not changing the loader is a very strict rule i will not break because of this, when we open that can of worms we have soon 10 different version of the loader we have to test against. I for sure will not do that to support a listener that is not really used. If we wanna use that listener in the future i will then find a solution for this, atm i can live with this limitation.
As long it is not planned to expose that listener in any way, CommandBox can not benefit from that feature anyway and there are no plans to do so. In addition you start the servlet engine yourself in commandbox, so you can easily at your own listener independent from Lucee and why should undertow use Lucee to add a listener to undertow that makes no sense at all.
What loader changes you are waiting for years? Best open or point to tickets we can discuss, so far i always have find ways to avoid a loader change and it is safe to say that i’m writing most of the code that interacts with the loader in existing. But sure if there are good reasons to update the loader let’s do it. But have in mind we focus to remove functionality from the loader and not add. So we are only talking about adding/extending interfaces, definitions and annotations. There is code i would like to see gone in the loader, like most of the “Util“ class.
i will open a discussion in dev about this.
Brad Wood 5 May 2022 at 17:27
I put that info in the ticket description:
IllegalStateException - if this ServletContext has already been initialized
That means you can’t call this method after the servlet context is already initialized. I’ll ping the Undertow developers and ask them if there is a way to make this work. I do agree it’s a bit of a catch 22 if the init of our servlet is already after the context is initialized.
we do not make any changes to the Lucee loader, unless we switch from one major version to another.
This is a good reason why Lucee 6 needs to update the loader, but regardless, I can see not making BREAKING changes to the loader, but why can’t we add a backwards compatible feature? It’s not going to affect older core versions.
But with Lucee 6 we decided to make no change to the loader, because it was not necessary.
It seems this ticket is proving that assumption wrong There are actually several loader changes I was hoping to see in Lucee 6 which I’ve been waiting years for.
But like i said, the Listener registered in that case is not used anyway, so no harm done.
I’d prefer to find a way for CommandBox/undertow servers to be able to benefit from whatever this listener does. Otherwise, why does it exist.
Details
Details
Assignee
Reporter
Priority
New Issue warning screen
Before you create a new Issue, please post to the mailing list first https://dev.lucee.org
Once the issue has been verified, one of the Lucee team will ask you to file an issue
This has been happening for a while so I'm not sure when it started. It doesn't seem to cause any issues, but it does fill the server context's Application.log with errors.
Lucee deployments on CommandBox/JBoss Undertow will log this error every time the server is restarted in the Application.log
ERROR","main","08/28/2020","13:58:54","add-event-listener","UT010041: The servlet context has already been initialized, you can only call this method from a ServletContainerInitializer or a ServletContextListener;UT010041: The servlet context has already been initialized, you can only call this method from a ServletContainerInitializer or a ServletContextListener;java.lang.IllegalStateException: UT010041: The servlet context has already been initialized, you can only call this method from a ServletContainerInitializer or a ServletContextListener at io.undertow.servlet.spec.ServletContextImpl.ensureNotInitialized(ServletContextImpl.java:960) at io.undertow.servlet.spec.ServletContextImpl.addListener(ServletContextImpl.java:715) at lucee.runtime.engine.CFMLEngineImpl.addEventListener(CFMLEngineImpl.java:776) at lucee.runtime.engine.CFMLEngineImpl.addServletConfig(CFMLEngineImpl.java:723) at lucee.loader.engine.CFMLEngineWrapper.addServletConfig(CFMLEngineWrapper.java:87) at lucee.loader.engine.CFMLEngineFactory.getInstance(CFMLEngineFactory.java:211) at lucee.loader.servlet.LuceeServlet.init(LuceeServlet.java:42) at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:117) at io.undertow.servlet.core.ManagedServlet$DefaultInstanceStrategy.start(ManagedServlet.java:305) at io.undertow.servlet.core.ManagedServlet.createServlet(ManagedServlet.java:145) at io.undertow.servlet.core.DeploymentManagerImpl$2.call(DeploymentManagerImpl.java:585) at io.undertow.servlet.core.DeploymentManagerImpl$2.call(DeploymentManagerImpl.java:556) at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:42) at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) at io.undertow.servlet.core.DeploymentManagerImpl.start(DeploymentManagerImpl.java:598) at runwar.Server.startServer(Server.java:552) at runwar.Start.main(Start.java:123)
There are three versions of the error message, one for the CFMLService, the LuceeServlet, and the RESTServlet.
The exception itself is coming from the servlet container Undertow when Lucee tries to call the addListener() method on the ServletContext. Undertow's code does not allow listeners to be added to the servlet context after the context has been initialized. Looking at the javadocs for the servlet spec, this is correct
https://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html#addListener(T)
The addListener() method should throw
so it appears what Lucee is doing is illegal per the spec.