Announcement

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

    serverCustom validator: dependentField not passed to server

    SmartClient Version: v11.0p_2016-08-18/Enterprise Development Only (built 2016-08-18)

    Chrome on OSX

    Hello, I found a problem with a <serverCondition> validator, where a 'dependentFields' field is not passed in.

    Please modify the #inlineScriptValidation sample like this:

    Code:
    isc.ValuesManager.create({
        ID: "myVM",
        dataSource: "inlineScript_orderForm"
    });
    
    
    isc.DynamicForm.create({
        validateOnChange:true,
        valuesManager:"myVM",
        fields: [
            { type:"header", defaultValue:"Add an item to your Order" },
            { name:"itemId", title:"Item", editorType:"ComboBoxItem", optionDataSource:"StockItem",
                valueField:"id", displayField:"description" },
            { name:"quantity", validateOnExit:true },
            { name:"instructions", editorType:"TextAreaItem" },
            { type:"submit", title:"Submit Order" }
        ]
    });
    then modify the inlineScript_orderForm dataSource like this:
    Code:
    <DataSource ID="inlineScript_orderForm" serverType="sql">
        <fields>
            <field name="orderItem" type="sequence" primaryKey="true"/>
            <field name="itemId" foreignKey="StockItem.id"/>
            <field name="quantity" type="integer">
                <validators>
                    <validator type="serverCustom" dependentFields="orderItem">
                        <serverCondition language="groovy"><![CDATA[
                            value < dataSource.fetchById(record.orderItem).quantity
                        ]]></serverCondition>
                        <errorMessage>Not enough in stock</errorMessage>
                    </validator>
                </validators>
            </field>
            <field name="instructions" type="text"/>
         </fields>
    </DataSource>
    select an item, and then start typing in the quantity field. You'll see in the tomcat logs that 'orderItem' is not in the payload (while there's itemId):

    Code:
    === 2016-08-19 14:13:29,988 [83-5] DEBUG RPCManager - Processing 1 requests.
    === 2016-08-19 14:13:29,989 [83-5] DEBUG RPCManager - Request #1 (DSRequest) payload: {
        values:{
            itemId:1,
            quantity:9
        },
        operationConfig:{
            dataSource:"inlineScript_orderForm",
            repo:null,
            operationType:"validate",
            textMatchStyle:"exact"
        },
        validationMode:"partial",
        pendingAdd:true,
        appID:"builtinApplication",
        operation:"inlineScript_orderForm_validate",
        oldValues:{
            itemId:1,
            quantity:9
        },
        criteria:{
        }
    }
    === 2016-08-19 14:13:29,989 [83-5] INFO  IDACall - Performing 1 operation(s)
    === 2016-08-19 14:13:29,989 [83-5] DEBUG DeclarativeSecurity - Processing security checks for DataSource null, field null
    === 2016-08-19 14:13:29,989 [83-5] DEBUG DeclarativeSecurity - DataSource inlineScript_orderForm is not in the pre-checked list, processing...
    === 2016-08-19 14:13:29,989 [83-5] DEBUG AppBase - [builtinApplication.inlineScript_orderForm_validate] No userTypes defined, allowing anyone access to all operations for this application
    === 2016-08-19 14:13:29,989 [83-5] DEBUG AppBase - [builtinApplication.inlineScript_orderForm_validate] No public zero-argument method named '_inlineScript_orderForm_validate' found, performing generic datasource operation
    === 2016-08-19 14:13:29,991 [83-5] DEBUG DeclarativeSecurity - [builtinApplication.inlineScript_orderForm_validate] Processing security checks for DataSource null, field null
    === 2016-08-19 14:13:29,991 [83-5] DEBUG DeclarativeSecurity - [builtinApplication.inlineScript_orderForm_validate] Request is not a client request, ignoring security checks.
    === 2016-08-19 14:13:29,991 [83-5] DEBUG AppBase - [builtinApplication.inlineScript_orderForm_validate, builtinApplication.null] No userTypes defined, allowing anyone access to all operations for this application
    === 2016-08-19 14:13:29,991 [83-5] DEBUG AppBase - [builtinApplication.inlineScript_orderForm_validate, builtinApplication.null] No public zero-argument method named '_null' found, performing generic datasource operation
    === 2016-08-19 14:13:29,991 [83-5] INFO  SQLDataSource - [builtinApplication.inlineScript_orderForm_validate, builtinApplication.null] Performing fetch operation with
        criteria: {orderItem:null}    values: {orderItem:null}
    === 2016-08-19 14:13:29,992 [83-5] INFO  SQLDataSource - [builtinApplication.inlineScript_orderForm_validate, builtinApplication.null] derived query: SELECT $defaultSelectClause FROM $defaultTableClause WHERE $defaultWhereClause
    === 2016-08-19 14:13:29,992 [83-5] INFO  SQLDataSource - [builtinApplication.inlineScript_orderForm_validate, builtinApplication.null] 735: Executing SQL query on 'HSQLDB': SELECT inlineScript_orderForm.orderItem, inlineScript_orderForm.itemId, inlineScript_orderForm.quantity, inlineScript_orderForm.instructions FROM inlineScript_orderForm WHERE (inlineScript_orderForm.orderItem IS NULL)
    === 2016-08-19 14:13:29,992 [83-5] DEBUG SQLConnectionManager - [builtinApplication.inlineScript_orderForm_validate, builtinApplication.null] Borrowed connection '1990234682'
    === 2016-08-19 14:13:29,992 [83-5] INFO  SQLDriver - [builtinApplication.inlineScript_orderForm_validate, builtinApplication.null] Executing SQL query on 'HSQLDB' using connection '1990234682': SELECT inlineScript_orderForm.orderItem, inlineScript_orderForm.itemId, inlineScript_orderForm.quantity, inlineScript_orderForm.instructions FROM inlineScript_orderForm WHERE (inlineScript_orderForm.orderItem IS NULL)
    === 2016-08-19 14:13:29,993 [83-5] INFO  DSResponse - [builtinApplication.inlineScript_orderForm_validate] DSResponse: List with 0 items
    === 2016-08-19 14:13:29,993 [83-5] DEBUG SQLDataSource - [builtinApplication.inlineScript_orderForm_validate] About to clear SQLDriver state for DS instance 735
    === 2016-08-19 14:13:29,993 [83-5] DEBUG SQLDriver - [builtinApplication.inlineScript_orderForm_validate] Freeing SQLDriver dbConnection 1990234682 for SQLDriver instance 1946047614
    === 2016-08-19 14:13:29,993 [83-5] DEBUG SQLConnectionManager - [builtinApplication.inlineScript_orderForm_validate] About to close connection with hashcode "1990234682"
    === 2016-08-19 14:13:29,993 [83-5] DEBUG PoolableSQLConnectionFactory - [builtinApplication.inlineScript_orderForm_validate] Passivating connection '1990234682
    === 2016-08-19 14:13:29,993 [83-5] DEBUG SQLDataSource - [builtinApplication.inlineScript_orderForm_validate] About to clear SQLDriver state for DS instance 735
    === 2016-08-19 14:13:29,993 [83-5] DEBUG SQLDataSource - [builtinApplication.inlineScript_orderForm_validate] About to clear SQLDriver state for DS instance 735
    === 2016-08-19 14:13:29,994 [83-5] ERROR DefaultValidators - [builtinApplication.inlineScript_orderForm_validate] Failed to evaluate script.
    java.lang.NullPointerException: Cannot get property 'quantity' on null object
        at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:60)
        at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:172)
        at org.codehaus.groovy.runtime.callsite.NullCallSite.getProperty(NullCallSite.java:47)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296)
        at Script1.run(Script1.groovy:10)
        at In-memory script.(In-memory script:2)
        at com.isomorphic.scripting.ScriptGroovy.evalScript(ScriptGroovy.java:108)
        at com.isomorphic.scripting.ScriptXBase.eval(ScriptXBase.java:52)
        at com.isomorphic.util.DefaultValidators$serverCustom.evaluateServerScript(DefaultValidators.java:1539)
        at com.isomorphic.util.DefaultValidators$serverCustom.validate(DefaultValidators.java:1398)
        at com.isomorphic.util.DefaultValidators.processValidator(DefaultValidators.java:297)
        at com.isomorphic.util.DefaultValidators.validateField(DefaultValidators.java:255)
        at com.isomorphic.datasource.SimpleType.validateValue(SimpleType.java:101)
        at com.isomorphic.datasource.SimpleType.create(SimpleType.java:75)
        at com.isomorphic.datasource.BasicDataSource.validateFieldValue(BasicDataSource.java:2155)
        at com.isomorphic.datasource.BasicDataSource.validateFieldValue(BasicDataSource.java:2070)
        at com.isomorphic.datasource.BasicDataSource.toRecord(BasicDataSource.java:1434)
        at com.isomorphic.datasource.BasicDataSource.toRecords(BasicDataSource.java:1371)
        at com.isomorphic.datasource.BasicDataSource.toRecords(BasicDataSource.java:1332)
        at com.isomorphic.datasource.DataSource.validateDSRequest(DataSource.java:3662)
        at com.isomorphic.datasource.DataSource.validateDSRequest(DataSource.java:3607)
        at com.isomorphic.datasource.DataSource.execute(DataSource.java:2219)
        at com.isomorphic.application.AppBase.executeDefaultDSOperation(AppBase.java:735)
        at com.isomorphic.application.AppBase.executeAppOperation(AppBase.java:652)
        at com.isomorphic.application.AppBase.execute(AppBase.java:493)
        at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:2723)
        at com.isomorphic.servlet.IDACall.handleDSRequest(IDACall.java:230)
        at com.isomorphic.servlet.IDACall.processRPCTransaction(IDACall.java:187)
        at com.isomorphic.servlet.IDACall.processRequest(IDACall.java:152)
        at com.isomorphic.servlet.IDACall._processRequest(IDACall.java:119)
        at com.isomorphic.servlet.IDACall.doPost(IDACall.java:79)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:643)
        at com.isomorphic.servlet.BaseServlet.service(BaseServlet.java:162)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at com.isomorphic.js.JSSyntaxScannerFilter._doFilter(JSSyntaxScannerFilter.java:262)
        at com.isomorphic.servlet.BaseFilter.doFilter(BaseFilter.java:88)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at com.isomorphic.servlet.CompressionFilter._doFilter(CompressionFilter.java:260)
        at com.isomorphic.servlet.BaseFilter.doFilter(BaseFilter.java:88)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:470)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:612)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503)
        at java.lang.Thread.run(Thread.java:745)
    === 2016-08-19 14:13:29,996 [83-5] WARN  RequestContext - dsRequest.execute() failed: 
    java.lang.NullPointerException
        at com.isomorphic.util.DefaultValidators$serverCustom.validate(DefaultValidators.java:1421)
        at com.isomorphic.util.DefaultValidators.processValidator(DefaultValidators.java:297)
        at com.isomorphic.util.DefaultValidators.validateField(DefaultValidators.java:255)
        at com.isomorphic.datasource.SimpleType.validateValue(SimpleType.java:101)
        at com.isomorphic.datasource.SimpleType.create(SimpleType.java:75)
        at com.isomorphic.datasource.BasicDataSource.validateFieldValue(BasicDataSource.java:2155)
        at com.isomorphic.datasource.BasicDataSource.validateFieldValue(BasicDataSource.java:2070)
        at com.isomorphic.datasource.BasicDataSource.toRecord(BasicDataSource.java:1434)
        at com.isomorphic.datasource.BasicDataSource.toRecords(BasicDataSource.java:1371)
        at com.isomorphic.datasource.BasicDataSource.toRecords(BasicDataSource.java:1332)
        at com.isomorphic.datasource.DataSource.validateDSRequest(DataSource.java:3662)
        at com.isomorphic.datasource.DataSource.validateDSRequest(DataSource.java:3607)
        at com.isomorphic.datasource.DataSource.execute(DataSource.java:2219)
        at com.isomorphic.application.AppBase.executeDefaultDSOperation(AppBase.java:735)
        at com.isomorphic.application.AppBase.executeAppOperation(AppBase.java:652)
        at com.isomorphic.application.AppBase.execute(AppBase.java:493)
        at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:2723)
        at com.isomorphic.servlet.IDACall.handleDSRequest(IDACall.java:230)
        at com.isomorphic.servlet.IDACall.processRPCTransaction(IDACall.java:187)
        at com.isomorphic.servlet.IDACall.processRequest(IDACall.java:152)
        at com.isomorphic.servlet.IDACall._processRequest(IDACall.java:119)
        at com.isomorphic.servlet.IDACall.doPost(IDACall.java:79)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:643)
        at com.isomorphic.servlet.BaseServlet.service(BaseServlet.java:162)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at com.isomorphic.js.JSSyntaxScannerFilter._doFilter(JSSyntaxScannerFilter.java:262)
        at com.isomorphic.servlet.BaseFilter.doFilter(BaseFilter.java:88)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at com.isomorphic.servlet.CompressionFilter._doFilter(CompressionFilter.java:260)
        at com.isomorphic.servlet.BaseFilter.doFilter(BaseFilter.java:88)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:470)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:612)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503)
        at java.lang.Thread.run(Thread.java:745)
    PS: this test case also raises the same error I reported here http://forums.smartclient.com/forum/...-valuesmanager
    but I think they are unrelated problems so I started to different threads

    #2
    This form creates a new record, and orderItem is the PK field. It is expected to be null since the record does not exist yet.

    Further, if the record did exist, you should not expect unchanged fields to be present in the "values" of a validation request. You would need to access such fields via "oldValues", however, keep in mind the caveat noted in the docs that the "oldValues" come from the client, so can't be trusted in a secure application (or may be out of date) - the secure way to get current values for an existing record would be to use the PK to fetch it.

    Comment


      #3
      Originally posted by Isomorphic View Post
      This form creates a new record, and orderItem is the PK field. It is expected to be null since the record does not exist yet.
      Of course you're right, actually I've simplified too much the test case, I'll repost it below.
      Originally posted by Isomorphic View Post
      Further, if the record did exist, you should not expect unchanged fields to be present in the "values" of a validation request. You would need to access such fields via "oldValues", however, keep in mind the caveat noted in the docs that the "oldValues" come from the client, so can't be trusted in a secure application (or may be out of date) - the secure way to get current values for an existing record would be to use the PK to fetch it.
      But actually the missing value it's the PK of the record, which I want to use to fetch the actual record from database.
      Also note that I'm using dependentFields="orderItem": isn't it the right approach to have it in the "values"?

      This is the right test case:
      please remove the custom validator on the quantity field, so that you may add a record to the inlineScript_orderForm dataSource, such as:
      inlineScript_orderForm.addData({itemId:1, orderItem:1, quantity:1, instructions:"foo"})

      then put the validator back in place:
      Code:
              <field name="quantity" type="integer">
                  <validators>
                      <validator type="serverCustom" dependentFields="orderItem">
                          <serverCondition language="groovy"><![CDATA[
                              value < dataSource.fetchById(record.orderItem).quantity
                          ]]></serverCondition>
                          <errorMessage>Not enough in stock</errorMessage>
                      </validator>
                  </validators>
              </field>
      and run this js code
      Code:
      isc.ValuesManager.create({
          ID: "myVM",
          dataSource: "inlineScript_orderForm"
      });
      
      isc.SectionStack.create({
          ID: "sectionStack",
          visibilityMode: "multiple",
          width: "100%", height: "100%",
          border: "1px solid blue",
          sections: [
              {
                  title: "List Grid", canCollapse: false, expanded: true,
                  items: [
                      isc.ListGrid.create({
                          dataSource: "inlineScript_orderForm",
                          autoFetchData: true,
                          recordClick: function (viewer, record, recordNum, field, fieldNum, value, rawValue) {
                              myVM.editRecord(record);
                          }
                      })
                  ]
              },
              {
                  title: "Form", expanded: true, canCollapse: false,
                  items: [
                      isc.DynamicForm.create({
                          validateOnChange: true,
                          valuesManager: "myVM",
                          fields: [
                              {type: "header", defaultValue: "Add an item to your Order"},
                              {
                                  name: "itemId", title: "Item", editorType: "ComboBoxItem", optionDataSource: "StockItem",
                                  valueField: "id", displayField: "description"
                              },
                              {name: "quantity", validateOnExit: true},
                              {name: "instructions", editorType: "TextAreaItem"},
                              {type: "submit", title: "Submit Order"}
                          ]
                      })
                  ]
              }
          ]
      });
      Select the grid's record, and type in the quantity field of the form.
      Tomcat log:
      Code:
      === 2016-08-20 13:27:21,642 [83-5] DEBUG RPCManager - Processing 1 requests.
      === 2016-08-20 13:27:21,642 [83-5] DEBUG RPCManager - Request #1 (DSRequest) payload: {
          values:{
              itemId:"1",
              quantity:19,
              instructions:"foo"
          },
          operationConfig:{
              dataSource:"inlineScript_orderForm",
              repo:null,
              operationType:"validate",
              textMatchStyle:"exact"
          },
          validationMode:"partial",
          appID:"builtinApplication",
          operation:"inlineScript_orderForm_validate",
          oldValues:{
              itemId:"1",
              quantity:19,
              instructions:"foo"
          },
          criteria:{
          }
      }
      as you may see, orderItem isn't present in "values"

      Comment


        #4
        I've just realized that the form hasn't got orderItem as an item, if I add it, then everything works.
        I got confused because everything worked if editing in the grid, but when editing with the form, the PK is used for updating even if not present as an item, but isn't considered by the validate with dependentFields.

        So I think that this is by design, right?

        Comment


          #5
          We've made a change to SC 11.0p and newer branches to ensure that all of the ValuesManager values are present. It's in the nightly builds dated 2016-08-22 and beyond.

          Comment


            #6
            SmartClient Version: v11.0p_2016-08-24/Enterprise Development Only (built 2016-08-24)

            I can confirm it's fixed, thank you very much

            Comment

            Working...
            X