Errai: The browser as a platform

Tuesday, March 2, 2010

Errai 1.0!

I am pleased to announce our 1.0 Release of the Errai Framework. It rounds out the first stepping stone in our journey towards building a truly innovative way to build next-generation web applications.

I would like to thank the entire team for their hard work on this: Heiko Braun, Lillian Angel, Rodney Russ, and myself for contributing to getting us to this goal.

We'd especially like to thank our early adopters who helped us work out the kinks, report bugs, and make us aware of what the community needs.

Some of the important highlights and milestone of this release include:

- Async IO support in ErraiBus for Apache Tomcat, JBoss AS, and Jetty. As well as standard synchronous IO support for all servlet containers.
- Easy to use homogeneous programming model that permeates both the server and client.
- Initial public release of our Workspaces RAD console/app framework.

Version 1.1, which will be released in the coming weeks will add support for Glassfish, WebLogic and WebSphere.

We encourage anybody interested in contributing to contact us on our mailing lists. For more information on Errai, check our main project website here: http://www.jboss.org/errai

Friday, February 19, 2010

Mission Control: Prepare for landing

I am glad to announce that we've begun preparing the 1.0 release of Errai:
http://anonsvn.jboss.org/repos/errai/branches/errai-1.0.x/


(Image courtesey of
CBSNEWS)

We will add another round of QA during the next week and polish our documentation. If you are an early adopter, this would be a good time to tell us what problems you experience. So make sure to file your bugs and let us now through the mailing list.

Wednesday, February 17, 2010

Errai at the JUG Toronto @ 18.0.2010

Mike Brock will be presenting Errai at the Toronto Java User's Group on Thursday, February 18th at the Free Time Cafe (320 College St, Toronto). Details here.

Errai at the Java User Group Zurich, Switzerland

Heiko will be talking about Errai in Zurich at the 2.3.2010:

Patterns and Best Practices for building large GWT applications

In this presentation weʼll see how to organize a nontrivial GWT application. Weʼll go through the lessons learned in a real world project and take a look the complete development lifecycle and best practices that go beyond what GWT has to offer out-of-the-box. This talk does focus on modularity of GWT applications and how to overcome the burdens of compile-time linking. Weʼll talk about client side patterns and server side implementation options and explore different approaches that allow for quick turn around times without sacrificing maintainability.

Travel details can be found here:
http://www.jugs.ch/html/events.html

Tuesday, December 8, 2009

Integrating Errai with Weld (CDI), Part 1

While GWT is strong on the client side it doesn't provide any server side programming models. There is GWT RPC, but that's merely an integration layer. We've been discussing various options within the Errai team, looking for some best practice recommendations. In this article we'll look into CDI, which is part of the EE6 specification and offers a concise, easy to use programming model.

In the first part of this series, we'll focus on the CDI Event API and see how it integrates with Errai Bus.


Some knowledge about Errai Bus and GWT is recommended before reading any further. If you don't know about the Bus and it's purpose, then checkout the project page first.


Creating a CDI event consumer


To begin with, we'll create a simple CDI component that listens on paticular event types:

@ApplicationScoped
public class EchoService
{
@Inject
BeanManager beanManager;

public void echo(@Observes EchoRequest message)
{
String replyText = message.getMessageText() + " Response";

beanManager.fireEvent(
new EchoResponse(replyText),
new ErraiBusQualifier()
);
}

}


In this example the echo(...) operation will be invoked on any occurance of an event type EchoRequest. It will create an EchoResponse event type and dispatch it through the BeanManager.

A simple GWT client


Now that we've got our server side component implementation, it's time to look at the GWT client. The client component basically needs to do two things:


  1. Fire events that will ultimately invoke our server side component
  2. Listen to events that are send in response


Create an event producer
We keep it simple and fire event when a button is clicked:

Button b = new Button("Send", new ClickHandler()
{
public void onClick(ClickEvent clickEvent)
{
CommandMessage.create(WeldCommands.WELD_EVENT)
.toSubject("weldDispatcher")
.set(WeldProtocol.TYPE, EchoRequest.class.getName())
.set(WeldProtocol.OBJECT_REF,
new EchoRequest("Message from client"))
.sendNowWith(bus);
}
});


