Root cause: thanks to Phil Webb for pointing out that the issue is with the way the query string is parsed. Given "q=1USD=?EUR", the value of "q" is "1USD=?EUR", which contains a reserved character "=". Ideally, for such cases, where reserved characters are expected, it is recommend to use a URI variable:
This ensures the URI can be parsed correctly and the value encoded so the resulting URI would be:
Spring 3.0 vs 3.1: in Spring 3.0, the UriTemplate encoded the query string as a whole without attempting to parse it, which meant that query parameters could not be fully encoded. Spring 3.1 introduced UriComponentsBuilder (also used inside UriTemplate), which does parse the query string and fully encodes query parameter names and values. However, when the query string contains reserved characters there is ambiguity in the parsing.
Fix: I've updated the regular expression used to parse query params to give more intuitive behavior in some common cases and to fix the regression. Below is the comment from commit 072114.
Improve regex for parsing query params
Previously UriComponentsBuilder used a regular expression for parsing
query name-value pairs where both name and value were expected to not
contain neither '&', not '='. The idea is that the presence of reserved
characters makes it impossible to guess correctly how to parse the
query string (e.g. a=b&c).
This change relaxes the constraint on query param values, allowing them
to contain '='. In effect '&' is the ultimate separator of name-value
pairs, and any '=' in values is ignored. For example "q=1USD=?EUR" is
interpreted as "q equals '1USD=?EUR'".