Sure, my web.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee";
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd";
         version="6.0">
    <display-name>Struts Blank</display-name>
      <!-- 1. Context Parameter para Log4j2 -->
    <context-param>
        <param-name>log4jConfiguration</param-name>
        <param-value>/WEB-INF/classes/log4j2.xml</param-value>
    </context-param>
    <filter>
        <filter-name>struts2</filter-name>

<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

I forgot also show my struts.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts
Configuration 6.0//EN"
    "https://struts.apache.org/dtds/struts-6.0.dtd";>
<struts>
     <constant name="struts.ui.theme" value="simple"/> <!-- En struts.xml
-->
     <constant name="struts.ui.templateDir" value="template"/>
     <constant name="struts.ui.templateSuffix" value="ftl"/>
     <constant name="struts.devMode" value="true"/>
     <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
     <constant name="struts.logging.fileUploadInterceptor" value="TRACE"/>
     <constant name="struts.logging.level" value="TRACE"/>
     <constant name="struts.multipart.parser"
value="mx.com.struts.action.DebugMultiPartRequest"/>  <!-- Using my custom
DebugMultiPartRequest -->

     <package name="default" extends="struts-default">

      <action name="">
   <result>/index.jsp</result>
</action>

<action name="hello" class="mx.com.struts.action.HelloAction">
          <result name="success">/success.jsp</result>
          <result name="error">/error.jsp</result>
        </action>

    </package>

</struts>

On the log I can see that I don't have file on my action:

2025-06-03 12:48:20 DEBUG ActionFileUploadInterceptor:200 - Found multipart
request: MultiPartRequestWrapper
2025-06-03 12:48:20 DEBUG ActionFileUploadInterceptor:179 - No files have
been uploaded/accepted

Now I can see is blocked!. I was reading that this message is normal on the
log:

2025-06-03 12:48:21 DEBUG DefaultAcceptedPatternsChecker:115 - Sets
accepted patterns to
[[\w+((\.\w+)|(\[\d+])|(\(\d+\))|(\['(\w-?|[\u4e00-\u9fa5]-?)+'])|(\('(\w-?|[\u4e00-\u9fa5]-?)+'\)))*]],
note this impacts the safety of your application!
2025-06-03 12:48:21 DEBUG StrutsUrlEncoder:38 - Using default encoding:
UTF-8
2025-06-03 12:48:21 DEBUG SecurityMemberAccess:142 - Checking access for
[target: mx.com.struts.action.HelloAction@4489b4fa, member: private
org.apache.struts2.dispatcher.multipart.UploadedFile
mx.com.struts.action.HelloAction.miLogo, property: miLogo]
2025-06-03 12:48:21 WARN  SecurityMemberAccess:174 - Access to non-public
[private org.apache.struts2.dispatcher.multipart.UploadedFile
mx.com.struts.action.HelloAction.miLogo] is blocked!
2025-06-03 12:48:21 DEBUG InstantiatingNullHandler:106 - Entering
nullPropertyValue [target=[mx.com.struts.action.HelloAction@4489b4fa,
org.apache.struts2.text.DefaultTextProvider@287a1ff7], property=miLogo]

As comment I changed file name as miLogo because I was trying use a
different name like upload.

Thanks for the support.

JMC


El lun, 2 jun 2025 a las 23:44, Zoran Avtarovski (<zo...@sparecreative.com>)
escribió:

