When we are using Play Framework Action Composition we can directly use the @With
annotation, as explained here. Alternatively, we can define custom action annotations.
But what are the advantages of defining your own annotations? It’s like we are just adding a middle-man (interface).
And one more doubt: while implementing the action class we use generics to specify a corresponding interface. Is it just because Play is type safe? In the docs they have mentioned “Action definition retrieves the annotation as configuration”. Is it just because we can configure using custom annotations?
Advertisement
Answer
Think about the following annotation:
@With(CacheAction.class) @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Cached { String key(); Long expires(); String region(); }
With the annotation above, you can annotate your actions like:
@Cached( key = "my.cached.page", expires = 30, region = "pages" ) public Result index() { ... }
So, how would you pass these cache configurations to the composing action using the @With
annotation? You could not. @With
is good if you don’t have to configure how the composing action will behave, like logging in the documentation examples. But if you need, then declaring your own annotations is necessary.
The Action
class expects the annotation type because you can then retrieve the configuration
while calling the composing action:
public CompletionStage<Result> call(Context ctx) { Cached cacheConfiguration = this.configuration; String key = cacheConfiguration.key(); Long expires = cacheConfiguration.expires(); string region = cacheConfiguration.region(); ... }
Finally, defining your annotations is good because you can better express their semantics (this is a @Cached
action, an @Authenticated
action, etc.).