Errai: The browser as a platform

Monday, July 19, 2010

Dependency Injection in the Browser!

One of the things that will be coming in Errai 1.1 is our new IOC module which provides a dependency injection framework, based on JSR-330 in the browser. Now, this is not just Gin packaged with Errai. Rather, it's an implementation which has been built specifically to intermix with Errai's code generation infrastructure and provide a boiler-plate free experience.

When we release 1.1, gone will be the days of having to access the bus or the dispatchers through static factories. Rather, your client-side code will look even more like your server-side code.

Check out our new HelloWorld example built atop our new DIfoundations.

@EntryPoint @Service
public class HelloWorld extends VerticalPanel implements MessageCallback
{
    private Button sayHello;
    private Label label;

    private MessageBus bus;

    @Inject
    public HelloWorld(MessageBus bus) {
        this.bus = bus;
    }

    public void callback(Message message) {
        label.setText(SimpleMessage.get(message));
    }

    @PostConstruct
    public void init() {
        sayHello = new Button("Say Hello!");

        /**
         * Register click handler.
         */

        sayHello.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                MessageBuilder.createMessage()
                        .toSubject("HelloWorldService")
                        .with(MessageParts.ReplyTo, "HelloWorld")
                        .done().sendNowWith(bus);
            }
        });

        label = new Label();

        add(sayHello);
        add(label);

        RootPanel.get().add(this);
    }
}


Notice use of the @EntryPoint annotation. When you use @EntryPoint you don't need to implement your own GWT EntryPoint class, we build that for you.

You're probably already wondering if you can provide your own arbitrary providers to inject custom services, widgets and other components. And the answer is yes. We've provided a simple Provider interface that you can annotate to be discovered by the container at compile time to provide an injectable dependency. In fact both MessageBus and RequestDispatcher plug-in using this mechanism. Here's the provider for MessageBus:

@Provider
@Singleton
public class MessageBusProvider implements TypeProvider<MessageBus> {
    public MessageBus provide() {
        return ErraiBus.get();
    }
}


Pretty cool, huh? Doing more sophisticated things requires tying into the code generator which is used to generate the wiring code, and there will be documentation on how to do that. But the code generation interfaces will be surprisingly easy to use if you want to do anything particularly advanced, such as provide custom annotations for the container to process during the bootstrap process.

This is just one of the many cool features coming to Errai 1.1. Stay tuned for more!

6 comments:

  1. What about supporting producer methods from CDI rather than @Provider?

    ReplyDelete
  2. Pete, I'm actually looking into that, as a matter of fact. The use of @Provider here is sort of a container-level configuration concept.

    When the container bootstraps at compile time, it scans for all type providers. These are like our boilerplate things, like MessageBus and RequestDispatcher. So perhaps my post is deceiving. It probably doesn't make sense to equate @Producer and @Provider. I will have to think about this more...

    ReplyDelete
  3. Also, one of the important parts of this baseline implementation is it's designed to be something we can build the JSR-299 stuff on top of. So we also have this other concept called a Decorator, which is a code-generation concept which is what a lot of our CDI stuff will be built on-top of.

    ReplyDelete
  4. Gotcha - that makes sense. BTW CDI also has a different concept called Decorator ;-)

    ReplyDelete
  5. Pete,

    Well, in that case, I should probably rename ours CodeDecorator. =)

    ReplyDelete