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 May 30, 2019
1 parent 626d4fb commit 6d6dbbc
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 @@ -855,3 +855,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.
Hance 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 javax.validation.constraints.NotBlank;
import javax.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 javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.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 javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.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 javax.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 6d6dbbc

Please sign in to comment.