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.