Currently I define my app's javascript router in a fairly verbose way
def javascriptRoutes = Action { implicit request =>
import routes.javascript._
Ok(Routes.javascriptRouter("jsRoutes")(
Login.method1,Login.Method2,
OtherController.method1,OtherController.method2,
//[...]
)).as("text/javascript")
}
What I really would like to do is to create a javascriptRouter
with all of the routes in the routes
file, so I don't have to manually update the javascriptRoutes
definition each time I add a new controller method.
Is there a way to accomplish this task, or is there even a slightly less verbose way of defining the javascriptRouter
?
You can do it via reflection like so:
val routeCache = {
import routes._
val jsRoutesClass = classOf[routes.javascript]
val controllers = jsRoutesClass.getFields().map(_.get(null))
controllers.flatMap { controller =>
controller.getClass().getDeclaredMethods().map { action =>
action.invoke(controller).asInstanceOf[play.core.Router.JavascriptReverseRoute]
}
}
}
def javascriptRoutes = Action { implicit request =>
Ok(Routes.javascriptRouter("jsRoutes")(routeCache:_*)).as("text/javascript")
}
This was derived from the generated source files found in target/scala-2.x.x/src_managed. You could actually add your own source generator and parse the routes file yourself, but I find doing it via reflection easier.
An additional thing you might want to do is filter out the methods you don't want as this will give you ALL the routes (including the javascriptRouter itself).
Also, if you are using Play 2.4, some Classes/packages have been changed:
def javascriptRoutes = Action { implicit request =>
Ok(play.api.routing.JavaScriptReverseRouter("jsRoutes")(routeCache:_*)).as("text/javascript")
}
val routeCache: Array[JavaScriptReverseRoute] = {
import routes._
val jsRoutesClass: Class[javascript] = classOf[routes.javascript]
val controllers = jsRoutesClass.getFields.map(_.get(null))
val met = for (
controller <- controllers;
method <- controller.getClass.getDeclaredMethods if method.getReturnType == classOf[play.api.routing.JavaScriptReverseRoute]
) yield method.invoke(controller).asInstanceOf[play.api.routing.JavaScriptReverseRoute]
met
}
I needed that in java. Copying it here in case it is of use for someone.
public static Result javascriptRoutes() throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
// use reflection to get the fields of controllers.routes.javascript
Set<Object> reverseRoutes = new HashSet<Object>();
for (Field f : controllers.routes.javascript.class.getFields()) {
// get its methods
for (Method m : getAllMethods(f.getType(), withReturnType(JavascriptReverseRoute.class))) {
// for each method, add its result to the reverseRoutes
reverseRoutes.add(m.invoke(f.get(null)));
}
}
// return the reverse routes
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter("jsRoutes",
reverseRoutes.toArray(new JavascriptReverseRoute[reverseRoutes.size()])));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With