3

Trying to inject the eventbus into a component but I'm getting the "has no default (zero args) constructor." error. Any clues what I'm doing wrong? Very new to GIN, so it might be trivial..

Here is my code:

module:

public class MyWidgetClientModule extends AbstractGinModule { 
    protected void configure() { 
        bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class); 
    } 
} 

injector:

@GinModules(MyWidgetClientModule.class) 
public interface MyWidgetGinjector extends Ginjector { 

} 

and the component I trying to inject:

public class I18NLabel extends Label implements ChangeLanguageEventHandler{ 

  private final SimpleEventBus eventBus; 
    private String key; 

    @Inject 
    public I18NLabel(SimpleEventBus eventBus) { 
        this.eventBus = eventBus; 
    } 
... 

It gives me this error log:

00:00:45.767  [DEBUG] Rebinding com.test.fdc.gui.gwt.client.customer.CustomerDetailView.Binder
00:00:45.767  [DEBUG] Invoking generator com.google.gwt.uibinder.rebind.UiBinderGenerator
00:00:45.767  [ERROR] com.test.fdc.gui.gwt.client.content.i18n.I18NLabel has no default (zero args) constructor. To fix this, you can define a @UiFactory method on the UiBinder's owner, or annotate a constructor of I18NLabel with @UiConstructor.
00:00:45.767  [ERROR] Deferred binding failed for 'com.test.fdc.gui.gwt.client.customer.CustomerDetailView.Binder'; expect subsequent failures

00:00:45.767  [ERROR] Uncaught exception escaped
java.lang.ExceptionInInitializerError: null
    at com.test.fdc.gui.gwt.client.FDC$4.onSuccess(FDC.java:394)
    at com.test.fdc.gui.gwt.client.FDC$4.onSuccess(FDC.java:1)
    at com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.onResponseReceived(RequestCallbackAdapter.java:215)
    at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:287)
    at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:395)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:157)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:326)
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:207)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:126)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:562)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:214)
    at sun.reflect.GeneratedMethodAccessor22.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:157)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:281)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:531)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:352)
    at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.RuntimeException: Deferred binding failed for 'com.test.fdc.gui.gwt.client.customer.CustomerDetailView$Binder' (did you forget to inherit a required module?)
    at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:53)
    at com.google.gwt.core.client.GWT.create(GWT.java:97)
    at com.test.fdc.gui.gwt.client.customer.CustomerDetailView.(CustomerDetailView.java:34)
    at com.test.fdc.gui.gwt.client.FDC$4.onSuccess(FDC.java:394)
    at com.test.fdc.gui.gwt.client.FDC$4.onSuccess(FDC.java:1)
    at com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.onResponseReceived(RequestCallbackAdapter.java:215)
    at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:287)
    at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:395)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:157)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:326)
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:207)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:126)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:562)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:214)
    at sun.reflect.GeneratedMethodAccessor22.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:157)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:281)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:531)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:352)
    at java.lang.Thread.run(Thread.java:619)
Caused by: com.google.gwt.core.ext.UnableToCompleteException: (see previous log entries)
    at com.google.gwt.dev.shell.ModuleSpace.rebind(ModuleSpace.java:596)
    at com.google.gwt.dev.shell.ModuleSpace.rebindAndCreate(ModuleSpace.java:456)
    at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:49)
    at com.google.gwt.core.client.GWT.create(GWT.java:97)
    at com.test.fdc.gui.gwt.client.customer.CustomerDetailView.(CustomerDetailView.java:34)
    at com.test.fdc.gui.gwt.client.FDC$4.onSuccess(FDC.java:394)
    at com.test.fdc.gui.gwt.client.FDC$4.onSuccess(FDC.java:1)
    at com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.onResponseReceived(RequestCallbackAdapter.java:215)
    at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:287)
    at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:395)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:157)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:326)
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:207)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:126)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:562)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:214)
    at sun.reflect.GeneratedMethodAccessor22.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:157)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:281)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:531)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:352)
    at java.lang.Thread.run(Thread.java:619)
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Andreas Blomqvist
  • 437
  • 1
  • 9
  • 22

3 Answers3

3

When you declare a widget in a UiBinder, GWT tries to instantiate it with the default zero-arg constructor. Since your new Widget doesn't have a no-arg constructor, the UiBinder methods fail.

You can look into the @UiConstructor and @UiField(provided=true) annotations, but neither will give you a very elegant solution for this. You may be better off programmatically declaring your widget and inserting it into your layout in Java. If you do want to keep using the UiBinder, you can do something like

@UiField(provided=true)
protected I18NLabel theLabel;

public MyCompositeWidgetDefinedByUiBinder()
{
   theLabel = new I18NLabel(eventBusToInject);
   initWidget(uiBinder.createAndBindUI(this));
}

but there's no elegant way to inject an object through a UiBinder other than this.

