Results 1 to 7 of 7

Thread: merge form controller and multiAction controller

  1. #1
    Join Date
    Nov 2004
    Posts
    20

    Default merge form controller and multiAction controller

    Hello all,

    I am a newbie to Spring and just migrating to it. so please bear with me.

    I would like to put all the CRUD operations for a domain object into one controller. in this case my controller will be able to handle form and list related operations. But the required functions are spreaded in two main classes. Anybody combined these functionalties into one class before? the simplest way might be copy the multiaction controller and derive the new one from a formcontroller. the other way around would be harder since it spreaded into several classes.

    then, ask a more generic question. why the multiaction controller does not support form submission/resubmission mecanism? Looks like to me, there should be a new class like FormProcessor that will take some parameters (eg, request, command object etc) , and then do the bind to populate the domain object. return a result Wrapper that has command, binderrors etc.

    then developer take this wrapper and decide to resubmission with this wrapper ( a base class function) or keep moving ahead.

    Of course, the I <sprint:bind> will lookup from this wrapper.

    If we implement this way, we further separated the form and controller architecturely and any actions in a controller can process forms to support multiple form in one controller. Actuay, the Pagelisthholder is more or less implemented this way.

    Thanks a lot.

    jfd

  2. #2
    Join Date
    Aug 2004
    Location
    Auburn, AL, USA.
    Posts
    106

    Default

    I have found this to be an issue too; in fact it is one of the only major uglinesses I see in the Spring Web MVC (the other is the fact that FormController supports only one command object). I have taken a couple different approaches to tackeling this, none of which have completely satisfied me, including one base controller with the logic for common stuff, and then seperate controllers for each CRUD operation; alteratively you can put all code into one FormController and then implement you own logic to process the different operations. If anyone has a better approach I'd very much like to know it, so please do post it.

  3. #3
    Join Date
    Sep 2004
    Location
    Boston, US
    Posts
    130

    Default

    I faced a similar issue and created a subclass of SimpleFormController that does method based dispatching like the MultiActionController.

    I wish Spring supported a MultiActionFormController out of the box.

    Sanjiv

  4. #4
    Join Date
    Oct 2004
    Location
    London, UK
    Posts
    71

    Default

    a lot of people seem to be interested in this and there was a discussion at
    http://forum.springframework.org/showthread.php?t=11086

    To summarise though the MultiActionController will handle binds to a command object but doesnt really help with the error handling.

    i have written a couple of classes for doing some similar stuff. Although this may not be what you are after hope this can help you develop something that works for you
    Code:
    public class SubmitParameterPropertiesMethodNameResolver implements
    		MethodNameResolver {
    
    	private String defaultMethodName;
    	
    	private Properties mappings;
    
    	/**
    	 * Set URL to method name mappings from a Properties object.
    	 * @param mappings properties with URL as key and method name as value
    	 */
    	public void setMappings(Properties mappings) {
    		this.mappings = mappings;
    	}
    	
    	/**
    	 * @param defaultMethodName The defaultMethodName to set.
    	 */
    	public void setDefaultMethodName(String defaultMethodName) {
    		this.defaultMethodName = defaultMethodName;
    	}
    	
    	public void afterPropertiesSet() {
    		if (this.mappings == null || this.mappings.isEmpty()) {
    			throw new IllegalArgumentException("'mappings' property is required");
    		}
    	}
    
    	public String getHandlerMethodName(HttpServletRequest request)
    			throws NoSuchRequestHandlingMethodException {
    	
    		for (Iterator it = this.mappings.keySet().iterator(); it.hasNext();) {
    			String submitParamter = (String) it.next();
    			if (WebUtils.hasSubmitParameter(request, submitParamter)) {
    				return (String) this.mappings.get(submitParamter);
    			}
    		}
    		return defaultMethodName;
    	}
    and
    Code:
    public abstract class SimpleMultiActionFormController extends SimpleFormController {
    	
    	private MethodNameResolver methodNameResolver = new SubmitParameterPropertiesMethodNameResolver();
    	
    	public final void setMethodNameResolver(MethodNameResolver methodNameResolver) {
    		this.methodNameResolver = methodNameResolver;
    	}
    	
    	public final MethodNameResolver getMethodNameResolver() {
    		return this.methodNameResolver;
    	}
    	
    	protected ModelAndView processFormSubmission(HttpServletRequest request,
    			HttpServletResponse response, Object command, BindException errors)
    			throws Exception {
    		
    		if (errors.hasErrors() || isFormChangeRequest(request)) {
    			if (logger.isDebugEnabled()) {
    				logger.debug("Data binding errors: " + errors.getErrorCount());
    			}
    			return showForm(request, response, errors);
    		}
    		else {
    			String methodName = this.methodNameResolver.getHandlerMethodName(request);
    			
    			Method m = (Method) this.getClass().getMethod(methodName,
    					new Class[] {HttpServletRequest.class,
    								 Object.class,
    								 BindException.class});
    			if (m == null) {
    				throw new NoSuchRequestHandlingMethodException(methodName, getClass());
    			}
    			
    
    			List params = new ArrayList(3);
    			params.add(request);
    			params.add(command);
    			params.add(errors);
    			
    			return (ModelAndView) m.invoke(this, params.toArray(new Object[params.size()]));
    		}
    		
    	}
    
    }
    an example is


    Code:
    	<bean id="submitActionParamResolver" class="com.codebitches.springframework.web.servlet.mvc.multiaction.SubmitParameterPropertiesMethodNameResolver">
           <property name="mappings">
              <props>
                <prop key="_addSubject">addSubject</prop>
                <prop key="_finish">finalSubmit</prop>
             </props>
           </property>
           <property name="defaultMethodName"><value>finalSubmit</value></property>
       </bean>
    
       <bean id="createEditItemFormController" class="com.codebitches.springxmldb.examples.tilesnews.web.spring.CreateEditItemFormController">
          <property name="methodNameResolver"><ref bean="submitActionParamResolver"/></property>
          <property name="sessionForm"><value>true</value></property>
          <property name="successView"><value>createEditItemConfirmation</value></property>
          <property name="commandName"><value>item</value></property>
          <property name="formView"><value>createEditItemForm</value></property>
       </bean>
    Code:
    public class CreateEditItemFormController extends SimpleMultiActionFormController {
    
    	private ITilesNewsCMS cms;
    	
    	private static Log log = LogFactory.getLog(CreateEditItemFormController.class);
    
    	/**
    	 * @param cms The cms to set.
    	 */
    	public void setCms(ITilesNewsCMS cms) {
    		this.cms = cms;
    	}
    	
    	public CreateEditItemFormController() {
    	}
    
    
    	protected Object formBackingObject(HttpServletRequest request) throws ModelAndViewDefiningException {
    		String id = request.getParameter("itemId");
    		
    		Item item = new Item();
    		
    		if (id != null && !id.equals("")) {
    			item = cms.getItem(id);
    		}
    		
    		return item;
    	}
    	
    	public ModelAndView addSubject(HttpServletRequest request, Object command, BindException errors) throws Exception {
    		Item item = (Item) command;
    		
    		Collection subs = item.getMetadata().getSubjects();
    		subs.add(new ItemSubject());
    		
    		
    		return this.showForm(request, errors, getFormView());
    	}
    	
    	public ModelAndView finalSubmit(HttpServletRequest request, Object command, BindException errors) throws Exception {
    		Item item = (Item) command;
    		
    		item = cms.createOrUpdateItem(item);
    		
    		Map model = new HashMap();
    		model.put("item", item);
    		
    		return new ModelAndView(getSuccessView(), model);
    	}
    
    	/* (non-Javadoc)
    	 * @see org.springframework.web.servlet.mvc.SimpleFormController#referenceData(javax.servlet.http.HttpServletRequest)
    	 */
    	protected Map referenceData(HttpServletRequest request) throws Exception {
    		return super.referenceData(request);
    	}
    Last edited by robyn; May 14th, 2006 at 05:22 PM.

  5. #5
    Join Date
    Sep 2004
    Location
    Boston, US
    Posts
    130

    Default

    Thanks. I had a similar version to suit my requirements.

    Minor point : The Class#getMethods() method throws NoSuchMethodException if a method does not exist as opposed to returning 'null'.


    Code:
             String methodName = this.methodNameResolver.getHandlerMethodName&#40;request&#41;; 
              
             Method m = &#40;Method&#41; this.getClass&#40;&#41;.getMethod&#40;methodName, 
                   new Class&#91;&#93; &#123;HttpServletRequest.class, 
                             Object.class, 
                             BindException.class&#125;&#41;; 
             if &#40;m == null&#41; &#123; 
                throw new NoSuchRequestHandlingMethodException&#40;methodName, getClass&#40;&#41;&#41;; 
             &#125;

  6. #6
    Join Date
    Sep 2005
    Posts
    12

    Default

    Has anyone taken this further? Something like this should really be integrated into Spring MVC. I like the concept of abstracting the form processing out into another class so we can simply work with a MultiActionController and optionally do form validation with it.

    I'm going to poke around a bit and possibly submit a Jira ticket if I don't find anything.

  7. #7
    Join Date
    Sep 2005
    Posts
    12

Similar Threads

  1. Replies: 46
    Last Post: Jan 19th, 2011, 01:15 PM
  2. Replies: 1
    Last Post: Nov 17th, 2004, 03:03 AM
  3. Replies: 2
    Last Post: Sep 14th, 2004, 09:58 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •