<?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="chapter-xml-configuration">
  <title>Configuring via XML</title>

  <para>So far we have used the default configuration source for Bean
  Validation, namely annotations. However, there also exist two kinds of XML
  descriptors allowing configuration via XML. The first descriptor describes
  general Bean Validation behaviour and is provided as
  <filename>META-INF/validation.xml</filename>. The second one describes
  constraint declarations and closely matches the constraint declaration
  approach via annotations. Let's have a look at these two document
  types.<note>
      <para>The XSD files are available via <ulink
      url="http://www.jboss.org/xml/ns/javax/validation/configuration/">http://www.jboss.org/xml/ns/javax/validation/configuration</ulink>
      and <ulink
      url="http://www.jboss.org/xml/ns/javax/validation/mapping">http://www.jboss.org/xml/ns/javax/validation/mapping</ulink>.</para>
    </note></para>

  <section id="section-configuration-validation-xml">
    <title>Configuring the validator factory in
    <filename>validation.xml</filename></title>

    <para>The key to enable XML configuration for Hibernate Validator is the
    file <filename>META-INF/validation.xml</filename>. If this file exists on
    the classpath its configuration will be applied when the
    <classname>ValidatorFactory</classname> gets created. <xref
    linkend="image-validation-configuration"/> shows a model view of the XML
    schema to which <filename>validation.xml</filename> has to adhere.<example
        id="image-validation-configuration">
        <title>validation-configuration-1.1.xsd</title>

        <mediaobject>
          <imageobject role="fo">
            <imagedata align="center"
                       fileref="validation-configuration-1.1.png" format="PNG"
                       width="80%"/>
          </imageobject>

          <imageobject role="html">
            <imagedata depth="" fileref="validation-configuration-1.1.png"
                       format="PNG" scalefit="1"/>
          </imageobject>
        </mediaobject>
      </example></para>

    <para><xref linkend="example-validation-xml"/> shows the several
    configuration options of <filename>validation.xml</filename>. All settings
    are optional and the same configuration options are also available
    programmatically through
    <classname>javax.validation.Configuration</classname>. In fact the XML
    configuration will be overridden by values explicitly specified via the
    programmatic API. It is even possible to ignore the XML configuration
    completely via
    <methodname>Configuration#ignoreXmlConfiguration()</methodname>. See also
    <xref linkend="section-configuring-validator-factory"/>.</para>

    <example id="example-validation-xml">
      <title>validation.xml</title>

      <programlisting language="XML" role="XML">&lt;validation-config
    xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration"&gt;

    &lt;default-provider&gt;com.acme.ValidationProvider&lt;/default-provider&gt;

    &lt;message-interpolator&gt;com.acme.MessageInterpolator&lt;/message-interpolator&gt;
    &lt;traversable-resolver&gt;com.acme.TraversableResolver&lt;/traversable-resolver&gt;
    &lt;constraint-validator-factory&gt;
        com.acme.ConstraintValidatorFactory
    &lt;/constraint-validator-factory&gt;
    &lt;parameter-name-provider&gt;com.acme.ParameterNameProvider&lt;/parameter-name-provider&gt;

    &lt;executable-validation enabled="true"&gt;
        &lt;default-validated-executable-types&gt;
            &lt;executable-type&gt;CONSTRUCTORS&lt;/executable-type&gt;
            &lt;executable-type&gt;NON_GETTER_METHODS&lt;/executable-type&gt;
            &lt;executable-type&gt;GETTER_METHODS&lt;/executable-type&gt;
        &lt;/default-validated-executable-types&gt;
    &lt;/executable-validation&gt;

    &lt;constraint-mapping&gt;META-INF/validation/constraints-car.xml&lt;/constraint-mapping&gt;

    &lt;property name="hibernate.validator.fail_fast"&gt;false&lt;/property&gt;
