Reputation: 2089
I'm using scala play 2.5 and I have the following error while trying to inject an object in one of my controllers. I'm using the default injection framework given with play which is 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
Here is the controller:
package controllers
import services.MyService
class MyController @Inject()(myService: MyService, val messagesApi: MessagesApi) extends Controller with I18nSupport {
def someFunctionThatUsesMyService(url: String) = Action {}
}
Here is the service I would like to inject:
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
}
That is how I'm using it:
@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)))
}
}
Upvotes: 4
Views: 1102
Reputation: 3729
can you try to inject services directly, why do you need that layer of dummy traits? All stuff must work out of the box w/o any extra coding. You can always fine-tune your external deps. See example below.
Here is some code
Controller:
class MyController @Inject()(service: SomeConcreteService) extends Controller { /** just use service.anyMethod here */ }
Service:
@Singleton
class SomeConcreteService @Inject()(otherStuff: OtherStuffConcrete){
/** otherStuff will be also injected */
def mySuperServiceMethod:={ "Hey!" }
}
Test:
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")
}
}
Upvotes: 0
Reputation: 1874
You should add ImplementedBy
annotation to Service trait
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
}
Upvotes: 6