Git Product home page Git Product logo

gwteventbinder's Introduction

What is EventBinder?

GWT's EventBus is great - it allows you to write maintainable GWT applications by decoupling the components of your application, making them easy to add, modify, or remove. However, using EventBus in GWT can require a lot of boilerplate in the form of implementing events, defining handler interfaces for them, and implementing those interfaces all over your code in anonymous classes. EventBinder automates away these boring details using a strategy similar to the @UiHandler annotation defined by UiBinder.

How do I use it?

Easy - just define your event, register handler methods for it, and then fire it.

Defining events

With EventBinder, events are just immutable value types extending GenericEvent. If your event doesn't have any arguments, defining it only takes one line:

public class SaveClickedEvent extends GenericEvent {}

To create an event with arguments, just create a normal Java value type:

public class EmailLoadedEvent extends GenericEvent {
  private final String subject;
  private final String body;

  public EmailLoadedEvent(String subject, String body) {
    this.subject = subject;
    this.body = body;
  }

  public String getSubject() { return subject; }
  public String getBody() { return body; }
}

That's it - no need to implement getAssociatedType or dispatch from GwtEvent or to define handler interfaces.

Registering event handlers

Event handlers are methods annotated with the @EventHandler annotation. It works the same way as @UiHandler - the name of the method is ignored, and the argument to the method is checked to determine what type of event to handle. In order to get this to work, you must also define an EventBinder interface and invoke bindEventHandlers on it in the same way you would for a UiBinder. Here's an example:

class EmailPresenter {
  interface MyEventBinder extends EventBinder<EmailPresenter> {}
  private final MyEventBinder eventBinder = GWT.create(MyEventBinder.class);

  EmailPresenter(EventBus eventBus) {
    eventBinder.bindEventHandlers(this, eventBus);
  }

  @EventHandler
  void onEmailLoaded(EmailLoadedEvent event) {
    view.setSubject(email.getSubject());
    view.setBody(email.getBody());
  }
}

After bindEventHandlers is called, onEmailLoaded will be invoked whenever an EmailLoadedEvent is fired on the given event bus.

It's possible to handle several events in one method. In this case you must enumerate these event classes in handles property of @EventHandler annotation and event parameter must be a superclass for all of these events. Also if handles is specified and you don't need event parameter you may omit it.

class SuperEvent extends GenericEvent { }

class EventOne extends SuperEvent { }

class EventTwo extends SuperEvent { }

class FormPresenter {
  interface MyEventBinder extends EventBinder<FormPresenter> {}
  private final MyEventBinder eventBinder = GWT.create(MyEventBinder.class);

  FormPresenter(EventBus eventBus) {
    eventBinder.bindEventHandlers(this, eventBus);
  }

  @EventHandler
  void onEventOne(EventOne event) {
    // handler for EventOne
  }

  @EventHandler(handles = {EventOne.class, EventTwo.class})
  void onEventOneAndTwo(SuperEvent event) {
    // handler for EventOne and EventTwo
  }

  @EventHandler(handles = {EventOne.class, EventTwo.class})
  void onEventOneAndTwo2() {
    // handler for EventOne and EventTwo without parameter
  }
}

Firing events

The last step is easy and doesn't require anything special from EventBinder - just construct an event and fire it on the event bus:

eventBus.fireEvent(new EmailLoadedEvent("Hello world!", "How are you?"));

Firing this event will cause all @EventHandlers for EmailLoadedEvent in the application to be invoked in an undefined order. That's it, you're done!

How do I install it?

If you're using Maven, you can add the following to your <dependencies> section:

    <dependency>
      <groupId>com.google.gwt.eventbinder</groupId>
      <artifactId>eventbinder</artifactId>
      <version>1.1.0</version>
    </dependency>

You can also download the jar directly or check out the source using git from https://github.com/google/eventbinder.git and build it yourself. Once you've installed EventBinder, be sure to inherit the module in your .gwt.xml file like this:

    <inherits name='com.google.web.bindery.event.EventBinder'/>

