How to prevent parameter binding from interpreting commas in Spring 3.0.5?

Consider the following controller method:

@RequestMapping(value = "/test", method = RequestMethod.GET) public void test(@RequestParam(value = "fq", required = false) String[] filterQuery) { logger.debug(fq = " + StringUtils.join(filterQuery, "|")); } 

Here is the result for different fq combinations:

  • /test?fq=foo leads to fq = foo
  • /test?fq=foo&fq=bar leads to fq = foo|bar
  • /test?fq=foo,bar leads to fq = foo|bar
  • /test?fq=foo,bar&fq=bash leads to fq = foo,bar|bash
  • /test?fq=foo,bar&fq= result fq = foo,bar|

Example 3 is a problem. I expect (want / need) its output fq = foo,bar .

I tried to escape the comma using \ and use %3C , but niether worked.

If I look at the version of the HttpServletRequest object:

 String[] fqs = request.getParameterValues("fq"); logger.debug(fqs = " + StringUtils.join(fqs, "|")); 

It prints the expected result: fqs = foo,bar . So the "problem" is related to Spring data binding.

I could bypass the Spring binding and use the HttpServletRequest , but I really don't want to, because I use bean support in my real code (the same thing happens) and don't want to re-implement the binding functionality. I hope someone can provide an easy way to prevent this behavior through escaping or some other mechanism.

TIA

UPDATE:. I posted this Q on Twitter and got a response saying the expected output from Spring 3.0.4.RELEASE . I have confirmed that this is so, and therefore this is a temporary solution. I will talk about this as a bug in the Spring JIRA system. If someone can provide work or fix using 3.0.5, I will accept their answer.

+46
java spring spring-mvc data-binding
Feb 15 2018-11-11T00:
source share
5 answers

I checked your code: this is unbelievable, but I cannot reproduce your problem. I downloaded the latest version of spring (3.0.5), this is my controller:

 package test; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping("/test/**") public class MyController { private static final Logger logger = Logger.getLogger(MyController.class); @RequestMapping(value = "/test/params", method = RequestMethod.GET) public void test(SearchRequestParams requestParams, BindingResult result) { logger.debug("fq = " + StringUtils.join(requestParams.getFq(), "|")); } } 

this is my SearchRequestParams class:

 package test; public class SearchRequestParams { private String[] fq; public String[] getFq() { return fq; } public void setFq(String[] fq) { this.fq = fq; } } 

and this is my simple spring configuration:

 <bean id="urlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> <bean class="test.MyController" /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/jsp/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> 

I tested my code in tomcat 7.0.8; when I type http://localhost:8080/testweb/test/params.htm?fq=foo,bar , I can read this line in my log file: DEBUG fq = foo,bar . What are the differences from my code? Am I doing something wrong? I would like to help you, so if you have any doubts or I can do some other tests for you, it will be nice.

UPDATE / DECISION
With your code, I reproduced the problem; you have the <mvc:annotation-driven /> in the dispatcher servlet configuration, so you quietly use the default conversion service, an instance of FormattingConversionService , which contains the default converter from String to String[] , which uses a comma as a separator. You must use another bean conversion service containing your own converter from String to String[] . You must use a different delimiter, I chose to use ";" because this is the separator commonly used in the query string ("? first = 1; second = 2; third = 3"):

 import org.springframework.core.convert.converter.Converter; import org.springframework.util.StringUtils; public class CustomStringToArrayConverter implements Converter<String, String[]>{ @Override public String[] convert(String source) { return StringUtils.delimitedListToStringArray(source, ";"); } } 

Then you must specify this bean conversion service in your configuration:

 <mvc:annotation-driven conversion-service="conversionService" /> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <list> <bean class="au.org.ala.testspringbinding.CustomStringToArrayConverter" /> </list> </property> </bean> 

The problem is fixed, now you should check for any side effects. I hope you don’t need the original conversion from String to String[] (with a comma as a separator) in your application. ;-)

+28
Mar 08 2018-11-11T00:
source share

I found the most elegant and shortest way for me - add @InitBinder to @Controller :

 @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(String[].class, new StringArrayPropertyEditor(null)); } 

It converts String to String [] without using a null param, with the Spring class org.springframework.beans.propertyeditors.StringArrayPropertyEditor. If someone from the same project uses the new default conversion method, this will be fine.

+18
Dec 04 '13 at 12:26
source share

As Philip Potter suggested, I am posting an β€œupdate” to my question as an answer, as it might have been easy to miss ...

A downward deviation from Spring 3.0.5.RELEASE to 3.0.4.RELEASE is fixed when using the @RequestParam annotation, assuming this is a bug with 3.0.5.

However, it does not fix the related problem when binding to the bean support form - this is what I have in my webapp. I tested the whole version up to 3.0.0.RELEASE and got the same result ( /test?fq=foo,bar produces fq = foo|bar ).

eg.

 @RequestMapping(value = "/test", method = RequestMethod.GET) public void test(SearchRequestParams requestParams, BindingResult result) { logger.debug("fq = " + StringUtils.join(requestParams.getFq(), "|")); } 

where SearchRequestParams contains the String[] fq field.

If anyone has a fix, I will gladly accept their answer.

+4
Mar 06 2018-11-11T00:
source share

javanna has already indicated the correct reason. I just wanted to point out that you can also completely remove StringToArrayConverter as shown here , and.

+3
Nov 20 '12 at 21:20
source share

Hack it, but you thought you were passing your parameters limited to '-'

 /test?fq=foo-bar results in fq = foo-bar /test?fq=foo-bar&fq=bash results in fq = foo-bar|bash 

Or any other delimiter, perhaps ~, or !, or ^, or

0
Mar 07
source share



All Articles