Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    #16
    Sorry to keep doggedly going after this, but we're really trying to understand your suggestion here..

    It seems like you are asking for direct J2CL support in addition to supporting GWT versions that work via J2CL.

    1. is that correct?

    And then:

    2. what is the advantage of direct J2CL support, if we already support GWT versions that use J2CL?

    We can't figure out why this would matter to you, so we're sincerely trying to figure out if we've missed some kind of advantage here, perhaps something non-obvious.

    Comment


      #17
      Sorry to keep doggedly going after this, but we're really trying to understand your suggestion here..
      That's okay.

      It seems like you are asking for direct J2CL support in addition to supporting GWT versions that work via J2CL.
      Yes, that would align SmartClient with GWT3's goals of cross-compatibility with both the EOL's GWT2 Java compiler and the J2CL complier.

      2. what is the advantage of direct J2CL support, if we already support GWT versions that use J2CL?
      The problem is that most of the world thinks GWT is dead, and have moved on as Google did. Many GWT projects have been rewritten in React/Angular/J2CL/TypeScript/etc, and many more having been mulling it. The advantage with J2CL support is that current SmartGWT users can be confident to continue with SmartClient technology without needing to wed themselves to the drama created by GWT's problems.

      I'm confident that today's announcement does inject some life into GWT again, but it begs the question whether the project is still in a hospice. And whether it can convince existing users to stay onboard, and attract new users into the community again.

      From Isomorphic's perspective, J2CL support is likely to bring in more customers that you wouldn't have had otherwise had. Indeed, Isomorphic's main competitors have moved away from and decoupled themselves from GWT for these reasons.

      Comment


        #18
        We've never been coupled to GWT - our product existed 6 years before the GWT project was even started, and it has always been more powerful and a lot more flexible{1} if you do not use GWT.

        Anyone concerned about the future of GWT - or perhaps more generally concerned about the future of Google's support for Java to JS translation - should look at SmartGWT's sister product, SmartClient, which has TypeScript support for those looking for static error checking and strong IDE support.

        Another great way to future proof yourself is to make use of Component XML, which is supported by both SmartGWT and SmartClient. Similarly, use Reify to build most of your UI and basic interactivity, and you will further minimize any dependencies on a specific client-side implementation language, while still getting all the power of our platform.



        That all said, given Google's extensive in-house use of GWT, and given that SmartGWT only needs Java > JS translation and absolutely nothing else, it takes some serious imagination to construct a circumstance in which committing to SmartGWT is an issue.

        Even if, because of some crazy apocalyptic scenario, GWT 2.9 is the last GWT release, that's Java 11 support, which will be current enough to use for several years, and still acceptable for years beyond that.

        So you have Java 11 support and indefinite support for the latest browsers (we don't use GWT for browser support) and well as feature development continuing at the breakneck pace we've always done - none of that depends on GWT.

        And that's examining at extremely implausible, worst case scenario.



        So, we will be looking at J2CL, because it's a good idea to support it for, say, projects beginning in maybe 2028 - but there's no pressing need, or cause for concern. Other GWT projects maybe, but not us.



        {1} GWT's monolithic compilation model, and lack of support for Java reflection, makes it difficult to build extremely flexible applications (like, for example, Reify). The fact that SmartClient is more powerful and flexible than SmartGWT is not a choice Isomorphic made, it's just how GWT is.

        Comment


          #19
          Thanks. This makes sense.

          Comment


            #20
            Originally posted by Isomorphic View Post
            We don't know of any incompatibilities with GWT 2.9. We haven't had incompatibility with previous releases because we don't use GWT for anything except Java > JS translation. Our widgets, data binding, class system etc is all separate.

            For the same reason, JSInterop will not change any of SmartGWT's APIs.

            If there is some functional improvement that is possible in the framework that you believe GWT's new features enable, please let us know.
            GWT 2.9 seems totally broken regarding JSNI, when calling "var v = getAttributeAsJavaScriptObject(k)" on a Record then store k,v in a Map<String, JavaScriptObject> we get back a ClassCastException when doing a ForeEach on that Map (same thing happen using "for" on EntrySet)! Seems that there is some sort of wrong implicit conversion

            this was working perfectly with GWT 2.8.2, as a result we switched back for the moment...

            Comment


              #21
              Is this something that affects the SmartGWT API, or only your own JSNI?

              A test case showing the crash would be really great, especially with some details on which browser(s) were affected, and the mode you were running in (Hosted Mode, SuperDevMode)?

              Hosted Mode (as in, the old mode where a JVM is actually running your app while connected to the browser) has been deprecated for a while, so we would be unsurprised if that's completely broken now. But it would be a surprise if they broke SuperDevMode even when new Java features are not being used (we do not use them in SmartGWT core APIs).

              Comment


                #22
                Originally posted by Isomorphic View Post
                Is this something that affects the SmartGWT API, or only your own JSNI?

                A test case showing the crash would be really great, especially with some details on which browser(s) were affected, and the mode you were running in (Hosted Mode, SuperDevMode)?

                Hosted Mode (as in, the old mode where a JVM is actually running your app while connected to the browser) has been deprecated for a while, so we would be unsurprised if that's completely broken now. But it would be a surprise if they broke SuperDevMode even when new Java features are not being used (we do not use them in SmartGWT core APIs).
                It was JSNI from SmartGWT : the code from getAttributeAsJavaScriptObject in DataClass, I'm not sure if anything can be done to circumvent that... maybe there is somet I was using Chrome 81.0.4044.138, we never used Hosted Mode, but anyway it was the result after compilation via gradle with no optimize=0 and draftCompile=true...
                We finally decided not to use getAttributeAsJavaScriptObject and used instead getAttribute and stored POJOs in the map instead of JSO...

                Comment


                  #23
                  OK, not immediately following your use case, but can we get some details?

                  1. it sounds as if you're saying that the SmartGWT API per se did not misbehave, but when you retrieved a JavaScript Object from a SmartGWT API, GWT blew up on interactions with that object, is that correct?

                  2. Did that only happen with Java 9+ syntax or is this something that happened with existing (Java 8-) code?

                  3. What use case caused you to go directly to JavaScriptObject? So you know, we want to craft our APIs so this is not necessary except for edge cases (as a completely separate concern from JSNI vs JSInterop issues)

                  4. Outside of this case, have you see any other issues with GWT 2.9, or is it generally working for your app?

                  Finally, a test case that shows how you broke GWT 2.9 would be really useful to us. Thanks!

                  Comment


                    #24
                    1. yes correct, when doing a for or foreach on the resulting map that should contain only JavaScriptObject as values, it throws a ClassCastException on internal CheckType just before executing the for, I tried to print debug when building the map juste after the return of getAttributeAsJavaScriptObject and it said that jso.getClass().getSimpleName() was a "String" instead of "JavaScriptObject"
                    2. I did used Java 8 syntax, no var type or whatever coming from java 9, but there was lambdas which may behave differently underneath, and it was compiled using java 11 as target...
                    3. I wanted to save primary keys from a ListGridRecord according to the DataSource definition of the ListGrid and store it into a JSONObject
                    4. At this early stage nothing else seemed to go wrong to my surprise...
                    Here is an extract of the problematic code which work before GWT 2.9.0

                    Code:
                    public abstract class BaseList extends ListGrid
                    {
                    
                        public void saveSelectedRecord(int type)
                        {
                            Record record = getSelectedRecord();
                            if (record != null)
                                savePK(type, getPKMap(getDataSource(), record));
                        }
                    
                        public static Map<String, JavaScriptObject> getPKMap(DataSource ds, Record record)
                        {
                            return Stream.of(ds.getPrimaryKeyFieldNames()).collect(Collectors.toMap(k -> k, k -> record.getAttributeAsJavaScriptObject(k)));
                        }
                    
                        public static void savePK(int type, Map<String, JavaScriptObject> map)
                        {
                            if (map != null)
                            {
                                final JSONObject json = new JSONObject();
                                map.forEach((k, v) -> json.put(k, new JSONObject(v)); // <- this is failing here
                                /* ...then do something with json to save it into browser's LocalStorage  */
                        }
                    }
                    and how I prevented this to fail (while still being Java 8 compatible) :

                    Code:
                    public abstract class BaseList extends ListGrid
                    {
                        public void saveSelectedRecord(int type)
                        {
                            Record record = getSelectedRecord();
                            if(record != null)
                                savePK(type, getPKMap(getDataSource(), record));
                        }
                    
                        public static Map<String, ?> getPKMap(DataSource ds, Record record)
                        {
                            return Stream.of(ds.getPrimaryKeyFieldNames()).collect(Collectors.toMap(k -> k, k -> record.getAttribute(k)));
                        }
                    
                        public static void savePK(int type, Map<String, ?> map)
                        {
                            if(map != null)
                            {
                                final JSONObject json = new JSONObject();
                                map.forEach((k, v) -> {
                                    if(v instanceof JavaScriptObject)
                                        json.put(k, new JSONObject((JavaScriptObject)v));
                                    else if(v instanceof String)
                                        json.put(k, new JSONString((String)v));
                                    else if(v instanceof Boolean)
                                        json.put(k, JSONBoolean.getInstance((Boolean)v));
                                    else if(v instanceof Number) json.put(k, new JSONNumber(((Number)v).doubleValue()));
                                });
                                /* ...then do something with json to save it into browser's LocalStorage  */
                            }
                        }
                    
                    }
                    Last edited by opty; 19 May 2020, 04:09.

                    Comment


                      #25
                      I can also confirm that compiling using java 1.8 as sourceLevel and sourceCompatibility/targetCompatibility gave the same result, the console output is giving this :

                      14:22:49.004:XRP7:WARN:Log:java.lang.ClassCastException
                      at java.lang.Throwable.createError(webclient-0.js)
                      at java.lang.Throwable.initializeBackingError(webclient-0.js)
                      at java.lang.Throwable.Throwable(webclient-0.js)
                      at java.lang.Exception.Exception(webclient-0.js)
                      at java.lang.RuntimeException.RuntimeException(webclient-0.js)
                      at lang.ClassCastException.ClassCastException(webclient-0.js)
                      at internal.InternalPreconditions.checkCriticalType(webclient-0.js)
                      at internal.InternalPreconditions.checkType(webclient-0.js)
                      at internal.InternalPreconditions.checkType(webclient-0.js)
                      at google.gwt.lang.Cast.castToJso(webclient-0.js)
                      at compodata.capture.client.webclient.forms.lists.BaseList$lambda$7$Type.accept(webclient-0.js)
                      at util.Map.$forEach(webclient-0.js)
                      at java.util.AbstractMap.forEach(webclient-0.js)
                      at capture.client.webclient.forms.lists.BaseList.savePK(webclient-0.js)
                      at compodata.capture.client.webclient.forms.lists.BaseList.saveSelectedRecord(webclient-0.js)
                      ....

                      Comment


                        #26
                        seems that getClass().getSimpleName() will always return the underlying type and not the original java class type

                        Comment


                          #27
                          Hi opty,

                          I saw in https://gitter.im/gwtproject/gwt that right now every change of sourceCompatibility/targetCompatibility will require a clean - in case you were using SuperDevMode and not a full compile, see also here.

                          Best regards
                          Blama

                          Comment


                            #28
                            Hi Blama

                            That could explain why this is only happening from SmartGWT API and not elsewhere in our code, and if I'm not wrong, DataClass is never recompiled since it come from a jar library... And that would mean that you can't mix up with gwt libs "precompiled" with an older java than yours!

                            Regards

                            Comment


                              #29
                              Just to throw our 5 cents to this: We have a very complex SmartGWT based app (currently using 12.0p nightly) and we have transitioned to GWT 2.9.0 with no problems. We've been on it from its release and so far haven't encountered any anomalies.

                              Comment

                              Working...
                              X