Errai: The browser as a platform

Friday, November 30, 2012

Get ready for Errai 2.2

Today marks the first candidate release for Errai 2.2.0. With this release, we're delivering dozens of fixes and enhancements. If we had to choose the three most important changes, they would be: the new client-side Bus Lifecycle API, addition of state parameters to the Page Navigation framework, and the ability to nest bindable properties.

While you're reading this, why not kick off a compile of your existing Errai project against the new release?

Do it now! It only takes a couple of minutes to switch the version number in your pom.xml to 2.2.0.CR1. If you're not using Maven, grab the release bits from our download page.

Seriously! We'll wait right here for you!

Client-side Bus Lifecycle

We've had questions over the years about how to find out exactly what the client-side message bus is up to: is it connected to the server? Is it attempting to reconnect? Has it given up and gone offline? Although there were ways to infer some of this information in the past, we decided it was time to make all of this information available in one place, and to make some guarantees about the order that these state transitions will happen in.

The best way to dive into the new bus lifecycle API would be to check out the BusStatusWidget that we added to the bus-stress-test demo, but here's a quick teaser:

class BusStatusLogger implements BusLifecycleListener {

  @Override
  public void busAssociating(BusLifecycleEvent e) {
    GWT.log("Errai Bus trying to connect...");
  }

  @Override
  public void busOnline(BusLifecycleEvent e) {
    GWT.log("Errai Bus connected!");
  }

  @Override
  public void busOffline(BusLifecycleEvent e) {
    GWT.log("Errai Bus trying to connect...");
  }

  @Override
  public void busDisassociating(BusLifecycleEvent e) {
    GWT.log("Errai Bus going into local-only mode.");
  }
}

To attach such a listener to the bus, just do the following in client-side code:

ClientMessageBus bus = (ClientMessageBus) ErraiBus.get();
bus.addLifecycleListener(new BusStatusLogger());


Nested Bindable Properties

We got good feedback about the data binding module that we added in Errai 2.1, which lets you bind properties from your model objects to GWT widgets (actually, to anything that implements HasValue). As a refresher, imagine you have an Item class with name and department properties, and a Department class with a name property of its own:

@Bindable
public class Item {

  private String name;
  private Department department;

  public String getName() { return name; }
  public void setName(String name) { this.name = name; }

  public Department getDepartment() { return department}
  public void setDepartment(Department department) { this.department = department; }
}

@Bindable
public class Department {

  private String name;

  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
}

Then you can link the value of item.name to a TextBox like this (this annotation-driven approach is provided by Errai UI):

@Templated("#main")
public class ItemWidget extends Composite {
  @Inject private @AutoBound DataBinder<Item> itemBinder;
  @Inject private @Bound @DataField TextBox name;
}

This is great, but what about the department name? We want a TextBox for that too! It became apparent pretty quickly that this feature would be way better if you could dig into the object graph and bind to nested properties, the data binding feature would cover a lot more use cases. Now you can:

@Templated
public class ItemWidget extends Composite {
  @Inject private @AutoBound DataBinder<Item> itemBinder;
  @Inject private @Bound @DataField TextBox name;
  @Inject private @Bound(property="department.name") @DataField TextBox department;
}

That's it! The name of the Department object nested inside item will be kept in sync with the contents of the department textbox.

State Parameters in Page Navigation

The last big enhancement we want to call out is the addition of extra parameters to the page navigation framework. Following from the previous example, say your ItemWidget is also a @Page:

@Templated @Page("item")
public class ItemWidget extends Composite {

  @Inject private @AutoBound DataBinder<Item> itemBinder;
  @Inject private @Bound @DataField TextBox name;
  @Inject private @Bound(property="department.name"@DataField TextBox department;

}


That's great: you can bookmark that you were at http://myapp.mycompany.com/#item. But which item were you looking at? That's important!

Now you can do this:

@Templated @Page("item")
public class ItemWidget extends Composite {

