Announcement

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

    SelectItem calls toString on invalid Java object

    Version: SmartClient Version: v11.0p_2016-09-30/LGPL Development Only (built 2016-09-30)
    Browser: Chrome Version 52.0.2743.116 m

    One of the problems we have while upgrading our project to SmartGWT 6.0

    One of our SelectItem form items will cause an exception when we add a value object to it. From what we can see, SmartGWT seems to call toString on an non-initialized instance of our item object.
    I created a minimal case which shows this happening:
    Code:
    public class TestClass {
        private String name = "TestName";
        private static int IDCounter = 1;
        private int ID;
        
        public TestClass(String name) {
            ID = IDCounter++;
            this.name = name;
        }
        
        @Override
        public String toString() {
            Log.message("ID: " + ID);
            return "Name length: " + name.length();
        }
    }
    Code:
    testSelectItem = new SelectItem();
    testForm = new DynamicForm();
    testForm.setItems(testSelectItem);
    testSelectItem.setValue(new TestClass("123"));
    When running this, it will print ID as 0(Expected 1), and throw an exception on the return:
    1. TypeError: Cannot read property 'length' of undefined
    2. at $length_14_g$ (code-0.js:1150:26)
    3. at length__I__devirtual$_1_g$ (code-0.js:1789:10)
    4. at toString_127_g$ [as toString$] (code-0.js:293735:28)
    5. at _.toString (code-0.js:345:15)
    6. at Object.isc_isA_Date [as Date] (http://localhost:55020/code/sc/modul...Core.js:143:10)
    7. at Object.isc_FormItem__formatDataType [as $17c] (http://localhost:55020/code/sc/modul...orms.js:943:12)
    8. at Object.isc_FormItem_mapValueToDisplay [as mapValueToDisplay] (http://localhost:55020/code/sc/modul...Forms.js:935:9)
    9. at Object.isc_c_Class_invokeSuper [as invokeSuper] (http://localhost:55020/code/sc/modul...ore.js:273:162)
    10. at Object.isc_SelectItem_mapValueToDisplay [as mapValueToDisplay] (http://localhost:55020/code/sc/modul...rms.js:2079:13)
    11. at Object.isc_FormItem_getDisplayValue [as getDisplayValue] (http://localhost:55020/code/sc/modul...orms.js:931:13)
    12. at Object.isc_FormItem__showValue [as $124t] (http://localhost:55020/code/sc/modul...orms.js:981:13)
    13. at Object.isc_FormItem_setValue [as setValue] (http://localhost:55020/code/sc/modul...orms.js:978:28)
    14. at Object.isc_c_Class_invokeSuper [as invokeSuper] (http://localhost:55020/code/sc/modul...ore.js:273:162)
    15. at Object.isc_SelectItem_setValue [as setValue] (http://localhost:55020/code/sc/modul...ms.js:2072:912)
    16. at Object.isc_DynamicForm_setItemValues [as setItemValues] (http://localhost:55020/code/sc/modul...rms.js:379:163)
    17. at Object.isc_DynamicForm_setValues [as setValues] (http://localhost:55020/code/sc/modul...orms.js:275:22)
    18. at Object.isc_DynamicForm_initWidget [as initWidget] (http://localhost:55020/code/sc/modul...orms.js:211:49)
    19. at Object.isc_Canvas_init [as init] (http://localhost:55020/code/sc/modul...ore.js:2126:19)
    20. at Object.isc_Class_completeCreation [as completeCreation] (http://localhost:55020/code/sc/modul..._Core.js:323:6)
    21. at Object.isc_c_Class_create (http://localhost:55020/code/sc/modul...re.js:211:1837)
    22. at create_199_g$ (code-0.js:200521:48)
    23. at getOrCreateJsObj_6_g$ [as getOrCreateJsObj_14_g$] (code-0.js:85140:23)
    24. at addMember_2_g$ [as addMember_11_g$] (code-0.js:94414:37)
    25. at onModuleLoad_5_g$ (code-0.js:290756:19)
    26. at Array.init_2_g$ (code-0.js:46309:46)
    27. at initializeModules_0_g$ (code-0.js:221:30)
    28. at apply_0_g$ (code-0.js:11977:28)
    29. at entry0_0_g$ (code-0.js:12047:14)
    30. at code-0.js:12013:14
    31. at gwtOnLoad_0_g$ (code-0.js:234:40)
    32. at code-0.js:426181:1
    It seems that it is calling on toString on a Java class instance, before running the constructor and variable setup.
    Last edited by wildex999; 30 Sep 2016, 03:55.

    #2
    SmartGWT doesn't actually have the ability to bypass your Object's constructor (just as no Java library could do this in ordinary Java).

    What you might be seeing is some kind of corruption issue with your GWT project - you should try clearing the browser cache, clearing the GWT unitcache, restarting both your browser and IDE, and ultimately reinstalling GWT.

    Comment


      #3
      I tried creating a completely new SmartGWT project to see if I could reproduce the problem. However, then everything just seems to work. No exception or anything.

      However, no clearing of cache, recompiling, using different browsers or even different computers seem to fix the problem in our main project.
      I can only assume there is something else in our project which causes it, but I have had no luck tracking it down.

      Two tings seems to fix the problem:
      1. Calling selectItem.setValue(newClassInstance) AFTER the draw has completed.
      2. Calling selectItem.setValue(newClassInstance) with an instance which is not completely new.

      The second point might be of interest. As it seems that the exception only happens if nothing has changed the object instance before setting it at the SelectItem.
      Simply calling newClassInstance.setTitle("Test") will make it run just fine. I honestly have no idea what might cause this. For now, we are simply calling setTitle("") on our new instance before adding it, however it does feel more like a hack than a fix.


      EDIT: Found another case where this is happening. This time in a ListGrid cell edit.
      Cannot read property 'getValue_272_g$' of undefined.
      Code:
      getName_49_g$ (Profile.java:76)
      hashCode_20_g$ (Profile.java:388)
      hashCode__I__devirtual$_0_g$ (Object.java:78)
      $toString_0_g$ (Object.java:83)
      toString_0_g$ (Object.java:82)
      _.toString (Object.java:26)
      isc_isA_Date (ISC_Core.js:143)
      isc_c_DynamicForm_valuesHaveChanged (ISC_Forms.js:621)
      isc_DynamicForm_valuesHaveChanged (ISC_Forms.js:282)
      isc_DynamicForm_getChangedValues (ISC_Forms.js:282)
      isc_ListGrid_storeUpdatedEditorValue (ISC_Grids.js:2165)
      isc_ListGrid_getEditValues (ISC_Grids.js:2044)
      isc_ListGrid_saveEdits (ISC_Grids.js:2233)
      isc_ListGrid__saveAndHideEditor (ISC_Grids.js:2196)
      isc_ListGrid_cellEditEnd (ISC_Grids.js:2160)
      isc_ListGrid__handleClickOutsideEditor (ISC_Grids.js:2035)
      (anonymous function) (VM11609:2)
      isc_c_Class_fireCallback (ISC_Core.js:282)
      isc_c_EventHandler__clickMaskClick (ISC_Core.js:1892)
      isc_c_EventHandler_clickMaskClick (ISC_Core.js:1890)
      isc_c_EventHandler_doHandleMouseDown (ISC_Core.js:1498)
      isc_c_EventHandler_handleMouseDown (ISC_Core.js:1493)
      isc_c_EventHandler_dispatch (ISC_Core.js:1782)
      (anonymous function) (VM11430:3)
      We pass in a working instance of an object to SmartGWT, and somewhere along the chain, it replaces it with an uninitialized instance of the same class.
      isc_isA_Date (ISC_Core.js:143) seems a repeat offender.
      In this case, getName should never get a "undefined" exception, as it's given a value in the class initialization:

      Code:
      public class Profile {
      ...
      final BindName name = new BindName(...);
      ...
      public String getName() {
          return name.getValue();
      }
      All of this worked perfectly before we upgraded to SmartGWT 6.0.
      Last edited by wildex999; 6 Oct 2016, 04:46. Reason: Added another case

      Comment


        #4
        Ok, it does seem that isc_isA_Date is at fault here, or something which ends up calling it is.
        The point of isA_Date seems to be a check if the given object is a Date object. This is the part where it seems to fail:
        Code:
        return(""+_1.constructor)==(""+Date)&&_1.getDate&&isc.isA.Number(_1.getDate())},
        I put a breakpoint on this line, and every time it's called, _1.constructor is a function.
        However, for some reason this is called with _1.constructor being an object in the cases above.
        Thus, this forces a call to toString on that object, which at that point is an uninitialized Java Object(It's prototype object?), and throws an exception.

        Either something is passing along the wrong argument to isc_isA_Date, or it does not expect the objects toString to be dependent on a working instance.

        Comment


          #5
          Good investigative work, but again, SmartGWT does not have the capability to postpone object initialization or access uninitialized Java objects, just as we would not if this were actual Java. So you seem to have found some kind of bug in core GWT that occurs just for you in your particular setup.

          Comment


            #6
            This problem is not something that only occurs for a unique project setup of wildex999 : I recreated this bug using the set up of the sample HelloWorld project shipped with smartgwt in smartgwt-6.0p.zip

            My steps to reproduce wildex999's error:
            - Downloaded gwt 2.8.0 and set %GWT_HOME% to point to where this was stored.
            - Downloaded and extracted smartgwt-6.0p.zip found at https://www.smartclient.com/builds/S...rtgwt-6.0p.zip
            - Modified \smartgwt-6.0p\helloworld-2.0\src\com\mycompany\client\HelloWorld.java to the following:

            Code:
            package com.mycompany.client;
            
            import com.google.gwt.core.client.EntryPoint;
            import com.smartgwt.client.widgets.form.DynamicForm;
            import com.smartgwt.client.widgets.form.fields.SelectItem;
            
            /**
             * Entry point classes define onModuleLoad().
             */
            public class HelloWorld implements EntryPoint {
                
                /**
                 * This is the entry point method.
                 */
                @Override
                public void onModuleLoad() {
                    SelectItem testSelectItem = new SelectItem();
                    DynamicForm testForm = new DynamicForm();
                    testForm.setItems(testSelectItem);
                    testSelectItem.setValue(new TestClass("123"));
                    
                    testForm.draw();
                }
                
                
                private static class TestClass {
                    private String name = "TestName";
                    private static int IDCounter = 1;
                    private int ID;
                    
                    public TestClass(String name) {
                        ID = IDCounter++;
                        this.name = name;
                    }
                    
                    @Override
                    public String toString() {
                        return "Name length: " + name.length();
                    }
                }
            }
            - Built the project and ran it in SuperDevMode (ant hosted).
            - Opened the hosted web-page and got the mentioned error in TestClass.toString() because of 'name' being undefined.

            So, this problem occurs also on rather "standard" setup.
            Last edited by someDeveloper; 14 Nov 2016, 13:18.

            Comment


              #7
              As we've covered, neither SmartGWT nor any other GWT code has the ability skip Object initialization. So this strongly suggests a GWT bug.

              someDeveloper, can you reproduce this with GWT 2.7? Maybe it's a new bug.

              wildex999, are you also using GWT 2.8? Did you switch to GWT 2.8 at the same time as you upgraded your project to a more recent SmartGWT version?

              Comment


                #8
                Thanks for the quick response. Yes, I can reproduce it with GWT 2.7. I can also reproduce it with older SmartGWT versions (tested with version 5.0p from 2014-11-23).
                I am on the same project as wildex999, and saw this error only after upgrading to SmartGWT 6.0p. However, it does seem like it (the isolated version of the bug - described in this forum) is actually an old bug which simply haven't been triggered by our project until upgrading SmartGWT. So upgrading SmartGWT must have altered some code paths. Nevertheless, this is something which is not working correctly, either in SmartGWT or in GWT.

                Comment


                  #9
                  We are able to reproduce the issue and are investigating. If a solution is made, we'll update this thread.

                  Comment


                    #10
                    From what we see, this is a SuperDevMode-only issue, and doesn't happen in Production Mode. Is that consistent with what you're seeing?

                    Comment


                      #11
                      You haven't responded with the requested information, but we've applied a fix to SGWT 6.0p/SC 11.0p and newer branches to address this problem where we observed it - in SGWT SuperDevMode. It should be in the nightly builds dated 2016-11-19 and beyond.

                      Comment


                        #12
                        Thank you for the quick work and sorry for the late reply. Our project now works nicely in SuperDevMode. Unfortunately, we still see the bug in production mode. That is, the simple code example posted earlier now works both in SuperDevMode and in production mode, but our project code only works in SuperDevMode.
                        Could you apply the fix of SuperDevMode also to production mode? I realize this might be harder to check as you don't really have a failing example to compare to.

                        Comment

                        Working...
                        X