Open spring-projects-issues opened 6 years ago
I've updated the description with the description from the Boot ticket.
This is Java issue which throws java.lang.IllegalArgumentException: unknown format type: 3
. Spring core silently proceeding with the raw message in this case. org.springframework.context.support.MessageSourceSupport#formatMessage
MessageFormat messageFormat = new MessageFormat("{0} must match \"\\d{1,3}\"");
messageFormat.format(new Object[] {"valid"});
@jayanth1007, thanks for investigating this and providing your findings.
You're completely right: executing the following...
public static void main(String[] args) {
new MessageFormat("{0} must match \"\\d{1,3}\"");
}
... results in:
Exception in thread "main" java.lang.IllegalArgumentException: unknown format type: 3
at java.text.MessageFormat.makeFormat(MessageFormat.java:1526)
at java.text.MessageFormat.applyPattern(MessageFormat.java:479)
at java.text.MessageFormat.<init>(MessageFormat.java:362)
So, the MessageFormat
constructor throws an exception immediately.
The above mentioned IllegalArgumentException
is because of that MessageFormat
tried to parse {1,3}
as a FormatElement
with the format of { ArgumentIndex , FormatType }
, which is described in the java doc of MessageFormat
.
Currently, the original message in @yoshikawaa's example is:
{0} must match "{regexp}".
it would be interpolated by a MessageInterpolator
as:
{0} must match "\d{1,3}".
When MessageFormat
sees it, it would start parsing {1,3}
and then throw an exception.
I suggest that we should use single quotes to quote the "non-FormatElement" part of the message when interpolating the message, so that it won't be parsed by MessageFormat
. For example, we can provide a custom MessageInterpolator
which interpolate the message as:
{0} must match "'\d{1,3}'".
so that it can be successfully formatted by MessageFormat.format()
as:
invalid must match "\d{1,3}".
One can test the above behavior by the code snippet:
public static void main(String[] args) {
MessageFormat messageFormat = new MessageFormat("{0} must match \"'\\d{1,3}'\"");
String formattedString = messageFormat.format(new Object[] {"invalid"});
System.out.println(formattedString); // prints "invalid must match "\d{1,3}"."
}
Here is a demonstration of how to use a custom MessageInterpolator
to fix the problem: https://github.com/yoshikawaa/spring-boot-pattern-demo/pull/1
However, I am not very sure about where to put the custom MessageInterpolator
; should I put it in spring-context
, spring-boot
, or even hibernate-validator
?
I guess this issue is related to https://github.com/spring-projects/spring-framework/issues/18167.
Hi, may i know this problem was resolved or not? And another two issues was occurred:
MessageFormat.format("{0} is a number, {1} is a number, but i want to show single quote \"'\"", 1, 2) //print 1 is a number, 2 is a number, but i want to show single quote ""
Single quote was missing, what i want to display is:
1 is a number, 2 is a number, but i want to show single quote "'"
However, upper problems can be fixed by adding "'" before single quote as below:
MessageFormat.format("{0} is a number, {1} is a number, but i want to show single quote \"''\"", 1, 2) print 1 is a number, 2 is a number, but i want to show single quote "'"
And PR is needed or not?
yoshikawaa opened SPR-17217 and commented
Application
Spring Boot Web MVC Application Spring Boot 2.0.4.RELEASE Sample : https://github.com/yoshikawaa/spring-boot-pattern-demo
Problem
There are cases where
@Pattern
error message{0}
is not resolved.My validation is that if a range of digits is used in a regular expression, the mechanism for resolving {0} does not work properly.
When logging
BindingResult
with Controller, you can see thatLocalValidatorFactoryBean
(Hibernate Validator) resolves message variable{regexp}
beforehand. After that, when Spring MVC resolve the message, it is considered that the regular expression in the message is obstructing resolution of{0}
.Affects: 5.0.8
Reference URL: https://github.com/spring-projects/spring-boot/issues/14163