javamavenmigrationapache-commons-fileuploadmodule-info

JAVA maven apache commons-fileupload: How to migrate from 1.5 to 1.6.0


[MOTIVATION]

I have a maven project that uses commons-fileupload 1.5. When I want to update the dependency to 1.6.0, it does not compile. here

[LIMITATION]

I cannot use jakarta libraries on code, because of later dependency (org.gwtproject).

[MIGRATION IN CONFIGURATION FILES]

@pom.xml:

<dependency>
    <groupId>commons-fileupload</groupId><!-- poi excel does not like u! -->
    <artifactId>commons-fileupload</artifactId>
    <exclusions>
        <exclusion>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
        </exclusion>
    </exclusions>
    <version>1.6.0</version><!-- 1.5 was working -->
</dependency>

@module-info.java:

requires org.apache.commons.fileupload;//commons.fileupload;

[COMPILE ERRORS]

cd C:\git\blg\com.tugalsan.blg.org_apache_commons_fileupload_1_6_0; JAVA_HOME=C:\\bin\\java\\home cmd /c "\"C:\\bin\\netbeans\\home\\java\\maven\\bin\\mvn.cmd\" -Dmaven.ext.class.path=C:\\bin\\netbeans\\home\\java\\maven-nblib\\netbeans-eventspy.jar --no-transfer-progress clean install"

Required filename-based automodules detected: [javax.servlet-api-4.0.1.jar]. Please don't publish this project to a public artifact repository!

COMPILATION ERROR : 
-------------------------------------------------------------
com/tugalsan/blg/org_apache_commons_fileupload_1_6_0/server/TS_SUploadWebServlet.java:[113,51] cannot access javax.servlet.ServletContextListener
  class file for javax.servlet.ServletContextListener not found
com/tugalsan/blg/org_apache_commons_fileupload_1_6_0/server/TS_SUploadWebServlet.java:[48,35] cannot access javax.servlet.http.HttpServletRequest
  class file for javax.servlet.http.HttpServletRequest not found
com/tugalsan/blg/org_apache_commons_fileupload_1_6_0/server/TS_SUploadWebServlet.java:[55,73] no suitable method found for parseRequest(javax.servlet.http.HttpServletRequest)
    method org.apache.commons.fileupload.FileUploadBase.parseRequest(org.apache.commons.fileupload.RequestContext) is not applicable
      (argument mismatch; javax.servlet.http.HttpServletRequest cannot be converted to org.apache.commons.fileupload.RequestContext)
    method org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(javax.servlet.http.HttpServletRequest) is not applicable
      (argument mismatch; javax.servlet.http.HttpServletRequest cannot be converted to javax.servlet.http.HttpServletRequest)
3 errors 

[QUESTION]

What code changes should I apply to migrate fully.

[ADDITIONAL NOTES]

on netbeans on projects on dependencies, javax.servlet-api-4.0.1.jar & commons-fileupload-1.6.0.jar & commons-io-2.19.0.jar exists.


