Reputation: 97
I have a file upload REST endpoint implemented in Dropwizard. I am new to this and just trying to learn.
@Path("/files")
@Produces(MediaType.APPLICATION_JSON)
public class FileUploadResource {
private final MyAppWebConfiguration configuration;
private static final Logger logger = LoggerFactory.getLogger(FileUploadResource.class);
public FileUploadResource(MyAppWebConfiguration configuration) {
this.configuration = configuration;
}
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
@FormDataParam("file") InputStream uploadedInputStream,
@FormDataParam("file") FormDataContentDisposition fileDetail) throws IOException {
logger.info("Request to upload the file ", fileDetail.getFileName());
final String uploadedFileLocation = configuration.getCsvUploadPath();
final String fileName = fileDetail.getFileName();
writeToFile(uploadedInputStream, uploadedFileLocation, fileName);
return Response.ok("File " + fileName + " is uploaded to the location " + uploadedFileLocation).build();
}
// save uploaded file to new location
protected void writeToFile(InputStream uploadedInputStream, String uploadedFileLocation, String fileName) throws IOException {
logger.info("Writing {} to {}", fileName, uploadedFileLocation);
final java.nio.file.Path outputPath = FileSystems.getDefault().getPath(uploadedFileLocation, fileName);
Files.copy(uploadedInputStream, outputPath, StandardCopyOption.REPLACE_EXISTING);
logger.info("Uploaded {} to the location {}", fileName, uploadedFileLocation);
}
The code works fine and am able to upload the file. I am trying to test it with below code based on https://gist.github.com/psamsotha/218c6bbeb6164bac7cbc :
public class FileUploadResourceTest extends JerseyTest {
private final static MyAppWebConfiguration mockConfiguration = mock(MyAppWebConfiguration.class);
@Override
public ResourceConfig configure() {
return new ResourceConfig(FileUploadResource.class)
.register(MultiPartFeature.class)
.register(new LoggingFilter(Logger.getAnonymousLogger(), true));
}
@Override
public void configureClient(ClientConfig config) {
config.register(MultiPartFeature.class);
}
@Test
public void test() {
FileDataBodyPart filePart = new FileDataBodyPart("file", new File("/Users/rocky/Downloads/test.csv"));
filePart.setContentDisposition(FormDataContentDisposition.name("file").fileName("/Users/rocky/Downloads/test.csv").build());
MultiPart multiPart = new FormDataMultiPart()
.bodyPart(filePart);
Response response = target("/files").request()
.post(Entity.entity(multiPart, MediaType.MULTIPART_FORM_DATA_TYPE));
assertThat(response.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
response.close();
}
This test fails with the below error:
WARNING: The following warnings have been detected: WARNING: HK2 service reification failed for [com.my.app.resources.FileUploadResource] with an exception:
MultiException stack 1 of 2
java.lang.NoSuchMethodException: Could not find a suitable constructor in com.my.app.resources.FileUploadResource class.
at org.glassfish.jersey.internal.inject.JerseyClassAnalyzer.getConstructor(JerseyClassAnalyzer.java:192)
at org.jvnet.hk2.internal.Utilities.getConstructor(Utilities.java:178)
at org.jvnet.hk2.internal.ClazzCreator.initialize(ClazzCreator.java:128)
at org.jvnet.hk2.internal.ClazzCreator.initialize(ClazzCreator.java:179)
I do not have a no argument constructor in FileUploadResource
but new ResourceConfig(FileUploadResource.class)
expects a no argument constructor. How do I pass the info about the one argument constructor here?
Any help here would be highly appreciated. Also, please feel free to suggest any other best practices about the code and the tests so that I can improve them.
Many thanks in advance.
Upvotes: 1
Views: 828
Reputation: 209052
When you register the resource as a class
new ResourceConfig(FileUploadResource.class)
You are telling Jersey to create it. But it has no idea how to create it, as there is only a constructor that accepts a configuration object, which Jersey knows nothing about. Instead you should just register as an object. Same way as if you were registering with Dropwizard (env.jersey().register(...)
).
new ResourceConfig().regster(new FileUploadResource(mockConfiguration))
...
As an aside, with Dropwizard we don't need to explicitly use the JerseyTest
. Dropwizard comes with a JUnit Rule, that explicitly run its own JerseyTest
, and we can configure it with the rule. See this issue, where I posted a complete example.
Upvotes: 2