[hibernate-dev] [Bean Validation] XML Mapping with rules (in the spec)

Emmanuel Bernard emmanuel at hibernate.org
Fri Jan 30 14:54:04 EST 2009


Check out chapter 7 of the spec.
It includes all the overriding rules. I adjusted a bit the schema as  
well.

The full spec is available on demand.
Chapter 7. XML deployment descriptor

Two kind of XML descriptors are used by Bean Validation. The first one  
describes the Bean Validation configuration provided as META-INF/ 
validation.xml. The second one describes constraints declarations and  
closely matches the annotations declaration approach.

7.1. Constraint definition and declaration

Bean Validation lets you declare constraints via XML rather than  
annotations. You can either ignore constraints declared via  
annotations or consider XML as adding additional constraints on top of  
annotation constraints. While it is not possible to define a new  
constraint via XML, you can redefine the list of ConstraintValidator  
classes associated to a given constraint definition.

There is no distinction between an annotation based constraint  
declaration and an XML based constraint declaration: they are  
considered equivalent and should be treaded as such by the Bean  
Validation provider.. Specifically when exploring metadata, the Bean  
Validation provider must ensure that an annotation instance  
corresponding to the XML declaration is provided  
viaConstraintDescriptor.getAnnnotation(). The annotation elements as  
well as ConstraintValidator.getParameters() must reflect the values  
described in the XML declaration (seeSection 7.1.3, “Converting the  
string representation of a value”). Likewise,  
ConstraintDescriptor.getConstraintValidatorClasses() must reflect XML  
based constraint definition overriding (see Section 7.1.2, “Overriding  
constraint definitions in XML”).

A given class must not be described more than once amongst the XML  
mapping descriptors. A given field or getter must not be described  
more than once on a given class description. A given constraint  
definition must not be overridden more than once amongst the XML  
mapping descriptors. If any of these rule is violated in a given  
validation deployment, aDuplicateMappingException is raised during the  
creation of the ValidatorFactory.

The schema is provided in Section 7.1.4, “XML Schema”.

7.1.1. Constraint declaration in XML

If default-package is set, all unqualified class names (including  
annotations) are considered part of the package described by default- 
package.

A given JavaBean is described by the bean element. The name of the  
class is mandatory. By default, all constraint declarations expressed  
via annotation are ignored for classes described in XML. You can force  
Bean Validation to consider both annotation and XML constraint  
declarations by using ignore-annotation="false" on bean.

If the name of the class does refer to a class not present in in the  
classpath, a ConfigurationException is raised.

Example 7.1. Example of bean XML declaration

<constraint-mappings
         xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping 
  validation-mapping-1.0.xsd">

     <default-package>com.acme.app.domain</default-package>

     <bean class="Customer" ignore-annotations="false">
         [...]
     </bean>
     <bean class="com.acme.common.model.Address">
         [...]
     </bean>
</constraint-mappings>
7.1.1.1. Class-level overriding

Class level annotations are described via the class element. If ignore- 
annotations is declared, Bean Validation must honor the explicit value  
for this element. If not declared, the default value for the bean is  
considered.

When ignore annotations is true, class-level Bean Validation  
annotations are ignored for this class (including the @GroupSequence).  
When ignore annotations is false:

Constraints declared in XML and constraints declared in annotations  
are added and form the list of class-level declared constraints.

@GroupSequence is considered unless group-sequence element is  
explicitly used.

Example 7.2. Example of class-level declaration

<constraint-mappings
         xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping 
  validation-mapping-1.0.xsd">
     <default-package>com.acme.app.domain</default-package>
     <bean class="Customer" ignore-annotations="false">
         <class ignore-annotations="true">
             [...]
         </class>
     </bean>
     <bean class="com.acme.common.model.Address">
         <class>
             [...]
         </class>
     </bean>
</constraint-mappings>
7.1.1.2. Field-level overriding

Field level annotations are described via the field element. The name  
attribute correspond to the name of the field considered. If ignore- 
annotations is declared, Bean Validation must honor the explicit value  
for this element. If not declared, the default value for the bean is  
considered.

When ignore annotations is true, field-level Bean Validation  
annotations on the targeted field are ignored (including the @Valid).  
When ignore annotations is false:

Constraints declared in XML and constraints declared in annotations  
are added and form the list of field-level declared constraints.

