I am in the process of upgrading an application to Spring 3.1 during this slow Christmas time. Most of the issues found have been relatively easy to resolve except one.
The app is basically a web services provider using json but we also have a few web pages (controllers and jsp) to see internal state for debugging/testing purposes. These are generated using JSP and are behind the security layer with a login page. Some of the jsp's are in a subdirectory under WEB-INF/jsp.
Calling a url "http://<server>/dashboard" which calls the dashboard controller which returns a ModelAndView (ModelAndView("test/dashboard", context)) object to direct the call to the jsp page with a valid context. In spring 3.0.7 this worked fine but in 3.1 it fails. It returns a 404 error and the log shows "PWC6117: File "<edited>\classes\webapp\WEB-INF\jsp\dashboard.jsp" not found. The page is actually in WEB-INF\jsp\test\dashboard.jsp as the ModelAndView specifies.
After a lot of tracing through the spring code in 3.0.7 and 3.1, for the DispatcherServlet.doDispatch() method (the same code between 3.0.7 and 3.1)
For 3.1 the HandlerAdapter returned is an instance of RequestMappingHandlerAdaptor, where mappedHandler.getHandler() returns an org.springframework.web.method.HandlerMethod instance (which contains a ref to the DashboardController). When handle(...) is called it returns a ModelAndView.Code:HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); ... // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); // Do we need view name translation? if (mv != null && !mv.hasView()) { mv.setViewName(getDefaultViewName(request)); }
ModelAndView: materialized View is [null]; model is {modelAndView=ModelAndView: reference to view with name 'test/dashboard'; model is {accessToken=false, ...
Since the wrapper model and view name is null the if condition is called and the name is reset back to what the original request url was, for the controller '/dashboard'. And no such jsp page exists with that name in the base jsp path. The ModelAndView returned from the controller method seems to be ignored.
For 3.0.7 the HandlerAdapter returned is an instance of AnnotationMethodHandlerAdaptor, where mappedHandler.getHandler() returns a DashBoardController instance. When handle(...) is called it returns a ModelAndView.
ModelAndView: reference to view with name 'test/dashboard'; model is {accessToken=false, ...
The returned model appears as expected and the jsp page is invoked at 'WEB-INF/jsp/test/dashboard.jsp'.
I realise that the HandlerMethod instance is new in 3.1 (to act as a proxy) but the AnnotationMethodHandlerAdaptor does not seem to work on a HandlerMethod instance or delegate the method annotation identification for it's enclosed member handler (in this case DashboardController). And the RequestMappingHandlerAdaptor seems to ignore the ModelAndView returned from the controller by wrapping it with another ModelAndView and hence returns the default request url.
Am I missing something here as far as new configuration goes? Why in 3.1 is the ModelAndView returned from handle(...) not the same ModelAndView instance returned from the DashboardController handler method. Either there is an issue identifying the correct HandlerAdaptor to use given a HandlerMethod instance or the handle() method is wrapping the ModelAndView unnecessarily.
Or is there another problem I am not seeing? Any thoughts or assistance gladly accepted.
(I suppose the simple answer is to move the jsp from the subdirectory to the main jsp directory but I would like to understand why this has stopped working.)


Reply With Quote
