Java Validator custom message still includes the field name - java

I have the following annotation for a field:
#NotEmpty(message = "unique_name may not be empty")
#JsonProperty("unique_name")
private String uniqueName;
However, when I run a request, the error message I get back is:
uniqueName unique_name may not be empty
Why is the message contains the field name uniqueName? How can I fix this so the message only says unique_name may not be empty?

I believe the plain message string in the annotation is actually using interpolation behind the scenes to prepend the field name. It looks like you probably want to use a custom message.properties file instead. See here: Entity not null validation message
So in src/main/resources/messages you'd have a messages.properties file that contains the message, such as:
error.uniqueName.notEmpty=unique_name may not be empty
Then in your annotation:
#NotEmpty(message = "error.uniqueName.notEmpty")

Related

Java validation: Cannot interpolate field name in validation message

I tried the approach mentioned on How get property name in a validation message, but cannot apply it to the following situation.
#Data
public class CompanyRequest {
#PositiveOrZero(message = "validation.amount.positiveOrZero")
int quantity;
// code omitted for brevity
}
Here is my *.properties file having message:
validation.amount.positiveOrZero=The ${fieldName} value must be positive or zero
So, how can I use the property name in the validation message?
${fieldName} could not be retrieved easily inside the annotation without major modifications inside the core mechanism that makes the evaluation.
An easier way to achieve what you want, considering that for each field the name would be different, is the following.
Inside properties file put the property
validation.amount.positiveOrZero= value must be positive or zero
And then define the annotation in the code as
#PositiveOrZero(message = "The quantity {validation.amount.positiveOrZero}")
int quantity;
Edit:
It seems that the property should not be defined in a simple application.properties file but in another file named ValidationMessages.properties in the classpath.
As documented here
setValidationMessageSource(MessageSource messageSource) Specify a
custom Spring MessageSource for resolving validation messages, instead
of relying on JSR-303's default "ValidationMessages.properties" bundle
in the classpath.

org.springframework.web.bind.MethodArgumentNotValidException

I am using spring boot and I have a RestController with method
addBook(#Validated #RequestBody BookDto bookDto)
BookDto has a field annotated with write only
#JsonProperty(access = Access.WRITE_ONLY)
#NotNull(message = "cannot be empty")
#Size(min = 1, max = 20)
private String isdnNo;
This works as expected and I have to provide isdnNo while i do a post request.
And when I get it don't bring the isdnNo in reponse which is fine.
Issue here is in JUnit test case. I am using stand alone setup to test controller.
MockMvcBuilders.standaloneSetup(bookController).build();
MockHttpServletRequestBuilder postRequest = MockMvcRequestBuilders.post("/books/").contentType(JSON)
.accept(JSON);
postRequest.content(asJsonString(bookDto));
ResultActions result = mvc.perform(postRequest);
This JUnit test case gives exception org.springframework.web.bind.MethodArgumentNotValidException and says idnNo cannot be empty even though I have provided isdnNo in bookDto on performing post. What can be the issue here.
if I remove #JsonProperty(access = Access.WRITE_ONLY) the test case works fine.
Thanks in advance !
You want to keep Access.WRITE_ONLY removed because, according to the documentation, during serialization (ie writing it to a string) it will not read the value for serialization. You're method asJsonString is serializing the object thus removing the value.
AUTO: Access setting which means that visibility rules are to be used to automatically determine read- and/or write-access of this property.
READ_ONLY:
Access setting that means that the property may only be read for serialization, but not written (set) during deserialization.
READ_WRITE
Access setting that means that the property will be accessed for both serialization (writing out values as external representation) and deserialization (reading values from external representation), regardless of visibility rules.
WRITE_ONLY
Access setting that means that the property may only be written (set) for deserialization, but will not be read (get) on serialization, that is, the value of the property is not included in serialization.
https://fasterxml.github.io/jackson-annotations/javadoc/2.6/index.html?com/fasterxml/jackson/annotation/JsonProperty.Access.html

How to pass a field name to the global message in the properties file

I have the following message in my global-messages.properties file.
errors.integer=${getText(fieldname)} must be an integer.
which works fine with the validation.xml code, but I want to be able use the same message in my java action validation method with the addFieldError() method. My question is how to pass the fieldname to the message. If I use:
addFieldError("seqId", getText("errors.integer"));
I only get the "must be an integer." part of the message. I know I could change the message and use {0} instead of ${getText(fieldname)} but that is not an option because other code uses the message as it is.
First of all: You should really avoid using getText in properties because it is available only in some context.
Second: You should really avoid using fieldname in properties because it is validator specific field.
To achieve what you want, w/o modifying property file, you can create a fieldname property in your action with getter/setter and set its value before using addFieldError.
private String fieldname;
// getter/setter
// ...
fieldname = "seqId";
addFieldError("seqId", getText("errors.integer"));
Someone else showed me another way which worked which I thought I would share.
addFieldError("",getText("seqId")+ getText("errors.integer"));

Hibernate's validateValue() throws illegal argument exception if a property has no rules?

I have the following class:
class Foo
{
#NotEmpty
private String member1;
#NotEmpty
private String member2;
private String member3; //this one is optional, so has no rules
}
I have a library to which I add all the property names and corresponding UI fields, each time the UI's onChange event occurs, I call validateValue() on the given field name for that field, to validate it and show error/success message.
The problem is, in this case where I have no rules for member3, if I try to validate it by doing this:
String value = event.getValue(); //whatever the new value is now
validator.validateValue(Foo.class, "member3", value);
On the 2nd line, I get the following exception:
Caused by: java.lang.IllegalArgumentException: member3 is not a valid property of
com.xxx.Foo
Both member1 and member2 within the same class, are validated correctly.
Is there anything I can do to avoid getting this exception on the fields that don't have any rules set on them? If not, is there a way (without reflection or specifying it manually for each field) to check if a rule has no rules set on it, so i can avoid calling validateValue on it?
Which version of Hibernate Validator are you using? I checked with the latest version (5.1.0.Final) and there it works. If you can I recommend you upgrade.
You can also create an issue in the Validator issue tracker, reporting your problem and in particular which Validator version you are using.
Last but not least, to answer your question about alternatives. You could use the Bean Validation metadata API to find the constrained properties:
validator.getConstraintsForClass(Foo.class).getConstrainedProperties()
This will allow you to process only the properties which are acually constrained.

spring messages.properties uses variable name

Is there a way to use a title instead of a variable name when overriding Spring's default messages using the messages.properties file?
For example, I used this
typeMismatch.java.lang.Integer={0} must be a number.
to create the error message "firstName must be a number.", but I would prefer more readability, like "First Name must be a number.".
Is there any way to do this?
You can customize the property for a specific field of a specific class. Say your model attribute is named foo and it has a property named firstName then you can declare a custom error message for that specific field using:
typeMismatch.foo.firstName=First Name must be a number
You can see this page for more information.

Categories