Announcement Announcement Module
Collapse
No announcement yet.
ErrorView instead of SuccessView Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • ErrorView instead of SuccessView

    We extended Spring MVC to use with our own custom framework where we use a base from controller that suclasses from SimpleFormController. While we need to show successView, we dont take the value using getSuccessView() and instead use our own navigation flow to determine what will be our next page to show. So getSuccessView() is instead unused in our case.

    Firstly, we must specify a successView in application configutation file irrespective of we use it or not, same is true for formView (which we use). Is this statement correct?

    Secodnly, I want to override successView as errorView, In other words, in simple form controller's onSubmit(), I want to call the getSuccessView() as getErrorView(). Is it ffeasible? Do you know what code segment I have to override?

    I dont want to specify
    <property name="successView"><value>successPage</value></property>
    as
    <property name="successView"><value>errorPage</value></property>

    because the use case developers will get misled. Rather I want to specify it as follows -

    <property name="errorView"><value>errorPage</value></property>

    and if possible remove successView property from my form controller declaration in XML file. Is it feasible?

    Any light on it is appreciated.

  • #2
    Originally posted by ashik
    We extended Spring MVC to use with our own custom framework where we use a base from controller that suclasses from SimpleFormController. While we need to show successView, we dont take the value using getSuccessView() and instead use our own navigation flow to determine what will be our next page to show. So getSuccessView() is instead unused in our case.

    Firstly, we must specify a successView in application configutation file irrespective of we use it or not, same is true for formView (which we use). Is this statement correct?
    No that statement is not correct, the success view will just stay as null if you don't specify it in your context XML.

    Originally posted by ashik
    Secodnly, I want to override successView as errorView, In other words, in simple form controller's onSubmit(), I want to call the getSuccessView() as getErrorView(). Is it ffeasible? Do you know what code segment I have to override?

    I dont want to specify
    <property name="successView"><value>successPage</value></property>
    as
    <property name="successView"><value>errorPage</value></property>

    because the use case developers will get misled. Rather I want to specify it as follows -

    <property name="errorView"><value>errorPage</value></property>

    and if possible remove successView property from my form controller declaration in XML file. Is it feasible?

    Any light on it is appreciated.
    Easiest way is to create an AbstractFormController that subclasses SimpleFormController from which all your form controllers are then derived. This abstract form controller then needs setErrorView(String errorView) and getErrorView(). That's it.

    Bob

    Comment


    • #3
      I appreciate the response.

      About extending from AbstractFormController instead of SimpleFormController. If my base controller doesn't extend from SimpleFormController, I have to write down codes for showForm() and processFormSubmission(). While I initially I skipped it to save coding time, I think now its worth to figure out not only errorView but adding some more staffs for our cutom framework.

      Thank you very much. Its a helpful forum I knew earlier.

      Comment


      • #4
        Sorry, I didn't make myself clear. You create your own abstract form controller that extends SimpleFormController. Here's mine for example, that implements loads of other stuff, including an error view (though I've called it failureView).

        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;
        
        import java.util.Enumeration;
        import java.util.Map;
        import java.util.Properties;
        
        import javax.servlet.ServletException;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        
        import org.apache.commons.logging.Log;
        import org.apache.commons.logging.LogFactory;
        
        import org.springframework.beans.propertyeditors.CustomBooleanEditor;
        import org.springframework.beans.propertyeditors.CustomNumberEditor;
        import org.springframework.context.support.MessageSourceAccessor;
        import org.springframework.validation.BindException;
        import org.springframework.validation.Errors;
        import org.springframework.validation.ObjectError;
        import org.springframework.web.bind.ServletRequestDataBinder;
        import org.springframework.web.servlet.ModelAndView;
        import org.springframework.web.servlet.mvc.SimpleFormController;
        import org.springframework.web.servlet.view.RedirectView;
        
        import uk.co.mpcontracting.modules.spring.model.AbstractControlModel;
        import uk.co.mpcontracting.modules.spring.model.ControlModel;
        
        public abstract class AbstractFormController extends SimpleFormController
        {
            private static Log log = LogFactory.getLog(AbstractFormController.class);
            
            private static final String DEFAULT_MESSAGE = "error.standard.defaultMessage";
        
            protected abstract ControlModel process(HttpServletRequest request, HttpServletResponse response, Object command,
                Errors errors) throws Exception;
        
            private static ThreadLocal formBackingObjectStore = new ThreadLocal();
            
            private String failureView;
        
            public final void setFailureView(String failureView)
            {
                this.failureView = failureView;
            }
        
            protected final String getFailureView()
            {
                return (failureView);
            }
        
            protected final int getMaxIndex(HttpServletRequest request, String property)
            {
                int maxIndex = -1;
                
                for (Enumeration parameters = request.getParameterNames(); parameters.hasMoreElements();)
                {
                    String parameterName = (String)parameters.nextElement();
        
                    if (parameterName.startsWith(property))
                    {
                        int startIndex = parameterName.indexOf("[");
                        int endIndex = parameterName.indexOf("]");
                        
                        if ((startIndex == -1) || (endIndex == -1))
                        {
                            log.error("Non-indexed property - " + property);
                            
                            return (-1);
                        }
        
                        int index = Integer.parseInt(parameterName.substring((startIndex + 1), endIndex));
                        
                        if (index > maxIndex)
                        {
                            maxIndex = index;
                        }
                    }
                }
                
                return (maxIndex);
            }
        
            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);
            }
        
            protected ModelAndView processFormSubmission(HttpServletRequest request, HttpServletResponse response, 
                Object command, BindException errors) throws Exception
            {
                if (errors.hasErrors() || isFormChangeRequest(request))
                {
                    if (log.isDebugEnabled())
                    {
                        log.debug("Data binding errors - " + errors.getErrorCount());
                    }
                    
                    ControlModel controlModel = getControlModel(request);
                    
                    if (controlModel != null)
                    {
                        return (showForm(request, response, errors, controlModel.getControlModelMap()));
                    }
                    else
                    {
                        return (showForm(request, response, errors, null));
                    }
                }
                else
                {
                    if (log.isDebugEnabled())
                    {
                        log.debug("No errors - processing submit");
                    }
                    
                    return (onSubmit(request, response, command, errors));
                }
            }
        
            public ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, 
                BindException errors) throws Exception 
            {
                ControlModel controlModel = process(request, response, command, errors);
                
                if (errors.hasErrors())
                {
                    if (failureView != null)
                    {
                        ModelAndView modelAndView = getModelAndView(failureView, getControlModel(request));
                        modelAndView.addAllObjects(errors.getModel());
                        
                        return (modelAndView);
                    }
                    else
                    {
                        ControlModel storedControlModel = getControlModel(request);
                    
                        if (storedControlModel != null)
                        {
                            return (showForm(request, response, errors, storedControlModel.getControlModelMap()));
                        }
                        else
                        {
                            return (showForm(request, response, errors, null));
                        }
                    }
                }
                else
                {
                    return (getModelAndView(getSuccessView(), controlModel));
                }
            }
        
            private ModelAndView getModelAndView(String viewName, ControlModel controlModel) throws Exception
            {
                ModelAndView modelAndView;
                
                if (viewName.indexOf('.') > -1)
                {
                    // This is a redirect URL
                    modelAndView = new ModelAndView(new RedirectView(viewName, true));
                }
                else
                {
                    // This is a view name
                    modelAndView = new ModelAndView(viewName);
                }
                
                if (controlModel != null)
                {
                    Map internalMap = controlModel.getControlModelMap();
                    
                    if (internalMap != null)
                    {
                        modelAndView.addAllObjects(controlModel.getControlModelMap());
                    }
                }
        
                return (modelAndView);
            }
        
            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);
            }
        
            protected final Object formBackingObject(HttpServletRequest request) throws Exception 
            {
                Object formBackingObject = createCommand();
                
                populateFormBackingObject(formBackingObject);
                
                // Store in a thread local for possible later retrieval
                formBackingObjectStore.set(formBackingObject);
                
                return (formBackingObject);
            }
        
            protected void populateFormBackingObject(Object formBackingObject)
            {
                // Nothing - override in subclass if required
            }
        
            protected ControlModel getControlModel(HttpServletRequest request) throws Exception
            {
                return (AbstractControlModel.retrieveControlModel(request));
            }
        
            protected final void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) 
                throws Exception
            {
                binder.registerCustomEditor(Boolean.class, new CustomBooleanEditor(true));
                binder.registerCustomEditor(Double.class, new CustomNumberEditor(Double.class, true));
                binder.registerCustomEditor(Integer.class, new CustomNumberEditor(Integer.class, true));
        
                initCustomBinder(request, binder);
            }
        
            protected void initCustomBinder(HttpServletRequest request, ServletRequestDataBinder binder) 
                throws Exception
            {
                // Nothing - override in subclass if required
            }
        }
        There are references to other classes that I've written, but hopefully it gives you some ideas on how to extend the standard classes. I've had to remove my JavaDoc comments and some methods to get it inside the 10000 character posting limit.

        Bob

        Comment


        • #5
          Thats awesome Bob! Earlier I misunderstood the AbstractFormController as Spring's one instead of a custom base class that we need to write ourselves.

          I suppose you can specify now, in your application configuration XML file's controller bean declaration, a new property named failureView in the following way -

          <property name="failureView"><value>errorPage</value></property>

          and load it from your form controller implementation by getFailureView()?

          Thank you again.

          Comment


          • #6
            Originally posted by ashik
            Thats awesome Bob! Earlier I misunderstood the AbstractFormController as Spring's one instead of a custom base class that we need to write ourselves.

            I suppose you can specify now, in your application configuration XML file's controller bean declaration, a new property named failureView in the following way -

            <property name="failureView"><value>errorPage</value></property>

            and load it from your form controller implementation by getFailureView()?

            Thank you again.
            Yes, that's how it works. You can inject any bean that's defined in your context into your controllers in this way.

            Comment

            Working...
            X