Riley Lark
  • 20,660
  • 15
  • 80
  • 128
  • 2
    +1 True (although, this is *not* the only way to create a Widget without a zero-arg constructor via UiBinder - see [the good docs](http://code.google.com/webtoolkit/doc/latest/DevGuideUiBinder.html#Using_a_widget)) - this is why xworker should be using MVP to separate Views and Presenters - only the Presenter needs the Event Bus, the View doesn't (and can be easily instantiated by UiBinder). – Igor Klimer Nov 01 '10 at 21:34
  • Agreed - even if you don't like the other reasons to use MVP, you should understand that UiBinder is meant to be used as a tool for creating Views that don't know about event buses and other application-wide objects. UiBinder wants to create widgets that can be used in any project, with no other dependencies. – Riley Lark Nov 01 '10 at 22:18
  • Thanks all for the replies, will test them. Tried myself with the @constructor and the provided=true, but could get it to work.I feel that the full MVP design gives me too much code, therefor I only use parts of it. – Andreas Blomqvist Nov 02 '10 at 07:50
  • Let me explain what I'm trying to do, maybe I way off... I want to create a label that I can use on all my uibinding pages. The label has a property "messageKey" that gets a text from a hashmap with textkeys. So the label shows I18N content. the label has a setMetod that looks like this: public void setMessageKey(String key) { this.key=key; this.getElement().setInnerHTML(Storage.getSessionStorage().getItem(key)); } works very well, but I want to refresh every lable if the user change language, therefor the I need the eventbus to catch changeLangEvent – Andreas Blomqvist Nov 02 '10 at 08:13
  • 1
    You're talking about i18n support in UiBinder? You can do the following: . That does set the text attribute of the label to the property defined by the given key. I'd suggest you use the existing i18n support instead of your own. See http://code.google.com/webtoolkit/doc/latest/DevGuideUiBinderI18n.html for more information or just ask. – z00bs Nov 02 '10 at 08:36
2

Probably a bit late on this one but you were injecting the implementation as opposed to the interface. Try just injecting EventBus instead of SimpleEventBus. GIN will know to use the right one because you bound it in your module.

sth
  • 222,467
  • 53
  • 283
  • 367
Aigeec
  • 21
  • 1
1

I assume your SimpleEventBus does not have a zero-arg constructor? So Gin can not instatiate it because it does not know how (which args to use).

In this case add this to MyWidgetClientModule:

// assuming you only need one event bus in whole app
// use appropriate "args.." 
private static final SimpleEventBus eventBus = new SimpleEventBus(args..);

@Provides
SimpleEventBus provideEventBus() {
    return eventBus;
}
Peter Knego
  • 79,991
  • 11
  • 123
  • 154
  • 1
    It does have zero arg constructor. SimpleEventBus eventBus = new SimpleEventBus(); – Andreas Blomqvist Nov 01 '10 at 17:03
  • Hi, sorry for the delay, heres the error log:00:00:45.767 [DEBUG] Rebinding com.test.fdc.gui.gwt.client.customer.CustomerDetailView.Binder 00:00:45.767 [DEBUG] Invoking generator com.google.gwt.uibinder.rebind.UiBinderGenerator 00:00:45.767 [ERROR] com.test.fdc.gui.gwt.client.content.i18n.I18NLabel has no default (zero args) constructor. To fix this, you can define a @UiFactory method on the UiBinder's owner, or annotate a constructor of I18NLabel with @UiConstructor. – Andreas Blomqvist Nov 02 '10 at 07:44
  • 00:00:45.767 [ERROR] Deferred binding failed for 'com.test.fdc.gui.gwt.client.customer.CustomerDetailView.Binder'; expect subsequent failures ¨00:00:45.767 [ERROR] Uncaught exception escaped
    java.lang.ExceptionInInitializerError: null
     at com.test.fdc.gui.gwt.client.FDC$4.onSuccess(FDC.java:394)
     at com.test.fdc.gui.gwt.client.FDC$4.onSuccess(FDC.java:1)
     at
    – Andreas Blomqvist Nov 02 '10 at 07:44
  • You have a problem with UIBinder, not with Gin (@Riley noted this in another answer). UIBinder expects I18NLabel to either have zero-arg constructor or to inject constructor or initialize component by hand:http://code.google.com/webtoolkit/doc/latest/DevGuideUiBinder.html#Using_a_widget – Peter Knego Nov 02 '10 at 08:17
  • The @factory solved it without GIN, but I was hopeing the GIN would eliminate the need for a @factory? – Andreas Blomqvist Nov 02 '10 at 09:40
  • It could if you used `@UiField(provided=true)` and injected via Gin. – Peter Knego Nov 02 '10 at 10:01
  • Thats what I was aiming for, but when I try this: public class I18NLabel extends Label implements ChangeLanguageEventHandler{ @UiField(provided=true) private final SimpleEventBus eventBus; private String key; @Inject @UiConstructor public I18NLabel(SimpleEventBus eventBus) { super(); this.eventBus = eventBus; eventBus.addHandler(ChangeLanguageEvent.getType(), this); it gives me: 00:00:35.205 [ERROR] missing required attribute(s): eventBus Element (:21) – Andreas Blomqvist Nov 02 '10 at 12:10
  • If I understand correctly, you have `CustomerDetailView` defined via uibinder XML that refers to `I18NLabel`, that you would like to instantiate via Gin? In this case UIBinder would have to call Gin to instantiate `I18NLabel` and I don't think this is possible. – Peter Knego Nov 02 '10 at 13:25
  • Yes, thats exactly the case. The CustomerDetailView.ui.xml has the following line: and I wanted GIN to inject the EventBus into the I18Label without have a specific @Factory. The whole point is that every I18NLabel should listen to events to be able to update itself when the user clicks a button to change language. Is there at better way to "repaint" the gui? – Andreas Blomqvist Nov 02 '10 at 15:08