No multipartconfig for servlet error from Jetty using scalatra

11,386

Solution 1

This is the solution I found when using ServletContextHandler and not WebAppContext. From here : https://bugs.eclipse.org/bugs/show_bug.cgi?id=395000

import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import javax.servlet.MultipartConfigElement;

public class WebServer {

    protected Server server;

    public static void main(String[] args) throws Exception {
        int port = 8080;
        Server server = new Server(port);

        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");


        ServletHolder fileUploadServletHolder = new ServletHolder(new FileUploadServlet());
        fileUploadServletHolder.getRegistration().setMultipartConfig(new MultipartConfigElement("data/tmp"));
        context.addServlet(fileUploadServletHolder, "/fileUpload");

        server.setHandler(context);
        server.start();
        server.join();
    }
}

Solution 2

In case anyone else is looking for this in Jetty 9:

Add this to the request.handle( ... )

MultipartConfigElement multipartConfigElement = new MultipartConfigElement((String)null);
request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, multipartConfigElement);

Solution 3

The @MultipartConfig is a Servlet spec 3.0 annotation. You'll need to add the appropriate artifacts and configuration to support annotation in your Jetty environment.

You'll want the jetty-annotations and jetty-plus artifacts.

Then you'll want to setup the test server with the appropriate configurations.

like this...

(I don't know the Scala specifics here, sorry)

package com.company.foo;

import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.TagLibConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;

public class EmbedMe {
    public static void main(String[] args) throws Exception {
        int port = 8080;
        Server server = new Server(port);

        String wardir = "target/sample-webapp-1-SNAPSHOT";

        WebAppContext context = new WebAppContext();
        context.setResourceBase(wardir);
        context.setDescriptor(wardir + "WEB-INF/web.xml");
        context.setConfigurations(new Configuration[] {
                new AnnotationConfiguration(), new WebXmlConfiguration(),
                new WebInfConfiguration(), new TagLibConfiguration(),
                new PlusConfiguration(), new MetaInfConfiguration(),
                new FragmentConfiguration(), new EnvConfiguration() });

        context.setContextPath("/");
        context.setParentLoaderPriority(true);
        server.setHandler(context);
        server.start();
        server.join();
    }
}

This is from the https://github.com/jetty-project/embedded-servlet-3.0 example project.

Share:
11,386
James Black
Author by

James Black

I have been programming since I was in high school, and my favorite computer was my Amiga 2000, as that is what I learned to program in C on, and was just a great computer. I have been an advocate about unit testing since 1999, and believe we can get better code by getting before the user more frequently so we can narrow the solution to what they really want, as users don't really know what they want, initially. I am comfortable with many languages, but am trying to understand how to program in functional languages, giving up while loops is very difficult for me in designing applications. :)

Updated on June 16, 2022

Comments

  • James Black
    James Black about 2 years

    I am trying to unit test an upload call but I get this error for the following code:

    @MultipartConfig(maxFileSize = 3145728)
    class WebServlet extends ScalatraServlet with FileUploadSupport {
      override def isSizeConstraintException(e: Exception) = e match {
        case se: ServletException if se.getMessage.contains("exceeds max filesize") ||
          se.getMessage.startsWith("Request exceeds maxRequestSize") => true
        case _ => false
      }
      error {
        case e: SizeConstraintExceededException => RequestEntityTooLarge("too much!")
      }
      post("/uploadscript") {
        val privateParam = try {params("private") != null && params("private").equals("true") } catch { case _ => false }
        println("privateParam = " + privateParam)
        val file = fileParams("file")
        println(s"The size of the file is ${file.size}")
      }
    

    The error is:

    java.lang.IllegalStateException: No multipart config for servlet
        at org.eclipse.jetty.server.Request.getParts(Request.java:2064) ~[jetty-server-8.1.10.v20130312.jar:8.1.10.v20130312]
        at org.scalatra.servlet.FileUploadSupport$class.getParts(FileUploadSupport.scala:133) ~[scalatra_2.10-2.2.1.jar:2.2.1]
        at org.scalatra.servlet.FileUploadSupport$class.extractMultipartParams(FileUploadSupport.scala:108) ~[scalatra_2.10-2.2.1.jar:2.2.1]
        at org.scalatra.servlet.FileUploadSupport$class.handle(FileUploadSupport.scala:79) ~[scalatra_2.10-2.2.1.jar:2.2.1]
        at com.ui.WebServlet.handle(WebServlet.scala:32) ~[classes/:na]
    

    And this is my unit test, and the first one succeeds, so it is finding my webservice:

    class WebServletSpecification extends MutableScalatraSpec {
      addServlet(classOf[WebServlet], "/*")
    
      "GET /hello" should {
        "return status 200" in {
          get("/hello/testcomputer") {
            status must_== 200
          }
        }
      }
      "POST /uploadscript" should {
        "return status 200" in {
        val scriptfile = "testfile"
        val scriptname = "basescript"
          post("/uploadscript", Map("private" -> "true"), Map("file" -> new File(scriptfile))) {
            status must_== 200
          }
        }
      }
    }
    

    I am running this inside of Eclipse and I am not certain what is going on.

    It works fine with using HttpPost and MultipartEntity so it seems to be a problem with Eclipse or how the scalatra specification framework works.

    Any idea what may be going wrong?

    I don't have a separate web.xml.

    I am only using jetty 8.1.10, as seen from what I use in build.sbt:

    "org.eclipse.jetty" % "jetty-webapp" % "8.1.10.v20130312" % "container"

    ,

  • James Black
    James Black almost 11 years
    Thank you. As I mentioned, when I start it from sbt (simple build tool) it works fine, as I can tell when I use a junit test that goes to the webserver. But, when I try to use specs2, and I assume it is due to running in Eclipse, it isn't. I don't want to make changes to the program for this unit test as much as understand why it isn't working.
  • SRedouane
    SRedouane over 7 years
    this does not even compile for me, __MULTIPART_CONFIG_ELEMENT is unknown field
  • Richard
    Richard over 7 years
    I just checked (I hate outdated stuff on the interwebs too :) ) I have this as my jetty version: <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.3.8.v20160314</version> </dependency>
  • Terry Horner
    Terry Horner about 6 years
    For compilation, Request is org.eclipse.jetty.server.Request in 9.2 (for me this didn't fix the problem, now I am getting java.io.IOException: Incomplete parts)
  • Vincent Gerris
    Vincent Gerris almost 5 years
    thanks, this works like a charm after a jetty upgrade from 8.4 to 9.2.