Reputation: 995
I am using Jersey based restful Service implementation strategy to build a service which will be used to upload files. My service class name is : UploadFileService.java (See Code below)
package com.jerser.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
@Path("/fileUpload")
public class UploadFileService {
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
@FormDataParam("file") InputStream uploadedInputStream,
@FormDataParam("file") FormDataContentDisposition fileDetail) {
String uploadedFileLocation = "d://uploaded/" + fileDetail.getFileName();
// save it
writeToFile(uploadedInputStream, uploadedFileLocation);
String output = "File uploaded to : " + uploadedFileLocation;
return Response.status(200).entity(output).build();
}
// save uploaded file to new location
private void writeToFile(InputStream uploadedInputStream,
String uploadedFileLocation) {
try {
OutputStream out = new FileOutputStream(new File(
uploadedFileLocation));
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(uploadedFileLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
These are the JAR files I have inside my lib:
aopalliance-repackaged-2.4.0-b10.jar asm-debug-all-5.0.2.jar hk2-api-2.4.0-b10.jar hk2-locator-2.4.0-b10.jar hk2-utils-2.4.0-b10.jar javassist-3.18.1-GA.jar javax.annotation-api-1.2.jar javax.inject-2.4.0-b10.jar javax.servlet-api-3.0.1.jar javax.ws.rs-api-2.0.1.jar jaxb-api-2.2.7.jar jersey-client.jar jersey-common.jar jersey-container-servlet-core.jar jersey-container-servlet.jar jersey-core-1.11.jar jersey-guava-2.17.jar jersey-media-jaxb.jar jersey-multipart-1.18.jar jersey-server.jar org.osgi.core-4.2.0.jar osgi-resource-locator-1.0.1.jar persistence-api-1.0.jar validation-api-1.1.0.Final.jar
I am getting the following error when I am trying to up my tomcat server :
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 com.jerser.service.UploadFileService.uploadFile(java.io.InputStream,com.sun.jersey.core.header.FormDataContentDisposition) at index 0.; source='ResourceMethod{httpMethod=POST, consumedTypes=[multipart/form-data], producedTypes=[], suspended=false, suspendTimeout=0, suspendTimeoutUnit=MILLISECONDS, invocable=Invocable{handler=ClassBasedMethodHandler{handlerClass=class com.jerser.service.UploadFileService, handlerConstructors=[org.glassfish.jersey.server.model.HandlerConstructor@d3e2d4]}, definitionMethod=public javax.ws.rs.core.Response com.jerser.service.UploadFileService.uploadFile(java.io.InputStream,com.sun.jersey.core.header.FormDataContentDisposition), parameters=[Parameter [type=class java.io.InputStream, source=file, defaultValue=null], Parameter [type=class com.sun.jersey.core.header.FormDataContentDisposition, source=file, defaultValue=null]], responseType=class javax.ws.rs.core.Response}, nameBindings=[]}']
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:528)
at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:166)
at org.glassfish.jersey.server.ApplicationHandler$3.run(ApplicationHandler.java:327)
at org.glassfish.jersey.internal.Errors$2.call(Errors.java:289)
at org.glassfish.jersey.internal.Errors$2.call(Errors.java:286)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:286)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:324)
at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:338)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:171)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:363)
at javax.servlet.GenericServlet.init(GenericServlet.java:160)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1176)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1102)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1009)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4885)
at org.apache.catalina.core.StandardContext$3.call(StandardContext.java:5212)
at org.apache.catalina.core.StandardContext$3.call(StandardContext.java:5207)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Over the internet I found there are plenty of example which shows How to upload MULTIPART file using RESTFul API. But with same solution. I am not able to run those code as well. I think I am doing something wrong with the JAR files. Could anyone please help me on this?
Upvotes: 66
Views: 85517
Reputation: 209112
Get rid of jersey-multipart-1.18.jar
. That is for Jersey 1.x. Add these two
For Maven you would use the following dependency (you don't need to explicitly add the mimepull
dependency, as this one will pull it in).
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.17</version> <!-- Make sure the Jersey version matches
the one you are currently using -->
</dependency>
Then you need to register the MultiPartFeature
. If you are using a ResourceConfig
for configuration, you can simply do
register(MultiPartFeature.class);
If you are using web.xml, then you can add the class as an <init-param>
to the Jersey servlet
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
Note that if you have multiple providers that you want to register, then you can delimit each provider class with a comma, semicolon, or space/newline. You cannot use this same param-name
twice. See Suarabh's answer
UPDATE
Also, once you get rid of jersey-multipart-1.18.jar
you will have compile errors for the missing imported classes. For the most part, the class names are still the same, just the packages have changed, i.e.
org.glassfish.jersey.media.multipart.FormDataParam
org.glassfish.jersey.media.multipart.FormDataContentDisposition
If you're using Dropwizard, instead of adding the jersey-media-multipart
, they document for your to add dropwizard-forms
instead. And instead of registering the MultiPartFeature
, you should register the MultiPartBundle
@Override
public void initialize(Bootstrap<ExampleConfiguration> bootstrap) {
bootstrap.addBundle(new MultiPartBundle());
}
Really doesn't make much difference though as all the Dropwizard bundle does is register the MultiPartFeature
with the ResourceConfig
.
If you are here for a different ModelValidationException
, here are some links for information on other causes of the exception.
Upvotes: 183
Reputation: 1
Indeed my web.xml was lacking "org.glassfish.jersey.media.multipart.MultiPartFeature" (among other classes) within "jersey.config.server.provider.classnames" parameter value. At least :
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
Upvotes: 0
Reputation: 73
In case someone comes across this in the future and is running into the same problem I was running into. Make sure that the annotations you are importing are from the correct packages. In my case I was importing javax.websocket.server.PathParam
instead of javax.ws.rs.PathParam
.
Upvotes: 0
Reputation: 383
I had a very similar problem and the answer that helped me was this https://stackoverflow.com/a/30407999/6801721
I was trying to use a user defined object as a query parameter and from the answer that's usually not allowed unless it meets some conditions.
Upvotes: 0
Reputation: 51
in case you are getting this error while writing Dropwizard tests for the upload Resource this is the solution:
2.add this in the application file:
@Override
public void initialize(Bootstrap<ExampleConfiguration> bootstrap) {
bootstrap.addBundle(new MultiPartBundle());
}
ResourceExtension.builder()
.addResource(new FileResource())
.addProvider(new MultiPartFeature())
.build();
Upvotes: 2
Reputation: 7862
Below code worked for me:
Class ->>> add it
Class Property --->> add it
Public Class userREST () {
@POST
@Path("upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public Response uploadImageFile(@FormDataParam("uploadFile") InputStream fileInputStream,
@FormDataParam("uploadFile") FormDataContentDisposition fileFormDataContentDisposition,
@FormDataParam("FIR_REG_NUM") String FIR_REG_NUM, @FormDataParam("LOGIN_ID") String LOGIN_ID) {
final_json_result = WriteFileInFolder.fileAnalysis(fileInputStream, fileFormDataContentDisposition, FIR_REG_NUM,
LOGIN_ID);
return Response.ok(final_json_result).build();
}// uploadImageFile
Public Class FileJAXRSConfig () {
package ####.jaxrs.jwt;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import ####.helper.Common@@@;
import ####.jaxrs.jwt.filters.JWTRequestFilter;
import ####.jaxrs.jwt.filters.JWTResponseFilter;
import ####.service.FileServicesREST;
@ApplicationPath("fileservice")
public class FileJAXRSConfig extends Application {
@Override
public Set<Class<?>> getClasses() {
Common@@@.logging("@ApplicationPath@FileServicesREST...");
Set<Class<?>> clazzes = new HashSet<Class<?>>();
clazzes.add(JWTRequestFilter.class);
clazzes.add(FileServicesREST.class);
clazzes.add(JWTResponseFilter.class);
return clazzes;
}
@Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("jersey.config.server.provider.packages", "####.service");
properties.put("jersey.config.server.provider.classnames", "org.glassfish.jersey.media.multipart.MultiPartFeature");
return properties;
}
}
Don't need to add following in web.xml
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>mha.@@@.service</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
Upvotes: 2
Reputation: 2914
I had the same problem when I tried to upload the file. I spent a lot of time until I found a solution to the problem.
1.If you changed version of your JARs files you may have a version conflicts!
Clean up your artifacts/libs and rebuild project.
2.You need to register your UploadFileService class too:
register(MultiPartFeature.class);
register(UploadFileService.class);
Hope it will help someone and save your time.
Upvotes: 1
Reputation: 13248
Yet another possible cause for this very generic error is that Jersey only searches for factories associated with the last annotation when multiple ones are declared on a param. (See bug report)
Until this is fixed, if you are using any other annotations besides @FormDataParam
, it has to come last.
This works:
@NotEmpty @FormDataParam("myParam") String myParam
This does not:
@FormDataParam("myParam") @NotEmpty String myParam
Upvotes: 11
Reputation: 11
I had this same problem with Scala and this helped me solve it. Just want to add some Scala specific details to help anyone using Dropwizard with Scala. Here is an example of how to "register" the MultiPartFeature in a Scala and Dropwizard project.
package org.research.s3.service
import io.dropwizard.Application
import io.dropwizard.setup.Environment
import org.research.s3.service.resource._
import org.research.service.s3.resource.UploadResource
import org.glassfish.jersey.media.multipart.{FormDataParam,MultiPartFeature}
class CmdaaApp() extends Application[CmdaaAppConfig] {
override def run(t: CmdaaAppConfig, env: Environment): Unit = {
env.jersey().register(new RootResource)
//Need this to make the file upload code work in
env.jersey().register(new MultiPartFeature)
env.jersey().register(new UploadResource(curBucket))
}
}
object CmdaaApp {
def main(args: Array[String]): Unit = new CmdaaApp().run(args: _*)
}
and here is the code for the UploadResource that does the upload:
package org.research.service.s3.resource
import java.io.{FileInputStream, InputStream}
import com.google.gson.{Gson, GsonBuilder}
import javax.ws.rs.core.MediaType.APPLICATION_JSON
import javax.ws.rs._
import javax.ws.rs.core.Response
import javax.ws.rs.core.MediaType
import org.research.util.OptionSerializer
import org.research.s3.service.resource.s3Bucket
import org.glassfish.jersey.media.multipart.{FormDataParam,MultiPartFeature}
@Path("/file")
class UploadResource(currentBucket: s3Bucket) {
val gsonb = new GsonBuilder()
gsonb.registerTypeAdapter(classOf[Option[Any]], new OptionSerializer)
val gson = gsonb.create
@POST
@Path("upload")
@Produces(Array(APPLICATION_JSON))
@Consumes(Array(MediaType.MULTIPART_FORM_DATA))
// def uploadFile(): Response = {
def uploadFile(@FormDataParam("file") uploadedInputStream: InputStream): Response = {
/* Need code here to get a uuid for the file name
Then return the uuid if we have success and of course 200
*/
Response.ok.entity(currentBucket.upload("testName",uploadedInputStream,false)).build()
//Response.ok().build()
}
}
This code refers to an s3 bucket but you don't need that. You can just replace that call with code do download your incoming file data to a regular file. scala
Upvotes: 1
Reputation: 1689
Register MultiPartFeature. In web.xml add to the Jersey servlet:
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
Upvotes: 2
Reputation: 637
If someone is using @FormDataParam
with @ApiOperation
swagger annotation, it won't work(as per swagger latest version at this time) as mentioned here:
https://github.com/swagger-api/swagger-ui/issues/169
Upvotes: 2
Reputation: 7833
I too got the same exception.I did the following changes in web.xml
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.filter.LoggingFilter;org.glassfish.jersey.moxy.json.MoxyFeature;org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
and changed jersey 2.7 to 2.9 .I do not know what change of this 2 has solved the issue.
Upvotes: 5