5 Replies Latest reply on May 29, 2007 4:43 AM by mvlior

    PojoCacheListener: modify

    supi

      Hey everybody,

      I'm experimenting with Habanero b2, and with POJO listener notification in particular. I have a couple of questions:

      - I am getting "attach" and "detach" notifications, but no "modify" calls. Do I have to configure something to make this work?

      - Will there be an API to query the cache for a Pojo's Fqns or Ids? I understand that this can be an expensive operation but I think it should be available on demand if not provided with the notification.

      - What is getPojoID() supposed to return? If it is what I think it is, shouldn't it return the complete list of cycle-free paths instead of a single string? Or is ID something else?

      - If I have to do implement it myself, what would be the best way to do it? Walking up the tree from PojoInstance to its references minus the last fqn entry and so on seems to be very inefficient since the nodes aren't physically linked.

      Thanks,
      Basil

        • 1. Re: PojoCacheListener: modify
          jason.greene

           

          "supi" wrote:
          Hey everybody,

          I'm experimenting with Habanero b2, and with POJO listener notification in particular. I have a couple of questions:

          - I am getting "attach" and "detach" notifications, but no "modify" calls. Do I have to configure something to make this work?


          In order to see modify calls the subject interceptor must be added to any code that modifies fields. Typically this is the pojo itself. Can you verify that you have set jboss.aop.path to pojocache-aop.xml?

          Also, there is a known design flaw, where notifications are only dispatched locally.
          http://jira.jboss.com/jira/browse/JBCACHE-774


          - Will there be an API to query the cache for a Pojo's Fqns or Ids? I understand that this can be an expensive operation but I think it should be available on demand if not provided with the notification.


          Is PojoCache.findAll(String id) what you are looking for?


          - What is getPojoID() supposed to return? If it is what I think it is, shouldn't it return the complete list of cycle-free paths instead of a single string? Or is ID something else?


          I believe the intention is to return the id passed to attach. In some cases though this could be an internal identifier.

          -Jason

          • 2. Re: PojoCacheListener: modify
            vincent.marquez

             

            "supi" wrote:
            Hey everybody,

            I'm experimenting with Habanero b2, and with POJO listener notification in particular. I have a couple of questions:

            - Will there be an API to query the cache for a Pojo's Fqns or Ids? I understand that this can be an expensive operation but I think it should be available on demand if not provided with the notification.


            There is baseInterceptor.getFqn(), and you can get an interceptor by doing something like:
            (BaseInterceptor) AopUtil.findCacheInterceptor(((Advised) o)._getInstanceAdvisor());

            This used to work in 1.4.1 fine, but now returns the InternalFqn, which doesn't work for me. (and may be a bug?) Might work for what you want though.




            • 3. Re: PojoCacheListener: modify
              supi

               

              "jason.greene@jboss.com" wrote:

              Also, there is a known design flaw, where notifications are only dispatched locally.
              http://jira.jboss.com/jira/browse/JBCACHE-774

              Yes, I realized this too. Unfortunately, I need to have it now, so I'm trying to do everything from the outside by converting (tree) cache notifications to pojo cache notifications.


              Is PojoCache.findAll(String id) what you are looking for?

              No, exactly the opposite. For example, if I get notified of address object changes, how can the person the address belongs to be determined? I think that I should be able to look up all (cycle-free) paths.

              Could look something like this:

               public List<String> findPojoIds(Object inPojo) {
               List<String> result = new ArrayList<String>();
              
               if (inPojo instanceof Advised) {
               PojoInstance instance = null;
              
               // retrieve instance object
               BaseInterceptor interceptor = (BaseInterceptor)AopUtil.findCacheInterceptor(((Advised)inPojo)._getInstanceAdvisor());
               if (interceptor != null) {
               NodeSPI node = cache_.getRoot().getChildDirect(interceptor.getFqn());
               if (node != null) {
               instance = (PojoInstance)node.getDirect(PojoInstance.KEY);
               }
               }
              
               // find ids recursively
               Set<Fqn> visited = new HashSet<Fqn>();
               visited.add(interceptor.getFqn());
               result = getVirtualIds((CacheImpl)_cacheL.getCache(), instance, new Fqn(), visited);
               }
              
               return result;
               }
              
               private static List<String> getVirtualIds(CacheSPI inCache, PojoInstance inInstance, Fqn inVirtualTail, Set<Fqn> inVisited) {
               List<String> result = new ArrayList<String>();
              
               if (inInstance != null) {
               List<Fqn> refs = inInstance.getReferencedBy(); // not currently accessible
               for(Fqn ref : refs) {
               if (isInternal(ref)) {
               Object element = ref.getLastElement();
               Fqn oneLevelUp = ref.getSubFqn(0, ref.size() - 1);
               if (!inVisited.contains(oneLevelUp)) {
               // read instance, recurse
               NodeSPI node = (NodeSPI)inCache.getRoot().getChildDirect(oneLevelUp);
               PojoInstance instance = (PojoInstance)node.getDirect(PojoInstance.KEY);
               Set<Fqn> visited = new HashSet<Fqn>(inVisited); // we want a complete list of cycle-free paths
               visited.add(oneLevelUp);
               result.addAll(getVirtualIds(inCache, instance, new Fqn(new Fqn(element), inVirtualTail), visited));
               }
               } else {
               // found something
               result.add(new Fqn(ref, inVirtualTail).toString());
               }
               }
               }
               return result;
               }
              


              For symmetry reasons, find() would also have to be changed to take virtual paths into account: (should be anyway, IMO)

               public Object find(Fqn inFqn) {
               Object result = null;
               Fqn fqn = inFqn;
               LinkedList<Object> fqn2 = new LinkedList<Object>();
               while (!_cache.getCache().getRoot().hasChild(fqn) && fqn.size() > 0) {
               fqn2.addFirst(fqn.getLastElement());
               fqn = fqn.getSubFqn(0, fqn.size() - 1);
               }
               if (fqn.size() > 0) {
               while (!fqn2.isEmpty()) {
               NodeSPI node = cache_.getRoot().getChildDirect(fqn);
               fqn = new Fqn(((PojoReference)node.get(PojoReference.KEY)).getFqn(), fqn2.removeFirst());
               }
               // now that we have the internal fqn, retrieve the object as usual
               result = getObject(fqn);
               }
               return result;
               }
              
              


              So, this is more or less what I am looking for :) I guess that in many cases the object itself contains some kind of identifier, or even a reference back to its owner. However, I think people shouldn't be forced to include this information in their pojos. findPojoId() can't be used because the internal fqn isn't exactly useful. Neither is a randomly chosen external one.

              Basil
              Achermann


              • 4. Re: PojoCacheListener: modify
                supi

                Oh, I quickly tested it before posting and now the code contains some of my external variables :(, "_cache.getCache()" is just the pojo cache I used and should read "cache_".

                • 5. Re: PojoCacheListener: modify
                  mvlior

                  Hi,

                  Is there a JIRA issue for this one ?
                  We too would vote for it :)

                  For notification purposes, the FQN information is there... at least for the current notification which is local, the fqn could have been added to the notification object with no need for extra search.