How to Prevent Parameter Binding from Interpreting Commas in Spring 3.0.5

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

I've tested your code: it's unbelievable, but I can't reproduce your issue. I've 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've tested my code within tomcat 7.0.8; when I type http://localhost:8080/testweb/test/params.htm?fq=foo,bar I'm able to read in my log file this line: DEBUG fq = foo,bar.
What are the the differences from my code to yours? Am I doing something wrong?
I'd like to help you, so if you have any doubts or if I can do some other tests for you, it will be a pleasure.

UPDATE / SOLUTION
With your code I've reproduced the issue; you have the tag <mvc:annotation-driven /> in your dispatcher servlet configuration, so you silently use a default conversion service, instance of FormattingConversionService, which contains a default converter from String to String[] that uses comma as separator.
You have to use a different conversion service bean containing your own converter from String to String[]. You should use a different separator, I've choosed to use ";" because it's the separator commonly used into 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 have to specify this conversion service bean 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 issue has fixed, now you should check for any side effects. I hope you don't need in your application the original conversion from String to String[] (with comma as separator). ;-)

How to prevent Spring MVC from interpreting commas when converting to a Collection in Spring Boot?

You can remove the StringToCollectionConverter and replace it with your own in WebMvcConfigurerAdapter.addFormatters(FormatterRegistry registry) method:

Something like this:

@Configuration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.removeConvertible(String.class,Collection.class);
registry.addConverter(String.class,Collection.class,myConverter);
}
}

Modify Spring MVC Request to List Parameter Binding to Not Separate on Commas

The conversion seems to happen in:

org.springframework.core.convert.support.StringToCollectionConverter

which must be a defult converter registered by the framework.

You can use an @InitBinder method in a controller or a Controller Advice to register converters however I am not sure how you override or disable this default converter.

The simplest thing to do then is just to fall back to accessing the param directly from the HttpServletRequest:

 @Controller
public class TestController {

@RequestMapping("/test")
public String test(@RequestParam("names") List<String> names, HttpServletRequest request) {

//1
System.out.println(request.getParameterValues("names").length);
System.out.println(Arrays.toString(request.getParameterValues("names")));

//2
System.out.println(names.size());
System.out.println(names);

return null;
}
}

After additional experimentation, you can disable the invocation of the framework's StringToCollectionConverter in Spring Boot by explicitly removing the conversion from String.class to Collection.class from the GenericConversionService:

@Autowired
void conversionService(GenericConversionService genericConversionService) {
List<String> names = genericConversionService.convert("Ed, Al", List.class);
System.out.println(names.size()); // 2

genericConversionService.removeConvertible(String.class, Collection.class);

names = genericConversionService.convert("Ed, Al", List.class);
System.out.println(names.size()); // 1

}

How to disable spring boot parameter split

I find the solution.
To override a default conversion we must add a new one. If we remove the old one only it doesn't work.

The correct (example) code should be:

@Configuration
public class MvcConfig implements WebMvcConfigurer {

@Override
public void addFormatters(FormatterRegistry registry) {
registry.removeConvertible(String.class, String[].class);
registry.addConverter(String.class, String[].class, noCommaSplitStringToArrayConverter());
}

@Bean
public Converter<String, String[]> noCommaSplitStringToArrayConverter() {
return new Converter<String, String[]>() {
@Override
public String[] convert(String source) {
String[] arrayWithOneElement = {source};
return arrayWithOneElement;
}
};
}
}

This way any controller like the one in the main question will not split parameters values:

  • [...]/countphrases?phrase=a,b will return 1 (and fq=["a,b"])
  • [...]/countphrases?phrase=a,b&phrase=c,d will return 2 (and fq=["a,b", "c,d"])

Binding multiple select where option values may contain commas in Spring 3

I believe this thread is related to your issue: How to prevent parameter binding from interpreting commas in Spring 3.0.5?. This Spring issue may also be helpful: https://jira.springsource.org/browse/SPR-7963

The solution provided at https://stackoverflow.com/a/5239841/1259928, which details how to create a new conversion service which uses a different string separator and wiring it into Spring config should do the trick.

Encoded Comma in URL is read as List in Spring

You can set your Delimiter. The comma is just the default one used in org.springframework.boot.convert.DelimitedStringToCollectionConverter when it isn't set. If you wish, you can disable the Delimiter completely. For your code, it would look like this:

import org.springframework.boot.convert.Delimiter;

@RequestMapping(value = "/route", method = RequestMethod.GET)
public Object thisIsTheMethod(@Delimiter(Delimiter.None) @RequestParam(value = "value", required = false) List<String> values) {
return OtherClass.doTheThing(values);
}

Spring ModelAttribute correct parsing

I did some investigation and figured out that for first request value=John%2CBill%2CAlex Spring using org.springframework.format.supportDefaultFormattingConversionService class which under the hood has org.springframework.core.convert.support.StringToArrayConverter whose convert() method split your string by to array using comma as a separator.

You have 2 ways to resolve this issue:

  1. Use ; instead of , as separator for you value (value=John;Bill;Alex)
  2. Use different conversion service bean containing your own converter from String to String[]. For more details look at this answer

How to escape commas in environment-variables mapped to lists in Spring configuration classes

You cannot escape comma for list in spring boot , I'm afraid you will have to think of alternative way to load those environment variables



Related Topics



Leave a reply



Submit