Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC Annotated Controller Interface with @PathVariable

Is there any reason not to map Controllers as interfaces?

In all the examples and questions I see surrounding controllers, all are concrete classes. Is there a reason for this? I would like to separate the request mappings from the implementation. I hit a wall though when I tried to get a @PathVariable as a parameter in my concrete class.

My Controller interface looks like this:

@Controller @RequestMapping("/services/goal/") public interface GoalService {      @RequestMapping("options/")     @ResponseBody     Map<String, Long> getGoals();      @RequestMapping(value = "{id}/", method = RequestMethod.DELETE)     @ResponseBody     void removeGoal(@PathVariable String id);  } 

And the implementing class:

@Component public class GoalServiceImpl implements GoalService {      /* init code */      public Map<String, Long> getGoals() {         /* method code */         return map;     }      public void removeGoal(String id) {         Goal goal = goalDao.findByPrimaryKey(Long.parseLong(id));         goalDao.remove(goal);     }  } 

The getGoals() method works great; the removeGoal(String id) throws an exception

ExceptionHandlerExceptionResolver - Resolving exception from handler [public void     todo.webapp.controllers.services.GoalServiceImpl.removeGoal(java.lang.String)]:      org.springframework.web.bind.MissingServletRequestParameterException: Required      String parameter 'id' is not present 

If I add the @PathVariable annotation to the concrete class everything works as expected, but why should i have to re-declare this in the concrete class? Shouldn't it be handled by whatever has the @Controller annotation?

like image 238
willscripted Avatar asked Nov 03 '11 22:11

willscripted


People also ask

What is the purpose of @PathVariable annotation in Spring MVC?

@PathVariable is a Spring annotation which indicates that a method parameter should be bound to a URI template variable. If the method parameter is Map<String, String> then the map is populated with all path variable names and values. It has the following optional elements: name - name of the path variable to bind to.

Can we use @RequestParam and @PathVariable together?

The @PathVariable annotation is used for data passed in the URI (e.g. RESTful web services) while @RequestParam is used to extract the data found in query parameters. These annotations can be mixed together inside the same controller. @PathParam is a JAX-RS annotation that is equivalent to @PathVariable in Spring.

What is the use of @PathVariable annotation in Spring rest?

The @PathVariable annotation is used to extract the value of the template variables and assign their value to a method variable. A Spring controller method to process above example is shown below; @RequestMapping("/users/{userid}", method=RequestMethod.

What is the use of @PathVariable annotation?

The @PathVariable annotation is used to extract the value from the URI. It is most suitable for the RESTful web service where the URL contains some value. Spring MVC allows us to use multiple @PathVariable annotations in the same method. A path variable is a critical part of creating rest resources.


1 Answers

Apparently, when a request pattern is mapped to a method via the @RequestMapping annotation, it is mapped to to the concrete method implementation. So a request that matches the declaration will invoke GoalServiceImpl.removeGoal() directly rather than the method that originally declared the @RequestMapping ie GoalService.removeGoal().

Since an annotation on an interface, interface method, or interface method parameter does not carry over to the implementation there is no way for Spring MVC to recognize this as a @PathVariable unless the implementing class declares it explicitly. Without it, any AOP advice that targets @PathVariable parameters will not be executed.

like image 169
willscripted Avatar answered Sep 25 '22 05:09

willscripted