Spring ROO GWT,在 ui:binder 创建的小部件上进行 GIN 注入

发布于 2024-10-11 13:22:45 字数 2031 浏览 8 评论 0原文

我正在尝试访问 ui:binder 组件内的一些对象,但不确定如何访问 eventBus、requestFactory 等,而无需编写令人讨厌的代码,这些代码会让我彻夜难眠(另请注意,我完全不熟悉JAVA,背景是Perl/Python/PHP)。

我的 ui.xml 文件:

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    xmlns:g='urn:import:com.google.gwt.user.client.ui'
    xmlns:ig='urn:import:com.ig.client.scaffold.ui.widget'>
    <ui:style>
        ...
    </ui:style>
    <g:HorizontalPanel>
        ...
    </g:HorizontalPanel>
</ui:UiBinder>

以这种方式注入 eventBus 失败 com.ig.client.scaffold.ui.widget.R 没有默认(零参数)构造函数。

public class R extends Composite {

    interface MyUiBinder extends UiBinder<Widget, R> {}
    private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

    private final EventBus eventBus;

    @UiField SimplePanel fieldA, ...;

    @Inject
    public R(EventBus eventBus){
        this.eventBus = eventBus;
        initWidget(uiBinder.createAndBindUi(this));
    }
}

因此,根据错误消息,我创建了一个 UIFactory,然后收到错误 ... '{style.entityComponent}'>缺少必需的属性:eventBus 元素...(似乎它正在尝试在 ui:binder 样式表中找到 eventBus。

public class R extends Composite {

    interface MyUiBinder extends UiBinder<Widget, R> {}
    private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

    private final EventBus eventBus;

    @UiField SimplePanel fieldA, ...;

    public @UiConstructor R(EventBus eventBus){
        this.eventBus = eventBus;
        initWidget(uiBinder.createAndBindUi(this));
    }

    @Inject
    @UiFactory R makeR(){
        return new R(eventBus);
    }
}

通过过去几天的阅读和阅读,我还没有看到任何人访问eventBus、requestFactory 和 HistoryController 直接在视图中绑定到 ui:binder 小部件,这导致了这样的结论:这可能不是最佳实践 反正。

假设我有一个对象,我们称之为代理,代理包含handleButtonClick,然后调用eventBus.doSomething()。如何将此 Proxy 对象链接到 ui:binder 小部件,而无需实例化它或无需将其传递给每个小部件?

是否可以在接口上进行 GIN 注入,然后通过类 R 实现该接口,然后类 R 将以某种方式包含我正在寻找的对象?

任何可行的解决方案都是受欢迎的,只需寻找一个示例(Java n00b 可以理解),它基本上可以让我将我的前端与 ROO 创建的其余服务连接起来。

谢谢 J

I'm trying to access some objects inside a ui:binder component, but not sure of how to access the eventBus, requestFactory, etc without writing nasty code that will keep me awake at night (also take note that I'm completely new to JAVA, background is in Perl/Python/PHP).

My ui.xml file:

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    xmlns:g='urn:import:com.google.gwt.user.client.ui'
    xmlns:ig='urn:import:com.ig.client.scaffold.ui.widget'>
    <ui:style>
        ...
    </ui:style>
    <g:HorizontalPanel>
        ...
    </g:HorizontalPanel>
</ui:UiBinder>

Injecting the eventBus this way fails with
com.ig.client.scaffold.ui.widget.R has no default (zero args) constructor.

public class R extends Composite {

    interface MyUiBinder extends UiBinder<Widget, R> {}
    private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

    private final EventBus eventBus;

    @UiField SimplePanel fieldA, ...;

    @Inject
    public R(EventBus eventBus){
        this.eventBus = eventBus;
        initWidget(uiBinder.createAndBindUi(this));
    }
}

So, as per the error message, I create a UIFactory and then I get an error
... '{style.entityComponent}'> missing required attribute(s): eventBus Element ... (seems like it is trying to find the eventBus in the ui:binder stylesheet.

public class R extends Composite {

    interface MyUiBinder extends UiBinder<Widget, R> {}
    private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);

    private final EventBus eventBus;

    @UiField SimplePanel fieldA, ...;

    public @UiConstructor R(EventBus eventBus){
        this.eventBus = eventBus;
        initWidget(uiBinder.createAndBindUi(this));
    }

    @Inject
    @UiFactory R makeR(){
        return new R(eventBus);
    }
}

From reading and reading and more reading for the past couple of days, I haven't seen anyone accessing the eventBus, requestFactory and historyController directly in the view binding to the ui:binder widget which led to the conclusion that it's probably not a best practice
anyway.

