Yes, but it's not part of the regular Spring framework. I have my own AbstractFormController and AbstractViewController as part of my own Spring extension library.
The setup in the application context (the view controller extends AbstractViewController and the form controller extends AbstractFormController):-
Code:
<bean id="addProductViewController" class="org.myclient.controller.AddProductViewController">
<property name="associatedFormController">
<ref bean="addProductFormController"/>
</property>
<property name="categoryDAO">
<ref bean="categoryDAO"/>
</property>
<property name="successView"><value>secure/product/addEditProduct</value></property>
</bean>
<bean id="addProductFormController" class="org.myclient.controller.AddProductFormController">
<property name="commandName"><value>addEditProductCommand</value></property>
<property name="commandClass"><value>org.myclient.command.AddEditProductCommand</value></property>
<property name="sessionForm"><value>true</value></property>
<property name="validator">
<ref bean="commonsValidator"/>
</property>
<property name="categoryDAO">
<ref bean="categoryDAO"/>
</property>
<property name="productDAO">
<ref bean="productDAO"/>
</property>
<property name="formView"><value>secure/product/addEditProduct</value></property>
<property name="successView"><value>secure/product/viewProduct</value></property>
</bean>
AbstractFormController (abbreviated):-
Code:
/*
* MPSC-Spring - A library of common code to use with the Spring framework
*
* Copyright 2005 Matt Parker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.co.mpcontracting.modules.spring.controller;
/**
* An abstract Spring controller that deals with form submissions
*
* @author Matt Parker (matt@mpcontracting.co.uk)
*/
public abstract class AbstractFormController extends SimpleFormController
{
private static Log log = LogFactory.getLog(AbstractFormController.class);
private static final String DEFAULT_MESSAGE = "error.standard.defaultMessage";
/**
* A hook for a sub-class to process the form submission
*
* @param request The request
* @param response The response
* @param command The associated command object
* @param errors The current errors collection
* @return The associated control model
* @throws Exception If there are any problems with the form processing
*/
protected abstract ControlModel process(HttpServletRequest request, HttpServletResponse response, Object command,
Errors errors) throws Exception;
/**
* A thread local holder for the form backing object associated with
* this thread
*/
private static ThreadLocal formBackingObjectStore = new ThreadLocal();
/**
* Retrieves the form backing object
*
* @param The current request
* @return The form backing object
* @throws Exception If there is a problem getting the form backing object
*/
protected final Object getFormBackingObject(HttpServletRequest request) throws Exception
{
Object formBackingObject = request.getSession().getAttribute(getFormSessionAttributeName(request));
if (formBackingObject == null)
{
formBackingObject = formBackingObjectStore.get();
}
if (formBackingObject == null)
{
throw new ServletException("Unable to find form backing object either in session or local store");
}
return (formBackingObject);
}
/**
* Allows an associated view controller to call into the form controller to request
* that the form backing object is created. This allows Spring bind tags to be used
* in the view
*
* @param request The request
* @return The form backing object
* @throws Exception If there is a problem creating the form backing object
*/
Object createFormBackingObject(HttpServletRequest request) throws Exception
{
if (log.isDebugEnabled())
{
log.debug("Creating form backing object");
}
// Clear out any existing commands that may still exist in the session
request.getSession().removeAttribute(getFormSessionAttributeName(request));
Object formBackingObject = formBackingObject(request);
request.setAttribute(getCommandName(), formBackingObject);
return (formBackingObject);
}
}
AbstractViewController (abbreviated):-
Code:
/*
* MPSC-Spring - A library of common code to use with the Spring framework
*
* Copyright 2005 Matt Parker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package uk.co.mpcontracting.modules.spring.controller;
/**
* An abstract Spring controller that deals with resolving views
*
* @author Matt Parker (matt@mpcontracting.co.uk)
*/
public abstract class AbstractViewController implements Controller
{
private static Log log = LogFactory.getLog(AbstractViewController.class);
private static final String DEFAULT_MESSAGE = "error.standard.defaultMessage";
/**
* A hook for a sub-class to process the view request
*
* @param request The request
* @param response The response
* @return The model and view
* @throws Exception If there are any problems with the view request
*/
protected abstract ModelAndView process(HttpServletRequest request, HttpServletResponse response,
Errors errors) throws Exception;
/**
* A thread local holder for the form backing object associated with
* this thread
*/
private static ThreadLocal formBackingObjectStore = new ThreadLocal();
private AbstractFormController associatedFormController;
/**
* Sets the associated form controller. This allows a view to be associated with a form which in
* turn allows a form backing object to be created for the view to enable the Spring bind tags
* to function correctly
*
* @param associatedFormController The associated form controller
*/
public void setAssociatedFormController(AbstractFormController associatedFormController)
{
this.associatedFormController = associatedFormController;
}
/**
* Retrieves the associated form controller
*
* @return The associated form controller
*/
protected AbstractFormController getAssociatedFormController()
{
return (associatedFormController);
}
/**
* Retrieves the form backing object
*
* @return The form backing object
*/
protected final Object getFormBackingObject()
{
return (formBackingObjectStore.get());
}
/**
* Creates a form backing object if required then passes control to the process method
*
* @param request The request
* @param response The response
* @return The returned model and view
* @throws Exception If there are any problems with the view request
*/
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception
{
// Create a form backing object if we have an associated form
if (associatedFormController != null)
{
// Store in a thread local for possible later retrieval
formBackingObjectStore.set(associatedFormController.createFormBackingObject(request));
}
BindException errors = new BindException("*", "*");
ModelAndView modelAndView = process(request, response, errors);
if (errors.hasErrors())
{
modelAndView.addAllObjects(errors.getModel());
}
return (modelAndView);
}
}
I had to abbreviate the classes to get past the post size limit. My extension code is Apache licensed so if you want to have the whole library then you'd be welcome. It's only at version 0.2 at the moment though and is not yet publically released so I can't guarantee it free from bugs.
Bob