See ya next year Google I/O !

It’s been an incredible trip to San Francisco. We arrived Saturday afternoon and spent some time visiting the city before Google I/O. For some of us, like myself, it was our first time in San Francisco and we were stunned by the beauty of the city! On Monday we attended the boot camp and it gave us a chance to meet early on with many great developers. We then attended a mini-summit at Google’s office where we had an opportunity to learn more about some of the coolest projects being built on GWT today. We also met with some of the core developers on GWT as well as some of the most influential members of the community and, guess what, it’s packed full of very friendly and very knowledgeable people. No wonder the open source GWT scene is so flourishing!

Then, on Tuesday, Google I/O proper began.  What an event! From the start the organization appeared flawless, even though the crowd was huge, all the details seemed right even. Well, ok, save for the WiFi… Day one started with the first keynote, where we learned about the future of Android and received the new Galaxy Tab 10.1. Following this, it was time for us to hit the session Philippe was giving together with David Chandler and Jeff Schnitzer. Wow, the room was packed and they even had to refuse some people at the door! I want to thank everyone one who attended Highlighly Productive GWT, as well as those of you who missed it but watched the YouTube version. After the sessions we met many users of GWT-Platform as well as a enthusiasts who wanted to give it a try. Tuesday’s after hours event was totally crazy, lots of robots, Google’s self-driving car, and tons of geeky bleeding edges gizmos that were just fun to watch and try.

Day two was also filled with a lot of interesting sessions. The conference boasted many interesting sessions on GWT but, unfortunatly, I could not attend every single one of them so I’m trying to catch up on some of what I missed on YouTube, please let me know of your favorite session in the comments, to make sure I don’t miss it.  On Wednesday night I had the chance to have dinner with some the finest GWT experts like David Chandler, Jeff Larsen, Pierre-Laurent Coirier, Kyle Baley and others. I had a really great time with them and it was fun to share ideas and just get to know everyone.

Google I/O is finished and I’m already looking forward to next year’s event! See ya next year Google I/O, see ya later San Francisco and I hope to see all of you, GWT and GAE fans, very soon someway or another! Meanwhile, the net and its various forums will have to do…

2

We won the regional event

We’re proud to announce that we won the first prize in the Technological and Technical Innovation category at the regional final of the Quebec Entrepreneurship Competition. This second step secures us a place for the last event, the provincial final, wich will be held on June 16th. Wish us luck!

C’est avec fierté que nous vous annonçons avoir gagné le premier prix catégorie Innovation technologique lors de la finale régional du Concours Québécois en Entrepreneuriat. Cette deuxième étape nous permet de nous qualifier pour la dernière, la finale provinciale de l’événement, qui aura lieu de le 16 juin prochain. Souhaitez-nous bonne chance!

Official web site release date

We would like to announce that our official web site will be lauched officially May 6th in May. You can already get a sneak peak here : hive.arcbees.com. Our development blog will still be available and a summary will be shown from the main page of our official web site.

Nous aimerions vous annoncer que notre site officiel sera lancé officiellement le 6 mai en mai. Vous pouvez déjà avoir un aperçu au hive.arcbees.com. Notre blog de développement sera toujours disponible et vous pourrez avoir un résumé de ce que nous publions du site web officiel.

ArcBees wins!

We’re proud to announce that ArcBees won the first prize in the Technological and Technical Innovation category as well as the grand prize overall at the 13th edition of the Quebec Entrepreneurship Competition for the local edition at Université Laval. We were awarded 1000$ for winning the first prize in our category, as well as 1000$ in consulting services from Avocats BCF. For the BMO grand prize we received 4000$ as well as 1000$ in services from BMO Financial Group.

We’d like to thanks everybody who help us write and clean-up our business plan, in particular Yves Plourde from Entrepreneuriat LavalInno-Centre, Éric Matteau, Charles Simard, Frédéric Lavigne, Geneviève Doyle as well as Robert Beaudoin. Their comments greatly increased the quality of our document, and helped us express the technical details in layman terms (even if we still have work to do in that area ;)). We would also like to thanks the judges who believed in us and in our project.

We are now looking forward to the next phase of the competition: the regional final of the Quebec City area, where we are finalists in the Technological and technical innovation category.

Version française

C’est avec fierté que je vous annonce que ArcBees a remporté le premier prix de la catégorie Innovation technologique et technique ainsi que le grand prix toutes catégories de la treizième édition du Concours Québécois en Entrepreneuriatpour l’édition locale de l’Université Laval. Nous avons reçu une bourse de 1000 $ ainsi que 1000 $ en consultation chez Avocats BCF pour notre premier prix ainsi qu’une bourse de 4000 $ et 1000 $ en consultation et services chez BMO Groupe Financier pour le Grand prix BMO.

