10 Replies Latest reply on May 27, 2004 2:44 PM by starksm64

    Intercepting java.lang.reflect methods -- bad idea?

    squeak

      I am trying to develop a pattern where I am handing out to my Client Tier DataObjects that are read-only, until the Client asked for it to be unlocked.

      My thinking is that it will be more efficient to 'lock' down objects that are coming from my O/R layer (cache), as opposed to either cloning them, or creating another Value Object. All this, with the goal of the ClientTier not having the ability to mutate objects that are referenced in a global cache. Since 90% of my hits are going to read-only -- I wanted to defer the process of cloning the cache-references until it is really needed.

      Obviously, I could add booleans to my DO's and in every set method check to make sure that it isn't a locked object. Instead, it seems to me this is a perfect place for AOP. And it works for the times the application uses the setters.

      However, we have a util class that will map/populate objects from HTML form postings, using introspection. In that case, the Interceptors are never fired (which makes complete sense).

      The most obvious solution would be to intercept the Field.set* methods and see if the object it is working on is one of mine, and do my check there. But, I am not sure if there would be a negative ramification to intercepting such methods, considering they are system-level methods, that I am sure AOP is using as well.

      Thoughts?

        • 1. Re: Intercepting java.lang.reflect methods -- bad idea?
          kabirkhan

          There is some brand new stuff for intercepting reflection using caller pointcuts in cvs, it's in the aop module under org.jboss.aop.reflection. There's a page on the wiki too that explains it.

          • 2. Re: Intercepting java.lang.reflect methods -- bad idea?
            squeak

            Wow, that stuff rocks!

            Now, let me ask you this: I have tried to define the following pointcut, but it is not working as I would think

             <bind pointcut="call(void java.lang.reflect.Field->set(..))
             AND within(org.osn.*)
             AND !withincode(Object org.osn.bom.CatalogItem->clone()) ">
             <interceptor class="org.osn.aspects.GetInterceptor"/>
             </bind>
            


            What the intent of this is to say that whenever the set method on Field is called from anywhere within in the org.osn.* package, but not when it is called from inside the Clone method of org.osn.bom.CatalogItem.

            However, it still intercepts at the Clone method. Is this because I have given it two conflicting statments? (One says do inside of org.osn.*, but the other says not inside something that is in org.osn.*?)

            • 3. Re: Intercepting java.lang.reflect methods -- bad idea?
              kabirkhan

              I haven't checked properly, but does not "within" have to take a full class name?

              • 4. Re: Intercepting java.lang.reflect methods -- bad idea?
                bill.burke

                This should work. It may be a bug in the expression parser although I thought I tested for this.

                I'm consulting this week, but I'll try to take a look as soon as I can.

                Thanks,

                Bill

                • 5. Re: Intercepting java.lang.reflect methods -- bad idea?
                  squeak

                  No worries, thanks for the help.

                  I will try to dig into it more tomorrow and see what I can find as well.

                  The 'within' clause seems to work -- without it I get all of the Field.set()'s from OJB.

                  As for the clone method -- some background: I have a base object called BusinessObject, that includes the clone method with the call to Field.set.

                  All my object's extend from BusinessObject, including CatalogItem. Ideally, I want to exclude the clone method for all BusinessObject-extended objects.

                  I have tried the following clauses, with no luck, and a sanity check with the CatalogItem version:

                  !withincode(Object org.osn.bom.BusinessObject->clone())
                  !withincode(Object org.osn.bom.*->clone())
                  !withincode(Object $instanceof{org.osn.bom.BusinessObject}->clone())
                  


                  • 6. Re: Intercepting java.lang.reflect methods -- bad idea?
                    squeak

                    Well, I have gotten it to work, and I don't know if this is a bug, or ignorance on my part.

                    The following does *not* work:

                    <bind pointcut="call(void java.lang.reflect.Field->set(..))
                     AND within(org.osn.*)
                     AND !withincode(Object org.osn.bom.BusinessObject->clone()) ">
                     <interceptor class="org.osn.aspects.GetInterceptor"/>
                     </bind>
                    


                    But the following does:
                    <bind pointcut="call(void java.lang.reflect.Field->set(..))
                     AND within(org.osn.*)
                     AND !withincode(* org.osn.bom.BusinessObject->clone()) ">
                     <interceptor class="org.osn.aspects.GetInterceptor"/>
                     </bind>
                    


                    Note: the difference is the change of the return type inside the !withincode expression from Object to *.

                    So, when I declare the return type, it doesn't recognize that method and prepares it.

                    • 7. Re: Intercepting java.lang.reflect methods -- bad idea?
                      bill.burke

                      Sorry I didn't see it.....

                      It should be "java.lang.Object"

                      not "Object"

                      It should be "java.lang.String"

                      not

                      "String"

                      Only fully qualified names.

                      • 8. Re: Intercepting java.lang.reflect methods -- bad idea?
                        squeak

                        Of course! I am not sure how I missed that.

                        Sorry for wasting your time.

                        • 9. Re: Intercepting java.lang.reflect methods -- bad idea?
                          bill.burke

                          NP.

                          Just makes me realize that you should be able to type in java.lang types without java.lang. I've made the same mistake a few times myself. Others will like crazy too.

                          Bill

                          • 10. Re: Intercepting java.lang.reflect methods -- bad idea?
                            starksm64

                            You can have an Object class that is not java.lang.Object

                            [starksm@banshee9100 java]$ cat Object.java
                            public class Object extends java.lang.Object
                            {
                             public Object()
                             {
                             }
                            }
                            
                            [starksm@banshee9100 java]$ javap Object
                            Compiled from "Object.java"
                            public class Object extends java.lang.Object{
                             public Object();
                            }