Child pages
  • Data/Record/Column validation
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

From release 2020.09 on Servoy has added/changed how validation is done for database data.

databaseManager has now a new method: JSValidationObject databaseManager.validate(record [, optionalState]);

Which is automatically called when saveData() is done for every record that was changed and will be saved to the database. But you can also call it manually your self to report possible validation problems.

It will return a JSValidationObject when the record has validation problems, if everything was ok then a null is returned.

The optionalState object can be anything that you want to pass on to all of the validators that are being called.

The validate(record) call will first call the new "onValidate" table event method which has the signature: (record, validationObject, stateObject).

  • record: the record to validate.
  • validationObject: the JSValidationObject where problems can be reported in to
  • stateObject:  is the optionalState object you give to the databaseManager.validate(record, {something:1}) call for extra information that you want to give into the onValidate entity event.

If there is a problem that should be reported the JSValidationObject has a few report methods that you can use to report problems, the largest one has the signature: (message,dataprovider,level,customObject,messageKeyParams), only message is mandatory, the rest are optional.

  • message: the message your want to report back to the user (can be an i18n key then it should start with "i18n:")
  • dataprovider: the column where this message belongs to
  • level: a LOGGINGLEVEL level, so you can report that this is really an ERROR or just INFO/WARNING.
  • customObject, the same as the optionalState object this can be anything that can be used later on the have more information about this problem.
  • messageKeyParams: if the message was an i18n key that has dynamic values then this is the array that has those dynamic values that are injected into the final message.

After the "onValidate" table event, it will call one of the "onRecordUpdate" or "onRecordInsert" table event depending on if the record is an existing or new record. The signature of those table events are also changed: (record, validationObject, stateObject), so those are now the same as "onValidate". Instead of returning false or throwing an exception it is now better to just report problems on the validationObject and alwasy just return true. This way you control the message.

The 3rd step is to check if there are columns that are null or an empty string but the column is marked as not null. If the column has this problem it will be reported with the i18n key: servoy.record.error.null.not.allowed ("Dataprovider '{0}' can't be null or empty")

The 4th step is to check the size of the column, if a column has a value that won't fit into the database it will be reported by the i18n key: servoy.record.error.columnSizeTooSmall ("Column {0} is too small, max length can be {1}, value '{2}'")

The last step is calling all the column validators for all the changed columns of the record. By default Servoy will not call the column validators anymore when the value is set into the record, it will only validate the columns when saving or when the validate(record) method is called. This change of behavior is controlled by the servoy property "servoy.execute.column.validators.only.on.validate_and_save" which is default true. In the table editor column validation section there is now a check box that controls this property "Only execute validators on validate/save"

All the build in validators are changed to use the new way, this means for the GlobalMethodValidator that also there the signature is changed from just getting the value object to: (value, dataproviderid, validationObject, stateObject)

  • value: the value to validate.
  • dataproviderid: the is the dataprovider that is being validated, can be used in a report call so it is known which dataprovider/column had this problem.
  • validationObject: the JSValidationObject where problems can be reported in to
  • stateObject:  is the optionalState object you give to the databaseManager.validate(record, {something:1})

Also for this the same applies as from the "onRecordUpdate" instead of return false or throwing an Exception, the global method validator should report problems to the validationObject and always just return true.

All of the steps are called, even if one already fails, so the JSValidationObject can have multiply reported problems at once. When all the steps/checks are done and it has at least 1 problem reported then it will set itself on the JSRecord.validationObject property (which is cleared before any validate) and the validationObject will be returned.

If the caller of databaseManager.validate(record) sees that an object is returned it can then call validationObject.getProblems() to get an array of JSProblems. A JSProblem has has a number of fields:

  • message: the message that was reported by the call JSValidationObject.report(message), can just be an i18n key
  • i18NMessage: the resolved message if the above message was an i18n key.
  • column: the column for which this problems was generated
  • level: the LOGGINGLEVEL of this problem.
  • customObject: the custom object that was passed into the report() method, for standard or build in checks like the null check of the RangeColumnValidatior this custom object is the object that you give into the validate(record, x) call.
  • record: the record for which this problems was generated


var validatonObject = databaseManager.validate(record, {originationCall: "customerForm"});
if (validationObject)
{
   var problems = validationObject.getProblems();
   problems.forEach(/** @param {JSProblem} problem*/ function(problem) {
			application.output(problem.message)
			application.output(problem.i18NMessage);
			application.output(problem.column);
			application.output(problem.customObject);
		});
}





  • No labels