6 Replies Latest reply on Feb 16, 2007 2:30 PM by fhh

    Protected methods on Seam components

    Mike Quilleash Newbie

      Hi all,

      If I have a protected method in some circumstances on a Seam component I get an error when the method is called via a cglib proxy.
      I get this exception thrown out of the cglib MethodProxy class.

       throw new IllegalArgumentException("Protected method: " + sig1);
      


      The class structure involved..

      @Scope( ScopeType.STATELESS )
      public abstract class ScreenActionComponent
      {
       public abstract void execute( ScreenActionMetadata screenActionMetadata, ScreenActionContext screenActionContext );
      
       public abstract ScreenActionMetadata[] getScreenActionMetadata( ScreenActionContext screenActionContext );
      }
      


      public abstract class SingleItemScreenAction extends ScreenActionComponent
      {
       public final void execute( ScreenActionMetadata screenActionMetadata, ScreenActionContext screenActionContext )
       {
       execute( screenActionContext );
       }
      
       public final ScreenActionMetadata[] getScreenActionMetadata( ScreenActionContext screenActionContext )
       {
       if ( isValidSelection( screenActionContext ) )
       return new ScreenActionMetadata[]{ new DefaultScreenActionMetadata( getDisplay(), getTooltip(), getImage() ) };
       else
       return new ScreenActionMetadata[ 0 ];
       }
      
       protected abstract void execute( ScreenActionContext screenActionContext );
       protected abstract boolean isValidSelection( ScreenActionContext screenActionContext );
       protected abstract String getDisplay();
       protected abstract String getTooltip();
       protected abstract String getImage();
      }
      


      @Name( "deleteEntityScreenAction" )
      public class DeleteEntityScreenAction extends SingleItemScreenAction
      {
       @In
       private Session referenceSession;
      
       public void execute( ScreenActionContext screenActionContext )
       {
       // TODO
       }
      
       public boolean isValidSelection( ScreenActionContext screenActionContext )
       {
       return !screenActionContext.getSelection().isEmpty();
       }
      
       protected final String getDisplay()
       {
       return "Delete";
       }
      
       protected final String getTooltip()
       {
       return "Logically deletes the selected items";
       }
      
       protected final String getImage()
       {
       // TODO:
       return null;
       }
      }
      


      Without the final modifiers on the DeleteEntityScreenAction getXXX methods I get the above exception when they are called from SingleItemScreenAction.getScreenActionMetadata(). But obviously with the final modifier I get no interception/bijection etc.

      Wondered if this is a known limitation in cglib or not.

      Cheers.

      Mike.


        • 1. Re: Protected methods on Seam components
          fhh Expert

          I don't get it.

          Why do you want to declare your methods protected? And why will you "obviously" not get bijection if you declare a completly different method final?

          Regards

          Felix

          • 2. Re: Protected methods on Seam components
            Mike Quilleash Newbie

            I don't have to have them protected in this instance but I'm using the SingleItemScreenAction class here to make life easier for implementors so all they have to define are some simple getters(). Making them protected means they are only accessible to subclasses which is what I want.

            Perhaps not so "obviously" :) but Seam uses a cglib proxy to wrap all component objects it creates. The proxy object subclasses the component so the Seam interceptors are called on each method call which, amongst other things, handles the bijection around calling the actual target method. A final method can't be subclassed so cglib doesn't add a method proxy for them so you get no Seam interception and therefore no bijection.

            Still not sure why a method being protected means cglib can't proxy it tho.

            • 3. Re: Protected methods on Seam components
              fhh Expert

               


              I don't have to have them protected in this instance but I'm using the SingleItemScreenAction class here to make life easier for implementors so all they have to define are some simple getters(). Making them protected means they are only accessible to subclasses which is what I want.


              It means that they are only accessible from subclasses or from any class of that package. Anyway, that is not a security feature. It is used to seperate visible api from implementation details. If you are the sole developer, why bother?


              A final method can't be subclassed so cglib doesn't add a method proxy for them


              Yes, but you annotated referenceSession. You did not show getters and setters for that property but I assume they are not final.

              And I still don't get what you are trying to do. From what object are you calling your protected method?

              Regards

              Felix

              • 4. Re: Protected methods on Seam components
                Pete Muir Master

                [Sorry about the rant below - I would claim its an attempt to drag back on topic, but as I can't answer the question I guess it isn't ;)]

                "fhh" wrote:
                It means that they are only accessible from subclasses or from any class of that package. Anyway, that is not a security feature. It is used to seperate visible api from implementation details. If you are the sole developer, why bother?


                What? Are you saying that we aren't allowed to use protected methods if we work on small projects?! I would still use encapsulation even when I was working alone - for a start it helps describe the code (and how you should call methods, secondly its kinda a fundamental part of OO.

                Anyway, Mike quite clearly stated he was implementing this code so that it would make the implementors (aka other developers) life easier - I would infer he *is* writing an API (albeit for internal use).


                A final method can't be subclassed so cglib doesn't add a method proxy for them


                Yes, but you annotated referenceSession. You did not show getters and setters for that property but I assume they are not final.


                No. Mike is making the point that cglib subclasses the component, and through this allows Seam to biject. If a method is final then it can't be altered (hmm, not sure if this is true when using reflection or not) and so bijection cannot occur. (Please note that I'm not saying this is what happens at all, just interpreting what Mike said ;) - I have no real idea about how this side of things works).


                And I still don't get what you are trying to do. From what object are you calling your protected method?


                I really doubt he is trying to call a protected method from somewhere BUT is trying to call a public method (e.g. from JSF) which in turn calls a protected method.

                • 5. Re: Protected methods on Seam components
                  Mike Quilleash Newbie

                  Writing an internal API. Yes.

                  When a method is final cglib does not proxy it so the Seam interceptors can't hook in for that method call (other non-final methods work fine)? Yes.


                  In my case JSF action method calls a public "API" method for which there is a
                  base helper implementation containing protected abstract methods. The abstract methods are implemented by subclasses which may be Seam components.


                  My problem is for some reason cglib does not like the protected methods in the subclass, you get the above exception when one is invoked through the proxy.

                  I don't really see why as cglib is just creating a proxy subclass and should be able to wrap a proxy round a protected method and call down to it after the Seam interception is done.

                  Making the method final (no Seam interception) fixes it and making the methods signatures in the subclass public also fixes it.

                  This isn't a big deal for me right now, I can make them public easily enough; I was just having a hard time understanding why it was happening. I'll move over to the cglib site and ask there, just wondering if anyone else here had come across it.

                  Cheers.

                  Mike.

                  • 6. Re: Protected methods on Seam components
                    fhh Expert

                    Sorry, but that was far from "obvious". In the code you posted the getters and setters for the annotated property are not shown and the shown methods are not annotated.

                    Anyway, I wish you good luck.

                    Regards

                    Felix