2

I try to route on TomTom maps and get a callback from the routing method. So I made up a Java Application in JavaFx and showed the TomTom Map on my webview from JavaFX.

Now my issue: I do call a method in Javascript from JavaCode and want to get the response from the routing method, but this takes time and is asynchronous. And I just get the Promise Object from javascript and not the response...

I changed the javscript functions and don't work with promises anymore.

Edited Code:

JavaCode:

package application;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Properties;

import javafx.application.Application;
import javafx.concurrent.Worker.State;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import netscape.javascript.JSObject;

public class Main extends Application{

static JSObject window;
static Stage primaryStage;

public void start(Stage primaryStage) {



try {
        Browser browser = new Browser();
        browser.getWebEngine().getLoadWorker().stateProperty()
        .addListener((obs, oldValue, newValue) -> {
            if (newValue == State.SUCCEEDED) {

                window = (JSObject) browser.getWebEngine().executeScript("window");

                System.out.println("Now call gogo");
                System.out.println("gogo Output: " + window.call("gogo"));

                WebController webControl= new WebController(browser, window);
                window.setMember("clickController", webControl);

                System.out.println("First it will go over here and print this");

                LocalDate date = LocalDate.now();
                try {
                    FileWriter fw = new FileWriter("output/"+date+".csv", true);
                    BufferedWriter bw = new BufferedWriter(fw);
                    bw.append(LocalTime.now() + ";" + delay + "\n");
                    bw.close();
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        Scene scene = new Scene(browser, Color.web("#666970"));
        primaryStage.setTitle("TestApplication");
        primaryStage.setScene(scene);
        primaryStage.show();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

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

Javascript:

    function gogo(){
    var data = goTask(function(data) {
    console.log(data.summary.totalDistanceMeters);
    clickController.print("after all that java stuff it will invoke this syso")
    clickController.print("output Routing function: " + data.summary.totalDistanceMeters);
    clickController.print("gogo output with invoking java from javascript");    
    return data;
    });
    return data;
    }

    function goTask(call){
    function callback(d){
        call(d);
    }
    routeMe(callback);
    function routeMe(callbackFunc){
        var points = [ [48.7061643,9.1664228], [48.7322085,9.0489835] ]; 
        var service = new tomtom.services.RoutingService("'ApiKey'");
        var options = {
            includeTraffic: true
            // avoidTolls: true
        };
        service.getRoute(points, options,callbackFunc);
    }
    }

Output:

Now call gogo
gogo Output: undefined
First it will go over here and print this syso
WebController Syso: after all that java stuff it will invoke this
WebController Syso: output Routing function: 9419
WebController Syso: gogo output with invoking java from javascript

The problem is that Java does not wait on Javascript...

Can anyone help me?

Edit:

@Bonatti I am running it on

ScriptEngineFactory getEngine --> Oracle Nashorn

ScriptEngine getLanguage --> ECMAScript

CrazyFisch
  • 25
  • 5
  • What is the result for System.out.println(delay), currently? – Spork Jul 28 '15 at 14:17
  • com.sun.webkit.dom.JSObject cannot be cast to java.lang.String after I changed the cast to JSObject its --> [object Promise] – CrazyFisch Jul 28 '15 at 14:22
  • Embrace the asynchronous nature presented by the environment and not fight it. – Prusse Jul 28 '15 at 14:26
  • Don't try to "wait" for the response, try passing a callback to javascript. – Prusse Jul 28 '15 at 14:46
  • String delay = (String) window.call("goTask", "return arg"); function goTask(callback){ var call = new Function("arg",callback); routeMe().(function(result){ call(result); }); } I tried this and get undefined. Or did u mean something else? – CrazyFisch Jul 28 '15 at 14:52

2 Answers2

0

I do not know the tomtom service. But from reading your code return new Promise is working as intended, as you are receiving the Promise I would suggest having another function to receive the route then use a SOAP to read the data into your application

Bonatti
  • 2,778
  • 5
  • 23
  • 42
  • Well, I think I have no other opportunity to receive the route cause with the TomTom Api I have just access with this function. (I use a own Map Client from TomTom, not the website to get information. – CrazyFisch Jul 28 '15 at 14:14
  • Is there any opportunity to get Java wait on the Javascript? – CrazyFisch Jul 28 '15 at 14:21
  • I'm pretty sure the Promise object isn't what he wants to return to Java, he wants to return the value of the fulfilled promise. – Spork Jul 28 '15 at 14:25
  • @Spork It is not what he wants, but it is what he wrote for the JVM to do. My point is that he should use some in-between mode to write the data somewhere, Then have the other language go fetch it. Hence, the link – Bonatti Jul 28 '15 at 14:30
  • I actually want to get the value, I thought if I use the promise like this I will get the value... – CrazyFisch Jul 28 '15 at 14:34
  • 1
    @CrazyFisch Then please, detail furher your problem, in your question, writte down: Where are you running this? A phone? a GPS? a browser? then use [this](http://www.java2s.com/Tutorial/Java/0120__Development/ListingAllScriptEngines.htm) to find the engine, and writte it down as well. Finally, writte down what methods you already tried.. [things like this usually fix a lot of issues](https://blogs.oracle.com/javafx/entry/communicating_between_javascript_and_javafx) – Bonatti Jul 28 '15 at 16:26
0

Right now you are returning a Promise to Java, which doesn't know what to do with it. It won't wait for the promise to be fulfilled, and since there's no way of it interpreting the promise not much happens.

You can only handle this promise within Javascript, with something like .then( ... ), wherein you actually handle the result you expect right now (the delay).

Forcing the promise to be used synchronously will not work, it would be the same issue if you would want to handle your function result synchronously within Javascript (Call An Asynchronous Javascript Function Synchronously).

Try @Evan Knowles' answer here but with your callback instead:

We're going to set a listener for the successful state - basically we're going to inject a Java class into the JavaScript and have it call us back. Let's create a WebController that checks what is passed in and prints out the ID

How to catch return value from javascript in javafx?

Community
  • 1
  • 1
Spork
  • 1,631
  • 1
  • 21
  • 37
  • Correct, I want to use the value of the fulfilled promise. But I dont know enough of javascript to get rid of this problem. I tried .then(), but several times it failed and didn't worked for me... Do you have a code example of .then(..) I could use? – CrazyFisch Jul 28 '15 at 14:32
  • I'm a little rusty, does the return within the then not work? In that case... there is no way around the problem, and I'll delete my answer. – Spork Jul 28 '15 at 14:34
  • I tried your suggestion, but it gives me undefined. – CrazyFisch Jul 28 '15 at 14:37
  • I used your answer to get the edited code, but it's still a problem if i want the value right in that moment of calling the gogo function from javascript. – CrazyFisch Jul 29 '15 at 09:23
  • @CrazyFisch I'm glad it helped, you seem to be close to a good result. The thing you *want* is impossible (results from the asynchronous function synchronously), so you need to find a way of dealing with it differently, and you seem to be there! – Spork Jul 29 '15 at 09:31