Message parameters not resolved using Thymeleaf - java

I'm working on a web application using Spring Boot + Thymeleaf and I'm using #Size annotation to validate a field of a form backing object:
#Size(max=50)
private String name;
By using the default error message, all works fine and I'm getting the following message:
size must be between 0 and 50
Now I'm trying to customize the error message. First of all I've tried the following:
#Size(max=50, message="Max size: {max}")
private String name;
And it's working correctly:
Max size: 50
But now I'd like to move the custom message in a messages.properties file. I set the property this way:
Size=Max size: {max}
But now I'm getting this error:
org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring4.processor.attr.SpringErrorsAttrProcessor' with root cause
java.lang.NumberFormatException: For input string: "max"
It seems the max parameter is null, or something similar...
Why? What am I doing wrong?

In your messages.properties set like below.
Size=Max size {1}
Your field will be like below.
#Size(max=50)
private String name;

Related

How to resolve a message with named parameters from Spring's MessageSource

I have resource bundle with one of the key/value pairs looking like:
my.key=A message specifying min: {min} and max: {max} parameters
It all works well when used with #Length annotation, Thymeleaf and validators. If error conditions are met the message gets resolved and displayed, however if I try to resolve the same message using the MessageSource.getMessage(...) method there's now way I can get this to work.
I tried the following;
messageSource.getMessage("my.key", new Object[] {Map.of("min", 4, "max", 16)}, validLocale);
also
messageSource.getMessage("my.key", new Object[]{"{min:4}", "max:16"}, validLocale);
And a few more things but every time I get IllegalArgumentException caused by NumberFormatException with the message: "can't parse argument number: min"
Will appreciate any suggestions
Your code should work, but you have to modify it slightly
messageSource.getMessage("my.key", new Object[] { 4, 16 }, validLocale);
And change your key to something like
my.key=A message specifying min: {0} and max: {1} parameters
MessageSource doesn't support named arguments (e.g. {min}). min and max in #Length are just attributes -- they have nothing to with the message.properties' placeholders.
#dsp_user
I know very well that if modified as you proposed it the code would work, but the following code has to work too:
#Length(max = 4, min = 16, message = "{my.key}")
private String username;
and it would cease to work if changed to what you suggested.

Get path variable out of HttpMessageNotReadable exception

We have some web services which are being consumed by mobile clients , in which the mobile clients make some request's and we return response to them. Somehow if the client make any invalid request we throw Custom Exceptions .But recently the mobile client has made some request which was out of range for Long variable. The client has different variables for ex ::
{
"accountId":"343"
"Amount":"90909090909090909090"
}
In case of the value for accountId or Amount are made more than 19 digits we get HttpMessageNotReadable exception as the range is out of long value. But from exception i am not able to fetch for which variable the exception has been raised whether for accountId or Amount. From the exception i am getting this information in _path variable but i am not able to fetch it.
And in the path variable i get something like::
[com.Upload["AccountInfo"], com.Info["Account"]]
Does somebody know how to fetch this information.
The following code prints out the field which causes the exception.
InvalidFormatException invalidFormatException = (InvalidFormatException) exception
.getCause();
System.out.println(invalidFormatException.getPath().get(0)
.getFieldName());
#ArunM's answer works as long as the field is in 1st level viz the example given by OP.
But what happens when the field is in nested json? say paymentType has wrong value in the following example?
{
"userType": "CUSTOMER",
"payment": {
"amount": 123456,
"paymentType": "INTERNET_BANKING"
}
}
In the above example, if there's anything wrong with the value of userType, there will be just one element in _path.
But if any value inside the payment is wrong, say for example paymentType, there will be multiple elements in the _path variable. Each element representing the hierarchical attribute.
So for paymentType, _path will have 2 elements as illustrated below:
_path[0].fieldName = "payment"
_path[1].fieldName = "paymentType"
Hence the correct approach is to get the last element in _path as shown below. If needed, we can build the complete path by using all the elements.
InvalidFormatException ifx = (InvalidFormatException) exception.getCause();
System.out.println(ifx.getPath().get(ifx.size() - 1).getFieldName());
This I believe is the right approach to get the invalid attribute name.

Override error messages in BindingResult

