<

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

In this short tutorial, we’ll discuss a common problem when working with Spring MVC – when using a Spring @PathVariable with a @RequestMapping to map the end of a request URI that contains a dot, we’ll end up with a partial value in our variable, truncated at the last dot.

In the next sections, we’ll focus on why this happens and how to change this behavior.

For an introduction to Spring MVC, please refer to this article.

2. Unwanted Spring Help

The framework causes this often unwanted behavior because of the way it interprets the path variable.

Specifically, Spring considers that anything behind the last dot is a file extension such as .json or .xml.

As a result, it truncates the value to retrieve the parameter.

Let’s see an example of using path variables, then analyze the result with different possible values:

@RestController
public class CustomController {
    @GetMapping("/example/{firstValue}/{secondValue}")
    public void example(@PathVariable("firstValue") String firstValue,
      @PathVariable("secondValue") String secondValue) {
        // ...  
    }
}

With the above example, let’s consider the next requests and evaluate our variables:

  • the URL example/gallery/link results in evaluating firstValue = “gallery” and secondValue = “link”
  • when using the example/gallery.df/link.ar URL, we’ll have firstValue = “gallery.df” and secondValue = “link”
  • with the example/gallery.df/link.com.ar URL, our variables will be: firstValue = “gallery.df” and secondValue = “link.com”

As we can see, the first variable isn’t affected but the second is always truncated.

3. Solutions

One way to solve this inconvenience is to modify our @PathVariable definition by adding a regex mapping. Thereby any dot, including the last one, will be considered as part of our parameter:

@GetMapping("/example/{firstValue}/{secondValue:.+}")   
public void example(
  @PathVariable("firstValue") String firstValue,
  @PathVariable("secondValue") String secondValue) {
    //...
}

Another way to avoid this issue is by adding a slash at the end of our @PathVariable. This will enclose our second variable protecting it from Spring’s default behavior:

@GetMapping("/example/{firstValue}/{secondValue}/")

The two solutions above apply to a single request mapping that we’re modifying.

If we want to change the behavior at a global MVC level, we can customize the Spring MVC configuration by declaring our own DefaultAnnotationHandlerMapping bean in the application context and setting its useDefaultSuffixPattern property to false: 

@Configuration
public class CustomWebConfiguration extends WebMvcConfigurationSupport {
    
    @Bean
    public RequestMappingHandlerMapping 
      requestMappingHandlerMapping() {
 
        RequestMappingHandlerMapping handlerMapping
          = super.requestMappingHandlerMapping();
        handlerMapping.setUseSuffixPatternMatch(false);
        return handlerMapping;
    }
}

We have to remember that this approach affects all URLs.

With these 3 options, we’ ll obtain the same result: when calling the example/gallery.df/link.com.ar URL, our secondValue variable will be evaluated to “link.com.ar”, which is what we want.

4. Conclusion

In this quick writeup, we’ve explored different ways to solve a common problem when working with @PathVariable and @RequestMapping in Spring MVC and the source of this issue.

As always, the full source code of the examples is available over on GitHub.

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE LESSONS