[[validator-integration]]
== Integrating with other frameworks

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. For this reason there are multiple integration points with
other technologies.

[[validator-checkconstraints-orm]]
=== ORM integration

Hibernate Validator integrates with both Hibernate ORM and all pure Java Persistence providers.

[TIP]
====
When lazy loaded associations are supposed to be validated it is recommended to place the constraint
on the getter of the association. Hibernate ORM replaces lazy loaded associations with proxy instances
which get initialized/loaded when requested via the getter. If, in such a case, the constraint is
placed on field level, the actual proxy instance is used which will lead to validation errors.
====

[[validator-checkconstraints-db]]
==== Database schema-level validation

Out of the box, Hibernate ORM will translate the constraints you have defined for
your entities into mapping metadata. For example, if a property of your entity is annotated
`@NotNull`, its columns will be declared as `not null` in the DDL schema generated by Hibernate ORM.

If, for some reason, the feature needs to be disabled, set `hibernate.validator.apply_to_ddl` to
`false`. See also <<validator-defineconstraints-spec>> and <<validator-defineconstraints-hv-constraints>>.

You can also limit the DDL constraint generation to a subset of the defined constraints by setting
the property `org.hibernate.validator.group.ddl`. The property specifies the comma-separated, fully
specified class names of the groups a constraint has to be part of in order to be considered for DDL
schema generation.

[[validator-checkconstraints-orm-hibernateevent]]
==== Hibernate ORM event-based validation

Hibernate Validator has a built-in Hibernate event listener -
https://github.com/hibernate/hibernate-orm/blob/main/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationEventListener.java[`org.hibernate.cfg.beanvalidation.BeanValidationEventListener`] -
which is part of Hibernate ORM. Whenever a `PreInsertEvent`,
`PreUpdateEvent` or `PreDeleteEvent` occurs, the listener will verify all constraints of the entity
instance and throw an exception if any constraint is violated. Per default, objects will be checked
before any inserts or updates are made by Hibernate ORM. Pre deletion events will per default not
trigger a validation. You can configure the groups to be validated per event type using the
properties `jakarta.persistence.validation.group.pre-persist`,
`jakarta.persistence.validation.group.pre-update` and `jakarta.persistence.validation.group.pre-remove`.
The values of these properties are the comma-separated fully specified class names of the groups
to validate. <<example-beanvalidationeventlistener-config>> shows the default values for these
properties. In this case they could also be omitted.

On constraint violation, the event will raise a runtime `ConstraintViolationException` which contains
a set of `ConstraintViolation` instances describing each failure.

If Hibernate Validator is present in the classpath, Hibernate ORM will use it transparently.
To avoid validation even though Hibernate Validator is in the classpath, set
`jakarta.persistence.validation.mode` to none.

[NOTE]
====
If the beans are not annotated with validation annotations, there is no runtime performance cost.
====

In case you need to manually set the event listeners for Hibernate ORM, use the following
configuration in _hibernate.cfg.xml_:

[[example-beanvalidationeventlistener-config]]
.Manual configuration of `BeanValidationEvenListener`
====
[source, XML]
----
<hibernate-configuration>
    <session-factory>
        ...
        <property name="jakarta.persistence.validation.group.pre-persist">
            jakarta.validation.groups.Default
        </property>
        <property name="jakarta.persistence.validation.group.pre-update">
            jakarta.validation.groups.Default
        </property>
        <property name="jakarta.persistence.validation.group.pre-remove"></property>
        ...
        <event type="pre-update">
            <listener class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener"/>
        </event>
        <event type="pre-insert">
            <listener class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener"/>
        </event>
        <event type="pre-delete">
            <listener class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener"/>
        </event>
    </session-factory>
</hibernate-configuration>
----
====

==== Jakarta Persistence

If you are using Jakarta Persistence {versionJakartaPersistence} and Hibernate Validator is in the classpath,
the Jakarta Persistence {versionJakartaPersistence} specification requires
that Jakarta Validation gets enabled. The properties `jakarta.persistence.validation.group.pre-persist`,
`jakarta.persistence.validation.group.pre-update` and `jakarta.persistence.validation.group.pre-remove` as
described in <<validator-checkconstraints-orm-hibernateevent>> can in this case be configured in
_persistence.xml_. _persistence.xml_ also defines a node validation-mode which can be set to `AUTO`,
`CALLBACK` or `NONE`. The default is `AUTO`.

[[section-presentation-layer]]

=== JSF & Seam

When working with JSF2 or JBoss Seam and Hibernate Validator (Jakarta Validation) is present in the
runtime environment, validation is triggered for every field in the application. <<example-jsf2>>
shows an example of the `f:validateBean` tag in a JSF page. The `validationGroups` attribute is optional
and can be used to specify a comma separated list of validation groups. The default is
`jakarta.validation.groups.Default`. For more information refer to the Seam documentation or the JSF 2
specification.


[[example-jsf2]]
.Usage of Jakarta Validation within JSF2
====
[source, XML]
----
<h:form>

  <f:validateBean validationGroups="jakarta.validation.groups.Default">

    <h:inputText value=#{model.property}/>
    <h:selectOneRadio value=#{model.radioProperty}> ... </h:selectOneRadio>
    <!-- other input components here -->

  </f:validateBean>

</h:form>
----
====

[TIP]
====
The integration between JSF 2 and Jakarta Validation is described in the "Jakarta Validation Integration"
chapter of http://jcp.org/en/jsr/detail?id=314[JSR-314]. It is interesting to know that JSF
2 implements a custom `MessageInterpolator` to ensure proper localization. To encourage the use
of the Jakarta Validation message facility, JSF 2 will per default only display the generated Bean
Validation message. This can, however, be configured via the application resource bundle by
providing the following configuration (`{0}` is replaced with the Jakarta Validation message and `{1}` is
replaced with the JSF component label):

----
jakarta.faces.validator.BeanValidator.MESSAGE={1}: {0}
----

The default is:

----
jakarta.faces.validator.BeanValidator.MESSAGE={0}
----
====


[[section-integration-with-cdi]]
=== CDI

As of version 1.1, Bean Validation (and therefore Jakarta Validation) is integrated with CDI
(Contexts and Dependency Injection for Jakarta EE).

This integration provides CDI managed beans for `Validator` and `ValidatorFactory` and enables
dependency injection in constraint validators as well as custom message interpolators, traversable
resolvers, constraint validator factories, parameter name providers, clock providers and value
extractors.

Furthermore, parameter and return value constraints on the methods and constructors of CDI managed
beans will automatically be validated upon invocation.

When your application runs on a Jakarta EE container, this integration is enabled by default. When
working with CDI in a Servlet container or in a pure Java SE environment, you can use the CDI
portable extension provided by Hibernate Validator. To do so, add the portable extension to your
class path as described in <<section-getting-started-cdi>>.

==== Dependency injection

CDI's dependency injection mechanism makes it very easy to retrieve `ValidatorFactory` and `Validator`
instances and use them in your managed beans. Just annotate instance fields of your bean with
`@jakarta.inject.Inject` as shown in <<example-dependency-injection>>.

[[example-dependency-injection]]
.Retrieving validator factory and validator via `@Inject`
====
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter11/cdi/validator/RentalStation.java[tags=include]
----
====

The injected beans are the default validator factory and validator instances. In order to configure
them - e.g. to use a custom message interpolator - you can use the Jakarta Validation XML descriptors
as discussed in <<chapter-xml-configuration>>.

If you are working with several Jakarta Validation providers, you can make sure that factory and
validator from Hibernate Validator are injected by annotating the injection points with the
`@HibernateValidator` qualifier which is demonstrated in <<example-dependency-injection-using-hv>>.

[[example-dependency-injection-using-hv]]
.Using the `@HibernateValidator` qualifier annotation
====
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter11/cdi/validator/qualifier/RentalStation.java[tags=include]
----
====

[TIP]
====
The fully-qualified name of the qualifier annotation is
`org.hibernate.validator.cdi.HibernateValidator`. Be sure to not import
`org.hibernate.validator.HibernateValidator` instead which is the `ValidationProvider` implementation
used for selecting Hibernate Validator when working with the bootstrapping API (see
<<section-retrieving-validator-factory-validator>>).
====

Via `@Inject` you also can inject dependencies into constraint validators and other Jakarta Validation
objects such as `MessageInterpolator` implementations etc.

<<example-constraint-validator-injected-bean>>
demonstrates how an injected CDI bean is used in a `ConstraintValidator` implementation to determine
whether the given constraint is valid or not. As the example shows, you also can work with the
`@PostConstruct` and `@PreDestroy` callbacks to implement any required construction and destruction
logic.

[[example-constraint-validator-injected-bean]]
.Constraint validator with injected bean
====
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter11/cdi/injection/ValidLicensePlateValidator.java[tags=include]
----
====

==== Method validation

The method interception facilities of CDI allow for a very tight integration with Jakarta Validation's
method validation functionality. Just put constraint annotations to the parameters and return values
of the executables of your CDI beans and they will be validated automatically before (parameter
constraints) and after (return value constraints) a method or constructor is invoked.

Note that no explicit interceptor binding is required, instead the required method validation
interceptor will automatically be registered for all managed beans with constrained methods and
constructors.

[NOTE]
====
The interceptor `org.hibernate.validator.cdi.interceptor.spi.ValidationInterceptor` is
registered by `org.hibernate.validator.cdi.ValidationExtension`. This happens implicitly
within a Jakarta EE runtime environment or explicitly by adding the _hibernate-validator-cdi_
artifact - see <<section-getting-started-cdi>>
====

You can see an example in <<example-cdi-method-validation>>.

[[example-cdi-method-validation]]
.CDI managed beans with method-level constraints
====
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter11/cdi/methodvalidation/RentalStation.java[tags=include]
----

