1 2 Previous Next 29 Replies Latest reply on Jan 15, 2003 10:25 PM by belaban

    Reopening getters/setters vs. field interception

    bill.burke

      Here's some thoughts from a conversation I've had with Bob Lee. He makes some interesting points. (I will reply to this thread)

      .....................

      Bill,

      Thinking about it more, I really don't think field interception is a good
      idea.

      First, given int field i, i++ now results in the creation of two objects
      (boxing the Integer, get, set) not to mention method invocations. That's a
      ton of overhead for what used to be a simple primitive access (something
      completely stack based that didn't even involve the heap).

      Second, when we reflectively invoke methods, the invocation still goes
      through the aspects because we've replaced the implementation. If you
      reflectively get/set a field, it will not go through the aspects. This is a
      common practice. For example, a framework automatically maps XML to beans
      (which should be transparently persisted). None of the field sets would get
      picked up.

      Third, HotSpot justifies a lot of what we do (inlining etc.). Many said Java
      wasn't usable before these performance enhancements. Having this runtime
      level of indirection will cripple potential optimizations.

      It's a lot of work and added complication to intercept fields that probably
      have getters/setters anyway. Plus, this will increase the noise level,
      taking away from the rest of the framework, hindering its chances at
      adoption.

      Sorry if I'm beating this point to death.

      Thanks,
      Bob

        • 1. 3761539
          belaban

          > A/ DP vs Class
          >
          > DP is fine, it is what we use today. The problem
          > with DP is that there is the indirection call,
          > always. Speed is one issue although I am not
          > religious about it. I think that the class
          > instrumentation, while tricky, allows us to do
          > optimizations such as "no stack?" go native, meaning
          > that we can instrument all the classes in the server.
          >

          blah.. you still have not covered how we can do instrumention on the client side. Everybody including me can CLEARLY see the power we can get from instrumentation on the server-side. The problem this thread is trying to address is client side aop.

          >
          > Remember that the first application of this is mostly
          > serverside ONLY. The first ones are cache and
          > persistence. So this approach buys us speed and ease
          > of use as we can port existing applications to our
          > caches in production without modification of the
          > code. That is an established fact that we need to
          > nail fast.

          Yes, needed, but it does not address the question this topic raises.

          >
          > Then for client side. Either we have the JMX on the
          > client and we can do some magic, but it means we need
          > to reconstruct what the DP serialization already does

          Are you saying you want to do instrumentation on the client side?? How are you going to get this to work on say an Applet??

          > which is tricky. So when we have the remote aspect
          > in there I would default to a interface based
          > implementation. What does that mean? I am not sure
          > :) essentially returning interface based stuff to
          > clients is easy and we should somehow require that
          > for clients. That means that on the server side the
          > instrumentation uses the interfaces when available.

          Yes, I beleive that you are right. Client side objects will be DPs. Interfaces must be used.

          >
          > B/ JMX on the client.
          >
          > I still believe in that. In fact more than ever. I
          > think this is one of the most promising ways to push
          > JBoss. Let's put a microkernel version for "light
          > clients" where you have some of the services
          > available to the client VM.

          Client enviorments cannot be controled as easily as a server enviorment. When you think about a client, allways think about the worst case: an Applet in security sandbox. Will be be able to run the micro-kernel there and how transparent will it be to the client??

          Regards,
          Hiram

          • 2. Re: Reopening getters/setters vs. field interception
            bill.burke

            > I would hate having to create deployment descriptors
            > for each object that's put into my cache !
            >
            > Bela

            No, no, no. The attribute would not be tied to your framework. We need some way of differentiating query/update methods. I'm suggesting attributes:

            /**
            * Gets something.
            *
            * @read-only
            */
            public Object getSomething();

            /**
            * Sets something.
            */
            public void setSomething(Object something);

            These attributes could be used by all frameworks that care if an object's state has changed. The safe default will be that all methods are mutators unless specified otherwise.

            This isn't my idea. I *think* this is how Rickard and Jon Tirsen are implementing it. I read it somewhere.

            • 3. Re: Reopening getters/setters vs. field interception
              marc.fleury



              > Don't deal with TX demarcation.
              >
              > Transaction start is something else and I don't think
              > you should put that in the cache. IF THERE IS A
              > TRANSACTION then record changes as part of it and
              > wait for demarcation. IF THERE ISN"T then do field
              > by field.
              >
              > This is how the CMP engine works. The CMP engine
              > doesn't start a transaction, the transaction
              > interceptor does. Orthogonal, forget TX creation.


              I'm not talking about JBoss Transactions, these are my internal 'transactions'. My transactions are simply used to associate locks and modifications with a caller.

              So this is Cache-specific.

              That said, when using the Cache in the EntityBeanInterceptor (or whatever it is called), i *will* actually use JBoss's Transactions for my Cache.

              Are you confused yet ? :-)




              > We sketched out the
              > way the aspect would work with cache.
              >
              > Object o = new Object();
              > cache.put(o);

              > in the cache you then do
              >
              > put (Object o) {
              > ((AOP) o).getStack().addInterceptor(new
              > cacheInterceptor().registerListener(this))
              > ...
              > }
              >
              > The code in the interceptor is
              >
              > invoke(invocation) {
              >
              > if (setterCall) notifyListeners; // your cache is
              > there listening;
              > }


              Beautiful ! This is *exactly* what I need ! Great work guys !

              When will this be ready ? Is it already ? Because I can use these interceptors also to *implement* my cache.


              Bela

              • 4. Re: Reopening getters/setters vs. field interception
                bill.burke

                >
                > Thinking about it more, I really don't think field
                > interception is a good
                > idea.
                >

                I'm still open to it....

                > First, given int field i, i++ now results in the
                > creation of two objects
                > (boxing the Integer, get, set) not to mention method
                > invocations. That's a
                > ton of overhead for what used to be a simple
                > primitive access (something
                > completely stack based that didn't even involve the
                > heap).
                >

                If we're doing transaction or distributed caches, or persistence, this overhead probably will not matter. We will make field interception optional.

                > Second, when we reflectively invoke methods, the
                > invocation still goes
                > through the aspects because we've replaced the
                > implementation. If you
                > reflectively get/set a field, it will not go through
                > the aspects. This is a
                > common practice. For example, a framework
                > automatically maps XML to beans
                > (which should be transparently persisted). None of
                > the field sets would get
                > picked up.
                >

                This is your most intriguing point and we should really think about this one. Even if our persistence framework used reflection to access fields, it actually may be a good thing that field reflection is not intercepted. It frees us worrying about infinite loops. (Intercept get, lazy load from db, set field no need for interception.) I say we implement it and see where it takes us. Iteration is key.

                > Third, HotSpot justifies a lot of what we do
                > (inlining etc.). Many said Java
                > wasn't usable before these performance enhancements.
                > Having this runtime
                > level of indirection will cripple potential
                > optimizations.
                >
                > It's a lot of work and added complication to
                > intercept fields that probably
                > have getters/setters anyway. Plus, this will increase
                > the noise level,
                > taking away from the rest of the framework, hindering
                > its chances at
                > adoption.
                >

                Unless Sun comes out with an AOP spec, not much will hinder us from becoming adopted. Remember, we have had 2.4 million downloads of JBoss and have a dominant percentage of the J2EE market. We have the user base to push and develop this standard.

                And again, field interception will be optional.

                > Sorry if I'm beating this point to death.

                Keep it flowing. Discussion is good.

                Bill

                • 5. Re: Reopening getters/setters vs. field interception
                  belaban

                  With respect to field interception, here's my use case:

                  I have a replicated cache. First I update an item conventionally:

                  Cache cache;
                  Person p; // has fields 'age' and 'name'

                  // starts a new transaction & associates
                  // it with the current thread
                  cache.begin(Xid.READ_COMMITTED);

                  p=new Person("Bela", 37);
                  cache.put("bela", p); // will replicate to all nodes
                  cache.put("otherkey", "some other value");

                  // all nodes apply the changes ("bela" and "otherkey")
                  cache.commit();


                  Now, let's look at a use case where AOP would come in handy:

                  // 1. cache contains Person 'p'
                  // 2. transaction has committed
                  // 3. there is currently no TX associated with the thread

                  p.incrementAge();

                  Method incrementAge() increments age (age++). At this point, I would have to create a new transaction (if none exists). After this, I would have to cmmit the transaction. If one existed before I would reuse it and *not* commit until the user commits it.

                  Therefore we have the following choice:

                  1. We don't support modification of values in a replicated cache. Or at least the modifier has to call put() at the end of the modifications again. Or

                  2. We use field interceptors to detect when a fields has changed (to start a transaction) and to record whether/which state has changed. Actually this can be turned into

                  3. We use field interceptors to detect whether state has changed. If state has changed I sent the entire contents to all nodes. If not, I do nothing.


                  So it all boils down to whether you can tell me if an object's state has changed ?

                  If this can be done without field interceptors, great.

                  Bela

                  • 6. Re: Reopening getters/setters vs. field interception
                    crazybob

                    We mark Person.incrementAge() as a mutator method (using attributes). We intercept all mutator methods--starting a transaction and replicating as neccessary.

                    Actually, using field interceptors won't work well here. Again, reflective field accesses would bypass the interceptors. We don't have this problem with method interceptors.

                    • 7. Re: Reopening getters/setters vs. field interception
                      marc.fleury


                      > 1. We don't support modification of values in a
                      > replicated cache. Or at least the modifier has to
                      > call put() at the end of the modifications again. Or

                      clearly we want to replicate state modifications.

                      > 2. We use field interceptors to detect when a fields
                      > has changed (to start a transaction) and to record
                      > whether/which state has changed.

                      Don't deal with TX demarcation.

                      Transaction start is something else and I don't think you should put that in the cache. IF THERE IS A TRANSACTION then record changes as part of it and wait for demarcation. IF THERE ISN"T then do field by field.

                      This is how the CMP engine works. The CMP engine doesn't start a transaction, the transaction interceptor does. Orthogonal, forget TX creation.

                      > 3. We use field interceptors to detect whether state
                      > has changed. If state has changed I sent the entire
                      > contents to all nodes. If not, I do nothing.
                      >

                      You want that. The discussion bob/bill/me are having is that I want field automation they are arguing for getter/setters. The case of field automation is completely transparent porting of EXISTING apps to JBoss AS IS. Their point is that getters/setters will be there. I think the point on reflection by Bob is definitive though.

                      Meaning, the discussion is not whether we intercept state changes for you but really if we enforce a programming model of getter/setter on the end programmer.

                      >
                      > So it all boils down to whether you can tell me if an
                      > object's state has changed ?

                      we can.

                      I was talking to Yannis, the Georgia Professor last week. He is putting a student full time on these applications (and other things). We sketched out the way the aspect would work with cache.

                      Object o = new Object();

                      cache.put(o);

                      in the cache you then do

                      put (Object o) {

                      ((AOP) o).getStack().addInterceptor(new cacheInterceptor().registerListener(this))
                      ...
                      }

                      The code in the interceptor is

                      invoke(invocation) {

                      if (setterCall) notifyListeners; // your cache is there listening;
                      }


                      The beauty of this design is that the end user programmer doesn't need to be coding for "cache support and stack configuration", the stack configuration is dynamic as the object IS INSERTED IN CACHE.

                      • 8. Re: Reopening getters/setters vs. field interception
                        crazybob

                        Mark Person.incrementAge() as a mutator (using attributes) and intercept all mutator methods.

                        We don't need field granularity. The method may alter 10 fields. All we really care about is that the object's state changed. There's no need to execute 20 interceptions, and start 20 transactions (one for read, one for write).

                        Again, if you use field interception, code that reflectively sets the field will bypass the interceptors entirely. It's not always clear that this is happening. We don't have this problem with method interception.

                        Bill, in regard to adoption, I don't mean that people won't adopt it because of this. I just mean that field interception adds little value and makes it more difficult to learn and adopt the framework.

                        I'm afraid it gives people too much rope to hang themselves with.

                        • 9. Re: Reopening getters/setters vs. field interception
                          belaban



                          > Don't deal with TX demarcation.
                          >
                          > Transaction start is something else and I don't think
                          > you should put that in the cache. IF THERE IS A
                          > TRANSACTION then record changes as part of it and
                          > wait for demarcation. IF THERE ISN"T then do field
                          > by field.
                          >
                          > This is how the CMP engine works. The CMP engine
                          > doesn't start a transaction, the transaction
                          > interceptor does. Orthogonal, forget TX creation.


                          I'm not talking about JBoss Transactions, these are my internal 'transactions'. My transactions are simply used to associate locks and modifications with a caller.

                          So this is Cache-specific.

                          That said, when using the Cache in the EntityBeanInterceptor (or whatever it is called), i *will* actually use JBoss's Transactions for my Cache.

                          Are you confused yet ? :-)




                          > We sketched out the
                          > way the aspect would work with cache.
                          >
                          > Object o = new Object();
                          > cache.put(o);

                          > in the cache you then do
                          >
                          > put (Object o) {
                          > ((AOP) o).getStack().addInterceptor(new
                          > cacheInterceptor().registerListener(this))
                          > ...
                          > }
                          >
                          > The code in the interceptor is
                          >
                          > invoke(invocation) {
                          >
                          > if (setterCall) notifyListeners; // your cache is
                          > there listening;
                          > }


                          Beautiful ! This is *exactly* what I need ! Great work guys !

                          When will this be ready ? Is it already ? Because I can use these interceptors also to *implement* my cache.


                          Bela

                          • 10. Re: Reopening getters/setters vs. field interception
                            belaban

                            > Mark Person.incrementAge() as a mutator (using
                            > attributes) and intercept all mutator methods.

                            How ? I don't want to do *anything* besides sticking an object into my cache and using AOP to determine when that object's state has changed at the end of a transaction.

                            I would hate having to create deployment descriptors for each object that's put into my cache !

                            Bela

                            • 11. Re: Reopening getters/setters vs. field interception
                              bill.burke

                              > > Mark Person.incrementAge() as a mutator (using
                              > > attributes) and intercept all mutator methods.
                              >
                              > How ? I don't want to do *anything* besides sticking
                              > an object into my cache and using AOP to determine
                              > when that object's state has changed at the end of a
                              > transaction.
                              >
                              > I would hate having to create deployment descriptors
                              > for each object that's put into my cache !

                              This is a great use case for field interception.

                              • 12. Re: Reopening getters/setters vs. field interception
                                crazybob

                                > I would hate having to create deployment descriptors
                                > for each object that's put into my cache !
                                >
                                > Bela

                                No, no, no. The attribute would not be tied to your framework. We need some way of differentiating query/update methods. I'm suggesting attributes:

                                /**
                                * Gets something.
                                *
                                * @read-only
                                */
                                public Object getSomething();

                                /**
                                * Sets something.
                                */
                                public void setSomething(Object something);

                                These attributes could be used by all frameworks that care if an object's state has changed. The safe default will be that all methods are mutators unless specified otherwise.

                                This isn't my idea. I *think* this is how Rickard and Jon Tirsen are implementing it. I read it somewhere.

                                • 13. Re: Reopening getters/setters vs. field interception
                                  crazybob

                                  > I'm saying that this is a good thing that
                                  > java.lang.reflect.Field is not intercepted. That way
                                  > we can have easy non-intercepted access to fields.

                                  Here's an example. I have a cached domain object. I recieve updates in the form of XML. I have a framework that automatically maps this XML to my domain object. If the framework uses reflection to set the fields, none of the updates get intercepted.

                                  • 14. Re: Reopening getters/setters vs. field interception
                                    crazybob

                                    > Welcome to the group bob :)

                                    Thanks for having me.

                                    1 2 Previous Next