Nous tenons à remercier tous ceux qui nous ont aidés à rédiger et mettre en forme notre plan d’affaire, notamment Yves Plourde d’Entrepreneuriat LavalInno-Centre, Éric Matteau, Charles Simard, Frédéric Lavigne, Geneviève Doyle ainsi que Robert Beaudoin. Leur aide a grandement contribué à la qualité du document et nous a permis de vulgariser les détails techniques (même si du travail reste à faire à ce niveau ;)). Nous remercions aussi tous les juges qui ont cru en nous et en notre projet.

Nous passons donc maintenant à la prochaine étape du concours, la finale régionale de la région de la capitale nationale où nous sommes finalistes dans la catégorie Innovation technologique et technique.

If you think it’s obvious, think again, it’s probably wrong

In the past three months, we worked hard on our business plan and participated in various competitions for young entrepreneurs. While doing this, I learned a lot about the entrepreneurial world. One of those lessons is how easy it is to forget that the person reading your business plan might not be technically inclined, and as a consequence may not understand one word of what you’re saying. While I though I finally understood the lesson, it looks like the fourth iteration of our business plan is still too technical. I’m not saying the reader is dumb or anything, but it looks impossible to assess how technical the document is by ourselves, and even asking people around us to review it wasn’t enough. I should have asked even more people, people with no technical background, people like my grandfather who bought his first computer last year, people who hate technologies, people who don’t know me or that are not afraid to really say what they think.

There are many examples of obvious things that end up being wrong. For example, how many times did you finish an exam thinking you totally failed it, only to find out a week later that you got a really good mark ? How many times did you write some code thinking that it was perfect and then had to write it all again two weeks later ? How many times did you get out of a presentation thinking you nailed it, only to find out later that the audience was underwhelmed? Finally, how many times did you think you found something new just to realize that someone else had this idea long before you ? The lesson here is that there’s nothing obvious: always seek to make it better and, when you think you can’t go further, push it some more!

The last competition we participated in was Concours Québecois en Entrepreneuriat. While I already know the business plan was too technical, it doesn’t mean we didn’t win. We will only find out on April 14th for the regional competition and June 16th for the national. The thing that really matters is to remember that a Business Plan is a work in progress, it’s never final nor completed. You’ll have more than one version depending on who will read it. It has to be solid and simple. What’s left to do is to sell yourself, sell your team and, more importantly, sell your dream.

I’m a dreamer, I have the best associates in the world and we’re not afraid of loosing or winning because, no mater what, we will keep pushing forward. That’s obvious, isn’t it ?

3

My upcoming Google I/O talk on all the cool toys, including gwt-platform

As you probably know by now, we love the Google Web Toolkit, App Engine, Objectify, Gin, Guice and friends. ArcBee’s project, GWT-platform, has slowly crept up the ranks and is now a very popular tool for people who want to quickly develop solid GWT applications.

If you’re a GWTP user, or if you are considering it for your next project, you’ll be happy to learn that this year’s Google I/O will feature the talk: Highly Productive GWT: Rapid Development with App Engine, Objectify, RequestFactory, and gwt-platform. Given by David Chandler (of Google) and myself, this talk will briefly introduce the above technologies as well as recent additions to GWT such as Cell widgets and RequestFactory. We will take you in a live-coding journey starting from (almost) nothing and ending up with a fully usable webapp deployed on AppEngine.

I hope to see you in San Francisco… If you were not fortunate enough to get tickets, make sure to join us on the live video stream.

Google I/O 2011

We’re very excited to announce that ArcBees will be at Google I/O 2011 ! Some of us were lucky enough to be invited one week before the crazy registration day where tickets sold out in less than an hour! Out of the four members of ArcBees, only one wasn’t able to make it. Unfortunately for him, he went to grab a snack and when he came back, Google I/O was already sold out. Next time pal, don’t blink, just hit the refresh button endlessly. Kidding apart, I’m really sorry as I would have enjoyed to see him join us on our trip to San Francisco.

If you’re following one of our projects or if you just want to see how good-looking we are, let’s meet and have some fun at this incredible event! That is, if you were fortunate enough to snatch some tickets. For everyone who did not make it, we send you some love and lots of virtual drinks. We’ll blog/tweet about Google I/O and relay everything that we find interesting while participating. In the meantime, we will keep teasing our partner and try to make him cry.

