Errai: The browser as a platform

Saturday, March 24, 2012

Errai IOC: DI in the Browser (Part 1)

A central facet of the Errai programming model is the use of dependency injection (DI). The preferred programming model is a subset of the JSR-299 Context and Dependency Injection specification.

This is not the only DI solution for GWT. Gin is clearly the popular choice among GWT developers. But there are a few reasons you might want to consider looking into Errai as a good choice for doing dependency injection in your client code.

As we have gravitated towards standardizing around CDI, we have thus moved towards more container-oriented applications. Whereas, the Gin/Guice model aims to do absolutely no magic, we aim to at least give you a sprinkle of fairy dust to help eliminate boilerplate and help make your application more modular.

The first evidence of just a little bit of fairy dust occurs when you create your first GWT EntryPoint in Errai.

@EntryPoint
public class MyErraiEntryPoint {
   // class body here.
}

This is a little bit different than you may be used to with a GWT project -- instead of actually implementing the GWT EntryPoint interface, we have annotated a normal bean as our entry point bean.

The only thing that was necessary to accomplish this, was to have Errai IOC added as a module in our GWT project.

The cool thing is, MyErraiEntryPoint is a fully managed bean. We can inject other beans into it, and we can do lifecycle events like @PostConstruct on it.  Let's update our example:
@EntryPoint
public class MyErraiEntryPoint {
  @PostConstruct
  public void sayHello() {
    Window.alert("Hello, there!");
  }
}

We added an arbitrarily named method sayHello() to our class and added a @PostConstruct annotation.

@PostConstruct is a standard lifecycle annotation which is part of the javax.annotation.* package. It is supported in EJBs, CDI Beans, and by Errai IOC, naturally.  Its contract guarantees that the container will call the method before the bean is put into production, and only after all dependency injection tasks have been satisfied.

Thus, it provides a good way of doing things that need to be done at the startup of your application after the container has wired all the beans.

Errai goes a little bit further, building on the @PostConstruct idea, and adding a similar but distinct lifecycle annotation known as @AfterInitialization, for which there is no real analogue in CDI proper. In the case of @AfterInitialization calls, the method is guaranteed to be called only after all framework extensions (the message bus, RPC services, etc) have entered a ready state.

It turns out this is necessary, since the asynchronous nature of JavaScript in the browser means that your application will almost always finish wiring itself up before fancy things like WebSockets have been negotiated and are ready to start receiving messages.

So if right out of the gate we need to talk to the server, we can modify our bean again:

@EntryPoint
public class MyErraiEntryPoint {
  @Inject MessageBus bus;
  @AfterInitialization
  public void sayHelloToServer() {
    MessageBuilder.createMessage()
      .toSubject("ServerService")
      .command("SayHello")
      .done().sendNowWith(bus);
  }
}

So we've built an entire application that loads, and the first thing that happens is it sends a message to the server over the ErraiBus. That doesn't seem like much. But the only boilerplate code we've written are annotations.

This nice, concise, programming model is all made possible by the use of dependency injection and all the services built around the container.

But this is just scratching the surface. In the next part of this series we'll explore working with producers and dependent scoped beans!

Friday, March 16, 2012

Errai Marshalling and the Builder Pattern

My previous post was about the Errai Marshalling framework and its facilities for working with immutable types. In that post, I laid out how to use Errai's @MapsTo annotation to create entity instances via a public constructor or—as is often advantageous—a public static factory method.

But as an entity class grows to accommodate a real-world-use-case, a third approach to creating instances of immutable types becomes more and more appealing: the builder pattern.

If you use the builder pattern exactly as laid out by Joshua Bloch, Errai's marshalling system will be unable to infer a property mapping for the entity's constructor:

import java.util.Date;
import org.jboss.errai.common.client.api.annotations.Portable;

@Portable
public final class OrientationSensorReading {

  private final Date observationTime;
  private final double x;
  private final double y;
  private final double z;

  // ERROR: Errai Marshalling does not know what to do with this constructor
  private OrientationSensorReading(Builder builder) {
    this.observationTime = new Date(builder.observationTime.getTime());
    this.x = builder.x;
    this.y = builder.y;
    this.z = builder.z;
  }

  public Date getObservationTime() { return new Date(observationTime.getTime()); }
  public double getX() { return x; }
  public double getY() { return y; }
  public double getZ() { return z; }