[MRE FILES]
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.tugalsan</groupId>
    <artifactId>com.tugalsan.blg.org_apache_commons_fileupload_1_6_0</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId><!-- poi excel does not like u! -->
            <artifactId>commons-fileupload</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>commons-io</groupId>
                    <artifactId>commons-io</artifactId>
                </exclusion>
            </exclusions>
            <version>1.6.0</version><!-- 1.5 was working -->
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.19.0</version> <!-- poi version 5 needs it, becuase servlet-upload and gwt messes up -->
        </dependency>        
    </dependencies>
    
    <build>
        <resources> 
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.java</include>
                    <include>**/*.gwt.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
        
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-source-plugin</artifactId>
                    <version>3.3.1</version>
                    <executions>
                        <execution>
                            <id>attach-sources</id>
                            <phase>package</phase>
                            <goals>
                                <goal>jar-no-fork</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <release>24</release><!--prop.jdk-->
                    <enablePreview>true</enablePreview>
                    <!--<compilerArgs>
                       <arg>- -add-modules</arg>
                        <arg>jdk.incubator.vector</arg>
                    </compilerArgs> -->
                </configuration>
            </plugin>
        </plugins>
    </build>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

module-info.java

module com.tugalsan.blg.org_apache_commons_fileupload_1_6_0 {
        requires javax.servlet.api; 

//        requires commons.fileupload;
        requires org.apache.commons.fileupload;//;

}

TS_SUploadWebServlet.java

package com.tugalsan.blg.org_apache_commons_fileupload_1_6_0.server;

import javax.servlet.http.*;
import java.io.File;
import static java.lang.System.out;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebListener;
import javax.servlet.annotation.WebServlet;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.FileCleanerCleanup;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

@WebServlet("/u")
@MultipartConfig(
        fileSizeThreshold = 1024 * 1024 * TS_SUploadWebServlet.UPLOAD_MB_LIMIT_MEMORY,
        maxFileSize = 1024 * 1024 * TS_SUploadWebServlet.UPLOAD_MB_LIMIT_FILE,
        maxRequestSize = 1024 * 1024 * TS_SUploadWebServlet.UPLOAD_MB_LIMIT_REQUESTBALL,
        location = "/" + TS_SUploadWebServlet.UPLOAD_DIR_NAME//means C:/bin/tomcat/home/work/Catalina/localhost/spi-xxx/upload (do create it)
)
public class TS_SUploadWebServlet extends HttpServlet {

    final public static String UPLOAD_DIR_NAME = "p";
    final public static int UPLOAD_MB_LIMIT_MEMORY = 10;
    final public static int UPLOAD_MB_LIMIT_FILE = 25;
    final public static int UPLOAD_MB_LIMIT_REQUESTBALL = 50;

    @Override
    public void doGet(HttpServletRequest rq, HttpServletResponse rs) {
        call(this, rq, rs);
    }

    @Override
    protected void doPost(HttpServletRequest rq, HttpServletResponse rs) {
        call(this, rq, rs);
    }

    public static void call(HttpServlet servlet, HttpServletRequest rq, HttpServletResponse rs) {
        try {
            var appPath = rq.getServletContext().getRealPath("");// constructs path of the directory to save uploaded file
            var savePath = appPath + File.separator + TS_SUploadWebServlet.UPLOAD_DIR_NAME;// creates the save directory if it does not exists
            var fileSaveDir = new File(savePath);
            if (!fileSaveDir.exists()) {
                fileSaveDir.mkdir();
            }

            if (!ServletFileUpload.isMultipartContent(rq)) {
                println(rs, "USER_NOT_MULTIPART");
                return;
            }

            //GETING ITEMS
            //WARNING: Dont touch request before this, like execution getParameter or such!
            var items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(rq);

            //GETTING PROFILE
            var profile = items.stream().filter(item -> item.isFormField()).findFirst().orElse(null);
            if (profile == null) {
                println(rs, "RESULT_UPLOAD_USER_PROFILE_NULL");
                return;
            }
            println(rs, "profile_selected");

            var profileValue = profile.getString();
            if (profileValue == null) {
                println(rs, "RESULT_UPLOAD_USER_PROFILEVALUE_NULL");
                return;
            }
            println(rs, "profileValue: " + profileValue);

            //GETING SOURCEFILE
            var sourceFile = items.stream().filter(item -> !item.isFormField()).findFirst().orElse(null);
            if (sourceFile == null) {
                println(rs, "RESULT_UPLOAD_USER_SOURCEFILE_NULL");
                return;
            }
            println(rs, "sourceFile_selected");

            var sourceFileName = sourceFile.getName();
            if (sourceFileName == null) {
                println(rs, "RESULT_UPLOAD_USER_SOURCEFILENAME_NULL");
                return;
            }
            println(rs, "sourceFileName: " + sourceFileName);

            //COMPILING TARGET FILE
            var targetFile = fileSaveDir.toPath().resolve(profileValue).resolve(sourceFileName);

            //CREATE DIRECTORIES
            targetFile.getParent().toFile().mkdirs();

            //STORE FILE
            Files.createFile(targetFile);
            sourceFile.write(targetFile.toFile());

            //RETURN SUCCESS FLAG
            rs.setStatus(HttpServletResponse.SC_CREATED);
            println(rs, "RESULT_UPLOAD_USER_SUCCESS");
        } catch (Exception e) {
            throwIfInterruptedException(e);
            e.printStackTrace();
        }
    }

    private static void println(HttpServletResponse rs, String msg) {
        try {
            out.println("println: " + msg);
            rs.getWriter().println(msg);
        } catch (Exception e) {
            throwIfInterruptedException(e);
        }
    }

    //---------------------------- LISTENER ----------------
    @WebListener
    public class ApacheFileCleanerCleanup extends FileCleanerCleanup {

    }

    //----------------------------- UTILS -----------------------
    @SuppressWarnings("unchecked")
    private static <T extends Throwable> void _throwAsUncheckedException(Throwable exception) throws T {
        throw (T) exception;
    }

    @Deprecated //only internalUse
    private static void throwAsUncheckedException(Throwable exception) {
        TS_SUploadWebServlet.<RuntimeException>_throwAsUncheckedException(exception);
    }

    public static <R> R throwIfInterruptedException(Throwable t) {
        if (isInterruptedException(t)) {
            Thread.currentThread().interrupt();
            throwAsUncheckedException(t);
        }
        return null;
    }

    public static boolean isInterruptedException(Throwable t) {
        if (t instanceof InterruptedException) {
            return true;
        }
        if (t.getCause() != null) {
            return isInterruptedException(t.getCause());
        }
        return false;
    }
}

Solution

  • The main problem is:

    I found that 1.6.1 uses javax.servlet:servlet-api rather than javax.servlet:javax.servler-api. So I try to upgrade the version from the pom.xml, It did not compile.

    Additionally,

    I found that here 2.0.0-M5 version is compatible with javax.servlet if I fork it from javax.servlet:servlet-api to javax.servlet:javax.servler-api on the pom as here here

        <!-- <depe`ndency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>${commons.servlet-api.version}</version>
          <scope>provided</scope>
        </dependency>-->
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>`
    

    Now the project compiles.