org.shept.org.springframework.web.servlet.mvc.delegation
Class DelegatingController

java.lang.Object
  extended by org.springframework.context.support.ApplicationObjectSupport
      extended by org.springframework.web.context.support.WebApplicationObjectSupport
          extended by org.springframework.web.servlet.support.WebContentGenerator
              extended by org.springframework.web.servlet.mvc.AbstractController
                  extended by org.shept.org.springframework.web.servlet.mvc.delegation.DelegatingController
All Implemented Interfaces:
org.springframework.beans.factory.BeanNameAware, org.springframework.beans.factory.InitializingBean, org.springframework.context.ApplicationContextAware, org.springframework.web.context.ServletContextAware, org.springframework.web.servlet.mvc.Controller, org.springframework.web.servlet.mvc.LastModified
Direct Known Subclasses:
MultiActionController

public class DelegatingController
extends org.springframework.web.servlet.mvc.AbstractController
implements org.springframework.web.servlet.mvc.LastModified, org.springframework.beans.factory.BeanNameAware, org.springframework.beans.factory.InitializingBean

Controller implementation that allows multiple request types to be handled by the same class. The design is inspired by the org.springframework.web.servlet.mvc.delegating.DelegatingController but there are some important differences. The DelegatingController is specifically designed to support repetitive elements on a WebPage such as Tables, Schedules, Filtering and searching or any combination of these elements and your own custom requirements.

This is accomplished by delegating to predefined handlers aka WebComponent A number of handlers for filters and tables are already predefined and ready to use. By subclassing AbstractComponent and implementing the WebComponent you can extend the controller with custom Components.

A component is associated with some part of your command object. To resolve the association between components and your command object your command object needs to implement the SubCommandProvider Interface which will inform the controller about the components it supports. Basically the SubCommandProvider Interface specifies a map of bean pathnames and the (sub-)command objects at the nodes of each pathName. See DefaultCommandObject for an example.

This design is very flexible and allows for infinite extension as elements may repeat an infinte number of times requiring just a single handler to take care of them. A good example is a WebPage where you search for customers and their associated data, e.g. addresses, contracts, history information e.t.c. Its easily possible to expand the searchpage towards the end and so you can group a lot of editable information without writing much code.

Now we need to match a form submission with the component handler in duty. By convention each form submission for a component other than root needs a prefix of the same bean pathname which is returned the SubCommandProvider interface. Two resolvers provide this solution: The ComponentNameResolver will match the the pathname of the associated handler and the form submission. In a second step the WebActionResolver will supply the paramters of the form submission with a WebActionToken gathering all the information from the form submission wrapping it with command object and component in a ComponentToken for further processing by the target handler.

The DelegatingController does not bind request parameters to the command object this has to be done by the invoked handler. This allows for full control over the entire binder setup and usage, including the invocation of Validators and the subsequent evaluation of binding/validation errors. All error handling is in the responsibility of the invoked handler

Return values can be a map containing model attributes or ModelAndView or RedirectView objects. If there is no model name or redirect url specified then default values will be provided. The configured RequestToViewNameTranslator will be used to determine the view name. In case of a RedirectView it will use the redirectViewName field which is be default the controllers name which should be by convention servlet pathName so redirected views implement by default the get-after-post strategy.

Author:
Rod Johnson, Juergen Hoeller, Colin Sampaleanu, Rob Harrop, Sam Brannen, Andreas Hahn
See Also:
WebActionResolver, ComponentNameResolver, SubmitActionResolver, LastModified.getLastModified(javax.servlet.http.HttpServletRequest), ServletRequestDataBinder

Field Summary
private  WebActionResolver actionResolver
          Delegate that knows how to determine method names and submission values from incoming requests
private  Class<Object> commandClass
          Command class specification
static String DEFAULT_COMMAND_NAME
          Default command name used for binding command objects: "command"
private  WebComponent[] delegates
          components handlers
private  String formView
          formView - this is the fileName
static String LAST_MODIFIED_METHOD_SUFFIX
          Suffix for last-modified methods
