Skip to content

Commit

Permalink
HV-1328 Add documentation on new fail fast mode
Browse files Browse the repository at this point in the history
  • Loading branch information
marko-bekhta committed Feb 23, 2022
1 parent c6afe31 commit 4661a86
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 0 deletions.
49 changes: 49 additions & 0 deletions documentation/src/main/asciidoc/ch12.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -1001,3 +1001,52 @@ should be used as a default way of resolving the name (see how it is used in <<e
- `org.hibernate.validator.spi.nodenameprovider.JavaBeanProperty` is an interface that holds metadata about a bean property. It
extends `org.hibernate.validator.spi.nodenameprovider.Property` and provide some additional methods like `Class<?> getDeclaringClass()`
which returns the class that is the owner of the property.

[[section-fail-fast-on-property-violation]]
=== Fail fast on property violation mode

Fail fast on property violation mode allows to perform class level constraint validation only if all property level constrints have passed without any violations.
Enabling such mode should make writing class level constraint validators easier and cleaner, as the user will be working with valid properties.
Hence there will be no need in any additional `null` checks or data sanity checks.

This mode can be enabled using one of the Hibernate Validator common ways.
It can be done either programmatically (<<example-programmatic-fail-fast-on-property-violation>>), or through the property (<<example-property-fail-fast-on-property-violation>>).

[[example-programmatic-fail-fast-on-property-violation]]
.Using the fail fast on property violation validation mode
====
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/failfastonpropertyviolation/Book.java[tags=include]
----
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/failfastonpropertyviolation/FailFastOnPropertyViolationTest.java[tags=include]
----
====

Using this mode allows us to omit any additional checks in our class level validator.
We don't need to be worried about any of the properties being `null` as we've dealt with it already, using standard constraints.

[WARNING]
====
It is important to mention that only simple property constraints will be checked before going to class level ones. Any cascading constraints will be delayed till later.
====

.Implementation of `NonSelfPublishing` class level constrain validator
====
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/failfastonpropertyviolation/NonSelfPublishing.java[tags=include]
----
====

[[example-property-fail-fast-on-property-violation]]
.Setting the fail fast on property violation validation mode using an XML property
====
[source, XML, indent=0]
----
include::{resourcesdir}/org/hibernate/validator/referenceguide/chapter12/fail-fast-on-property-violation-validation.xml[]
----
====
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// tag::include[]
package org.hibernate.validator.referenceguide.chapter12.failfastonpropertyviolation;

//end::include[]

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import org.hibernate.validator.constraints.ISBN;

//tag::include[]
@NonSelfPublishing
public class Book {

@ISBN
private String isbn;

@NotBlank
private String title;

@NotNull
private Person author;

@NotNull
private Person publisher;

//constructors, getters and setters...
//end::include[]

public Book(String isbn, String title, Person author, Person publisher) {
this.isbn = isbn;
this.title = title;
this.author = author;
this.publisher = publisher;
}

public String getIsbn() {
return this.isbn;
}

public String getTitle() {
return this.title;
}

public Person getAuthor() {
return this.author;
}

public Person getPublisher() {
return this.publisher;
}

//tag::include[]
}
//end::include[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.hibernate.validator.referenceguide.chapter12.failfastonpropertyviolation;

import static org.junit.Assert.assertEquals;

import java.util.Set;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.constraints.NotNull;

import org.hibernate.validator.HibernateValidator;

import org.junit.Test;

public class FailFastOnPropertyViolationTest {

@Test
public void failFastOnPropertyViolation() {
//tag::include[]
Validator validator = Validation.byProvider( HibernateValidator.class )
.configure()
.failFastOnPropertyViolation( true )
.buildValidatorFactory()
.getValidator();

Book book = new Book( "978-1-56619-909-4", "Book", null /* author */, null /* publisher */ );

Set<ConstraintViolation<Book>> constraintViolations = validator.validate( book );

assertEquals( 2, constraintViolations.size() );

for ( ConstraintViolation<Book> constraintViolation : constraintViolations ) {
assertEquals(
NotNull.class,
constraintViolation.getConstraintDescriptor()
.getAnnotation()
.annotationType()
);
}
//end::include[]
}

@Test
public void failFastOnPropertyViolationProperty() {
//tag::property[]
Validator validator = Validation.byProvider( HibernateValidator.class )
.configure()
.addProperty( "hibernate.validator.fail_fast_on_property_violation", "true" )
.buildValidatorFactory()
.getValidator();
//end::property[]

Book book = new Book( "978-1-56619-909-4", "Book", null /* author */, null /* publisher */ );

Set<ConstraintViolation<Book>> constraintViolations = validator.validate( book );

assertEquals( 2, constraintViolations.size() );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.hibernate.validator.referenceguide.chapter12.failfastonpropertyviolation;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import jakarta.validation.Constraint;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import jakarta.validation.Payload;

import org.hibernate.validator.referenceguide.chapter12.failfastonpropertyviolation.NonSelfPublishing.NonSelfPublishingValidator;

@Documented
@Constraint(validatedBy = { NonSelfPublishingValidator.class })
@Target({ TYPE })
@Retention(RUNTIME)
public @interface NonSelfPublishing {

String message() default "{org.hibernate.validator.referenceguide.chapter12.failfastonpropertyviolation.NonSelfPublishing.message}";

Class<?>[] groups() default { };

Class<? extends Payload>[] payload() default { };
// tag::include[]
class NonSelfPublishingValidator implements ConstraintValidator<NonSelfPublishing, Book> {

@Override
public boolean isValid(Book book, ConstraintValidatorContext context) {
return !book.getAuthor().equals( book.getPublisher() );
}
}
//end::include[]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// tag::include[]
package org.hibernate.validator.referenceguide.chapter12.failfastonpropertyviolation;

//end::include[]

import jakarta.validation.constraints.NotNull;

//tag::include[]
public class Person {

@NotNull
private String firstName;

@NotNull
private String lastName;

public Person(@NotNull final String firstName, @NotNull final String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

//getters, setters, equals and hashcode...
}
//end::include[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<validation-config
xmlns="http://xmlns.jcp.org/xml/ns/validation/configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/validation/configuration
http://xmlns.jcp.org/xml/ns/validation/configuration/validation-configuration-2.0.xsd"
version="2.0">

<property name="hibernate.validator.fail_fast_on_property_violation">true</property>

</validation-config>

0 comments on commit 4661a86

Please sign in to comment.