0

I have a Swing app that requires reading and writing to a file in CSV format. I have this file at src/main/resources/dictData.dat

Currently, when I execute the executable jar via

java -jar dictionary-jar-with-dependencies.jar

and try to execute a save operation, I get

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at com.test.dictionary.utils.FileIO.writeToDataFile(FileIO.java:91)
    at com.test.dictionary.dao.DictionaryDAO.writeToFile(DictionaryDAO.java:145)**

Here, I have a method that wirtes the contents of a Map structure to a CSV file using Apache CSV library.

The topmost message on the stacktrace is at the dataWriter.flush() method within the finally {} block.

@Override
public void writeToDataFile(Map<String, Word> dictMap){

    try {
        Path path = Paths.get(dataUrl.toURI());
        dataWriter = new FileWriter(path.toFile());

        csvFormat = CSVFormat.DEFAULT.withRecordSeparator("\n");
        csvPrinter = new CSVPrinter(dataWriter, csvFormat);

        csvPrinter.printRecord(CSVHeaderMapping.FILE_HEADER);
        List<String> wordData;

        //CSVPrinter.printRecord is best utilized with an Iterable object, thus the initialization of a new ArrayList
        //for each dictionary value
        for (Word word : dictMap.values()){
            wordData = new ArrayList<>();
            wordData.add(String.valueOf(word.getId()));
            wordData.add(word.getWordName());
            wordData.add(word.getWordDefinition());
            wordData.add(word.getDateCreated().toString());
            wordData.add(word.getDateLastUpdated().toString());

            csvPrinter.printRecord(wordData);
        }

    } catch (NullPointerException | IOException | URISyntaxException e){
        e.printStackTrace();
    } finally {
        try {
            dataWriter.flush();  //throws a NPE here, stacktrace above
            dataWriter.close();
            csvPrinter.close();
        } catch (IOException e){
            e.printStackTrace();
        }
    }
}

Strangely, I had a similar issue with reading the file from the same location. It was resolved by converting the file open to a stream via

//Open file connection and read stream
dataUrl = classLoader.getResource(dictionaryFile);
dataReader = new InputStreamReader(dataUrl.openStream());

Note that this only occurs when executing via java -jar, and this application works perfectly when run inside the IDE.

Jason
  • 11,263
  • 21
  • 87
  • 181
  • Don't write to classpath resources. Also, your `.jar` seems to have been incorrectly built and doesn't include your resource. – Sotirios Delimanolis Dec 09 '14 at 23:59
  • It does include the resource, otherwise I wouldn't be able to read from it in the first place. Given that the data is loading in the application, the file exists and is readable. However, its only when writes occur that the NPE is thrown – Jason Dec 10 '14 at 00:07

1 Answers1

1
  1. src won't exist once the program is built. You should NEVER reference it from within your source code.
  2. You can't treat a resources as a "file", it probably won't reside on the OS's disk and will most likely be embedded within the applications Jar (which is a Zip file). If that wasn't complicated enough, updating a running Jar is next to near impossible...

Instead of writing to the resource, consider writing the to a common location, may be stored in the user.home location

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Regarding your last, I can't, has to be internal with the jar file. – Jason Dec 10 '14 at 00:07
  • @Jason Then, frankly, you're screwed. Can you explain why it HAS to be internal...resources are generally not meant to be writable... – MadProgrammer Dec 10 '14 at 00:09
  • A goal for this application is to have it executable with all internal dependencies. Since this is a small application, I was unsure if a database would be a proper decision for this, and decided to use a CSV file as data storage. – Jason Dec 10 '14 at 00:10
  • *"A goal for this application is to have it executable with all internal dependencies"* - I'm not sure that is entirely possible. If you need to store content, it has to be external to the application binaries, but could still be internal to the "application context" – MadProgrammer Dec 10 '14 at 00:12
  • Alright, thanks. I'm looking at moving the data file to the repository root and having it accessible from there. – Jason Dec 10 '14 at 00:13