That all looks reasonable, sure.

Avoiding use of @Named is a matter of best practice, wherein a large code
base becomes susceptible to global namespace collisions, and even a small
code base is at risk for typos.  Hence use of a well typed
@BindingAnnotation is superior.

Glad this does the trick.

-Fred

On Fri, Oct 15, 2010 at 9:12 AM, Sondre Bjornebekk <
sondre.bjorneb...@gmail.com> wrote:

> Neat. In fact the MapMaker[1] that takes a Function and provides
> different eviction policies etc. that you used for the map of caches
> will probably also save me from some manual work in the actual local
> heap cache implementation around synchronization etc. Thanks!
>
> Since I found it less than smooth to integrate Guice 3.0 in my maven
> build at this point (Stuart McCulloch's snapshot build that was
> discussed here seems to only have 2.1.8?), I replaced the
> @AlwaysCreatesNewInstances with a simple @Named annotation to
> differentiate the injection for the "actual cache factory" from the
> Multiton giving me:
>
>    @Inject
>    public MultitonCacheFactory(@Named("underlyingFactory")
> CacheFactory cacheFactory) {
>        this.underlyingFactory = cacheFactory;
>    }
>
> And:
>        bind(CacheFactory.class).
>                to(MultitonCacheFactory.class).in(Singleton.class);
>        bind(CacheFactory.class).
>                annotatedWith(Names.named("underlyingFactory")).
>
> toProvider( FactoryProvider.newFactory(CacheFactory.class,
> NamedCacheLocal.class) );
>
> This seems to work in the unit testing (and with some simple
> concurrency testing). Any comments on that approach?
>
> Will do a quick feasibility test, but cannot see why I should not be
> able to wrap Coherence (or something similar) by just changing the
> last of the two bindings.
>
> -S-
>
> [1] - This Google guava library was in fact all new to me and seems
> really useful. Kudos goes to MV for releasing it under an Apache
> license.
>
> On Oct 14, 12:27 pm, Fred Faber <ffa...@faiser.com> wrote:
> > Basically you have a factory that should return a singleton instance for
> > each unique string value passed into it?
> >
> > FactoryProvider won't do this for you out of the box, as it will create a
> > new instance per invocation (as you've illustrated).
> >
> > What I would do in this case is to decorate your factory with an
> > implementation that controls singletonness:
> >
> > interface CacheFactory {
> >   // This can be named anything you want, not just "create"
> >   NamedCache create(String name);
> >
> > }
> >
> > class CachingCacheFactory implements CacheFactory {
> >
> >  private final CacheFactory underlyingFactory;
> >
> >  //
> http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/co...
> >  private final Map<String, NamedCache> caches = new MapMaker()
> >       .makeComputingMap(new Function<String, NamedCache>(){
> >            @Override public NamedCache apply(String name) {
> >                 return underlyingFactory.create(name);
> >           }
> >       });
> >
> >   @Inject
> >   CachingCacheFactory {
> >       @AlwaysCreatesNewInstances CacheFactory cacheFactory) {
> >      this.underlyingFactory = cacheFactory;
> >    }
> >
> >   @Override
> >   NamedCache create(String name) {
> >       return caches.get(name);
> >   }
> >
> > }
> >
> > * * *
> >
> > public class YourModule extends AbstractModule {
> >
> >    @Override protected void configure() {
> >        // as an alternative to binding this as a singleton, you could
> inject
> > the map of caches
> >        // as a singleton instance.  6 or 1/2 dozen, unless you want to
> > unittest your
> >        // implementation, in which case you'll want to inject the
> singleton
> > map
> >        bind(CacheFactory.class)
> >            .to(CachingCacheFactory.class)
> >            .in(Singleton.class);
> >
> >        //
> http://google-guice.googlecode.com/svn/trunk/javadoc/com/google/injec...
> >        // this binds a "CacheFactory" instance, annotated with
> > @AlwaysCreatesNewInstances, to
> >        // a default factory implementation which will return instances of
> > NamedCacheLocal when
> >        // its create() method is invoked
> >        install(new FactoryModuleBuilder()
> >            .implement(NamedCache, NamedCacheLocal)
> >            .build(Key.get(NamedCache.class,
> > AlwaysCreatesNewInstances.class));
> >     }
> >
> > }
> >
> > That should do the trick.
> >
> > -Fred
> >
> > On Thu, Oct 14, 2010 at 4:25 AM, Sondre Bjornebekk <
> >
> > sondre.bjorneb...@gmail.com> wrote:
> > > Hi,
> >
> > > Trying to use assisted inject and find it pretty neat, the minor
> > > detail is that it does not quite work for me yet :-)
> >
> > > I have created a Map wrapper to ease switching of caches (typically to
> > > something like Coherence) for my application. I want the Map to be
> > > returned "in a Singleton scope, based on the value of the (assisted)
> > > parameter". I am doing:
> >
> > > bind(CacheFactory.class).toProvider(
> > > FactoryProvider.newFactory(CacheFactory.class,
> > > NamedCacheLocal.class) );
> >
> > > And I have:
> > > /**
> > >  * A factory for named caches, that later might hide its
> > > implementation using a cluster wide storage.
> > >  */
> >
> > > public interface CacheFactory {
> > >    //had to be named create to work with guice assisted inject, so
> > > renamed from getNamedCache
> > >    public NamedCache create(String name);
> > > }
> >
> > > public interface NamedCache<K,V> extends Map<K,V> {
> > >    public int getHitPercent();
> > >    public String getHitPercentString();
> > >    ...
> > > }
> >
> > > /**
> > >  * A named cache with a local map as implementation for storage.
> > >  */
> >
> > > public class NamedCacheLocal<K,V> implements NamedCache<K,V> {
> > > ...
> >
> > >    /**
> > >     * Constructs a NamedCacheLocal with its dependencies.
> > >     */
> > >    @Inject
> > >    public NamedCacheLocal(@Assisted String cacheName) {
> > > ...
> > > }
> >
> > > I have this (failing) unit test that checks that the same cache is
> > > used for the same name:
> >
> > >        System.out.println("doing put / get test");
> > >        NamedCache<String,String> namedCache =
> > > namedCacheFactory.create("myCache");
> > >        namedCache.put("fisk","fesk");
> > >        for(int i=0;i<10; i++){
> > >            Object o = namedCache.get("non-hit");
> > >            namedCache.put("test"+i,"testval"+i);
> > >        }
> > >        Object hit = namedCache.get("fisk");
> > >        System.out.println("cache " + namedCache + " delivered value "
> > > + hit + " to a hit percent of " + namedCache.getHitPercentString());
> > >        assertTrue(namedCache.getHitPercent() > 8 &&
> > > namedCache.getHitPercent() < 10);
> > >        NamedCache<String,String> namedCacheWithSameName =
> > > namedCacheFactory.create("myCache");
> > >        for(int i=0;i<10; i++){
> > >            String val = namedCacheWithSameName.get("test"+i);
> > >            System.out.println("got val from cache: " + val);
> > >        }
> > >        //should have used the same reference, thus hit pct now higher
> > >        System.out.println("done with cache " +
> > > namedCacheWithSameName);
> > >        assertTrue(namedCache.getHitPercent() > 10);
> > >        assertTrue(namedCache.equals(namedCacheWithSameName));
> >
> > > So is the thing I put in quotation marks in the intro ("in a Singleton
> > > scope, based on the value of the (assisted) parameter") even possible
> > > just by Guice config, or do I have to go two steps back and one
> > > forward and just implement the CacheFactory myself with this logic?
> > > The first thing I tried was
> >
> > >        bind( CacheFactory.class ).
> > >        toProvider( FactoryProvider.newFactory(CacheFactory.class,
> > > NamedCacheLocal.class) ) .
> > >        in ( Singleton.class );
> >
> > > But that (of course) just gives me a singleton CacheFactory, not the
> > > NamedCacheLocal "singleton" based on the assisted factory parameter.
> >
> > > Cheers,
> >
> > > Sondre
> >
> > > --
> > > You received this message because you are subscribed to the Google
> Groups
> > > "google-guice" group.
> > > To post to this group, send email to google-gu...@googlegroups.com.
> > > To unsubscribe from this group, send email to
> > > google-guice+unsubscr...@googlegroups.com<google-guice%2bunsubscr...@googlegroups.com>
> <google-guice%2bunsubscr...@googlegroups.com<google-guice%252bunsubscr...@googlegroups.com>
> >
> > > .
> > > For more options, visit this group at
> > >http://groups.google.com/group/google-guice?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups
> "google-guice" group.
> To post to this group, send email to google-gu...@googlegroups.com.
> To unsubscribe from this group, send email to
> google-guice+unsubscr...@googlegroups.com<google-guice%2bunsubscr...@googlegroups.com>
> .
> For more options, visit this group at
> http://groups.google.com/group/google-guice?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to google-gu...@googlegroups.com.
To unsubscribe from this group, send email to 
google-guice+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en.

Reply via email to