I am using Spring MVC 2.5 .
I have fields where numbers should only be the allowed in put. And I get the exact error message on my UI I was looking for . Something like
Failed to convert property value of type [java.lang.String] to required type [java.math.BigDecimal] for property executionThresholdAmount; nested exception is java.lang.NumberFormatException
I don't want to display that kind of message to the user. I do use message.properties file to organize texts to be displayed.
The only thing I need is I wanted to overwrite the error message for specific fields. I couldn't do that but here is the trick I was using for
if(result.hasFieldErrors()){
List<FieldError> bindingErrors=( List<FieldError>)result.getFieldErrors();
BindingResult fieldErrors=new BeanPropertyBindingResult (offerSetting, "offerSetting");
for(FieldError error :bindingErrors ){
String field=error.getField();
fieldErrors.rejectValue(field, "invalid.amount."+field);
}
result=fieldErrors;
#more code
What I am doing is I created BeanPropertyBindingResult which is an implementation of BindingResult and populated the error fields with the message I want and pass the reference to result object so it gets displayed. However, I am now getting both the default messages
like
Failed to convert property value of type [java.lang.String] to required type [java.math.BigDecimal] for property executionThresholdAmount; nested exception is java.lang.NumberFormatException
and also the message I wanted. Something like
"The amount for field price you entered is invalid"
Any better ideas?
Try adding to your messages properties file somethig like this:
typeMismatch.objectClassName.field=Your custom message
In your case:
typeMismatch.offerSetting.amount=The amount for field price you entered is invalid
Works for me :)

Problem in displaying data from database in JSF

i have a problem when i run a page.jsp :
Exception while calling encodeEnd on component : {Component-Path : [Class: javax.faces.component.UIViewRoot,ViewId: /compteListe.jsp][Class: javax.faces.component.html.HtmlDataTable,Id: j_id_jsp_1879226420_1][Class: javax.faces.component.UIColumn,Id: j_id_jsp_1879226420_2][Class: javax.faces.component.html.HtmlOutputText,Id: j_id_jsp_1879226420_4]}
Caused by:
org.apache.jasper.el.JspPropertyNotFoundException - /compteListe.jsp(29,13) '#{l.Identifiant}' Property 'Identifiant' not found on type com.bankonet.bean.Compte
but when i do System.out.println (rs.getString (1));..., it works well and displays data !!
Unless the property name itself actually starts with 2 uppercased characters, the property name in EL needs to start with lowercase, so:
#{l.identifiant}
This requires a public no-arg getter method with name getIdentifiant().
org.apache.jasper.el.JspPropertyNotFoundException - /compteListe.jsp(29,13) '#{l.Identifiant}' Property 'Identifiant' not found on type com.bankonet.bean.Compte
It searches for a Field with name Identifiant in class com.bankonet.bean.Compte with standard setter/getter methods , which it doesn't find and so the error
but when i do System.out.println (rs.getString (1));..., it works well and displays data !!
It doesn't relate to your problem. You need to pass a collection to view to produce view

Bean Validation + Resource Bundle ideas?

Here is what i want to be able to do with bean validation in my JPA entities :
Instead of #NotNull, i would like to do #NotNull(message="keyInMyResourceBundleFile")
I would like also to parameterize the resourceBundle, and i dont know the syntax for it, because it seems to me the message attribute contains only a string.
The parameter itself could be i18n-ed. For example, assuming there's a param attribute for the resourcebundle parameters, in English, #NotNull(message="missing.value", params={"credit card"}) String creditCard; It will be displayed something like this : "Missing required value for field credit card. In Indonesia, it'll be something like "Nilai harus di isi untuk Kartu Kredit. In this example, i cant hardcode the "credit card" because in Indonesia, it's "Kartu Kredit"
Displays the error message defined in the resource bundle on the log file or UI. Im not sure the way on how to do it, should i catch the ConstraintViolationException, get the message, and process the resource bundle by my own code ?
Please share your thoughts on this ?
Thank you !
Regarding 1 + 2
#NotNull(message="{keyInMyResourceBundleFile}")
Curly brackets are the indicator of a parameter substitution
Regarding 3
No idea what you are after. There is no params attribute for #NotNull. I guess you would do
#NotNull(message="{missing.credit.card}")
And of if you place it on another property you would call the key {missing.name}
Regarding 4
The ConstraintViolationException contains the set of *ConstraintViolation*s. Each ConstraintViolation contains the interpolated message as well as the message template. If you want to log it, do it ...

Categories

Resources