I am using Java's Validator class to validate some input fields from my Spring Object class. I am validating URIs, and they can be in either format, http:/myURL/uri, or "readFromURI.v1". Originally, I was just validating the first part, so my Object class had:
#Pattern(regexp="[\\w\\s.,;:*&#(){}+-=?/|!\\[\\]%#$~]{0,512}", message="incorrect format")
private String URI;
Now, if the user selects a checkbox in my app, they will enter in the value as the second format, so I created a new regexp:
#Pattern.List({
#Pattern(regexp="[\\w\\s.,;:*&#(){}+-=?/|!\\[\\]%#$~]{0,512}", message="incorrect format"),
#Pattern(regexp="^\"(Create|Read|Update|Delete)[a-zA-Z]+.*vd+\"${0,512}", message="incorrect format")
})
private String URI;
The regexp is probably wrong for the second part, and I will probably ask that question at a later time. But now whenever I validate either format it fails both conditions. So I'm assuming that the way I wrote it, it's trying to apply both regex's. How can I choose one based on a value? That value field is in the same Class if that helps:
private String URI;
private boolean useHttp; //if true, validate using [\\w\\s.,;:*&#(){}+-=?/|!\\[\\]%#$~]{0,512}
You should write a custom validator, as explained here:
Create a new annotation CustomConstraint annotated with #Constraint(validatedBy = CustomConstraintValidator.class)
Have some class CustomConstraintValidator implements ConstraintValidator<CustomConstraint, YourType>
Annotate YourType with #CustomConstraint
Do your validation in your CustomConstraintValidator depending on your bean value.
Your validation will be able to check whatever field you want to test (I don't remember if class level constraint pass after each field level annotation pass, so you might have to check if URI is not null).
Related
Using Jakarta Been Validation https://hibernate.org/validator/ to validate Java code, I annotate a Classes property by a default #NotEmpty validation anotaton
#Validate
public class A {
..
#NotEmpty
private List<String> myList;
..
}
In a Test I set myList to an empty List, validate that List and expect the violation "must not be empty", which is the default violation message for the standard #NotEmpty annotation. I found that by printing it, but also here https://github.com/hibernate/hibernate-validator/blob/main/engine/src/main/resources/org/hibernate/validator/ValidationMessages.properties
Set<ConstraintViolation<A>> violations = validator.validate(A);
assertThat(violations).anyMatch(having Message("must not be empty", A.class));
This works, but I would like to replace the expected Message string with a reference to the default-string like jakarta.validation.constraints.Null.message, avoiding duplication of Strings. This however does not work:
assertThat(violations).anyMatch(having Message(jakarta.validation.constraints.Null.message, A.class));
Is there any validation expert around, that can show me what I am missing?
one has to load it from the classpath, if provided by /ValidationMessages.properties (or language specific ValidationMessages_<x>(_<y>).properties):
Properties ps = new Properties() ;
ps.load( getClass().getResourceAsStream("/ValidationMessages.properties") ) ;
assertThat(violations).anyMatch(having Message(
ps.getProperty( "jakarta.validation.constraints.Null.message"),
A.class))
if provided/overridden by direct class annotation, one has to use reflection on the specific classes field or method and get its annotation.
I'm implementing an in-memory API gateway to a SOAP service utilizing JAXB. One of the schema elements is a "choice", and there are several elements in the choice block.
I'm attempting to mirror the generated JAXB classes in the client namespace, so for this "choice" scenario I have a bean class with several properties, only one of which will be non-null.
I'm attempting to use the #NotNull annotation from javax.validation, along with the ValidatorFactory and Validator. However, a "choice" scenario makes this a little more complicated. I'm guessing this would call for a custom ConstraintValidator, along with a custom annotation to refer to the custom ConstraintValidator.
For instance, here's some fake code that resembles a part of my structure:
public class InquireRandomInformationRequest {
#NotNull(message ="subscriberSelector cannot be null")
#Valid
private SubscriberSelector subscriberSelector; // required
private SelectorMode mode; // optional
...
}
public class SubscriberSelector {
// Choice 1
private String billingAccountNumber; // \d{8,9,12,13}; required
private MarketInfo billingMarket; // optional
// Choice 2
private String subscriberNumber; // \d{10}; required
private ValidationCriteria validationCriteria; // optional
private BillingAccountInformation billingAccountInformation; // optional
private MemoProductType memoProductType; // optional
// Choice 3
private String unifiedBillingAccountNumber; // [0-9A-Za-z]{13}; required
...
}
I understand that I need the #Valid annotation on the "subscriberSelector" property for the validator to validate the sub-object. Past that, I'm not quite sure what I need to do to handle the choices problem.
To fit my example, I will need exactly one of "billingAccountNumber", "subscriberNumber", or "unifiedBillingAccountNumber" to be non-null (although I could compromise on simply taking the first non-null one in a particular sequence). In each "choice group", the other properties are optional, but it's possible that another property could be "required" if that particular choice group is selected (the selector property is non-null, in other words).
I've looked through the Hibernate Validator documentation, but I'm not sure exactly how to apply that for this situation.
If I define a custom annotation and a custom ConstraintValidator, where is the annotation referenced? On the class (like "SubscriberSelector") or on the "subscriberSelector" property (the former seems more logical to me).
You can define constraints on the class or on the property depending on your requirements.
Usually, the constraints are placed on the property but, in the case you mention, as multiple properties are concerned and interdependent, you should place the constraint at the class level.
See https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#section-declaring-bean-constraints in our documentation.
Problem:
How to save object Account as nested object when only ID is needed without getting ConstraintValidator exception?
Problem is because i have set validation rules to class, but when i want to save sem entity as nested object i get exception that some property values are missing. So i would liek to have different validation rules when i want to persist object as a whole and when i want to use it only sa nested object (when only ID is needed).
public class Account {
private int id;
#NotNull
private String name;
#NotNull
private String lastName;
#NotNull
private String userName;
//getters&setters
If I include Account as nested object i just need ID to be able to use it as FK (account entity is already in DB), but because of #NotNull annotation i get Exception.
Is there a way to ignore those annotations from Account when trying to save object Shop or how to create different validation rules for Account to validate just soem other properties and not all?
public class Shop {
private int id;
private Account owner; // only ID is needed
Do you have any basic example? I dont understand those in documentation. I have already read documentation before posting here.
You want to look at Bean Validation groups where you can classify specific validations so they are only activated when that group is validated and ignored otherwise.
You can refer to the documentation here for details.
Taking an example from the documentation:
// This is just a stub interface used for tagging validation criteria
public interface DriverChecks {
}
// The model
public class Driver {
#Min(value = 18, message = "You must be 18", groups = DriverChecks.class)
private int age;
// other stuffs
}
A group is nothing more than a tag that allows you to enable/disable validations based on specific use cases at run-time. By not specifying the groups attribute on a bean validation annotation, it defaults to the Default group, which is what Bean Validation uses if a group-tag isn't specified at the time of validation.
That means the following holds true:
// Age won't be validated since we didn't specify DriverChecks.class
validator.validate( driver );
// Age will be validated here because we specify DriverChecks.class
validator.validate( driver, DriverChecks.class );
This works great when you're triggering the validation yourself inside your service methods because you can manually control which group checks are applicable based on that method's use case.
When it comes to integrating directly with Hibernate ORM's event listeners that can also trigger bean validation, group specifications become a bit harder as they must be specified based on the event-type raised by hibernate.
javax.persistence.validation.group.pre-persist
javax.persistence.validation.group.pre-update
javax.persistence.validation.group.pre-remove
For each of the above properties you can specify in the JPA properties supplied to Hibernate, you can list a comma delimited list of groups that are to be validated for each of those event types. This allows you to have varying checks during insert versus update versus removal.
If that isn't sufficient, there is always the fact that you can create your own constraint validator implementation and annotation to plug into Bean Validation and specify that at the class or property level.
I have often found this useful in cases where values from multiple fields must be validated as a cohesive unit to imply their validity as the normal field-by-field validations didn't suffice.
Is it possible to check a String against a hibernate constraint without having to write a special Class for it? For example, if I just want to check if a given String is an email, is it possible to check it as a one-off test without writing a full class and validating that constraint against a particular property of the class?
You can annotate the property with #Email in your entity class. You can read the documentation in this link: http://docs.jboss.org/ejb3/app-server/HibernateAnnotations/api/org/hibernate/validator/Email.html
Edited:
String email = "email#test.com";
EmailValidator validator = new EmailValidator();
validator.isValid(email, null);
The method "isValid" will return true if your string is a well-formed email address.
Hope it helps!
I have the following class that I'm trying to validate via Hibernate:
public class LoginForm
{
#NotBlank(message = "{myCustomMessage}")
private String user;
#NotBlank(message = "{myCustomMessage}")
private String pw;
//....
}
This works fine and my custom message is correctly displayed for NotBlank, however if I have to specify the (message = "{myCustomMessage}") line for every single constraint, for every single member, in every single class, its going to become very repetitive.
Is there a way to globally set this message, so it doesn't have to be specified individually for every member? I.e so it will, by default, fetch myCustomMessage for #NotBlank? (And for all the other constraints that I specify it for).
Edit: So if I rename the message key from myCustomMessage to org.hibernate.validator.constraints.NotBlank.message , then I no longer need to specify the (message..) line. However, I'd still prefer if it could be made to work with myCustomMessage globally.
As you already found out, the only way would be to specify a value for the default key org.hibernate.validator.constraints.NotBlank.message. You also could define your own NotBlank constraint which specifies the value you want as default value for the message attribute, but I would not really recommend that.