= Bean Validator Component
:doctitle: Bean Validator
:shortname: bean-validator
:artifactid: camel-bean-validator
:description: Validate the message body using the Java Bean Validation API.
:since: 2.3
:supportlevel: Stable
:tabs-sync-option:
:component-header: Only producer is supported
//Manually maintained attributes
:camel-spring-boot-name: bean-validator

*Since Camel {since}*

*{component-header}*

The Validator component performs bean validation of the message body
using the Java Bean Validation API
(http://jcp.org/en/jsr/detail?id=303[JSR 303]). Camel uses the reference
implementation, which is
https://docs.jboss.org/hibernate/validator/6.2/reference/en-US/html_single/[Hibernate
Validator].

Maven users will need to add the following dependency to their `pom.xml`
for this component:

[source,xml]
------------------------------------------------------------
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-bean-validator</artifactId>
    <version>x.y.z</version>
    <!-- use the same version as your Camel core version -->
</dependency>
------------------------------------------------------------

== URI format

------------------------------
bean-validator:label[?options]
------------------------------

Where *label* is an arbitrary text value describing the endpoint.
You can append query options to the URI in the following format: `?option=value&option=value&...`


// component-configure options: START

// component-configure options: END

// component options: START
include::partial$component-configure-options.adoc[]
include::partial$component-endpoint-options.adoc[]
// component options: END

// endpoint options: START

// endpoint options: END

=== Using HibernateValidationProviderResolver

[tabs]
====
Java::
+
[source,java]
--------------------------------------------------------------------------------------------------------------------------------
from("direct:test").
  to("bean-validator://ValidationProviderResolverTest?validationProviderResolver=#myValidationProviderResolver");
--------------------------------------------------------------------------------------------------------------------------------

XML::
+
[source,xml]
--------------------------------------------------------------------------------------------------------------------------------
<bean id="myValidationProviderResolver" class="org.apache.camel.component.bean.validator.HibernateValidationProviderResolver"/>
--------------------------------------------------------------------------------------------------------------------------------
====

== Example

Assumed we have a java bean with the following annotations

*Car.java*

[source,java]
-----------------------------------------------------------
public class Car {

    @NotNull
    private String manufacturer;

    @NotNull
    @Size(min = 5, max = 14, groups = OptionalChecks.class)
    private String licensePlate;
    
    // getter and setter
}
-----------------------------------------------------------

and an interface definition for our custom validation group

*OptionalChecks.java*

[source,java]
---------------------------------
public interface OptionalChecks {
}
---------------------------------

with the following Camel route, only the *@NotNull* constraints on the
attributes `manufacturer` and `licensePlate` will be validated (Camel uses
the default group `jakarta.validation.groups.Default`).

[source,java]
-------------------------
from("direct:start")
.to("bean-validator://x")
.to("mock:end")
-------------------------

If you want to check the constraints from the group `OptionalChecks`,
you have to define the route like this

[source,java]
----------------------------------------------
from("direct:start")
.to("bean-validator://x?group=OptionalChecks")
.to("mock:end")
----------------------------------------------

If you want to check the constraints from both groups, you have to
define a new interface first:

*AllChecks.java*

[source,java]
-----------------------------------------------------
@GroupSequence({Default.class, OptionalChecks.class})
public interface AllChecks {
}
-----------------------------------------------------

And then your route definition should look like this:

[source,java]
-----------------------------------------
from("direct:start")
.to("bean-validator://x?group=AllChecks")
.to("mock:end")
-----------------------------------------

And if you have to provide your own message interpolator, traversable
resolver and constraint validator factory, you have to write a route
like this:

[tabs]
====
Java::
+
[source,xml]
------------------------------------------------------------------------------------------------------
<bean id="myMessageInterpolator" class="my.ConstraintValidatorFactory" />
<bean id="myTraversableResolver" class="my.TraversableResolver" />
<bean id="myConstraintValidatorFactory" class="my.ConstraintValidatorFactory" />
------------------------------------------------------------------------------------------------------
XML::
+
[source,java]
------------------------------------------------------------------------------------------------------
from("direct:start")
.to("bean-validator://x?group=AllChecks&messageInterpolator=#myMessageInterpolator
&traversableResolver=#myTraversableResolver&constraintValidatorFactory=#myConstraintValidatorFactory")
.to("mock:end")
------------------------------------------------------------------------------------------------------
====

It's also possible to describe your constraints as XML and not as Java
annotations.
In this case, you have to provide the files `META-INF/validation.xml` and `constraints-car.xml` which could look like this:

[tabs]
====
validation.xml::
+
[source,xml]
------------------------------------------------------------------------------------------------------------------------------
<validation-config
        xmlns="https://jakarta.ee/xml/ns/validation/configuration"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://jakarta.ee/xml/ns/validation/configuration https://jakarta.ee/xml/ns/validation/validation-configuration-3.0.xsd"
        version="3.0">

    <default-provider>org.hibernate.validator.HibernateValidator</default-provider>
    <message-interpolator>org.hibernate.validator.engine.ResourceBundleMessageInterpolator</message-interpolator>
    <traversable-resolver>org.hibernate.validator.engine.resolver.DefaultTraversableResolver</traversable-resolver>
    <constraint-validator-factory>org.hibernate.validator.engine.ConstraintValidatorFactoryImpl</constraint-validator-factory>
    <constraint-mapping>/constraints-car.xml</constraint-mapping>

</validation-config>
------------------------------------------------------------------------------------------------------------------------------

constraints-car.xml::
+
[source,xml]
----------------------------------------------------------------------------------------------------
<constraint-mappings
        xmlns="https://jakarta.ee/xml/ns/validation/mapping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://jakarta.ee/xml/ns/validation/mapping
            https://jakarta.ee/xml/ns/validation/validation-mapping-3.0.xsd"
        version="3.0">

    <default-package>org.apache.camel.component.bean.validator</default-package>
    
    <bean class="CarWithoutAnnotations" ignore-annotations="true">
        <field name="manufacturer">
            <constraint annotation="jakarta.validation.constraints.NotNull" />
        </field>
        
        <field name="licensePlate">
            <constraint annotation="jakarta.validation.constraints.NotNull" />
            
            <constraint annotation="jakarta.validation.constraints.Size">
                <groups>
                    <value>org.apache.camel.component.bean.validator.OptionalChecks</value>
                </groups>
                <element name="min">5</element>
                <element name="max">14</element>
            </constraint>
        </field>
    </bean>
</constraint-mappings>
----------------------------------------------------------------------------------------------------
====

Here is the XML syntax for the example route definition where **OrderedChecks** can be https://github.com/apache/camel/blob/main/components/camel-bean-validator/src/test/java/org/apache/camel/component/bean/validator/OrderedChecks.java 

Note that the body should include an instance of a class to validate.

[source,xml]
----------------------------------------------------------------------------------------------------
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
  
    <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="direct:start"/>
            <to uri="bean-validator://x?group=org.apache.camel.component.bean.validator.OrderedChecks"/>
        </route>
    </camelContext>
</beans>
----------------------------------------------------------------------------------------------------


include::spring-boot:partial$starter.adoc[]
