Route binding custom classes in Play! Framework

Andrew Conner
Keep It Up
Published in
2 min readMay 13, 2016

One of Play!’s primary features is typed routing, which enables you to use strong types from your controllers. Buried in Play’s documentation (to the best of my knowledge, not linked anywhere) is an example of how to use your own types in routes using QueryStringBindable and PathBindable. At Kifi, we’ve found immense value in typing nearly all paths and query parameters. For example, instead of using a Long for a User id, we use Id[User]. This helps us document our endpoints more safely, and makes using types in the controllers much easier.

Implementing this is simple enough:

If you provide your own PathBindable or QueryStringBindable, make sure Play! knows to import them in your routes file by using the routesImport SBT settings key.

You can take this approach a bit further and accept binding to/from entire case classes. Let’s say you have a value class holding filtering and sorting information:

If you plan on using this case class in many routes (for all endpoints that support this kind of pagination, filtering, etc), it’s may be useful to define a QueryStringBindable so that your routes file can be as simple as:

Here’s a direct implementation:

You’ll notice two helper methods bnd and ubnd that help a bit with boilerplate and type inference. Since all parameters are optional (or we can fill in a default), we’ll always match (by always returning Some). However, if any sub-keys are provided, they must bind correctly — so if an invalid DateTime is provided, the client will know.

Routing will simply use the key specified in your routes file, followed by .subkey:

Ideas for future work: If you use this pattern frequently, you may want to use Play’s functional combinators to create something similar to their JSON combinator parsing. Or, use a macro, like Kifi’s json macro.

--

--