Affects: \5.0 and newer, latest test 5.3.0-RC2
To reproduce:
1) Download a WildFly https://www.wildfly.org/downloads/ unzip in a folder of your choice
2) Create a simple spring initializr project, time of writing this issue 2.4.0M4; Packaging WAR; Java 8. One Dependency Spring Web.
3) Run the build and create the WAR file
4) Copy the result out of 3 to
<logger category="org.jboss.as.ee">
<level name="TRACE"/>
</logger>
6) Start the server, observe
The following classes are missing a default constructor, which was removed in 5.0
- org.springframework.http.server.reactive.ServletServerHttpResponse$ResponseAsyncListener
- org.springframework.http.server.reactive.ServletServerHttpRequest$RequestAsyncListener
- org.springframework.http.server.reactive.ServletHttpHandlerAdapter$HandlerResultAsyncListener
- org.springframework.http.server.ServletServerHttpAsyncRequestControl
- org.springframework.web.context.request.async.StandardServletAsyncWebRequest
Please check, whether you can add safely a default constructor
Warnings in server.log
2020-10-22 10:59:04,188 WARN [org.jboss.as.ee] (MSC service thread 1-3) WFLYEE0007: Not installing optional component org.springframework.http.server.reactive.ServletServerHttpResponse$ResponseAsyncListener due to an exception (enable DEBUG log level to see the cause)
2020-10-22 10:59:04,188 DEBUG [org.jboss.as.ee] (MSC service thread 1-3) Not installing optional component org.springframework.http.server.reactive.ServletServerHttpResponse$ResponseAsyncListener due to an exception: org.jboss.as.server.deployment.DeploymentUnitProcessingException: WFLYEE0048: Could not find default constructor for class org.springframework.http.server.reactive.ServletServerHttpResponse$ResponseAsyncListener
at org.jboss.as.ee.component.DefaultInterceptorConfigurator.configure(DefaultInterceptorConfigurator.java:92)
at org.jboss.as.ee.component.deployers.EEModuleConfigurationProcessor.deploy(EEModuleConfigurationProcessor.java:92)
at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:144)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701)
at org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1378)
at java.lang.Thread.run(Thread.java:748)
2020-10-22 10:59:04,188 DEBUG [org.jboss.as.ee] (MSC service thread 1-3) Configuring component class: org.springframework.http.server.reactive.ServletHttpHandlerAdapter$HandlerResultAsyncListener named org.springframework.http.server.reactive.ServletHttpHandlerAdapter$HandlerResultAsyncListener
2020-10-22 10:59:04,188 WARN [org.jboss.as.ee] (MSC service thread 1-3) WFLYEE0007: Not installing optional component org.springframework.http.server.reactive.ServletHttpHandlerAdapter$HandlerResultAsyncListener due to an exception (enable DEBUG log level to see the cause)
2020-10-22 10:59:04,188 DEBUG [org.jboss.as.ee] (MSC service thread 1-3) Not installing optional component org.springframework.http.server.reactive.ServletHttpHandlerAdapter$HandlerResultAsyncListener due to an exception: org.jboss.as.server.deployment.DeploymentUnitProcessingException: WFLYEE0048: Could not find default constructor for class org.springframework.http.server.reactive.ServletHttpHandlerAdapter$HandlerResultAsyncListener
at org.jboss.as.ee.component.DefaultInterceptorConfigurator.configure(DefaultInterceptorConfigurator.java:92)
at org.jboss.as.ee.component.deployers.EEModuleConfigurationProcessor.deploy(EEModuleConfigurationProcessor.java:92)
at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:144)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701)
at org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1378)
at java.lang.Thread.run(Thread.java:748)
2020-10-22 10:59:04,198 DEBUG [org.jboss.as.ee] (MSC service thread 1-3) Configuring component class: org.springframework.http.server.ServletServerHttpAsyncRequestControl named org.springframework.http.server.ServletServerHttpAsyncRequestControl
2020-10-22 10:59:04,198 WARN [org.jboss.as.ee] (MSC service thread 1-3) WFLYEE0007: Not installing optional component org.springframework.http.server.ServletServerHttpAsyncRequestControl due to an exception (enable DEBUG log level to see the cause)
2020-10-22 10:59:04,198 DEBUG [org.jboss.as.ee] (MSC service thread 1-3) Not installing optional component org.springframework.http.server.ServletServerHttpAsyncRequestControl due to an exception: org.jboss.as.server.deployment.DeploymentUnitProcessingException: WFLYEE0048: Could not find default constructor for class org.springframework.http.server.ServletServerHttpAsyncRequestControl
at org.jboss.as.ee.component.DefaultInterceptorConfigurator.configure(DefaultInterceptorConfigurator.java:92)
at org.jboss.as.ee.component.deployers.EEModuleConfigurationProcessor.deploy(EEModuleConfigurationProcessor.java:92)
at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:144)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701)
at org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1378)
at java.lang.Thread.run(Thread.java:748)
2020-10-22 10:59:04,198 DEBUG [org.jboss.as.ee] (MSC service thread 1-3) Configuring component class: org.springframework.web.context.request.async.StandardServletAsyncWebRequest named org.springframework.web.context.request.async.StandardServletAsyncWebRequest
2020-10-22 10:59:04,198 WARN [org.jboss.as.ee] (MSC service thread 1-3) WFLYEE0007: Not installing optional component org.springframework.web.context.request.async.StandardServletAsyncWebRequest due to an exception (enable DEBUG log level to see the cause)
2020-10-22 10:59:04,198 DEBUG [org.jboss.as.ee] (MSC service thread 1-3) Not installing optional component org.springframework.web.context.request.async.StandardServletAsyncWebRequest due to an exception: org.jboss.as.server.deployment.DeploymentUnitProcessingException: WFLYEE0048: Could not find default constructor for class org.springframework.web.context.request.async.StandardServletAsyncWebRequest
at org.jboss.as.ee.component.DefaultInterceptorConfigurator.configure(DefaultInterceptorConfigurator.java:92)
at org.jboss.as.ee.component.deployers.EEModuleConfigurationProcessor.deploy(EEModuleConfigurationProcessor.java:92)
at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:144)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701)
at org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1378)
at java.lang.Thread.run(Thread.java:748)
2020-10-22 10:59:04,198 DEBUG [org.jboss.as.ee] (MSC service thread 1-3) Configuring component class: org.springframework.http.server.reactive.ServletServerHttpRequest$RequestAsyncListener named org.springframework.http.server.reactive.ServletServerHttpRequest$RequestAsyncListener
2020-10-22 10:59:04,206 WARN [org.jboss.as.ee] (MSC service thread 1-3) WFLYEE0007: Not installing optional component org.springframework.http.server.reactive.ServletServerHttpRequest$RequestAsyncListener due to an exception (enable DEBUG log level to see the cause)
2020-10-22 10:59:04,206 DEBUG [org.jboss.as.ee] (MSC service thread 1-3) Not installing optional component org.springframework.http.server.reactive.ServletServerHttpRequest$RequestAsyncListener due to an exception: org.jboss.as.server.deployment.DeploymentUnitProcessingException: WFLYEE0048: Could not find default constructor for class org.springframework.http.server.reactive.ServletServerHttpRequest$RequestAsyncListener
at org.jboss.as.ee.component.DefaultInterceptorConfigurator.configure(DefaultInterceptorConfigurator.java:92)
at org.jboss.as.ee.component.deployers.EEModuleConfigurationProcessor.deploy(EEModuleConfigurationProcessor.java:92)
at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:144)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701)
at org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1378)
at java.lang.Thread.run(Thread.java:748)
Comment From: bclozel
This does not fail the deployment, and is a logging behavior specific to Wildfly.
Have you seen this comment and this issue?
The point about the Servlet spec is a bit unclear: this specific behavior does not happen with other Servlet containers which are also spec compliant. Maybe they just ignore this possible problem and don't log it?
Without any new information from your side @bunckelvhv, this issue is likely to be closed as a duplicate of #15304.
Comment From: bunckelvhv
Thanks for your fast feedback and the useful RedHat issue. I don't think the Servlet Spec or the AsyncListener API doc forces one to provide a default constructor.
It took me some time to understand that not our application has a fault, which was my first guess. Second guess was a implementation fault.
Would it be possible to provide a fail safe default constructor? Maybe with a @Deprecated
"Compatibility only - please use XYZ Constructur" hint and link to this issue and the RedHat one?
Comment From: bclozel
Even if we reintroduce constructors for those classes in a deprecated fashion, we're likely to end up with hard to track problems as those constructors should never be used in the first place. See https://github.com/spring-projects/spring-framework/issues/15304#issuecomment-453403802
Balancing a hard to track problem in our codebase vs. an annoying but harmless WARN message during deployment on a particular Servlet container - I guess we're likely to stick to our decision in #15304. Keeping this open for now to check that with the team.
Comment From: bclozel
After chatting with the team, we agreed that the conclusion in #15304 still applies.
Checking that AsyncListener
implementations should have a default constructor in case they're used in the context of AsyncContext.createListener
is one thing - logging it as a failed component is another. We don't think this behavior is part of the spec. Introducing a default constructor there, even in a deprecated fashion, is likely to cause issues.
This call is making use of the default constructor but its deprecation status is completely hidden from the developer.
asyncContext.addListener(asyncContext.createListener(ResponseAsyncListener.class));
We could also consider the case where you're deploying a Spring MVC app (with the Servlet variant of that class), which happens to use the WebClient
from spring-webflux. You'd also get the reactive variant mentioned in this issue. Adding a default constructor there would prevent the WARN log, but instantiating this class in a MVC setup is not going to work.
The Wildfly team improved the situation a bit with the logging changes; I don't think we can make things better with a change in the Spring Framework codebase at this point.
Thanks for raising this issue!