The main intent behind defining a component class for each component is to enable the automatic binding of component instances based on both their structural relationship as well as their types. During the process of binding the components are validated on the server-side to ensure that the component structure is valid before it is run on the client. The validation mechanism uses whatever information is provided in the component classes to detect as many logical errors as it can. However, applications can be built using custom JavaScript so in some cases the information necessary to perform the validation may be missing. If that is the case, then the behavior is determined by the validation mode.
The main intent behind defining a component class for each component is to enable the automatic binding of component instances based on both their structural relationship as well as their types. During the process of binding the components are validated on the server-side to ensure that the component structure is valid before it is run on the client. The validation mechanism uses whatever information is provided in the component classes to detect as many logical errors as it can. However, applications can be built using custom JavaScript so in some cases the information necessary to perform the validation may be missing. If that is the case, then the behavior is determined by the validation mode.
For each error that is not ignored a diagnostic message is created and logged to the standard MCS log. Fatal errors cause MCS to abort the rendering of the page, but where possible, MCS processes the page as long as possible to detect other binding errors.
The errors are split into three main groups:
Errors that are potentially caused by incomplete class information. Component classes must always be specified, but may provide incomplete information and therefore an issue such as trying to bind a reference which was not defined in the component class could be an error (e.g. due to misspelling the reference name, or missing the reference definition).
These issues are treated as errors only if the component class indicates that it completely defines the aspect of the component class that covers the missing information, and the validation mode for the component instance that is being validated is set to 'strict' or 'warn'.
Please note that if a cx:component-class element indicates that it defines 'reference-types', then it is an error if during binding a component instance attempts to explicitly bind a reference that has not been defined in the component class.
Errors that are potentially caused by incomplete application information. As components can be bound using custom JavaScript (which cannot be validated) instead of or as well as using server-side markup an issue such as not binding a required reference could be an error. For example, it is an error if after binding a required reference is not bound to a component, i.e. the page author did not explicitly specify a reference and no suitable component with the correct structural relationship was found. Also, it is an error if after binding a reference is bound to a component that does not exist, i.e. the page author explicitly referenced a component id that did not correspond to the id of a component element.
These issues are treated as errors if the validation mode is set to 'strict' or 'warn'.
All other issues, such as those that arise as a result of a mismatch or conflict between information that has been provided by a component are always treated as errors, irrespective of whether the component class definitions are complete or the setting of the validation mode.
Note that it is an error if after binding a component, a reference is bound to a component that does not implement the set of types required by the reference. Also, it is an error if after binding a component, a reference is bound to an incorrect number of components. Such situation can occur if there is more than one child component that implements the required reference types.
The cf2:validation-mode meta property allows page authors to control the behavior of the validator of the Client Framework 2 components when an error arises as a result of incomplete information, e.g. if a component class is not provided, or a component reference is not bound. If it is specified in the head of a document and does not have the about attribute, then it applies to the whole document. If the about attribute points to an element, then it applies to that element and all its children. It is an error if no such element exists, or multiple settings are applied to the same element. The default validation mode across the whole application is set in the mcs-config.xml configuration file using the validation-mode attribute on the client-framework2 element.
There are three validation modes:
The component class must define all aspects of the class. All errors found will be treated as fatal, i.e. will cause the processing of the XDIME page to abort after all validation has been performed.
It is not recommended that this mode is used within a page as it could cause forward compatibility issues. If it is used, then it is the application author's responsibility to fix any issues that arise as a result of upgrading to a newer version of MCS. The intent is that this mode should only be specified in the configuration file. When upgrading MCS this would then be changed to 'warn' while the component class definitions are extended and any arising issues fixed.
The main difference between this mode and 'strict' is that any errors logged will not be treated as fatal and so will not cause the processing of the XDIME page to abort. The intent is that this mode will be used when migrating applications to run on a later version of MCS.
This is the default setting and means that validation errors due to missing information are simply ignored. The "missing information" refers to the components that are created and the references that are bound in a custom JavaScript. It is "missing" because MCS cannot analyze the JavaScript code to obtain that information. The cf2:validation-mode meta property allows page authors to indicate which components are affected by that "missing information" and so cannot be fully validated and which are not and so can be fully validated by MCS. As mentioned, cf2:validation-mode is intended to be used temporarily within the page when migrating pages from using custom JavaScript to using custom component markup.
There are three types of errors reported in logs which are not affected by the validation mode.
Missing references - e.g. "Reference 'second' missing".
Wrong number of references - e.g. "Too many cx:ref elements for component 'full' declared".
Type mismatch - e.g. "Reference 'partial' does not implement expected types".
Missing references/Wrong number of references
If an author uses custom component markup to define a component class and to create instances of that class, then the component instance must be valid according to the class. If the class places limitations on the number of references (e.g. required), then the component instance must specify the correct number of references otherwise it is an error.
For instance, in the example provided there is a component class 'FullClass' that amongst others has a required reference 'second' which is not provided in the component instance, and is causing an error. Now, an author can provide a binding for that reference through some custom JavaScript and so it could be argued that the reference is "missing information" and therefore should be controlled by the cf2:validation-mode meta property. However, to reduce the amount of work that is done in custom JavaScript and as the author is already using custom component markup to define the component and create the instance it is easy for them to add another cx:ref element to bind that reference.
Type mismatch
In this case, the reference states the types it expects, the component class of the component instance it is referencing defines what types it provides but they do not match.
The following example is annotated with comments that explain if a custom component, custom class or reference is in error, if so why and in what validation modes.
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/2002/06/xhtml2"
xmlns:cf2="http://www.volantis.com/xmlns/2009/07/cf2"
xmlns:cx="http://www.volantis.com/xmlns/2010/07/cf2/cx"
xmlns:mcs="http://www.volantis.com/xmlns/2006/01/xdime/mcs"
xmlns:ui="http://www.volantis.com/xmlns/2009/07/cf2/ui"
xmlns:my="http://www.mycomponents">
<head>
<title>Custom Validation Example</title>
<mcs:script type="text/javascript">
// Some JavaScript that could define components on the client.
</mcs:script>
<!--
! Set the mode from the request parameter mode, defaulting to lax if not specified.
!-->
<meta property='cf2:validation-mode' content="%{request:getParameter('mode', 'warn')}"/>
<!--
! Fully define the reference-types aspect of a component class.
!-->
<cx:component-class id="FullClass" defines="reference-types" name="my:FullClass">
<cx:client-class name="Object"/>
<cx:reference name="first" component-types="my:PartialClass"/>
<cx:reference name="optional" component-types="" min-occurs="0"/>
<cx:reference name="second" component-types=""/>
<cx:reference name="third" component-types="my:NoReference"/>
<cx:reference name="last" component-types=""/>
<cx:reference name="box" component-types=""/>
</cx:component-class>
<!--
! Partially define a component class.
!
! This is in error if the validation mode for any associated instance is set to strict
! of warn as this does not indicate that it defines all supported aspects of the class.
!-->
<cx:component-class id="PartialClass" name="my:PartialClass">
<cx:client-class name="Object"/>
<cx:reference name="other" component-types="my:FullClass"/>
<cx:reference name="another" component-types=""/>
</cx:component-class>
<!--
! Completely define a class with no references.
!-->
<cx:component-class id="NoReference" defines="reference-types" name="my:NoReference">
<cx:client-class name="Object"/>
</cx:component-class>
</head>
<body>
<!--
! Create an instance of the full class.
!
! This is in error irrespective of the validation mode because:
! * 'second' is required but is not bound either explicitly or implicitly.
!-->
<cx:component id="full" class-ref="FullClass">
<cx:ref name="first" component="partial"/>
<!--
! The following cx:ref is is in error irrespective of the validation mode as it is
! using a reference 'sekond' that has not been defined and the component class
! specifically indicates through having reference-types in the defines attribute
! that it has defined all the references.
!-->
<cx:ref name="sekond" component="partial"/>
<!--
! The following cx:ref is in error if the validation mode for this instance is set to
! strict or warn as it is referencing a component that has not been explicitly defined
! in the page. It may be defined in the custom script, in which case
! the validation mode for this instance should be set to lax until the page is
! modified to use cx:component markup to create the instance.
!-->
<cx:ref name="last" component="other2"/>
<!--
! The following cx:ref is in error irrespective of the validation mode because it must
! be a reference to a component implementing my:NoReference but the referenced
! component only implements my:PartialClass.
!-->
<cx:ref name="third" component="partial"/>
<!--
! The following cx:ref is in error if the validation mode for this instance is set to
! strict or warn as it is referencing a component that has not been explicitly defined
! in the page.
!-->
<cx:ref name="box" component="box"/>
</cx:component>
<!--
! Create an instance of the partial class.
!
! This is in error irrespective of the validation mode because:
! * 'another' is required but is not bound either explicitly or implicitly.
!-->
<cx:component id="partial" class-ref="PartialClass">
<cx:ref name="other" component="partial"/>
<!--
! The following cx:ref is in error if the validation mode for this instance is set to
! strict or warn as it is using a reference that has not been defined. If the
! validation mode is set to lax then this is not an error because the component class
! does not indicate that all references have been specified.
!
! If this is not an error then this behaves as if a reference was defined using
! the following markup:
! <cx:reference name="extra" component-types=""/>
!-->
<cx:ref name="extra" component="other1"/>
</cx:component>
<!--
! Create an instance of the no reference class.
!-->
<cx:component id="no-ref" class-ref="NoReference"/>
<ui:box id="box"/>
</body>
</html>