> Hi Jesus,
>
> What does your web.xml look like with regards to the struts filters? We
> had a similar issue which was resolved by moving to the combined
> StrutsPrepareAndExecuteFilter. Sitemesh also played a part in our issue,
> but I think by what you are seeing it's worth trying.
>
> Z.
>
> On 1/6/2025 6:29 am, Jesus Moreno wrote:
> > Hi Lukasz, thanks for your appreciated comments.
> >
> > I would like to explain in more detail what we have done to try to find
> the
> > problem and solve it. Here the context:
> >
> > This is my environment:
> >
> > - Struts Version: 7.0.3
> > - Java Version: 17
> > - Servlet Container: Apache Tomcat 10.1.36
> > - Key Dependencies (pom):
> > - struts2-core:7.0.3
> > - struts2-convention-plugin:7.0.3
> > - struts2-json-plugin:7.0.3
> > - jakarta.servlet-api:5.0.0
> > - log4j-core:2.17.2
> > - Enforced exclusions: javax.servlet:*, javax.activation:*
> >
> > We've created a basic Maven project (standard archetype) with a simple
> file
> > upload form containing:
> >      - 4 regular text fields (working correctly with
> > @StrutsParameter(depth=0))
> >      - 1 file upload field (<input type="file" name="upload">)
> >
> > This is my basic jsp:
> >
> > <%@ page contentType="text/html; charset=UTF-8" %>
> > <%@ taglib prefix="s" uri="/struts-tags" %>
> > <!DOCTYPE html>
> > <html>
> > <head>
> >      <title>File upload result</title>
> > </head>
> > <body>
> > <h1>Hola Mundo desde la tierra...</h1>
> > <form action="hello" method="post" enctype="multipart/form-data">
> > <input type="text" name="name"/>
> > <input type="text" name="lastname"/>
> > <input type="text" name="gender"/>
> > <input type="text" name="age"/>
> >       <input type="file" name="*upload*"/>
> >       <input type="submit" value="Subir" />
> > </form>
> > </body>
> > </html>
> >
> > Expected Behavior:
> >
> > - When implementing UploadedFilesAware, the framework should:
> > - Detect multipart requests
> > - Process uploaded files through withUploadedFiles(List<UploadedFile>)
> > - Make files available to the action
> >
> > Where my action looks like:
> >
> > import org.apache.logging.log4j.LogManager;
> > import org.apache.logging.log4j.Logger;
> > import org.apache.struts2.ActionSupport;
> > import org.apache.struts2.action.UploadedFilesAware;
> > import org.apache.struts2.dispatcher.multipart.UploadedFile;
> > import org.apache.struts2.interceptor.parameter.StrutsParameter;
> >
> > public class HelloAction extends ActionSupport implements
> > UploadedFilesAware {
> >      private static final long serialVersionUID = 1L;
> >      private Logger logger = LogManager.getLogger(HelloAction.class);
> >
> >      private UploadedFile upload;
> >      private String uploadFileName;
> >      private String uploadContentType;
> >
> >      @StrutsParameter(depth = 0)
> >      public String name;
> >
> >      @StrutsParameter(depth = 0)
> >      public String lastname;
> >
> >      @StrutsParameter(depth = 0)
> >      public String gender;
> >
> >      @StrutsParameter(depth = 0)
> >      public String age;
> >
> >      @Override
> >      public String execute() {
> >      logger.info("Executing execute method..." + this.uploadFileName);
> >      return SUCCESS;
> >      }
> >      public UploadedFile getUpload() {
> >          return upload;
> >      }
> >      public void setUpload(UploadedFile upload) {
> >          this.upload = upload;
> >      }
> >      public String getUploadFileName() {
> >          return uploadFileName;
> >      }
> >      public void setUploadFileName(String uploadFileName) {
> >      this.uploadFileName = uploadFileName;
> >      }
> >      public String getUploadContentType() {
> >          return uploadContentType;
> >      }
> >      public void setUploadContentType(String uploadContentType) {
> >      this.uploadContentType = uploadContentType;
> >      }
> > public Logger getLogger() {
> > return logger;
> > }
> > public void setLogger(Logger logger) {
> > this.logger = logger;
> > }
> > public String getName() {
> > return name;
> > }
> > public void setName(String name) {
> > this.name = name;
> > }
> > public String getLastname() {
> > return lastname;
> > }
> > public void setLastname(String lastname) {
> > this.lastname = lastname;
> > }
> > public String getGender() {
> > return gender;
> > }
> > public void setGender(String gender) {
> > this.gender = gender;
> > }
> > public String getAge() {
> > return age;
> > }
> > public void setAge(String age) {
> > this.age = age;
> > }
> >
> > @Override
> >      public void withUploadedFiles(List<UploadedFile> uploadedFiles) {
> >            if (uploadedFiles != null && !uploadedFiles.isEmpty()) {
> >               UploadedFile firstFile = uploadedFiles.get(0); // Take the
> file
> >               this.upload = firstFile;
> >               this.uploadFileName = firstFile.getName();     // String
> >               this.uploadContentType = firstFile.getContentType(); //
> String
> >               logger.info("File name: " + uploadFileName);
> >           }
> >   }
> >
> > Actual Behavior:
> > Despite proper multipart request detection:
> >
> > The interceptor finds the request wrapper:
> >
> > 2025-05-31 DEBUG ActionFileUploadInterceptor:200 - Found multipart
> request:
> > MultiPartRequestWrapper
> >
> > *Our custom DebugMultiPartRequest confirms file presence:*
> >
> > 2025-05-31 12:00:13 INFO  DebugMultiPartRequest:26 - Todos los parámetros
> > del request:
> > 2025-05-31 12:00:13 INFO  DebugMultiPartRequest:30 -  - nombre: Jesus
> > 2025-05-31 12:00:13 INFO  DebugMultiPartRequest:30 -  - apellido: Moreno
> > 2025-05-31 12:00:13 INFO  DebugMultiPartRequest:30 -  - sexo: M
> > 2025-05-31 12:00:13 INFO  DebugMultiPartRequest:30 -  - edad: 50
> >
> >
> >
> > *2025-05-31 12:00:13 INFO  DebugMultiPartRequest:39 - Part 'upload'
> > encontrada:2025-05-31 12:00:13 INFO  DebugMultiPartRequest:40 -  -
> Nombre:
> > Adaware.jpg2025-05-31 12:00:13 INFO  DebugMultiPartRequest:41 -  -
> Tamaño:
> > 25546*2025-05-31 12:00:13 DEBUG InstantiatingNullHandler:106 - Entering
> > nullPropertyValue
> > [target=[org.apache.struts2.text.DefaultTextProvider@2a580722],
> > property=struts]
> > 2025-05-31 12:00:13 DEBUG ConfigurationManager:180 - Checking
> > ConfigurationProviders for reload.
> > 2025-05-31 12:00:13 DEBUG InstantiatingNullHandler:106 - Entering
> > nullPropertyValue
> > [target=[org.apache.struts2.text.DefaultTextProvider@2a580722],
> > property=struts]
> > 2025-05-31 12:00:13 DEBUG DefaultActionProxy:88 - Creating an
> > DefaultActionProxy for namespace [/] and action name [hello]
> > 2025-05-31 12:00:14 DEBUG DefaultActionInvocation:310 - Executing
> > conditional interceptor: ActionFileUploadInterceptor
> > 2025-05-31 12:00:14 DEBUG ActionFileUploadInterceptor:200 - Found
> multipart
> > request: MultiPartRequestWrapper
> >
> > But the interceptor reports:
> >
> > *2025-05-31 12:00:14 DEBUG ActionFileUploadInterceptor:179 - No files
> have
> > been uploaded/accepted*
> >
> > Investigation Steps Taken:
> >
> > 1. Verified all prerequisites:
> >     -  Form uses enctype="multipart/form-data"
> >     -  Using DTD 6.0 as suggested
> >     -  Regularly cleaning Tomcat's work directory
> >     -  Confirmed Jakarta EE 9+ compatibility
> >
> > 2. Created extensive debug instrumentation:
> >     -  Custom DebugMultiPartRequest shows files reach the server
> >     -  Interceptor-level logging confirms the disconnect
> >
> > Technical Findings:
> >
> > 1. The MultiPartRequestWrapper appears to lose file references between:
> >     -   Initial parsing (where files are detectable via raw Part API)
> >     -   Interceptor processing phase
> >
> > 2. Key suspicious behavior:
> >     -   getFileParameterNames() returns empty enumeration
> >     -   Despite request.getPart("upload") working correctly
> >
> > Finally As you suggested, we've:
> >
> >      -  Consistently cleaned deployment directories
> >      -  Verified DTD compatibility
> >      -  Followed migration guides carefully
> >      -  Yet the team remains persistent in investigating this apparent
> > framework bug rather than working around it.
> >
> > # Summary
> > Files are received by the server (confirmed via custom
> > DebugMultiPartRequest) but ActionFileUploadInterceptor fails to process
> > them via UploadedFilesAware interface in Struts 7.0.3 (Jakarta EE
> 9/Tomcat
> > 10 environment).
> >
> > This is my custom DebugMultiPartRequest:
> >
> > public class DebugMultiPartRequest extends JakartaMultiPartRequest {
> > private static final Logger logger =
> > LogManager.getLogger(DebugMultiPartRequest.class);
> >   @Override
> >     public void parse(HttpServletRequest request, String saveDir) throws
> > IOException {
> >         super.parse(request, saveDir); // Procesa el request normalmente
> >         logger.info("=== DebugMultiPartRequest (Struts 7) ===");
> >         // 1. Listar TODOS los parámetros del request (no solo archivos)
> >         logger.info("Todos los parámetros del request:");
> >         Enumeration<String> paramNames = request.getParameterNames();
> >         while (paramNames.hasMoreElements()) {
> >             String name = paramNames.nextElement();
> >             logger.info(" - " + name + ": " +
> request.getParameter(name));
> >         }
> >        // 2. Listar partes multipart (alternativa para Jakarta EE 9+)
> >         if (request instanceof jakarta.servlet.http.HttpServletRequest
> > jakartaRequest) {
> >             jakarta.servlet.http.Part part;
> > try {
> > part = jakartaRequest.getPart("upload");
> > if (part != null) {
> >
> >
> >
> > * logger.info<http://logger.info>("Part 'upload' encontrada:");
> > logger.info<http://logger.info>(" - Nombre: " +
> > part.getSubmittedFileName()); logger.info<http://logger.info>(" -
> Tamaño:
> > " + part.getSize());*            } else {
> >              logger.info("❌ Parte 'upload' NO encontrada en el
> request.");
> >             }
> > } catch (IOException e) {
> > // TODO Auto-generated catch block
> > e.printStackTrace();
> > } catch (ServletException e) {
> > // TODO Auto-generated catch block
> > e.printStackTrace();
> > } // Nombre de tu campo
> >
> >         }
> >        }
> > }
> >
> > After this investigation, we appreciated your feedback if there's any
> > version where this issue we've identified has been resolved, or how we
> can
> > make file uploads work properly.
> >
> > Regards
> > JMC
> >
> >
> > El mié, 14 may 2025 a las 0:09, Lukasz Lenart (<lukaszlen...@apache.org
> >)
> > escribió:
> >
> >> sob., 10 maj 2025 o 07:09 Jesus Moreno<jesus...@gmail.com> napisał(a):
> >>> 2025-05-09 01:00:25 WARNFile:79 - Struts has detected a file upload UI
> >> tag
> >>> (s:file) being used without a form set to method 'POST'
> >>> (Despite <s:form method="POST" enctype="multipart/form-data"> being
> >>> correctly declared)
> >> This can be related to cached JSP files, please remove them from the
> >> container "temp" folder or "work" folder.
> >>
> >>
> https://cwiki.apache.org/confluence/display/WW/Struts+6.x.x+to+7.x.x+migration#Struts6.x.xto7.x.xmigration-Temp/WorkdirectoryofApplicationServer/ServletContainer
> >>
> >>> struts.xml:
> >>> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts
> >>> Configuration 6.5//EN"
> >>>      "https://struts.apache.org/dtds/struts-6.5.dtd";>
> >> There is no such version as 6.5, use 6.0 instead
> >> https://struts.apache.org/dtds/
> >>
> >>
> >> Cheers
> >> Łukasz
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail:user-unsubscr...@struts.apache.org
> >> For additional commands, e-mail:user-h...@struts.apache.org
> >>
> >>



-- 
Ing. Jesús Moreno Canseco
Tel.: (55)6377-0600
Cel.: 55-1409-5156
jesus...@gmail.com <jmor...@ismarts.com.mx>

Reply via email to