Spring validation for list of accepted string values - java

Is there a validation annotation for Spring that will do something like:
#ValidString({"US", "GB", "CA"})
final String country;
and validate that the string is one of the supported values in the array?

You need to create a custom annotation to do this, I would say have an annotation which accepts enum over string comparison, and use it something like this.
public enum CountryCode {
US,
GB,
CA;
}
#ValidateString(CountryCode.STRING)
String code;
You may go thru all the responses in this question
Java String validation using enum values and annotation
A not so clean way is to use #Pattern annotation with all the country codes in regex.
#Pattern(regexp="^(AF|AX|AL|DZ|AS|AD|AO|AI|AQ|AG|AR|AM|AW|AU|AT|AZ|BS|BH|BD|BB|BY|BE|BZ|BJ|BM|BT|BO|BQ|BA|BW|BV|BR|IO|BN|BG|BF|BI|KH|CM|CA|CV|KY|CF|TD|CL|CN|CX|CC|CO|KM|CG|CD|CK|CR|CI|HR|CU|CW|CY|CZ|DK|DJ|DM|DO|EC|EG|SV|GQ|ER|EE|ET|FK|FO|FJ|FI|FR|GF|PF|TF|GA|GM|GE|DE|GH|GI|GR|GL|GD|GP|GU|GT|GG|GN|GW|GY|HT|HM|VA|HN|HK|HU|IS|IN|ID|IR|IQ|IE|IM|IL|IT|JM|JP|JE|JO|KZ|KE|KI|KP|KR|KW|KG|LA|LV|LB|LS|LR|LY|LI|LT|LU|MO|MK|MG|MW|MY|MV|ML|MT|MH|MQ|MR|MU|YT|MX|FM|MD|MC|MN|ME|MS|MA|MZ|MM|NA|NR|NP|NL|NC|NZ|NI|NE|NG|NU|NF|MP|NO|OM|PK|PW|PS|PA|PG|PY|PE|PH|PN|PL|PT|PR|QA|RE|RO|RU|RW|BL|SH|KN|LC|MF|PM|VC|WS|SM|ST|SA|SN|RS|SC|SL|SG|SX|SK|SI|SB|SO|ZA|GS|SS|ES|LK|SD|SR|SJ|SZ|SE|CH|SY|TW|TJ|TZ|TH|TL|TG|TK|TO|TT|TN|TR|TM|TC|TV|UG|UA|AE|GB|US|UM|UY|UZ|VU|VE|VN|VG|VI|WF|EH|YE|ZM|ZW)$",message="invalid code")
private String countryCode;

Related

Can Java Validator method validateProperty validate object with multiple fields inside?

