By: Ariel Almog and Avi Klein
In this post, we suggest the usage of Spring Validation as your infrastructure for data storage validation.
If you are,for an example, a widget or module developer, who is interested in data persistence, you will most likely need to verify your data prior to business logic processing and data persistence. By choosing ‘Spring’ as a technology for client to server interaction, you are seamlessly granted with the ability to define a set of data-verification tools and user-feedback infrastructure that is already being used by the HANA Cloud Portal development teams.
Due to the enormous autonomy, provided to the developer by the SPRING infrastructure, it would be a good practice to integrate a data-validation infrastructure. The data validation principal is a must in every externally or end-user configurable software module use case.
Our aim is to suggest using this methodology as a slim, cross feature mechanism for validating user passed data to the server and system service configuration using the configuration files.
When it comes to the functionality defined by the data validator module, few aspects must be covered:
- a. Defining the input-data-type validation logic
- b. Defining the set of output as validation-failure
- c. Applying the validation strategy on the concrete input type (project/source related)
- d. Linkage between the validation logic output and the appropriate output
When introducing a new feature or module to our CP product, we often go through the process of defining a new relevant Bean (SPRING) to handle the feature attributes and flow. Within the life cycle of a request, those services (beans) handle input from the user-agent and calculate it according to the specific configurations. In order to validate the data and current configuration, the developer must implement one of the following measures:
- 1) A block of “if else” with the relevant rules to each of the relevant data containers in every relevant location in the source
- 2) Implement our own validation pattern and mechanism, including an inherent user feedback mechanism
- 3) Use the already delivered Spring Validators mechanism
When working on the import & export feature we needed to validate the imported object against a set of rules. We choose # 3 since spring provides a simplified set of APIs and supporting classes for validating domain objects which was our use case. Also, the framework is extensible and it is possible to hook-in custom validator implementations into the framework, if the requirements change. And last, the framework supports error handling and reporting which later on can be used to issue a detailed log about the importing process.
When a developer is about to add a new service that processes such a data that needs to be validated prior to processing stage, a specific data-holder-validator can should be implemented to validate the the relevant data-holder (processed by the service/bean).
Common functionality can be shared by different validators and all validators should implement org.springframework.validation.Validator
Validation using spring’s Validator interface
In this sample we will use the Validator interface to validate objects. The Validator interface works using an Errors object so that while validating, validators can report validation failures to the Errors object.
In the below code sample, we defined a class called “Book” which we want to validate against a set of rules.
The class defines basic properties and we want to ensure that the caller who created the book will set non-null values to the properties “name” and “author”. In addition, we would like to ensure that the property “noOfPages” will not have a zero value or a negative value.
So first we define the book class:
Now we define the valuator (we named it BookValidator)
Looking at the above class, we can see that the custom validator implements the interface “Validator”. The method “validate()” can be invoked directly or indirectly by the framework/caller to trigger the validation.
You can see that the first argument passed to this method is the object to be validated and the second object is the “Errors” object. This object is expected to be populated within the method in case of any errors.
To validate the “name” property, we check if the value is null or empty and if so, we call the method “rejectValue()” which is defined on the “errors” object.
The argument of this method is the name of the field that violated the validation, the error code and the error message.
Note that there is a utility method “rejectIfEmptyOrWhitespace”, which is available in the class “ValidationUtils”. This method performs the job of “Errors.rejectValue”.
We have used this method for validating the property “author” and we also checked if the value for the property “noOfPages” for the cases where the value is zero or negative.
To use the Validator we set the following code:
Above is the main program that makes use of validation. We have created an instance of Book object and haven’t set the properties “name” and “author”.
For invoking the validator object on the book object we have used the utility method “invokeValidator” defined in the class “ValidationUtils”. The validation action is set by passing the validator object, the object to be validated and the “errors’ object.
In case of any validation errors, the “Errors” object can be analyzed to obtain information on the verified object. In this case, we have used the method “getErrorCount()” to get the number of validation errors. After that, iteration is done to obtain the list of errors.
The above code generates the following output: