4

I've exported my Java console application to a Jar file, but when I run the jar and call code that parses in a JSON file I get a java.lang.IllegalArgumentException

Does anyone know why the exception is being thrown when I run the program as a JAR? The parsing works fine when the application is run from Eclipse.

This is the exact error that is output when I execute the jar file and call the code that parses the JSON file:

Exception in thread "main" java.lang.IllegalArgumentException: URI is not hierar
chical
        at java.io.File.<init>(Unknown Source)
        at gmit.GameParser.parse(GameParser.java:44)
        at gmit.Main.main(Main.java:28)

This is how the parsing is being done in my GameParser class:

public class GameParser {
    private static final String GAME_FILE = "/resources/game.json";
    private URL sourceURL = getClass().getResource(GAME_FILE); 
    private int locationId;

    private List<Location> locations;
    private List<Item> items;
    private List<Character> characters;

    public void parse() throws IOException, URISyntaxException {
        ObjectMapper mapper = new ObjectMapper();
       mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        try {                   
            // read from file, convert it to Location class
            Location loc = new Location();
            loc = mapper.readValue(new File(sourceURL.toURI()), Location.class);
            Item item = mapper.readValue(new File(sourceURL.toURI()), Item.class);
            GameCharacter character = mapper.readValue(new File(sourceURL.toURI()), GameCharacter.class);

            // display to console
            System.out.println(loc.toString());
            System.out.println(item.toString());
            System.out.println(character.toString());
        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

This is the folder structure of my project:

source tree

Brian Var
  • 6,029
  • 25
  • 114
  • 212

2 Answers2

8

The call getClass().getResource(GAME_FILE); will return a URL relative to this class. If you are executing your program from a JAR file, it will return a URL pointing to a JAR file.

Files in java can only represent direct filesystem files, not the ones in zip/jar archives.

To fix it:

  1. Try to use getClass().getResourceAsStream() and use that instead of Files or
  2. extract the files into some directory and use File in the same way as you are trying now.
Crazyjavahacking
  • 9,343
  • 2
  • 31
  • 40
  • Okay so what be the work around in this case, drop the getResource? Can you show a code snippet example. – Brian Var Apr 10 '15 at 14:51
  • Updated with proposal. – Crazyjavahacking Apr 10 '15 at 14:53
  • 1
    Okay I've added a snap shot of my source tree above. I tried the above but `File` expects a string not an InputStream. `private InputStream sourceURL = getClass().getResourceAsStream(GAME_FILE); ` `loc = mapper.readValue(new File(sourceURL), Location.class);` – Brian Var Apr 10 '15 at 14:57
  • http://jackson.codehaus.org/1.8.8/javadoc/org/codehaus/jackson/map/ObjectMapper.html – Brian Var Apr 10 '15 at 15:01
  • Then I already answered your question, use the `readValue(sourceInputStream, Location.class)` – Crazyjavahacking Apr 10 '15 at 15:03
  • Okay I understand now, so I need to have: `GameState parser = mapper.readValue(resourceAsStream, GameState.class);` but that then throws mapping exception, http://hastebin.com/tolehexumi.avrasm – Brian Var Apr 10 '15 at 17:14
0

This problem happen when you have two files with the same name,i mean in your project you have folder whith name "Images" and in your desktop you have other folder his name "images" automatically JVM choose desktop folder ,so if you want to confirm try to print your URI.Use this example to show your URI before creating your file

try {
    URL location = this.getClass().getResource("/WavFile");
    System.out.println(location.toURI());
     File file = new File(location.toURI()); 
     if (!file.exists()) {
        System.out.println(file.mkdirs());
        System.out.println(file.getAbsoluteFile());
    }else
    {
         System.out.println(file.getPath());
    }
} catch (Exception e) {
    e.printStackTrace();
}
Pang
  • 9,564
  • 146
  • 81
  • 122