@Valid is considered unless valid element is explicitly use. Note that  
the only way to disable cascading on a field marked as @Valid is to  
use ignore-validation=true.

If the name of the field does not correspond to a field in the given  
bean a ConfigurationException is raised.

Example 7.3. Field-level declaration

<constraint-mappings
         xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping 
  validation-mapping-1.0.xsd">
     <default-package>com.acme.app.domain</default-package>
     <bean class="Customer" ignore-annotations="false">
         <field name="firstName">
             [...]
         </field>
         <field name="orders">
             <valid/>
             [...]
         </field>
     </bean>
</constraint-mappings>
7.1.1.3. Property-level overriding

Property-level annotations are described via the getter element. The  
name attribute correspond to the name of the property considered as  
defined in Section 3.1.2, “Field and property validation” (for example  
a getter String getAge() would have <getter name="age"/> as a  
corresponding descriptor). If ignore-annotations is declared, Bean  
Validation must honor the explicit value for this element. If not  
declared, the default value for the bean is considered.

When ignore annotations is true, property-level Bean Validation  
annotations on the targeted property are ignored (including the  
@Valid). When ignore annotations is false:

Constraints declared in XML and constraints declared in annotations  
are added and form the list of property-level declared constraints.

@Valid is considered unless valid element is explicitly use. Note that  
the only way to disable cascading on a field marked as @Valid is to  
use ignore-validation=true.

If the name of the property does not correspond to a property in the  
given bean a ConfigurationException is raised.

Example 7.4. Property-level declaration

<constraint-mappings
         xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping 
  validation-mapping-1.0.xsd">
     <default-package>com.acme.app.domain</default-package>
     <bean class="Customer" ignore-annotations="false">
         <getter name="firstName">
             [...]
         </getter>
         <getter name="orders">
             <valid/>
             [...]
         </getter>
     </bean>
</constraint-mappings>
7.1.1.4. Constraint declaration

A new constraint declaration is represented by the constraint element.  
The annotation attribute is the class name of the annotation  
representing the constraint. Message and groups are defined  
respectively by the message and groups elements.

Other custom elements of an annotation are represented by element. The  
name attribute is mandatory and represents the name of the element in  
the constraint declaration. “message”, “groups” are not permitted  
names, use the message or groups elements instead.

If the element represents a primitive type, a class or an enum, the  
string representation of its value is placed in the element itself.  
See Section 7.1.3, “Converting the string representation of a value”  
for a detailed explanation of the conversion rules from string to the  
type.

If the element represents a primitive type array, a class array or an  
enum array, the string representation of each value is placed in a  
value element placed under the element itself.

If the element represents an annotation, the annotation element is  
used to represent the annotation and placed under element. An  
annotation element contains element elements.

If the element represents an array of annotations, one or more  
annotation elements are placed under element.

Elements with default values in the annotation definition do not have  
to be represented in XML: the default value will be used in this case.  
If an XML constraint declaration is missing mandatory elements, or if  
it contains elements not part of the constraint definition, a  
ConfigurationException is raised.

Example 7.5. Constraint declaration

<constraint-mappings
         xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping 
  validation-mapping-1.0.xsd">
     <default-package>com.acme.app.domain</default-package>
     <bean class="Customer" ignore-annotations="false">

         <field name="firstName">


             <!-- @LooksLike(patterns={
                       @Pattern(value="myRegExp",  
flag=PatternFlag.INSENSITIVE),
                       @Pattern(value="my2ndRegExp")}
                   )
              -->
             <constraint annotation="com.acme.app.constraint.LooksLike">
                 <element name="patterns">
                     <annotation>
                         <element name="value">myRegExp</element>
                         <element name="flag">
                             <value>INSENSITIVE</value>
                         </element>
                     </annotation>
                     <annotation>
                         <element name="value">my2ndRegExp</element>
                     </annotation>
                 </element>
             </constraint>


         </field>
         <field name="orders">
             <valid/>


             <!-- @DiscreteSize(value={ 0, 20 } )
              -->
             <constraint  
