Latest refinements and batch of questions:
 1  I gave up type subclassing, too much work and nobody seems excited

 2 should we have <fields/> and <getters/> or should <field/> <getter/> be directly under <bean/> ?

 3 should we have <groups/> or should <group/> be under <constraint/> directly?

 4 should we allow 
<element name"size">30</element> 
with the risk of people doing 
<element name"size">30<value>blah</value></element>
or should we mandate the use of value
<element name"size"><value>30</value></element> 

 5 if some people could look at the xsd and propose improvement, that'd be great.

I plan to introduce that in the spec tomorrow, so early feedback would be fantastic

XML represents a sample and XSD is the schema generated from the XML file and adjusted.

<?xml version="1.0" encoding="UTF-8"?>
<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 mapping.xsd">
    <default-package>com.acme.dvdstore.model</default-package>
    <bean class="Customer" ignore-annotations="true"> <!-- default false -->
        <class ignore-annotations="true">
            <stop-constraint-inheritance/>
            <constraint annotation="constraint.ConstraintTest">
              <message>{error.tooSmall}</message>
              <groups>
                <group>javax.validation.groups.Default</group>
                <group>javax.validation.groups.NONDEFAULT</group>
              </groups>
              <element name="max">2</element>
              <element name="defaultClass">com.acme.MyClass</element>
              <element name="states">
                <value>com.myenum.State.OK</value>
                <value>com.myenum.State.NOK</value>
              </element>
              <element name="patterns">
                <annotation>
                  <element name="value">kindaregexp</element>
                  <element name="states">
                    <value>com.myenum.State.OK</value>
                    <value>com.myenum.State.NOK</value>
                  </element>
                </annotation>
                <annotation>
                  <element name="value">kindaregexp</element>
                  <element name="states">
                    <value>com.myenum.State.OK</value>
                    <value>com.myenum.State.NOK</value>
                  </element>
                </annotation>
              </element>
            </constraint>
            <constraint annotation="constraint.ConstraintTest">
              <message>{error.tooSmall}</message>
              <groups>
                <group>javax.validation.groups.Default</group>
                <group>javax.validation.groups.NONDEFAULT</group>
              </groups>
              <element name="max">2</element>
              <element name="defaultClass">com.acme.MyClass</element>
              <element name="states">
                <value>com.myenum.State.OK</value>
                <value>com.myenum.State.NOK</value>
              </element>
              <element name="patterns">
                <annotation>
                  <element name="value">kindaregexp</element>
                  <element name="states">
                    <value>com.myenum.State.OK</value>
                    <value>com.myenum.State.NOK</value>
                  </element>
                </annotation>
                <annotation>
                  <element name="value">kindaregexp</element>
                  <element name="states">
                    <value>com.myenum.State.OK</value>
                    <value>com.myenum.State.NOK</value>
                  </element>
                </annotation>
              </element>
            </constraint>

        </class>
        <fields>
            <field name="firstname" ignore-annotations="true">
              <valid/>
              <stop-constraint-inheritance/>
              <constraint annotation="constraint.ConstraintTest">
              <message>{error.tooSmall}</message>
              <groups>
                <group>javax.validation.groups.Default</group>
                <group>javax.validation.groups.NONDEFAULT</group>
              </groups>
              <element name="max">2</element>
              <element name="defaultClass">com.acme.MyClass</element>
              <element name="states">
                <value>com.myenum.State.OK</value>
                <value>com.myenum.State.NOK</value>
              </element>
              <element name="patterns">
                <annotation>
                  <element name="value">kindaregexp</element>
                  <element name="states">
                    <value>com.myenum.State.OK</value>
                    <value>com.myenum.State.NOK</value>
                  </element>
                </annotation>
                <annotation>
                  <element name="value">kindaregexp</element>
                  <element name="states">
                    <value>com.myenum.State.OK</value>
                    <value>com.myenum.State.NOK</value>
                  </element>
                </annotation>
              </element>
            </constraint>
            </field>
            <field name="firstname">
              <constraint annotation="constraint.ConstraintTest">
              <message>{error.tooSmall}</message>
              <groups>
                <group>javax.validation.groups.Default</group>
                <group>javax.validation.groups.NONDEFAULT</group>
              </groups>
            </constraint>
            </field>
        </fields>
        <getters>
            <getter name="firstname" ignore-annotations="true">
              <valid/>
              <stop-constraint-inheritance/>
              <constraint annotation="constraint.ConstraintTest">
              <message>{error.tooSmall}</message>
              <groups>
                <group>javax.validation.groups.Default</group>
                <group>javax.validation.groups.NONDEFAULT</group>
              </groups>
              <element name="max">2</element>
              <element name="defaultClass">com.acme.MyClass</element>
              <element name="states">
                <value>com.myenum.State.OK</value>
                <value>com.myenum.State.NOK</value>
              </element>
              <element name="patterns">
                <annotation>
                  <element name="value">kindaregexp</element>
                  <element name="states">
                    <value>com.myenum.State.OK</value>
                    <value>com.myenum.State.NOK</value>
                  </element>
                </annotation>
                <annotation>
                  <element name="value">kindaregexp</element>
                  <element name="states">
                    <value>com.myenum.State.OK</value>
                    <value>com.myenum.State.NOK</value>
                  </element>
                </annotation>
              </element>
            </constraint>
            </getter>
            <getter name="firstname">
              <constraint annotation="constraint.ConstraintTest">
                <message>{error.tooSmall}</message>
                <groups>
                  <group>javax.validation.groups.Default</group>
                  <group>javax.validation.groups.NONDEFAULT</group>
                </groups>
              </constraint>
              <constraint annotation="javax.validation.NotNull"/>
            </getter>
        </getters>
    </bean>

    <bean class="User"> <!-- default false -->
        <class>
            <stop-constraint-inheritance/>
            <constraint annotation="constraint.ConstraintTest">
              <element name="max">2</element>
              <element name="defaultClass">com.acme.MyClass</element>
              <element name="states">
                <value>com.myenum.State.OK</value>
                <value>com.myenum.State.NOK</value>
              </element>
              <element name="patterns">
                <annotation>
                  <element name="value">kindaregexp</element>
                  <element name="states">
                    <value>com.myenum.State.OK</value>
                    <value>com.myenum.State.NOK</value>
                  </element>
                </annotation>
                <annotation>
                  <element name="value">kindaregexp</element>
                  <element name="states">
                    <value>com.myenum.State.OK</value>
                    <value>com.myenum.State.NOK</value>
                  </element>
                </annotation>
              </element>
            </constraint>
        </class>
    </bean>

    <constraint-definition annotation="javax.validation.NotNull">
      <validated-by include-existing-validators="true">
          <value>NotNullObjectValidator</value>
          <value>NotNullStringValidator</value> <!-- assuming a null string is validated differently :) -->
      </validated-by>
    </constraint-definition>
    <constraint-definition annotation="javax.validation.NotNull">
      <validated-by>
          <value>NotNullObjectValidator</value>
          <value>NotNullStringValidator</value> <!-- assuming a null string is validated differently :) -->
      </validated-by>
    </constraint-definition>
</constraint-mappings>

Attachment: mapping.xsd
Description: Binary data



On  Jan 26, 2009, at 12:08, Emmanuel Bernard wrote:

Feedback please. I am sick of talking to myself

On  Jan 21, 2009, at 23:37, Emmanuel Bernard wrote:

I looked at the OVAL schema and as usual there are good stuffs here, I also added some missing elements
 - I forgot the flag to be able to ignore existing annotations
 - I forgot the @Valid equivalent
 - OVal has the ability to describe OVal specific constraints in a typesafe way but not custom user constraints (as far as I can see). 

Let me know what you think, especially on the constraints declarations options.

Ignore Annotation flag
Should the ignore-annotation flag be a <bean/> level attribute only or should a user be able to define it at the field/method/class level?
If set to true, annotations placed on the bean, field or getter will not be considered. If set to false, they will.

@Valid
<valid/>
will indicate that a field or a getter is to be cascaded

Constraints declarations
In the current schema proposal, here is how constraints are declared

           <constraint annotation="com.acme.validate.SafeCustomer">
               <attribute name="category">
                   <array-element>com.acme.validate.SecurityLevel.SECURED_COUNTRY</array-element>
                   <array-element>com.acme.validate.SecurityLevel.SECURED_ADDRESS</array-element>
                   <array-element>com.acme.validate.SecurityLevel.SECURED_FINANCIALS</array-element>
               </attribute>
               <attribute name="failPerCategory">false</attribute>
           </constraint>
           <constraint annotation="javax.validation.constraint.NotNull">
               <message>blah</message>
           </constraint>

We could enhance this in two ways:
 - provide type-safe support for built-in validations:
<not-null/>, 
<min>
  <value>3</value>
  <message>blah</message>
</min>
etc
 - allow custom constraints support in a type-safe way: 

