gpanders
gpanders

Reputation: 1421

Jersey: MessageBodyReader not found for media type=multipart/form-data

I have found a few questions like this on SO already but none of them seemed to address my particular problem, and I have been unable to find a solution on my own.

Here is the error I'm getting:

Caused by: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=multipart/form-data; boundary=----WebKitFormBoundaryHWk1XUaeu7pEiDth, type=class org.glassfish.jersey.media.multipart.FormDataMultiPart, genericType=class org.glassfish.jersey.media.multipart.FormDataMultiPart.

I am sending this through a jQuery AJAX request that looks like this:

$('#upload-image-form').on('submit', function(e) {
    e.preventDefault();
    var data = new FormData(this);
    $.ajax({
        url: url,
        method: 'POST',
        contentType: false,
        processData: false,
        data: data,
    }).done(function(data) {
        console.log(data);
    }).fail(function(res, status) {
        onError(res, status, 'Image upload failed');
    });
});

And this is my Java endpoint:

@POST
@Path("/{userId}")
@Consumes("multipart/form-data")
public Response createGraphic(
   @PathParam("userId") int userId,
   FormDataMultiPart multiPartFormData) { ... }

I have seen a few people have luck with changing the parameter of the endpoint method to use @FormDataParam instead of FormDataMultiPart (as seen here), but I cannot edit the Java class, so I must use it how it is above.

My pom.xml has the following dependencies:

<dependency>
    <groupId>org.jvnet</groupId>
    <artifactId>mimepull</artifactId>
    <version>1.6</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-server</artifactId>
    <version>2.12</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>2.12</version>
</dependency>

web.xml

<servlet>
   <servlet-name>Jersey</servlet-name>
   <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
   <init-param>
      <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>my.package</param-value>
   </init-param>
   <load-on-startup>5</load-on-startup>
</servlet>

<servlet-mapping>
   <servlet-name>Jersey</servlet-name>
   <url-pattern>/api/*</url-pattern>
</servlet-mapping>

The only other thing I was able to dig up was to register the MultiPartFeature using a ResourceConfig; however, the project I'm working with does not have any Application classes or any class that extends ResourceConfig (it's a WAR that's deployed to Tomcat, so no main class).

Is there any other configuration that needs to be done? I'm stumped as to why this is not working.

Upvotes: 5

Views: 6383

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 208994

The MultiPartFeature has the required reader and writer. But you still need to register the feature. As you've mentioned, you will often see it's registration in an Application/ResourceConfig subclass. But in a web.xml, you can simply add it to the list of classes to add as provider. You can do that by adding an <init-param> to the servlet configuration, i.e.

<init-param>
    <param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>
        org.glassfish.jersey.media.multipart.MultiPartFeature,
        some.other.Provider
    </param-value>
</init-param>

As you can see in the example, if you need to register any other providers/features, you comma-delimit the class names.

Upvotes: 2

Related Questions