[hibernate-commits] Hibernate SVN: r15907 - in validator/trunk/hibernate-validator: src/main and 9 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Thu Feb 5 12:43:34 EST 2009
Author: hardy.ferentschik
Date: 2009-02-05 12:43:34 -0500 (Thu, 05 Feb 2009)
New Revision: 15907
Added:
validator/trunk/hibernate-validator/src/main/docbook/
validator/trunk/hibernate-validator/src/main/docbook/en-US/
validator/trunk/hibernate-validator/src/main/docbook/en-US/images/
validator/trunk/hibernate-validator/src/main/docbook/en-US/images/hibernate_logo_a.png
validator/trunk/hibernate-validator/src/main/docbook/en-US/master.xml
validator/trunk/hibernate-validator/src/main/docbook/en-US/modules/
validator/trunk/hibernate-validator/src/main/docbook/en-US/modules/checkconstraints.xml
validator/trunk/hibernate-validator/src/main/docbook/en-US/modules/defineconstraints.xml
validator/trunk/hibernate-validator/src/test/resources/org/
validator/trunk/hibernate-validator/src/test/resources/org/hibernate/
validator/trunk/hibernate-validator/src/test/resources/org/hibernate/validation/
validator/trunk/hibernate-validator/src/test/resources/org/hibernate/validation/ValidationMessages_de.properties
Modified:
validator/trunk/hibernate-validator/pom.xml
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolator.java
Log:
Checked in a shell for the new documentation and added it to the build cycle
Modified: validator/trunk/hibernate-validator/pom.xml
===================================================================
--- validator/trunk/hibernate-validator/pom.xml 2009-02-05 17:41:58 UTC (rev 15906)
+++ validator/trunk/hibernate-validator/pom.xml 2009-02-05 17:43:34 UTC (rev 15907)
@@ -66,6 +66,62 @@
<testOutputDirectory>${project.build.directory}/site</testOutputDirectory>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.jboss.maven.plugins</groupId>
+ <artifactId>maven-jdocbook-plugin</artifactId>
+ <version>2.1.0</version>
+ <extensions>true</extensions>
+ <dependencies>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-jdocbook-style</artifactId>
+ <version>1.0.2</version>
+ <type>jdocbook-style</type>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <sourceDocumentName>master.xml</sourceDocumentName>
+ <sourceDirectory>${basedir}/src/main/docbook/en-US</sourceDirectory>
+ <masterTranslation>en-US</masterTranslation>
+ <imageResource>
+ <directory>${basedir}/src/main/docbook/en-US/images</directory>
+ </imageResource>
+ <formats>
+ <format>
+ <formatName>pdf</formatName>
+ <stylesheetResource>classpath:/xslt/hibernate/pdf/main-pdf.xsl</stylesheetResource>
+ <finalName>hibernate-validator-guide.pdf</finalName>
+ </format>
+ <format>
+ <formatName>html_single</formatName>
+ <stylesheetResource>classpath:/xslt/hibernate/html/main-single.xsl
+ </stylesheetResource>
+ <finalName>index.html</finalName>
+ </format>
+ <format>
+ <formatName>html</formatName>
+ <stylesheetResource>classpath:/xslt/hibernate/html/main-chunk.xsl
+ </stylesheetResource>
+ <finalName>index.html</finalName>
+ </format>
+ </formats>
+ <options>
+ <xincludeSupported>true</xincludeSupported>
+ <localeSeparator>-</localeSeparator>
+ <useRelativeImageUris>true</useRelativeImageUris>
+ </options>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-doc</id>
+ <phase>package</phase>
+ <goals>
+ <goal>resources</goal>
+ <goal>generate</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
<reporting>
Added: validator/trunk/hibernate-validator/src/main/docbook/en-US/images/hibernate_logo_a.png
===================================================================
(Binary files differ)
Property changes on: validator/trunk/hibernate-validator/src/main/docbook/en-US/images/hibernate_logo_a.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: validator/trunk/hibernate-validator/src/main/docbook/en-US/master.xml
===================================================================
--- validator/trunk/hibernate-validator/src/main/docbook/en-US/master.xml (rev 0)
+++ validator/trunk/hibernate-validator/src/main/docbook/en-US/master.xml 2009-02-05 17:43:34 UTC (rev 15907)
@@ -0,0 +1,92 @@
+<?xml version='1.0' encoding="UTF-8"?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Middleware LLC.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+ <!ENTITY versionNumber "4.0.0.Alpha1">
+ <!ENTITY copyrightYear "2004">
+ <!ENTITY copyrightHolder "Red Hat Middleware, LLC.">
+]>
+
+<book lang="en">
+ <bookinfo>
+ <title>Hibernate Validator</title>
+ <subtitle>Reference Guide</subtitle>
+ <releaseinfo>&versionNumber;</releaseinfo>
+ <productnumber>&versionNumber;</productnumber>
+ <issuenum>1</issuenum>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/hibernate_logo_a.png" format="png" />
+ </imageobject>
+ </mediaobject>
+ <copyright>
+ <year>©rightYear;</year>
+ <holder>©rightHolder;</holder>
+ </copyright>
+ <!-- include translators... -->
+ </bookinfo>
+
+ <toc/>
+
+ <preface id="preface" revision="2">
+ <title>Preface</title>
+
+ <para>Annotations are a very convenient and elegant way to specify
+ invariant constraints for a domain model. You can, for example, express
+ that a property should never be null, that the account balance should be
+ strictly positive, etc. These domain model constraints are declared in the
+ bean itself by annotating its properties. A validator can then read them
+ and check for constraint violations. The validation mechanism can be
+ executed in different layers in your application without having to
+ duplicate any of these rules (presentation layer, data access layer).
+ Following the DRY principle, Hibernate Validator has been designed for
+ that purpose.</para>
+
+ <para>Hibernate Validator works at two levels. First, it is able to check
+ in-memory instances of a class for constraint violations. Second, it can
+ apply the constraints to the Hibernate metamodel and incorporate them into
+ the generated database schema.</para>
+
+ <para>Each constraint annotation is associated to a validator
+ implementation responsible for checking the constraint on the entity
+ instance. A validator can also (optionally) apply the constraint to the
+ Hibernate metamodel, allowing Hibernate to generate DDL that expresses the
+ constraint. With the appropriate event listener, you can execute the
+ checking operation on inserts and updates done by Hibernate. Hibernate
+ Validator is not limited to use with Hibernate. You can easily use it
+ anywhere in your application as well as with any Java Persistence provider
+ (entity listener provided).</para>
+
+ <para>When checking instances at runtime, Hibernate Validator returns
+ information about constraint violations in an array of
+ <classname>InvalidValue</classname> s. Among other information, the
+ <classname>InvalidValue</classname> contains an error description message
+ that can embed the parameter values bundle with the annotation (eg. length
+ limit), and message strings that may be externalized to a
+ <classname>ResourceBundle</classname> .</para>
+ </preface>
+
+ <xi:include href="modules/defineconstraints.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="modules/checkconstraints.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+</book>
\ No newline at end of file
Added: validator/trunk/hibernate-validator/src/main/docbook/en-US/modules/checkconstraints.xml
===================================================================
--- validator/trunk/hibernate-validator/src/main/docbook/en-US/modules/checkconstraints.xml (rev 0)
+++ validator/trunk/hibernate-validator/src/main/docbook/en-US/modules/checkconstraints.xml 2009-02-05 17:43:34 UTC (rev 15907)
@@ -0,0 +1,235 @@
+<?xml version='1.0' encoding="UTF-8"?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Middleware LLC.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+
+<chapter id="validator-checkconstraints">
+ <title>Using the Validator framework</title>
+
+ <para>Hibernate Validator is intended to be used to implement multi-layered
+ data validation, where constraints are expressed in a single place (the
+ annotated domain model) and checked in various different layers of the
+ application.</para>
+
+ <para>This chapter will cover Hibernate Validator usage for different
+ layers</para>
+
+ <section id="validator-checkconstraints-db" revision="2">
+ <title>Database schema-level validation</title>
+
+ <para>Out of the box, Hibernate Annotations will translate the constraints
+ you have defined for your entities into mapping metadata. For example, if
+ a property of your entity is annotated <literal>@NotNull</literal>, its
+ columns will be declared as <literal>not null</literal> in the DDL schema
+ generated by Hibernate.</para>
+
+ <para>Using hbm2ddl, domain model constraints will be expressed into the
+ database schema.</para>
+
+ <para>If, for some reason, the feature needs to be disabled, set
+ <literal>hibernate.validator.apply_to_ddl</literal> to
+ <literal>false</literal>.</para>
+ </section>
+
+ <section id="validator-checkconstraints-orm">
+ <title>ORM integration</title>
+
+ <para>Hibernate Validator integrates with both Hibernate and all pure Java
+ Persistence providers</para>
+
+ <section id="validator-checkconstraints-orm-hibernateevent" revision="1">
+ <title>Hibernate event-based validation</title>
+
+ <para>Hibernate Validator has two built-in Hibernate event listeners.
+ Whenever a <literal>PreInsertEvent</literal> or
+ <literal>PreUpdateEvent</literal> occurs, the listeners will verify all
+ constraints of the entity instance and throw an exception if any
+ constraint is violated. Basically, objects will be checked before any
+ inserts and before any updates made by Hibernate. This includes changes
+ applied by cascade! This is the most convenient and the easiest way to
+ activate the validation process. On constraint violation, the event will
+ raise a runtime <classname>InvalidStateException</classname> which
+ contains an array of <literal>InvalidValue</literal>s describing each
+ failure.</para>
+
+ <para>If Hibernate Validator is present in the classpath, Hibernate
+ Annotations (or Hibernate EntityManager) will use it transparently. If,
+ for some reason, you want to disable this integration, set
+ <literal>hibernate.validator.autoregister_listeners</literal> to
+ false</para>
+
+ <para><note>
+ <para>If the beans are not annotated with validation annotations,
+ there is no runtime performance cost.</para>
+ </note></para>
+
+ <para>In case you need to manually set the event listeners for Hibernate
+ Core, use the following configuration in
+ <literal>hibernate.cfg.xml</literal>:</para>
+
+ <programlisting><hibernate-configuration>
+ ...
+ <event type="pre-update">
+ <listener
+ class="org.hibernate.validator.event.ValidateEventListener"/>
+ </event>
+ <event type="pre-insert">
+ <listener
+ class="org.hibernate.validator.event.ValidateEventListener"/>
+ </event>
+</hibernate-configuration></programlisting>
+ </section>
+
+ <section id="validator-checkconstraints-orm-jpaevent">
+ <title>Java Persistence event-based validation</title>
+
+ <para>Hibernate Validator is not tied to Hibernate for event based
+ validation: a Java Persistence entity listener is available. Whenever an
+ listened entity is persisted or updated, Hibernate Validator will verify
+ all constraints of the entity instance and throw an exception if any
+ constraint is violated. Basically, objects will be checked before any
+ inserts and before any updates made by the Java Persistence provider.
+ This includes changes applied by cascade! On constraint violation, the
+ event will raise a runtime <classname>InvalidStateException</classname>
+ which contains an array of <literal>InvalidValue</literal>s describing
+ each failure.</para>
+
+ <para>Here is how to make a class validatable:</para>
+
+ <programlisting>@Entity
+ at EntityListeners( JPAValidateListener.class )
+public class Submarine {
+ ...
+}</programlisting>
+
+ <para><note>
+ <para>Compared to the Hibernate event, the Java Persistence listener
+ has two drawbacks. You need to define the entity listener on every
+ validatable entity. The DDL generated by your provider will not
+ reflect the constraints.</para>
+ </note></para>
+ </section>
+ </section>
+
+ <section>
+ <title>Application-level validation</title>
+
+ <para>Hibernate Validator can be applied anywhere in your application
+ code.</para>
+
+ <programlisting>ClassValidator personValidator = new ClassValidator( Person.class );
+ClassValidator addressValidator = new ClassValidator( Address.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) );
+
+InvalidValue[] validationMessages = addressValidator.getInvalidValues(address);</programlisting>
+
+ <para>The first two lines prepare the Hibernate Validator for class
+ checking. The first one relies upon the error messages embedded in
+ Hibernate Validator (see <xref
+ linkend="validator-defineconstraints-error" />), the second one uses a
+ resource bundle for these messages. It is considered a good practice to
+ execute these lines once and cache the validator instances.</para>
+
+ <para>The third line actually validates the <literal>Address</literal>
+ instance and returns an array of <literal>InvalidValue</literal>s. Your
+ application logic will then be able to react to the failure.</para>
+
+ <para>You can also check a particular property instead of the whole bean.
+ This might be useful for property per property user interaction</para>
+
+ <programlisting>ClassValidator addressValidator = new ClassValidator( Address.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) );
+
+//only get city property invalid values
+InvalidValue[] validationMessages = addressValidator.getInvalidValues(address, "city");
+
+//only get potential city property invalid values
+InvalidValue[] validationMessages = addressValidator.getPotentialInvalidValues("city", "Paris")</programlisting>
+ </section>
+
+ <section>
+ <title>Presentation layer validation</title>
+
+ <para>When working with JSF and <productname>JBoss Seam</productname>, one
+ can triggers the validation process at the presentation layer using Seam's
+ JSF tags <literal><s:validate></literal> and
+ <literal><s:validateAll/></literal>, letting the constraints be
+ expressed on the model, and the violations presented in the view</para>
+
+ <programlisting><h:form>
+ <div>
+ <h:messages/>
+ </div>
+ <emphasis role="bold"><s:validateAll></emphasis>
+ <div>
+ Country:
+ <h:inputText value="#{location.country}" required="true"/>
+ </div>
+ <div>
+ Zip code:
+ <h:inputText value="#{location.zip}" required="true"/>
+ </div>
+ <div>
+ <h:commandButton/>
+ </div>
+ <emphasis role="bold"></s:validateAll></emphasis>
+</h:form></programlisting>
+
+ <para>Going even further, and adding <productname>Ajax4JSF</productname>
+ to the loop will bring client side validation with just a couple of
+ additional JSF tags, again without validation definition
+ duplication.</para>
+
+ <para>Check the <ulink url="http://www.jboss.com/products/seam">JBoss
+ Seam</ulink> documentation for more information.</para>
+ </section>
+
+ <section>
+ <title>Validation informations</title>
+
+ <para>As a validation information carrier, hibernate provide an array of
+ <classname>InvalidValue</classname>. Each <literal>InvalidValue</literal>
+ has a buch of methods describing the individual issues.</para>
+
+ <para><methodname>getBeanClass()</methodname> retrieves the failing bean
+ type</para>
+
+ <para><methodname>getBean()</methodname>retrieves the failing instance (if
+ any ie not when using
+ <methodname>getPotentianInvalidValues()</methodname>)</para>
+
+ <para><methodname>getValue()</methodname> retrieves the failing
+ value</para>
+
+ <para><methodname>getMessage()</methodname> retrieves the proper
+ internationalized error message</para>
+
+ <para><methodname>getRootBean()</methodname> retrieves the root bean
+ instance generating the issue (useful in conjunction with
+ <literal>@Valid</literal>), is null if getPotentianInvalidValues() is
+ used.</para>
+
+ <para><literal>getPropertyPath()</literal> retrieves the dotted path of
+ the failing property starting from the root bean</para>
+ </section>
+</chapter>
\ No newline at end of file
Added: validator/trunk/hibernate-validator/src/main/docbook/en-US/modules/defineconstraints.xml
===================================================================
--- validator/trunk/hibernate-validator/src/main/docbook/en-US/modules/defineconstraints.xml (rev 0)
+++ validator/trunk/hibernate-validator/src/main/docbook/en-US/modules/defineconstraints.xml 2009-02-05 17:43:34 UTC (rev 15907)
@@ -0,0 +1,494 @@
+<?xml version='1.0' encoding="UTF-8"?>
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat Middleware LLC.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ This program is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ ~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+
+<chapter id="validator-defineconstraints">
+ <title>Defining constraints</title>
+
+ <section id="validator-defineconstraints-definition" revision="1">
+ <title>What is a constraint?</title>
+
+ <para>A constraint is a rule that a given element (field, property or
+ bean) has to comply to. The rule semantic is expressed by an annotation. A
+ constraint usually has some attributes used to parameterize the
+ constraints limits. The constraint applies to the annotated
+ element.</para>
+ </section>
+
+ <section id="validator-defineconstraints-builtin" revision="2">
+ <title>Built in constraints</title>
+
+ <para>Hibernate Validator comes with some built-in constraints, which
+ covers most basic data checks. As we'll see later, you're not limited to
+ them, you can literally in a minute write your own constraints.</para>
+
+ <table>
+ <title>Built-in constraints</title>
+
+ <tgroup cols="4">
+ <colspec align="center" />
+
+ <thead>
+ <row>
+ <entry>Annotation</entry>
+
+ <entry>Apply on</entry>
+
+ <entry>Runtime checking</entry>
+
+ <entry>Hibernate Metadata impact</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>@Length(min=, max=)</entry>
+
+ <entry>property (String)</entry>
+
+ <entry>check if the string length match the range</entry>
+
+ <entry>Column length will be set to max</entry>
+ </row>
+
+ <row>
+ <entry>@Max(value=)</entry>
+
+ <entry>property (numeric or string representation of a
+ numeric)</entry>
+
+ <entry>check if the value is less than or equals to max</entry>
+
+ <entry>Add a check constraint on the column</entry>
+ </row>
+
+ <row>
+ <entry>@Min(value=)</entry>
+
+ <entry>property (numeric or string representation of a
+ numeric)</entry>
+
+ <entry>check if the value is more than or equals to min</entry>
+
+ <entry>Add a check constraint on the column</entry>
+ </row>
+
+ <row>
+ <entry>@NotNull</entry>
+
+ <entry>property</entry>
+
+ <entry>check if the value is not null</entry>
+
+ <entry>Column(s) are not null</entry>
+ </row>
+
+ <row>
+ <entry>@NotEmpty</entry>
+
+ <entry>property</entry>
+
+ <entry>check if the string is not null nor empty. Check if the
+ connection is not null nor empty</entry>
+
+ <entry>Column(s) are not null (for String)</entry>
+ </row>
+
+ <row>
+ <entry>@Past</entry>
+
+ <entry>property (date or calendar)</entry>
+
+ <entry>check if the date is in the past</entry>
+
+ <entry>Add a check constraint on the column</entry>
+ </row>
+
+ <row>
+ <entry>@Future</entry>
+
+ <entry>property (date or calendar)</entry>
+
+ <entry>check if the date is in the future</entry>
+
+ <entry>none</entry>
+ </row>
+
+ <row>
+ <entry>@Pattern(regex="regexp", flag=) or @Patterns(
+ {@Pattern(...)} )</entry>
+
+ <entry>property (string)</entry>
+
+ <entry>check if the property match the regular expression given a
+ match flag (see <classname>java.util.regex.Pattern </classname>
+ )</entry>
+
+ <entry>none</entry>
+ </row>
+
+ <row>
+ <entry>@Range(min=, max=)</entry>
+
+ <entry>property (numeric or string representation of a
+ numeric)</entry>
+
+ <entry>check if the value is between min and max
+ (included)</entry>
+
+ <entry>Add a check constraint on the column</entry>
+ </row>
+
+ <row>
+ <entry>@Size(min=, max=)</entry>
+
+ <entry>property (array, collection, map)</entry>
+
+ <entry>check if the element size is between min and max
+ (included)</entry>
+
+ <entry>none</entry>
+ </row>
+
+ <row>
+ <entry>@AssertFalse</entry>
+
+ <entry>property</entry>
+
+ <entry>check that the method evaluates to false (useful for
+ constraints expressed in code rather than annotations)</entry>
+
+ <entry>none</entry>
+ </row>
+
+ <row>
+ <entry>@AssertTrue</entry>
+
+ <entry>property</entry>
+
+ <entry>check that the method evaluates to true (useful for
+ constraints expressed in code rather than annotations)</entry>
+
+ <entry>none</entry>
+ </row>
+
+ <row>
+ <entry>@Valid</entry>
+
+ <entry>property (object)</entry>
+
+ <entry>perform validation recursively on the associated object. If
+ the object is a Collection or an array, the elements are validated
+ recursively. If the object is a Map, the value elements are
+ validated recursively.</entry>
+
+ <entry>none</entry>
+ </row>
+
+ <row>
+ <entry>@Email</entry>
+
+ <entry>property (String)</entry>
+
+ <entry>check whether the string is conform to the email address
+ specification</entry>
+
+ <entry>none</entry>
+ </row>
+
+ <row>
+ <entry>@CreditCardNumber</entry>
+
+ <entry>property (String)</entry>
+
+ <entry>check whether the string is a well formated credit card
+ number (derivative of the Luhn algorithm)</entry>
+
+ <entry>none</entry>
+ </row>
+
+ <row>
+ <entry>@Digits</entry>
+
+ <entry>property (numeric or string representation of a
+ numeric)</entry>
+
+ <entry>check whether the property is a number having up to
+ <literal>integerDigits</literal> integer digits and
+ <literal>fractionalDigits</literal> fractonal digits</entry>
+
+ <entry>define column precision and scale</entry>
+ </row>
+
+ <row>
+ <entry>@EAN</entry>
+
+ <entry>property (string)</entry>
+
+ <entry>check whether the string is a properly formated EAN or
+ UPC-A code</entry>
+
+ <entry>none</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section id="validator-defineconstraints-error" xreflabel="Error messages">
+ <title>Error messages</title>
+
+ <para>Hibernate Validator comes with a default set of error messages
+ translated in about ten languages (if yours is not part of it, please sent
+ us a patch). You can override those messages by creating a
+ <filename>ValidatorMessages.properties</filename> or (
+ <filename>ValidatorMessages_loc.properties</filename> ) and override the
+ needed keys. You can even add your own additional set of messages while
+ writing your validator annotations. If Hibernate Validator cannot resolve
+ a key from your resourceBundle nor from ValidatorMessage, it falls back to
+ the default built-in values.</para>
+
+ <para>Alternatively you can provide a
+ <classname>ResourceBundle</classname> while checking programmatically the
+ validation rules on a bean or if you want a completly different
+ interpolation mechanism, you can provide an implementation of
+ <literal>org.hibernate.validator.MessageInterpolator</literal> (check the
+ JavaDoc for more informations).</para>
+ </section>
+
+ <section id="validator-defineconstraints-own" revision="1">
+ <title>Writing your own constraints</title>
+
+ <para>Extending the set of built-in constraints is extremely easy. Any
+ constraint consists of two pieces: the constraint
+ <emphasis>descriptor</emphasis> (the annotation) and the constraint
+ <emphasis>validator</emphasis> (the implementation class). Here is a
+ simple user-defined descriptor:</para>
+
+ <programlisting>@ValidatorClass(CapitalizedValidator.class)
+ at Target(METHOD)
+ at Retention(RUNTIME)
+ at Documented
+public @interface Capitalized {
+ CapitalizeType type() default Capitalize.FIRST;
+ String message() default "has incorrect capitalization"
+} </programlisting>
+
+ <para><literal>type</literal> is a parameter describing how the property
+ should to be capitalized. This is a user parameter fully dependant on the
+ annotation business.</para>
+
+ <para><literal>message</literal> is the default string used to describe
+ the constraint violation and is mandatory. You can hard code the string or
+ you can externalize part/all of it through the Java ResourceBundle
+ mechanism. Parameters values are going to be injected inside the message
+ when the <literal>{parameter}</literal> string is found (in our example
+ <literal>Capitalization is not {type}</literal> would generate
+ <literal>Capitalization is not FIRST</literal> ), externalizing the whole
+ string in <filename>ValidatorMessages.properties</filename> is considered
+ good practice. See <xref linkend="validator-defineconstraints-error" />
+ .</para>
+
+ <programlisting>@ValidatorClass(CapitalizedValidator.class)
+ at Target(METHOD)
+ at Retention(RUNTIME)
+ at Documented
+public @interface Capitalized {
+ CapitalizeType type() default Capitalize.FIRST;
+ String message() default "{validator.capitalized}";
+}
+
+
+#in ValidatorMessages.properties
+validator.capitalized = <literal>Capitalization is not {type}</literal>
+ </programlisting>
+
+ <para>As you can see the {} notation is recursive.</para>
+
+ <para>To link a descriptor to its validator implementation, we use the
+ <literal>@ValidatorClass</literal> meta-annotation. The validator class
+ parameter must name a class which implements
+ <literal>Validator<ConstraintAnnotation></literal> .</para>
+
+ <para>We now have to implement the validator (ie. the rule checking
+ implementation). A validation implementation can check the value of the a
+ property (by implementing <literal>PropertyConstraint</literal> ) and/or
+ can modify the hibernate mapping metadata to express the constraint at the
+ database level (by implementing
+ <literal>PersistentClassConstraint</literal> )</para>
+
+ <programlisting>public class CapitalizedValidator
+ implements Validator<Capitalized>, PropertyConstraint {
+ private CapitalizeType type;
+
+ //part of the Validator<Annotation> contract,
+ //allows to get and use the annotation values
+ public void initialize(Capitalized parameters) {
+ type = parameters.type();
+ }
+
+ //part of the property constraint contract
+ public boolean isValid(Object value) {
+ if (value==null) return true;
+ if ( !(value instanceof String) ) return false;
+ String string = (String) value;
+ if (type == CapitalizeType.ALL) {
+ return string.equals( string.toUpperCase() );
+ }
+ else {
+ String first = string.substring(0,1);
+ return first.equals( first.toUpperCase();
+ }
+ }
+} </programlisting>
+
+ <para>The <literal>isValid()</literal> method should return false if the
+ constraint has been violated. For more examples, refer to the built-in
+ validator implementations.</para>
+
+ <para>We only have seen property level validation, but you can write a
+ Bean level validation annotation. Instead of receiving the return instance
+ of a property, the bean itself will be passed to the validator. To
+ activate the validation checking, just annotated the bean itself instead.
+ A small sample can be found in the unit test suite.</para>
+
+ <para>If your constraint can be applied multiple times (with different
+ parameters) on the same property or type, you can use the following
+ annotation form:</para>
+
+ <programlisting>@Target(METHOD)
+ at Retention(RUNTIME)
+ at Documented
+<emphasis role="bold">public @interface Patterns {</emphasis>
+ Pattern[] value();
+}
+
+ at Target(METHOD)
+ at Retention(RUNTIME)
+ at Documented
+ at ValidatorClass(PatternValidator.class)
+public @interface Pattern {
+ String regexp();
+}</programlisting>
+
+ <para>Basically an annotation containing the value attribute as an array
+ of validator annotations.</para>
+ </section>
+
+ <section>
+ <title>Annotating your domain model</title>
+
+ <para>Since you are already familiar with annotations now, the syntax
+ should be very familiar</para>
+
+ <programlisting>public class Address {
+ private String line1;
+ private String line2;
+ private String zip;
+ private String state;
+ private String country;
+ private long id;
+
+ // a not null string of 20 characters maximum
+ @Length(max=20)
+ @NotNull
+ public String getCountry() {
+ return country;
+ }
+
+ // a non null string
+ @NotNull
+ public String getLine1() {
+ return line1;
+ }
+
+ //no constraint
+ public String getLine2() {
+ return line2;
+ }
+
+ // a not null string of 3 characters maximum
+ @Length(max=3) @NotNull
+ public String getState() {
+ return state;
+ }
+
+ // a not null numeric string of 5 characters maximum
+ // if the string is longer, the message will
+ //be searched in the resource bundle at key 'long'
+ @Length(max=5, message="{long}")
+ @Pattern(regex="[0-9]+")
+ @NotNull
+ public String getZip() {
+ return zip;
+ }
+
+ // should always be true
+ @AssertTrue
+ public boolean isValid() {
+ return true;
+ }
+
+ // a numeric between 1 and 2000
+ @Id @Min(1)
+ @Range(max=2000)
+ public long getId() {
+ return id;
+ }
+} </programlisting>
+
+ <para>While the example only shows public property validation, you can
+ also annotate fields of any kind of visibility</para>
+
+ <programlisting>@MyBeanConstraint(max=45
+public class Dog {
+ @AssertTrue private boolean isMale;
+ @NotNull protected String getName() { ... };
+ ...
+} </programlisting>
+
+ <para>You can also annotate interfaces. Hibernate Validator will check all
+ superclasses and interfaces extended or implemented by a given bean to
+ read the appropriate validator annotations.</para>
+
+ <programlisting>public interface Named {
+ @NotNull String getName();
+ ...
+}
+
+public class Dog implements Named {
+
+ @AssertTrue private boolean isMale;
+
+ public String getName() { ... };
+
+}
+ </programlisting>
+
+ <para>The name property will be checked for nullity when the Dog bean is
+ validated.</para>
+ </section>
+</chapter>
\ No newline at end of file
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolator.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolator.java 2009-02-05 17:41:58 UTC (rev 15906)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ResourceBundleMessageInterpolator.java 2009-02-05 17:43:34 UTC (rev 15907)
@@ -30,11 +30,11 @@
import org.hibernate.validation.util.LoggerFactory;
-
/**
* Resource bundle backed message interpolator.
*
* @author Emmanuel Bernard
+ * @author Hardy Ferentschik
*/
public class ResourceBundleMessageInterpolator implements MessageInterpolator {
private static final String DEFAULT_VALIDATION_MESSAGES = "org.hibernate.validation.ValidationMessages";
@@ -63,6 +63,16 @@
defaultResourceBundle = ResourceBundle.getBundle( DEFAULT_VALIDATION_MESSAGES );
}
+ public String interpolate(String message, ConstraintDescriptor constraintDescriptor, Object value) {
+ // probably no need for caching, but it could be done by parameters since the map
+ // is immutable and uniquely built per Validation definition, the comparaison has to be based on == and not equals though
+ return replace( message, constraintDescriptor.getParameters() );
+ }
+
+ public String interpolate(String message, ConstraintDescriptor constraintDescriptor, Object value, Locale locale) {
+ throw new UnsupportedOperationException( "Interpolation for Locale. Has to be done." );
+ }
+
/**
* Search current thread classloader for the resource bundle. If not found, search validator (this) classloader.
*
@@ -101,17 +111,6 @@
return rb;
}
- public String interpolate(String message, ConstraintDescriptor constraintDescriptor, Object value) {
- //probably no need for caching, but it could be done by parameters since the map
- //is immutable and uniquely built per Validation definition, the comparaison has to be based on == and not equals though
- return replace( message, constraintDescriptor.getParameters() );
- }
-
- public String interpolate(String message, ConstraintDescriptor constraintDescriptor, Object value, Locale locale) {
- throw new UnsupportedOperationException( "Interpolation for Locale. Has to be done." );
- }
-
-
private String replace(String message, Map<String, Object> parameters) {
Matcher matcher = messagePattern.matcher( message );
StringBuffer sb = new StringBuffer();
@@ -122,7 +121,6 @@
return sb.toString();
}
-
private String resolveParameter(String token, Map<String, Object> parameters) {
Object variable = parameters.get( token );
if ( variable != null ) {
Added: validator/trunk/hibernate-validator/src/test/resources/org/hibernate/validation/ValidationMessages_de.properties
===================================================================
--- validator/trunk/hibernate-validator/src/test/resources/org/hibernate/validation/ValidationMessages_de.properties (rev 0)
+++ validator/trunk/hibernate-validator/src/test/resources/org/hibernate/validation/ValidationMessages_de.properties 2009-02-05 17:43:34 UTC (rev 15907)
@@ -0,0 +1,11 @@
+# $Id: ValidationMessages.properties 15846 2009-02-02 11:56:15Z hardy.ferentschik $
+validator.notNull=may not be null
+validator.size=size must be between {min} and {max}
+validator.length=length must be between {min} and {max}
+validator.notEmpty=may not be empty
+validator.pattern=must match "{regex}"
+validator.min=must be greater than {value}
+validator.max=must be less than {value}
+validator.null=must be null
+validator.past=must be in the past
+validator.future=must be in the future
More information about the hibernate-commits
mailing list