Register a listener for response messages:

MessageBus.subscribe("echoClient", // local endpoint
new MessageCallback()
{
public void callback(CommandMessage message)
{
[...]
}
}
);


In this case, we've create a listener that will receive messages that are send to the subject "echoClient".

Great, now we have a GWT event producer that sends messages through Errai Bus and we've created a CDI event consumer that listens on the internal CDI event subsystem. But how do we introduce them to each other?

Bridge between Errai Bus and the CDI Event Subsystem
If you carefully followed the example, you might have realized the event producer sends messages to a subject called "weldDispatcher". Actually this is an Errai server side service consuming messages send from a GWT client. That means any message put on the Bus that addresses this particular subject will be directed to a service that is registered to this subject:

@Service("weldDispatcher")
@ApplicationScoped
public class WeldDispatcher implements MessageCallback
{
[...]

// Invoked by Errai
public void callback(CommandMessage message)
{
try
{
switch (WeldCommands.valueOf(message.getCommandType()))
{
case WELD_EVENT:
String type =
message.get(String.class, WeldProtocol.TYPE);
Class clazz =
getClass().getClassLoader().loadClass(type);
Object o = message.get(clazz, WeldProtocol.OBJECT_REF);
beanManager.fireEvent(o);
break;
default:
throw new IllegalArgumentException(
"Unknown command type "+message.getCommandType()
);
}
}
catch (Exception e)
{
throw new RuntimeException(
"Failed to dispatch Weld Event", e
);
}
}

// Invoked by Weld Event producer
public void sendMessage(@Observes @ErraiBus Object message)
{
String subject = null;
ErraiBus busAnnotation =
message.getClass().getAnnotation(ErraiBus.class);
if(busAnnotation!=null)
subject = busAnnotation.subject();

assert subject!=null : "Missing subject declaration";

// put on the bus
CommandMessage.create(WeldCommands.WELD_EVENT)
.toSubject(subject)
.set(WeldProtocol.TYPE, message.getClass().getName())
.set(WeldProtocol.OBJECT_REF, message)
.sendNowWith(erraiBus);
}

[...]
}


What's happening here?

The WeldDispatcher implementation acts a bridge between the Errai Bus and the CDI event subsystem. It does listen on messages in both directions and fowards the event message to the corresponding subsystem: either Errai Bus or CDI.

Receiving messages send from the client
When a messages is send to the "weldDispatcher" subject the callback(CommandMessage message) operation will be invoked. It umarshalls the the event type and forwards it to CDI using the BeanManager API:


String type = message.get(String.class, WeldProtocol.TYPE);
Class clazz = getClass().getClassLoader().loadClass(type);
Object o = message.get(clazz, WeldProtocol.OBJECT_REF);
beanManager.fireEvent(o);


Forwarding events produced on the server side
The CDI component that we've shown in the beginning of this article, fires EchoResponse events in response to it's invocation. These events are caught by a CDI ObserverMethod (sendMessage(@Observes @ErraiBus Object message)) that extracts the recipient subject, creates an Errai message and put's it on the bus:

CommandMessage.create(WeldCommands.WELD_EVENT)
.toSubject(subject)
.set(WeldProtocol.TYPE, message.getClass().getName())
.set(WeldProtocol.OBJECT_REF, message)
.sendNowWith(erraiBus);


Wrap up


That's it for today. To sum up, here's what we've shown in this example:

  1. We've created a simple example that uses GWT on the client side.
  2. It does leverage Errai Bus for integrating with the server side
  3. We've used a CDI component on the server side to back our application
  4. All communication is done asynchronously, using a bridge between Errai Bus and the CDI event subsystem


Stay tuned. More articles on Errai and CDI integration are following.


Update
More recent examples can be found here:
http://anonsvn.jboss.org/repos/errai/projects/weld-integration/trunk/