Announcement Announcement Module
Collapse
No announcement yet.
AbstractWizardFormController is bugged. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • AbstractWizardFormController is bugged.

    There are a number of methods:

    protected int getInitialPage(HttpServletRequest request)
    protected String getViewName(HttpServletRequest request, Object command, int page)
    protected int getPageCount(HttpServletRequest request, Object command)

    which the JavaDoc says you can override in order to implement, for example, dynamic lists of pages (which is what I need: the pages in the wizard should change based on choices made on the first page).

    The problem is that the showPage method simply calls getPages() and decides for itself which page to show next!

    OK, I thought, so I'll override getPages() to return my dynamic list: but you can't because getPages(), a method on an abstract class, has been declared final!

    So that only leaves me with one option: to inappropriately override another method (I'm thinking of onBindAndValidate to setPages()) to set my dynamic list of views. I'd always wondered why there were no real examples of a wizard beyond the simple fixed set of pages ones in the pet store sample.

  • #2
    I feel your pain. I'm not using any AbstractWizardFormControllers but I've found on my Spring travels that the developers have maybe been a bit overzealous with the 'final' keyword ;-)

    I've often had to resort to slightly hacky behaviour in order to override some behaviour.

    My personal opinion is that developers should not be treated as so dumb. If I override a method that completely breaks the functionality then it's my fault, but I should still be able to do it.

    Bob

    Comment


    • #3
      Just a quick note, the final keyword is not necessarily added because developers are dumb.

      Check out the Open-Closed principle:
      http://www.objectmentor.com/resources/articles/ocp.pdf

      It basically states that a class should be open for extension but closed for change. In other words, the final keyword is there to keep you from changing the behavior of the class. However, the class *should* provide extension points, which is why you see so many onXxx methods. Those "on" methods generally are the extension points for you to plug into.

      I've found the developers to generally be helpful and accomodating, so if you need an extension method, just ask.

      Now, I'm not sure if that helped at all with the above post.

      Comment


      • #4
        Originally posted by Edward Kenworthy
        I'd always wondered why there were no real examples of a wizard beyond the simple fixed set of pages ones in the pet store sample.
        Because the wizard isn't meant for complex workflows. If you're looking for dynamic or complex user experiences, consider Spring Web Flow.

        I'd consider the wizard good at one thing: splitting an otherwise large form into multiple pages. It's just not a class meant for dynamic behavior. Once I accepted that, I wasn't so angry at the class anymore.

        I do consider it very helpful when I do have a 2 or 3 page form. Otherwise, I go to Spring Web Flow.

        Comment


        • #5
          OK, now that I've actually read your post, I think it's easy to solve your problem.

          You are thinking you want to change the pages array inside the controller. This won't work because the controller is a singleton, and each user needs their own copy of the collection of pages. Instead of trying to change the controller's pages array, store each user's collection of pages inside the session.

          Then, override getViewName() and return the next page from the collection you found in the user's session. Luckily, getViewName() takes a HttpServletRequest.

          Hope that helps,
          Seth

          Comment


          • #6
            Hi Edward,

            We sort of do what you want, by just putting all possible pages that can appear in the wizard, and then drawing tabs along the top for the pages that are visible.

            Our wizard framework class, MultiViewSupport (extends AbstractWizardFormController) has a TabPolicy class injected. The default implementation shows all tabs.

            You can inject a different TabPolicy implementation that can run any sort of rules to work out which tab pages to show.

            TabPolicy just has one method currently, boolean isTabVisible(String name);, but seems to do what we need, where 'name' is the Tiles name of the page.

            If pages 0 and 2 were visible, then the Next button of page 0 would have _target2 in it, not _target1.

            Comment


            • #7
              Thanks all, given me some things to think about.

              I've don't use _targetX as that would mean encoding the flow in the page.

              As to the controller being a singleton, forgot about that but it's a trivial change to make it not a singleton. But I do like the idea of putting that information in the session.

              Edward

              Comment


              • #8
                Just to note, you don't have to use _target, you can override getTargetPage if you like.

                Good luck.

                Comment


                • #9
                  Originally posted by sethladd
                  Then, override getViewName() and return the next page from the collection you found in the user's session. Luckily, getViewName() takes a HttpServletRequest.
                  Unfortunately not. "The problem is that the showPage method simply calls getPages() and decides for itself which page to show next!" so getViewName() doesn't get called.

                  Comment


                  • #10
                    Originally posted by sethladd
                    Just a quick note, the final keyword is not necessarily added because developers are dumb.
                    I think he was saying the spring dev team were treating developers using spring as dumb. I think he's right.

                    Originally posted by sethladd
                    Check out the Open-Closed principle:
                    http://www.objectmentor.com/resources/articles/ocp.pdf
                    It basically states that a class should be open for extension but closed for change. In other words, the final keyword is there to keep you from changing the behavior of the class. However, the class *should* provide extension points, which is why you see so many onXxx methods. Those "on" methods generally are the extension points for you to plug into.
                    Doesn't mean it's right, in fact what it means is that you can't extend a class in a way the class designer didn't think of. Which I think is bad. Final should be a very last resort, it's only just behind of static in terms of easily abused.

                    Originally posted by sethladd
                    I've found the developers to generally be helpful and accomodating, so if you need an extension method, just ask.
                    The problem is, because of their use of final and because showForm() doesn't call the extension point methods the class isn't extensible. The design is flawed.

                    Comment


                    • #11
                      Originally posted by Edward Kenworthy
                      I think he was saying the spring dev team were treating developers using spring as dumb. I think he's right.



                      Doesn't mean it's right, in fact what it means is that you can't extend a class in a way the class designer didn't think of. Which I think is bad. Final should be a very last resort, it's only just behind of static in terms of easily abused.



                      The problem is, because of their use of final and because showForm() doesn't call the extension point methods the class isn't extensible. The design is flawed.
                      Exactly. That is what I meant with my "dumb" comment.

                      I'm entirely in agreement here. The final keyword should be used extremely sparingly not as a matter of course.

                      I happen to think that Spring is a great framework, but it's biggest downfall is its lack of extensibility.

                      OCP works when you're writing code for a very specific task, but in a framework which is designed to potentially be used for anything the developer can imagine, it's an extremely bad idea IMO since it implies that the framework architect has thought of and catered for every use case possible. Of course, that can never be the case.

                      Bob

                      Comment


                      • #12
                        I absolutely disagree

                        Using final is a very valid way to ensure correct behaviour.

                        If things were defined as final, I guarantee there would be far more posts on here "saying ClassXYZ is broken", and actually it isn't broken, but developers, who sometimes *are* dumb have forgotten to call super.method.

                        Before you shoot this down in flames, go and check how many methods you have overridden and forgotten to call super, and check how many constructors you have created that don't call super

                        Comment


                        • #13
                          Originally posted by Edward Kenworthy
                          Unfortunately not. "The problem is that the showPage method simply calls getPages() and decides for itself which page to show next!" so getViewName() doesn't get called.
                          Ah, I see exactly what you mean. It's worth opening a JIRA issue requesting this be fixed.

                          Comment


                          • #14
                            Originally posted by Cowboy Bob
                            I happen to think that Spring is a great framework, but it's biggest downfall is its lack of extensibility.
                            I respect your opinion, but...

                            That's odd, I happen to think Spring is one of the most extensible framework's I've used. A lot of frameworks don't take into account these design principles, which leads to a less flexible design later.

                            If I've ever run into a situation where I couldn't add behavior, the developers usually are willing to add in an extension point. It's worth a shot.

                            Comment

                            Working...
                            X