10 Replies Latest reply on Apr 10, 2007 4:27 PM by supi

    JBCACHE-1004 and JBCACHE-1005

    manik

      For the next beta of JBoss Cache 2.0.0, I've taken the public APIs a step further by genericising them.

      This is in CVS right now. Feedback on this new, genericised API is much appreciated.

      Affected classes/interfaces are: Cache, CacheSPI, Node, NodeSPI, Fqn, CacheFactory.

      My reasoning behind genericising has been that while a lot of people would still want a cache that holds generic Objects, certain degree of control as to the type can be useful. For example, enforcing the elements that make up an Fqn or what objects can be used as keys.

      One of the issues here is that if you decide to specify what you want in your cache (keys and values) you'd need to specify this when creating the cache using the cache factory, and these types are then used whenever Nodes are created.

      Typical usage pattern:

      
      // example where we want all keys to be integers and all the objects in the cache are Strings.
      CacheFactory<Integer, String> cf = DefaultCacheFactory.getInstance();
      Cache<Integer, String> cache = cf.createCache();
      
      Fqn<String> myFqn = Fqn.fromString("/a/b/c");
      Node<Integer, String> node = cache.getRoot().getChild(myFqn);
      
      node.put(33, "Hello world");
      


      Does this relative inflexibility mean that most people would just create
      Cache<Object, Object>
      anyway?


        • 1. Re: JBCACHE-1004 and JBCACHE-1005
          genman


          I'm guessing for a Cache that has multiple regions that the key/value pairs will likely be different types. But I concede there may be cases where the data types are homogeneous across the cache.

          The only downside I see, from a user perspective, is that one might wonder if it is good practice to use a untyped cache.

          The best argument against typing, is that as the eventual practice will be to share a different types of data in a single cache, rather than have multiple caches.

          • 2. Re: JBCACHE-1004 and JBCACHE-1005
            manik

            Declaring a cache as containing

            <Object, Object>
            or even leaving it untyped will be, at worst, what we had before - a generic object cache containing anything at all.

            This just gives users flexibility if they do have a homogenous cache, or even a "partly-homogenous" one (for example, where key types are fixed to Strings but values can be anything) or where you want to restrict value types (e.g., Serializable)

            Moving forward, once we break down the cache into discrete regions (JBCACHE-64) with their own configurations, we could specify types on a per-region basis.

            • 3. Re: JBCACHE-1004 and JBCACHE-1005
              brian.stansberry

              Haven't really thought about this, but I'd figure a cache built up by the microcontainer (or any DI framework) would be untyped (i.e. not Cache<Object, Object> but just plain old Cache). You can't cast it to Cache<Object, Object>, so thereafter any calls against the DI-injected cache will give you those lovely compiler warnings.

              Not the end of the world, but wanted to point it out as a consideration.

              • 4. Re: JBCACHE-1004 and JBCACHE-1005
                manik

                Well, one workaround is to use a return type rather than a cast, which is valid, e.g.:

                
                Cache<Object, Object> myCache = getCache();
                Cache injected;
                
                private Cache<Object, Object> getCache()
                {
                 return injected;
                }
                
                


                But that's just an ugly workaround to prevent ugly compiler warnings. One of the things we need to deal with until DI containers start supporting generics better, I suppose (Google Guice has some support for this already).

                • 5. Re: JBCACHE-1004 and JBCACHE-1005
                  brian.stansberry

                  OK, that's not so bad; cuts it down to a single warning, which could be eliminated with a @SuppressWarnings inside getCache(). Accessing a field via a getter isn't a bad practice anyway.

                  • 6. Re: JBCACHE-1004 and JBCACHE-1005
                    jason.greene

                     

                    "manik.surtani@jboss.com" wrote:
                    Well, one workaround is to use a return type rather than a cast, which is valid:
                    .


                    You don't need to do this. Since a DI framework does this at runtime the generics info is irrelevant. So you can declare the injected type to be whatever you want. To demonstrate:

                    public class GenericsFun
                    {
                     private Map<String, Integer> foo = new HashMap<String, Integer>();
                    
                     public static void main(String[] args) throws Exception
                     {
                     HashMap<Long, Long> map = new HashMap<Long, Long>();
                     map.put(5L, 6L);
                     GenericsFun fun = new GenericsFun();
                     Field field = GenericsFun.class.getDeclaredField("foo");
                     field.setAccessible(true);
                     field.set(fun, map);
                     fun.throwCCE();
                     }
                    
                     public void throwCCE()
                     {
                     Integer boom = foo.get(5L);
                     }
                    }
                    


                    -Jason

                    • 7. Re: JBCACHE-1004 and JBCACHE-1005
                      brian.stansberry

                      DOH!

                      I spent 1/2 a year working on a really complex Spring app with a lot of genericized stuff. As I was clicking on the 'Submit' button on the 1st post the thought 'hmmm, don't remember having problems with this sort of thing at ...' flashed through my head. But I clicked the button anyway :(

                      Sorry for the noise; thanks Jason.

                      • 8. Re: JBCACHE-1004 and JBCACHE-1005
                        supi

                         

                        "manik.surtani@jboss.com" wrote:
                        Well, one workaround is to use a return type rather than a cast, which is valid:
                        .


                        "jason.greene@jboss.com" wrote:

                        You don't need to do this. Since a DI framework does this at runtime the generics info is irrelevant. So you can declare the injected type to be whatever you want.


                        Ok, there will be all kinds of workarounds (subclasses, wrappers, getters etc.) at compile time or (type-less) wiring at runtime that make me think: what's the point? The only benefit I see is type-safety that affects about 2-3 users who only put one kind of objects into the cache. Everyone else has to deal with this new inflexibility in their own way, potentially introducing new bugs, clumsy workarounds, unreadable code, unsafe code (e.g. disable unchecked warnings in whole methods), etc. And lets not forget the cache library itself. More letters, less readable code => more bugs.

                        In my opinion, at this point a step in the wrong direction.


                        • 9. Re: JBCACHE-1004 and JBCACHE-1005
                          jason.greene

                           

                          "supi" wrote:

                          Ok, there will be all kinds of workarounds (subclasses, wrappers, getters etc.) at compile time or (type-less) wiring at runtime that make me think: what's the point? The only benefit I see is type-safety that affects about 2-3 users who only put one kind of objects into the cache. Everyone else has to deal with this new inflexibility in their own way, potentially introducing new bugs, clumsy workarounds, unreadable code, unsafe code (e.g. disable unchecked warnings in whole methods), etc. And lets not forget the cache library itself. More letters, less readable code => more bugs.

                          In my opinion, at this point a step in the wrong direction.


                          No worry, workarounds are not needed, you don't have to use generics (just like you don't have to use them with java collections). It's purely syntactic sugar for those that want the additional compiler checking.

                          -Jason

                          • 10. Re: JBCACHE-1004 and JBCACHE-1005
                            supi

                             

                            "jason.greene@jboss.com" wrote:


                            No worry, workarounds are not needed, you don't have to use generics (just like you don't have to use them with java collections). It's purely syntactic sugar for those that want the additional compiler checking.

                            -Jason


                            Syntactic sugar with lots of warnings. The difference between collections and a cache is that one instance of the former is usually used to store one kind of objects, while one instance of the latter is (speculation) usually used to store very different objects. So, while warnings in the case of collections are usually justified, here they are just a nuisance that will probably do more harm than good.

                            Basil