  @Inject private @AutoBound DataBinder<Item> itemBinder;
  @Inject private @Bound @DataField TextBox name;
  @Inject private @Bound(property="department.name"@DataField TextBox department;

  @PageState private int itemId;

  @PageShowing
  private void setupItem() {
    itemBinder.setModel(findItem(itemId));
  }

}

And presto! Your bookmarkable URL is now http://myapp.mycompany.com/#item;itemId=42.

We hope to enhance the navigation framework even more in Errai 3.0. Your input has been invaluable so far. Keep it coming!



On top of the three headliners, 2.2.0 CR1 includes 17 bug fixes and 10 enhancements/features across virtually every part of the framework. See the release notes for full details.

Once again, I urge you to try your project against Errai 2.2.0.CR1 today! We truly believe this is the best and most stable release to date, so you have nothing to lose. And in the unlikely event that you do find a new issue, you'll be able to tell us before 2.2.0 goes final.

Happy coding,
The Errai Team

Friday, November 16, 2012

The Future is Asynchronous!

For the last month or so, I've been hiding in a cave working on a big, upcoming feature in Errai 3.0. Which may sound crazy considering that we have yet to release 2.2 yet. But that's how I roll.

Well, it's more that this is a big feature, and we've feature-frozen Errai 2.2 on its path to productization as part of JBoss's WFK product, of which Errai will be a featured framework next year. So, big new features are bound for 3.0.

So what is this new feature? It is nothing other than the new asynchronous bean manager for Errai IOC/CDI! If you follow me on Twitter (@JBossMike) or on Google+, then you might have stumbled upon the highs and lows of my gargantuan effort to implement this.

First the big questions: what is asynchronous bean management, and why do we need it?

Asynchronous bean management may be an unfortunate term. Perhaps a more accurate name would be asynchronously-loading bean management. But I don't like how that sounds, so... the former it is!

The basic idea behind asynchronous bean management is the idea that the loading, construction and dependency-injectimification (yes, I made that word up) are done asynchronously. Obviously. But what does that mean?

It means that bean loading happens in parallel to your application logic -- the reason why this is desirable will be answered in the 'why' part.

In practice, you make a request to the bean manager for the instance of a bean, it goes and gets the bean (if it's already in existence) or it makes a new instance and gives it to you. But the way it gives the bean to you is through a callback mechanism.

Let's take a look at this in practice:
That's a bit different than what one might be use to if you've used the old bean manager API, where you would instead do this:

The asynchronous version is quite a bit more code!

The difference is, with the asynchronous lookup, the anonymous class we defined -- CreationalCallback  -- is used to receive the bean once its been created by the bean manager. When this happens, the callback() method is called, passing an instance of the bean. You then do something with that bean. In this case, we call it's show() method which, displays the popup widget.

You could imagine this sort of thing getting really out of hand. But really, most direct calls to the bean manager in your app are probably quite rare, and probably something you may already be abstracting away behind say, an Activity and Places pattern -- in which case, this extra code overhead is negligible.

But here's the real question: why?

The answer is: code-splitting!

One of the really cool features of GWT is its ability to partition your code behind runAsync() calls. This means, that as your app grows, you may find that the upfront loading time becomes undesirably long; wouldn't it be nice if the actual code needed was downloaded on-demand, based on the parts of the application which the user is actually using? Well, that's what GWT's code-splitting does!

The problem with synchronous bean loading, is it short-circuits your ability to use GWT's code-splitting effectively if your app is built completely around CDI. This is because Errai emits synchronously executing bootstrapping code to wire you application.

The asynchronous bean manager instead makes all the mechanics of the bean manager internally and externally (as shown above) based completely on a callback pattern. Meaning, quite simply, any aspect of bean management can now be contained in a GWT runAsync() callback. Yay!

Taking our example above as a scenario to contemplate: it may be that we have indicated that the class Popup is a bean we'd like to code-split. Errai 3.0 will allow you to do this by annotating that bean with the @LoadAsync annotation. This means, that all of the code of Popup -- assuming it does not have code paths to and from parts of your app that are needed in the initial application download --  can be segmented into a separate JavaScript payload. So, when we make our asynchronous lookup of this bean for the first time, we are able to download the JavaScript code, create the bean, and pass the loaded bean to you when it's ready!

You might decide, for the size of you app, that you don't need this functionality. Which is fine. We will be retaining both implementations of the bean manager -- the old one is not being deprecated. The caveat is only this: your app will be required to use one or the other. You cannot mix synchronous and asynchronous bean management within a single Errai app. Trust me: it's not possible or practical.

In closing, this is just one of the new amazing features coming in 3.0 which will allow you to take maximum advantage of GWT's performance-optimizing capabilities when using Errai.

I'm hoping to have something people can play with in the coming days. Stay tuned!