You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by James Whetstone <ja...@comcast.net> on 2011/07/20 07:22:03 UTC

Question about implenting Cache

This question might be more about proper Java than it is about the Cache<K,V> interface, but I wouldn't know where else to ask this.

I'm implementing a Cache<K,V> interface for memached and I'm using spymemcached.  The spymemcached client only takes a string as the key.  

So I've implemented, for example, the get(K key) method it by casting the arguments as shown below. 
@Override

public V get(K key) throws CacheException {


return (V) mc.get((String) key);


}


So the question is, is this safe/proper use of Java in this context?  It doesn't look right to me.

Thanks,
James


Re: Question about implenting Cache

Posted by Les Hazlewood <lh...@apache.org>.
Hi James,

If you use EHCache, you won't have any issues - it supports any type
of key - not just Strings.

Best,

Les

Re: Question about implenting Cache

Posted by James Whetstone <ja...@comcast.net>.
Great info...thanks Les.

Pluggability would definitely be a nice feature in this context and I'll 
create a feature request for it...thanks.

So if I choose to use EHCache which, as you know, already has a nice 
implementation in Shiro, will these implementation issues go away?

In other words, if I switch to using EHCache for the time being, will I have 
to address the issues you've described?

Thank you!
James

----- Original Message ----- 
From: "Les Hazlewood" <lh...@apache.org>
To: <us...@shiro.apache.org>
Sent: Wednesday, July 20, 2011 11:44 AM
Subject: Re: Question about implenting Cache<K,V>


> At the moment, Shiro can use 3 different Cache instances if a
> CacheManager is configured:
>
> 1. A realm's Authentication Cache - the key is the return value of
> realm.getAuthenticationCacheKey(authenticationToken), which defaults
> to returning authenticationToken.getPrincipal().  If your end user's
> submitted AuthenticationToken principals are strings (e.g. usernames
> or email addresses), then the runtime keys will be strings and the
> runtime values will be AuthenticationInfo instances.  Authentication
> Caching is disabled by default.  If you will not use authentication
> caching, you don't need to worry about this.
>
> 2.  A realm's Authorization Cache - the key is the return value of
> realm.getAuthorizationCacheKey(PrincipalCollection) which defaults to
> returning the PrincipalCollection immediately.  This is an object, not
> a String.  You can override the getAuthorizationCacheKey method to
> return a String instead - maybe by returning
> principalCollection.getPrimaryPrincipal() (if that is indeed a
> string).  You can override it to return a string however you like.
> AuthorizationCaching is enabled by default if a CacheManager is
> present.
>
> 3.  CachingSessionDAO implementation's Session Cache - only used if
> using Shiro's native sessions.  The key is the session ID (a
> Serializable object) and the value is a Session object.  At runtime,
> all of Shiro's session IDs are Strings by default, so you wouldn't
> have to do anything special (some end-users have the session ID be a
> long integer, i.e. a data store surrogate primary key, which is why
> the type is specified as Serializable and not String).
>
> So if you want to require that all keys are Strings and you want to
> use AuthorizationCaching (recommended) you will need to override the
> realm's getAuthorizationCacheKey method to return a String.  Then
> everything should work fine.
>
> Ideally this key resolution mechanism should be a pluggable component
> so you don't have to subclass a Realm to customize this behavior -
> please open a Jira issue as a feature request and we can see about
> adding this if you (or someone else) would find it valuable.
>
> HTH!
>
> Best,
>
> -- 
> Les Hazlewood
> CTO, Katasoft | http://www.katasoft.com | 888.391.5282
> twitter: http://twitter.com/lhazlewood
> katasoft blog: http://www.katasoft.com/blogs/lhazlewood
> personal blog: http://leshazlewood.com
> 


Re: Question about implenting Cache

Posted by Les Hazlewood <lh...@apache.org>.
At the moment, Shiro can use 3 different Cache instances if a
CacheManager is configured:

1. A realm's Authentication Cache - the key is the return value of
realm.getAuthenticationCacheKey(authenticationToken), which defaults
to returning authenticationToken.getPrincipal().  If your end user's
submitted AuthenticationToken principals are strings (e.g. usernames
or email addresses), then the runtime keys will be strings and the
runtime values will be AuthenticationInfo instances.  Authentication
Caching is disabled by default.  If you will not use authentication
caching, you don't need to worry about this.

2.  A realm's Authorization Cache - the key is the return value of
realm.getAuthorizationCacheKey(PrincipalCollection) which defaults to
returning the PrincipalCollection immediately.  This is an object, not
a String.  You can override the getAuthorizationCacheKey method to
return a String instead - maybe by returning
principalCollection.getPrimaryPrincipal() (if that is indeed a
string).  You can override it to return a string however you like.
AuthorizationCaching is enabled by default if a CacheManager is
present.