static String PAGE_NOT_FOUND_LOG_CATEGORY
          Log category to use when no mapped handler is found for a request.
protected static org.apache.commons.logging.Log pageNotFoundLogger
          Additional logger to use when no mapped handler is found for a request.
private  String redirectUrl
          Redirection url - by default this should be the name of the bean (set via BeanNameAware)
private  org.springframework.web.bind.support.WebBindingInitializer webBindingInitializer
          Optional strategy for pre-initializing data binding
 
Fields inherited from class org.springframework.web.servlet.support.WebContentGenerator
METHOD_GET, METHOD_HEAD, METHOD_POST
 
Fields inherited from class org.springframework.context.support.ApplicationObjectSupport
logger
 
Constructor Summary
DelegatingController()
           
 
Method Summary
 void afterPropertiesSet()
           
protected  ComponentDataBinder createBinder(javax.servlet.http.HttpServletRequest request, Object command)
          Create a new binder instance for the given command and request.
protected  String getCommandName(Object command)
          Return the command name to use for the given command object.
protected  Object getCommandObject(javax.servlet.http.HttpServletRequest request, Class clazz)
          Create a new command object of the given class.
 String getFormView()
           
 long getLastModified(javax.servlet.http.HttpServletRequest request)
          Try to find an XXXXLastModified method, where XXXX is the name of a handler.
 String getRedirectUrl()
           
 org.springframework.web.bind.support.WebBindingInitializer getWebBindingInitializer()
          Return the WebBindingInitializer (if any) which will apply pre-configured configuration to every DataBinder that this controller uses.