  public static class Builder {
    private Date observationTime = new Date();
    private double x;
    private double y;
    private double z;

    public Builder time(Date time) { this.observationTime = time; return this; }
    public Builder x(double x) { this.x = x; return this; }
    public Builder y(double y) { this.y = y; return this; }
    public Builder z(double z) { this.z = z; return this; }

    public OrientationSensorReading build() {
      return new OrientationSensorReading(this);
    }
  }
}

You could work around this issue by implementing a custom marshaller (these are explained in in the Errai reference guide). But that's a burden: it's extra, external code you have to revisit every time you add or remove a property on your entity type.

A better approach is to adopt a modified version of Bloch's builder pattern. Instead of giving the class a constructor that takes the Builder as its sole parameter, create one big constructor that takes every single property, each of which annotated with a @MapsTo annotation. This constructor does triple duty as the target of Builder.build(), the target of Errai's de-marshaller, and a place to hang directions for Errai's marshaller generator. Now you have the builder pattern, and you haven't given up the convenience of Errai's automatic marshaller generation:

import java.util.Date;
import org.jboss.errai.common.client.api.annotations.Portable;
import org.jboss.errai.marshalling.client.api.annotations.MapsTo;

@Portable
public final class OrientationSensorReading {

  private final Date observationTime;
  private final double x;
  private final double y;
  private final double z;

  public OrientationSensorReading(
      @MapsTo("observationTime") Date observationTime,
      @MapsTo("x") double x,
      @MapsTo("y") double y,
      @MapsTo("z") double z) {
    this.observationTime = new Date(observationTime.getTime());
    this.x = x;
    this.y = y;
    this.z = z;
  }

  public Date getObservationTime() { return new Date(observationTime.getTime()); }
  public double getX() { return x; }
  public double getY() { return y; }
  public double getZ() { return z; }

  public static class Builder {
    private Date observationTime = new Date();
    private double x;
    private double y;
    private double z;

    public Builder time(Date time) { this.observationTime = time; return this; }
    public Builder x(double x) { this.x = x; return this; }
    public Builder y(double y) { this.y = y; return this; }
    public Builder z(double z) { this.z = z; return this; }

    public OrientationSensorReading build() {
      return new OrientationSensorReading(observationTime, x, y, z);
    }
  }
}

Yes, it's a little bit more verbose than Bloch's approach. But the client code using the builder is identical, and the integrity of the immutable type is in no way compromised. And it's still all in the same file, and far less verbose than a handwritten custom marshaller.

Future Work

There's always room for improvement. In particular, I'd like the option of making the entity constructor (the one with the @MapsTo annotations) package private. This would enforce usage of the builder, which is less error prone than the constructor. That's why you went to the trouble of creating a builder in the first place, right? This is in our issue tracker as ERRAI-234.

Additionally, the contract of Errai's @Portable annotation is that all nested classes of a @Portable class are also portable. This means Errai will generate marshallers for your Builder subclasses. Although this is harmless in the above examples, it becomes a problem when your builders have mandatory fields expressed as constructor parameters. We're tracking this issue as ERRAI-233. The workaround for now is to include a public no-args constructor in any such Builders.

Tuesday, March 6, 2012

Large scale application development with GWT and Errai

Development teams collaborating on the same codebase are always faced with the challenge of keeping their source code maintainable as it evolves and grows over time. By choosing GWT to implement your web application you already gain the benefit of having IDE support for client-side code refactorings. This is a distinct advantage, but how should a GWT application be designed to allow for the collaboration of large teams and stay maintainable over the course of time?

The Model-View-Presenter (MVP) pattern provides an answer to this. Applying the MVP pattern in GWT applications is described in this two-part article: Large scale application development and MVP

In this post, I will demonstrate a modified version of the example code of this article series to show how Errai makes implementing a MVP application in GWT even easier and how Errai helps to further decouple the individual components. The source code of the modified example can be found on GitHub: https://github.com/csadilek/errai-mvp-demo

So, let's take a look at the individual components used in MVP and the modifications and improvements made to it using Errai.

The Model

The business objects used in this example (Contact and ContactDetail) remain more or less unchanged. The @Portable annotation was added to mark them as serializable by Errai. Errai marshalling was designed for maximum flexibility and to impose as few limitations to serializable classes as possible (see our documentation for details). The classes do not need to (but may of course) implement java.io.Serializable.