annotation="com.acme.app.constraint.DiscreteSize">
                 <element name="value">
                     <value>0</value>
                     <value>20</value>
                 </element>
             </constraint>


         </field>

         <getter name="orders">
             <valid/>


             <!-- @Size(message="Size is limited",
                        groups={Default.class, LightValidation.class},
                        max=30
                  )
             -->
             <constraint annotation="javax.validation.constraint.Size">
                 <message>Size is limited</message>
                 <groups>
                     <value>com.acme.app.model.LightValidation</value>
                     <value>javax.persistence.Default</value>
                 </groups>
                 <element name="max">30</element>
             </constraint>


         </getter>
     </bean>
</constraint-mappings>
7.1.2. Overriding constraint definitions in XML

A constraint definition (ie. the annotation representing a  
constraint), cannot be fully expressed in XML but the list of  
ConstraintValidator associated to a given constraint can be altered.

A constraint definition is represented by a constraint-definition  
element. The annotation attribute represents the constraint annotation  
being altered. The validated-by elements represent the (ordered) list  
of ConstraintValidator implementations associated to the constraint.

If include-existing-validator is set to false, ConstraintValidator  
defined on the constraint annotation are ignored. If set to true, the  
list of ConstraintValidators described in XML are concatenated to the  
list of ConstraintValidator described on the annotation to form a new  
array of ConstraintValidator evaluated. Annotation based  
ConstraintValidator come before XML based ConstraintValidatot in the  
array. The new array is returned by  
ConstraintDescriptor.getConstraintValidatorClasses().

Example 7.6. Overriding constraint definitions

<constraint-mappings
         xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping 
  validation-mapping-1.0.xsd">
    <default-package>com.acme.app.domain</default-package>
    <bean class="com.acme.common.model.Address">
        [...]
     </bean>

     <constraint-definition  
annotation="javax.validation.constraint.Size">
         <validated-by include-existing-validators="true">
              
<value>com.acme.app.constraint.SizeValidatorForDictionary</value>
         </validated-by>
     </constraint-definition>
     <constraint-definition annotation="AcmeOrderNumber">
         [...]
     </constraint-definition>
</constraint-mappings>
7.1.3. Converting the string representation of a value

Primitive types, Class and Enum are represented as strings in the XML  
descriptor. Elements of an array are represented by the value element.

byte are represented according to the rules defined in  
Byte.parseByte(String).

short are represented according to the rules defined in  
Short.parseShort(String).

int are represented according to the rules defined in  
Integer.parseInt(String).

long are represented according to the rules defined in  
Long.parseLong(String).

float are represented according to the rules defined in  
Float.parseFloat(String).

double are represented according to the rules defined in  
Double.parseDouble(String).

boolean are represented according to the rules defined in  
Boolean.parseBoolean(String).

char are represented according to the following rules:

the string must be of one character long

the character extracted from the string is the returned char

A Class is represented by the fully qualified class name of the class.  
Note that if the raw string is unqualified, default package is taken  
into account.

An enum is represented by its enum.name() value.

If any of the string representation does not match its type  
counterpart, a ConfigurationException is raised.

7.1.4. XML Schema

This section contains the XML schema used for constraint mapping.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified"
            elementFormDefault="qualified"
            targetNamespace="http://jboss.org/xml/ns/javax/validation/mapping 
"
            xmlns:xs="http://www.w3.org/2001/XMLSchema"
            version="1.0">
     <xs:element name="constraint-mappings"
                 type="map:constraint-mappingsType"
                 xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>

     <xs:complexType name="groupsType">
         <xs:sequence>
             <xs:element type="xs:string" name="value"  
maxOccurs="unbounded" minOccurs="0"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="groupSequenceType">
         <xs:sequence>
             <xs:element type="xs:string" name="value"  
maxOccurs="unbounded" minOccurs="0"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="constraint-mappingsType">
         <xs:sequence>
             <xs:element type="xs:string" name="default-package"  
minOccurs="0"/>
             <xs:element type="map:beanType"
                         name="bean"
                         maxOccurs="unbounded"
                         minOccurs="0"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
             <xs:element type="map:constraint-definitionType"
                         name="constraint-definition"
                         maxOccurs="unbounded"
                         minOccurs="0"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="validated-byType">
         <xs:sequence>
             <xs:element type="xs:string" name="value"  
maxOccurs="unbounded" minOccurs="0"/>
         </xs:sequence>
         <xs:attribute type="xs:boolean" name="include-existing- 