protected  org.springframework.web.servlet.ModelAndView handleNoSuchRequestHandlingMethod(org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException ex, javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
          Handle the case where no request handler method was found.
protected  org.springframework.web.servlet.ModelAndView handleRequestInternal(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
          Determine a handler method and invoke it.
protected  void initBinder(javax.servlet.http.HttpServletRequest request, ComponentDataBinder binder)
          Initialize the given binder instance, for example with custom editors.
protected  org.springframework.web.servlet.ModelAndView massageReturnValueIfNecessary(Object returnValue)
          Processes the return value of a handler method to ensure that it either returns null or an instance of ModelAndView.
protected  void postProcessModel(javax.servlet.http.HttpServletRequest request, org.springframework.web.servlet.ModelAndView modelAndView)
           
private  Map<String,Object> prepareComponentPathForLookup(Map<String,Object> components)
          put a colon '.' at the end of non empty pathNames
 void setActionResolver(WebActionResolver actionResolver)
           
 void setBeanName(String name)
           
 void setCommandClass(Class<Object> commandClass)
           
 void setDelegates(WebComponent[] delegates)
           
 void setFormView(String formView)
           
 void setRedirectUrl(String viewName)
           
 void setWebBindingInitializer(org.springframework.web.bind.support.WebBindingInitializer webBindingInitializer)
          Specify a WebBindingInitializer which will apply pre-configured configuration to every DataBinder that this controller uses.
 
Methods inherited from class org.springframework.web.servlet.mvc.AbstractController
handleRequest, isSynchronizeOnSession, setSynchronizeOnSession
 
Methods inherited from class org.springframework.web.servlet.support.WebContentGenerator
applyCacheSeconds, applyCacheSeconds, cacheForSeconds, cacheForSeconds, checkAndPrepare, checkAndPrepare, getCacheSeconds, getSupportedMethods, isRequireSession, isUseCacheControlHeader, isUseCacheControlNoStore, isUseExpiresHeader, preventCaching, setCacheSeconds, setRequireSession, setSupportedMethods, setUseCacheControlHeader, setUseCacheControlNoStore, setUseExpiresHeader
 
Methods inherited from class org.springframework.web.context.support.WebApplicationObjectSupport
getServletContext, getTempDir, getWebApplicationContext, initApplicationContext, initServletContext, isContextRequired, setServletContext
 
Methods inherited from class org.springframework.context.support.ApplicationObjectSupport
getApplicationContext, getMessageSourceAccessor, initApplicationContext, requiredContextClass, setApplicationContext
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

LAST_MODIFIED_METHOD_SUFFIX

public static final String LAST_MODIFIED_METHOD_SUFFIX
Suffix for last-modified methods

See Also:
Constant Field Values

DEFAULT_COMMAND_NAME

public static final String DEFAULT_COMMAND_NAME
Default command name used for binding command objects: "command"

See Also:
Constant Field Values

PAGE_NOT_FOUND_LOG_CATEGORY

public static final String PAGE_NOT_FOUND_LOG_CATEGORY
Log category to use when no mapped handler is found for a request.

See Also:
pageNotFoundLogger, Constant Field Values

pageNotFoundLogger

protected static final org.apache.commons.logging.Log pageNotFoundLogger
Additional logger to use when no mapped handler is found for a request.

See Also:
PAGE_NOT_FOUND_LOG_CATEGORY

actionResolver

private WebActionResolver actionResolver
Delegate that knows how to determine method names and submission values from incoming requests


webBindingInitializer

private org.springframework.web.bind.support.WebBindingInitializer webBindingInitializer
Optional strategy for pre-initializing data binding


delegates

private WebComponent[] delegates
components handlers


redirectUrl

private String redirectUrl
Redirection url - by default this should be the name of the bean (set via BeanNameAware)


formView

private String formView
formView - this is the fileName


commandClass

private Class<Object> commandClass
Command class specification

Constructor Detail

DelegatingController

public DelegatingController()
Method Detail

setActionResolver

public void setActionResolver(WebActionResolver actionResolver)
Parameters:
actionResolver - the actionResolver to set

setDelegates

public void setDelegates(WebComponent[] delegates)
Parameters:
delegates - the delegates to set

setCommandClass

public void setCommandClass(Class<Object> commandClass)
Parameters:
commandClass - the commandClass to set

setWebBindingInitializer

public final void setWebBindingInitializer(org.springframework.web.bind.support.WebBindingInitializer webBindingInitializer)
Specify a WebBindingInitializer which will apply pre-configured configuration to every DataBinder that this controller uses.

Allows for factoring out the entire binder configuration to separate objects, as an alternative to initBinder(javax.servlet.http.HttpServletRequest, org.shept.org.springframework.web.bind.support.ComponentDataBinder).


getWebBindingInitializer

public final org.springframework.web.bind.support.WebBindingInitializer getWebBindingInitializer()
Return the WebBindingInitializer (if any) which will apply pre-configured configuration to every DataBinder that this controller uses.


getLastModified

public long getLastModified(javax.servlet.http.HttpServletRequest request)
Try to find an XXXXLastModified method, where XXXX is the name of a handler. Return -1 if there's no such handler, indicating that content must be updated.

Specified by:
getLastModified in interface org.springframework.web.servlet.mvc.LastModified
See Also:
LastModified.getLastModified(HttpServletRequest)

handleRequestInternal

protected org.springframework.web.servlet.ModelAndView handleRequestInternal(javax.servlet.http.HttpServletRequest request,
                                                                             javax.servlet.http.HttpServletResponse response)
                                                                      throws Exception
Determine a handler method and invoke it.

Specified by:
handleRequestInternal in class org.springframework.web.servlet.mvc.AbstractController
Throws:
Exception
See Also:
MethodNameResolver.getHandlerMethodName(javax.servlet.http.HttpServletRequest), #invokeNamedMethod, handleNoSuchRequestHandlingMethod(org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)

prepareComponentPathForLookup

private Map<String,Object> prepareComponentPathForLookup(Map<String,Object> components)
put a colon '.' at the end of non empty pathNames

Parameters:
-
componentPathName -
pathNames -
Returns:

handleNoSuchRequestHandlingMethod

protected org.springframework.web.servlet.ModelAndView handleNoSuchRequestHandlingMethod(org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException ex,
                                                                                         javax.servlet.http.HttpServletRequest request,
                                                                                         javax.servlet.http.HttpServletResponse response)
                                                                                  throws Exception
Handle the case where no request handler method was found.

The default implementation logs a warning and sends an HTTP 404 error. Alternatively, a fallback view could be chosen, or the NoSuchRequestHandlingMethodException could be rethrown as-is.

Parameters:
ex - the NoSuchRequestHandlingMethodException to be handled
request - current HTTP request
response - current HTTP response
Returns:
a ModelAndView to render, or null if handled directly
Throws:
Exception - an Exception that should be thrown as result of the servlet request

massageReturnValueIfNecessary

protected org.springframework.web.servlet.ModelAndView massageReturnValueIfNecessary(Object returnValue)
Processes the return value of a handler method to ensure that it either returns null or an instance of ModelAndView. When returning a Map, the Map instance is wrapped in a new ModelAndView instance.


getCommandObject

protected Object getCommandObject(javax.servlet.http.HttpServletRequest request,
                                  Class clazz)
                           throws Exception
Create a new command object of the given class.

This implementation uses BeanUtils.instantiateClass, so commands need to have public no-arg constructors. Subclasses can override this implementation if desired.

Throws:
Exception - if the command object could not be instantiated
See Also:
BeanUtils.instantiateClass(Class)

createBinder

protected ComponentDataBinder createBinder(javax.servlet.http.HttpServletRequest request,
                                           Object command)
                                    throws Exception
Create a new binder instance for the given command and request.

Called by bind. Can be overridden to plug in custom ServletRequestDataBinder subclasses.

The default implementation creates a standard ServletRequestDataBinder, and invokes initBinder. Note that initBinder will not be invoked if you override this method!

Parameters:
request - current HTTP request
command - the command to bind onto
Returns:
the new binder instance
Throws:
Exception - in case of invalid state or arguments
See Also:
#bind, initBinder(javax.servlet.http.HttpServletRequest, org.shept.org.springframework.web.bind.support.ComponentDataBinder)

getCommandName

protected String getCommandName(Object command)
Return the command name to use for the given command object.

Default is "command".

Parameters:
command - the command object
Returns:
the command name to use
See Also:
DEFAULT_COMMAND_NAME

initBinder

protected void initBinder(javax.servlet.http.HttpServletRequest request,
                          ComponentDataBinder binder)
                   throws Exception
Initialize the given binder instance, for example with custom editors. Called by createBinder.

This method allows you to register custom editors for certain fields of your command class. For instance, you will be able to transform Date objects into a String pattern and back, in order to allow your JavaBeans to have Date properties and still be able to set and display them in an HTML interface.

The default implementation is empty.

Note: the command object is not directly passed to this method, but it's available via DataBinder.getTarget()

Parameters:
request - current HTTP request
binder - new binder instance
Throws:
Exception - in case of invalid state or arguments
See Also:
createBinder(javax.servlet.http.HttpServletRequest, java.lang.Object), DataBinder.registerCustomEditor(java.lang.Class, java.beans.PropertyEditor), CustomDateEditor

postProcessModel

protected void postProcessModel(javax.servlet.http.HttpServletRequest request,
                                org.springframework.web.servlet.ModelAndView modelAndView)
                         throws Exception
Throws:
Exception

setBeanName

public void setBeanName(String name)
Specified by:
setBeanName in interface org.springframework.beans.factory.BeanNameAware

getRedirectUrl

public String getRedirectUrl()
Returns:
the viewName

setRedirectUrl

public void setRedirectUrl(String viewName)
Parameters:
viewName - the viewName to set

afterPropertiesSet

public void afterPropertiesSet()
                        throws Exception
Specified by:
afterPropertiesSet in interface org.springframework.beans.factory.InitializingBean
Throws:
Exception

getFormView

public String getFormView()
Returns:
the formView

setFormView

public void setFormView(String formView)
Parameters:
formView - the formView to set


Copyright © 2011. All Rights Reserved.