Lucas Yang
Lucas Yang

Reputation: 43

Why Guice cannot find my implementation in Play framework?

My controller code have a trait and a implementation of that trait which also extends CustomeExecutionContext, but Guice cannot find my implementation.

The controller code:

package controllers

import javax.inject._
import play.api._
import play.api.mvc._
import play.api.libs.json._
import com.ntu.rule._
import akka.actor.ActorSystem
import scala.concurrent.Future
import play.api.libs.concurrent._
import scala.concurrent.ExecutionContext

trait RuleValidationExecutionContext extends ExecutionContext

class RuleValidationExecutionContextImpl @Inject()(system: ActorSystem)
  extends CustomExecutionContext(system, "rule-validation-context") with RuleValidationExecutionContext

@Singleton
class RulesController @Inject()(cc: ControllerComponents,
                                ruleValidationExecutionContext: RuleValidationExecutionContext) extends AbstractController(cc) {

  def validate() = Action(parse.json).async { implicit request: Request[JsValue] =>
    Future {
      val rule = (request.body \ "rule").as[String]
      val parsedRule = RuleUtils.parseRules(rule)
      val (isSuccess, message) = RuleUtils.validate(parsedRule)
      Ok(Json.parse(
        s"""
           |{"success": $isSuccess, "message": "$message"}
      """.stripMargin))
    }(ruleValidationExecutionContext)
  }
}

And application.conf:

rule-validation-context {
  fork-join-executor {
    parallelism-factor = 20.0
    parallelism-max = 200
  }
}

When I request the action, it shows:

1 error]
        at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1.reload(DevServerStart.scala:186)
        at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1.get(DevServerStart.scala:124)
        at play.core.server.AkkaHttpServer.play$core$server$AkkaHttpServer$$modelConversion(AkkaHttpServer.scala:183)
        at play.core.server.AkkaHttpServer.play$core$server$AkkaHttpServer$$handleRequest(AkkaHttpServer.scala:189)
        at play.core.server.AkkaHttpServer$$anonfun$5.apply(AkkaHttpServer.scala:106)
        at play.core.server.AkkaHttpServer$$anonfun$5.apply(AkkaHttpServer.scala:106)
        at akka.stream.impl.fusing.MapAsync$$anon$24.onPush(Ops.scala:1191)
        at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:512)
        at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:475)
        at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:371)
Caused by: com.google.inject.ProvisionException: Unable to provision, see the following errors:

1) No implementation for controllers.RuleValidationExecutionContext was bound.
  while locating controllers.RuleValidationExecutionContext
    for the 2nd parameter of controllers.RulesController.<init>(RulesController.scala:19)
  while locating controllers.RulesController
    for the 4th parameter of router.Routes.<init>(Routes.scala:38)
  while locating router.Routes
  while locating play.api.inject.RoutesProvider
  while locating play.api.routing.Router
    for the 1st parameter of play.api.http.JavaCompatibleHttpRequestHandler.<init>(HttpRequestHandler.scala:222)
  while locating play.api.http.JavaCompatibleHttpRequestHandler
  while locating play.api.http.HttpRequestHandler
    for the 6th parameter of play.api.DefaultApplication.<init>(Application.scala:236)
  at play.api.DefaultApplication.class(Application.scala:235)
  while locating play.api.DefaultApplication
  while locating play.api.Application

But the implementation is in the controller code as above, why Guice cannot find it?? My Scala version is 2.11.11, Play Framework version is 2.6.11

Upvotes: 1

Views: 853

Answers (1)

David
David

Reputation: 241

I guess the reason is Guice needs more information on which instance should be instantiated for the parameter of type ruleValidationExecutionContext. although you add @inject annotation to the class RuleValidationExecutionContextImpl, it is not the same type as ruleValidationExecutionContext. you can do

  1. add another annotation

    @ImplementedBy(classOf[RuleValidationExecutionContextImpl]) trait RuleValidationExecutionContext extends ExecutionContext //blah blah...

or

  1. add something like below to your module.scala

```

import com.google.inject.AbstractModule

class Module extends AbstractModule {
  def configure() = {
    bind(classOf[RuleValidationExecutionContext])
      .to(classOf[RuleValidationExecutionContextImpl])
  }
}

```

Please refer to this link

Upvotes: 2

Related Questions