ebc149
ebc149

Reputation: 44

Is there a way for passing multipart config to auto configured JSP Servlet on jboss eap8 with undertow, spring-web-6.1.9?

The problem

I am migrating from eap7 to 8 (also from javax to jakarta), and have a request with MultipartFile. My app is using jsp. File gets to the server, in controller it is processed (not written) then multipart resolver tries to clean up multipart, during which it expects (with jsp servlet) the multipart configuration to be present. This config is present on my declared servlet but not on the auto generated jsp servlet.

This is jsp framgent that triggers my controller:

<form:form id="myFancyForm${myEntity.id}" method="POST"
           action="addStuff?${_csrf.parameterName}=${_csrf.token}"
           enctype="multipart/form-data" class="skip">
    <input id="someId" type="hidden" name="someId" class="myIdClass"
           value="${myEntity.id}"/>

    <div class="my_fancy_button" id="SomeButtonId${myEntity.id}">
        <input id="file" name="file" type="file" class="some_class_css"
               onchange="checkFileSizeAndSubmit(this, '#myFancyForm${myEntity.id}');"/>
    </div>
</form:form>

Controller:

    @RequestMapping(value = "/addStuff", method = RequestMethod.POST)
    public String addStuff(Model model, @RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
           doSomeReadLogicWithFile(file);
           return "myJspPage";
        }
    }

When return "myJspPage" is reached, the org.springframework.web.multipart.support.StandardServletMultipartResolver kicks in with method cleanupMultipart and it does so for each servlet. My main servlet (declared in web.xml) goes through like a charm (I added xml config for multipart), but then, auto-generated jsp servlet reaches the code io.undertow.servlet.spec.HttpServletRequestImpl verifyMultipartServlet, tries to get multipart config from servlet, gets null, and raises throw UndertowServletMessages.MESSAGES.multipartConfigNotPresent() exception

The stack then looks like this:


