<?xml version="1.0" encoding="UTF-8"?>
<!--
	~ JBoss, Home of Professional Open Source
	~ Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
	~ by the @authors tag. See the copyright.txt in the distribution for a
	~ full listing of individual contributors.
	~
	~ Licensed under the Apache License, Version 2.0 (the "License");
	~ you may not use this file except in compliance with the License.
	~ You may obtain a copy of the License at
	~ http://www.apache.org/licenses/LICENSE-2.0
	~ Unless required by applicable law or agreed to in writing, software
	~ distributed under the License is distributed on an "AS IS" BASIS,
	~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	~ See the License for the specific language governing permissions and
	~ limitations under the License.
-->
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "../hv.ent">
%BOOK_ENTITIES;
]>
<chapter id="validator-specifics">
  <title>Hibernate Validator Specifics</title>

  <para>In this chapter you will learn how to make use of several features
  provided by Hibernate Validator in addition to the functionality defined by
  the Bean Validation specification. This includes the fail fast mode, the API
  for programmatic constraint configuration and the boolean composition of
  constraints.</para>

  <note>
    <para>Using the features described in the following sections may result in
    application code which is not portable between Bean Validation
    providers.</para>
  </note>

  <section>
    <title>Public API</title>

    <para>Let's start, however, with a look at the public API of Hibernate
    Validator. <xref linkend="validator-public-api"/> lists all packages
    belonging to this API and describes their purpose. Note that when a
    package is part of the public this is not necessarily true for its
    sub-packages.</para>

    <table id="validator-public-api">
      <title>Hibernate Validator public API</title>

      <tgroup cols="2">
        <thead>
          <row>
            <entry>Packages</entry>

            <entry>Description</entry>
          </row>
        </thead>

        <tbody valign="top">
          <row>
            <entry><package>org.hibernate.validator</package></entry>

            <entry>Classes used by the Bean Validation bootstrap mechanism
            (eg. validation provider, configuration class); For more details
            see <xref linkend="chapter-bootstrapping"/>.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.cfg</package>,
            <package>org.hibernate.validator.cfg.context</package>,
            <package>org.hibernate.validator.cfg.defs</package></entry>

            <entry>Hibernate Validator's fluent API for constraint
            declaration; In <package>org.hibernate.validator.cfg</package> you
            will find the <classname>ConstraintMapping</classname> interface
            and in <package>org.hibernate.validator.cfg.defs</package> all
            constraint definitions. Refer to <xref
            linkend="section-programmatic-api"/> for the details.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.constraints</package>,
            <package>org.hibernate.validator.constraints.br</package></entry>

            <entry>Some useful custom constraints provided by Hibernate
            Validator in addition to the built-in constraints defined by the
            Bean Validation specification; The constraints are described in
            detail in <xref
            linkend="validator-defineconstraints-hv-constraints"/>.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.constraintvalidation</package></entry>

            <entry>Extended constraint validator context which allows to set
            custom attributes for message interpolation. <xref
            linkend="section-hibernateconstraintvalidatorcontext"/> describes
            how to make use of that feature.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.group</package>,
            <package>org.hibernate.validator.spi.group</package></entry>

            <entry>The group sequence provider feature which allows you to
            define dynamic default group sequences in function of the
            validated object state; The specifics can be found in <xref
            linkend="section-default-group-class"/>.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.messageinterpolation</package>,
            <package>org.hibernate.validator.resourceloading</package>,
            <package>org.hibernate.validator.spi.resourceloading</package></entry>

            <entry>Classes related to constraint message interpolation; The
            first package contains Hibernate Validator's default message
            interpolator,
            <classname>ResourceBundleMessageInterpolator</classname>. The
            latter two packages provide the<classname>
            ResourceBundleLocator</classname> SPI for the loading of resource
            bundles (see <xref linkend="section-resource-bundle-locator"/>)
            and its default implementation.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.parameternameprovider</package></entry>

            <entry>A <classname>ParameterNameProvider</classname> based on the
            ParaNamer library, see <xref
            linkend="section-paranamer-parameternameprovider"/>.</entry>
          </row>

          <row>
            <entry><package>org.hibernate.validator.valuehandling</package>,
            <package>org.hibernate.validator.spi.valuehandling</package></entry>

            <entry>Classes related to the processing of values prior to their
            validation, see <xref
            linkend="section-value-handling"/>.</entry>
          </row>
        </tbody>
      </tgroup>
    </table>

    <note>
      <para>The public packages of Hibernate Validator fall into two
      categories: while the actual API parts are intended to be
      <emphasis>invoked</emphasis> or <emphasis>used</emphasis> by clients
      (e.g. the API for programmatic constraint declaration or the custom
      constraints), the SPI (service provider interface) packages contain
      interfaces which are intended to be <emphasis>implemented</emphasis> by
      clients (e.g. <classname>ResourceBundleLocator</classname>).</para>
    </note>

    <para>Any packages not listed in that table are internal packages of
    Hibernate Validator and are not intended to be accessed by clients. The
    contents of these internal packages can change from release to release
    without notice, thus possibly breaking any client code relying on
    it.</para>
  </section>

  <section id="section-fail-fast">
    <title>Fail fast mode</title>

    <para>Using the fail fast mode, Hibernate Validator allows to return from
    the current validation as soon as the first constraint violation occurs.
    This can be useful for the validation of large object graphs where you are
    only interested in a quick check whether there is any constraint violation
    at all.</para>

    <para><xref linkend="example-using-fail-fast"/> shows how to bootstrap and
    use a fail fast enabled validator.</para>

    <example floatstyle="" id="example-using-fail-fast">
      <title>Using the fail fast validation mode</title>

      <programlisting language="JAVA" role="JAVA">package org.hibernate.validator.referenceguide.chapter11.failfast;