Where can I learn more?

  • For more details on the EventBinder API, consult the Javadoc.
  • Check out the sample app for a full example of using EventBinder.
  • For general advice on architecting GWT applications, see this video and this document

Version history

1.1.0

  • Ability to handle multiple events with a single handler mehtod (thanks to @ymakhno)

1.0.2

  • Compatibility with GWT 2.6 (thanks to @tbroyer).

1.0.1

  • Preliminary compatibility with GWT 2.6.
  • EventBinder now searches for @EventHandler annotation in superclasses as well as the current class.

1.0.0

  • Initial release.

gwteventbinder's People

Contributors

64bitasura avatar ekuefler avatar gkdn avatar tbroyer avatar ymakhno avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gwteventbinder's Issues

Missing EventBinder.gwt.xml

Hi,

The documentation states in the client project's .gwt.xml one should add

In the git checkout there is no such file. There is only module.gwt.xml
If I copy this to the proper location the compile runs fine.

cd gwteventbinder/
cp eventbinder/src/main/module.gwt.xml eventbinder/src/main/java/com/google/web/bindery/event/EventBinder.gwt.xml

Am I missing something?

EventBinder module definition is incompatible with separate compilation landed on GWT trunk

Separate compilation is used to speed up SuperDevMode. It compiles each module on its own and fails on EventBinder.gwt.xml because it only inherits com.google.web.bindery.event.Event but uses classes from com.google.gwt.event.EventBase, e.g. class GwtEvent.

To fix that I locally changed EventBinder.gwt.xml to inherit com.google.gwt.event.EventBase. This seems to work although I am not sure if it wouldn't be better to inherit com.google.gwt.user.User instead.

However after doing so, separate compilation complains that the interface com.google.web.bindery.event.shared.binder.EventBinder is provided by two modules: com.google.web.bindery.event.EventBinder and com.google.gwt.user.User. That's probably because gwteventbinder has reused the shared package already provided by com.google.web.bindery.event.Event. Separate compilation requires that each compilation unit is unique to a single GWT module so I think to fix that problem gwteventbinder classes must be moved to its own package.

You can reproduce the issue by creating a sample application using gwt trunk and gwteventbinder. Then start SuperDevMode using -Xincremental.

GWT 2.6.0-rc1 : com.google.gwt.dev.util.Preconditions removed

When I try to compile my application with GWT 2.6.0-rc1, I get an error:

Caused by: java.lang.NoClassDefFoundError: com/google/gwt/dev/util/Preconditions
at com.google.web.bindery.event.gwt.rebind.binder.EventBinderGenerator.getTargetType(EventBinderGenerator.java:73)

which is because the Preconditions class has been removed from GWT. It's also a problem for GIN according to:
https://code.google.com/p/google-web-toolkit/issues/detail?id=8433
https://groups.google.com/forum/#!topic/Google-Web-Toolkit/O3YYBYkO8t0

Activity and Presenter should be in same class or in the same package

Is it possible to use fully qualified name for ContactsPresenter or add import to generated file:
com.google.web.bindery.event.shared.binder.impl.AbstractEventBinder

I want to keep my presenter fully independent from GWT so i don't want to keep AppEventBinder interface in ContactsPresenter

interface AppEventBinder extends EventBinder<ContactsPresenter> {}

Generated ContactsActivity_AppEventBinderImpl:

package test.client.activity;

import com.google.web.bindery.event.shared.binder.EventBinder;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.binder.GenericEvent;
import com.google.web.bindery.event.shared.binder.impl.GenericEventHandler;
import com.google.web.bindery.event.shared.HandlerRegistration;
import java.util.LinkedList;
import java.util.List;

public class ContactsActivity_AppEventBinderImpl extends com.google.web.bindery.event.shared.binder.impl.AbstractEventBinder<ContactsPresenter> implements ContactsActivity.AppEventBinder {
  protected List<HandlerRegistration> doBindEventHandlers(final test.client.presenter.ContactsPresenter target, EventBus eventBus) {
    List<HandlerRegistration> registrations = new LinkedList<HandlerRegistration>();
    bind(eventBus, registrations, test.client.event.PersonDeletedEvent.class, new GenericEventHandler() {
      public void handleEvent(GenericEvent event) { target.onPersonLoader((test.client.event.PersonDeletedEvent) event); }
    });
    return registrations;
  }
}

