Community   SpringSource   Projects    Downloads    Documentation    Forums    Training   Exchange   Blogs

Go Back   Spring Community Forums > Core Spring Projects > Web

Reply
 
Thread Tools Display Modes
  #1  
Old Feb 25th, 2008, 04:20 PM
Johnhup Johnhup is offline
Junior Member
 
Join Date: May 2007
Posts: 10
Default Common Model Objects

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.
Reply With Quote
  #2  
Old Feb 25th, 2008, 05:28 PM
Steve O Steve O is offline
Senior Member
 
Join Date: Jul 2005
Location: Idaho
Posts: 224
Default

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;
}
You should be able to do this with other template technologies too.

How that helps,

Steve O
Reply With Quote
  #3  
Old Feb 25th, 2008, 05:37 PM
Johnhup Johnhup is offline
Junior Member
 
Join Date: May 2007
Posts: 10
Default

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.
Reply With Quote
  #4  
Old Feb 25th, 2008, 08:09 PM
joshk joshk is offline
Senior Member
 
Join Date: Apr 2007
Location: Wellington, New Zealand
Posts: 125
Default

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");
}
Be warned, if you add common model data and then redirect, the model data will be appended to the query string, I recommend using the interceptor but checking what the view is. If you use a handler exception resolver then you might have to create a hook for it to use the interceptor as well.

I hope this helps (and makes sense)

Josh
Reply With Quote
  #5  
Old Feb 25th, 2008, 08:21 PM
Johnhup Johnhup is offline
Junior Member
 
Join Date: May 2007
Posts: 10
Default

Quote:
Originally Posted by joshk View Post
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.
Thanks Josh, that does make sense, especially using the WebRequestInterceptor.postHandle. I would like to do this route as it is transparent to the caller, however, how do I get beans that were created using Spring's container into a super class that all my controllers would extend? My main problem is, I dont want to have to wire up all of this shared functionality into every controller.

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.
Reply With Quote
  #6  
Old Feb 25th, 2008, 08:29 PM
joshk joshk is offline
Senior Member
 
Join Date: Apr 2007
Location: Wellington, New Zealand
Posts: 125
Default

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
Reply With Quote
  #7  
Old Feb 25th, 2008, 09:43 PM
Johnhup Johnhup is offline
Junior Member
 
Join Date: May 2007
Posts: 10
Default

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?
Reply With Quote
  #8  
Old Feb 25th, 2008, 10:39 PM
joshk joshk is offline
Senior Member
 
Join Date: Apr 2007
Location: Wellington, New Zealand
Posts: 125
Default

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");
	}
}
(Please note, I have not tried out this code)

You will also need to register each Interceptor with each handler mapper.

I hope this helps

Josh
Reply With Quote
  #9  
Old Feb 26th, 2008, 01:51 AM
Johnhup Johnhup is offline
Junior Member
 
Join Date: May 2007
Posts: 10
Default

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.
Reply With Quote
  #10  
Old Feb 26th, 2008, 05:12 AM
joshk joshk is offline
Senior Member
 
Join Date: Apr 2007
Location: Wellington, New Zealand
Posts: 125
Default

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
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -5. The time now is 02:47 AM.


Contegix provides first-class managed hosting and partial sponsorship of these forums.

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.