Announcement

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

    Cannot set datasource ID for XSD DataSource

    Hi SmartGwt gurus,

    I'm hitting an issue setting the datasource ID when it's created from a XSD. This ID is needed to render the entity name in the RPC call to server:

    Code:
    <request>
        <data>
            <country> <---- here's where I use the ID
                <countryCode>A1</countryCode>
                <countryName>New Value</countryName>
                <capital>New Value</capital>
                <continent>New Value</continent>
                <area>45</area>
                <article>Article A1</article>
                <population>45</population>
                <member_g8>false</member_g8>
                <independence>2010-03-04T02:17:36</independence>
                <government>Despotism</government>
            </country>
        </data>
        <dataSource>country</dataSource>
        <operationType>add</operationType>
        <oldValues></oldValues>
     </request>
    Am I doing something wrong here?

    Many thanks!

    Regards,

    Cheng

    ----

    Here's the issue report:

    1. the SmartGWT or SmartClient version and browser version(s) involved;

    SmartGWT 2.2/2.4 - Chrome/FF - Win7

    2. for a server-side problem, the complete logs generated during processing of the request;

    N/A

    3. for a client-side problem, the contents of the Developer Console (see FAQ for usage);

    Code:
    00:18:44.418 [ERROR] [mybanners2] 00:18:44.408:XRP0:WARN:Log:java.lang.IllegalStateException: Cannot change configuration property 'ID' to supplyItem after the component has been created.
    
    com.smartgwt.client.core.JsObject$SGWT_WARN: 00:18:44.408:XRP0:WARN:Log:java.lang.IllegalStateException: Cannot change configuration property 'ID' to supplyItem after the component has been created.
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:105)
        at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
        at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:157)
        at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:281)
        at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:531)
        at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:352)
        at java.lang.Thread.run(Thread.java:662)
    4. if there is a JavaScript error, the stack trace logged in the Developer Console (from Internet Explorer if possible); and

    N/A

    5. sample code.

    I've only tweaked the XSD datasource example at showcase:
    http://www.smartclient.com/smartgwt/showcase/#featured_xsd_ds

    I'm pasting the code for conveniece. The line added is "schemaDS.setID("supplyItem");":

    Code:
    package com.googlecode.mybanners.client;
    
    /*
     * Smart GWT (GWT for SmartClient)
     * Copyright 2008 and beyond, Isomorphic Software, Inc.
     *
     * Smart GWT is free software; you can redistribute it and/or modify it
     * under the terms of the GNU Lesser General Public License version 3
     * as published by the Free Software Foundation.  Smart GWT is also
     * available under typical commercial license terms - see
     * http://smartclient.com/license
     *
     * This software is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
     * Lesser General Public License for more details.
     */
    
    import com.google.gwt.core.client.EntryPoint;
    import com.google.gwt.core.client.GWT;
    import com.smartgwt.client.core.KeyIdentifier;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.data.SchemaSet;
    import com.smartgwt.client.data.XMLTools;
    import com.smartgwt.client.data.XSDLoadCallback;
    import com.smartgwt.client.data.fields.DataSourceDateField;
    import com.smartgwt.client.data.fields.DataSourceTextField;
    import com.smartgwt.client.util.KeyCallback;
    import com.smartgwt.client.util.Page;
    import com.smartgwt.client.util.SC;
    import com.smartgwt.client.widgets.IButton;
    import com.smartgwt.client.widgets.events.ClickEvent;
    import com.smartgwt.client.widgets.events.ClickHandler;
    import com.smartgwt.client.widgets.form.DynamicForm;
    import com.smartgwt.client.widgets.grid.ListGrid;
    import com.smartgwt.client.widgets.layout.VLayout;
    
    public class XsdDataSourceSample implements EntryPoint {
    
      private VLayout layout;
    
      public void onModuleLoad() {
        if (!GWT.isScript()) {
          KeyIdentifier debugKey = new KeyIdentifier();
          debugKey.setCtrlKey(true);
          debugKey.setKeyName("D");
          Page.registerKey(debugKey, new KeyCallback() {
            public void execute(String keyName) {
              SC.showConsole();
            }
          });
        }
    
        final ListGrid listGrid = new ListGrid();
        listGrid.setCanEdit(true);
    
        final DynamicForm dynamicForm = new DynamicForm();
    
        final IButton validateButton = new IButton("Validate");
        validateButton.setDisabled(true);
    
        validateButton.addClickHandler(new ClickHandler() {
          public void onClick(ClickEvent event) {
            dynamicForm.validate();
    
          }
        });
    
        IButton loadButton = new IButton("Load Schema");
        loadButton.addClickHandler(new ClickHandler() {
          public void onClick(ClickEvent event) {
            XMLTools.loadXMLSchema("schema/supplyItem.xsd", new XSDLoadCallback() {
              public void execute(SchemaSet schemaSet) {
                loadXMLSchemaReply(schemaSet, listGrid, dynamicForm, validateButton);
              }
            });
          }
        });
    
        layout = new VLayout(15);
        layout.addMember(loadButton);
        layout.addMember(listGrid);
        layout.addMember(dynamicForm);
        layout.addMember(validateButton);
    
        layout.draw();
      }
    
      private void loadXMLSchemaReply(SchemaSet schemaSet, ListGrid listGrid,
          DynamicForm dynamicForm, IButton validateButton) {
        DataSource schemaDS = schemaSet.getSchema("supplyItem");
        schemaDS.setID("supplyItem");
    
        DataSource dataSource = new DataSource();
        dataSource.setInheritsFrom(schemaDS);
        dataSource.setUseParentFieldOrder(true);
    
        DataSourceTextField itemID = new DataSourceTextField("itemId");
        itemID.setHidden(true);
        itemID.setPrimaryKey(true);
    
        DataSourceTextField itemName = new DataSourceTextField("itemName",
            "item name");
        DataSourceDateField nextShipment = new DataSourceDateField("nextShipment",
            "next shipment");
        nextShipment.setUseTextField(true);
    
        dataSource.setFields(itemID, itemName, nextShipment);
    
        listGrid.setDataSource(dataSource);
        dynamicForm.setDataSource(dataSource);
    
        // to demonstrate grid editors, add sample data and start editing
    
        listGrid.setData(new ItemRecord[] { new ItemRecord(123, "Sample Item",
            "1091600", null, "Rollfix Glue", "Ea", 3.73, null, null) });
        listGrid.startEditing();
    
        // to demonstrate validation, use values that will fail validation
        dynamicForm.setValue("unitCost", -1.234);
        dynamicForm.setValue("SKU", "thisSkuIsWayTooLong");
        validateButton.enable();
    
      }
    
    }

    #2
    You can't change the ID of the DataSource derived from XML schema, but you can change the ID of the DataSource that inheritsFrom it (see the sample code you posted).

    Comment


      #3
      Originally posted by Isomorphic
      You can't change the ID of the DataSource derived from XML schema, but you can change the ID of the DataSource that inheritsFrom it (see the sample code you posted).
      I know it's been a long time but I tried your suggestion and it didn't work.

      I've replaced:

      Code:
      schemaDS.setID("supplyItem");
      for:
      Code:
      dataSource.setID("supplyItem");
      and I'm still getting the error:


      Error :Cannot change configuration property 'ID' to supplyItem after the component has been created.


      So the problem seems to be setID() since it's immutable. I've worked around it by bypassing setID() and directly setting the id as follows:

      Code:
        class MyDataSource extends DataSource {
          public MyDataSource(String id) {
            super();
            this.id = id;
          }
        }
      This let me advance a little only to hit the next roadblock:


      Error :Cannot change configuration property 'inheritsFrom' to [XSComplexType ID:supplyItem] after the component has been created.


      So the next change is to avoid setInheritFrom():

      Code:
        class MyDataSource extends DataSource {
          public MyDataSource(String id, DataSource schemaDS) {
            this.id = id;
            JSOHelper.setAttribute(config, "inheritsFrom", schemaDS.getOrCreateJsObj());
          }
        }
      which failed with this message:


      Error :Fields cannot be added to a DataSource after the underlying component has been created


      I'm out of clue here. Any help is appreciated

      Many thanks

      Comment


        #4
        Again, in the sample code, a new DataSource is created (literally the code is new DataSource()). You can setID() on that.

        Comment


          #5
          Originally posted by Isomorphic
          Again, in the sample code, a new DataSource is created (literally the code is new DataSource()). You can setID() on that.
          I'm sorry my point didn't get thru but I actually said that "new DataSource().setId()" doesn't work since it's throwing:


          Error :Cannot change configuration property 'ID' to supplyItem after the component has been created.

          Here is my snippet:

          Code:
          /*
           * Smart GWT (GWT for SmartClient)
           * Copyright 2008 and beyond, Isomorphic Software, Inc.
           *
           * Smart GWT is free software; you can redistribute it and/or modify it
           * under the terms of the GNU Lesser General Public License version 3
           * as published by the Free Software Foundation.  Smart GWT is also
           * available under typical commercial license terms - see
           * http://smartclient.com/license
           *
           * This software is distributed in the hope that it will be useful,
           * but WITHOUT ANY WARRANTY; without even the implied warranty of
           * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
           * Lesser General Public License for more details.
           */
          
          import com.google.gwt.core.client.EntryPoint;
          import com.google.gwt.core.client.GWT;
          import com.smartgwt.client.core.KeyIdentifier;
          import com.smartgwt.client.data.DataSource;
          import com.smartgwt.client.data.SchemaSet;
          import com.smartgwt.client.data.XMLTools;
          import com.smartgwt.client.data.XSDLoadCallback;
          import com.smartgwt.client.data.fields.DataSourceDateField;
          import com.smartgwt.client.data.fields.DataSourceTextField;
          import com.smartgwt.client.util.JSOHelper;
          import com.smartgwt.client.util.KeyCallback;
          import com.smartgwt.client.util.Page;
          import com.smartgwt.client.util.SC;
          import com.smartgwt.client.widgets.IButton;
          import com.smartgwt.client.widgets.events.ClickEvent;
          import com.smartgwt.client.widgets.events.ClickHandler;
          import com.smartgwt.client.widgets.form.DynamicForm;
          import com.smartgwt.client.widgets.grid.ListGrid;
          import com.smartgwt.client.widgets.layout.VLayout;
          
          public class XsdDataSourceSample implements EntryPoint {
          
            private VLayout layout;
          
            public void onModuleLoad() {
              if (!GWT.isScript()) {
                KeyIdentifier debugKey = new KeyIdentifier();
                debugKey.setCtrlKey(true);
                debugKey.setKeyName("D");
                Page.registerKey(debugKey, new KeyCallback() {
                  public void execute(String keyName) {
                    SC.showConsole();
                  }
                });
              }
          
              final ListGrid listGrid = new ListGrid();
              listGrid.setCanEdit(true);
          
              final DynamicForm dynamicForm = new DynamicForm();
          
              final IButton validateButton = new IButton("Validate");
              validateButton.setDisabled(true);
          
              validateButton.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                  dynamicForm.validate();
          
                }
              });
          
              IButton loadButton = new IButton("Load Schema");
              loadButton.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                  XMLTools.loadXMLSchema("schema/supplyItem.xsd", new XSDLoadCallback() {
                    public void execute(SchemaSet schemaSet) {
                      loadXMLSchemaReply(schemaSet, listGrid, dynamicForm, validateButton);
                    }
                  });
                }
              });
          
              layout = new VLayout(15);
              layout.addMember(loadButton);
              layout.addMember(listGrid);
              layout.addMember(dynamicForm);
              layout.addMember(validateButton);
          
              layout.draw();
            }
          
            private void loadXMLSchemaReply(SchemaSet schemaSet, ListGrid listGrid,
                DynamicForm dynamicForm, IButton validateButton) {
              DataSource schemaDS = schemaSet.getSchema("supplyItem");
          
              DataSource dataSource = new DataSource();
              dataSource.setID("supplyItem");
              dataSource.setInheritsFrom(schemaDS);
              dataSource.setUseParentFieldOrder(true);
          
              DataSourceTextField itemID = new DataSourceTextField("itemId");
              itemID.setHidden(true);
              itemID.setPrimaryKey(true);
          
              DataSourceTextField itemName = new DataSourceTextField("itemName",
                  "item name");
              DataSourceDateField nextShipment = new DataSourceDateField("nextShipment",
                  "next shipment");
              nextShipment.setUseTextField(true);
          
              dataSource.setFields(itemID, itemName, nextShipment);
          
              listGrid.setDataSource(dataSource);
              dynamicForm.setDataSource(dataSource);
          
              // to demonstrate grid editors, add sample data and start editing
          
              listGrid.setData(new ItemRecord[] { new ItemRecord(123, "Sample Item",
                  "1091600", null, "Rollfix Glue", "Ea", 3.73, null, null) });
              listGrid.startEditing();
          
              // to demonstrate validation, use values that will fail validation
              dynamicForm.setValue("unitCost", -1.234);
              dynamicForm.setValue("SKU", "thisSkuIsWayTooLong");
              validateButton.enable();
          
            }
          }

          Comment


            #6
            This code is incorrect in that it ends up with two DataSources with the same ID ("supplyItem"). However it doesn't throw the error you claim (if it did, almost all of the examples in the Showcase wouldn't work).

            Comment


              #7
              Originally posted by Isomorphic
              This code is incorrect in that it ends up with two DataSources with the same ID ("supplyItem"). However it doesn't throw the error you claim (if it did, almost all of the examples in the Showcase wouldn't work).
              I've narrowed down the problem to the XSD file. It has to do with the following line I've added to the XSD:

              Code:
                  <element name="supplyItem" type="tns:SupplyItemType"></element>
              which is creating a datasource with the name "supplyItem", thus conflicting with my second datasource which intends to inherit properties from it. Once I removed it, the error was gone.

              Now, why would XMLTools.loadXMLSchema() create two datasources, one with the name "supplyItem" and another with the name "SupplyItemType"? For my usecase it's better if the former is ignored so I can create a DataSource with an ID that matches the element name "supplyItem". Sometimes I don't even have control over the XSD so not being able to disable this behavior would be a blocker.

              Comment


                #8
                The docs for XMLTools.loadXMLSchema() explain what DataSources and other definitions result from loading an .xsd file.

                You have no particular reason to give your inheriting DataSource a conflicting ID, or any ID at all (an ID not required).

                Comment


                  #9
                  Originally posted by Isomorphic
                  The docs for XMLTools.loadXMLSchema() explain what DataSources and other definitions result from loading an .xsd file.

                  You have no particular reason to give your inheriting DataSource a conflicting ID, or any ID at all (an ID not required).
                  Thank you for the explanation. Really appreciate that.

                  Regarding the usecase of using an ID for a DataSource. The reason I'm explicitly setting the ID is to identify which entity I'm operating upon on the server side. So by setting a DataSource with ID "country" it would generate the following XML:

                  Code:
                  <request>
                      <data>
                          <country> <---- The ID
                              <countryCode>A1</countryCode>
                              <countryName>New Value</countryName>
                              <capital>New Value</capital>
                              <continent>New Value</continent>
                              <area>45</area>
                              <article>Article A1</article>
                              <population>45</population>
                              <member_g8>false</member_g8>
                              <independence>2010-03-04T02:17:36</independence>
                              <government>Despotism</government>
                          </country>
                      </data>
                      <dataSource>country</dataSource> <-- the ID
                      <operationType>add</operationType>
                      <oldValues></oldValues>
                   </request>
                  If such ID is not set, then it would be an auto-generated name like "isc_CountryDataSource_0" which I can't use to identify my entities on the server side:

                  Code:
                  <request>
                      <data>
                          <isc_CountryDataSource_0> <---- autogenerated ID
                              <countryCode>A1</countryCode>
                              <countryName>New Value</countryName>
                              <capital>New Value</capital>
                              <continent>New Value</continent>
                              <area>45</area>
                              <article>Article A1</article>
                              <population>45</population>
                              <member_g8>false</member_g8>
                              <independence>2010-03-04T02:17:36</independence>
                              <government>Despotism</government>
                          </isc_CountryDataSource_0>
                      </data>
                      <dataSource>isc_CountryDataSource_0</dataSource> <-- autogenerated ID
                      <operationType>add</operationType>
                      <oldValues></oldValues>
                   </request>
                  So this is why I have to set an ID. Because XmlTools creates a dataSource "countr" with <element name="country" type="tns:CountryType"></element>, this prevents me from creating a datasource that inherits from it.

                  Many thanks!

                  Comment


                    #10
                    You need to get the entity name to the server - this is not a reason to use a conflicting ID for the DataSource - use a standard prefix, for example. You can also control serialization via DataSource.tagName.

                    Comment


                      #11
                      Originally posted by Isomorphic
                      You need to get the entity name to the server - this is not a reason to use a conflicting ID for the DataSource - use a standard prefix, for example. You can also control serialization via DataSource.tagName.
                      Thanks, specifying both tagName (for serialization) and recordName (for deserialization) solved the problem of autogenerated XML element name.

                      To sum up:

                      DataSources don't need ID so don't specify them for the purpose of setting tagName. Do this instead:

                      Code:
                      dataSource.setRecordName("country");
                      dataSource.setTagName("country");
                      There's one small comment that I'd like to make. I found the message "Error :Cannot change configuration property 'ID' to supplyItem after the component has been created." a little bit confusing since I didn't realize that there's already a dataSource with the same name created. Is is possible to improve message by stating that there's already a datasource with the same name if that's the case?

                      Many thanks and keep up the good work!

                      Comment

                      Working...
                      X