public class Car {

	@NotNull
	private String manufacturer;

	@AssertTrue
	private boolean isRegistered;

	public Car(String manufacturer, boolean isRegistered) {
		this.manufacturer = manufacturer;
		this.isRegistered = isRegistered;
	}

	//getters and setters...
}</programlisting>

      <programlisting language="JAVA" role="JAVA">Validator validator = Validation.byProvider( HibernateValidator.class )
		.configure()
		.failFast( true )
		.buildValidatorFactory()
		.getValidator();

Car car = new Car( null, false );

Set&lt;ConstraintViolation&lt;Car&gt;&gt; constraintViolations = validator.validate( car );

assertEquals( 1, constraintViolations.size() );</programlisting>
    </example>

    <para>Here the validated object actually fails to satisfy both the
    constraints declared on the <classname>Car</classname> class, yet the
    validation call yields only one <classname>ConstraintViolation</classname>
    since the fail fast mode is enabled.</para>

    <note>
      <para>There is no guarantee in which order the constraints are
      evaluated, i.e. it is not deterministic whether the returned violation
      originates from the <classname>@NotNull</classname> or the
      <classname>@AssertTrue</classname> constraint. If required, a
      deterministic evaluation order can be enforced using group sequences as
      described in <xref linkend="section-defining-group-sequences"/>.</para>
    </note>

    <para>Refer to <xref linkend="section-provider-specific-settings"/> to
    learn about the different ways of enabling the fail fast mode when
    bootstrapping a validator.</para>
  </section>

  <section id="section-programmatic-api">
    <title>Programmatic constraint declaration</title>

    <para>As per the Bean Validation specification, you can declare
    constraints using Java annotations and XML based constraint
    mappings.</para>

    <para>In addition, Hibernate Validator provides a fluent API which allows
    for the programmatic configuration of constraints. Use cases include the
    dynamic addition of constraints at runtime depending on some application
    state or tests where you need entities with different constraints in
    different scenarios but don't want to implement actual Java classes for
    each test case.</para>

    <para>By default, constraints added via the fluent API are additive to
    constraints configured via the standard configuration capabilities. But it
    is also possible to ignore annotation and XML configured constraints where
    required.</para>

    <para>The API is centered around the
    <classname>ConstraintMapping</classname> interface. You obtain a new
    mapping via
    <classname>HibernateValidatorConfiguration#createConstraintMapping()</classname>
    which you then can configure in a fluent manner as shown in <xref lang=""
    linkend="example-constraint-mapping"/>.</para>

    <example id="example-constraint-mapping">
      <title>Programmatic constraint declaration</title>

      <programlisting language="JAVA" role="JAVA">HibernateValidatorConfiguration configuration = Validation
		.byProvider( HibernateValidator.class )
		.configure();

ConstraintMapping constraintMapping = configuration.createConstraintMapping();