2024-07-17 12:15:05,436 WARN  [org.springframework.web.multipart.support.StandardServletMultipartResolver] (default task-53) Failed to perform cleanup of multipart items: java.lang.IllegalStateException: UT010057: multipart config was not present on Servlet
    at [email protected]//io.undertow.servlet.spec.HttpServletRequestImpl.verifyMultipartServlet(HttpServletRequestImpl.java:567)
    at [email protected]//io.undertow.servlet.spec.HttpServletRequestImpl.getParts(HttpServletRequestImpl.java:556)
    at [email protected]//jakarta.servlet.http.HttpServletRequestWrapper.getParts(HttpServletRequestWrapper.java:306)
    at [email protected]//jakarta.servlet.http.HttpServletRequestWrapper.getParts(HttpServletRequestWrapper.java:306)
    at [email protected]//jakarta.servlet.http.HttpServletRequestWrapper.getParts(HttpServletRequestWrapper.java:306)
    at [email protected]//jakarta.servlet.http.HttpServletRequestWrapper.getParts(HttpServletRequestWrapper.java:306)
    at deployment.my-app-web.war//org.springframework.web.multipart.support.StandardServletMultipartResolver.cleanupMultipart(StandardServletMultipartResolver.java:122)
    at deployment.my-app-web.war//org.springframework.web.servlet.DispatcherServlet.cleanupMultipart(DispatcherServlet.java:1268)
    at deployment.my-app-web.war//org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1125)
    at deployment.my-app-web.war//org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
    at deployment.my-app-web.war//org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
    at deployment.my-app-web.war//org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)
    at [email protected]//jakarta.servlet.http.HttpServlet.service(HttpServlet.java:547)
    at deployment.my-app-web.war//org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
    at [email protected]//jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)
    at [email protected]//io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
    at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
    at deployment.my-app-web.war//my.app.packaging.filters.HttpHeadFilter.doFilter(HttpHeadFilter.java:43)
    at [email protected]//io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:67)
    at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at deployment.my-app-web.war//my.app.packaging.filters.MyAppSecurityFilter.doFilter(MyAppSecurityFilter.java:28)
    at [email protected]//io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:67)
    at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:365)
    at deployment.my-app-web.war//org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:100)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)
    at deployment.my-app-web.war//org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:131)
    at deployment.my-app-web.war//org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:85)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:179)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:181)
    at deployment.my-app-web.war//org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227)
    at deployment.my-app-web.war//org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107)
    at deployment.my-app-web.war//org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:131)
    at deployment.my-app-web.war//org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
    at deployment.my-app-web.war//org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
    at deployment.my-app-web.war//org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62)
    at deployment.my-app-web.war//org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:151)
    at deployment.my-app-web.war//org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:129)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82)
    at deployment.my-app-web.war//org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42)
    at deployment.my-app-web.war//org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233)
    at deployment.my-app-web.war//org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191)
    at deployment.my-app-web.war//org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:352)
    at deployment.my-app-web.war//org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:268)
    at [email protected]//io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:67)
    at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at deployment.my-app-web.war//org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at deployment.my-app-web.war//org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at [email protected]//io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:67)
    at [email protected]//io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at [email protected]//io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
    at [email protected]//io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at [email protected]//io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
    at [email protected]//io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at org.wildfly.security.elytron-web.undertow-server@4.0.1.Final-redhat-00001//org.wildfly.elytron.web.undertow.server.ElytronRunAsHandler.lambda$handleRequest$1(ElytronRunAsHandler.java:68)
    at [email protected]//org.wildfly.security.auth.server.FlexibleIdentityAssociation.runAsFunctionEx(FlexibleIdentityAssociation.java:103)
    at [email protected]//org.wildfly.security.auth.server.Scoped.runAsFunctionEx(Scoped.java:161)
    at [email protected]//org.wildfly.security.auth.server.Scoped.runAs(Scoped.java:73)
    at org.wildfly.security.elytron-web.undertow-server@4.0.1.Final-redhat-00001//org.wildfly.elytron.web.undertow.server.ElytronRunAsHandler.handleRequest(ElytronRunAsHandler.java:67)
    at [email protected]//io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
    at [email protected]//io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117)
    at [email protected]//io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
    at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at [email protected]//io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    at [email protected]//io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    at [email protected]//io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
    at org.wildfly.security.elytron-web.undertow-server-servlet@4.0.1.Final-redhat-00001//org.wildfly.elytron.web.undertow.server.servlet.CleanUpHandler.handleRequest(CleanUpHandler.java:38)
    at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at [email protected]//org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at [email protected]//org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
    at [email protected]//io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52)
    at [email protected]//io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:276)
    at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
    at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:132)
    at [email protected]//io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
    at [email protected]//io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
    at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1430)
    at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1430)
    at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1430)
    at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1430)
    at [email protected]//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1430)
    at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:256)
    at [email protected]//io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:101)
    at [email protected]//io.undertow.server.Connectors.executeRootHandler(Connectors.java:393)
    at [email protected]//io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:859)
    at [email protected]//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
    at [email protected]//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990)
    at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
    at [email protected]//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
    at [email protected]//org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1282)
    at java.base/java.lang.Thread.run(Thread.java:840)

What I tried

I checked if I can pass multipart config through standalone.xml via <jsp-config/> but looked into the code, and org.wildfly.extension.undertow.JSPConfig class does not has such fields.

Then tried to override jsp servlet with <jsp-config/> removed from standalone.xml and inside web.xml with such entries

    <servlet>
        <servlet-name>jsp</servlet-name>
        <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <multipart-config>
            <max-file-size>10485760</max-file-size>
            <max-request-size>20971520</max-request-size>
            <file-size-threshold>5242880</file-size-threshold>
        </multipart-config>
    </servlet>
    <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jsp</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>jsp</servlet-name>
        <url-pattern>*.jspx</url-pattern>
    </servlet-mapping>

But such config does not work, as I should at least call io.undertow.jsp.JspServletBuilder#setupDeployment during server startup to register tag libs, which I would rather not do.

Last (and my biggest disapointment) was this part of servlets configuration: class io.undertow.servlet.core.ManagedServlet#ManagedServlet in constructor calls method setupMultipart. When multipart config is not present on servlet that is being initialized it tries to get it from some defaults

if(multipartConfig == null) {
  multipartConfig = servletContext.getDeployment().getDeploymentInfo().getDefaultMultipartConfig();
}

Unfortunately a setter to this field in class io.undertow.servlet.api.DeploymentInfo is not called when object is being initialized in org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService

What I expect

To pass multipart configuration to auto generated jsp servlet.

Upvotes: 1

Views: 264

Answers (0)

Related Questions