Constraint annotation must have an element 'payload' which may be assigned to an array of classes extending javax.validation.Payload. By default this array should be empty , so it's optional.
Payload is an interface, we can provide an implementation of this interface as an element for 'payload' to provide some additional metadata information in a typed-safe way (as compare to some string literal) or we can even invoke some dynamic code with it. By default this interface does not define any methods.
Let's see how we can do that with some examples.
Examples
Using payload to specify severity level
This example idea is taken from the spec documents.
In this example, we are using Payload to specify a level of validation error severity with the constraint declaration so that the invoking code make some decision based on that.
package com.logicbig.example;
import javax.validation.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Set;
public class ConstraintPayloadExample {
private static final Validator validator;
static {
Configuration<?> config = Validation.byDefaultProvider().configure();
ValidatorFactory factory = config.buildValidatorFactory();
validator = factory.getValidator();
factory.close();
}
public static class Severity {
public static class Info implements Payload {
}
public static class Error implements Payload {
}
}
public static class TestBean {
@NotNull(payload = {Severity.Error.class})
@Size(min = 1, payload = {Severity.Info.class})
private String str;
public String getStr () {
return str;
}
public void setStr (String str) {
this.str = str;
}
}
public static void main (String[] args) {
TestBean bean = new TestBean();
//uncommenting next line will give us info severity
// or setting an non-empty string won't give any validation error
//bean.setStr("");
Set<ConstraintViolation<TestBean>> constraintViolations =
validator.validate(bean);
boolean severeError = false;
if (constraintViolations.size() > 0) {
for (ConstraintViolation<TestBean> violation : constraintViolations) {
Set<Class<? extends Payload>> payloads =
violation.getConstraintDescriptor().getPayload();
for (Class<? extends Payload> payload : payloads) {
if (payload == Severity.Error.class) {
severeError = true;
System.out.println("Error: " + violation.getPropertyPath() + " " +
violation.getMessage());
} else if (payload == Severity.Info.class) {
System.out.println("Info: " + violation.getPropertyPath() + " " +
violation.getMessage());
}
}
}
}
if (!severeError) {
//continue working with bean
System.out.println("working with : " + bean);
}
}
} OutputError: str must not be null
Invoking dynamic code using payload
This example shows how payload can be used to invoke some dynamic code using reflection.
The idea is to attach an application level error handler which will send email to the support team on errors.
package com.logicbig.example;
import javax.validation.*;
import javax.validation.constraints.NotNull;
import java.util.Set;
public class ConstraintPayloadExample2 {
private static final Validator validator;
static {
Configuration<?> config = Validation.byDefaultProvider().configure();
ValidatorFactory factory = config.buildValidatorFactory();
validator = factory.getValidator();
factory.close();
}
public interface AppErrorHandler<T> extends Payload {
void onError (ConstraintViolation<T> violation);
}
public static class ErrorEmailSender<T> implements AppErrorHandler<T> {
@Override
public void onError (ConstraintViolation<T> violation) {
System.out.println("Sending email to support team: " +
violation.getPropertyPath() + " " +
violation.getMessage());
}
}
public static class TestBean {
@NotNull(payload = {ErrorEmailSender.class})
private String str;
public String getStr () {
return str;
}
public void setStr (String str) {
this.str = str;
}
}
public static void main (String[] args) {
TestBean bean = new TestBean();
Set<ConstraintViolation<TestBean>> constraintViolations =
validator.validate(bean);
if (constraintViolations.size() > 0) {
constraintViolations.stream().forEach(
ConstraintPayloadExample2::processError);
} else {
//proceed using user object
System.out.println(bean);
}
}
private static void processError (ConstraintViolation<TestBean> violation) {
Set<Class<? extends Payload>> payload =
violation.getConstraintDescriptor().getPayload();
payload.forEach(p -> {
if (AppErrorHandler.class.isAssignableFrom(p)) {
try {
AppErrorHandler errorHandler = (AppErrorHandler) p.newInstance();
errorHandler.onError(violation);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
} OutputSending email to support team: str must not be null
Example ProjectDependencies and Technologies Used: - hibernate-validator 6.2.0.Final (Hibernate's Jakarta Bean Validation reference implementation)
Version Compatibility: 5.0.0.Final - 6.2.0.Final Version compatibilities of hibernate-validator with this example: groupId: org.hibernate artifactId: hibernate-validator Reference implementation for Bean Validation 1.1
- 5.0.0.Final
- 5.0.1.Final
- 5.0.2.Final
- 5.0.3.Final
- 5.1.0.Final
- 5.1.1.Final
- 5.1.2.Final
- 5.1.3.Final
- 5.2.0.Final
- 5.2.1.Final
- 5.2.2.Final
- 5.2.3.Final
- 5.2.4.Final
- 5.2.5.Final
- 5.3.0.Final
- 5.3.1.Final
- 5.3.2.Final
- 5.3.3.Final
- 5.3.4.Final
- 5.3.5.Final
- 5.3.6.Final
- 5.4.0.Final
- 5.4.1.Final
- 5.4.2.Final
- 5.4.3.Final
groupId: org.hibernate.validator artifactId: hibernate-validator Reference implementation for Bean Validation 2.0
- 6.0.0.Final
- 6.0.1.Final
- 6.0.2.Final
- 6.0.3.Final
- 6.0.4.Final
- 6.0.5.Final
- 6.0.6.Final
- 6.0.7.Final
- 6.0.8.Final
- 6.0.9.Final
- 6.0.10.Final
- 6.0.11.Final
- 6.0.12.Final
- 6.0.13.Final
- 6.0.14.Final
- 6.0.15.Final
- 6.0.16.Final
- 6.0.17.Final
- 6.0.18.Final
- 6.0.19.Final
- 6.0.20.Final
- 6.0.21.Final
- 6.0.22.Final
- 6.1.0.Final
- 6.1.1.Final
- 6.1.2.Final
- 6.1.3.Final
- 6.1.4.Final
- 6.1.5.Final
- 6.1.6.Final
- 6.1.7.Final
- 6.2.0.Final
Version 7 and later: Jakarta Bean Validation 3.0 jakarta.* packages
Versions in green have been tested.
- javax.el-api 3.0.0 (Expression Language 3.0 API)
- javax.el 2.2.6 (Expression Language 2.2 Implementation)
- JDK 8
- Maven 3.8.1
|