Wicket
  1. Wicket
  2. WICKET-1134

Multiple abstract/implement tags instead of child/extend

    Details

    • Type: New Feature New Feature
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Won't Fix
    • Affects Version/s: 1.3.0-rc1
    • Fix Version/s: 1.5-M2.1
    • Component/s: wicket
    • Labels:
      None

      Description

      The current implementation of wicket:child and wicket:extend only allows for a single extension per subpage. However, this restriction is neither mandated by java class hierarchy nor by any other reason. Therefore, it should be possible to extend the current implementation to support multiple 'abstract' sections, just like abstract methods in java classes. This could be done by replacing

      <wicket:child>
      <wicket:extend>
      some content
      </wicket:extend>
      </wicket:child>

      with

      <wicket:abstract id="foo">
      <wicket:implement id="foo">
      some content
      </wicket:extend>
      </wicket:child>

      (new names have been suggested in http://www.nabble.com/Multiple-%3Cwicket%3Achild--%3E-tags-on-a-single-base-page--tf4738673.html)

      A possible application is a layout with two columns, e.g. a header with navigation, a left column with sub-navigation and a right column with content (where the sub-navigation may change depending on the section. In deed, this is already possible using panels or similar means. However, it would allow to take advantage of markup inheritance only:

      BasePage extens WebPage:
      <div wicket:id="links>[some nav links here]</div>
      <div><wicket:abstract id="subNavigation">[left navigation goes here]</wicket:abstract></div>
      <div><wicket:abstract id="content">[content goes here]</wicket:abstract</div>

      SectionPage extends BasePage:
      <wicket:implement id="subNavigation">[sub navigation links here]</wicket:implement>

      FooPage extends SectionPage:
      <wicket:implement id="content">[content goes here]</wicket:implement>

      1. wicket-abstract-implement.patch
        29 kB
        Stefan Fussenegger
      2. wicket-1134.patch
        21 kB
        Juergen Donnerstag

        Activity

        Hide
        Stefan Fussenegger added a comment -

        from http://www.nabble.com/Patch%3A-Multiple-%3Cwicket%3Achild--%3E-tags-on-a-single-base-page--tf4759260.html:

        I want to post this patch that was inspired by this discussion: http://www.nabble.com/Multiple-%3Cwicket%3Achild--%3E-tags-on-a-single-base-page--tf

        I added two new tags called <wicket:abstract> and <wicket:implement>. They can be used similar to <wicket:child> and <wicket:extend> but with an additional (optional) attribute id. In fact, the submitted patch uses child and extend as aliases for abstract and implement respectively.

        The patch currently disables the old Markup merging completely (MergedMarkup.java). However, this is easy to change in InheritedMarkupMarkupLoader.java by commenting in the code in checkForMarkupInheritance(...) in order to use the old implementation for child/extend and the new code for abstract/implement.

        I also added a new JUnit Test that demonstrates the new feature: MarkupInheritance*_13.(html|java) (btw: all other test cases in MarkupInheritanceTest.java work with the new and old implementation)

        Please have a look and tell me what you think.

        Show
        Stefan Fussenegger added a comment - from http://www.nabble.com/Patch%3A-Multiple-%3Cwicket%3Achild--%3E-tags-on-a-single-base-page--tf4759260.html: I want to post this patch that was inspired by this discussion: http://www.nabble.com/Multiple-%3Cwicket%3Achild--%3E-tags-on-a-single-base-page--tf I added two new tags called <wicket:abstract> and <wicket:implement>. They can be used similar to <wicket:child> and <wicket:extend> but with an additional (optional) attribute id. In fact, the submitted patch uses child and extend as aliases for abstract and implement respectively. The patch currently disables the old Markup merging completely (MergedMarkup.java). However, this is easy to change in InheritedMarkupMarkupLoader.java by commenting in the code in checkForMarkupInheritance(...) in order to use the old implementation for child/extend and the new code for abstract/implement. I also added a new JUnit Test that demonstrates the new feature: MarkupInheritance*_13.(html|java) (btw: all other test cases in MarkupInheritanceTest.java work with the new and old implementation) Please have a look and tell me what you think.
        Hide
        Bruno Borges added a comment - - edited

        This implementation can already be achieved by other means, like using abstract factory methods, panels, borders, etc.
        I don't know if adding more tags just to implement such functionality will make things easier for developers.

        Developers will easily get lost trying to pick one of hundred methods to compose pages. Plus, Wicket's greatest feature Plain HTML is losing it's way if more tags were added.

        Regards

        Show
        Bruno Borges added a comment - - edited This implementation can already be achieved by other means, like using abstract factory methods, panels, borders, etc. I don't know if adding more tags just to implement such functionality will make things easier for developers. Developers will easily get lost trying to pick one of hundred methods to compose pages. Plus, Wicket's greatest feature Plain HTML is losing it's way if more tags were added. Regards
        Hide
        Stefan Fussenegger added a comment -

        @Bruno

        In deed, it is possible by other means. However, using markup inheritance isn't new at all - it's rather one of wicket's killer features! The proposed change would only improve the flexibility of this feature.

        The tag names are a suggestion by Igor Vaynberg and Chris Colman. In fact, it's only an added id attribute to the existing child/extend tags (I think most people agree, that these names aren't a very good choice, as the relationship between child and extend isn't obvious at all.) So it doesn't change the plain HTML, as you would only use abstract/implement instead of child/extend - so no change here.

        If the change is really accepted, one could still discuss whether using abstract/implement makes sense (even with child/extend as aliases).

        So just imagine, the old names are kept: is it a valuable extension to have multiple extension points on one base page (defined by IDs)?

        Show
        Stefan Fussenegger added a comment - @Bruno In deed, it is possible by other means. However, using markup inheritance isn't new at all - it's rather one of wicket's killer features! The proposed change would only improve the flexibility of this feature. The tag names are a suggestion by Igor Vaynberg and Chris Colman. In fact, it's only an added id attribute to the existing child/extend tags (I think most people agree, that these names aren't a very good choice, as the relationship between child and extend isn't obvious at all.) So it doesn't change the plain HTML, as you would only use abstract/implement instead of child/extend - so no change here. If the change is really accepted, one could still discuss whether using abstract/implement makes sense (even with child/extend as aliases). So just imagine, the old names are kept: is it a valuable extension to have multiple extension points on one base page (defined by IDs)?
        Hide
        Bruno Borges added a comment - - edited

        I think this improvement is just more of a way to "override" components declared in markups of a super class. Because this is what really happens.
        Let's check your example:

        In the BasePage, there are two fragments:

        • subNavigation
        • content

        What about if I want to have a fragment in SectionPage with id "content", but not related with that content from BasePage? You see, the concept of extend/child, is the same as in OOP's inheritance. What goes in child, is from the subclass. Period.

        In Java, if you declare:
        class BasePage ...

        { protected Object someProperty; }

        class SectionPage extends BasePage { protected Object someProperty; }

        What happens here is that SectionPage.someProperty does NOT override/implement/whatever-you-wanna-call, BasePage.someProperty. What you want to do in HTML would be this in Java.

        I'm worry about people trying to subclass some WebMarkupContainer, and having to be carefully with components ids, just to not match something that would generate strange output.

        If in SectionPage I add some component (like Label) with "content" id, what would happen? Throw a message: "You cannot use this id because there's an abstract 'content' markup in BasePage.html". This would lead to code in HTML that has NO reference within it's Java class.

        This means that: what you don't see in Java, it might be possible to exist in the HTML.

        And what I like most of Wicket, is its ability to let me take control of everything, just from one source: Java. But if I'm going to be obligated of taking care of what people declare in HTML files that I can't see in some Java source code, then I will reconsider my framework's choice.

        Regards

        Show
        Bruno Borges added a comment - - edited I think this improvement is just more of a way to "override" components declared in markups of a super class. Because this is what really happens. Let's check your example: In the BasePage, there are two fragments: subNavigation content What about if I want to have a fragment in SectionPage with id "content", but not related with that content from BasePage? You see, the concept of extend/child, is the same as in OOP's inheritance. What goes in child, is from the subclass. Period. In Java, if you declare: class BasePage ... { protected Object someProperty; } class SectionPage extends BasePage { protected Object someProperty; } What happens here is that SectionPage.someProperty does NOT override/implement/whatever-you-wanna-call, BasePage.someProperty. What you want to do in HTML would be this in Java. I'm worry about people trying to subclass some WebMarkupContainer, and having to be carefully with components ids, just to not match something that would generate strange output. If in SectionPage I add some component (like Label) with "content" id, what would happen? Throw a message: "You cannot use this id because there's an abstract 'content' markup in BasePage.html". This would lead to code in HTML that has NO reference within it's Java class. This means that: what you don't see in Java, it might be possible to exist in the HTML. And what I like most of Wicket, is its ability to let me take control of everything, just from one source: Java. But if I'm going to be obligated of taking care of what people declare in HTML files that I can't see in some Java source code, then I will reconsider my framework's choice. Regards
        Hide
        Stefan Fussenegger added a comment -

        No, ids used with abstract/implement are completely different from wicket:ids ... they are only used to construct (i.e. merge ... or link) the markup, so it is perfectly legal to use <div wicket:id="foo"> when there is a <wicket:abstract id="foo"> somewhere, as they won't be related. Therefore, no of the concerns you mention would apply, as ...

        The concept of abstract/implement is the same as in OOP's inheritance. What goes in child, is from the subclass! Exclamation mark!

        Show
        Stefan Fussenegger added a comment - No, ids used with abstract/implement are completely different from wicket:ids ... they are only used to construct (i.e. merge ... or link) the markup, so it is perfectly legal to use <div wicket:id="foo"> when there is a <wicket:abstract id="foo"> somewhere, as they won't be related. Therefore, no of the concerns you mention would apply, as ... The concept of abstract/implement is the same as in OOP's inheritance. What goes in child, is from the subclass! Exclamation mark!
        Hide
        Johan Compagner added a comment -

        move this to 1.4. Then we can look at it if we can put this into the core (<wicket:extend name="x"> and <wicket:child name="x"> ) so that everything is backwards compatible has my preference.

        Show
        Johan Compagner added a comment - move this to 1.4. Then we can look at it if we can put this into the core (<wicket:extend name="x"> and <wicket:child name="x"> ) so that everything is backwards compatible has my preference.
        Hide
        Juergen Donnerstag added a comment -

        Small update on this one:

        • generified the patch
        • minor bug fixing

        But not working properly: 3 tests failing

        The ability to have multiple "implementations" identified by an "id" attribute in derived classes obviously is not yet implemented

        No test cases yet for new features

        Show
        Juergen Donnerstag added a comment - Small update on this one: generified the patch minor bug fixing But not working properly: 3 tests failing The ability to have multiple "implementations" identified by an "id" attribute in derived classes obviously is not yet implemented No test cases yet for new features
        Hide
        Damian Nowak added a comment - - edited

        Is this going to be implemented or 1.5-M2 is just a synonymous with "we will set it to 1.6 when 1.5 is near"? It's been almost three years since the issue was created. Just to remind, there was a very long discussion about that. I provide links to the most important thoughts.

        http://www.mail-archive.com/users@wicket.apache.org/msg06304.html
        http://www.mail-archive.com/users@wicket.apache.org/msg06303.html
        http://www.mail-archive.com/users@wicket.apache.org/msg06353.html - "the real-wicket-way(tm) for multiple content-places in a tied page-area" - like going back to C "as I can achieve everything from Java in C and get better performance".
        http://www.mail-archive.com/users@wicket.apache.org/msg06336.html
        http://www.mail-archive.com/users@wicket.apache.org/msg06337.html
        http://www.mail-archive.com/users@wicket.apache.org/msg06369.html
        http://www.mail-archive.com/users@wicket.apache.org/msg06358.html
        http://apache-wicket.1842946.n4.nabble.com/Attempted-summary-of-multiple-wicket-child-thread-td1851835.html - summary.

        Even Open Power Template for PHP has got such a feature. http://static.invenzzia.org/docs/opt/2_0/single/en/#toc:syntax_instructions_snippet

        If you are not going to implement this please tell me if there are any easy ways to achieve this. I haven't found anything in docs; the mailing discussion shows only one correct solution but it doesn't look good (messing with onRenders, initializations, etc.).

        Show
        Damian Nowak added a comment - - edited Is this going to be implemented or 1.5-M2 is just a synonymous with "we will set it to 1.6 when 1.5 is near"? It's been almost three years since the issue was created. Just to remind, there was a very long discussion about that. I provide links to the most important thoughts. http://www.mail-archive.com/users@wicket.apache.org/msg06304.html http://www.mail-archive.com/users@wicket.apache.org/msg06303.html http://www.mail-archive.com/users@wicket.apache.org/msg06353.html - "the real-wicket-way(tm) for multiple content-places in a tied page-area" - like going back to C "as I can achieve everything from Java in C and get better performance". http://www.mail-archive.com/users@wicket.apache.org/msg06336.html http://www.mail-archive.com/users@wicket.apache.org/msg06337.html http://www.mail-archive.com/users@wicket.apache.org/msg06369.html http://www.mail-archive.com/users@wicket.apache.org/msg06358.html http://apache-wicket.1842946.n4.nabble.com/Attempted-summary-of-multiple-wicket-child-thread-td1851835.html - summary. Even Open Power Template for PHP has got such a feature. http://static.invenzzia.org/docs/opt/2_0/single/en/#toc:syntax_instructions_snippet If you are not going to implement this please tell me if there are any easy ways to achieve this. I haven't found anything in docs; the mailing discussion shows only one correct solution but it doesn't look good (messing with onRenders, initializations, etc.).
        Hide
        Igor Vaynberg added a comment - - edited

        alternatives to this have been discussed and shown many times

        class basepage extends webpage {
        protected abstract Component newArea1(String id);
        protected abstract Component newArea2(String id);
        protected void onInitialize()

        { add(newArea1("a1")); add(newArea2("a2")); }

        }

        <html><body><div wicket:id="a1"></div><div wicket:id="a2"></div></body></html>

        newArea1() and 2() can return a panel or a fragment or anything else that can be attached to the tag it is assigned in the base page.

        it is a simple and elegant solution. i am not sure that implementing it using these extra tags is a better idea as it would still require that each area of the webpage is populated by a separate method in order to maintain any kind of extensibility.

        indeed, can be almost exactly implemented using the standard wicket:fragment tag instead of two new tags that complicate things and make tracing which markup comes from where more difficult.

        Show
        Igor Vaynberg added a comment - - edited alternatives to this have been discussed and shown many times class basepage extends webpage { protected abstract Component newArea1(String id); protected abstract Component newArea2(String id); protected void onInitialize() { add(newArea1("a1")); add(newArea2("a2")); } } <html><body><div wicket:id="a1"></div><div wicket:id="a2"></div></body></html> newArea1() and 2() can return a panel or a fragment or anything else that can be attached to the tag it is assigned in the base page. it is a simple and elegant solution. i am not sure that implementing it using these extra tags is a better idea as it would still require that each area of the webpage is populated by a separate method in order to maintain any kind of extensibility. indeed, can be almost exactly implemented using the standard wicket:fragment tag instead of two new tags that complicate things and make tracing which markup comes from where more difficult.
        Hide
        Igor Vaynberg added a comment -

        obsoleted by Component#onInitialize() which makes it trivial to implement this using panels or fragments, which from the core committer point-of-view has been adopted as a cleaner solution to this problem.

        Show
        Igor Vaynberg added a comment - obsoleted by Component#onInitialize() which makes it trivial to implement this using panels or fragments, which from the core committer point-of-view has been adopted as a cleaner solution to this problem.
        Hide
        Abul Fayes added a comment - - edited

        It is sad so see that the resolution is set to "Won't Fix" which I understand to mean it won't be implemented. The ability to reuse the same parent html markup in multiple child pages and have the ability to override one to many sections is a basic functionality in templating technologies. You can do this in Django, Apache tiles, and I am sure there are other countless examples that I am not aware of.

        @igor: the abstract method technique where each child class provides the custom components is not a complete solution to the problem. if there are 100 child pages where the only difference is two content areas, each child page will also have to reconstitute/duplicate the common markup areas such as nav, footer etc. whereas child pages should only provide markup for overridden areas. In the case where you want to restyle/reposition div elements, if the functionality in question was implemented this would mean mainly changing the base markup rather than a 100 html files! unless of course I have misunderstood something

        I am not particularly fussy whether new tags are used e.g. abstract/implement or the current child/extend with id, it is the functionality is which most important.

        a side note: A badly implemented framework which is easy to use and has all the required functionality will be more widely used than a well implemented framework that does not provide what people NEED!

        Show
        Abul Fayes added a comment - - edited It is sad so see that the resolution is set to "Won't Fix" which I understand to mean it won't be implemented. The ability to reuse the same parent html markup in multiple child pages and have the ability to override one to many sections is a basic functionality in templating technologies. You can do this in Django, Apache tiles, and I am sure there are other countless examples that I am not aware of. @igor: the abstract method technique where each child class provides the custom components is not a complete solution to the problem. if there are 100 child pages where the only difference is two content areas, each child page will also have to reconstitute/duplicate the common markup areas such as nav, footer etc. whereas child pages should only provide markup for overridden areas. In the case where you want to restyle/reposition div elements, if the functionality in question was implemented this would mean mainly changing the base markup rather than a 100 html files! unless of course I have misunderstood something I am not particularly fussy whether new tags are used e.g. abstract/implement or the current child/extend with id, it is the functionality is which most important. a side note: A badly implemented framework which is easy to use and has all the required functionality will be more widely used than a well implemented framework that does not provide what people NEED!
        Hide
        Juergen Donnerstag added a comment -

        @Abul: why do you need to maintain 100 page markups? It's perfectly ok that BasePage only has associated markup. SectionPage only needs to add the "abstract" components, which in case of Panel have their own associated markup.

        Show
        Juergen Donnerstag added a comment - @Abul: why do you need to maintain 100 page markups? It's perfectly ok that BasePage only has associated markup. SectionPage only needs to add the "abstract" components, which in case of Panel have their own associated markup.
        Hide
        Abul Fayes added a comment -

        @Juergen: I have written some simple test code to test out what you said and it turns out you are right. Child pages that extend a base page use the same html markup, for some reason I believed otherwise.

        In that case the abstract component technique is fine and perhaps an elegant solution. The multiple child/extend functionality I guess will not add much in the way of extra functionality but perhaps make it clear which areas are/can be overridden. The drawback with multiple child/extend is however that it requires extra coding e.g. creating the extra html pages which could be many, therefore If both approaches were available I would probably prefer the abstract technique anyway! Plus content areas/components can be made 'optional' to override if the getComponent method is not abstract, whereas with the multiple child/extend this would require extra tag semantics.

        I have been having fun with Wicket the past few weeks whilst going through Wicket In Action. After reading 'Composing you pages' chapter 7, I felt that having 1 child/extend was to restrictive for real world needs which is what led me to search the net and find this issue. The chapter addresses this drawback by discussing panel swapping based on link actions which is very messy if you have many pages and also the URL does not change. The chapter could definitely be improved by illustrating the abstract method technique.

        Show
        Abul Fayes added a comment - @Juergen: I have written some simple test code to test out what you said and it turns out you are right. Child pages that extend a base page use the same html markup, for some reason I believed otherwise. In that case the abstract component technique is fine and perhaps an elegant solution. The multiple child/extend functionality I guess will not add much in the way of extra functionality but perhaps make it clear which areas are/can be overridden. The drawback with multiple child/extend is however that it requires extra coding e.g. creating the extra html pages which could be many, therefore If both approaches were available I would probably prefer the abstract technique anyway! Plus content areas/components can be made 'optional' to override if the getComponent method is not abstract, whereas with the multiple child/extend this would require extra tag semantics. I have been having fun with Wicket the past few weeks whilst going through Wicket In Action. After reading 'Composing you pages' chapter 7, I felt that having 1 child/extend was to restrictive for real world needs which is what led me to search the net and find this issue. The chapter addresses this drawback by discussing panel swapping based on link actions which is very messy if you have many pages and also the URL does not change. The chapter could definitely be improved by illustrating the abstract method technique.

          People

          • Assignee:
            Igor Vaynberg
            Reporter:
            Stefan Fussenegger
          • Votes:
            7 Vote for this issue
            Watchers:
            8 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development