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?
Apparently, when a request pattern is mapped to a method via the
@RequestMappingannotation, it is mapped to to the concrete method implementation. So a request that matches the declaration will invokeGoalServiceImpl.removeGoal()directly rather than the method that originally declared the@RequestMappingieGoalService.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
@PathVariableunless the implementing class declares it explicitly. Without it, any AOP advice that targets@PathVariableparameters will not be executed.