0

I'm trying to set the file path of a resource file in an Eclipse project on Windows, game.json but when I try to crate an input stream string from the InputStream I get a NullPointerException.

To debug this I've checked the correct file path to my resource is in place, which it seems it is. Also I've set a break point on the error and it seems to be happening at this line:

String inputStreamString = new Scanner(source,"UTF-8").useDelimiter("\\A").next();

Does anyone know why the JSON file isn't being found using the given path?

These are the steps I'm taking to reference the resource's file path, but I'm getting an NPE:

private static final String GAME_FILE = "/game.json";
//I've also tried the path, "resources/game.json" but got the same error..

InputStream source = getClass().getClassLoader().getResourceAsStream(GAME_FILE); 

String inputStreamString = new Scanner(source,"UTF-8").useDelimiter("\\A").next();

ObjectMapper mapper = new ObjectMapper();

// read from file, convert it to Location class
Location loc = mapper.readValue(new File(inputStreamString), Location.class);

This is the structure of my project tree:

project tree

This the error being thrown:

Exception in thread "main" java.lang.NullPointerException: source
    at java.util.Objects.requireNonNull(Unknown Source)
    at java.util.Scanner.<init>(Unknown Source)
    at gmit.GameParser.parse(GameParser.java:23)
    at gmit.Main.main(Main.java:13)
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
Brian Var
  • 6,029
  • 25
  • 114
  • 212

3 Answers3

1

You're presumably trying to read the JSON content of the resource file game.json and use ObjectMapper to parse that JSON and deserialize it into a Location object.

Location loc = mapper.readValue(new File(inputStreamString), Location.class); 

ObjectMapper already has a readValue method which accepts an InputStream. You don't need to use the one that takes a File.

So you can just have

InputStream source = getClass().getResourceAsStream(GAME_FILE); 
Location loc = mapper.readValue(source, Location.class); 

Note that a classpath resource is not necessarily reachable with a File instance since it doesn't necessarily represent a file system entity.


Your resource game.json is in the package resources. Retrieve it as such

private static final String GAME_FILE = "/resources/game.json";

(Assuming the package resources is in your runtime classpath.)

Also remove the getClassLoader call in

InputStream source = getClass().getClassLoader().getResourceAsStream(GAME_FILE); 
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • @BrianJ Right-click your project. Check the Build Path. Also check your Run Configuration and its classpath. – Sotirios Delimanolis Mar 30 '15 at 19:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/74133/discussion-between-brian-j-and-sotirios-delimanolis). – Brian Var Mar 30 '15 at 19:16
  • what exactly should I be checking for in the build path? – Brian Var Mar 30 '15 at 19:28
  • @BrianJ Hmm. Get rid of the `getClassLoader` call. – Sotirios Delimanolis Mar 30 '15 at 19:35
  • Okay so when I got rid of the `getClassLoader` it gives a different error and seems to print the contents of the JSON in the console window, http://hastebin.com/ologoracuw.pl this is the complete class that is doing the parsing for reference: http://hastebin.com/igoqayorid.avrasm any ideas? – Brian Var Mar 30 '15 at 19:50
  • @BrianJ You're reading the content of your resource and trying to use that content as the name of a file `new File(inputStreamString)`. – Sotirios Delimanolis Mar 30 '15 at 19:51
  • okay I intended to get the file path of the file, not the content of the resource, how can I fix that? I can't pass in InputStream to the File constructor as its expecting a String pathname.. – Brian Var Mar 30 '15 at 19:56
  • @BrianJ Don't confuse a classpath resource with a file. A classpath resource can be inside a JAR just like it can be on the file system directly. Classpath resources should be read only. Don't write to them. If you need to write somewhere, find a dedicated location and write there. – Sotirios Delimanolis Mar 30 '15 at 20:12
  • Okay how can I pass the file path of the JSON file `"/resources/game.json"` thats what is confusing me..I want to pass the file path string to File() – Brian Var Mar 30 '15 at 20:37
  • @BrianJ If `game.json` is not meant to be a classpath resource, take it out of the source folders and put it in some dedicated location. Take the absolute path to that location and use it in `new File(...)`. – Sotirios Delimanolis Mar 30 '15 at 20:57
  • okay I understand now, I need to add a folder to my project, containing the JSON file, then reference that location in a file path string? – Brian Var Mar 30 '15 at 21:06
  • @BrianJ That's what I would do (except it doesn't need to be in your project necessarily, it can be anywhere where you have access on your file system). Resources are read-only files. – Sotirios Delimanolis Mar 30 '15 at 21:14
  • okay but the key is that I want to able to launch the project as jar file, so having the json file outside of the project folder will not work. Needs to be included in the jar, does that matter? – Brian Var Mar 30 '15 at 21:20
  • okay so then it needs to be classpath resource correct? How can I pass that classpath source as a file path string to the File() ? – Brian Var Mar 30 '15 at 21:44
  • @BrianJ Note that since you already have an `InputStream`, you can pass that to the `readValue` method directly. It has an overload for `InputStream`. I was incorrectly assuming you were writing to it, not reading from it. There's no reason to use a `File` here. – Sotirios Delimanolis Mar 30 '15 at 22:42
  • Okay could you edit your answer to explain this? I've posted an answer also to explain my work around. – Brian Var Mar 30 '15 at 23:14
1

Try using an absolute path: /resources/game.json

Break up the line String inputStreamString = new Scanner(source,"UTF-8").useDelimiter("\\A").next();. You have to determine whether instantiating Scanner is causing the exception because InputStream is null (due to resource not found) or whether .next() is causing the exception.

To break up the line:

Scanner s = new Scanner(source,"UTF-8").useDelimiter("\\A");
String output = s.next();

Then determine which of these two lines throws the exception.

Lev
  • 100
  • 8
  • Tried the above path but got the same error, how can I break up the line? – Brian Var Mar 30 '15 at 18:49
  • so I split up the statement like the above, but I still get the same NPE error at the first line: Scanner s = new Scanner(source,"UTF-8").useDelimiter("\\A"); – Brian Var Mar 30 '15 at 19:14
  • This confirms that the InputStream you are passing in is null. Add the file to your classpath by following directions here: http://stackoverflow.com/questions/11302531/how-to-place-a-file-on-classpath-in-eclipse – Lev Mar 30 '15 at 20:04
0

The resource game.json needed to be a classpath resource, as the project is being exported to a jar file.

The code I was using to convert the Input stream below was actually converting the file to a string which is not what I was getting at:

String inputStreamString = new Scanner(source,"UTF-8").useDelimiter("\A").next();

What I needed to do was convert the classpath resource to a URI and call .toURI() in the constructor of File instead like so:

    URL sourceURL = getClass().getResource(GAME_FILE); 

    ObjectMapper mapper = new ObjectMapper();


    Location loc = mapper.readValue(new File(sourceURL.toURI()), Location.class);
Brian Var
  • 6,029
  • 25
  • 114
  • 212