The View

The views contain only UI layout code. They have no knowledge of the model, other views, transitions and contain no application logic. Errai can improve view implementations by providing the ability to inject UiBinders.

 Without Errai:


public class EditContactView extends Composite implements EditContactPresenter.Display {  

  interface EditContactViewUiBinder extends UiBinder<Panel, EditContactView> {}
  private static EditContactViewUiBinder uiBinder =  
      GWT.create(EditContactViewUiBinder.class);

  ...
}

With Errai:


public class EditContactView extends Composite implements EditContactPresenter.Display {

  @Inject 
  UiBinder<Panel, EditContactView> uiBinder;

  ...
}

The Presenter

The presenters contain all the application logic: view transitions, RPCs, etc. In the original example, the RPC proxies, the event bus and the view instances are passed to the presenters as constructor arguments. Using Errai, we can now inject all these components.


@Dependent
public class EditContactPresenter implements Presenter {
  public interface Display {
    ...
  }

  @Inject
  private Caller<ContactsService> contactsService;

  @Inject
  private HandlerManager eventBus;

  @Inject
  private Display display;

  ...
}

This might seem like a minor improvement at first, but once your application grows this will become more than handy. Let's say you come to a point where all your presenters need an additional RPC proxy. Without dependency injection, you would have to change all constructors and all call sites!

The GWT/RPC proxy was replaced with an Errai RPC proxy (the injected Caller). Errai RPC does not require an asynchronous interface nor a servlet based service implementation on the server. It can even be used to invoke methods on a server-side CDI bean (see our documentation for details).

The Application Controller

The application controller handles logic that is not specific to any presenter and also deals with history management and view transitions. It needs access to the event bus (which again we can inject using Errai IOC) to react on application events that trigger view transitions.


@ApplicationScoped
public class AppController implements Presenter, ValueChangeHandler<String> {
  @Inject
  private HandlerManager eventBus;
  
  @Inject
  private IOCBeanManager manager;

  ...
}

It also needs to be able to create new presenter instances when the browser's history stack changes. To create new managed instances of presenters, we use Errai's client-side bean manager that will make sure all the injection points of presenters are satisfied and the instance is ready to use.


public void onValueChange(ValueChangeEvent<String> event) {
    String token = event.getValue();
    if (token != null) {
      Presenter presenter = null;

      if (token.equals("list")) {
        IOCBeanDef<ContactsPresenter> bean = manager.lookupBean(ContactsPresenter.class);
        if (bean != null) {
          presenter = bean.getInstance();
        }
      } else if (token.equals("add") || token.equals("edit")) {
        IOCBeanDef<EditContactPresenter> bean = 
            manager.lookupBean(EditContactPresenter.class);
        if (bean != null) {
          presenter = bean.getInstance();
        }
      }

      if (presenter != null) {
        presenter.go(container);
      }
    }
  }

The EntryPoint

Since Errai allows us to use dependency injection for all the required components, the main difference here is that we no longer have to pass the RPC proxies and the event bus instance to the app controller which in turn would have to forward it to the presenters and views.

The @Produces method provides the event bus instance to all the event bus injection points in all the presenters. The application controller itself is also just injected and started as soon as the app is finished initializing (@AfterInitialization).


@EntryPoint
public class Contacts {

  private HandlerManager eventBus = new HandlerManager(null);

  @Inject
  private AppController appController;

  @AfterInitialization
  public void startApp() {
    appController.go(RootPanel.get());
  }

  @Produces
  private HandlerManager produceEventBus() {
    return eventBus;
  }
}

So to sum it up, Errai's IOC container helps implementing the MVP pattern by further decoupling the individual components and by alleviating boilerplate code for UiBinders and RPC proxies.

Future Work 

An extension that we are currently working on is the @MockFor annotation that can be used to replace an injected type with a mocked type for unit testing. During tests, a presenter could then get the mocked view injected in place for the actual view for example. The presenters can then be tested using a plain JUnit test instead of an integration test.

@MockFor(EditContactsView.class)
public class EditContactsMockView implements EditContactPresenter.Display { 
  ...
}

As always, feedback is welcome and appreciated!

Friday, March 2, 2012

Marshalling in Errai 2.0: Dealing with the Edge Case

Dovetailing off the last post on marshalling, lovingly laid out by Jonathan, I'd like to talk about dealing with edge cases in Errai 2.0's marshalling framework.

The real question is: what do you do when the annotations are not enough? What if I have to marshal a legacy class that isn't very bean-like.

Well, it turns out, we ran into these problems ourselves when implementing the default JRE marshallers. There are some classes which don't exactly lend themselves to just being slurped up into a reflection analyzer and having marshalling code emitted. And even if they did, they'd create very inefficient marshallers.

There are a grand total of two ways to deal with this problem when you come to it. The first solution is to try and manually describe the model to Errai. The second solution is just to write your own marshaller by hand. Let's look at the former approach today!

Teaching Errai about Your Model

This approach has the advantage of not requiring that you manually deal with building up and parsing wire protocol stuff. Instead, we give Errai a picture of what it should do to build the object through a series of mapping instructions.

A perfect example is the java.lang.Throwable class. Marshalling this class provides a few special challenges. For instance, to construct it with a message we must do so in a constructor argument. To chain a cause to it, we must call initCause(), and so on. Thus, Errai Marshalling's class analyzer is not going to do a very good job at comprehending the class. Instead, we will implement a MappingDefinition to describe the mappings needed to build and deconstruct a Throwable.

The first thing we do is create a class which extends org.jboss.errai.marshalling.rebind.api.model.MappingDefinition. This is a base class which contains the model of the mapping.

@CustomMapping
public class ThrowableDefinition extends MappingDefinition {
  public ThrowableDefinition() {
    super(Throwable.class);

    SimpleConstructorMapping constructorMapping = new SimpleConstructorMapping();
    constructorMapping.mapParmToIndex("message", 0, String.class);
    setInstantiationMapping(constructorMapping);
    addMemberMapping(new WriteMapping("cause", Throwable.class, "initCause"));

    addMemberMapping(new AccessorMapping("stackTrace", StackTraceElement[].class, "setStackTrace", "getStackTrace"));

    addMemberMapping(new ReadMapping("message", String.class, "getMessage"));
    addMemberMapping(new ReadMapping("cause", Throwable.class, "getCause"));
  }
}

Let's go through this line-by-line to see what's going on here.

super(Throwable.class);

We call the super constructor, passing the the class reference for Throwable. This configures the MappingDefinition to associate your mappings with this class.

SimpleConstructorMapping constructorMapping = new SimpleConstructorMapping();

We instantiate a org.jboss.errai.marshalling.rebind.api.model.impl.SimpleConstructorMapping to represent the constructor that will need to be called to instantiate the Throwable.

constructorMapping.mapParmToIndex("message", 0, String.class);

We map the message field of the class to the first argument (index: 0) of the constructor, and specify that is of type java.lang.String.

setInstantiationMapping(constructorMapping);

We call MappingDefinition.setInstantiationMapping() (it's in the super class), to record that this constructor mapping is needed to instantiate the class.

addMemberMapping(new WriteMapping("cause", Throwable.class, "initCause"));

We add a member mapping for the cause field of Throwable. In this case we specify a WriteMapping, which implies a method which accepts exactly one argument. In this case, another Throwable. The method we want is initCause.

addMemberMapping(new AccessorMapping("stackTrace", StackTraceElement[].class, "setStackTrace", "getStackTrace"));

For the stackTrace field, we utilize the AccessorMapping, which is a convenient two-way mapping where we have symmetric getters and setters. In this case, setStackTrace() and getStackTrace().

addMemberMapping(new ReadMapping("message", String.class, "getMessage"));

This time we specify a ReadMapping. Which like its namesake, tells the marshalling framework how to read a field. In this particular case, we map the message field, to the getMessage method. The ReadMapping expects the method to return the specific type (in this case String), and accept exactly zero arguments.

addMemberMapping(new ReadMapping("cause", Throwable.class, "getCause"));

Like with message, we do the same for cause. And guess what? We've told Errai everything it needs to know about marshalling this class. In fact, since many other classes extend Throwable and have the exact same marshalling characteristics, we can place an additional annotation on our class to make this definition project across these types as well!

@InheritedMappings(IOException.class, IllegalArgumentException.class, /* and more...  */))

The use of the InheritedMappings annotation accomplishes the aliasing for us. And that's that! We've described to Errai how to marshal and demarshal Throwable class, and classes which inherit it!

The next in this series will look at writing your own custom marshaller from scratch.

Mike, out.