Reputation: 377
I'm migrating a Play web app to v2.6 and I'm having trouble understanding how dependency injection works with Messages considering that Messages are dependent on the HTTP context of the request.
I added a field injection to a controller like this:
public class MyController extends Controller {
@Inject
private Messages m;
public Result all(String uuid){
// using m.at("xxxxxx")
}
}
And I've got something like this:
play.api.UnexpectedException: Unexpected exception[ProvisionException:
Unable to provision, see the following errors:
1) No implementation for play.i18n.Messages was bound.
while locating play.i18n.Messages
for field at
controllers.MyController.m(MyController.java:23)
while locating controllers.MyController
for the 5th parameter of router.Routes.<init>(Routes.scala:63)
Then I tried to fix it by configuring an implementation for the Messages interface by adding a Module class inside the app folder:
import com.google.inject.AbstractModule;
import play.i18n.Messages;
import play.libs.akka.AkkaGuiceSupport;
import play.mvc.Http;
public class Module extends AbstractModule implements AkkaGuiceSupport {
@Override
public void configure() {
bind(Messages.class).toInstance(Http.Context.current().messages());
}
}
This gave me another error:
1) No implementation for play.i18n.Messages was bound.
at Module.configure(Module.java:10) (via modules:
com.google.inject.util.Modules$OverrideModule -> Module)
2) An exception was caught and reported. Message: There is no HTTP
Context available from here.
at com.google.inject.util.Modules$OverrideModule.configure(Modules.java:177)
I had a look at a code example of how DI works with Play but I assume this is already implemented in Play for Messages.
I'm starting to think that I should use Http.Context.current().messages() in each controller and then pass it to any other class via constructor, which is verbose and maybe it defeats the purpose of DI in the first place.
Upvotes: 0
Views: 1783
Reputation: 3972
Alternatively if using Scala, in your controller add I18nSupport and make sure your action adds the implicit request =>
to enrich the request with default Languages:
import play.api.i18n._
@Singleton
class HomeController @Inject()(cc: ControllerComponents)
extends AbstractController(cc) with I18nSupport {
def index() = Action { implicit request =>
Ok(views.html.index())
}
}
In your main template and your specific templates make sure to import MessagesProvider:
@()(implicit messagesProvider: play.api.i18n.MessagesProvider)
And wherever in your template add i18n messages like this:
<h1>@messagesProvider.messages("app.title")</h1>
Upvotes: 3
Reputation: 477
You need to initialize it in constructor and the use it as follow
public class MyController extends Controller {
private final play.i18n.MessagesApi messagesApi;
@Inject
public MyController (MessagesApi messagesApi) {
this.messagesApi = messagesApi;
}
public Result all(String uuid){
messagesApi.get(Lang.forCode("en"), "hello");
}
}
Upvotes: 1