Spring MVC @PathVariable getting truncated Spring MVC @PathVariable getting truncated java java

Spring MVC @PathVariable getting truncated


Try a regular expression for the @RequestMapping argument:

RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName:.+}")


This is probably closely related to SPR-6164. Briefly, the framework tries to apply some smarts to the URI interpretation, removing what it thinks are file extensions. This would have the effect of turning blah2010.08.19-02:25:47 into blah2010.08, since it thinks the .19-02:25:47 is a file extension.

As described in the linked issue, you can disable this behaviour by declaring your own DefaultAnnotationHandlerMapping bean in the app context, and setting its useDefaultSuffixPattern property to false. This will override the default behaviour, and stop it molesting your data.


Spring considers that anything behind the last dot is a file extension such as .jsonor .xml and truncate it to retrieve your parameter.

So if you have /{blahName}:

  • /param, /param.json, /param.xml or /param.anything will result in a param with value param
  • /param.value.json, /param.value.xml or /param.value.anything will result in a param with value param.value

If you change your mapping to /{blahName:.+} as suggested, any dot, including the last one, will be considered as part of your parameter:

  • /param will result in a param with value param
  • /param.json will result in a param with value param.json
  • /param.xml will result in a param with value param.xml
  • /param.anything will result in a param with value param.anything
  • /param.value.json will result in a param with value param.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 /{blahName}:

  • /param, /param.json, /param.xml or /param.anything will result in a param with value param
  • /param.value.json, /param.value.xml or /param.value.anything will result in a param with value param.value

Note: the difference from the default config is visible only if you have a mapping like /something.{blahName}. 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 all the 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 interested in.

While overriding, be careful 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 and https://github.com/resthub/resthub-spring-stack/issues/217