JSNI - access inner class attribute from external JS?

108 views
Skip to first unread message

Jeff Ledgerwood

unread,
Jun 14, 2019, 2:45:39 PM6/14/19
to GWT Users
I am absolutely pulling my hear out with this one and I'm hoping someone can help.  I have been able to use JSNI on numerous other occasions to call GWT class functionality when needed.  It works very well once the syntax is figured out.  I need to do something similar but with an inner class.  I have an app that has an inner class within a GWT class.  I need to be able to access and change an attribute on that inner class from external/hand-written javascript.  

The GWT compiler is throwing an error: "Missing qualifier on instance method" and it's complaining about this line -- "$wnd.setValueFromExternal"

What is the proper way to call a GWT accessor from an external/hand-written javascript file when that accessor is within an inner class?


public class Foo extends DataEntryListener{

....

    public class Bar(){

        private int value;

        public int getValue(){

            return value;

        }

        public void setValue(int val){

            this.value = val;

        }

    }


public native void setValueFromExternal(int newValue) /*-{
$wnd.setValueFromExternal = $entry(@pkg.Foo.Bar::setValue(I)(newValue);
}-*/;
}


Here is the call from an external/hand-written javascript file:

function setValue(value){
    this.setValueFromExternal(value);

}

Jens

unread,
Jun 17, 2019, 6:15:26 AM6/17/19
to GWT Users
Your setValue() method must be static if you want to call it that way. If it must be an instance method you need to write barInstance.@pkg.Foo.Bar::method (don't forget the dot after instance variable)

-- J.

Jeff Ledgerwood

unread,
Jun 17, 2019, 12:35:07 PM6/17/19
to GWT Users


On Monday, June 17, 2019 at 5:15:26 AM UTC-5, Jens wrote:
Your setValue() method must be static if you want to call it that way. If it must be an instance method you need to write barInstance.@pkg.Foo.Bar::method (don't forget the dot after instance variable)

-- J.
 
Thanks for your help Jens.  Is there some documentation that explains this syntax to any degree?  All I can find is this and it isn't enough - http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html#calling


I've tried what you describe but when I call it from my external javascript I get an error indicating that the function I'm calling is not defined.  It passes the GWT compiler but at runtime it can't find the function.  I feel like the syntax isn't correct but I'm not seeing it.  Should "Bar" be the instance name of the internal class within the outer class?  I tried that too, same result.

Here is the updated native method:

public native void setValueFromExternal(int newValue) /*-{
Bar.maxInstance.@pkg.Foo.Bar::setValue(I)(newValue);
}-*/; 


The call from the external javascript file is still the same:

function setValue(value){
    this.setValueFromExternal(value);

}

Jens

unread,
Jun 17, 2019, 3:10:46 PM6/17/19
to GWT Users

Thanks for your help Jens.  Is there some documentation that explains this syntax to any degree?  All I can find is this and it isn't enough - http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html#calling

Thats the only information on the official site. http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html#methods-fields contains a short description how a JSNI method call is constructed.

 
I've tried what you describe but when I call it from my external javascript I get an error indicating that the function I'm calling is not defined. 

Be aware that GWT apps load asynchronous and you have to wait for it so that $wnd.setValueFromExternal is available once your external JS executes.

 
It passes the GWT compiler but at runtime it can't find the function.  I feel like the syntax isn't correct but I'm not seeing it.  Should "Bar" be the instance name of the internal class within the outer class?  I tried that too, same result.

So it sounds like you want setValue() to be an instance method. But at the same time it sounds like your external JS does not know anything about the Bar instance on which the external JS needs to call setValue(). In that case I would probably do


class Foo {

 
class Bar {

   
static void setValueFromExternal(int value) {
     
Bar barInstance = getBarInstanceSomeHow();
      barInstance
.setValue(value);
   
}

 
}
}

public static native void exportSetValueFromExternalFunction() /*-{
  // Note: when exporting functions do not write "setValueFromExternal(I)()" because that will call the function
  $wnd.setValueFromExternal = $entry(@com.example.Foo.Bar::setValueFromExternal(I));
}-*/


The above assumes that it is more natural to use Java code to get the Bar instance somehow. Of course you could also do it within the JSNI method but I would try to avoid real code in JSNI methods because that makes it easier to switch to JsInterop (something you should consider if you want that GWT code to be GWT 3 compatible).


-- J.
Reply all
Reply to author
Forward
0 new messages