Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: AbstractWizardFormController is bugged.

  1. #1

    Unhappy 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. #2
    Join Date
    Jul 2005
    Posts
    246

    Default

    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

  3. #3
    Join Date
    Aug 2004
    Location
    Hawaii, US
    Posts
    225

    Default

    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.

  4. #4
    Join Date
    Aug 2004
    Location
    Hawaii, US
    Posts
    225

    Default

    Quote 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.

  5. #5
    Join Date
    Aug 2004
    Location
    Hawaii, US
    Posts
    225

    Default

    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

  6. #6
    Join Date
    Aug 2004
    Location
    Sydney
    Posts
    503

    Default

    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.

  7. #7

    Default

    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

  8. #8
    Join Date
    Aug 2004
    Location
    Hawaii, US
    Posts
    225

    Default

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

    Good luck.

  9. #9

    Default

    Quote 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.

  10. #10

    Default

    Quote 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.

    Quote 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.

    Quote 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.

Posting Permissions

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