java.lang.NullPointerException while creating DiskFileItem
Asked Answered
B

5

8

I am trying to write a unit test for handling a file upload controller using Spring 3. Now if I send the image over to my service method through the controller everything works fine. But when doing a straight unit tests I am getting a null pointer exception.

It appears that the property "dfos" inside the DiskFilteItem is null when I instantiate it manually but it is populated when retrieving a MultipartFile from the controller.

    File file = new File("//Users//test//Downloads//testimage.jpg");
    log.info("found file: " +file.exists());
    log.info("file size: " +file.length());
    String fieldName = "field";
    String contentType = "image/jpeg";
    boolean isFormField = false;
    String fileName = "testimage.jpg";
    int sizeThreshold = 10240;

    DiskFileItemFactory factory = new DiskFileItemFactory();

    DiskFileItemFactory factory = new DiskFileItemFactory();
    // throws null pointer
    FileItem fi = factory.createItem(fieldName,contentType,isFormField,fileName);

    // so does this one
    DiskFileItem item = new DiskFileItem(fieldName, contentType, isFormField, fileName, sizeThreshold, file);
    MultipartFile f = new CommonsMultipartFile(item);

I feel like I am missing something silly in my setup. My pom file contains the following dependencies.

    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.2.2</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.0</version>
    </dependency>

This code throws the following stack trace

java.lang.NullPointerException
 at org.apache.commons.fileupload.disk.DiskFileItem.getSize(DiskFileItem.java:316)
 at org.springframework.web.multipart.commons.CommonsMultipartFile.(CommonsMultipartFile.java:60)
 at ImgurClientTest.testUploadImage(ImgurClientTest.java:58)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
 at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
 at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
 at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
 at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
 at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
 at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
 at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
 at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:65)
Brose answered 8/11, 2010 at 1:15 Comment(0)
Q
15

I ran into the same problem. The issue is that DiskFileItem.getSize() is temporally coupled with DiskFileItem.getOutputStream() in that an internal field is initialized in getOutputStream and used in getSize.

The solution is to do

final File TEST_FILE = new File("src/test/resources/test.jpg");
final DiskFileItem diskFileItem = new DiskFileItem("file", "image/jpeg", true, TEST_FILE.getName(), 100000000, TEST_FILE.getParentFile());
diskFileItem.getOutputStream();

before passing diskFileItem to the constructor of CommonsMultipartFile.

Quenelle answered 30/3, 2011 at 16:0 Comment(2)
thanks diskFileItem.getOutputStream(); save our day ...greatBecause
Thank you! The must have was diskFileItem.getOutputStream()Mosby
S
0

What does this part of this log say?

log.info("found file: " +file.exists());
log.info("file size: " +file.length());

But I think the problem might be because of this:

File file = new File("//Users//test//Downloads//");

It looks like it's pointing to a directory instead of a file, so maybe that is why you are getting a NullPointerException when you want to get the size of DiskFileItem

Scar answered 8/11, 2010 at 2:16 Comment(2)
You are right that was a typo in the description, I have modified the original sample to point at a file. The log file entries show the following 2010-11-08 11:57:11,907[main ] INFO ClientTest - found file: true 2010-11-08 11:57:11,908[main ] INFO ClientTest - file size: 291812Brose
If it solve your problem, please upvote and mark this as answer. Really appreciate it.Scar
H
0

And if none of the solutions above work for you as it happened for me :) simply ditch the DiskFileItem and use the solution bellow:

  final File fileToUpload = new File("src/test/resources/files/test.txt");
  final MultiValueMap<String, Object> request = new LinkedMultiValueMap<String, Object>();
  request.add("file", new FileSystemResource(fileToUpload.getAbsolutePath()));
Handcraft answered 19/7, 2013 at 11:16 Comment(0)
B
0

Although not entirely related to the question. I ran into the same exception when deploying some file-upload code to GAE. I modified systempuntoout's code from here using apache fileupload on GAE (which uses the streams part of apache commons) which then worked fine.

Braxy answered 19/8, 2017 at 16:29 Comment(0)
S
-1
new DiskFileItem(fieldName, contentType, isFormField, fileName, sizeThreshold, file);

results in a null value. Look into the docs to see what's wrong or maybe you pass some null as parameters

Selfimmolation answered 8/11, 2010 at 9:18 Comment(1)
No all values are populated with something, it appears to be how I am creating the DiskFileItem from scratch vs how Spring creates it when sending it from a controller. Stepping through the DiskFileItem code it appears to be missing an instantiation somewhere when doing it manually for the dfos parameter.Brose

© 2022 - 2024 — McMap. All rights reserved.