Spring MVC @PathVariable with dot (.) is getting truncated
As far as i know this issue appears only for the pathvariable at the end of the requestmapping.
We were able to solve that by defining the regex addon in the requestmapping.
/somepath/{variable:.+}
Spring considers that anything behind the last dot is a file extension such as .json
or .xml
and trucate it to retrieve your parameter.
So if you have /somepath/{variable}
:
/somepath/param
,/somepath/param.json
,/somepath/param.xml
or/somepath/param.anything
will result in a param with valueparam
/somepath/param.value.json
,/somepath/param.value.xml
or/somepath/param.value.anything
will result in a param with valueparam.value
if you change your mapping to /somepath/{variable:.+}
as suggested, any dot, including the last one will be consider as part of your parameter :
/somepath/param
will result in a param with valueparam
/somepath/param.json
will result in a param with valueparam.json
/somepath/param.xml
will result in a param with valueparam.xml
/somepath/param.anything
will result in a param with valueparam.anything
/somepath/param.value.json
will result in a param with valueparam.value.json
- ...
If you don't care of extension recognition, you can disable it by overriding mvc:annotation-driven
automagic :
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> <property name="contentNegotiationManager" ref="contentNegotiationManager"/> <property name="useSuffixPatternMatch" value="false"/></bean>
So, again, if you have /somepath/{variable}
:
/somepath/param
,/somepath/param.json
,/somepath/param.xml
or/somepath/param.anything
will result in a param with valueparam
/somepath/param.value.json
,/somepath/param.value.xml
or/somepath/param.value.anything
will result in a param with valueparam.value
note : the difference from the default config is visible only if you have a mapping like somepath/something.{variable}
. see Resthub project issue
if you want to keep extension management, since Spring 3.2 you can also set the useRegisteredSuffixPatternMatch property of RequestMappingHandlerMapping bean in order to keep suffixPattern recognition activated but limited to registered extension.
Here you define only json and xml extensions :
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> <property name="contentNegotiationManager" ref="contentNegotiationManager"/> <property name="useRegisteredSuffixPatternMatch" value="true"/></bean><bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <property name="favorPathExtension" value="false"/> <property name="favorParameter" value="true"/> <property name="mediaTypes"> <value> json=application/json xml=application/xml </value> </property></bean>
Note that mvc:annotation-driven accepts now a contentNegotiation option to provide a custom bean but the property of RequestMappingHandlerMapping has to be changed to true (default false) (cf. https://jira.springsource.org/browse/SPR-7632).
For that reason, you still have to override the all mvc:annotation-driven configuration. I opened a ticket to Spring to ask for a custom RequestMappingHandlerMapping : https://jira.springsource.org/browse/SPR-11253. Please vote if you are intereted in.
While overriding, be carreful to consider also custom Execution management overriding. Otherwise, all your custom Exception mappings will fail. You will have to reuse messageCoverters with a list bean :
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" /><bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" /><util:list id="messageConverters"> <bean class="your.custom.message.converter.IfAny"></bean> <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean></util:list><bean name="exceptionHandlerExceptionResolver" class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver"> <property name="order" value="0"/> <property name="messageConverters" ref="messageConverters"/></bean><bean name="handlerAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="webBindingInitializer"> <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"> <property name="conversionService" ref="conversionService" /> <property name="validator" ref="validator" /> </bean> </property> <property name="messageConverters" ref="messageConverters"/></bean><bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
I implemented, in the open source project Resthub that I am part of, a set of tests on these subjects : see https://github.com/resthub/resthub-spring-stack/pull/219/files & https://github.com/resthub/resthub-spring-stack/issues/217
Update for Spring 4: since 4.0.1 you can use PathMatchConfigurer
(via your WebMvcConfigurer
), e.g.
@Configurationprotected static class AllResources extends WebMvcConfigurerAdapter { @Override public void configurePathMatch(PathMatchConfigurer matcher) { matcher.setUseRegisteredSuffixPatternMatch(true); }}@Configurationpublic class WebConfig implements WebMvcConfigurer { @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch(false); }}
In xml, it would be (https://jira.spring.io/browse/SPR-10163):
<mvc:annotation-driven> [...] <mvc:path-matching registered-suffixes-only="true"/></mvc:annotation-driven>