Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using guice when creating a custom Action using ActionBuilder in play

How can I use guice when creating a custom Action using ActionBuilder?

It seems to complain with "not found: value MyAction" if I change the ActionBuilder from a object to a class.

I have this but it doesn't work:

case class MyModel(name: String, request: Request[A]) extends WrappedRequest[A](request)

class MyAction @Inject()(userService: UserService) extends ActionBuilder[MyModel] {
  def invokeBlock[A](request: Request[A], block: (MyModel[A]) => Future[SimpleResult]) = {
    val abc = loadAbc(request)
    block(new MyModel(abc, request))
  }

  def loadAbc(rh: RequestHeader): String {
    "abc" // just for testing
  }
}

So changing it from an object to a class causes it to fail, and I tried keeping it as an object but then it doesn't compile correctly.

How can I get this to work?

I have it working just fine in my controllers.

like image 541
Blankman Avatar asked Mar 06 '26 14:03

Blankman


2 Answers

With a few minor corrections, what you've got seems to work already. All you've got to do is inject the guice-instantiated instance of MyAction into your controller, and then you can use the instance (rather than trying to use the MyAction class name).

This works with Play 2.3:

import scala.concurrent.Future
import javax.inject.{Inject, Singleton}
import play.api.mvc._

class UserService() {
  def loadAbc(rh: RequestHeader) = "abc"
}

class MyModel[A](val name: String, request: Request[A]) extends WrappedRequest[A](request)

class MyAction @Inject()(userService: UserService) extends ActionBuilder[MyModel] {
  def invokeBlock[A](request: Request[A], block: (MyModel[A]) => Future[Result]) = {
    val abc = userService.loadAbc(request)
    block(new MyModel(abc, request))
  }
}

@Singleton
class Application @Inject() (myAction: MyAction) extends Controller {
  def index = myAction { request =>
    Ok(request.name)
  }
}

You can't use object because that violates the design of Guice. object is a singleton instantiated by Scala itself and cannot have instance variables, whereas Guice needs to be able to instantiate classes on the fly so that it can inject dependencies.

like image 107
Alex Varju Avatar answered Mar 08 '26 19:03

Alex Varju


I think your code should work if you use it like this:

class MyClass @Inject()(myAction: MyAction) {
  val echo = myAction { request =>
    Ok("Got request [" + request + "]")
  }
}
like image 35
noziar Avatar answered Mar 08 '26 20:03

noziar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!