0

Have a working Struts2 portlet environment where I cannot make Struts fileUpload work, in portlet mode.

I can see that

  • A file is uploaded to the server, created in temp space.
  • A multipart request is present on the original request, with the filename and file contents, where it enters Struts classes.
  • I can trigger the maximum size response, the default value set in Struts.
  • The FileUploadInterceptor is triggered but in the Jakarta MultipartRequest there is no file. Somewhere between the original request and the Jakarta wrapper the file is lost.

I have tried the same approach in a stripped down Spring boot 2 application, the same problem occurs as in the main project. Followed the code at

https://struts.apache.org/core-developers/file-upload.html

for the JSP and action classes. The portlet is created, the flow works, but no file in the action.

Standard Sping Boot 2 with extra in pom:

<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-spring-plugin</artifactId>
    <version>2.5.20</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

Struts.xml

<package name="uploadtest" extends="struts-portlet-default" namespace="/uploadtest">

    <action name="uploadtestPrepare" class="bouvet.no.fileuploadtest.action.FileUploadSubmitAction">
        <result name="success">/WEB-INF/struts2/test/fileUpload.jsp</result>
    </action>
    <action name="uploadTestSubmit" class="bouvet.no.fileuploadtest.action.FileUploadSubmitAction">
        <result name="success">/WEB-INF/struts2/test/fileUpload.jsp</result>
    </action>
</package>

and the form

<s:form action="uploadTestSubmit" method="post" enctype="multipart/form-data">
    FileName: <s:property value="%{filename}"/>
    <s:file name="upload" label="File" />
    <s:submit/>
</s:form>

a setter

public void setUploadFileName(String filename) {
        this.filename = filename;
    }

Is this a bug in portlet mode or am I missing a key dependency, a component, version? Alternative method?

In the image, a breakpoint in the JSR168 dispatcher, the file is present. First code to run after the server. breakpoint in JSR168 dispatcher

bugfreerammohan
  • 1,471
  • 1
  • 7
  • 22
TomRob
  • 11
  • 3
  • Read https://stackoverflow.com/a/14175896/573032 – Roman C Apr 11 '19 at 18:04
  • @RomanC that is a normal struts application and not a portlet. I am using the default stack (portllet stack) and in that stack fileupload is included. The example with the max allowed size was included to indicate some part of struts2 is involved. Any setting done on the fileuploadinterceptor never comes into play. – TomRob Apr 11 '19 at 18:54
  • Can the cause of this error be that when JakartaMultiPartRequest class gets a request to parse, the request is a portletRequest and the file content is not within that scope. – TomRob Apr 13 '19 at 12:18
  • If fileupload interceptor is included, then it should process uploaded files, read more about this https://stackoverflow.com/a/18596465/573032 – Roman C Apr 13 '19 at 13:31
  • True true but that is exactly what is not happening. I can step through the jakartamultipartrequest and see that it do NOT pick up the file from the request. That in the method: ```protected List parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException``` the context that gets created in the portlet env. not have the file data in it. This may be an error in the portlet container (an adapted Tomcat server with a CMS that can deploy portlets). Know not enough to say where the error is. – TomRob Apr 14 '19 at 11:54

1 Answers1

0

The solution in this case was to step back a step and look at what was present in the request. The CMS the portlet is running in is in fact taking care of the upload before the upload reach the portlet environment. The jakarta wrapper I found was created by the CMS but it is outside of the portlet scope.

Solution:

   public String intercept(ActionInvocation invocation) throws Exception {
        final ActionContext context = invocation.getInvocationContext();

        Object action = invocation.getAction();
        try {
            if (action instanceof FileUploadAware) {
                HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);
//                if (request instanceof MultipartRequestWrapper) {
                    File file = (File) request.getAttribute("upload");
                    ((FileUploadAware) action).setFile(file);

//                }
            }
        }catch (Exception e){
            LOG.error("Exception? {}", e);
        }finally {
            return invocation.invoke();
        }

Not a final solution but the concept, an interceptor that finds an upload attribute on the request and puts it on a FileUploadAware action. The attribute is a local temp file the CMS has intercepted and created. This works for me, a special solution for this CMS or a general for portlets? Do not know.

TomRob
  • 11
  • 3