thanks

Eventbinding in abstract classes.

Hello,

we successfully used the EventBinder in our project. All worked well but we have discovered one disadvantage.
Currently we cannot define a EventHandler in abstract classes which will be extended by our concrete presenter implementations.
This is very awkward.
Our current workaround for this is that we bind the event, which should be normally handled by the abstract class, in our extending presenter implementations and from there we call a method from the abstract class to handle/work with the events context.

Is it possible to bind the event handler methods in the abstract classes after all or do we have to work with our workaround?

With best regards
Marco

GWT dependencies have wrong dependency scope?

Hi,
it seems the current POM forces the 2.6.0 version of GWT when using gwteventbinder, even if the project using this library provides a newer version of GWT (for example, 2.6.1).

I'm no expert on maven (on the contrary), but from what I've seen in other projects (and the Maven docs) the solution is to declare the dependency of those gwt-* dependencies as provided:

<dependency>
  <groupId>com.google.gwt</groupId>
  <artifactId>gwt-dev</artifactId>
  <version>2.6.0</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>com.google.gwt</groupId>
  <artifactId>gwt-user</artifactId>
  <version>2.6.0</version>
  <scope>provided</scope>
</dependency>

Is GWT 2.7 supported?

Just looked through the release notes. Looks like in V1.0.2 added support for GWT 2.6. I didn't see any mention of GWT 2.7.

Does this currently support GWT 2.7?

Thanks,
Jake

Update to GWT 2.6

I think an update of gwt's dependency versions should be the only change...
Thanks

transitive dependency on GWT 2.6.0

There is a transitive dependency on (gwt-user-2.6.0) GWT 2.6.0 when using GRADLE/MAVEN.

workaround:

gwt ('com.google.gwt.eventbinder:eventbinder:1.1.0') {
exclude module: 'gwt-user'
}

Error compiling on gwt 2.6.0-rc1

[INFO] Caused by: java.lang.NoClassDefFoundError: com/google/gwt/dev/util/Preconditions
[INFO]  at com.google.web.bindery.event.gwt.rebind.binder.EventBinderGenerator.getTargetType(EventBinderGenerator.java:73)
[INFO]  at com.google.web.bindery.event.gwt.rebind.binder.EventBinderGenerator.generate(EventBinderGenerator.java:55)
[INFO]  at com.google.gwt.core.ext.IncrementalGenerator.generateNonIncrementally(IncrementalGenerator.java:40)
[INFO]  at com.google.gwt.dev.javac.StandardGeneratorContext.runGeneratorIncrementally(StandardGeneratorContext.java:676)
[INFO]  at com.google.gwt.dev.cfg.RuleGenerateWith.realize(RuleGenerateWith.java:41)
[INFO]  at com.google.gwt.dev.shell.StandardRebindOracle$Rebinder.rebind(StandardRebindOracle.java:79)
[INFO]  at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:276)
[INFO]  at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:265)
[INFO]  at com.google.gwt.dev.DistillerRebindPermutationOracle.getAllPossibleRebindAnswers(DistillerRebindPermutationOracle.java:91)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.handleGwtCreate(UnifyAst.java:387)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.handleMagicMethodCall(UnifyAst.java:465)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.endVisit(UnifyAst.java:255)
[INFO]  at com.google.gwt.dev.jjs.ast.JMethodCall.traverse(JMethodCall.java:244)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
[INFO]  ... 48 more
[INFO] Caused by: java.lang.ClassNotFoundException: com.google.gwt.dev.util.Preconditions
[INFO]  at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
[INFO]  at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
[INFO]  at java.security.AccessController.doPrivileged(Native Method)
[INFO]  at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
[INFO]  at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
[INFO]  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
[INFO]  at java.lang.ClassLoader.loadClass(ClassLoader.java:358)

