17

I want to pass in my parameters to my web service in the format:

http://.../greetings/neil/1

Rather than

http://.../greetings?name=neil&id=1

So I changed my code from (note, I've only included the first parameter in the code):

@RequestMapping("/greeting")
public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
    return new Greeting(counter.incrementAndGet(),
                        String.format(template, name));
}

to:

@RequestMapping
public Greeting greeting(@PathVariable String name) {
    return new Greeting(counter.incrementAndGet(),
                        String.format(template, name));
}

which works, however I do not know how to add default values to @PathVariable so that for example:

http://.../greetings/

http://.../greetings/neil/

would work as it does with query parameters.

How do I do this? I thought maybe it would pass null, but it just generates a page error.

I guess the answer might be to add multiple overloads, but that sounds a bit messy.

thanks.

thanks.

Neil Walker
  • 6,400
  • 14
  • 57
  • 86
  • 7
    Possible duplicate of [Spring MVC: how to indicate whether a path variable is required or not?](http://stackoverflow.com/questions/17821731/spring-mvc-how-to-indicate-whether-a-path-variable-is-required-or-not) – Arpit Aggarwal Jan 12 '17 at 18:44

3 Answers3

26

Spring 5 / Spring Boot 2 example:

@RequestMapping({"/greeting-blocking/{name}","/greeting-blocking/"})
public ResponseEntity<User> greetingBlocking(
        @PathVariable(name = "name", required = false) String name) {
    String username = StringUtils.isEmpty(name) ? "anonymous" : name;
    return ResponseEntity.ok().body(User.create(username));
}

@RequestMapping({"/greeting-reactive/{name}","/greeting-reactive/"})
public Mono<ResponseEntity<User>> greetingReactive(
        @PathVariable(name = "name", required = false) String name) {
    String username = StringUtils.isEmpty(name) ? "anonymous" : name;
    return userReactiveRepo.findByName(username).map(user -> ResponseEntity.ok().body(user));
}
kinjelom
  • 6,105
  • 3
  • 35
  • 61
14

How about the following way? I am using java.util.Optional class which acts as a wrapper over objects that can be null or not-null.

@RequestMapping
public Greeting greeting(@PathVariable Optional<String> name) {
    String newName = "";  
    if (name.isPresent()) {
        newName = name.get()   //returns the id
    }
    return new Greeting(counter.incrementAndGet(),
                        String.format(template, newName));
}

Alternately, you can define two separate request mapping handlers:

@RequestMapping("/greeting")
public Greeting defaultGreeting()

AND

@RequestMapping("/greeting/{name}")
public Greeting withNameGreeting(@PathVariable String name)
VHS
  • 9,534
  • 3
  • 19
  • 43
  • 1
    The second method I already did that, but wanted something like your first method. However, I can't get it to work when nothing is supplied, i.e. /greeting. Do I need to add anything to the class? the only way I can get it to do anything is by adding: @RequestMapping("/greeting/{name}") – Neil Walker Jan 12 '17 at 19:07
  • Are you saying that when you use `@RequestMapping("/greeting/{name}")` and then invoke the URL /greeting, it doesn't work? What exception does Spring throw? – VHS Jan 12 '17 at 19:33
2

One liner

@RequestMapping
public Greeting greeting(@PathVariable Optional<String> name) {
    return new Greeting(counter.incrementAndGet(),
                        String.format(template, name.orElse("World")));
}
Cililing
  • 4,303
  • 1
  • 17
  • 35
Emmanuel Osimosu
  • 5,625
  • 2
  • 38
  • 39