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!

2 comments:

  1. I'm curious whether you've approached the Google GWT team members about integrating at least some of this functionality directly into GWT?

    ReplyDelete