Search code examples
restjerseyjettymultipartform-datamultipart

No injection source found for a parameter of type public javax.ws.rs.core.Response - Jersey - MultiPartFeature


I'm creating a web service with Jersey and Jetty Embedded with no web.xml file. It is very simple, It receive a binary file by a POST from a HTML form. It seems I didn't register the MultiPart Feature properly because When I try to use it with HTML form I get this error :

*

WARNING: No injection source found for a parameter of type public javax.ws.rs.core.Response org.multipart.demo.ReceiveFile.postMsg(java.io.InputStream,org.glassfish.jersey.media.multipart.FormDataContentDisposition) throws java.lang.Exception at index 0. 2016-02-09 21:49:59.916:WARN:/:qtp1364335809-16: unavailable org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.|[[FATAL] No injection source found for a parameter of type public javax.ws.rs.core.Response org.multipart.demo.ReceiveFile.postMsg(java.io.InputStream,org.glassfish.jersey.media.multipart.FormDataContentDisposition) throws java.lang.Exception at index 0.; source='ResourceMethod{httpMethod=POST, consumedTypes=[multipart/form-data], producedTypes=[text/plain], suspended=false, suspendTimeout=0,

  • I was looking for the solution for weeks, I have read all question related to this error on StackOverflow, for instance:

MULTIPART_FORM_DATA: No injection source found for a parameter of type public javax.ws.rs.core.Response

Jersey 2 injection source for multipart formdata

They didn't help me because Im not using web.xml

I have 3 classes - ReceiveFile.class (try to receive the POST) - resourceConfig.class (try to register the MultiPart feature) - JettyServer.class (create server instance)

ReceiveFile.class

package org.multipart.demo;
import java.io.InputStream;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;



@Path("/resources")
public class ReceiveFile 
{

        @POST
        @Path("/fileUpload")
        @Produces("text/plain")
        @Consumes(MediaType.MULTIPART_FORM_DATA)
        public Response postMsg (
                @FormDataParam("file") InputStream stream,
                @FormDataParam("file") FormDataContentDisposition fileDetail) throws Exception {


                    Response.Status respStatus = Response.Status.OK;




                    return Response.status(respStatus).build();
                    }

}

resourceConfig.class

package org.multipart.demo;
import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;


    /**
     * Registers the components to be used by the JAX-RS application  
     *
     */
@ApplicationPath("/resources/fileUpload")
public class resourceConfig extends ResourceConfig {

     /**
        * Register JAX-RS application components.
        */  

        public resourceConfig(){
            register(ReceiveFile.class);    
            register(JettyServer.class);
            register(MultiPartFeature.class);
            //packages("org.glassfish.jersey.media", "com.mypackage.providers");


        }

}

JettyServer.class

package org.multipart.demo;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;


public class JettyServer
{
    //   private static final Logger LOGGER = Logger.getLogger(UploadFile.class.getName()); 


public static void main(String[] args) throws Exception
{

    ResourceConfig config = new ResourceConfig();
    config.packages("org.multipart.demo");

    Server jettyServer = new Server(8080);

    ResourceHandler resource_handler = new ResourceHandler();

    // Configure the ResourceHandler. Setting the resource base indicates where the files should be served out of.
    // In this example it is the current directory but it can be configured to anything that the jvm has access to.
    resource_handler.setDirectoriesListed(true);
    resource_handler.setWelcomeFiles(new String[]{ "./index.html" , "./html/FileUpload.html"  });
    resource_handler.setResourceBase(".");

    //Jersey ServletContextHandler
    final ResourceConfig resourceConfig = new ResourceConfig(ReceiveFile.class);
    resourceConfig.register(MultiPartFeature.class);

    ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
    ServletHolder jerseyServlet = servletContextHandler.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*" );
    jerseyServlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES, "org.multipart.demo");

    // Add the ResourceHandler to the server.
    HandlerList handlers = new HandlerList();
    handlers.setHandlers(new Handler[] { resource_handler, servletContextHandler, new DefaultHandler() });
    jettyServer.setHandler(handlers);

    try {
        jettyServer.start();
        jettyServer.join();
    } finally {
        jettyServer.destroy();
    }
}


}

the pom.xml

<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>org</groupId>
  <artifactId>multipart.demo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>multipart.demo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
  <dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-server</artifactId>
    <version>9.2.3.v20140905</version>
  </dependency>
  <dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-servlet</artifactId>
    <version>9.2.3.v20140905</version>
  </dependency>
  <dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-server</artifactId>
    <version>2.7</version>
  </dependency>
  <dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet-core</artifactId>
    <version>2.7</version>
  </dependency>
  <dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-jetty-http</artifactId>
    <version>2.7</version>
  </dependency>
  <dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.7</version>
  </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
 <dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>2.7</version>
</dependency>
 <dependency>
    <groupId>org.jvnet.mimepull</groupId>
    <artifactId>mimepull</artifactId>
    <version>1.9.6</version>
</dependency>
  </dependencies>
</project>

Thanks in advance!


Solution

  • I See three different ResourceConfigs in your codebase, but none of them are actually used for the application. So the MultiPartFeature is never register, which is what is causing the error. You have a few options on how to use a ResourceConfig in your case.

    1. You can instantiate the ServletContainer, passing in the ResourceConfig instance. Unfortunately, there is no ServletContextHolder#addServlet(Servlet) method, but there is a ServletContextHolder#addServlet(ServletHolder) method, so we need to wrap the ServletContainer in a ServletHolder

      ServletHolder jerseyServlet = new ServletHolder(new ServletContainer(resourceConfig));
      servletContextHolder.addServlet(jerseyServlet, "/*");
      
    2. With the above option, you can use a local instance or a subclass, but if you only have a subclass, like your first bit of code, then you add a servlet init param, that specifies the ResourceConfig subclass.

      ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
      ServletHolder jerseyServlet = servletContextHandler.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*" );
      jerseyServlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES, "org.multipart.demo");
      jerseyServlet.setInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, resourceConfig.class.getCanonicalName());
      

      Notice the last call where I set the application class name.

    3. Without using a ResourceConfig, you could just register the MulitPartFeature with an init param

      jerseyServlet.setInitParameter(ServerProperties.PROVIDER_CLASSNAMES, MultiPartFeature.class.getCanonicalName());