Let's say I have an oject, let's call it Proxy, proxy contains handleButtonClick which then calls eventBus.doSomething(). How do I link this Proxy object to the ui:binder widget without having to instantiate it or without having to pass it around to every widget?

Is it possible to do GIN injection on an interface and then implement that interface via class R which will then somehow contain the objects I'm looking for?

Any solution that work is welcome, just looking for a sample (that a Java n00b can understand) that will basically allow me to connect my front-end with the rest of the services created by ROO.

Thanks
J

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我是有多爱你 2024-10-18 13:22:45

查看模型、视图、演示者模式 - 它解决了
这个问题。一般来说,所有非显示逻辑都应该被排除在外
您的观点,以便 1)非显示逻辑可以进行单元测试,而无需
在(实例化缓慢)浏览器中运行,并且 2)不同
显示器可以插入同一应用程序而无需重复
非显示逻辑。

这是一个 MVP 示例,展示了
您正在寻找的行为(请注意,样式稍微
不同于活动和活动地方实施)。

MyPresenter.java:

public class MyPresenter {
  public interface Display extends IsWidget {
    void setButtonClickHandler(ClickHandler buttonClickHandler);
  }

  private final Display display;
  private final EventBus eventBus;

  @Inject
  public MyPresenter(EventBus eventBus,
                     Display display)
  {
    this.display = display;
    this.eventBus = eventBus;

    bind();
  }

  private void bind() {
    display.setButtonClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        eventBus.fireEvent(new MyButtonClickedEvent());
      }
    });
  }

  public void go(HasWidgets container) {
    container.add(display.asWidget());
  }
}

MyView.ui.xml:

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
  xmlns:g='urn:import:com.google.gwt.user.client.ui'
  xmlns:ig='urn:import:com.ig.client.scaffold.ui.widget'>

  <g:Button ui:field="myButton"/>
</ui:UiBinder>

MyView.java

public class MyView extends Composite implements MyPresenter.Display {
  interface MyViewUiBinder extends UiBinder<Widget, MyView> {}
  private static MyViewUiBinder uiBinder = GWT.Create(MyViewUiBinder.class);

  private ClickHandler buttonClickHandler = null;

  public MyView() {
    initWidget(uiBinder.createAndBindUi(this));
  }

  @UiHandler("myButton")
  void onButtonClick(ClickEvent event) {
    if (buttonClickHandler != null) {
      buttonClickHandler.onClick(event);
    }
  }

  @Override
  public void setButtonClickHandler(ClickHandler buttonClickHandler) {
    this.buttonClickHandler = buttonClickHandler;
  }
}

在你的 GIN 模块中: bind(MyPresenter.Display.class).to(MyView.class);

Check out the Model, View, Presenter pattern - it solves
this problem. Generally all non-display logic should be kept out
of your views so that 1) the non-display logic can be unit tested without
running inside a (slow to instantiate) browser and 2) different
displays can be plugged into the same application without duplicating
the non-display logic.

Here's an MVP example exhibiting the
behavior you're looking for (note that the style is slightly
different than the Activities & Places implementation).

MyPresenter.java:

public class MyPresenter {
  public interface Display extends IsWidget {
    void setButtonClickHandler(ClickHandler buttonClickHandler);
  }

  private final Display display;
  private final EventBus eventBus;

  @Inject
  public MyPresenter(EventBus eventBus,
                     Display display)
  {
    this.display = display;
    this.eventBus = eventBus;

    bind();
  }

  private void bind() {
    display.setButtonClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        eventBus.fireEvent(new MyButtonClickedEvent());
      }
    });
  }

  public void go(HasWidgets container) {
    container.add(display.asWidget());
  }
}

MyView.ui.xml:

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
  xmlns:g='urn:import:com.google.gwt.user.client.ui'
  xmlns:ig='urn:import:com.ig.client.scaffold.ui.widget'>

  <g:Button ui:field="myButton"/>
</ui:UiBinder>

MyView.java

public class MyView extends Composite implements MyPresenter.Display {
  interface MyViewUiBinder extends UiBinder<Widget, MyView> {}
  private static MyViewUiBinder uiBinder = GWT.Create(MyViewUiBinder.class);

  private ClickHandler buttonClickHandler = null;

  public MyView() {
    initWidget(uiBinder.createAndBindUi(this));
  }

  @UiHandler("myButton")
  void onButtonClick(ClickEvent event) {
    if (buttonClickHandler != null) {
      buttonClickHandler.onClick(event);
    }
  }

  @Override
  public void setButtonClickHandler(ClickHandler buttonClickHandler) {
    this.buttonClickHandler = buttonClickHandler;
  }
}

And in your GIN module: bind(MyPresenter.Display.class).to(MyView.class);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文