Multiple Play CacheApi instances?

549 views
Skip to first unread message

Jeff Simpson

unread,
Jan 2, 2018, 4:49:34 PM1/2/18
to Play Framework
Hi,

We've been using the default ehcache in-memory cache for our application via DI of AsyncCacheApi instances. However, we now have a need to persist data beyond restarts and wanted to use Play-Redis for specific caching uses and keep also keep the existing ehcache uses. Is this possible? More generically, is it possible to have multiple cache api implementations with different backends? This seems to indicate it is possible, but seems specific to ehcache, https://www.playframework.com/documentation/2.6.x/ScalaCache#Accessing-different-caches.

What I've tried thus far is adding the Play-Redis dependencies, then enabling the module. This causes issues due to ehcache and play-redis colliding:


1) A binding to play.api.cache.AsyncCacheApi was already configured at play.api.cache.redis.GuiceProvider$.defaultBinding$1(RedisCacheModule.scala:73):
Binding(interface play.api.cache.AsyncCacheApi to BindingKeyTarget(interface play.api.cache.AsyncCacheApi qualified with QualifierInstance(@javax.inject.Named(value=play)))) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1).
  at play
.api.cache.ehcache.EhCacheModule$$anonfun$$lessinit$greater$1.bindDefault$1(EhCacheApi.scala:85):
Binding(interface play.api.cache.AsyncCacheApi to BindingKeyTarget(interface play.api.cache.AsyncCacheApi qualified with QualifierInstance(@play.cache.NamedCache(value=play)))) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)


2) A binding to play.api.cache.SyncCacheApi was already configured at play.api.cache.redis.GuiceProvider$.defaultBinding$1(RedisCacheModule.scala:73):
Binding(interface play.api.cache.SyncCacheApi to BindingKeyTarget(interface play.api.cache.SyncCacheApi qualified with QualifierInstance(@javax.inject.Named(value=play)))) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1).
  at play
.api.cache.ehcache.EhCacheModule$$anonfun$$lessinit$greater$1.bindDefault$1(EhCacheApi.scala:85):
Binding(interface play.api.cache.SyncCacheApi to BindingKeyTarget(interface play.api.cache.SyncCacheApi qualified with QualifierInstance(@play.cache.NamedCache(value=play)))) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)


3) A binding to play.cache.AsyncCacheApi was already configured at play.api.cache.redis.GuiceProvider$.defaultBinding$1(RedisCacheModule.scala:73):
Binding(interface play.cache.AsyncCacheApi to BindingKeyTarget(interface play.cache.AsyncCacheApi qualified with QualifierInstance(@javax.inject.Named(value=play)))) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1).
  at play
.api.cache.ehcache.EhCacheModule$$anonfun$$lessinit$greater$1.bindDefault$1(EhCacheApi.scala:85):
Binding(interface play.cache.AsyncCacheApi to BindingKeyTarget(interface play.cache.AsyncCacheApi qualified with QualifierInstance(@play.cache.NamedCache(value=play)))) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)


4) A binding to play.cache.SyncCacheApi was already configured at play.api.cache.redis.GuiceProvider$.defaultBinding$1(RedisCacheModule.scala:73):
Binding(interface play.cache.SyncCacheApi to BindingKeyTarget(interface play.cache.SyncCacheApi qualified with QualifierInstance(@javax.inject.Named(value=play)))) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1).
  at play
.api.cache.ehcache.EhCacheModule$$anonfun$$lessinit$greater$1.bindDefault$1(EhCacheApi.scala:85):
Binding(interface play.cache.SyncCacheApi to BindingKeyTarget(interface play.cache.SyncCacheApi qualified with QualifierInstance(@play.cache.NamedCache(value=play)))) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)


4 errors
 at com
.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:470)
 at com
.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155)
 at com
.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107)
 at com
.google.inject.Guice.createInjector(Guice.java:99)
 at com
.google.inject.Guice.createInjector(Guice.java:84)
 at play
.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:185)
 at play
.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:137)
 at play
.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
 at play
.core.server.DevServerStart$$anon$1.$anonfun$reload$3(DevServerStart.scala:174)
 at play
.utils.Threads$.withContextClassLoader(Threads.scala:21)
 at play
.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:171)
 
... 25 common frames omitted



Thanks,
-Jeff

Marcos Pereira

unread,
Jan 3, 2018, 5:21:16 PM1/3/18
to play-fr...@googlegroups.com
Hi Jeff,

You can bind more than one implementation to the same interface, but you need to annotate/qualify the bind to make a distinction between these implementations. I'm not sure which play-redis module you are using, but maybe it has a way to disable the default bind (unqualified) and name the cache instances. Of course, when injecting you need to use `@NamedCache` too.

Best.

--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/63c68ef0-f82a-4ca6-9aa0-132dcf02ad93%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Marcos Pereira
Software Engineer, Lightbend.com

Jeff Simpson

unread,
Jan 4, 2018, 1:30:43 PM1/4/18
to Play Framework
Thanks Marcos. I'm going to be getting back to this today. I'm using play-redis and the developer from that project has also replied with an example of using both caches side-by-side.

Cheers
-Jeff
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

su...@greytip.com

unread,
Jan 17, 2018, 5:04:19 AM1/17/18
to Play Framework
Hi Jeff,,
 I am also using play-redis and I want to do the custom implementation of SyncCacheApi I have done the binding of my custom class like 

bind(SyncCacheApi.class).annotatedWith(Names.named("customDefaultSyncCacheApi")).to(CustomSyncCacheApi.class);
and below is the sample of CustomSyncCacheApi 


public class GtDefaultSyncCacheApi implements SyncCacheApi {


 
@Inject
 
public GtDefaultSyncCacheApi(@Named("gtDefaultSyncCacheApi") SyncCacheApi syncCacheApi) {


 
}
}

but still it is calling the 
play.cache.DefaultSyncCacheApi

any idea ??
Reply all
Reply to author
Forward
0 new messages