Utiliser des types personnalisés dans ses routes Play! Framework 2

L’utilisation des routes de Play! Framework est d’une extrême simplicité lorsque l’on utilise des types « standards ». Lorsqu’il s’agit d’utiliser un type plus exotique (au hasard, quelque chose que l’on n’utilise jamais… un UUID par exemple), la chose n’est pas aussi évidente.

Pour ce faire, il est nécessaire de définir un binder en implémentant l’interface PathBindable. Ce binder, pour l’API Java, doit être auto-récursif.

class FooBinder extends PathBindable { // Du contenu. }

Implémentation

L’observation de cette interface lève une interrogation sur la méthode unbind : comment « unbinder » la valeur si celle-ci n’est pas passée en paramètre ? Piège.

/** Unbind a URL path parameter. @param key Parameter key @param value Parameter value. */ public String unbind(String key);

L’astuce (grand mot s’il en est) consiste à stocker la valeur au moment de la construction de l’ojet. Prenons comme exemple l’UUID :

public class UuidBinder implements PathBindable { private UUID uuid; /** {@inheritDoc} / @Override public UuidBinder bind(String key, String txt) { uuid = UUID.fromString(txt); return this; } /* {@inheritDoc} / @Override public String unbind(String key) { return uuid.toString(); } /* {@inheritDoc} */ @Override public String javascriptUnbind() { return null; } }

Celui-ci sera utilisable dès lors qu’il aura été déclaré dans le fichier Build.scala :

val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings( routesImport += "util.binders.UuidBinder."; )

Utilisation

L’utilisation depuis les routes est immédiat :
GET /foo/:uuid controllers.MyFooController.viewBar(uuid: util.binders.UuidBinder)

L’utilisation depuis les templates l’est un peu moins. Une solution simple consiste à enrichir le modèle :

class Bar extends Model { @Id public UUID uuid; @Transient public UuidBinder bindUuid() { return UuidBinder.create(uuid); } }

La méthode create de UuidBinder se contente d’instancier un nouvel objet et de l’alimenter :

public static UuidBinder create(final UUID uuid) { UuidBinder u = new UuidBinder(); u.uuid = uuid; return u; }

View my bar!

Il peut être utile également de pouvoir récupérer la valeur de l’UUID. Ajoutons pour cela dans UuidBinder un simple getter :

public UUID uuid() { return uuid; }

Ainsi, on peut l’utiliser dans le contrôleur :

public static Result viewBar(UuidBinder id) { UUID uuid = id.uuid(); Bar bar = BarService.getBar(uuid); return barDetail(bar); }