|
#1
|
|||
|
|||
|
Its been a long time since I have worked with Spring's MVC layer, or with IoC in general, but this seems like a common problem.
There are some templating utilities as well as some common configuration that I always want stuffed in the ModelAndView. Is there any easy way to wire this with Spring? I have been attempting to just extend ModelAndView, however, there are many final methods in the Spring framework that cannot be overridden. |
|
#2
|
|||
|
|||
|
One method that we have used with Velocity is to have a 'defaultModel' to return with the ModelAndView.
Code:
Map model = getDefaultModel();
...
public Map getDefaultModel ( ) {
Map model = new HashMap();
model.put( "dateTool", new DateTool() );
model.put( "esc", new EscapeTool() );
model.put( "number", new NumberTool() );
return model;
}
How that helps, Steve O |
|
#3
|
|||
|
|||
|
Steveo,
Thanks for the response. The same thing occured to me, but if a developer wants to consctruct a different ModelAndView and then get to the template only to realize they are missing objects? I am looking for something transparent to the caller. |
|
#4
|
|||
|
|||
|
Hi Johnhup,
If you are using the new 2.5 styled controllers then there are quite a few ways to have common reference data added to the model using the @ModelAttribute annotation. If you are using the 2.0 controllers and the ModelAndView paradigm then there are still some good options available, but they tend to be less flexible First off, you could create a bean which you can inject into your controllers which includes a 'getCommonModelAndView' method. This is simple and easy and flexible as all controller types can use it, 2.0 and 2.5. Another option is to extend a commonly used class, say SimpleFormController, and override referenceData or add a new method (like above), but this is not flexible as it will only apply to one controller type. Another way is to create an interceptor which implements postHandle and adds the common reference data to the ModelAndView. This is nice as it is separate from the controllers and works only after processing has been accomplished. Although, its important to note that it will not fire if an exception occurs during handling as the postHandle processing is skipped. If you are using the 2.5 styled controllers you can create a super class which has a @ModelAttribute method which all controllers inherit, eg. Code:
@ModelAttribute
public void commonModelData(ModelMap modelMap){
modelMap.addAttribute("stuff", "stuff");
}
I hope this helps (and makes sense) Josh |
|
#5
|
|||
|
|||
|
Quote:
I have been working with programatic frameworks like Pico for a while now so its hard to get my head around this again. I gotta say I really miss pico's auto-wiring constructor injection. |
|
#6
|
|||
|
|||
|
Hi John,
Spring has auto-wiring as well, you just have to tell the bean definition that you want to use it. Sorry, can I just confirm, you want to use an interceptor ? if so, why do you need to create a controller super class ? Josh |
|
#7
|
|||
|
|||
|
I have read that Spring also has autowiring but sometimes there are ambiguous names due the 'targets' as the other engineer has called them which are proxy classes.
Now I see what you mean regarding the Post Handlers. Let me see if I get you correctly. If I create a class that implements any of those handlers then Spring will call them before rendering the request? |
|
#8
|
|||
|
|||
|
Hi John,
I need to make an amendment to my earlier post, do not use the WebRequestInterceptor as its postHandle method does not allow you to check the view because only the ModelMap is available for use. Instead use the HandlerInterceptor interface and implement the postHandle method. Check if the view exists and if it isn't of type RedirectView and the viewname doesn't start with "redirect:", add the reference data. eg. (sorry if its a bit messy) Code:
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
boolean isRedirectView = modelAndView.getView() instanceof RedirectView;
boolean isViewObject = modelAndView.getView() == null;
// if the view name is null then set a default value of true
boolean viewNameStartsWithRedirect = (modelAndView.getViewName() == null ? true : modelAndView.getViewName().startsWith(UrlBasedViewResolver.REDIRECT_URL_PREFIX));
if(modelAndView.hasView() && (
( isViewObject && !isRedirectView) ||
(!isViewObject && !viewNameStartsWithRedirect))){
modelAndView.addObject("stuff", "importantStuff");
modelAndView.addObject("moreStuff", "moreImportantStuff");
}
}
You will also need to register each Interceptor with each handler mapper. I hope this helps Josh |
|
#9
|
|||
|
|||
|
That worked like a charm. Thanks for your input Josh. Do you happen to know any documents that would explain more of the 'frameworky' type of aspects to Spring? I was thinking of writing a dynamic proxy to solve this problem but I was too afraid to go down that path!
Again, thanks for all your detailed help. |
|
#10
|
|||
|
|||
|
Hi John,
Its no problem at all, its interesting for me as well as I start digging into the code to check how it works. Regarding the dynamic proxies, could you explain a bit further what you would like to achieve, anything is possible its just knowing the right path. Josh |
![]() |
| Thread Tools | |
| Display Modes | |
|
|