0

**UPDATE---The issue was not the file writer not closing but incorrect termination of the Java application. I have updated the question.

I have the following classes launching a JAVAFX web view and exposing some java objects to the web view's html.

public class FileSystemBridge {

private void writeToFile(String[] fileContents){

        if (content!=null){

            String fileName ="pathToFile";
            BufferedWriter fileWriter;
                for (int i =0; i<fileContents.length(); i++ ){
                    String fileContent fileContents[i]);
                    try {
                        fileName = fileName+Integer.toString(i)+".txt";
                        fileName = fileName.replaceAll("\\s","");
                        System.out.println(fileName);
                        File f= new File(filesDir+"/"+fileName);
                        f.createNewFile();
                        fileWriter = new BufferedWriter(new FileWriter(f));
                        fileWriter.write("");
                        fileWriter.write(fileContent);

                        fileWriter.flush();
                        fileWriter.close();
                    } catch (IOException e) {
                        System.out.println("in the exception!");
                        e.printStackTrace();
                    }
                }

        }
        else {
            System.out.println("no content");
        }
        System.out.println("done writing, exit app now");

    }

public void exit(){
    System.out.println("EXITING!");
    Platform.exit();
    System.exit(0);
}
}

The above class also has additional member classes who serve as POJOS to expose the structure of files being read/written to the "front-end" html.

I pass an instance of FileSystemBridge to the web view by overriding the default Browser class constructor and adding the following code.

webEngine.getLoadWorker().stateProperty().addListener(
                (ObservableValue<? extends State> ov, State oldState, 
                    State newState) -> {

                        if (newState == State.SUCCEEDED) {
                            JSObject context= (JSObject) webEngine.executeScript("window");
                            context.setMember("fsBridge", new FileSystemBridge());
                            webEngine.executeScript("init('desktop')");//the hook into our app essentially

                        }
            });

The webEngine.executeScrit("init) essentially performs some initialization on our front end. Then on the javascript executing on the webview on user interaction we invoke our FileSystemBridge write method with a callback to invoke the FileSystemBridge's exit method, which is essentially a call to Platform.exit().

On user click

App.handleWrite(contentToBeWritten, function(success){
                        if (success){
                            console.log("inside success!");
                            App.handleExit();
                        }
                    });

then our handleWrite javascript function

handleWrite: function(content, callback){
    fsBridge.callWrite(content);
    retVal = true;//more logic to this but simplified for demo
    callBack(retVal);
}

Now in the FileSystemBridge.exit() method I have added System.exit(0), which succesfully terminates my java instance which was the original problem.However I would like to know if this is the correct approach to handling the exiting of a java app which uses a JAVAFX webview. Are there unforeseen consequences to using System.exit(0) in this manner?

Pasha Skender
  • 397
  • 4
  • 21
  • Is this part of an application with a UI? – erickson Feb 23 '16 at 20:46
  • Does your program print the 'done writing' line (and before, all expected filenames)? And you say 'in the command line it is still waiting for input' - which makes me suspect that the problem is not with the file writing. – Lars Feb 23 '16 at 20:48
  • Does this compile? What do you get for `filename` when i==2 for example? How does the main look like? – cantSleepNow Feb 23 '16 at 20:50
  • 1
    This is executing inside a javaFX web view, and the write method is being called from the web view javascript. However I have verified through System.out.prints that the function returns, and the program execution terminates. For whatever reason though the java instance doesn't terminate – Pasha Skender Feb 23 '16 at 20:52
  • 1
    You shouldn't really be writing to a file in a callback from a WebView. Instead, you should launch an async [Task](https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html) on a separate thread to perform the write operation (and be sure to gracefully shutdown the async thread in the Application's [stop](https://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html#stop--) method). You may wish to supply an [mcve](http://stackoverflow.com/help/mcve), your problems may lie elsewhere. – jewelsea Feb 23 '16 at 21:20

4 Answers4

3

Java applications that create a UI don't terminate until certain conditions are met. For a JavaFX application, make sure you are closing all Stage instances.

Community
  • 1
  • 1
erickson
  • 265,237
  • 58
  • 395
  • 493
  • This may actually be the root of the problem, I need to investigate further. I am calling Platform.exit() but after reading the documentation it seems that if this method is invoked while another thread is executing it may not actually execute. – Pasha Skender Feb 23 '16 at 21:40
2

If you can't manpulate it into a finally block per the previous answer, how about a try-with-resources? Like so (you'll need to remove the previous declaration of fileWriter):

'

for (int i =0; i<fileContents.length(); i++ ){
                String fileContent fileContents[i]);
                try {
                    fileName = fileName+Integer.toString(i)+".txt";
                    fileName = fileName.replaceAll("\\s","");
                    System.out.println(fileName);
                    File f= new File(filesDir+"/"+fileName);
                    f.createNewFile();
                    try(BufferedWriter fileWriter = new BufferedWriter(new FileWriter(f));)
                    {

                        fileWriter.write("");
                        fileWriter.write(fileContent);
                    }
                } catch (IOException e) {
                    System.out.println("in the exception!");
                    e.printStackTrace();
                }
            }

'

Arc
  • 58
  • 6
1

Try putting the close in a finally block like below and see if it makes any difference.

try {
} catch (Exception e) {
} finally {
 fileWriter.close();
}
user3509208
  • 531
  • 1
  • 5
  • 15
  • I wouldn't have access to the reference in the finally clause however, because the buffered reader is not initialized until the inside of the for loop. – Pasha Skender Feb 23 '16 at 20:43
  • As per your code I think if there is an exception and some how you open the filewriter it wont be closed as you dont have filewrite.close in catch block. Also you should have access to the filewriter as you have declared it outside the for loop. – user3509208 Feb 23 '16 at 20:53
1

I did see some pitfalls, but no real problem, especially as you handle the exceptions. The length() is an indication that you simplified the code here.

Try it in the newer style Path/Files as it is more "atomic" - even more simple.

    String fileName ="pathToFile";
    fileName = fileName.replaceAll("[\\s/\\\\]", "");
    for (int i = 0; i < fileContents.length; i++) {
        Path path = Paths.get(fileName + i + ".txt";
        byte[] bytes = ("\ufeff" + fileContents).getBytes("UTF-8");
        //Or: byte[] bytes = fileContents.getBytes();
        try {
            Files.write(path, bytes);
        } catch (IOException e) {
            System.out.println("Could not write " + path.getFileName());
        }
    }

This version writes in UTF-8 with a starting BOM char. The BOM is ugly, but allows Windows to recognize UTF-8. That allows special characters.

Files.write can have extra parameters list StandardOpenOptions.REPLACE_EXISTING.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138