constraintMapping
	.type( Car.class )
		.property( "manufacturer", FIELD )
			.constraint( new NotNullDef() )
		.property( "licensePlate", FIELD )
			.ignoreAnnotations()
			.constraint( new NotNullDef() )
			.constraint( new SizeDef().min( 2 ).max( 14 ) )
	.type( RentalCar.class )
		.property( "rentalStation", METHOD )
			.constraint( new NotNullDef() );

Validator validator = configuration.addMapping( constraintMapping )
		.buildValidatorFactory()
		.getValidator();     </programlisting>
    </example>

    <para>Constraints can be configured on multiple classes and properties
    using method chaining. The constraint definition classes
    <classname>NotNullDef</classname> and <classname>SizeDef</classname> are
    helper classes which allow to configure constraint parameters in a
    type-safe fashion. Definition classes exist for all built-in constraints
    in the <classname>org.hibernate.validator.cfg.defs</classname> package. By
    calling <methodname>ignoreAnnotations()</methodname> any constraints
    configured via annotations or XML are ignored for the given
    element.</para>

    <note>
      <para>Each element (type, property, method etc.) may only be configured
      once within all the constraint mappings used to set up one validator
      factory. Otherwise a <classname>ValidationException</classname> is
      raised.</para>
    </note>

    <note>
      <para>It is not supported to add constraints to non-overridden supertype
      properties and methods by configuring a subtype. Instead you need to
      configure the supertype in this case.</para>
    </note>

    <para>Having configured the mapping, you must add it back to the
    configuration object from which you then can obtain a validator
    factory.</para>

    <para>For custom constraints you can either create your own definition
    classes extending <classname>ConstraintDef</classname> or you can use
    <classname>GenericConstraintDef</classname> as seen in <xref
    linkend="example-generic-constraint-mapping"/>.</para>

    <example id="example-generic-constraint-mapping">
      <title>Programmatic declaration of a custom constraint</title>

      <programlisting language="JAVA" role="JAVA">ConstraintMapping constraintMapping = configuration.createConstraintMapping();

constraintMapping
	.type( Car.class )
		.property( "licensePlate", FIELD )
			.constraint( new GenericConstraintDef&lt;CheckCase&gt;( CheckCase.class )
				.param( "value", CaseMode.UPPER )
			); </programlisting>
    </example>

    <para>By invoking <methodname>valid()</methodname> you can mark a member
    for cascaded validation which is equivalent to annotating it with
    <classname>@Valid</classname>. Configure any group conversions to be
    applied during cascaded validation using the
    <methodname>convertGroup()</methodname> method (equivalent to
    <classname>@ConvertGroup</classname>). An example can be seen in <xref
    lang="" linkend="example-cascading-constraints"/>.</para>

    <example id="example-cascading-constraints">
      <title>Marking a property for cascaded validation</title>

      <programlisting language="JAVA" role="JAVA">ConstraintMapping constraintMapping = configuration.createConstraintMapping();

constraintMapping
	.type( Car.class )
		.property( "driver", FIELD )
			.constraint( new NotNullDef() )
			.valid()
			.convertGroup( Default.class ).to( PersonDefault.class )
	.type( Person.class )
		.property( "name", FIELD )
			.constraint( new NotNullDef().groups( PersonDefault.class ) );</programlisting>
    </example>

    <para>You can not only configure bean constraints using the fluent API but
    also method and constructor constraints. As shown in <xref lang=""
    linkend="example-method-constraint-mapping"/> constructors are identified
    by their parameter types and methods by their name and parameter types.
    Having selected a method or constructor, you can mark its parameters
    and/or return value for cascaded validation and add constraints as well as
    cross-parameter constraints.</para>

    <example id="example-method-constraint-mapping">
      <title>Programmatic declaration of method and constructor
      constraints</title>

      <programlisting language="JAVA" role="JAVA">ConstraintMapping constraintMapping = configuration.createConstraintMapping();