validators" use="optional"/>
     </xs:complexType>
     <xs:complexType name="constraintType">
         <xs:sequence>
             <xs:element type="xs:string" name="message" minOccurs="0"/>
             <xs:element type="map:groupsType"
                         name="groups"
                         minOccurs="0"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
             <xs:element type="map:elementType"
                         name="element"
                         maxOccurs="unbounded"
                         minOccurs="0"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
         </xs:sequence>
         <xs:attribute type="xs:string" name="annotation"  
use="required"/>
     </xs:complexType>
     <xs:complexType name="elementType" mixed="true">
         <xs:sequence>
             <xs:element type="xs:string" name="value"  
maxOccurs="unbounded" minOccurs="0"/>
             <xs:element type="map:annotationType"
                         name="annotation"
                         maxOccurs="unbounded"
                         minOccurs="0"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
         </xs:sequence>
         <xs:attribute type="xs:string" name="name" use="required"/>
     </xs:complexType>
     <xs:complexType name="classType">
         <xs:sequence>
             <xs:element type="groupSequenceType" name="group- 
sequence" minOccurs="0"/>
             <xs:element type="xs:simpleType" name="stop-constraint- 
inheritance" fixed="" minOccurs="0"/>
             <xs:element type="map:constraintType"
                         name="constraint"
                         maxOccurs="unbounded"
                         minOccurs="0"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
         </xs:sequence>
         <xs:attribute type="xs:boolean" name="ignore-annotations"  
use="optional"/>
     </xs:complexType>
     <xs:complexType name="beanType">
         <xs:sequence>
             <xs:element type="map:classType"
                         name="class"
                         minOccurs="0"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
">
             </xs:element>
             <xs:element type="map:fieldType"
                         name="field"
                         minOccurs="0"
                         maxOccurs="unbounded"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
             <xs:element type="map:getterType"
                         name="getter"
                         minOccurs="0"
                         maxOccurs="unbounded"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
         </xs:sequence>
         <xs:attribute type="xs:string" name="class" use="required"/>
         <xs:attribute type="xs:boolean" name="ignore-annotations"  
use="optional"/>
     </xs:complexType>
     <xs:complexType name="annotationType">
         <xs:sequence>
             <xs:element type="map:elementType"
                         name="element"
                         maxOccurs="unbounded"
                         minOccurs="0"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="getterType">
         <xs:sequence>
             <xs:element type="xs:string" name="valid" minOccurs="0"  
fixed=""/>
             <xs:element type="xs:string" name="stop-constraint- 
inheritance" minOccurs="0" fixed=""/>
             <xs:element type="map:constraintType"
                         name="constraint"
                         minOccurs="0"
                         maxOccurs="unbounded"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
         </xs:sequence>
         <xs:attribute type="xs:string" name="name" use="required"/>
         <xs:attribute type="xs:boolean" name="ignore-annotations"  
use="optional"/>
     </xs:complexType>
     <xs:complexType name="constraint-definitionType">
         <xs:sequence>
             <xs:element type="map:validated-byType"
                         name="validated-by"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
         </xs:sequence>
         <xs:attribute type="xs:string" name="annotation"  
use="required"/>
     </xs:complexType>
     <xs:complexType name="fieldType">
         <xs:sequence>
             <xs:element type="xs:string" name="valid" minOccurs="0"  
fixed=""/>
             <xs:element type="xs:string" name="stop-constraint- 
inheritance" minOccurs="0" fixed=""/>
             <xs:element type="map:constraintType"
                         name="constraint"
                         minOccurs="0"
                         maxOccurs="unbounded"
                         xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping 
"/>
         </xs:sequence>
         <xs:attribute type="xs:string" name="name" use="required"/>
         <xs:attribute type="xs:boolean" name="ignore-annotations"  
use="optional"/>
     </xs:complexType>
</xs:schema>




-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/hibernate-dev/attachments/20090130/2149a057/attachment.html 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: validation-mapping-1.0.xsd
Type: application/octet-stream
Size: 6954 bytes
Desc: not available
Url : http://lists.jboss.org/pipermail/hibernate-dev/attachments/20090130/2149a057/attachment.obj 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/hibernate-dev/attachments/20090130/2149a057/attachment-0001.html 


More information about the hibernate-dev mailing list