EDIT
I won’t be able to pick on him anymore,  he finally found a ticket ! Many thanks to Kyle Baley !

PRAIRIE DEV CON 2011

It’s been a while since our last post, but don’t worry, it wasn’t because we were sick or because we broke every single fingers of our hands. We only worked more than ever on our upcoming projects. Well, one of the them is the speaks that Philippe Beaudoin will give at the Prairies Dev Con about GWT, GAE and Gwt-Platform on June 13th and 14th 2011. If you’re interested about the sessions or if you want to meet with the team, buzz us and we’ll get in touch at this incredible event. In the meanwhile, you can read the sessions description.

Google Web Toolkit and the Model View Presenter Architecture
This session will give you the opportunity to write a complete GWT application from scratch using the Model-View-Presenter architecture recommended by Google. Your app will be built on the GWT-Platform framework and will include all the latest feature of GWT including history management, a command pattern for RPC calls, a client-side event bus, code splitting, and dependency injection through Gin and Guice.

Attendees will need a laptop with Eclipse and the Google Plugin for eclipse. Other libraries can be downloaded from the web during the session.

Introduction to Google AppEngine Development in Java
Google AppEngine is a Platform-as-a-Service cloud solution that is widely recognized as a cost-effective way to deploy a scalable web application. However, making good use of the platform requires you to understand some of the design choices behind it. This talk will discuss the advantages and drawbacks of AppEngine. It will also introduce some of its most important features, including the datastore (based on Google’s BigTable NoSQL database), and task queues. The lecture will use the AppEngine Java API as well as the open-source Objectify API to access the datastore.

For more informations: http://www.prairiedevcon.com/

Testing views using Gwt-Platform’s MockingBinder tool

Testing GWT views has always been difficult and really slow. This is due to the fact that instantiating javascript components makes it necessary to rely on GwtTestCase, which in turn instantiates HTMLUnit and turns a simple unit test into something that more closely resembles an integration test. In fact, the pain of relying on GwtTestCase is well documented. With the help of GWTMockUtilities, Jukito and our MockingBinder utility, views can be as easily tested as presenters!

Don’t shoot!

A well known trick that anybody who tried testing GWT code learns is to disarm. This is done simply by calling GWTMockUtilities.disarm(). This makes sure any call to GWT.create() returns null instead of launching its javascript infested voodoo.

As your spouse will tell you, however, returning null is not a solution! In many cases, you will run into null pointer exceptions when your code (or GWT’s internal code) expects an object but finds null. The key is therefore to never call GWT.create, either directly or via a call to new that would eventually lead to the dreaded GWT.create().

The first trick: don’t create your UiBinder yourself!

Let’s examine a typical view that relies on UiBinder:

[sourcecode language=”java”]
public class HelloViewImpl extends ViewImpl implements HelloView {
interface Binder extends UiBinder<Widget, HelloViewImpl> {
}

private static Binder uiBinder = GWT.create(Binder.class);

}
[/sourcecode]

Our first call to GWT.create() is right there. Worse, it’s in a static variable, so it will get created as soon as the class is loaded! How do we get rid of this one?

Enters Google GIN, dependency injection at its finest. One feature of GIN is that, if it finds an interface that has not been bound, then it creates it with a call to GWT.create(). This is precisely what we want here. Let’s then rewrite the above to use GIN:

[sourcecode language=”java”]
public class HelloViewImpl extends ViewImpl implements HelloView {
public interface Binder extends UiBinder<Widget, HelloViewImpl> {
}

@UiField HasText firstNameTextBox;
@UiField HasText helloLabel;

@Inject
public HelloView(final Binder uiBinder) {
initWidget(uiBinder.createAndBindUi(this));
}

}
[/sourcecode]

You are probably wondering if the binder will be GWT.create()d every time the view is instantiated. Yes. This is not a problem if the view is a singleton, but it can become one if you plan of filling a huge table with instances of that view. For those cases, simply go in your Gin configuration file and bind(HelloViewImpl.Binder.class).in(Singleton.class). We ran some GwtTestCase to verify the exact behavior of GWT.create() and using this singleton trick this will result in the same behavior as using a static field, but without the GWT.create().

Another option would be to inject Binder in a static field and rely on GIN’s requestStaticInjection(). But we all know static injection is evil, right?

What to do when testing?

When testing, you replace GIN with Guice (Is there a morale here?). As a result you will no longer have the automatic call to GWT.create(). This is great, but it also means you have to pass something else as a parameter when instantiating your view.

The first idea could be to simply pass an anonymous Binder class. Remember, however, that one of the side effects of the call to createAndBindUi is to fill all your @UiFields. We need our replacement class to do the same.

This is exactly what MockingBinder sets out to solve! This class uses reflection to identify all you @UiFields and let you use the mocking framework you want to fill them with mocked object of the corresponding type. It also ensures the call to createAndBindUi() returns a mocked object of the right type.

Writing a test using Jukito

When testing, you will need a TestBinder class that both extends MockingBinder and implements your view’s Binder. If you’re doing your unit test the old fashioned way, you can simply pass a new TestBinder() when instantiating your view. However, if you’ve discovered the joy of using DI and automocking right in your unit tests, then you will want to use Jukito. Let’s see how to do this:

[sourcecode language=”java”]
@RunWith(JukitoRunner.class)
public class HelloViewTest {
/**
* This is the Guice test module. Jukito runs the configureTest() method
* to setup all the bindings used in the following unit tests.
*/
public static class Module extends JukitoModule {
/**
* This is the test binder extending `MockingBinder` and implementing the view’s `Binder`.
*/
static class TestBinder extends MockingBinder implements Binder {
@Inject
public MyTestBinder(final MockitoMockFactory mockitoMockFactory) {
super(Widget.class, mockitoMockFactory);
}
}

@Override
protected void configureTest() {
GWTMockUtilities.disarm();
bind(Binder.class).to(TestBinder.class);
}
}

@AfterClass
public static void tearDown() {
GWTMockUtilities.restore(); // Just to be nice to future tests
}

@Inject HelloView view;

@Test
public void anyTest() {
// given
given(view.firstNameTextBox.getText()).willReturn("Christian");

// when
view.sayHello();

// then
verify(view.helloLabel).setText("Hello Christian!");
}
}
[/sourcecode]

And the factory:

[sourcecode language=”java”]
public class MockitoMockFactory implements MockFactory {
@Override
public T mock(Class classToMock) {
return Mockito.mock(classToMock);
}
}
[/sourcecode]

The first thing we do here, as soon as Jukito’s test module is initializing with the configureTest() method, is to call GWTMockUtilities.disarm(). This ensures nothing bad happens when loading the GWT classes since some static variables are initialized with calls to GWT.create(). For the benefit of future tests, we rearm GWT later in the tearDown() method.

Then we tell Guice that it should use our new TestBinder whenever it needs a Binder. Finally, we inject BlogView in the test class, this is caught by Jukito who uses Guice to instantiate BlogView, filling-in any dependencies. In this case, the TestBinder.

Finally our test can stub and verify behavior on all the @UiField of our view.

What about views that create widgets dynamically?

Some views need to create widgets dynamically, for example to fill a table with rows as data becomes available. Creating these widgets is typically done with new, but this will trigger an internal call to GWT.create() which, as we’ve seen, may later lead to null pointer exceptions.

The key here is to skip the new, again using the magic of dependency injection. Say, for example, you need to create labels dynamically. Simply inject a Provider<Label> in your view and call labelProvider.get() whenever you need a new instance. In your production code, this will have exactly the same effect as calling new Label(). In your testing code, however, you can substitute the Provider<Label> for a class that generates mock labels. In fact, this is exactly what Jukito will do for you provided you include this line in your configureTest() method: forceMock(UiObject.class);

If you want to dynamically instantiate widgets that require construction parameters you may need to create a factory, or to rely on Guice’s assisted factories which will be coming soon to GIN.

Philosophical questions…

One of the goals of the model-view-presenter architecture was to remove all the logic from the views so that you can test the core of your application without having to rely on GwtTestCase. With UiBinder, you end up with something that looks like MVVP since the declarative UI can be somehow seen as a dumb view. With the approach proposed here, you can pack as much logic as you want in your view and test it as easily as if it were a presenter. Does it mean we should drop one V on the MVVP pattern? What do you think?

More examples

For more complete examples, the ArcBees hive project heavily relies on this pattern to test views that have a bit of logic in them.

19

How I made my GWT/AppEngine application appear to load quicker

It’s a well known “feature” of AppEngine for Java that if your application does not retrieve much traffic, it’ll be unloaded to free resources for other applications. When your application does receive a visitor, your java application must be started. This is referred to as a “cold start”.

Jakob Nielsen’s Usability Engineering guidelines state that for any delay of greater than 1 second feedback is required. A GWT application running on Google AppEngine takes much longer than 1 second to get started. My GWT 2.0 application takes about 7 seconds from cold, or about 4 seconds on a warm AppEngine.

The following describes how I made my AppEngine application appear to load faster, without losing the XSRF protection provided by the gwt-platform framework.

Previously, when I loaded my app, my browser would show a blank page for about 7 seconds while the main html page loaded. To improve the user experience, I wanted to show the user a “fake” progress indicator that makes it seem like something was happening while the application is loading. (Something like every second, % complete += (15% of percentage incomplete). If % complete > 95, then % complete = 50. Gmail used this same pattern when loading. For more discussion on progress indicators, see ajaxpatterns.org.

In my main html file, I moved the script tag that included my .nocache.js from the head, to the bottom of the body.

Above this script tag I added some javascript that renders my progress bar, and use setTimeout to update it every second. The progress bar will continue to update as the javascript is loaded in background, and once my application is ready to be loaded I hide the progress bar in revealInParent() of my top-level presenter. By ordering things this way, my progress bar was displayed first and then the browser made the request to AppEngine to load the .nocache.js file.

Main HTML page

[sourcecode language=”html”]
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>MyApp</title>
</head>
<body>
<div id="loading" style="display: none">
<div id="progressbar" style="margin: 15px; width: 300px; height: 10px; border: 2px solid black; overflow: hidden;">
<div id="progress" style="background: silver; height: 100%; width: 0;"></div>
<script type="text/javascript">
var loading = document.getElementById(‘loading’);
var progress = document.getElementById(‘progress’);
var progressbar = document.getElementById(‘progressbar’);
function updateProgress() {
if(loading.style.display !== ‘none’) {
var width = parseInt(progress.offsetWidth+((progressbar.offsetWidth-progress.offsetWidth)*.15));
if(width > (progressbar.offsetWidth * .95)) {
width = parseInt(progressbar.offsetWidth) * .5;
}
progress.style.width = width + ‘px’;
window.setTimeout("updateProgress()", 1000);
}
}
document.body.style.margin = 0;
document.body.style.padding = 0;
loading.style.display = ‘block’;
updateProgress();
</script>
</div>
</div>
<iframe src="javascript:”" id="__gwt_historyFrame" tabIndex=’-1′ style="position: absolute; width: 0; height: 0; border: 0"></iframe>
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled in order for this application to display correctly.
</div>
</noscript>
<script type="text/javascript" language="javascript" src="myapp/myapp.nocache.js"></script>
</body>
</html>
[/sourcecode]

AppPresenter.java

[sourcecode language=”java”]
public class AppPresenterImpl extends …
// …
@Override
protected void revealInParent() {
DOM.setStyleAttribute(RootPanel.get("loading").getElement(), "display", "none");
RevealRootContentEvent.fire(this, this);
}
// …
}
[/sourcecode]

To return the main html before the java application starts, the main html file needs to be a static file, as App Engine serves static files from dedicated servers that are separate from the java application servers. Previously I used the code that was suggested in the wiki for XSRF protection, however this would no longer work as my main html file will be static and served from a different server.

DispatchServletModule.java

  • Send cookie to client attached to  .nocache.js

[sourcecode language=”java”]

public class DispatchServletModule extends ServletModule {
@Override
public void configureServlets() {
bindConstant().annotatedWith(SecurityCookie.class).to("MYCOOKIE");
filter("*.nocache.js").through(HttpSessionSecurityCookieFilter.class);
serve("/myapp/" + ActionImpl.DEFAULT_SERVICE_NAME + "*")
.with(DispatchServiceImpl.class);
}
}
[/sourcecode]

appengine-web.xml

  • Aggressively cache index.html and *.cache.*
  • I use gwt-math which puts some javascript files in /myapp/js/, this should be served statically
  • Don’t cache *.nocache.*
  • *.gwt.rpc is required for gwt-rpc serialization

[sourcecode language=”xml”]
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>myapp</application>
<version>…</version>
<static-files>
<include path="index.html" expiration="30d" />
<include path="myapp/**.cache.*" expiration="30d" />
<include path="myapp/js/*.js" expiration="30d" />
</static-files>
<resource-files>
<include path="myapp/*.gwt.rpc" />
<include path="myapp/*.nocache.*" />
</resource-files>
<precompilation-enabled>true</precompilation-enabled>
</appengine-web-app>
[/sourcecode]

Using a combination of the above techniques has improved my application so that:

  • Users get feedback almost instantly when they first browse to my application (about 0.4s according to Firebug)
  • The security cookie is still provided to the client (Firecookie shows the cookie was sent to the client in the headers and saved when myapp.appspot.com/myapp/myapp.nocache.js was retrieved).
  • Aggressive caching settings means that everything that it makes sense to cache, is cached.
12