&lt;/validation-config&gt;</programlisting>
    </example>

    <warning>
      <para>There must only be one file named
      <filename>META-INF/validation.xml</filename> on the classpath. If more
      than one is found an exception is thrown.</para>
    </warning>

    <para>The node <property>default-provider</property> allows to choose the
    Bean Validation provider. This is useful if there is more than one
    provider on the classpath. <property>message-interpolator</property>,
    <property>traversable-resolver</property>,
    <property>constraint-validator-factory</property> and
    <property>parameter-name-provider</property> allow to customize the used
    implementations for the interfaces
    <classname>MessageInterpolator</classname>,
    <classname>TraversableResolver</classname>,
    <classname>ConstraintValidatorFactory</classname> and
    <classname>ParameterNameProvider</classname> defined in the
    <classname>javax.validation</classname> package. See the sub-sections of
    <xref linkend="section-configuring-validator-factory"/> for more
    information about these interfaces.</para>

    <para><property>executable-validation</property> and its subnodes define
    defaults for method validation. The Bean Validation specification defines
    constructor and non getter methods as defaults. The
    <property>enabled</property> attribute acts as global switch to turn
    method validation on and off (see also <xref
    linkend="chapter-method-constraints"/>).</para>

    <para>Via the <property>constraint-mapping</property> element you can list
    an arbitrary number of additional XML files containing the actual
    constraint configuration. Mapping file names must be specified using their
    fully-qualified name on the classpath. Details on writing mapping files
    can be found in the next section.</para>

    <para>Last but not least, you can specify provider specific properties via
    the <property>property</property> nodes. In the example we are using the
    Hibernate Validator specific
    <property>hibernate.validator.fail_fast</property> property (see <xref
    linkend="section-fail-fast"/>).</para>
  </section>

  <section id="section-mapping-xml-constraints">
    <title id="section-mapping-constraints">Mapping constraints via
    <property>constraint-mappings</property></title>

    <para>Expressing constraints in XML is possible via files adhering to the
    schema seen in <xref linkend="image-mapping-configuration"/>. Note that
    these mapping files are only processed if listed via
    <property>constraint-mapping</property> in
    <filename>validation.xml</filename>.</para>

    <example id="image-mapping-configuration">
      <title>validation-mapping-1.1.xsd</title>

      <mediaobject>
        <imageobject role="fo">
          <imagedata align="center" contentdepth="200mm"
                     fileref="validation-mapping-1.1.png" format="PNG"/>
        </imageobject>

        <imageobject role="html">
          <imagedata fileref="validation-mapping-1.1.png" format="PNG"
                     scalefit="1"/>
        </imageobject>
      </mediaobject>
    </example>

    <para><xref linkend="example-constraints-car"/> shows how the classes
    <classname>Car</classname> and <classname>RentalCar</classname> from <xref
    linkend="example-car"/> resp. <xref linkend="example-rental-car"/> could
    be mapped in XML.</para>

    <example id="example-constraints-car">
      <title>Bean constraints configured via XML</title>

      <programlisting language="XML" role="XML">&lt;constraint-mappings
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.1.xsd"
    xmlns="http://jboss.org/xml/ns/javax/validation/mapping" version="1.1"&gt;

    &lt;default-package&gt;org.hibernate.validator.referenceguide.chapter05&lt;/default-package&gt;
    &lt;bean class="Car" ignore-annotations="true"&gt;
        &lt;field name="manufacturer"&gt;
            &lt;constraint annotation="javax.validation.constraints.NotNull"/&gt;
        &lt;/field&gt;
        &lt;field name="licensePlate"&gt;
            &lt;constraint annotation="javax.validation.constraints.NotNull"/&gt;
        &lt;/field&gt;
        &lt;field name="seatCount"&gt;
            &lt;constraint annotation="javax.validation.constraints.Min"&gt;
                &lt;element name="value"&gt;2&lt;/element&gt;
            &lt;/constraint&gt;
        &lt;/field&gt;
        &lt;field name="driver"&gt;
            &lt;valid/&gt;
        &lt;/field&gt;
        &lt;getter name="passedVehicleInspection" ignore-annotations="true"&gt;
            &lt;constraint annotation="javax.validation.constraints.AssertTrue"&gt;
                &lt;message&gt;The car has to pass the vehicle inspection first&lt;/message&gt;
                &lt;groups&gt;
                    &lt;value&gt;CarChecks&lt;/value&gt;
                &lt;/groups&gt;
                &lt;element name="max"&gt;10&lt;/element&gt;
            &lt;/constraint&gt;
        &lt;/getter&gt;
    &lt;/bean&gt;
    &lt;bean class="RentalCar" ignore-annotations="true"&gt;
        &lt;class ignore-annotations="true"&gt;
            &lt;group-sequence&gt;
                &lt;value&gt;RentalCar&lt;/value&gt;
                &lt;value&gt;CarChecks&lt;/value&gt;
            &lt;/group-sequence&gt;
        &lt;/class&gt;
    &lt;/bean&gt;
    &lt;constraint-definition annotation="org.mycompany.CheckCase"&gt;
        &lt;validated-by include-existing-validators="false"&gt;
            &lt;value&gt;org.mycompany.CheckCaseValidator&lt;/value&gt;
        &lt;/validated-by&gt;
    &lt;/constraint-definition&gt;
&lt;/constraint-mappings&gt;</programlisting>
    </example>

    <para><xref linkend="example-rental-station-xml"/> shows how the
    constraints from <xref
    linkend="example-declaring-parameter-constraints"/>, <xref
    linkend="example-declaring-return-value-constraints"/> and <xref
    linkend="example-specifying-constraint-target"/> can be expressed in
    XML.</para>

    <example id="example-rental-station-xml">
      <title>Method constraints configured via XML</title>

      <programlisting language="XML" role="XML">&lt;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.1.xsd" version="1.1"&gt;

    &lt;default-package&gt;org.hibernate.validator.referenceguide.chapter07&lt;/default-package&gt;

    &lt;bean class="RentalStation" ignore-annotations="true"&gt;
        &lt;constructor&gt;
            &lt;return-value&gt;
                &lt;constraint annotation="ValidRentalStation"/&gt;
            &lt;/return-value&gt;
        &lt;/constructor&gt;

        &lt;constructor&gt;
            &lt;parameter type="java.lang.String"&gt;
                &lt;constraint annotation="javax.validation.constraints.NotNull"/&gt;
            &lt;/parameter&gt;
        &lt;/constructor&gt;

        &lt;method name="getCustomers"&gt;
            &lt;return-value&gt;
                &lt;constraint annotation="javax.validation.constraints.NotNull"/&gt;
                &lt;constraint annotation="javax.validation.constraints.Size"&gt;
                    &lt;element name="min"&gt;1&lt;/element&gt;
                &lt;/constraint&gt;
            &lt;/return-value&gt;
        &lt;/method&gt;

        &lt;method name="rentCar"&gt;
            &lt;parameter type="Customer"&gt;
                &lt;constraint annotation="javax.validation.constraints.NotNull"/&gt;
            &lt;/parameter&gt;
            &lt;parameter type="java.util.Date"&gt;
                &lt;constraint annotation="javax.validation.constraints.NotNull"/&gt;
                &lt;constraint annotation="javax.validation.constraints.Future"/&gt;
            &lt;/parameter&gt;
            &lt;parameter type="int"&gt;
                &lt;constraint annotation="javax.validation.constraints.Min"&gt;
                    &lt;element name="value"&gt;1&lt;/element&gt;
                &lt;/constraint&gt;
            &lt;/parameter&gt;
        &lt;/method&gt;
    &lt;/bean&gt;

    &lt;bean class="Garage" ignore-annotations="true"&gt;
        &lt;method name="buildCar"&gt;
            &lt;parameter type="java.util.List"/&gt;
            &lt;cross-parameter&gt;
                &lt;constraint annotation="ELAssert"&gt;
                    &lt;element name="expression"&gt;...&lt;/element&gt;
                    &lt;element name="validationAppliesTo"&gt;PARAMETERS&lt;/element&gt;
                &lt;/constraint&gt;
            &lt;/cross-parameter&gt;
        &lt;/method&gt;
        &lt;method name="paintCar"&gt;
            &lt;parameter type="int"/&gt;
            &lt;return-value&gt;
                &lt;constraint annotation="ELAssert"&gt;
                    &lt;element name="expression"&gt;...&lt;/element&gt;
                    &lt;element name="validationAppliesTo"&gt;RETURN_VALUE&lt;/element&gt;
                &lt;/constraint&gt;
            &lt;/return-value&gt;
        &lt;/method&gt;
    &lt;/bean&gt;

