5.264 Configuration Constraints

Plugin types can optionally define validation constraints for the polling interval and plugin configuration. These parameters are then checked against the defined constraints during the creation of a new plugin. If the validation fails, meaning the configuration provided does not pass the constraints defined by the plugin type, the plugin will fail to be created with error messages based on the parameters and constraints defined.

Defining constraints

To define constraints for a plugin type and therefore for all plugins created using it, use the following syntax:

import com.adaptc.mws.plugins.*
class ConstrainedPlugin extends AbstractPlugin {
	static constraints = {
		// Set plugin's default polling interval
		pollInterval defaultValue:60
		// The "myParam" configuration parameter is automatically required and cannot be blank
		myParam blank:false
		// The "myEnum" configuration parameter is not required and must set to one of the values in the list
		myEnum required:false, inList:["val1", "val2", "val3]
		// Insert additional constraints here…
	}
}

In the table below, all available constraints are shown, as well as the expected value type, an example, the default message code, and the message suffix. The message columns are described in greater detail in the Messaging section below.

Constraint Default value Type Example value Default message code Message suffix Description
blank -- Boolean true default.blank.message blank If false, the parameter (if present) cannot be a blank string.
creditCard -- Boolean true default.invalid.creditCard.message creditCard.invalid If true, uses org.apache.commons.validator.CreditCardValidator to determine if the parameter (if present) is a valid credit card number.
defaultValue -- Object or Closure 60 -- -- If the parameter is not present, it will be set to this default value. Does not return any error messages. See Default value below for more information.
email -- Boolean true default.invalid.email.message email.invalid If true, the parameter (if present) must be a valid email address.
inList -- List ["first", "second"] default.not.inlist.message not.inList The parameter (if present) must be set to one of the values specified.
matches -- String "[a-z][A-Z]+" default.doesnt.match.message matches.invalid The parameter (if present) must match the specified regular expression.
max -- Integer 10 default.invalid.max.message max.exceeded The parameter (if present) must not be greater than the defined value.
*maxSize -- Integer 10 default.invalid.max.size.message maxSize.exceeded The parameter's (if present) size must not be greater than the defined value.
min -- Integer 1 default.invalid.min.message min.notmet The parameter (if present) must not be less than the defined value.
*minSize -- Integer 1 default.invalid.min.size.message minSize.notmet The parameter's (if present) size must not be less than the defined value.
notEqual -- Object "Invalid Value" default.not.equal.message notEqual The parameter (if present) must not be set to the defined value.
nullable true Boolean false default.null.message nullable If true, the parameter (if present) must be non-null value. See required for how to enforce the parameter to be present.
password -- Boolean true -- -- If true, the parameter (if present) is hidden from the user both on input and display when managing plugin configuration. It is not, however, hidden in the REST API. Does not return any error messages.
range -- Range 1..10 default.invalid.range.message range.toosmall/range.toobig Uses a groovy range to validate that the value is within a specified range.
required true Boolean false default.required.message required If true, the parameter must be present and non-null for the plugin to be created successfully. Implies the nullable:false constraint.
scale -- Integer 2 -- -- Only valid for Double parameters. Rounds the parameter (if present) to the specified number of digits. Does not return any error messages.
*size -- Range 2 default.invalid.size.message size.toosmall/size.toobig Uses a groovy range to restrict the size of a collection, string, or a number.
*type -- Class Integer.class typeMismatch typeMismatch See Type inferencing and conversion below.
url -- Boolean true default.invalid.url.message url.invalid If true, uses org.apache.commons.validator.UrlValidator to determine if the parameter (if present) is a valid URL. Does not support exec or file scheme URLs.
scriptableUrl -- Boolean true default.invalid.scriptable.url.message scriptableUrl.invalid Identical to the url validator, but adds support for exec and file scheme URLs.
validator -- Closure (See Custom validator) default.invalid.validator.message validator.error See Custom validator below.
widget -- String "textarea" -- -- By default, all strings render as a text field when creating or editing plugins. Setting this to "textarea" causes it to render as a text area with multi-line support. This is only valid for string configuration parameters.

* The user interface (see Plugin Management) does not support parameters whose type is a subclass of Collection (a List, for example). Such parameters are therefore not recommended.

The polling interval constraints must always apply to Integer types. If this specification is violated, the plugin type cannot be added or updated.

Messaging

When defined constraints are violated for a plugin, error messages are retrieved based on the configuration parameters and the applied constraints using i18n Messaging codes (see i18n Messaging). First, the most specific error message will be attempted to be resolved from a message code generated from the plugin type name, the configuration parameter, and the constraint. This code takes the format of pluginTypeName.parameterName.suffix where the plugin type's name has a lowercase first letter and the suffix is shown in the table above. If this message code is not defined, the default message code (as shown in the table above) will be used.

For example, if the url constraint validation failed for the "ExamplePlugin" plugin type's "endpoint" configuration parameter, the following message codes would be resolved in order:

Default messages

Default messages may be contained in any messages.properties file included in the plugin JAR file as explained in i18n Messaging (see i18n Messaging). Arguments for each constraint vary, but they always include these argument indices:

If default messages are not defined in the plugin project, the following messages will be used:

default.doesnt.match.message=The ''{0}'' configuration parameter value ({2}) does not match the required pattern ''{3}''
default.invalid.url.message=The ''{0}'' configuration parameter value ({2}) is not a valid URL
default.invalid.scriptable.url.message=The ''{0}'' configuration parameter value ({2}) is not a valid scriptable URL
default.invalid.creditCard.message=The ''{0}'' configuration parameter value ({2}) is not a valid credit card number
default.invalid.email.message=The ''{0}'' configuration parameter value ({2}) is not a valid e-mail address
default.invalid.range.message=The ''{0}'' configuration parameter value ({2}) does not fall within the valid range from {3} to {4}
default.invalid.size.message=The ''{0}'' configuration parameter value ({2}) does not fall within the valid size range from {3} to {4}
default.invalid.max.message=The ''{0}'' configuration parameter value ({2}) is greater than the maximum value of {3}
default.invalid.min.message=The ''{0}'' configuration parameter value ({2}) is less than the minimum value of {3}
default.invalid.max.size.message=The ''{0}'' configuration parameter value ({2}) exceeds the maximum size of {3}
default.invalid.min.size.message=The ''{0}'' configuration parameter value ({2}) is less than the minimum size of {3}
default.invalid.validator.message=The ''{0}'' configuration parameter value ({2}) does not pass custom validation
default.not.inlist.message=The ''{0}'' configuration parameter value ({2}) is not contained within the list [{3}]
default.blank.message=The ''{0}'' configuration parameter cannot be blank
default.not.equal.message=The ''{0}'' configuration parameter value ({2}) cannot be equal to ''{3}''
default.null.message=The ''{0}'' configuration parameter cannot be null
default.required.message=The ''{0}'' configuration parameter is required and cannot be null
typeMismatch=The ''{0}'' configuration parameter value ({2}) does not match the required type ''{3}''

Labels and help messages

Message codes may also be provided for configuration parameters to aid the admin user with human readable property labels and help messages. Similar to the validation error message codes, labels and help message codes may be defined using the pluginTypeName.parameterName.label and pluginTypeName.parameterName.help message codes. These values are used only in plugin type management (see Plugin Type Management) and are not exposed through the REST API.

Type inferencing and conversion

Due to the dynamic nature of configuration parameters, the expected type or class of values for each parameter are inferred from constraints. The following rules govern how type is inferred, in priority order:

If the configuration parameter values can be converted to the expected types, this will occur automatically. Otherwise, the *type constraint is violated and the applicable error messages will be generated.

Custom validator

In cases where the built-in constraints prove inadequate for validation, custom validators may be used. The validator constraint expects a Groovy Closure parameter which has one or (optionally) two arguments: the value of the configuration parameter and the plugin object. With these parameters, complex validation logic may be defined. Additionally, custom message codes and arguments may be defined by validator constraints and these will be used in generating error messages when validation fails.

For example, suppose that the parameter "user" cannot be set to the same value as parameter "creator." Additionally, the "creator" parameter must not be equal to either "bob" or "joe." The existing constraints are inadequate to fulfill this use case, but the following code using validators would perform exactly as expected:

import com.adaptc.mws.plugins.*
class ConstrainedPlugin extends AbstractPlugin {
	static constraints = {
		user validator:{ val, obj ->
			if (val==obj.config.creator)
				return "invalid.equal.to.creator"
		}
		creator validator:{ val ->
			if ("val"=="joe")
				return ["invalid.equal", "joe"]
			if (val=="bob")
				return ["invalid.equal", "bob"]
		}
	}
}

In the examples above, the message codes and output on validation failure is shown below:

Message codes
------------------------------------

constrainedPlugin.user.invalid.equal.to.creator=The user configuration parameter value ({2}) must not be equal to the creator parameter.
constrainedPlugin.creator.invalid.equal=The creator configuration parameter must not be equal to {3}.
Output error messages
------------------------------------

For user = "jill", creator = "jill"
"The user configuration parameter value (jill) must not be equal to the creator parameter."
For user = "jill", creator = "bob"
"The creator configuration parameter must not be equal to bob."

For user = "jill", creator = "joe"
"The creator configuration parameter must not be equal to joe."

The validator Closure may return:

All validator constraints automatically have the appConfig property available, which contains the application configuration as discussed in the Configuration section (see Configuration). The suite property contains the value of the configured MWS suite. Additionally, services may be retrieved as explained in the next section.

Retrieving services

At times it may be necessary to use Bundled Services in custom validators. A method named getService which takes a single string parameter of the name of the service (as used during injection) is provided to be used in these cases. For example, if a plugin needs a valid server certificate file, the SSL Service may be used as follows:

import com.adaptc.mws.plugins.*
class ConstrainedPlugin extends AbstractPlugin {
	static constraints = {
		certificateFile validator:{ val ->
			ISslService sslService = getService("sslService")
			try {
				sslService.getSocketFactory(val)
			} catch(Exception e) {
				// Certificate file is invalid, return an error
				return ["invalid", e.message]
			}
		}
	}
}

The getService method does not work with translators, custom components, RM services, or the Individual Datastore.

Default value

The default value for a configuration parameter might depend on the MWS configuration or other properties. Therefore, the defaultValue constraint can be set to a closure. The defaultValue closure does not take any parameters and must return the object to be used as the default value.

For example, if the default value of a parameter must be true if and only if MWS is configured for the Cloud suite, then the following constraints would satisfy these conditions:

import com.adaptc.mws.plugins.*
class ConstrainedPlugin extends AbstractPlugin {
	static constraints = {
		myParameter required: true, type: Boolean, defaultValue: {
			return suite == Suite.CLOUD
		}
	}
}

As with validator closures, defaultValue closures have access to appConfig, suite, and getService.

Related Topics 

© 2016 Adaptive Computing