Search code examples
javagwtjsni

Calling Java methods from inner function of GWT JSNI


I'm using W3C Geolocation API in order to retrieve location information within GWT web application. Geolocation API is built the way that callback function gets invoked as soon as location position is retrieved.

My current test code looks as follows:

public native void getCoordinates() /*-{
    function onPositionUpdate(position) {
        var lat = position.coords.latitude;
        var lng = position.coords.longitude;
        var alt = position.coords.altitude;

        // not OK,- doesn't get invoked, and function execution stops at this point
        [email protected]::testMethod()();

        alert("Coordinates retrieved: " + lat + ";" + lng + ";" + alt);
    }

    function onPositionUpdateFailed(error) {
        alert("Some error");
    }

    if(navigator.geolocation) {
        // OK when invoked somewhere here
        [email protected]::testMethod()();

        navigator.geolocation.getCurrentPosition(onPositionUpdate, onPositionUpdateFailed);
    } else {
        alert("Geolocation is not available");
    }
}-*/;

I'm trying to demonstrate that the method testMethod doesn't get invoked from inner method onPositionUpdate. Even more: no alert is shown afterwards (it does get shown when testMethod call is removed), but no warnings or errors are found in a log.

My question is: how do I reference this method from the inner function? I have feeling that this. is not a correct reference from the inner functions. If Java class cannot be referenced correctly, then what are the possible workarounds? Please note that I cannot pass anything else to function onPositionUpdate() as it's a callback function.


Solution

  • this is out of scope when a function defined within your javascript within the JSNI block is actually executed.

    Add a closure around this:

    public native void getCoordinates()
    /*-{
    
        var that = this;
    
        function onPositionUpdate(position) {
            var lat = position.Wecoords.latitude;
            var lng = position.coords.longitude;
            var alt = position.coords.altitude;
    
            [email protected]::testMethod()();
    
            alert("Coordinates retrieved: " + lat + ";" + lng + ";" + alt);
        }
    
        // ...
    }-*/;
    

    I was sure that this was documented in google's JSNI docs somewhere, at least in a passing example, but I can't find it now.

    This can also be accomplished by passing an instance through to the javascript injection, e.g.:

    public native void getCoordinates(com.test.GpsPanel instance)
    /*-{
    
        function onPositionUpdate(position)
        {
            var lat = position.Wecoords.latitude;
            var lng = position.coords.longitude;
            var alt = position.coords.altitude;
    
            [email protected]::testMethod()();
    
            alert("Coordinates retrieved: " + lat + ";" + lng + ";" + alt);
        }
    
        // ...
    }-*/;