Validation

ValidationService

A ValidationService is a simple functional interface that creates a MessageList containing validation result messages. In order to make use of a ValidationService in a BindingManager, it must be passed as an argument to the BindingManager's constructor. As described in Binding, BindingContext, BindingManager it is part of the BindingManager and not of a BindingContext because validation violations may refer to other input fields that are not part of the current BindingContext.

As mentioned in Binding to the Domain Model a linkki application consists of multiple layers.

layers

Most validations work on the domain model because the goal of the validation is to validate the data of the domain model itself. Other components, like services or batch processes can then also make use of those validations.

In most applications the validation service simply calls the domain model validation and collects all messages. In order to avoid a dependency from the domain model to linkki it is good practice to use an own implementation for messages in the domain model. In this case the validation service is also responsible for converting from domain layer messages to a linkki MessageList.

ValidationDisplayState

When a user enters a page containing required fields, it is usually not desirable to greet him with a lot of validation error messages without a chance to enter the values first. linkki supports a more pleasant experience with the ValidationDisplayState: HIDE_MANDATORY_FIELD_VALIDATIONS filters all messages with a ValidationMarker returning true for isRequiredInformationMissing() while SHOW_ALL does not filter messages.

The ValidationService can return a ValidationDisplayState via getValidationDisplayState() and offers the method getFilteredMessages() that takes the messages from getValidationMessages() and applies the ValidationDisplayState’s `filter method. It is good practice to switch the ValidationDisplayState once the user has triggered a submit button or another page advancement mechanism.

Message and MessageList

A Message has a human readable text, an error code and a Severity (one of INFORMATION, WARNING, ERROR). It may also contain a set of ObjectProperties to refer to specific invalid properties of an object. Additionally there may be ValidationMarkers to distinguish different kinds of validation messages.

The easiest way to create a Message is to use its builder (via the builder() method). Alternatively, a Message can also be created using the static factory methods (createError(), createWarning(), createInfo()) or by directly calling the constructor.

            Message passwordRequiredMessage = Message
                    .builder("Password is required", Severity.ERROR)
                    .invalidObject(new ObjectProperty(pmo.getUser(), User.PROPERTY_PASSWORD))
                    .markers(ValidationMarker.REQUIRED)
                    .create();

A MessageList is a container for a list of messages and provides an API to access the messages, for example by using filters.

ObjectProperties

A linkki message uses a set of ObjectProperty to identify which properties and objects the message refers to. An ObjectProperty consists of a reference to the bound object as well as the property’s name. If the property has an indexed type, the ObjectProperty can additionally contain the index of the referred value in its collection.

ValidationMarker

ValidationMarkers are used to group and categorize messages. By default, linkki can differentiate between mandatory-field validations and other messages using the validation marker ValidationMarker#REQUIRED. UI elements referring to messages that use this marker are not highlighted as long as a user hasn’t had a chance to enter any values (see ValidationDisplayState). The method isMandatoryFieldMessage on a Message can be used to check if any of the message’s markers return true for isRequiredInformationMissing:

            String text = message.getText();
            if (message.isMandatoryFieldMessage()) {
                text += " *";
            }
            messageLabel.setCaption(text);

Applications can introduce their own specialized validation markers by implementing the ValidationMarker interface. That way special meaning can be attached to messages and they can be categorized and processed accordingly, if required.