Announcement Announcement Module
Collapse
No announcement yet.
HMVC: Chaining controllers & models made simple Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • HMVC: Chaining controllers & models made simple

    Hallo everybody,

    I registered that many people are looking for controller chaining or some kind of hmvc (hierarchical model view controllers) following this simple diagram:

    Code:
    View&#40;Model1,2,3&#41; <-> Controller 1&#40;Model1&#41;  <-> Controller 2&#40;Model 2&#41; <-> Controller 3 &#40;Model 3&#41;
    http://www.javaworld.com/javaworld/j...0721-hmvc1.gif
    As seen at java.com

    In this case you do not need to implement someting special in spring, you can just chain controllers and their execution if you define a following kind of controller within the parent and merge resulting model data:

    Code:
    public class Page  &#123;
    
        /** Build hierarchical page flow by refererencing to other pages */
        private HashMap<String, Page> subPages = new HashMap<String, Page>&#40;&#41;;
    
        /**
         * This is our page specific controller
         */
        private Controller controller;
    
        public Controller getController&#40;&#41; &#123;
            return controller;
        &#125;
    
        public void setController&#40;Controller controller&#41; &#123;
            this.controller = controller;
        &#125;
    
       
        /** Here is our hierarchy !! */
        public HashMap<String, Page> getSubPages&#40;&#41; &#123;
            return subPages;
        &#125;
    
        public void setSubPages&#40;HashMap<String, Page> subPages&#41; &#123;
            this.subPages = subPages;
        &#125;
        
        public Page&#40;&#41; &#123;
        &#125;
    
    &#125;

    Now you can simply define a ModelAndView Chain in the top page and any subsequent page by simply coding a model merger:

    Code:
    public ModelAndView handleRequest&#40;HttpServletRequest request, HttpServletResponse response&#41;
                throws ServletException, Exception &#123;
      ... 
      Map model = new HashMap&#40;&#41;;
      model.put&#40;"selectedTopPage",             selectedTopPage&#41;;
      model.put&#40;"selectedSubPage",             selectedSubPage&#41;;
      model.put&#40;"selectedTopPageName",     selectedTopPageName&#41;;
      model.put&#40;"selectedSubPageName",     selectedSubPageName&#41;;
      ...
    
      /** THE FOLLOWING LINES ARE FOR CHAINING AND MERGING */
      /** BOTH MODELS ARE MERGED, YOU COULD EVEN PUSH THE RESULTING VIEW FROM SUB PAGES*/
      if &#40;selectedSubPage.getController&#40;&#41; != null&#41;&#123;
        model.putAll&#40;
             selectedSubPage.getController&#40;&#41;.handleRequest&#40;request,
             response&#41;.getModel&#40;&#41;&#41;;
      &#125;
    
       return new ModelAndView&#40;pageLayout.getView&#40;&#41;, "model", model&#41;;
    &#125;

    This works very perfect for me and should be applicable to most web applications page layout and navigation patterns with subsequent page structures and differnt controllers for each subpage. Please sorry me about not posting the whole code here, but it is not hard to implement. This approach even subsitutes the need for components or struts tiles )

    More detailed information about hmvc can be found here: http://www.javaworld.com/javaworld/j...21-hmvc_p.html
    (MVC layers from Javaworld.com)

    Just contact me when you need more information about it, I appreciate any direct questions within this forum or as openbc question.

    Andreas Bednarz, Germany - Hannover
    Senior J2EE Developer

    https://www.openbc.com/hp/Andreas_Bednarz/

  • #2
    To be honest, I wouldn't do it like that personally. I'd have one controller per action as normal, but implement a command pattern set of interfaces that can be chained behind as the logic - I don't like any logic in my controllers if I can help it.

    The way I do it currently is to define a ControlModel interface which is obtained like so in my own AbstractFormController which is a sub-class of SimpleFormController:-

    Code:
        /**
         * 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 control model
         * @throws Exception If there are any problems with the form processing
         */
        protected abstract ControlModel process&#40;HttpServletRequest request, HttpServletResponse response, Object command,
            BindException errors&#41; throws Exception;
    The onSubmit() method of SimpleFormController is overridden to call the new process method and deal with the returning ControlModel by calling ModelAndView.addAllObjects(ControlModel.getControl ModelMap());

    The ControlModel interface includes provision for chaining, so all the logic is handled outside the controller.

    Code:
    public interface ControlModel
    &#123;
        /**
         * A key under which the control model can be stored in the session
         */
        public static final String CONTROL_MODEL_KEY = "uk.co.mpcontracting.modules.spring.model.ControlModel.CONTROL_MODEL_KEY";
    
        /**
         * Adds a child control model to this control model
         *
         * @param controlModel The child control model
         */
        public void addChildControlModel&#40;ControlModel controlModel&#41;;
    
        /**
         * Retrieves the internal control model map - the logic inside the
         * control model is not run until this methods is called.
         *
         * @return The internal control model map
         * @throws Exception If there is an error retrieving the map
         */
        public Map getControlModelMap&#40;&#41; throws Exception;
        
        /**
         * Stores the control model for later retrieval
    
         *
         * @param request The request
         * @throws Exception If there is an error storing the control model
         */
        public void storeControlModel&#40;HttpServletRequest request&#41; throws Exception;
    &#125;
    I have an AbstractControlModel that deals with some common stuff like storing the model in the session for later retrieval.

    So in the process method, the control models can be chained, or individual control models can add other control models to themselves based on input parameters into their constructors.

    This way I can keep chunks of reusable logic in discrete chunks, but don't have to write any logic in my controllers.

    Bob

    Comment


    • #3
      Also a well done approach

      Hi Bob,

      this is also a well done approach. I think it depends on your application structure and seems also to depend on your session behaviour. What I have tried to realize is a complete session independand approach, so that navigational elements do not have to be stored within user sessions and just depend on url patterns. My url pattern are like this:

      Code:
      &#123;toppageaction&#125;_&#123;subpageaction&#125;.html
      and as example

      Code:
      index_mysettings.html
      where index is bound to a pagelayout action and mysetting is bound to a subpage with an assosiated controller. If you visit my example application shown as viewlett below, you will see that my top level pages are located in the main selection, any click on them just changes to content only and that the view is fed by multiple models just as viewable in bottom text. Viewresolving behind this is done by velocity and #parse tag which includes subpages belonging to each toppage and subpage combination. Toppages layouts are not redundant but kept as a single velocity template. You could do it with jSP also the same way.

      Main benefit of my way I that I can redesign behaviour and page layout within minutes without worry about my controllers just by shuffling my page layout beans.

      http://www.viewletcentral.com/vc/vie...ml?id=41542646

      My best,

      Andreas Bednarz, Hannover / Germany

      Comment


      • #4
        Chaining controllers - yet another implementation

        Hi,

        I have done something along the lines of Cowboy Bob's approach if anyone is interested. Code and configuration description are here in this blog:
        http://sujitpal.blogspot.com/2006/02...in-chains.html
        and some bug fixes to the original code:
        http://sujitpal.blogspot.com/2006/02...in-chains.html

        The code I have up here also allows you to chain controllers serially or parallelly, or in a hybrid chain.

        This appears to be a fairly common requirement for apps which deliver portal-style pages, such as a Yahoo! finance page with company reports, stock charts, user's portfolio, etc, where the information is related for the user, but probably uses very different controllers for each component. Chaining independent controllers (which are easy to develop in parallel and unit test in isolation) to populate the ModelAndView appears to be better than writing a monolithic controller that calls on various services. Adding or removing a component in the former case is a matter of configuration change, while the monolithic approach means that there must be some code change.

        So I am wondering why the Spring team does not include this sort of functionality in the distribution. I ask because I am concerned if there is some problems with this approach that I am overlooking, or if there is another better, recommended way to achieve this functionality.

        Thanks
        Sujit

        Comment


        • #5
          Thanks joe!

          hi joe!

          Thank you for your exciting post!

          I really admire your assiduity !

          I didn't know the things you said!:o

          as it shows, you should help me to know it!

          I'm waiting for your other posts & if I find any other thing let you know, too!

          Comment

          Working...
          X