The second point would work as followed
 - a constraint annotation would be associated with a given XML type eg. <Min/>
 - propose an abstract constraintType XML type that any constraint declared in XML would inherit (Min would extend ConstraintType)
 - thanks to that message and groups would be inherited
 - Min would have an attribute "annotation" fixed to the f.q.c.n of the corresponding annotation (I haven't find a way to hide it from the user but still have it present at parsing time)
 - subelements of a constraint XML element would represent attributes of the annotation (with the same name)

<?xml version="1.0" encoding="UTF-8"?>
<validation-mappings
  xmlns:appval="http://acme.com/appval"
  xsi:schemaLocation="http://jboss.com/java/validation-mapping validation-mapping.xsd">
    <default-package>com.acme.dvdstore.model</default-package>
    <bean class="Customer" ignore-annotations="true">
        <class>
            <constraint annotation="com.acme.validate.SafeCustomer">
                <attribute name="category">
                    <array-element>com.acme.validate.SecurityLevel.SECURED_COUNTRY</array-element>
                    <array-element>com.acme.validate.SecurityLevel.SECURED_ADDRESS</array-element>
                    <array-element>com.acme.validate.SecurityLevel.SECURED_FINANCIALS</array-element>
                </attribute>
                <attribute name="failPerCategory">false</attribute>
            </constraint>
        </class>
        <fields>
            <field name="firstname">
                 <valid/>
                <appval:min annotation="javax.validation.constraint.Min">
                    <message>blah</message>
                    <value>4</value>
                </appval:min>
                <constraint annotation="javax.validation.Min">
                    <message>{error.tooSmall}</message>
                    <groups>
                        <group>javax.validation.groups.Default</group>
                    </groups>
                    <attribute name="value">45</attribute>
                </constraint>
            </field>
        </fields>
        <getters>
            <getter name="firstname">
                <ignore-annotations/>
                <stop-inheritance/>
                <constraint annotation="javax.validation.Min">
                    <message>{error.tooSmall}</message>
                    <groups>
                        <group>javax.validation.groups.Default</group>
                    </groups>
                    <attribute name="value">45</attribute>
                </constraint>
            </getter>
        </getters>
    </bean>
</validation-mappings>


where app:val is described in the XSD as 
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0"
  <xs:element name="min" type="minType"/>

    <xs:complexType name="minType">
        <xs:complexContent>
            <xs:extension base="bv:AbstractConstraintType">
                <xs:sequence>
                    <xs:element name="value" type="xs:int" minOccurs="1"/>
                </xs:sequence>
                <xs:attribute name="annotation" use="required" fixed="javax.validation.constraint.Min"/>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
</xs:schema>

On  Jan 19, 2009, at 19:35, Emmanuel Bernard wrote:

Here is my very first attempt to describe the constraint mapping XML schema.
I did not look at other product approach to avoid being tainted. If you have examples of alternative approach, I would appreciate a link.

A couple of comments:
- I would have preferred a Web Beans style XML approach but this kind of approach is getting some heavy resistance from some members of the expert committee. So I fell back to a more classic approach.
- constraints themselves cannot be defined: you have to write an actual annotation. I wonder if we should provide such model. At minimal we might want to provide a way to override the constraint validator for a given constraint.
- I used JPA 2 mapping schema as inspiration
- I stayed very close to the Java structure

Better names, enhancements, alternative proposals are welcome.

Emmanuel

<?xml version="1.0" encoding="UTF-8"?>
<validation-mappings>
  <package>com.acme.dvdstore.model</package>
  <bean class="Customer">
      <class>
          <constraint annotation="com.acme.validate.SafeCustomer">
              <attribute name="category">
                  <array-element>com.acme.validate.SecurityLevel.SECURED_COUNTRY</array-element>
                  <array-element>com.acme.validate.SecurityLevel.SECURED_ADDRESS</array-element>
                  <array-element>com.acme.validate.SecurityLevel.SECURED_FINANCIALS</array-element>
              </attribute>
              <attribute name="failPerCategory">false</attribute>
          </constraint>
      </class>
      <fields>
          <field name="firstname">
              <ignore-annotations/>
              <stop-inheritance/>
              <constraint annotation="javax.validation.Min">
                  <message>{error.tooSmall}</message>
                  <groups>
                      <group>javax.validation.groups.Default</group>
                  </groups>
                  <attribute name="value">45</attribute>
              </constraint>
          </field>
      </fields>
      <getters>
          <getter name="firstname">
              <ignore-annotations/>
              <stop-inheritance/>
              <constraint annotation="javax.validation.Min">
                  <message>{error.tooSmall}</message>
                  <groups>
                      <group>javax.validation.groups.Default</group>
                  </groups>
                  <attribute name="value">45</attribute>
              </constraint>
          </getter>
      </getters>
  </bean>
</validation-mappings>
_______________________________________________
hibernate-dev mailing list
hibernate-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev

_______________________________________________
hibernate-dev mailing list
hibernate-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev

_______________________________________________
hibernate-dev mailing list
hibernate-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev

_______________________________________________
hibernate-dev mailing list
hibernate-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev

Reply via email to