Skip to content

Allow @PathVariable to be optional [SPR-14646] #19212

@spring-projects-issues

Description

@spring-projects-issues

Ulrich Hecht opened SPR-14646 and commented

@PathVariable's named-value-method-argument-resolver (PathVariableMethodArgumentResolver) defines it always as 'required'. In general this makes sense, because if you use @PathVariable then the path variable is expected to be available in the @RequestMapping's path value.

But consider the usage of @PathVariable in @ModelAttribute annotated methods. Those methods are called for all handlers and not all handlers provide the same path variables.

In my case I have a controller in which 4 of 5 methods provide a specific path variable. In order to avoid duplicate code I collect view variables in @ModelAttribute-methods.

This is, how it would look like if @PathVariable had a "required"-attribute:

@RequestMapping("/activity-recordings")
public String getActivityRecordingsAction(/*...*/) { /* This method doesn't have and need path variables */ }

@RequestMapping("/activity-recordings/{purchasePositionNumber}-{index}")
public String getActivityRecordingAction(/*...*/) { /* ... */ }

@PostMapping("/activity-recordings/{purchasePositionNumber}-{index}")
public String updateActivityRecordingAction(/*...*/) { /* ... */ }

@RequestMapping("/activity-recordings/{purchasePositionNumber}-new")
public String newActivityRecordingAction(/*...*/) { /* ... */ }

@PostMapping("/activity-recordings/{purchasePositionNumber}-new")
public String addActivityRecordingAction(/*...*/) { /* ... */ }

@ModelAttribute("activityRecordingPriceLimit")
public Double getActivityRecordingPriceLimit(@PathVariable(name = "purchasePositionNumber", required = "false") String purchasePositionNumber) {
   if (purchasePositionNumber == null) return null;
   /* Some code calculating the value. I don't want to duplicate it 4 times */
}

/* Lots of other @ModelAttribute methods. If I cannot use them I will need to have a block of multiple "modelMap.put(...)" lines that I need to duplicate in the last 4 request handlers */

At the moment, this code will throw a MissingPathVariableException when the first handler is called. My workaround is to define the @ModelAttribute method's argument as Map:

@ModelAttribute("activityRecordingPriceLimit")
public Double getActivityRecordingPriceLimit(@PathVariable Map<String, String> pathVariableMap) {
/* Look up required path variable in the map */
}

However, I don't like this solution.


Affects: 4.3.2

Issue Links:

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions