<?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-annotation-processor">
  <title>Annotation Processor</title>

  <para>Have you ever caught yourself by unintentionally doing things
  like</para>

  <itemizedlist>
    <listitem>
      <para>specifying constraint annotations at unsupported data types (e.g.
      by annotating a String with <classname>@Past</classname>)</para>
    </listitem>

    <listitem>
      <para>annotating the setter of a JavaBeans property (instead of the
      getter method)</para>
    </listitem>

    <listitem>
      <para>annotating static fields/methods with constraint annotations
      (which is not supported)?</para>
    </listitem>
  </itemizedlist>

  <para>Then the Hibernate Validator Annotation Processor is the right thing
  for you. It helps preventing such mistakes by plugging into the build
  process and raising compilation errors whenever constraint annotations are
  incorrectly used.</para>

  <tip>
    <para>You can find the Hibernate Validator Annotation Processor as part of
    the distribution bundle on <ulink
    url="http://sourceforge.net/projects/hibernate/files/hibernate-validator">Sourceforge</ulink>
    or in the usual Maven repositories such as Maven Central under the GAV
    org.hibernate:hibernate-validator-annotation-processor:&version;.</para>
  </tip>

  <section id="validator-annotationprocessor-prerequisites">
    <title>Prerequisites</title>

    <para>The Hibernate Validator Annotation Processor is based on the
    "Pluggable Annotation Processing API" as defined by <ulink
    url="http://jcp.org/en/jsr/detail?id=269">JSR 269</ulink> which is part of
    the Java Platform since Java 6.</para>
  </section>

  <section id="validator-annotationprocessor-features">
    <title>Features</title>

    <para>As of Hibernate Validator &version; the Hibernate Validator
    Annotation Processor checks that:</para>

    <itemizedlist>
      <listitem>
        <para>constraint annotations are allowed for the type of the annotated
        element</para>
      </listitem>

      <listitem>
        <para>only non-static fields or methods are annotated with constraint
        annotations</para>
      </listitem>

      <listitem>
        <para>only non-primitive fields or methods are annotated with
        <classname>@Valid</classname></para>
      </listitem>

      <listitem>
        <para>only such methods are annotated with constraint annotations
        which are valid JavaBeans getter methods (optionally, see
        below)</para>
      </listitem>

      <listitem>
        <para>only such annotation types are annotated with constraint
        annotations which are constraint annotations themselves</para>
      </listitem>

      <listitem>
        <para>definition of dynamic default group sequence with
        <classname>@GroupSequenceProvider</classname> is valid</para>
      </listitem>
    </itemizedlist>
  </section>

  <section id="validator-annotationprocessor-options">
    <title>Options</title>

    <para>The behavior of the Hibernate Validator Annotation Processor can be
    controlled using the <ulink
    url="http://java.sun.com/javase/6/docs/technotes/tools/windows/javac.html#options">processor
    options</ulink> listed in table <xref
    linkend="table_processor_options"/>:</para>

    <table id="table_processor_options">
      <title>Hibernate Validator Annotation Processor options</title>

      <tgroup cols="2">
        <thead>
          <row>
            <entry align="center">Option</entry>

            <entry align="center">Explanation</entry>
          </row>
        </thead>

        <tbody>
          <row>
            <entry><varname>diagnosticKind</varname></entry>

            <entry>Controls how constraint problems are reported. Must be the
            string representation of one of the values from the enum
            <classname>javax.tools.Diagnostic.Kind</classname>, e.g.
            <classname>WARNING</classname>. A value of
            <classname>ERROR</classname> will cause compilation to halt
            whenever the AP detects a constraint problem. Defaults to
            <classname>ERROR</classname>.</entry>
          </row>

          <row>
            <entry><varname>methodConstraintsSupported</varname></entry>

            <entry>Controls whether constraints are allowed at methods of any
            kind. Must be set to <varname>true</varname> when working with
            method level constraints as supported by Hibernate Validator. Can
            be set to <varname>false</varname> to allow constraints only at
            JavaBeans getter methods as defined by the Bean Validation API.
            Defaults to <varname>true</varname>.</entry>
          </row>

          <row>
            <entry><varname>verbose</varname></entry>

            <entry>Controls whether detailed processing information shall be
            displayed or not, useful for debugging purposes. Must be either
            <varname>true</varname> or <varname>false</varname>. Defaults to
            <varname>false</varname>.</entry>
          </row>
        </tbody>
      </tgroup>
    </table>
  </section>

  <section id="validator-annotationprocessor-usage">
    <title>Using the Annotation Processor</title>

    <para>This section shows in detail how to integrate the Hibernate
    Validator Annotation Processor into command line builds (javac, Ant,
    Maven) as well as IDE-based builds (Eclipse, IntelliJ IDEA,
    NetBeans).</para>

    <section id="validator-annotationprocessor-commandline">
      <title>Command line builds</title>

      <section id="validator-annotationprocessor-javac">
        <title>javac</title>

        <para>When compiling on the command line using <ulink
        url="http://java.sun.com/javase/6/docs/technotes/guides/javac/index.html">javac</ulink>,
        specify the JAR hibernate-validator-annotation-processor-&version;.jar
        using the "processorpath" option as shown in the following listing.
        The processor will be detected automatically by the compiler and
        invoked during compilation.</para>

        <example>
          <title>Using the annotation processor with javac</title>

          <programlisting>javac src/main/java/org/hibernate/validator/ap/demo/Car.java \
   -cp /path/to/validation-api-&bvVersion;.jar \
   -processorpath /path/to/hibernate-validator-annotation-processor-&version;.jar</programlisting>
        </example>
      </section>

      <section id="validator-annotationprocessor-ant">
        <title>Apache Ant</title>

        <para>Similar to directly working with javac, the annotation processor
        can be added as as compiler argument when invoking the <ulink
        url="http://ant.apache.org/manual/CoreTasks/javac.html">javac
        task</ulink> for <ulink url="http://ant.apache.org/">Apache
        Ant</ulink>:</para>

        <example>
          <title>Using the annotation processor with Ant</title>

          <programlisting language="XML" role="XML">&lt;javac srcdir="src/main"
       destdir="build/classes"
       classpath="/path/to/validation-api-&bvVersion;.jar"&gt;
       &lt;compilerarg value="-processorpath" /&gt;
       &lt;compilerarg value="/path/to/hibernate-validator-annotation-processor-&version;.jar"/&gt;
&lt;/javac&gt;</programlisting>
        </example>
      </section>

      <section>
        <title>Maven</title>

        <para>There are several options for integrating the annotation
        processor with <ulink url="http://maven.apache.org/">Apache
        Maven</ulink>. Generally it is sufficient to add the Hibernate
        Validator Annotation Processor as dependency to your project:</para>

        <example>
          <title>Adding the HV Annotation Processor as dependency</title>

          <programlisting language="XML" role="XML">...
&lt;dependency&gt;
    &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
    &lt;artifactId&gt;hibernate-validator-annotation-processor&lt;/artifactId&gt;
    &lt;version&gt;&version;&lt;/version&gt;
&lt;/dependency&gt;
...        </programlisting>
        </example>

        <para>The processor will then be executed automatically by the
        compiler. This basically works, but comes with the disadavantage that
        in some cases messages from the annotation processor are not displayed
        (see <ulink
        url="http://jira.codehaus.org/browse/MCOMPILER-66">MCOMPILER-66</ulink>).</para>

        <para>Another option is using the <ulink
        url="http://code.google.com/p/maven-annotation-plugin/">Maven
        Annotation Plugin</ulink>. To work with this plugin, disable the
        standard annotation processing performed by the compiler plugin and
        configure the annotation plugin by specifying an execution and adding
        the Hibernate Validator Annotation Processor as plugin dependency
        (that way the processor is not visible on the project's actual
        classpath):</para>

        <example>
          <title>Configuring the Maven Annotation Plugin</title>

          <programlisting language="XML" role="XML">...
&lt;plugin&gt;
    &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
    &lt;configuration&gt;
        &lt;source&gt;1.6&lt;/source&gt;
        &lt;target&gt;1.6&lt;/target&gt;
        &lt;compilerArgument&gt;-proc:none&lt;/compilerArgument&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;
&lt;plugin&gt;
    &lt;groupId&gt;org.bsc.maven&lt;/groupId&gt;
    &lt;artifactId&gt;maven-processor-plugin&lt;/artifactId&gt;
    &lt;version&gt;2.2.1&lt;/version&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;id&gt;process&lt;/id&gt;
            &lt;goals&gt;
                &lt;goal&gt;process&lt;/goal&gt;
            &lt;/goals&gt;
            &lt;phase&gt;process-sources&lt;/phase&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
            &lt;artifactId&gt;hibernate-validator-annotation-processor&lt;/artifactId&gt;
            &lt;version&gt;&version;&lt;/version&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
&lt;/plugin&gt;
...
                    </programlisting>
        </example>
      </section>
    </section>

    <section id="validator-annotationprocessor-ide">
      <title>IDE builds</title>

      <section>
        <title>Eclipse</title>

        <para>Do the following to use the annotation processor within the
        <ulink url="http://www.eclipse.org/">Eclipse</ulink> IDE:</para>

        <itemizedlist>
          <listitem>
            <para>Right-click your project, choose "Properties"</para>
          </listitem>

          <listitem>
            <para>Go to "Java Compiler" and make sure, that "Compiler
            compliance level" is set to "1.6". Otherwise the processor won't
            be activated</para>
          </listitem>

          <listitem>
            <para>Go to "Java Compiler - Annotation Processing" and choose
            "Enable annotation processing"</para>
          </listitem>

          <listitem>
            <para>Go to "Java Compiler - Annotation Processing - Factory Path"
            and add the JAR
            hibernate-validator-annotation-processor-&version;.jar</para>
          </listitem>

          <listitem>
            <para>Confirm the workspace rebuild</para>
          </listitem>
        </itemizedlist>

        <para>You now should see any annotation problems as regular error
        markers within the editor and in the "Problem" view:</para>

        <mediaobject>
          <imageobject>
            <imagedata align="center" arch="" contentwidth="150mm"
                       fileref="annotation_processor_eclipse.png"/>
          </imageobject>
        </mediaobject>
      </section>

      <section id="validator-annotationprocessor-idea">
        <title>IntelliJ IDEA</title>

        <para>The following steps must be followed to use the annotation
        processor within <ulink url="http://www.jetbrains.com/idea/">IntelliJ
        IDEA</ulink> (version 9 and above):</para>

        <itemizedlist>
          <listitem>
            <para>Go to "File", then "Settings",</para>
          </listitem>

          <listitem>
            <para>Expand the node "Compiler", then "Annotation
            Processors"</para>
          </listitem>

          <listitem>
            <para>Choose "Enable annotation processing" and enter the
            following as "Processor path":
            /path/to/hibernate-validator-annotation-processor-&version;.jar</para>
          </listitem>

          <listitem>
            <para>Add the processor's fully qualified name
            <classname>org.hibernate.validator.ap.ConstraintValidationProcessor</classname>
            to the "Annotation Processors" list</para>
          </listitem>

          <listitem>
            <para>If applicable add you module to the "Processed Modules"
            list</para>
          </listitem>
        </itemizedlist>

        <para>Rebuilding your project then should show any erronous constraint
        annotations:</para>

        <mediaobject>
          <imageobject>
            <imagedata align="center" arch="" contentwidth="150mm"
                       fileref="annotation_processor_intellij.png"/>
          </imageobject>
        </mediaobject>
      </section>

      <section id="validator-annotationprocessor-netbeans">
        <title>NetBeans</title>

        <para>Starting with version 6.9, also the <ulink
        url="http://www.netbeans.org/">NetBeans</ulink> IDE supports using
        annotation processors within the IDE build. To do so, do the
        following:</para>

        <itemizedlist>
          <listitem>
            <para>Right-click your project, choose "Properties"</para>
          </listitem>

          <listitem>
            <para>Go to "Libraries", tab "Processor", and add the JAR
            hibernate-validator-annotation-processor-&version;.jar</para>
          </listitem>

          <listitem>
            <para>Go to "Build - Compiling", select "Enable Annotation
            Processing" and "Enable Annotation Processing in Editor". Add the
            annotation processor by specifying its fully qualified name
            <classname>org.hibernate.validator.ap.ConstraintValidationProcessor</classname></para>
          </listitem>
        </itemizedlist>

        <para>Any constraint annotation problems will then be marked directly
        within the editor:</para>

        <mediaobject>
          <imageobject>
            <imagedata align="center" arch="" contentwidth="150mm"
                       fileref="annotation_processor_netbeans.png"/>
          </imageobject>
        </mediaobject>
      </section>
    </section>
  </section>

  <section id="validator-annotationprocessor-known-issues">
    <title>Known issues</title>

    <para>The following known issues exist as of May 2010:</para>

    <itemizedlist>
      <listitem>
        <para><ulink
        url="http://opensource.atlassian.com/projects/hibernate/browse/HV-308">HV-308</ulink>:
        Additional validators registered for a constraint <ulink
        url="http://docs.jboss.org/hibernate/stable/validator/reference/en/html_single/#d0e1957">using
        XML</ulink> are not evaluated by the annotation processor.</para>
      </listitem>

      <listitem>
        <para>Sometimes custom constraints can't be <ulink
        url="http://opensource.atlassian.com/projects/hibernate/browse/HV-293">properly
        evaluated</ulink> when using the processor within Eclipse. Cleaning
        the project can help in these situations. This seems to be an issue
        with the Eclipse JSR 269 API implementation, but further investigation
        is required here.</para>
      </listitem>

      <listitem>
        <para>When using the processor within Eclipse, the check of dynamic
        default group sequence definitions doesn't work. After further
        investigation, it seems to be an issue with the Eclipse JSR 269 API
        implementation.</para>
      </listitem>
    </itemizedlist>
  </section>
</chapter>