constraintMapping
	.type( Car.class )
		.constructor( String.class )
			.parameter( 0 )
				.constraint( new SizeDef().min( 3 ).max( 50 ) )
			.returnValue()
				.valid()
		.method( "drive", int.class )
			.parameter( 0 )
				.constraint( new MaxDef().value ( 75 ) )
		.method( "load", List.class, List.class )
			.crossParameter()
				.constraint( new GenericConstraintDef&lt;LuggageCountMatchesPassengerCount&gt;(
						LuggageCountMatchesPassengerCount.class ).param(
							"piecesOfLuggagePerPassenger", 2
						)
				)
		.method( "getDriver" )
			.returnValue()
				.constraint( new NotNullDef() )
				.valid();</programlisting>
    </example>

    <para>Last but not least you can configure the default group sequence or
    the default group sequence provider of a type as shown in the following
    example.</para>

    <example id="example-sequences">
      <title>Configuration of default group sequence and default group
      sequence provider</title>

      <programlisting language="JAVA" role="JAVA">ConstraintMapping constraintMapping = configuration.createConstraintMapping();

constraintMapping
	.type( Car.class )
		.defaultGroupSequence( Car.class, CarChecks.class )
	.type( RentalCar.class )
		.defaultGroupSequenceProviderClass( RentalCarGroupSequenceProvider.class );</programlisting>
    </example>
  </section>

  <section id="section-boolean-constraint-composition">
    <title>Boolean composition of constraints</title>

    <para>Bean Validation specifies that the constraints of a composed
    constraint (see <xref linkend="section-constraint-composition"/>) are all
    combined via a logical <emphasis>AND</emphasis>. This means all of the
    composing constraints need to return <constant>true</constant> in order
    for an overall successful validation.</para>

    <para>Hibernate Validator offers an extension to this and allows you to
    compose constraints via a logical <emphasis>OR</emphasis> or
    <emphasis>NOT</emphasis>. To do so you have to use the
    <classname>ConstraintComposition</classname> annotation and the enum
    <classname>CompositionType</classname> with its values
    <emphasis>AND</emphasis>, <emphasis>OR</emphasis> and
    <emphasis>ALL_FALSE</emphasis>.</para>

    <para><xref linkend="example-boolean-constraint-composition"/> shows how
    to build a composed constraint <classname>@PatternOrSize</classname> where
    only one of the composing constraints needs to be valid in order to pass
    the validation. Either the validated string is all lower-cased or it is
    between two and three characters long.</para>

    <example id="example-boolean-constraint-composition">
      <title>OR composition of constraints</title>

      <programlisting language="JAVA" role="JAVA">package org.hibernate.validator.referenceguide.chapter11.booleancomposition;

@ConstraintComposition(OR)
@Pattern(regexp = "[a-z]")
@Size(min = 2, max = 3)
@ReportAsSingleViolation
@Target({ METHOD, FIELD })
@Retention(RUNTIME)
@Constraint(validatedBy = { })
public @interface PatternOrSize {
	String message() default "{org.hibernate.validator.referenceguide.chapter11." +
			"booleancomposition.PatternOrSize.message}";

	Class&lt;?&gt;[] groups() default { };

