1

私は非常に単純なVaadinアプリケーションを持っています。Guiceを使用してVaadinアプリのメインウィンドウを挿入したいと思います。

私の問題は、メインウィンドウが挿入されているのに、このメインウィンドウコンポーネント内の@Injectディレクティブが処理されていないことです。

私のusecasの完全なコードソースは、bitbucketリポジトリで入手できます。

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

MainWindowクラス

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

guiceバインディングが定義されている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;
    }
}

何が起こるかというと、MainWindowは正しく挿入されますが、ラベルタイトルの文字列は常にnullです。何か案が?

4

6 に答える 6

1

解決策は、フィールドインジェクションの代わりにコンストラクターを使用して、MainWindowクラスに注入する必要があるものをすべて注入することです。hgリポジトリのタグstackoverflow-working-with-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 + ")"));
    }
}

この場合、フィールドインジェクションが機能しない理由はまだわかりません。

この投稿のおかげで、ソリューションが私に注入されました。

于 2011-12-04T13:46:21.683 に答える
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フォーラムにはさらに多くのメッセージがあります。

于 2012-01-05T14:46:46.600 に答える
0

タイトルはアプリケーションクラスに挿入されていますか?

あなたの問題は名前付きアノテーションのみを扱うことができますか?ウィンドウにBeanを挿入して、再確認してください...

于 2011-12-04T12:34:25.623 に答える
0

なぜこのようなものではないのですか?

bind(String.class)
.annotatedWith(Names.named("title"))
.toInstance("This is a guicy Vaadin Application");
于 2011-12-04T12:05:25.227 に答える
0

プロバイダーを使用して実際のインスタンスを取得しているように見えます。MainWindowを直接注入してみましたか?また、注入が実際に発生するかどうかをテストするには、

@Inject void foo(Injector i){
 System.out.println("injected");
}
于 2011-12-04T13:11:02.813 に答える
0

ラベルとタイトルのセッターを作成することをお勧めします。次に、それらに@Injectを定義します。どちらも保護されています。この場合のguiceの動作はわかりませんが、すべての作業例は、セッター注釈付きまたはパブリックフィールド注釈付きで機能します。

于 2011-12-04T17:25:36.890 に答える