3.  CachingSessionDAO implementation's Session Cache - only used if
using Shiro's native sessions.  The key is the session ID (a
Serializable object) and the value is a Session object.  At runtime,
all of Shiro's session IDs are Strings by default, so you wouldn't
have to do anything special (some end-users have the session ID be a
long integer, i.e. a data store surrogate primary key, which is why
the type is specified as Serializable and not String).

So if you want to require that all keys are Strings and you want to
use AuthorizationCaching (recommended) you will need to override the
realm's getAuthorizationCacheKey method to return a String.  Then
everything should work fine.

Ideally this key resolution mechanism should be a pluggable component
so you don't have to subclass a Realm to customize this behavior -
please open a Jira issue as a feature request and we can see about
adding this if you (or someone else) would find it valuable.

HTH!

Best,

-- 
Les Hazlewood
CTO, Katasoft | http://www.katasoft.com | 888.391.5282
twitter: http://twitter.com/lhazlewood
katasoft blog: http://www.katasoft.com/blogs/lhazlewood
personal blog: http://leshazlewood.com

Re: Question about implenting Cache

Posted by James Whetstone <ja...@comcast.net>.
I like this approach, but it leads me to another question.

The CacheManager object expects a Cache<Object,Object> type.  For example, if I compile my Cache<String,Object> and CacheManager 'getCache' method, the compile warns that the return object is the incorrect type because the CacheManager wants to return Cache<Object,Object>.

@Override

public Cache<String, Object> getCache(String name) throws CacheException {


try {

Memcache mc = null;


if (cacheTable.containsKey(name)) {

log.info("Found existing memcached client.");


mc = cacheTable.get(name);

}

else {

log.info("Constructing new memcached client and storing is for reuse.");


mc = new Memcache( new MemcachedClient( new InetSocketAddress("192.168.0.242", 11211)));


cacheTable.put(name, mc); 

}


return mc;

}

catch(IOException ex) {

log.error(ex);

}


return null;


}


So I'm unlclear on whether if I implement my cache as type Cache<String,Object>, if that will pose a problem for shiro.  For example,  will shiro ever use a non String key to access the cache?   

---James

  ----- Original Message ----- 
  From: shiro.atomicknight@xoxy.net 
  To: user@shiro.apache.org 
  Sent: Tuesday, July 19, 2011 10:33 PM
  Subject: Re: Question about implenting Cache<K,V>


  You probably don't want to do that because you lose the static typing that generics are meant to provide. A more appropriate implementation would be something like:


    public class ExampleCache implements Cache<String, Object> {
        @Override
        public Object get( String key ) throws CacheException {
            return mc.get( key );
        }


        // Other methods
    }


  If your cache contains only one type of object that is more specific than Object, you could potentially use that type instead and perform a (unsafe) cast within the definition of get(String).



  On Wed, Jul 20, 2011 at 1:22 AM, James Whetstone - jameswhetstone@comcast.net wrote:

    This question might be more about proper Java than it is about the Cache<K,V> interface, but I wouldn't know where else to ask this.

    I'm implementing a Cache<K,V> interface for memached and I'm using spymemcached.  The spymemcached client only takes a string as the key.  

    So I've implemented, for example, the get(K key) method it by casting the arguments as shown below. 
    @Override


    public
    V get(K key) throws CacheException { 


    return (V) mc.get((String) key); 

    }


    So the question is, is this safe/proper use of Java in this context?  It doesn't look right to me.

    Thanks,
    James




Re: Question about implenting Cache

Posted by sh...@xoxy.net.
You probably don't want to do that because you lose the static typing that
generics are meant to provide. A more appropriate implementation would be
something like:

public class ExampleCache implements Cache<String, Object> {
    @Override
    public Object get( String key ) throws CacheException {
        return mc.get( key );
    }

    // Other methods
}


If your cache contains only one type of object that is more specific than
Object, you could potentially use that type instead and perform a (unsafe)
cast within the definition of get(String).


On Wed, Jul 20, 2011 at 1:22 AM, James Whetstone -
jameswhetstone@comcast.net wrote:

> **
>  This question might be more about proper Java than it is about the
> Cache<K,V> interface, but I wouldn't know where else to ask this.
>
> I'm implementing a Cache<K,V> interface for memached and I'm using
> spymemcached.  The spymemcached client only takes a string as the key.
>
> So I've implemented, for example, the get(K key) method it by casting the
> arguments as shown below.
>
> @Override
>
> *public*
> V get(K key) *throws* CacheException {
>
> *return* *(V) *mc.get((String) key);
>
> }
>
> So the question is, is this safe/proper use of Java in this context?  It
> doesn't look right to me.
>
> Thanks,
> James
>
>
>