What is the use of groups and payload in custom Annotation In Java?
Asked Answered
C

1

16

Here's My code , I tried reading many stuff online but was not able to understand actual use of

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

Here is my code in which i have used it.

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueValidator.class)
public @interface UniqueValue {
    String message() default "Unique Constraint Violated";
    
    Class<?> [] groups() default{};
    Class<? extends Payload>[] payload() default{};
}

Thank you.

Charlotte answered 23/10, 2020 at 4:19 Comment(0)
A
15

Groups allow you to restrict the set of constraints applied during validation.

In the following example, the AClass class has the bool attribute that belongs to the AGroup group. But when the group of an attribute is not specified, which is the case of the other attributes of AClass, then it belongs to the default group javax.validation.groups.Default.

import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;

public class AClass {

    @NotBlank
    private String string;

    @Min(2)
    private int integer;

    @AssertTrue(groups = AGroup.class)
    private boolean bool;

    public AClass(String string, int integer, boolean bool) {
        this.string = string;
        this.integer = integer;
        this.bool = bool;
    }
}

A group declaration can be a simple empty interface.

public interface AGroup { }

In the following program, the validate method validates all attributes that belong to the default group. But to validate attributes of other groups, you must specify in the validate method which group of attributes will be validated.

import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import org.junit.Assert;

public class Program {

    public static void main(String[] args) {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

        // create a AClass and check that everything is ok with it.
        AClass a = new AClass("Foo", 2, false);
        Set<ConstraintViolation<AClass>> constraintViolations = validator.validate(a);
        Assert.assertEquals(0, constraintViolations.size());

        // but has it passed the bool field?
        constraintViolations = validator.validate(a, AGroup.class);
        Assert.assertEquals(1, constraintViolations.size());
        Assert.assertEquals("must be true", constraintViolations.iterator().next().getMessage()
        );
    }
}

Source: https://docs.jboss.org/hibernate/validator/5.2/reference/en-US/html/ch05.html#example-driver

Payloads can be used by clients of the Bean Validation API to assign custom payload objects to a constraint. This attribute is not used by the API itself.

In the following example, the TestBean class has an attribute with Payload.

import javax.validation.constraints.NotNull;

public class TestBean {

    @NotNull(payload = {ErrorEmailSender.class})
    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }
}

Implementation of ErrorEmailSender Payload:

import javax.validation.ConstraintViolation;
import javax.validation.Payload;

public class ErrorEmailSender implements Payload {

    public void onError(ConstraintViolation violation) {
        System.out.println("Sending email to support team: "
                + violation.getPropertyPath() + " "
                + violation.getMessage());
    }
}

The Client program checks whether a TestBean instance is valid, and if not, it calls the Payload of invalid attributes.

import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

public class Client {

    public static void main(String[] args) {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

        TestBean bean = new TestBean();
        Set<ConstraintViolation<TestBean>> constraintViolations = validator.validate(bean);

        if (constraintViolations.size() > 0) {
            constraintViolations.stream().forEach(Client::processError);
        } else {
            //proceed using user object
            System.out.println(bean);
        }
    }

    private static void processError(ConstraintViolation<TestBean> violation) {
        violation.getConstraintDescriptor().getPayload().forEach(p -> {
            if (ErrorEmailSender.class.isAssignableFrom(p)) {
                try {
                    ((ErrorEmailSender) p.getDeclaredConstructor().newInstance()).onError(violation);
                } catch (Exception ex) {
                    System.out.println(ex);
                }
            }
        });
    }
}

You should see in the output:

Sending email to support team: str must not be null

Sources:

Augustinaaugustine answered 31/10, 2020 at 3:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.