[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter11/cdi/methodvalidation/RentCarRequest.java[tags=include]
----
====

Here the `RentalStation` bean hosts several method constraints. When invoking one of the `RentalStation`
methods from another bean such as `RentCarRequest`, the constraints of the invoked method are
automatically validated. If any illegal parameter values are passed as in the example, a
`ConstraintViolationException` will be thrown by the method interceptor, providing detailed
information on the violated constraints. The same is the case if the method's return value violates
any return value constraints.

Similarly, constructor constraints are validated automatically upon invocation. In the example the
`RentalStation` object returned by the constructor will be validated since the constructor return
value is marked with `@Valid`.

===== Validated executable types

Jakarta Validation allows for a fine-grained control of the executable types which are automatically
validated. By default, constraints on constructors and non-getter methods are validated. Therefore,
the `@NotNull` constraint on the method `RentalStation#getAvailableCars()` in
<<example-cdi-method-validation>> does not get validated when the method is invoked.

You have the following options to configure which types of executables are validated upon
invocation:

* Configure the executable types globally via the XML descriptor __META-INF/validation.xml__;
see <<section-configuration-validation-xml>> for an example

* Use the `@ValidateOnExecution` annotation on the executable or type level

If several sources of configuration are specified for a given executable, `@ValidateOnExecution` on
the executable level takes precedence over `@ValidateOnExecution` on the type level and
`@ValidateOnExecution` generally takes precedence over the globally configured types in __META-
INF/validation.xml__.

<<example-using-validateonexecution>> shows how to use the `@ValidateOnExecution` annotation:

[[example-using-validateonexecution]]
.Using `@ValidateOnExecution`
====
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter11/cdi/methodvalidation/configuration/RentalStation.java[tags=include]
----
====

Here the method `rentCar()` won't be validated upon invocation because it is annotated with
`@ValidateOnExecution(type = ExecutableType.NONE)`. In contrast, the constructor and the
method `getAvailableCars()` will be validated due to `@ValidateOnExecution(type =
ExecutableType.ALL)` being given on the type level. `ExecutableType.ALL` is a more compact form for
explicitly specifying all the types `CONSTRUCTORS`, `GETTER_METHODS` and `NON_GETTER_METHODS`.


[TIP]
====
Executable validation can be turned off globally by specifying
`<executable-validation enabled="false"/>` in _META-INF/validation.xml_. In this case, all the
`@ValidateOnExecution` annotations are ignored.
====

Note that when a method overrides or implements a super-type method, the configuration will be taken
from that overridden or implemented method (as given via `@ValidateOnExecution` on the method itself
or on the super-type). This protects a client of the super-type method from an unexpected alteration
of the configuration, e.g. disabling validation of an overridden executable in a sub-type.

In case a CDI managed bean overrides or implements a super-type method and this super-type method
hosts any constraints, it can happen that the validation interceptor is not properly registered with
the bean, resulting in the bean's methods not being validated upon invocation. In this case you can
specify the executable type `IMPLICIT` on the sub-class as shown in
<<example-using-executabletype-implicit>>, which makes sure that all required metadata is discovered
and the validation interceptor kicks in when the methods on `ExpressRentalStation` are invoked.

[[example-using-executabletype-implicit]]
.Using `ExecutableType.IMPLICIT`
====
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter11/cdi/methodvalidation/implicit/RentalStation.java[tags=include]
----

[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter11/cdi/methodvalidation/implicit/ExpressRentalStation.java[tags=include]
----
====


=== Jakarta EE

When your application runs on a Jakarta EE application server such as http://wildfly.org/[WildFly],
you also can obtain `Validator` and `ValidatorFactory` instances via `@Resource` injection in
managed objects such as EJBs etc., as shown in <<example-validator-resource-injection>>.

[[example-validator-resource-injection]]
.Retrieving `Validator` and `ValidatorFactory` via `@Resource` injection
====
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter11/javaee/RentalStationBean.java[tags=include]
----
====

Alternatively you can obtain a validator and a validator factory from JNDI under the names
"_java:comp/Validator_" and "_java:comp/ValidatorFactory_", respectively.

Similar to CDI-based injection via `@Inject`, these objects represent default validator and validator
factory and thus can be configured using the XML descriptor _META-INF/validation.xml_ (see
<<chapter-xml-configuration>>).

When your application is CDI-enabled, the injected objects are CDI-aware as well and e.g. support
dependency injection in constraint validators.

=== JavaFX

Hibernate Validator also provides support for the unwrapping of JavaFX properties. If JavaFX is present
on the classpath, ``ValueExtractor``s for JavaFX properties are automatically registered.
See <<section-valueextraction-javafx>> for examples and further discussion.


[[validator-osgi]]
=== OSGi

Starting with Hibernate Validator 9.0, the Hibernate team no longer tests nor maintains the OSGi integration.
For users who would want to experiment with Hibernate Validator in an OSGi environment,
we will keep the existing manifest entries in place as they were.
