1 2 Previous Next 15 Replies Latest reply on Sep 16, 2009 4:23 AM by Stuart Douglas

    Component Inheritance

    Fijai Cairo Newbie

      Hello all,
      Is it possible to have multiple subclasses of an abstract class share the same component name so that they may be used in different scenarios?


      I can achieve my goal using composition but not without writing a ton of delegation methods.


      I'd like to be able to do the following but that doesn't work. How else can I achieve the same result?




      @Name("widget")
      public abstract class Widget...
      
      public class WidgetType1 extends Widget...
      public class WidgetType2 extends Widget...



      I want to be able to use either subclass as a widget component.



      @In(required=false) @Out(required=false) Widget widget;
      
      if(isType1Transaction)
         widget = new WidgetType1();
      
      if(isType2Transaction)
         widget = new WidgetType2();
      




        • 1. Re: Component Inheritance
          Joshua Jackson Master

          Why not use interface instead of abstract class for this case?


          best regards,

          • 2. Re: Component Inheritance
            Michael Brackx Newbie

            You can use a Factory for this


                 @Factory("widget")
                 public Widget createWidget() {
                      if(isType1Transaction)
                         return new WidgetType1();
                      if(isType2Transaction)
                         return new WidgetType2();
                      ...
                 }
            



            • 3. Re: Component Inheritance
              Fijai Cairo Newbie

              Thanks. So WidgetType1 and WidgetType2 don't even have to be annotated with @Name? Does that limit their usefulness?
              Thanks

              • 4. Re: Component Inheritance
                Fijai Cairo Newbie

                Thanks. Well i have a fair bit of default functionality that I'd like to inherit.

                • 5. Re: Component Inheritance
                  Joseph Nusairat Newbie

                  Michael:


                  I was curious on your example. Have you tried that out? Just seems like it wouldn't work.


                  I understand the concept of the factory. However if you are returning a new WidgetType1() ... then will any Seam components inside it be injected? I would think you'd need Seam to instantiate it for you for that to happen?


                  Maybe i am wrong here. But instead of that couldnt you do something like the following:


                  Make Widget1 and Widget2 Seam components directly.


                  Then inject them into whatever class that factory is in and then use your factory to return the injected component.


                  Btw to the OP your abstract class should still implement an interface. you dont really want to do the servicing on a concrete class.

                  • 6. Re: Component Inheritance
                    Jack Chen Newbie

                    So did Joseph's proposed solution work for you Fijai Cairo?

                    • 7. Re: Component Inheritance
                      Jack Chen Newbie

                      I'm experiencing a similar problem to Fijai.
                      I tried Joseph's suggested solution of injecting all the different 'WidgetType' into a factory class. Then call the factory class for the correct WidgetType for the specific instance.


                      public abstract class Widget{
                       public Widget(){
                        System.out.println("new Widget");  //1
                       }
                       ...
                      }
                      
                      @Name("widgetType1")
                      public class WidgetType1 extends Widget...
                      @Name("widgetType2")
                      public class WidgetType2 extends Widget...
                      




                      @Name("WidgetFactory")
                      @Scope(ScopeType.APPLICATION)
                      public class WidgetFactory {
                       @In private Widget widgetType1;
                       @In private Widget widgetType2;
                      
                       @Out(scope=ScopeType.CONVERSATION)
                       private Widget widget;
                      
                       @Factory("widget")
                       public Widget loadWidget(){
                        if(isType1Transaction)
                         return widgetType1;
                        if(isType2Transaction)
                         return widgetType2;
                       }
                      ...
                      }
                      



                      It all worked. But I noticed, when I call #{widget} in my xhtml file in a new conversation, all the constructors on all the WidgetTypes defined to be injected gets called - Even if the Widget is not being used. Is there a way to optimize this?

                      • 8. Re: Component Inheritance
                        Stuart Douglas Master

                        Use Component.getInstance() rather than injection.

                        • 9. Re: Component Inheritance
                          Stuart Douglas Master

                          Also why do you have the @Out? Is there more to the class that what you have shown us? Also widget will be outjected to the application scope, is that really what you are after?

                          • 10. Re: Component Inheritance
                            Fijai Cairo Newbie

                            Hi All,
                            Sorry for the late response. I actually never got to try Joseph's suggestion. I must have missed the email or something. What I ended doing is illustrated below. I'm writing this from memory so bear with me.



                            @In(required=false) @Out(required=false) Widget1 widget1;
                            @In(required=false) @Out(required=false) Widget2 widget2;
                            @In(required=false) @Out(required=false) CommonWidgetStuff commonWidgetStuff;
                            
                            //BaseWidget isn't a seam component
                            BaseWidget widget = (isType1Transaction) ? widget1 : widget2;
                            
                            widget.initialize()
                            widget.doStuff();
                            commonWidgetStuff.doStuff();
                            



                            Note that widget isn't a seam component so on my views I use {widget1.xxx} and {commonWidgetStuff.xxx}.


                            Both widget1 and widget2 get constructed when actions are invoked but I do the meaningful initialization explicitly with a method call.


                            • 11. Re: Component Inheritance
                              Fijai Cairo Newbie

                              I think my post needs clearing up...



                              //Isn't a Seam component but still has annotations for bijection
                              
                              public class BaseWidget{
                                  @In(required = false)
                                  @Out(required = false, scope = CONVERSATION)
                                  protected OrderDisplayHelper orderDisplayHelper;
                              // Common stuff and hooks 
                              
                              }
                              
                              @Name("widget1")
                              public class Widget1 extends BaseWidget{
                                //custom overrides
                              }
                              
                              @Name("widget2")
                              public class Widget2 extends BaseWidget{
                                //custom overrides
                              }
                              





                              @In(required=false) @Out(required=false) Widget1 widget1;
                              @In(required=false) @Out(required=false) Widget2 widget2;
                              //The commonWidgetStuff makes it easy to use fragments/includes.
                              @In(required=false) @Out(required=false) CommonWidgetStuff commonWidgetStuff;
                              
                              //BaseWidget isn't a seam component
                              BaseWidget widget;
                              
                              
                               public string doSomeAction(){
                                widget = (isType1Transaction) ? widget1 : widget2;
                                widget.initialize()
                                widget.doStuff();
                                commonWidgetStuff.doStuff();
                                return widget.someActionView();
                               }
                              
                               public string doAnotherAction(){
                                widget = (isType1Transaction) ? widget1 : widget2;
                                widget.initialize()
                                widget.doStuff();
                                commonWidgetStuff.doStuff();
                                return widget.someOtherView();
                               }



                              • 12. Re: Component Inheritance
                                Jack Chen Newbie

                                Thanks Stuart. I haven't tried with Component.getInstance (will let you all know when I do). I ended up using:

                                Expressions.instance().createValueExpression(expression)

                                . i.e: Expressions.instance().createValueExpression(#{widget2}). Will explain the how I did it shortly.


                                Stuart, why will: @Out(scope ScopeType.CONVERSATION) private Widget widget; be outjected to APPLICATION scope? I was hoping for it to outject to CONVERSATION scope.


                                Fijai, thanks for getting back to us. :)
                                In your case, I believe both Widget1 and Widget2 will be injected on each method call, even if it's not been used. It probably suited your application, but since I had more than 2 'widgets' I thought it'll be too inefficient?

                                • 13. Re: Component Inheritance
                                  Jack Chen Newbie

                                  Ok, here's my current implementation (open to improvements):




                                  public abstract class Widget{
                                   public Widget(){
                                    System.out.println("new Widget");  //1
                                   }
                                   ...
                                  }
                                  
                                  @Name("widgetType1")
                                  public class WidgetType1 extends Widget...
                                  @Name("widgetType2")
                                  public class WidgetType2 extends Widget...





                                  @Name("WidgetFactory")
                                  @Scope(ScopeType.APPLICATION)
                                  public class WidgetFactory {
                                   @Out(scope=CONVERSATION)
                                   private Widget widget;
                                  
                                   @Factory("widget")
                                   public Widget loadWidget(){
                                    if(isType1Transaction)
                                     widget = (Widget)Expressions.instance().createValueExpression(\"\#{widget1}\");
                                    if(isType2Transaction)
                                     widget = (Widget)Expressions.instance().createValueExpression(\"\#{widget2}\");
                                   }
                                  ...
                                  }
                                  



                                  The good thing is it doesn't inject all WidgetType(s). And the seam annotations work on the WidgetType classes.



                                  • 14. Re: Component Inheritance
                                    Fijai Cairo Newbie

                                    I remember trying a factory method as well but used





                                    widget = (isType1Transaction)? new Widget1() : new Widget2();
                                    




                                    but that didn't work. I'll try using the value expression.

                                    1 2 Previous Next