	Class&lt;? extends Payload&gt;[] payload() default { };
}</programlisting>
    </example>

    <tip>
      <para>Using <emphasis>ALL_FALSE</emphasis> as composition type
      implicitly enforces that only a single violation will get reported in
      case validation of the constraint composition fails.</para>
    </tip>
  </section>

  <section>
    <title><classname>ResourceBundleLocator</classname></title>

    <para>As described in <xref
    linkend="section-custom-message-interpolation"/>, Bean Validation allows
    to plug in custom message interpolator implementations.</para>

    <para>With <classname>ResourceBundleLocator</classname>, Hibernate
    Validator provides an additional SPI which allows to retrieve error
    messages from other resource bundles than
    <filename>ValidationMessages</filename> while still using the actual
    interpolation algorithm as defined by the specification. Refer to <xref
    linkend="section-resource-bundle-locator"/> to learn how to make use of
    that SPI.</para>
  </section>

  <section>
    <title>Custom contexts</title>

    <para>The Bean Validation specification offers at several points in its
    API the possibility to unwrap a given interface to a implementor specific
    subtype. In the case of constraint violation creation in
    <classname>ConstraintValidator</classname> implementations as well as
    message interpolation in <classname>Messageinterpolator</classname>
    instances, there exist <methodname>unwrap()</methodname> methods for the
    provided context instances -
    <classname>ConstraintValidatorContext</classname> respectively
    <classname>MessageInterpolatorContext</classname>. Hibernate Validator
    provides custom extensions for both of these interfaces.</para>

    <section id="section-hibernateconstraintvalidatorcontext">
      <title><classname>HibernateConstraintValidatorContext</classname></title>

      <para
      id="section-custom-constraint-validator-context"><classname>HibernateConstraintValidatorContext</classname>
      is a subtype of <classname>ConstraintValidatorContext</classname> which
      allows you to set arbitrary parameters for interpolation via the
      Expression Language message interpolation facility (see <xref
      linkend="section-interpolation-with-message-expressions"/>). For example
      the default error message for the <classname>@Future</classname>
      constraint is "must be in the future". What if you would like to include
      the current date to make the message more explicit? <xref
      linkend="example-custom-message-parameter"/> shows how this could be
      achieved.</para>

      <example id="example-custom-message-parameter">
        <title>Custom <classname>@Future</classname> validator with message
        parameters</title>

        <programlisting language="JAVA" role="JAVA">public class MyFutureValidator implements ConstraintValidator&lt;Future, Date&gt; {

	public void initialize(Future constraintAnnotation) {
	}

	public boolean isValid(Date value, ConstraintValidatorContext context) {
		Date now = GregorianCalendar.getInstance().getTime();

		if ( value.before( now ) ) {
			HibernateConstraintValidatorContext hibernateContext =
					context.unwrap( HibernateConstraintValidatorContext.class );

			hibernateContext.disableDefaultConstraintViolation();
			hibernateContext.addExpressionVariable( "now", now )
					.buildConstraintViolationWithTemplate( "Must be after ${now}" )
					.addConstraintViolation();

			return false;
		}

		return true;
	}
}</programlisting>
      </example>

      <note>
        <para>Note that the parameters specified via
        <methodname>addExpressionVariable(String, Object)</methodname> are
        global and apply for all constraint violations created by this
        <methodname>isValid()</methodname> invocation. This includes the
        default constraint violation, but also all violations created by the
        <classname>ConstraintViolationBuilder</classname>. You can, however,
        update the parameters between invocations of
        <methodname>ConstraintViolationBuilder#addConstraintViolation()</methodname>.</para>
      </note>

      <warning>
        <para>This functionality is currently experimental and might change in
        future versions.</para>
      </warning>
    </section>

    <section>
      <title><classname>HibernateMessageInterpolatorContext</classname></title>

      <para>Hibernate Validator also offers a custom extension of
      <classname>MessageInterpolatorContext</classname>, namely
      <classname>HibernateMessageInterpolatorContext</classname> (see <xref
      linkend="example-custom-message-interpolator-context"/>). This subtype
      was introduced to allow a better integration of Hibernate Validator into
      the Glassfish. The root bean type was in this case needed to determine
      the right classloader for the message resource bundle. If you have any
      other usecases, let us know.</para>

      <example id="example-custom-message-interpolator-context">
        <title><classname>HibernateMessageInterpolatorContext</classname></title>

        <programlisting language="JAVA" role="JAVA">public interface HibernateMessageInterpolatorContext extends MessageInterpolator.Context {

	/**
	 * Returns the currently validated root bean type.
	 *
	 * @return The currently validated root bean type.
	 */
	Class&lt;?&gt; getRootBeanType();
}</programlisting>
      </example>
    </section>
  </section>

  <section id="section-paranamer-parameternameprovider">
    <title>ParaNamer based
    <classname>ParameterNameProvider</classname></title>

    <para>Hibernate Validator comes with a
    <classname>ParameterNameProvider</classname> implementation which
    leverages the <ulink
    url="http://paranamer.codehaus.org/">ParaNamer</ulink> library.</para>

    <para>This library provides several ways for obtaining parameter names at
    runtime, e.g. based on debug symbols created by the Java compiler,
    constants with the parameter names woven into the bytecode in a
    post-compile step or annotations such as the <classname>@Named</classname>
    annotation from JSR 330.</para>

    <para>In order to use
    <classname>ParanamerParameterNameProvider</classname>, either pass an
    instance when bootstrapping a validator as shown in <xref
    linkend="example-using-custom-parameter-name-provider"/> or specify
    <property>org.hibernate.validator.parameternameprovider.ParanamerParameterNameProvider</property>
    as value for the <property>&lt;parameter-name-provider&gt;</property>
    element in the <filename>META-INF/validation.xml</filename> file.</para>

    <tip>
      <para>When using this parameter name provider, you need to add the
      ParaNamer library to your classpath. It is available in the Maven
      Central repository with the group id
      <literal>com.thoughtworks.paranamer</literal> and the artifact id
      <literal>paranamer</literal>.</para>
    </tip>

    <para>By default <classname>ParanamerParameterNameProvider</classname>
    retrieves parameter names from constants added to the byte code at build
    time (via <classname>DefaultParanamer</classname>) and debug symbols (via
    <classname>BytecodeReadingParanamer</classname>). Alternatively you can
    specify a <classname>Paranamer</classname> implementation of your choice
    when creating a <classname>ParanamerParameterNameProvider</classname>
    instance. </para>
  </section>

  <section id="section-value-handling">
    <title>Unwrapping values prior to validation</title>

    <para>Sometimes it is required to unwrap values prior to the validation.
    E.g. in <xref linkend="example-using-unwrapvalidatedvalue"/> property types
    as specified by <ulink url="http://docs.oracle.com/javafx/"> JavaFX</ulink>
    are used to define an element of some domain model.</para>

    <example id="example-using-unwrapvalidatedvalue">
      <title>Using<classname>@UnwrapValidatedValue</classname></title>

      <programlisting language="JAVA" role="JAVA">@Size(min = 3)
