我使用scala play 2.5并且在尝试在我的一个控制器中注入对象时出现以下错误。 我使用的是默认的注入框架,游戏是Guice。
ProvisionException: Unable to provision, see the following errors:
1) No implementation for services.MyService was bound.
while locating services.MyService for parameter 0 at controllers.MyController.<init>(MyController.scala:12)
while locating controllers.MyController for parameter 3 at router.Routes.<init>(Routes.scala:55)
while locating router.Routes
while locating play.api.inject.RoutesProvider while locating play.api.routing.Router for parameter 0 at play.api.http.JavaCompatibleHttpRequestHandler.<init>(HttpRequestHandler.scala:200)
while locating play.api.http.JavaCompatibleHttpRequestHandler
while locating play.api.http.HttpRequestHandler for parameter 4 at play.api.DefaultApplication.<init>(Application.scala:221) at play.api.DefaultApplication.class(Application.scala:221)
while locating play.api.DefaultApplication
while locating play.api.Application
这是控制器:
package controllers
import services.MyService
class MyController @Inject()(myService: MyService, val messagesApi: MessagesApi) extends Controller with I18nSupport {
def someFunctionThatUsesMyService(url: String) = Action {}
}
这是我想要注入的服务:
package services
import javax.inject._
trait MyService {
def op(param1: String, param2: String): Boolean
}
@Singleton
class BasicMyService extends MyService {
override def op(param1: String, param2: String): Boolean = true
}
这就是我使用它的方式:
@Singleton
class HomeController @Inject() extends Controller {
/**
* Create an Action to render an HTML page with a welcome message.
* The configuration in the `routes` file means that this method
* will be called when the application receives a `GET` request with
* a path of `/`.
*/
def index = Action {
//Ok(views.html.index("Your new application is ready."))
Redirect(routes.MyController.someFunctionThatUsesMyService(Some(routes.OtherController.welcomePage().url)))
}
}
答案 0 :(得分:5)
您应该将ImplementedBy
注释添加到服务特征
package services
import javax.inject._
@ImplementedBy(classOf[BasicMyService])
trait MyService {
def op(param1: String, param2: String): Boolean
}
@Singleton
class BasicMyService extends MyService {
override def op(param1: String, param2: String): Boolean = true
}
答案 1 :(得分:0)
你可以尝试直接注入服务吗,为什么你需要那层虚拟特征?所有的东西必须开箱即用,没有任何额外的编码。您可以随时微调外部设备。见下面的例子。
这是一些代码
控制器:
class MyController @Inject()(service: SomeConcreteService) extends Controller { /** just use service.anyMethod here */ }
服务:
@Singleton
class SomeConcreteService @Inject()(otherStuff: OtherStuffConcrete){
/** otherStuff will be also injected */
def mySuperServiceMethod:={ "Hey!" }
}
测试:
class MyControllerTest extends PlaySpec with OneAppPerSuite with MockitoSugar {
// do it this way if you want framework to provide controller instance
private val myController = app.injector.instanceOf[MyController]
// or mock external deps and build controller on your own
val externalService = mock[SomeConcreteService]
val handMadeController = new MyController(externalService)
"My controller" should{
"do its best " in {
val response = call(handMadeController.doStuff, FakeRequest())
status(response) mustBe OK
contentAsString(response) must include("Best controller")
}
}