Because Preconditions class is removed in GWT 2.6
GIN already has fix for this in trunk.

Compilation from master failed.

Internal error in the plugin manager executing goal 'net.ltgt.gwt.maven:gwt-maven-plugin:1.0-alpha-2:generate-module': Unable to load the mojo 'net.ltgt.gwt.maven:gwt-maven-plugin:1.0-alpha-2:generate-module' in the plugin 'net.ltgt.gwt.maven:gwt-maven-plugin'. A required class is missing: org/codehaus/plexus/classworlds/realm/DuplicateRealmException
org.codehaus.plexus.classworlds.realm.DuplicateRealmException

@EventHandler for base abstract events

Hey there!

I've made some changes to support specifying an @eventhandler for a base, abstract event. The generator just generates an additional bind() call for each subtype (recursively).

This is really great for us because now we can cover entire "classes" of events with just one handler, rather than manually being forced to specify explicit @EventHandlers for each subtype.

Is this something y'all would be interested in? If so, I can tidy things up and send a pull request this week.

Allow unregistering of handlers on a per-event class basis

According to EventBinderTest, when presenter.handlerRegistration.removeHandler() is called, all handlers are unregistered, regardless of the event's type.

It would be awesome if one could unregister only handlers of a particular event type, e.g.: presenter.handlerRegistration.removeHandler(SecondEvent.class);

Would be nice if example had one instance of removing handlers

It would be nice if one of the examples showed a really simple example of using the HandlerRegistration to remove the handlers on PresentsWidgets.stop(). This is obviously part of the GwtEventBinder API, but isn't demonstrated in the examples.

Ps. I am loving EventBinder! It has saved me a ton of boilerplate. And yes, I figured out the removal of handlers just fine after a few minutes, but it would still be helpful to have in the samples.

Support generic events

It would be nice if generic events were supported. Right now generic events are dispatched based on their type erasure.

My workaround is to create a non-generic subclass and fire that.

Using @EventHandler in derivative classes

Halo,

Is it possible to declare the interface and the eventBinder to a base class and pick the handlers from a child class?

I know it works if I define the @eventhandler in Base and @OverRide in Child.

Is this possible?

public class Base {
interface MyEventBinder extends EventBinder {
}
protected final MyEventBinder eventBinder = GWT.create(MyEventBinder.class);
public Base() {
eventBinder.bindEventHandlers(this, event_bus);
}
}

public class Child extends Base {
@eventhandler
public void onSelectionChangeEvent(SelectionChangeEvent event) {
log.info("event: " + event);
}
}

It doesn't work for me. I suppose the generator magic must have limits.

Vassillis

Is there a way to restrict which classes can catch events?

I use a pattern where events can either only be fired from classes in the same package (constructor is package-private) or events can only be caught by classes in the same package (handler is package private)

This makes it really easy to reason about the program flow and I catch a lot of bugs with this pattern.

Without handlers is it possible to restrict which classes can catch events?

Example is not working

I am trying to use the same example and it fails with this error:

 [java]       [ERROR] Line 36: Rebind result 'MyEventBinder' must be a class

Here is a snippet of my code
public class MyPresenter implements MyInterface.Presenter {
...
public MyPresenter(MyView view) {
this.view = view;
}

interface MyEventBinder extends EventBinder<MyPresenter> {}
private static final MyEventBinder eventBinder = GWT.create(MyEventBinder.class);

...

}

How to use gwteventbinder with guice during unit test

This is not an issue but a question.
I've a GWT application that uses GIN and gwteventbinder.
I'm writing some unit tests in order to test the client logic so I'm mocking views and services.
In order to run tests faster I'm avoiding GWTTestCase implementation and trying to run the tests as pure Java. In the test env I'm using directly Guice instead of GIN.
Setting up the tests I've issues providing to Guice a binding for the EventBinders because in normal env this is managed by code generators in GWT.
Have you never faced with the problem?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.