0
# Play Framework Cache API
1
2
The Play Framework Cache API provides a comprehensive caching abstraction layer for Play Framework applications. It offers both synchronous and asynchronous APIs for cache operations with support for various cache implementations (EhCache, Caffeine, JCache). The library supports both Scala and Java programming languages with type-safe operations and configurable expiration times.
3
4
## Package Information
5
6
- **Package Name**: com.typesafe.play:play-cache_2.11
7
- **Package Type**: Maven
8
- **Language**: Scala/Java (dual language support)
9
- **Version**: 2.7.9
10
- **Installation**: Add `libraryDependencies += "com.typesafe.play" %% "play-cache" % "2.7.9"` to your `build.sbt` (requires Play Framework 2.7.x)
11
12
## Core Imports
13
14
### Scala API
15
16
```scala
17
import play.api.cache.{AsyncCacheApi, SyncCacheApi, Cached}
18
import javax.inject.Inject
19
import scala.concurrent.duration._
20
```
21
22
### Java API
23
24
```java
25
import play.cache.AsyncCacheApi;
26
import play.cache.SyncCacheApi;
27
import play.cache.Cached;
28
import play.cache.NamedCache;
29
import javax.inject.Inject;
30
```
31
32
## Basic Usage
33
34
### Scala Example
35
36
```scala
37
import play.api.cache.{AsyncCacheApi, SyncCacheApi}
38
import javax.inject.Inject
39
import scala.concurrent.Future
40
import scala.concurrent.duration._
41
42
class UserService @Inject()(cache: AsyncCacheApi) {
43
// Async cache operations
44
def getUser(id: String): Future[Option[User]] = {
45
cache.get[User](s"user:$id").flatMap {
46
case Some(user) => Future.successful(Some(user))
47
case None =>
48
// Load from database and cache
49
loadUserFromDb(id).map { user =>
50
cache.set(s"user:$id", user, 1.hour)
51
Some(user)
52
}
53
}
54
}
55
56
// Sync cache operations
57
def getUserSync(id: String): Option[User] = {
58
cache.sync.get[User](s"user:$id") match {
59
case Some(user) => Some(user)
60
case None =>
61
val user = loadUserFromDbSync(id)
62
cache.sync.set(s"user:$id", user, 1.hour)
63
Some(user)
64
}
65
}
66
}
67
```
68
69
### Java Example
70
71
```java
72
import play.cache.AsyncCacheApi;
73
import play.cache.SyncCacheApi;
74
import javax.inject.Inject;
75
import java.util.concurrent.CompletionStage;
76
import java.util.Optional;
77
78
public class UserService {
79
private final AsyncCacheApi cache;
80
81
@Inject
82
public UserService(AsyncCacheApi cache) {
83
this.cache = cache;
84
}
85
86
// Async cache operations
87
public CompletionStage<Optional<User>> getUser(String id) {
88
return cache.getOptional("user:" + id)
89
.thenCompose(userOpt -> {
90
if (userOpt.isPresent()) {
91
return CompletableFuture.completedFuture(userOpt);
92
} else {
93
return loadUserFromDb(id)
94
.thenCompose(user ->
95
cache.set("user:" + id, user, 3600)
96
.thenApply(done -> Optional.of(user))
97
);
98
}
99
});
100
}
101
102
// Sync cache operations
103
public Optional<User> getUserSync(String id) {
104
Optional<User> cached = cache.sync().getOptional("user:" + id);
105
if (cached.isPresent()) {
106
return cached;
107
}
108
109
User user = loadUserFromDbSync(id);
110
cache.sync().set("user:" + id, user, 3600);
111
return Optional.of(user);
112
}
113
}
114
```
115
116
## Architecture
117
118
The Play Cache API is organized around several key components:
119
120
- **Async/Sync API Pattern**: Both AsyncCacheApi and SyncCacheApi provide similar operations, with sync APIs wrapping async APIs using blocking calls
121
- **Cross-Language Support**: Scala and Java APIs with adapter classes for interoperability
122
- **Dependency Injection**: Full integration with Play's DI framework using @Inject and @NamedCache
123
- **Type Safety**: Scala ClassTag and Java generics for compile-time type safety
124
- **Action-Level Caching**: Built-in support for HTTP response caching with ETag and Expires headers
125
- **Serialization**: Automatic serialization handling for cacheable objects
126
- **Multiple Cache Support**: @NamedCache annotation for using multiple cache instances
127
128
## Capabilities
129
130
### Core Cache Operations
131
132
Basic cache operations for storing, retrieving, and removing data with optional expiration times.
133
134
```scala { .api }
135
// Scala API
136
trait AsyncCacheApi {
137
def set(key: String, value: Any, expiration: Duration = Duration.Inf): Future[Done]
138
def get[T: ClassTag](key: String): Future[Option[T]]
139
def remove(key: String): Future[Done]
140
def getOrElseUpdate[A: ClassTag](key: String, expiration: Duration = Duration.Inf)(orElse: => Future[A]): Future[A]
141
def removeAll(): Future[Done]
142
lazy val sync: SyncCacheApi
143
}
144
145
trait SyncCacheApi {
146
def set(key: String, value: Any, expiration: Duration = Duration.Inf): Unit
147
def get[T: ClassTag](key: String): Option[T]
148
def remove(key: String): Unit
149
def getOrElseUpdate[A: ClassTag](key: String, expiration: Duration = Duration.Inf)(orElse: => A): A
150
}
151
```
152
153
```java { .api }
154
// Java API
155
public interface AsyncCacheApi {
156
default SyncCacheApi sync();
157
<T> CompletionStage<Optional<T>> getOptional(String key);
158
<T> CompletionStage<T> getOrElseUpdate(String key, Callable<CompletionStage<T>> block, int expiration);
159
<T> CompletionStage<T> getOrElseUpdate(String key, Callable<CompletionStage<T>> block);
160
CompletionStage<Done> set(String key, Object value, int expiration);
161
CompletionStage<Done> set(String key, Object value);
162
CompletionStage<Done> remove(String key);
163
CompletionStage<Done> removeAll();
164
}
165
166
public interface SyncCacheApi {
167
<T> Optional<T> getOptional(String key);
168
<T> T getOrElseUpdate(String key, Callable<T> block, int expiration);
169
<T> T getOrElseUpdate(String key, Callable<T> block);
170
void set(String key, Object value, int expiration);
171
void set(String key, Object value);
172
void remove(String key);
173
}
174
```
175
176
[Core Cache Operations](./core-cache-operations.md)
177
178
### Action-Level HTTP Caching
179
180
Built-in HTTP response caching for Play Framework actions with ETag and cache header support.
181
182
```scala { .api }
183
class Cached @Inject() (cache: AsyncCacheApi)(implicit materializer: Materializer) {
184
def apply(key: RequestHeader => String, caching: PartialFunction[ResponseHeader, Duration]): CachedBuilder
185
def apply(key: RequestHeader => String): CachedBuilder
186
def apply(key: String): CachedBuilder
187
def apply(key: RequestHeader => String, duration: Int): CachedBuilder
188
def apply(key: RequestHeader => String, duration: Duration): CachedBuilder
189
}
190
191
final class CachedBuilder {
192
def apply(action: EssentialAction): EssentialAction
193
def build(action: EssentialAction): EssentialAction
194
def includeStatus(status: Int): CachedBuilder
195
def includeStatus(status: Int, duration: Duration): CachedBuilder
196
def default(duration: Duration): CachedBuilder
197
def compose(alternative: PartialFunction[ResponseHeader, Duration]): CachedBuilder
198
}
199
```
200
201
```java { .api }
202
@With(CachedAction.class)
203
@Target({ElementType.TYPE, ElementType.METHOD})
204
@Retention(RetentionPolicy.RUNTIME)
205
public @interface Cached {
206
String key();
207
int duration() default 0;
208
}
209
210
public class CachedAction extends Action<Cached> {
211
public CompletionStage<Result> call(Request req);
212
}
213
```
214
215
[Action-Level HTTP Caching](./action-caching.md)
216
217
### Dependency Injection and Named Caches
218
219
Support for multiple cache instances using named cache injection with Play's DI framework.
220
221
```java { .api }
222
@Qualifier
223
@Retention(RetentionPolicy.RUNTIME)
224
public @interface NamedCache {
225
String value();
226
}
227
228
public class NamedCacheImpl implements NamedCache, Serializable {
229
public NamedCacheImpl(String value);
230
public String value();
231
}
232
```
233
234
```scala { .api }
235
// Type alias in Scala package object
236
type NamedCache = play.cache.NamedCache
237
```
238
239
[Dependency Injection and Named Caches](./named-caches.md)
240
241
## Types
242
243
```scala { .api }
244
// Scala types
245
import akka.Done
246
import scala.concurrent.Future
247
import scala.concurrent.duration.Duration
248
import scala.reflect.ClassTag
249
import play.api.mvc.{EssentialAction, RequestHeader, ResponseHeader, Result}
250
251
// Default implementation classes
252
class DefaultSyncCacheApi @Inject() (val cacheApi: AsyncCacheApi) extends SyncCacheApi
253
254
private[play] final class SerializableResult(constructorResult: Result) extends Externalizable
255
```
256
257
```java { .api }
258
// Java types
259
import akka.Done;
260
import java.util.concurrent.CompletionStage;
261
import java.util.concurrent.Callable;
262
import java.util.Optional;
263
264
// Default implementation classes
265
@Singleton
266
public class DefaultAsyncCacheApi implements AsyncCacheApi
267
public class DefaultSyncCacheApi implements SyncCacheApi
268
public class SyncCacheApiAdapter implements SyncCacheApi
269
```