I have a very simple Vaadin application. I want to inject the main window of my Vaadin app using Guice.
My problem is that my main window is injected, but none of my @Inject directives inside this main window component are processed.
The full code source of my use cas is available on a bitbucket repo
The Vaadin application class:
public class MyVaadinApplication extends Application {
protected final Provider<MainWindow> mainWindowProvider;
@Inject
@Named("title")
protected String title;
@Inject
public MyVaadinApplication(Provider<MainWindow> mainWindowProvider) {
this.mainWindowProvider = mainWindowProvider;
}
@Override
public void init() {
System.out.println("MyVaadinApplication:: found value <"+title+"> for injected title");
setMainWindow(this.mainWindowProvider.get());
}
}
The MainWindow class:
public class MainWindow extends Window {
@Inject
@Named("title")
protected String title;
@Inject
@Named("label")
protected String label;
private static int globalCounter = 0;
private int localCounter;
public MainWindow(String caption, ComponentContainer content) {
super(caption, content);
initUI();
}
public MainWindow(String caption) {
super(caption);
initUI();
}
public MainWindow() {
super();
initUI();
}
private void initUI() {
localCounter = globalCounter;
globalCounter++;
this.setCaption(title);
this.addComponent(new Button(label+" ("+localCounter+")"));
}
}
The GuiceServletContextListener where the guice binding are defined:
public class GuicyServletConfig extends GuiceServletContextListener {
@Override
protected Injector getInjector() {
ServletModule module = new ServletModule() {
@Override
protected void configureServlets() {
serve("/*").with(GuiceApplicationServlet.class);
bind(Application.class).to(MyVaadinApplication.class).in(ServletScopes.SESSION);
bind(MainWindow.class).in(ServletScopes.SESSION);
bindConstant().annotatedWith(Names.named("title")).to("This is a guicy Vaadin Application");
bindConstant().annotatedWith(Names.named("label")).to("Guice me!");
}
};
Injector injector = Guice.createInjector(module);
return injector;
}
}
What happens is that the MainWindow is correctly injected, but the label and title strings are always null. Any idea?
the solution is to inject anything that need to be injected in the MainWindow class using constructor instead of field injection. See the tag stackoverflow-working-with-constructor-injection on the hg repo.
Samples of the source code
public class MainWindow extends Window {
protected String title;
protected String label;
protected LabelCaption labelCaption;
private static int globalCounter = 0;
private int localCounter;
@Inject
public MainWindow(@Named("title") String title, @Named("label") String label, LabelCaption labelCaption) {
super();
this.title = title;
this.label = label;
this.labelCaption = labelCaption;
initUI();
}
private void initUI() {
localCounter = globalCounter;
globalCounter++;
this.setCaption(title);
String labelFromLabelCaption = "labelCaption is null";
if (labelCaption != null) {
labelFromLabelCaption = labelCaption.getCaption();
}
this.addComponent(new Button(label + "/" + labelFromLabelCaption + "/(" + localCounter + ")"));
}
}
Does not know yet why field injection does not work in this case.
The solution was injected to me thanks to this post.