&lt;/constraint-mappings&gt;</programlisting>
    </example>

    <para>The XML configuration is closely mirroring the programmatic API. For
    this reason it should suffice to just add some comments.
    <property>default-package</property> is used for all fields where a class
    name is expected. If the specified class is not fully qualified the
    configured default package will be used. Every mapping file can then have
    several <property>bean</property> nodes, each describing the constraints
    on the entity with the specified class name.<warning>
        <para>A given entity can only be configured once across all
        configuration files. The same applies for constraint definitions for a
        given constraint annotation. It can only occur in one mapping file. If
        these rules are violated a <classname>ValidationException</classname>
        is thrown.</para>
      </warning>Setting <property>ignore-annotations</property> to
    <constant>true</constant> means that constraint annotations placed on the
    configured bean are ignored. The default for this value is
    <constant>true</constant>. ignore-annotations is also available for the
    nodes <property>class</property>, <property>fields</property>,
    <property>getter</property>, <property>constructor</property>,
    <property>method</property>, <property>parameter</property>,
    <property>cross-parameter</property> and
    <property>return-value</property>. If not explicitly specified on these
    levels the configured <property>bean</property> value applies.</para>

    <para>The nodes <property>class</property>, <property>field</property>,
    <property>getter</property>, <property>constructor</property> and
    <property>method</property> (and its sub node
    <property>parameter</property>) determine on which level the constraint
    gets placed. The <property>constraint</property> node is then used to add
    a constraint on the corresponding level. Each constraint definition must
    define the class via the <property>annotation</property> attribute. The
    constraint attributes required by the Bean Validation specification
    (<property>message</property>, <property>groups</property> and
    <property>payload</property>) have dedicated nodes. All other constraint
    specific attributes are configured using the <property>element</property>
    node.</para>

    <para>The <property>class</property> node also allows to reconfigure the
    default group sequence (see <xref linkend="section-default-group-class"/>)
    via the <property>group-sequence</property> node. Not shown in the example
    is the use of <property>convert-group</property> to specify group
    conversions (see <xref linkend="section-group-conversion"/>). This node is
    available on <property>field</property>, <property>getter</property>,
    <property>parameter</property> and <property>return-value</property> and
    specifies a <property>from</property> and <property>to</property>
    attribute to specify the groups.</para>

    <para>Last but not least, the list of
    <classname>ConstraintValidator</classname>s associated to a given
    constraint can be altered via the
    <property>constraint-definition</property> node. The
    <property>annotation</property> attribute represents the constraint
    annotation being altered. The <property>validated-by</property> elements
    represent the (ordered) list of <classname>ConstraintValidator</classname>
    implementations associated to the constraint. If
    <property>include-existing-validator</property> is set to
    <constant>false</constant>, validators defined on the constraint
    annotation are ignored. If set to <constant>true</constant>, the list of
    constraint validators described in XML is concatenated to the list of
    validators specified on the annotation.</para>
  </section>
</chapter>
