Background
@RequestMapping(value="/home/{name}", method = RequestMethod.GET) public String welcome(Model model, @PathVariable(value="name") String name, @RequestParam(value="surname") String surname) { model.addAttribute("test", "TestValue"); System.out.println("Name : " + name); System.out.println("Surname : " + surname); return "welcome"; }
This controller method basically expects a URL like
- http://localhost:8080/WebProject/home/aniket?surname=thakur
Here you cannot have name or surname blank. If you do you will get an error. So URLs like -
- http://localhost:8080/WebProject/home?surname=thakur OR
You will get HTTP Status 404 - Requested Resource is not available - http://localhost:8080/WebProject/home/aniket
You will get - HTTP Status 400 - Required String parameter 'surname' is not present
Only URL that will work as mentioned above is -
- http://localhost:8080/WebProject/home/aniket?surname=thakur
Name : aniket
Surname : thakur
However you can make @RequestParam option. Spring provides you this functionality. All you have to do is set it's required property as false i.e
- @RequestParam(value="surname", required=false) String surname
- http://localhost:8080/WebProject/home/aniket
Name : aniket
Surname : null
However there is no such parameter in @PathVariable. So you cannot truly make it optional. However there are alternative and we will look at them now.
Making @PathVariable optional in Spring MVC
There are two way in which you can work -
- Provide two paths in value - One with path param and one without. In Arguments take map of path params and check for null.
@RequestMapping(value={"/home/{name}","/home"}, method = RequestMethod.GET) public String welcome(@PathVariable Map<String, String> pathVariablesMap) { if (pathVariablesMap.containsKey("name")) { //corresponds to path "/home/{name}" System.out.println("With Name : " + pathVariablesMap.get("name")); } else { //corresponds to path "/home" System.out.println("With No Name"); } return "welcome"; }
Here you are essentially saying this controller will map to both URLS - "/home/{name}" and "/home" and if you do get name in pathparams map then the URL was "/home/{name}" else it was "/home".
And now if you hit http://localhost:8080/WebProject/home/aniket you should get output as - "With Name : aniket" and if you hit http://localhost:8080/WebProject/home you should see output - "With No Name". - Another way is to use java.util.Optional provided by Java8. So if you are using Spring 4.1 and Java 8 you can use java.util.Optional which is supported in @RequestParam, @PathVariable, @RequestHeader and @MatrixVariable in Spring MVC -
@RequestMapping(value="/home/{name}", method = RequestMethod.GET) public String welcome(@PathVariable Optional<String> name) { if (name.get() != null) { //corresponds to path "/home/{name}" System.out.println("With Name : " + name.get()); } else { //corresponds to path "/home" System.out.println("With No Name"); } return "welcome"; }
Repeat same test as point 1. You should get same result. This is just another alternate way.
So as we have seen pathvariables cannot truly be null but there are workarounds. This case should not typically arise as it is poor design. You should always have some value in path param. If you are certain it can be null better make it a @RequestPram and use requiref=false.