Interesting. As far as I know it should not have worked. Your above example 
should map to JavaScript:

{ getUsername: function() { .... }, getProfilePictureUrl: function() { .... 
} }

At the bottom of the jsinterop page there is a link to the JsInterop 
spec: 
https://docs.google.com/document/d/10fmlEYIHcyead_4R1S5wKGs1t2I7Fnp_PaNaa7XTEk0/edit

It states that you need @JsProperty in that case. GWT compiler must know if 
it should treat the interface method as method or as property.

-- J.

Craig Mitchell schrieb am Montag, 13. Januar 2025 um 23:02:07 UTC+1:

> Thanks again Thomas,
>
> Yep, getters worked.  I thought I tried this previously, but obviously not.
>
> I didn't need the JsProperty annotation. maybe because the interface is 
> marked as native:
>
> @JsType(isNative = true, name = "?", namespace = JsPackage.GLOBAL)
> public interface CrazyGamesUser {
>   String getUsername();
>   String getProfilePictureUrl();
> }
>
> I'll update 
> https://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJsInterop.html 
> to mention this is how you access attributes using JsInterop.
>
> Cheers.
>
> On Tuesday, 14 January 2025 at 4:19:36 am UTC+11 Thomas Broyer wrote:
>
>> On Monday, January 13, 2025 at 10:14:33 AM UTC+1 [email protected] 
>> wrote:
>>
>> Hi Thomas,
>>
>> Can an interface have attributes?  I thought interfaces can only have 
>> methods?
>>
>>
>> Yes, you'd have to make them getters (probably need to annotate them with 
>> @JsProperty too)
>>  
>>
>> So if I make it:
>>
>> @JsType(isNative = true, name = "?", namespace = JsPackage.GLOBAL)
>> public interface CrazyGamesUser {
>> }
>>
>> I can't see how I can add the attributes:
>>
>> public String username;
>> public String profilePictureUrl;
>>
>> ?
>>
>> Thanks again.
>>
>> On Monday, 13 January 2025 at 7:03:43 pm UTC+11 Thomas Broyer wrote:
>>
>> Use an interface rather than a class.
>>
>> See the note about castability in the javadoc: 
>> https://javadoc.io/doc/com.google.jsinterop/jsinterop-annotations/latest/jsinterop/annotations/JsType.html
>>
>> Rule of thumb is: use a class only if it maps to a "constructor" in JS, 
>> i.e. something you'll either create an instance of, or use in an 
>> "instanceof" check; for everything else (generally something you get from 
>> another API or "receive" in a callback), use an interface.
>>
>> In this case, I think you could also use name="Object".
>>
>> On Monday, January 13, 2025 at 7:47:28 AM UTC+1 [email protected] 
>> wrote:
>>
>> Overlay types do work, and make it a little better:
>>
>> public class CrazyGamesUser extends JavaScriptObject {
>>   protected CrazyGamesUser() {}
>>   public final native String getUserName() /*-{ return this.username; 
>> }-*/;
>>   public final native String getProfilePictureUrl() /*-{ return 
>> this.profilePictureUrl; }-*/;
>> }
>>
>> However, it would be great if JsInterop just worked, so I could just do:
>>
>> @JsType(isNative = true, namespace = JsPackage.GLOBAL)
>> public static class CrazyGamesUser {
>>   public String username;
>>   public String profilePictureUrl;
>> }
>>
>> Maybe I'm missing something?
>> On Monday, 13 January 2025 at 4:02:40 pm UTC+11 Craig Mitchell wrote:
>>
>> I'm calling some existing JS that returns a JS Object which I've 
>> implemented in JsInterop:
>>
>> @JsType(isNative = true, namespace = "window.CrazyGames.SDK")
>> public static class JsUser {
>>     public native Promise<CrazyGamesUser> getUser();
>> }
>>
>> I can happily call it:
>> sdk.user.getUser()
>>   .then(user -> {
>>     // Do something with the user
>>     return null;
>>   })
>>   .catch_(error -> {
>>     return null;
>>   });
>>
>> This issue is I'm struggling to work out how to define the return object 
>> "CrazyGamesUser".  The actual JS object is just this:
>> {
>>     "username": "SingingCheese.TLNU",
>>     "profilePictureUrl": "
>> https://images.crazygames.com/userportal/avatars/4.png";
>> }
>>
>> If I define it like this:
>>
>> @JsType(isNative = true, namespace = JsPackage.GLOBAL)
>> public static class CrazyGamesUser {
>>   public String username;
>>   public String profilePictureUrl;
>> }
>>
>> I get a java.lang.ClassCastException.
>>
>> So if I set the name to "?":
>>
>> @JsType(isNative = true, name = "?", namespace = JsPackage.GLOBAL)
>> public static class CrazyGamesUser {
>>   public String username;
>>   public String profilePictureUrl;
>> }
>>
>> Then I get a compile error:
>> '?' can only be used as a name for native interfaces in the global 
>> namespace.
>>
>> But if I make it an interface, I can't have the member variables.
>>
>> If I do remove the member variables, it does work, and I can access them 
>> via some JSNI:
>>
>> public static native String getUsername(CrazyGamesUser instance) /*-{
>>   return instance.username;
>> }-*/;
>>
>> But that's really ugly.  What's the correct approach here?
>>
>> Thanks.
>>
>>

-- 
You received this message because you are subscribed to the Google Groups "GWT 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/google-web-toolkit/b0909a0e-46c5-4717-87c8-15eef025bbb3n%40googlegroups.com.

Reply via email to