@UnwrapValidatedValue
private Property&lt;String&gt; name = new SimpleStringProperty( "Bob" );</programlisting>
    </example>

    <note>
      <para>The concept of value unwrapping is considered experimental at this
      time and may evolve into more general means of value handling in future
      releases. Please let us know about your use cases for such functionality.
      </para>
    </note>

    <para>In JavaFX, bean properties are typically not of simple data types
    like <classname>String</classname> or <classname>int</classname>, but are
    wrapped in <classname>Property</classname> types which allows to make them
    observable, use them for data binding etc. When applying a constraint such
    as <classname>@Size</classname> to an element of type
    <classname>Property&lt;String&gt;</classname> without further preparation,
    an exception would be raised, indicating that no suitable validator for
    that constraint and data type can be found. Thus the validated value must
    be unwrapped from the containing property object before looking up a
    validator and invoking it.</para>

    <para>To do so, put the <classname>@UnwrapValidatedValue</classname>
    annotation to the element in question. This will advice the validation
    engine to look for an unwrapper implementation which returns the data type
    to be used for constraint validator resolution and unwraps the validated
    value. Unwrapper types must extend the SPI class
    <classname>ValidatedValueUnwrapper</classname> as shown in
    <xref linkend="example-implementation-of-validatedvalueunwrapper"/>.</para>

    <example id="example-implementation-of-validatedvalueunwrapper">
      <title>Implementing the <classname>ValidatedValueUnwrapper</classname>
      interface</title>

      <programlisting language="JAVA" role="JAVA">public class PropertyValueUnwrapper extends ValidatedValueUnwrapper&lt;Property&lt;?&gt;&gt; {

	@Override
	public Object handleValidatedValue(Property&lt;?&gt; value) {
		//...
	}

	@Override
	public Type getValidatedValueType(Type valueType) {
		//...
	}
}</programlisting>
    </example>

    <para>Value unwrappers must be registered when obtaining a <classname>Validator</classname>
    instance as follows:</para>

    <example id="example-registering-validatedvalueunwrapper">
      <title>Registering a <classname>ValidatedValueUnwrapper</classname></title>

      <programlisting language="JAVA" role="JAVA">Validator validator = Validation.byProvider( HibernateValidator.class )
		.configure()
		.addValidatedValueHandler( new PropertyValueUnwrapper() )
		.buildValidatorFactory()
		.getValidator();</programlisting>
    </example>

    <para>Several unwrapper implementations can be registered when working
    with different kinds of wrapper types in one application. Note that it is
    not specified which of the unwrapper implementations is chosen when more
    than one implementation is suitable to unwrap a given element.</para>

    <para>Alternatively, the fully-qualified names of one ore more unwrapper
    implementations can be specified via the configuration property
    <property>hibernate.validator.validated_value_handlers</property> which
    can be useful when configuring the default validator factory using the
    descriptor <filename>META-INF/validation.xml</filename> (see <xref
    linkend="chapter-xml-configuration"/>).</para>

  </section>
</chapter>
