Search code examples
javafxjavafx-8javafx-webengine

How can I get the data which has been generated using load HTML feature of JavaFX WebView?


I have a JavaFX application where I am loading the HTML page. The HTML generates a Base64 which is being written to a file once it is loaded using JavaScript bridge. I am trying to get this Base64 data once it is written from the main class. How can I achieve it?

Below is the code.

Test.java

public class Test {

    public static void main(String[] args) throws InterruptedException {
        String input = "[{'name': 'sub',
                          'description': 'sub',
                          'length': 25,
                          'diameter': {'outer': 0.5, 'inner': 0}
                         },
                         {'name': 'jar',
                          'description': 'jar',
                          'length': 25,
                          'diameter': {'outer': 0.5, 'inner': 0}
                         },
                         {'name': 'sub',
                          'description': 'sub',
                          'length': 15,
                          'diameter': {'outer': 0.5, 'inner': 0}
                         },
                         {'name': 'drill pipe',
                          'description': 'drill pipe',
                          'length': 35,
                          'diameter': {'outer': 0.5, 'inner': 0}
                         },
                         {'name': 'sub',
                          'description': 'sub',
                          'length': 20,
                          'diameter': {'outer': 0.5, 'inner': 0}
                         },
                         {'name': 'stabilizer',
                          'description': 'stabilizer',
                          'length': 35,
                          'diameter': {'outer': 0.5, 'inner': 0}
                         },
                         {'name': 'mwd',
                          'description': 'mwd',
                          'length': 25,
                          'diameter': {'outer': 0.5, 'inner': 0}
                         },
                         {'name': 'sub',
                          'description': 'sub',
                          'length': 10,
                          'diameter': {'outer': 0.5, 'inner': 0}
                         },
                         {'name': 'sub',
                          'description': 'sub',
                          'length': 10,
                          'diameter': {'outer': 0.5, 'inner': 0}
                         }]";

        new Thread() {
            @Override
            public void run() {
                String args[] = {"--inputData=" + input};
                JavaFxApplication.main(args);

                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        getBase64Data();
                    }
                });
            }
        }.start();

    private static void getBase64Data() {
        System.out.println("Done");
        try {
            File exisitingFile = new File(Paths.get("Output").toAbsolutePath() + "/Base64.txt");
            System.out.println("is File Exists=" + exisitingFile.exists());
            if(exisitingFile.exists()) {
                InputStream is = new FileInputStream(new File(Paths.get("Output").toAbsolutePath() + "/Base64.txt"));
                BufferedReader buf = new BufferedReader(new InputStreamReader(is));

                String line = buf.readLine();
                StringBuilder sb = new StringBuilder();

                while(line != null) {
                    sb.append(line).append("\n");
                    line = buf.readLine();
                }
                String fileAsString = sb.toString();
                buf.close();
                System.out.println("Valid Base64: " + fileAsString);
                FileUtils.forceDelete(exisitingFile);
            }
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally {
            System.exit(0);
        }
    }
}

JavaFxApplication.java

public class JavaFxApplication extends Application {

    private JavaBridge javaBridge = new JavaBridge();

    @Override
    public void start(Stage primaryStage) throws Exception {
        try {
            String path = Paths.get("Input/BHAEditor").toAbsolutePath() + File.separator + "OriginalCanvas.html";
            Parameters parameters = getParameters();
            Map<String, String> named = parameters.getNamed();
            String inputData = named.get("inputData");
            System.out.println("inputData=" + inputData);
            WebView webView = new WebView();
            WebEngine webEngine = webView.getEngine();
            webEngine.setJavaScriptEnabled(true);
            webView.setContextMenuEnabled(true);
            webView.getEngine().setOnError(event -> System.out.println(event.getMessage()));
            webView.getEngine().setOnAlert(event -> System.out.println(event.getData()));
            webView.getEngine().locationProperty()
                    .addListener((observable, oldValue, newValue) -> System.out.println(newValue));
            Scene scene = new Scene(webView, 600, 600);
            primaryStage.setScene(scene);
            primaryStage.setTitle("Hello World");
            // primaryStage.show();

            File f = new File(path);

            webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
                @Override
                public void changed(@SuppressWarnings("rawtypes") ObservableValue ov, State oldState, State newState) {
                    if (newState == Worker.State.SUCCEEDED) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        String javaScript = "BHAEditorDemo(" + inputData + ")";

                        webEngine.executeScript(javaScript);

                        JSObject jsobj = (JSObject) webEngine.executeScript("window");
                        jsobj.setMember("bridge", javaBridge);
                    }
                }
            });
            webEngine.load(f.toURI().toString());

            webEngine.setOnError((event) -> {
                System.out.println(event.getMessage());
            });
        }
        catch (Exception ex) {
            System.err.print("error " + ex.getMessage());
            ex.printStackTrace();
        }

        WebConsoleListener.setDefaultListener((webView, message, lineNumber, sourceId) -> {
            System.out.println(message + "[at " + lineNumber + "]");
        });

    }

    public static void main(String[] args) {
        launch(args);
    }

    public class JavaBridge {
        public void generateBase64(String base64) throws IOException {
            OutputStream os = null;
            try {
                File exisitingFile = new File(Paths.get("Output").toAbsolutePath() + "/Base64.txt");
                  if(exisitingFile.exists()) {
                      FileUtils.forceDelete(exisitingFile);
                  }
                os = new FileOutputStream(new File(Paths.get("Output").toAbsolutePath() + "/Base64.txt"));
                os.write(base64.getBytes(), 0, base64.length());
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            finally {
                try {
                    os.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Solution

  • Finally I was able to get the result. I kept the alert statement after the canvas image Base64 text generated in HTML. I used webEngine.setOnAlert method to check if the alert was executed and then printed the HTML content. I got the correct response. Below is the code

    HTML

    alert("ready");
    

    JavaFX application

    webEngine.setOnAlert(new EventHandler<WebEvent<String>>(){
    
        @Override
        public void handle(WebEvent<String> event) {
            //labelWebTitle.setText(webEngine.getTitle());
             if("ready".equals(event.getData())){
                 //TODO: initialize
                 System.out.println("HTML Ready");
                 WebEngine engine = (WebEngine)event.getSource();
                 String html = (String) engine.executeScript("document.documentElement.outerHTML");
                 org.jsoup.nodes.Document doc = Jsoup.parse(html);
                 Element image = doc.getElementById("canvasImage");
                 System.out.println(image.attr("src"));
            }
        }
    
    });