[2.4.6 Java] How to inject a controller into Twirl templates

1,007 views
Skip to first unread message

Peace MICHAELS

unread,
Jan 5, 2016, 7:07:43 PM1/5/16
to play-framework
just like the subject says, how do i inject a controller into a twirl template? i mean instead of calling a static method in the controller from the view like so:

@SomeController.staticMethod i want to be do something like
@injectedSomeController.method

Steve Chaloner

unread,
Jan 6, 2016, 4:36:58 AM1/6/16
to play-framework
To the best of my knowledge, templates are not injectable.  When you say controller, you mean an actual Play HTTP controller, or some utility class?

You can work around the lack of DI in a couple of ways.  You can wrap injectedSomeController.method in a function and pass that into the template, or you can use implicits.  For example, let's say you want to access a specific DAO (or controller, or whatever) in your template, you can write something like

package com.example.stuff

object ViewAccessPoint {
  private[stuff] val myDaoCache = Application.instanceCache[MyDao]

  object Implicits {
    implicit def myDao(implicit application: Application): MyDao = myDaoCache(application)
  }
}

In your template, you can then access it using

@import com.example.stuff.ViewAccessPoint.Implicits._

myDao.whatever()
 
This works for both Java and Scala, despite the code being written in Scala.

Peace MICHAELS

unread,
Jan 6, 2016, 5:42:12 AM1/6/16
to play-fr...@googlegroups.com
thank you steve. my scala proficiency is very much beginers' could you
please express it in java thanks..
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "play-framework" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/play-framework/88OL1zHANIE/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> play-framewor...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/play-framework/3ecb3ccf-9d2c-4252-b5a7-2df5a46f25ef%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

Steve Chaloner

unread,
Jan 6, 2016, 7:42:58 AM1/6/16
to play-framework
You will need to use Scala to get the implicit, but you can pretty much cut and paste the code from above.  You'll just need to change the type from MyDao to whatever you need.

Steve Chaloner

unread,
Jan 6, 2016, 7:50:18 AM1/6/16
to play-framework
Alternatively, you could explicitly pass a supplier into the template.

For example, if SomeController.staticMethod returns a string, you can rewrite this template

@import com.example.SomeController

<p>
@SomeController.staticMethod</p>

to this

@import java.util.function.Supplier
@(mySupplier: Supplier[String])

<p>mySupplier.get()</p>

with this controller

public F.Promise<Result> foo() {
   
return F.Promise.promise(() -> myTemplate.render(() -> SomeController.staticMethod))
                   
.map(Results::ok);
}

The static call within the lambda can of course be replaced by injecting a an object with the desired logic into the controller and using that instead.

This approach means that 
a) You don't have to write any Scala
b) You don't need to write an implicit for every thing you want to access
c) your templates are more declarative






On Wednesday, 6 January 2016 01:07:43 UTC+1, Peace MICHAELS wrote:

Greg Methvin

unread,
Jan 6, 2016, 8:01:04 AM1/6/16
to play-framework
Twirl doesn't integrate with Guice (or other runtime DI). But you can still do "manual" dependency injection by passing your dependencies as arguments to the template.

I have never had a need to inject things like DAOs or controllers into my templates. Generally I look at templates as pure functions that take some raw data and render it. If I need to fetch a list of people, for example, I would do that in my controller and pass the list to the template to render it. I think that makes the templates easier to understand and the controller code easier to debug.

Marius Soutier

unread,
Jan 6, 2016, 8:24:29 AM1/6/16
to play-fr...@googlegroups.com
Definitely yes!

Steve Chaloner

unread,
Jan 6, 2016, 8:38:40 AM1/6/16
to play-framework
Absolutely agreed, but I have found it useful to provide default values in some cases; handlerCache and viewSupport in this example comes from an implicit:

@import be.objectify.deadbolt.scala.ViewAccessPoint.Implicits._
@(handler: DeadboltHandler = handlerCache.apply(), name: String, meta: String = null, timeout: Function0[Long] = viewSupport.defaultTimeout)(body: => play.twirl.api.Html)(implicit request: Request[Any])



On Wednesday, 6 January 2016 01:07:43 UTC+1, Peace MICHAELS wrote:

Naftoli Gugenheim

unread,
Jan 6, 2016, 4:18:14 PM1/6/16
to play-framework

Pass it in as a parameter?


--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/ff13098b-e049-44d7-a5b0-2c7a64f2fff2%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages