Компонент Vaadin Window не полностью введен с Guice - PullRequest
1 голос
/ 04 декабря 2011

У меня очень простое Vaadin приложение. Я хочу добавить главное окно моего приложения Vaadin , используя Guice .

Моя проблема заключается в том, что мое главное окно внедрено, но ни одна из моих директив @ Inject внутри этого компонента основного окна не обрабатывается.

Полный исходный код моего использования доступен на Репозиторий 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+")"));
    }
}

GuiceServletContextListener , где определены привязки guice:

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 корректно вводится, но строки label и title всегда равны нулю. Есть идеи?

Ответы [ 6 ]

1 голос
/ 05 января 2012

Вы также должны рассмотреть что-то вроде следующего:

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 есть еще сообщения на эту тему.

1 голос
/ 04 декабря 2011

решение состоит в том, чтобы внедрить все, что нужно внедрить в класс MainWindow, используя конструктор вместо поле ввода .См. Тег stackoverflow-working-with-constructor-инъекция в hg repo .

Образцы исходного кода

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

Пока не знает, почему Внедрение поля не работает в этом случае.

Решение было введено мне благодаря этому посту .

0 голосов
/ 04 декабря 2011

Я предлагаю вам создать сеттер для метки и заголовка. Затем определите @Inject для них. И то и другое защищено. Я не знаю хитрого поведения в этом случае, но все мои рабочие примеры работают с аннотированными сеттерами или аннотированными открытыми полями.

0 голосов
/ 04 декабря 2011

похоже на то, что вы используете провайдера для получения фактического экземпляра. Вы пытались просто ввести MainWindow напрямую ? Также проверьте, действительно ли происходит инъекция, добавив

@Inject void foo(Injector i){
 System.out.println("injected");
}
0 голосов
/ 04 декабря 2011

Введено ли название в класс приложения?

Может ли ваша проблема иметь дело только с именованными аннотациями?Попробуйте ввести боб в окно для двойной проверки ...

0 голосов
/ 04 декабря 2011

почему бы не просто так?

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