Update: Play Framework now supports Java filters as of 2.5, so this post is no longer as relevant as it once was if you are on the latest version. However, if you aren’t able to upgrade, continue reading.
Working with the more advanced features of the Play Framework can be rather challenging if all you are used to is Java. Play only exposes Scala APIs for Filters. However, because of Java and Scala interoperability, it is possible to access those Scala APIs through Java. Possible doesn’t necessarily mean pretty. Below is a walkthough on how to implement a Filter only using Java.
Translating play.api.mvc.Filter from Scala to Java
The hard part about this whole process is understanding how to extend the Filter class in Java. Without further ado, here’s the magic:
The code above maps Scala only features into the Java features we know and love (read: are familiar with and tolerate).
the Filter trait is treated as an interface. Since traits can have method implementations, we must use a special syntax (Filter$class.apply) to access the trait method. Filter$class is a class that is created at compile time that contains static methods.
Function1 is a trait exposed to allow the use of lambda functions. Ideally, one would be able to pass in a Java 8 lambda function, but this is not possible since Function1 has more than one method defined and cannot be a functional interface. However, the pre-Java 8 trick of using anonymous classes as make-shift lambda functions totally works for us here.
The Scala Future API methods take in an implicit ExecutionContext. In Scala, implicit parameters don’t need to be explicitly passed in. Java has no such concept, so we must get the current ExecutionContext (with magic) and pass it long.
Implementing a simple Filter
Let’s say you want to add an HTTP response header “X-Hello” with value “World!” every time the incoming request has a “X-Filter” header. All you have to do is implement our JavaFilter from above!
JavaFilter provides a ready-to-go abstract definition that is eventually called by the Play pipeline. However, interacting with the Result class directly is a bit cumbersome since the method parameters take in classes that are generated by syntactic sugar in Scala. I’ve added a quick Adapter below that should allow you to add a response header as a traditional key-value pair.
Enabling the Filter
So, you’re good to go! Actually, not really. You need to let Play know about your new Filter. Below is an example Global.java class that will add the Filter.
Now you’re done!