2011-12-04 76 views
1

我有一个非常简单的Vaadin应用程序。我想使用Guice注入我的Vaadin应用程序的主窗口。Vaadin Window组件未完全注入Guice

我的问题是我的主窗口被注入,但是我的@Inject指令在这个主窗口组件中没有被处理。

我使用CAS的完整代码源可以用a bitbucket repo

Vaadin应用程序类:

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()); 
    } 
} 

主窗口类:

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+")")); 
    } 
} 

GuiceServletContextListener,其中吉斯结合的定义:

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; 
    } 
} 

什么情况是,在主窗口被正确注射,但标签标题字符串总是空。任何想法?

回答

1

的解决方案是注入任何需要使用构造而不是领域注入在主窗口类被注入发生。请参阅hg repo上的标签stackoverflow-working-constructor-injection。源代码

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 + ")")); 
    } 
} 

样还不知道为什么字段注入不会在这种情况下工作。

解决方案是注入对我感谢this post

0

为什么不只是这样?

bind(String.class) 
.annotatedWith(Names.named("title")) 
.toInstance("This is a guicy Vaadin Application"); 
+0

虽然我的用例只显示了字符串(和bindConstant())的问题,但它发生在我尝试在MainWindow组件中注入的任何东西。 –

0

标题注入应用程序类?

您的问题只能处理指定的注释吗?尝试在窗口中注入一个bean来仔细检查...

+0

是的,标题正确注入到应用程序类中。不,这与名称注释无关(请参阅标记堆栈溢出 - 与hg repo无关) –

0

看起来像使用提供者来获取实际实例。你是否试过直接注入MainWindow ? 另外测试,如果注入实际上是增加了

@Inject void foo(Injector i){ 
System.out.println("injected"); 
} 
+0

是的,直接注入MainWindow对象不会更好。 –

0

我会建议你为标签和标题创建一个setter。 然后在它们上面定义@Inject。两者都受到保护我不知道这种情况下的guice行为,但是我所有的工作示例都可以使用带注释的setter注释或public字段进行注释。

1

你也应该考虑像下面这样:

public class MainWindow { 
    @Inject 
    public MainWindow(Injector injector) { 
    this.injector = injector; 
    } 

    @Override 
    protected void attach() { 
    super.attach(); // must call!!! 

    this.title = injector.getInstance(something); 
    ... 

    // set up listeners, etc, here 
    } 

    @Override 
    protected void detach() { 
    // disconnect listeners, remove child components 
    super.detach(); 
    } 

} 

通过这样做,你可以保持您的最小化应用实例的大小;在某些环境中,它在存储时序列化。推迟子构件的构建直到真正需要(并且对附加的听众进行相同的处理)可以帮助很多。 Vaadin论坛上有更多关于此主题的信息。