As stated in the title, I'm using the Validator to validate fields based on their names like this:
mandatoryInputs.stream()
.map(x -> v.validateProperty(accountBenefitForm, x, AccountBenefitFormAdditionalInfo.class))
it works fine, but only for the simple fields like Strings that have their constraints in the accountBenefitForm for example:
#NotBlank(message = "Username can not be null.", groups = {AccountBenefitFormBasicInfo.class})
#Size(max = 255, message = "Username is too long (max size 255).")
private String username;
But it won't work for objects that have multiple fields inside them, like this one:
#Valid
private ContactData contactData;
where ContactData implementation looks like this:
#NotBlank(message = "You have to add e-mail address.", groups = {AccountBenefitFormAdditionalInfo.class})
#Email(message = "E-mail is not valid.", groups = {AccountBenefitFormAdditionalInfo.class})
#Size(max = 255, message = "E-mail is too long (max size 255).", groups = {AccountBenefitFormAdditionalInfo.class})
private String email;
#NotBlank(groups = {AccountBenefitFormAdditionalInfo.class})
private String phoneNumber;
Is there a way I can make this work or do I need to validate those more complex objects on their own?
You have basically two kinds of annotations that can be used for validations here: Spring annotations (#Validated) as well as the javax annotation (#Valid, #NotBlank) etc.
For Spring, you can luckily often skip the manual validation unless you have some custom constraints (e.g. if person lives in country ABC, they need to provide additional info). Annotating just the field is not enough if you don't cascade the validation from the outer class. This cascade can be done conveniently on method-level by annotating the method param with #Valid e.g.
void doSomething(#Valid ContactDataHolder contactDataHolder) { ... }
If you'd like to use validation in Spring, I would recommend to use the Spring Validator interface instead of the one from javax as it should give you the expected behavior for nesting. You might also decide to apply #Validated on the class level to save you from writing #Valid(ated) on the method level each time.
So I've managed to somewhat resolve my problem by using the Apache BVal. Heres the code to create a validator to use the validateProperty method with cascading validation enabled:
ValidatorFactory factory = Validation.byProvider(ApacheValidationProvider.class).configure().buildValidatorFactory();
CascadingPropertyValidator validator = factory.getValidator().unwrap(CascadingPropertyValidator.class);
validator.validateProperty(accountBenefitForm, x, true, Default.class, AccountBenefitFormAdditionalInfo.class))
where x is the string of field to validate, and if that field is annotated with #Valid, it will then validate the inside fields according to their own constraints.
Along the way I've also found out that you can just use the "normal" javax Validator and pass the field to validate as contactData.email which means validate email field of the contactData field of the object that u pass as first argument to the validateProperty method.
Edit:
BVal supports Bean Validation 1.1 (JSR 349) and not the 2.0 version(JSR 380), and since #NotBlank or #NotEmpty constrains are part of 2.0, it won't validate a field annotated with them. Here are the docs for the 1.1 , and 2.0

Dynamically Customize JSON Returned From A Spring Boot REST Service Using Jackson

I am developing a REST service using Spring Boot and Jackson. For this service the caller can specify the list of fields they want in the result. Suppose we had this java class for which we return the fields to the user:
public class Customer {
public int id;
public String firstName;
public String lastName;
public String addressLine1;
public String addressLine2;
public String city;
public String state;
public String zip;
public String phone;
}
The client would call our service:
https://myhost.net/getCustomer?id=2112&lof=id,firstName,lastName
Where the lof parameter is the "list of fields" that the client wants.
This is obviously a simple example, we are implementing something much larger and many more fields are being returned. In addition we are returning many occurrences of objects in 1 call. The requirement is that the client can limit the fields to only the fields they are interested in.
Annotations are out of the question for obvious reasons.
How can I control how the objects are serialized on a per request basis?
Thanks much!
Paul
What you could do:
Register a serialize that will take this field list in consideration https://www.baeldung.com/jackson-custom-serialization
Create a wrapper (or proxy) that will return null for fields that should not be fetched and use #JsonInclude(Include.NON_NULL) annotation, but there you loose the distinction between not present and null field
You can implement it using dynamic #JsonView, but, as it was mentioned in one of the comments, graphql is the way to go.

JSR Validation #Pattern allowing null values

When I annotate a field with #Pattern
#Pattern(regexp="someRegexp")
public String name;
If the JSON contains this field, with value as null, then I expect this regex to fail and thus invalid.
if the JSON does NOT contain this field, then it is fine for the validation to pass.
How to achieve this?
To Strings, I usually use #NotBlank for not empty strings, but im not sure at 100% that it doesnt allow null entries, but, in this case, use #NotNull annotation.
Edit: I was looking for an example and I got this from an old project:
#NotNull
#NotBlank
#Pattern(regexp = "somePattern")
public String getEmail() {
return this.email;
}
As you can see, I use NotNull and NotBlank even though I have a pattern there.

How to convert firebase data (snake_case) to Java object (camelCase)

I want to map my firebase data object to my pojo. However, my firebase object property name is snake case,
such as; "user_name".
I want to use camelCase on my pojo,
such as; "userName"
I found beautiful answers like this one, however, I couldn't find any sample about snake_case to camelCase mapping.
My pojo;
#SerializedName("content")
private String content;
#SerializedName("user_name")
private String userName;
I'm using the following line of code for mapping. 'content' matches with no problem(with or without #SerializedName annotation) but userName stays as null.
Story story = storySnapshot.getValue(Story.class);
That is also an issue for obfuscation. Is there an elegant way to match the data to pojo?
The problem was #SerializedName annotation. Firebase has its own annotation, which is #PropertyName.
It is important to be careful about getter name because annotation cares about its name too.
The property must be public too.
There is a perfect answer about that on this link.
Final state of my pojo;
#PropertyName("content")
public String content;
#PropertyName("user_name")
public String userName;

Is there any way to control the order of hibernate validator doing validation?

We have a requirement that every fields of the object must be validated in a special order.
For example, we have Person object like below:
public class Person {
#NotNull
private String firstName;
#NotNull
private String lastName;
// getter and setter
}
When I use the javax.validation.Validator to validate this object, we need to make sure that the firstName always be validated first and then lastName. Is there any way for hibernate validator archive that requirement?
You want to use group sequences. In particular you probably want to redefine the default group for your entity. See also Redefining the Default group for a class as defined by the Bean Validation specification .

Categories

Resources