Better SEO with GWT

When we started working on our new website, we quickly faced challenges often encountered with single-page application frameworks: enabling search engine optimization (SEO) and crawlability. The problem with these kinds of applications is that you only have one .html host file, which has two important consequences:

  1. Having only one title tag makes it hard for people to use the browser history for navigation
  2. It becomes impossible to define meta properties with relevant data for different site sections

Thankfully, each of these problems can be solved.¨

Changing the title

This is actually a simple fix. We can use GWT’s Document class to change the title when our section is attached to the DOM:

Adding and updating meta properties

Crawler

The hard way

We could create MetaElements and inject them into the head section manually when our section is attached to the DOM :

Using GWT-SEO

This seems a bit cumbersome and isn’t quite what webmasters are used to, so perhaps we can do better. This is where GWT-SEO comes into play. It allows us to define meta properties in the UiBinder’s ui.xml file as a Widget, almost like we would define them in an html file. The library will then create and inject the defined meta elements in the head section when your View is attached to the DOM, removing the need to register your own AttachHandler.

Now that’s better! Notice that the title is also handled, which means no more document.setTitle() is needed either!

Internationalization (i18n)

Moreover, since we’re within a UiBinder, we can therefore take advantage of the power of ui:msg to internationalize our properties (more details on using GWT i18n with UiBinder in an upcoming post!). In the meantime, you can take a look at our website for a live example of GWT-SEO using i18n, and especially at the sources of the website to see more in details how it was done, or at the source of my bee page for a specific example.

Dynamic data

More often than not, when implementing a single-page application, the content of the section will depend on some data fetched from an AJAX request (e.g. : a product page in an online store). GWT-SEO can also help you with that, although it requires some Java code in your request’s callback. Let’s say we have a Presenter that retrieves a Product when the product’s dynamic page is loaded, and passes it to its View through the setProduct method.

The advantage of using GWT-SEO, versus manually creating MetaElements to inject dynamic properties, is that it prevents duplicates by replacing existing properties with new ones, by leveraging the injection of derived tags (title and og:title, description and og:description, etc.).

But what good would all that do if crawlers like Google or Facebook can’t retrieve the fully rendered version of the page?

Making the application crawlable

Making your application crawlable could be the topic of a whole other blogpost, but I will discuss it briefly here.

Most crawlers nowadays implement a simple directive that allows us to serve different content when a hashbang (#!) is encountered in an URL. So the first step is to make sure your section URLs contain hashbangs. For example, a crawler fetching http://www.arcbees.com/#!/support would replace the hashbang with the escaped_fragment query parameter, in this case : http://www.arcbees.com/?_escaped_fragment_=/support (take a look at the rendered DOM).

Rendering for crawlers

Now that we have a way to identify crawlers’ requests, we need to serve a rendered version when we detect the _escaped_fragment_ query parameter to ensure the crawler doesn’t need to run any JavaScript code to access the content. To achieve this, we need something like HtmlUnit or PhantomJS to retrieve our webpage and process the JavaScript until we have a fully rendered page. Or better yet, use GWTP Crawler Service, which handles everything for us, from detecting crawlers’ requests to generating a fully rendered page!

Conclusion

Writing the meta properties for all the sections of your single-page application will allow you to be better ranked on search engines, and give you a chance to stand out against your competitors. It will also make your pages easier to share across social medias, which is, in this 2.0 era, mandatory for any web page. SEO and crawlability are easy things to overlook when developing your application, but to ignore them is to miss out on a substantial number of potential visitors!

Maxime Mériouma-Caron

Managing your CSS (GSS) files with variables and a theme

My previous article showed you how to use CSS inside your GWT application. Today, we will introduce the concept of variables, and show you how to manage them effectively using theme files.

Variables

Post_GSS_Howto2_v1-03-white

One of the best examples of variable use in CSS is probably color management. If your application has a default blue color, let’s say #2054e8, and it is used in multiple places, you will need to remember this particular color code every time you specify that color. Then if you decide to make your default color the lovely #f31ae5 shade of pink, you will need to do a find and replace across your whole project, and hope that everything went well.

All these hassles can be avoided if you use variables for your colors, so let’s do that!

Creating the Colors file

We will create Colors.java in src/main/java/com/company/project/client/resources.

package com.company.project.client.resources;

public class Colors {
    /* -> App colors -- */
    public static final String C_PRIMARY = "#2054e8";
    public static final String C_SECONDARY = "#bea885";
    /* -> Default colors -- */
    public static final String C_BACKGROUND = "#f0efef";
    public static final String C_TEXT = "#323232";
    public static final String C_TEXT_LIGHT = "#a1a1a1";
}

We will discuss variable naming conventions later. Right now, you only need to understand that we can define a variable, like C_PRIMARY, and assign it a value, such as our initial shade of blue #2054e8.

The main purpose of this file is to contain all color values in the same place. It will then be easy to replace them later, and create different themes for our app.

Creating the associated GSS file

This is where we start to feel the real power of GSS over regular CSS files. After compilation, GSS files output basic CSS, transforming variables into the values associated with them.

In order to easily use our variables, we need to define them in a file. We will name that file colors.gss and put it into src/main/resources/com/company/project/client/resources/css.

@provide 'colors';

@def C_PRIMARY        eval("com.company.project.client.resources.Colors.C_PRIMARY");
@def C_SECONDARY      eval("com.company.project.client.resources.Colors.C_SECONDARY");
@def C_BACKGROUND     eval("com.company.project.client.resources.Colors.C_BACKGROUND");
@def C_TEXT           eval("com.company.project.client.resources.Colors.C_TEXT");
@def C_TEXT_LIGHT     eval("com.company.project.client.resources.Colors.C_TEXT_LIGHT");

We define variable names, and point them to the associated variables inside Colors.java.

The most important part is the very first line:

@provide 'colors';

We are providing this file with a name that we will be able to import later on, making the variables defined in this file accessible in other contexts.

Binding it with your default resources style file

Before we can use this file, we need to supply it to our style’s resource file. My default style file is named style.gss and it uses the AppResources.java resource file, located in src/main/java/com/company/project/client/resources.

You can probably guess what you’ll find in this file:

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        // Your classes here
    }

    @Source("css/style.gss")
    Style style();
}

We can see that we are using style() with the file located at css/style.gss. We need to add the color.gss to @Source, so it’s accessible. Instead of a string, we need to pass an array of strings, pointing to the desired files.

    @Source({"css/colors.gss", "css/style.gss"})
    Style style();
}

Note that we need to declare colors.gss before style.gss. Otherwise, style.gss will try to load the colors.gss file, but it will not yet be defined, causing an error.

Using variables inside of the style file

Remember when we defined @provide 'colors'? It is now required inside style.gss. Once that’s done, you will have access to your variables!

@require "colors";

body {
    background-color: C_BACKGROUND;
    color: C_TEXT;
    font-size: 1.5rem;
}

Structure

You can define variables for a lot of things beside colors, like sizes and fonts. You could decide to create a variables.gss file and add all your variables there, but this can pose a problem as your application grows. I prefer to structure my files by what they do, giving each set of variables their own file:

// src/main/java/com/company/project/client/resources/variables
    -> Colors.java
    -> Fonts.java
    -> Sizes.java

// src/main/resources/com/company/project/client/resources/variables
    -> colors.gss
    -> fonts.gss
    -> sizes.gss

This way, if you only need to use Colors inside of a specific style sheet, you can import them alone. Variable types become more modular.

Naming Conventions

As variables are not prefixed with any symbols, it helps to write them in uppercase. That way it’s easy to spot them in your CSS.

I also like to prefix them with a single letter that represents the type of variable that it is.

- Colors.java   -> C_VARIABLE_NAME (C_PRIMARY, C_BACKGROUND, C_TEXT ...)
- Fonts.java    -> F_VARIABLE_NAME (F_PRIMARY, F_SECONDARY_BOLD ...)
- Sizes.java    -> S_VARIABLE_NAME (S_SECTION_PADDING, S_LINE_HEIGHT ...)

Give your variables meaningful names, something that you will be able to remember and understand upon reading. Describe the purpose of the variable, not its value.

For example, F_PRIMARY is the primary font used inside the app, the most common one that will be almost everywhere. I find the use of primary / secondary easy to remember. It has a strong meaning, and it’s about what the variable is used for, and not about the value held by the variable. A bad example would be F_ARIAL for the same variable with the same purpose. It’s bad because if, in the middle of the project, you decide to change the main font from Arial to Helvetica, you will need to refactor the name of your variable. This is what we are trying to avoid.

Instead of C_RED for an error message color, go for C_ERROR. Or even better : C_STATE_ERROR. You will be able to manage your state colors easily, like C_STATE_SUCCESS and C_STATE_DEFAULT without worrying about the color it is.

Theme

Post_GSS_Howto2_v1-04-white

The problem

If you create different variable files, you gain the ability to only load the ones you want. This is both good and bad. If you need several variable types, you have to specify each one of them inside of your resource loader, and then require them in your GSS file. This can quickly become annoying, and it makes your code harder to maintain.

// src/main/java/com/company/project/client/resources/AppResources.java

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        // Your classes here
    }

    @Source({"css/variables/colors.gss",
             "css/variables/fonts.gss",
             "css/variables/sizes.gss",
             "css/style.gss"})
    Style style();
}
/* src/main/resources/com/company/project/client/resources/css/style.gss */

@require "colors";
@require "fonts";
@require "sizes";

body {
    background-color: C_BACKGROUND;
    color: C_TEXT;
    font-family: F_PRIMARY;
    line-height: S_LINE_HEIGHT;
}

As you can see, if you have multiple GSS files, you need to include required variables inside each of those files. And if you need to add another variable set, or remove one, you will need to go inside each of your Resource and GSS files and adapt them accordingly. And that sucks.

The solution

Faced with the above problem, you might think going back to having just one Variables.java file and a variables.gss file is not a bad idea after all. But we can have our cake and eat it too. We can keep the separation in our Java files and have only one GSS to rule them all. This way, variable files will remain modular, and yet we will still have only one file to require in each GSS file that need to access variables. If we need to change the structure, like adding a new subset of variables, we will only need to update one file, and that’s all!

I call this super GSS file theme.gss because it will be used to produce different themes, but you could name it variables.gss and it would still be totally accurate.

// src/main/resources/com/company/project/client/resources/css/theme.gss

@provide 'theme';

/**
 * Colors
 */

@def C_PRIMARY                  eval("com.company.project.client.resources.theme.Colors.C_PRIMARY");
@def C_PRIMARY_BACKGROUND       eval("com.company.project.client.resources.theme.Colors.C_BACKGROUND");
@def C_TEXT                     eval("com.company.project.client.resources.theme.Colors.C_TEXT");
/* ... */

/**
 * Fonts
 */

@def F_PRIMARY                  eval("com.company.project.client.resources.theme.Fonts.F_PRIMARY");
@def F_PRIMARY_BOLD             eval("com.company.project.client.resources.theme.Fonts.F_PRIMARY_BOLD");
/* ... */

/**
 * Sizes
 */

@def S_LINE_HEIGHT              eval("com.company.project.client.resources.theme.Sizes.S_LINE_HEIGHT");
@def S_SECTION_PADDING          eval("com.company.project.client.resources.theme.Sizes.S_SECTION_PADDING");
/* ... */

With this new method, things are now easier to maintain:

// src/main/java/com/company/project/client/resources/AppResources.java

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        // Your classes here
    }

    // We only need to source the theme file
    @Source({"css/theme.gss",
             "css/style.gss"})
    Style style();
}
/* src/main/resources/com/company/project/client/resources/css/style.gss */

/* And we only have one file to require */
@require "theme";

body {
    /* All variables are still accessibles */
    background-color: C_BACKGROUND;
    color: C_TEXT;
    font-family: F_PRIMARY;
    line-height: S_LINE_HEIGHT;
}

As the constants’ values are stocked in Java files, these constants can be modified easily. With this technique, it is now super easy to create different themes that can be user-based or changed at compile time.

Updated Structure

Using a theme file, my structure now looks like this:

src/main/java/com/company/project/client/resources/
    -> elements/
    -> pages/
    -> theme/
        -> Colors.java
        -> Fonts.java
        -> Sizes.java
    -> AppResources.java
    -> ResourcesLoader.java

src/main/resources/com/company/project/client/resources/css
    -> elements/
    -> pages/
    -> style.gss
    -> theme.gss

Tips

A variable will output the string of text inside of it into your CSS. Sometimes, you will need a variable to output more then one set of properties. You can do so this way:

// src/main/java/com/company/project/client/resources/theme/Fonts.java
public class Fonts {
    public static final String F_PRIMARY = "'My Cool Typo', sans-serif";
    public static final String F_PRIMARY_BOLD = "'My Cool Typo', sans-serif; font-weight: 700";
}

Can you spot the trick in F_PRIMARY_BOLD? The variable is defining the font-family, closed with the semicolon ;, then define the font-weight, without a closing semicolon ; because the closure will be handled in the CSS.

/* src/main/resources/com/company/project/client/resources/css/theme.gss */
body {
    font-family: F_PRIMARY;
    /* will output : */
    font-family: 'My Cool Typo', sans-serif;
}

h1 {
    font-family: F_PRIMARY_BOLD;
    /* will output : */
    font-family: 'My Cool Typo', sans-serif;
    font-weight: 700;
}

Conclusion

You now understand the true power of variables. When used with a theme file, the management of your application becomes a breeze. Things can be made even easier, using a tool to manage the generation of your theme and the associated files. But that, my friends, is a topic for another blog post.

Post_GSS_Howto_v2-03

Getting started with CSS (GSS) and GWT

Getting started with CSS (GSS) in GWT

GWT can be hard to tackle at first, especially if your experience is entirely in front-end web development. You may be an HTML and CSS ninja, but not much of a Java wizard. This tutorial introduces how style sheets are used in GWT. I will not explain how to create a new GWT project, and will assume that you have an application you can run. That will let us focus on style sheets in GWT.

Once completed, don’t forget to have a look at the second part : Managing your CSS (GSS) files with variables and a theme.

From the beginning

If there is no style sheet inside of your application, or if you want a rough understanding of how it works, here’s a small step-by-step guide to add your default CSS file. Note that your application might be using a different folder structure than my example program, and that you will have to replace com/company/project to match your project.

The CSS file

Post_GSS_Howto_v2-01

We will create our initial CSS file into src/main/resources/com/company/project/client/resources/css and will name it style.gss. That’s right, .gss and not .css, as GSS files are like CSS files, but with more power. And we always want more power, don’t we?

We should add at least one line in our file, so we know that it’s working. Let’s use :

body { background-color: pink; }

At this point, it should not be working yet.

The Resource file

Post_GSS_Howto_v2-04

We then need to create the resource file that will be the bridge between your GSS file and your Java classes. This is because GWT will obfuscate class names on compliation, so this file will handle the links between the obfuscated names and classes inside of your GSS file.

Let’s create AppResources.java inside of src/main/java/com/company/project/client/resources

The code inside of it goes like this:

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
    }

    @Source("css/style.gss")
    Style style();
}

The Resource Loader file

Post_GSS_Howto_v2-06

We now need to setup the loader file to, well, to load everything inside the application.

Once again inside src/main/java/com/company/project/client/resources, create a file named ResourceLoader.java, containing :

package com.company.project.client.resources;

import javax.inject.Inject;

public class ResourceLoader {
    @Inject
    ResourceLoader(
            AppResources appResources) {
        appResources.style().ensureInjected();
    }
}

The ensureInjected() is the important part here, as it will inject your CSS into the DOM.

Don’t forget to bind this file inside your ClientModule, probably located at src/main/java/com/company/project/client/gin/ClientModule.java

package com.company.project.client.gin;

// [your imports]

public class ClientModule extends AbstractPresenterModule {
    @Override
    protected void configure() {
        // [your code]
        bind(ResourceLoader.class).asEagerSingleton();
    }

    // [you might have code here too]
}

Activate GSS

Post_GSS_Howto_v2-07

GSS has been included in GWT since version 2.7, but is not enabled by default. To enable it, you need to add one line of code inside your GWT module. Mine is located at src/main/java/com/company/project/AppModule.gwt.xml and looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.7.0//EN"
        "http://gwtproject.org/doctype/2.7.0/gwt-module.dtd">
<module rename-to="AppModule">
   // [Inheriting some stuff]
   // [Source some stuff]

   // The line that you need to add
   <set-configuration-property name="CssResource.enableGss" value="true">

   // [Some more code extending ... thing?]
</module>

Voilà! If things went well, your application should build and run, loading your style.gss file in the process. Don’t worry if it fails, as you might have your application structured in a different way than shown in this tutorial. If you take time to read compile errors, you should manage to make it right. If you don’t, but have a backend dev near you, it’s always good to ask for help.

Using classes

One of the most confusing thing at first while working on GSS files in GWT is that you will need to declare your classes inside of your resource file to be able to access them.

Let’s add some classes into our style.gss file :

body {
    background-color: pink;
    padding: 2em 0;
}

.my_first_class {
    color: red;
}

.my_second_class {
    color: blue;
}

We then need to adapt the resource file accordingly:

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        String my_first_class();

        String my_second_class();
    }

    @Source("css/style.gss")
    Style style();
}

Congratulations! You can now use you classes inside your views (you know, the files ending with .ui.xml) and even with your Java files.

We will first need a view. The file that we will be working on, aka ApplicationView.ui.xml, looks like this:

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>
    <div>
        <h1>Hello World!</h1>

        <p>This is my first paragraph.</p>
        <p>This is my second paragraph.</p>
    </div>
</ui:UiBinder>

In order to use our classes, we will need to import the desired resource into the view :

<ui:with field="resources" type="com.company.project.client.resources.AppResources"/>

We can now call the required classes using resources.style.name_of_my_class

In the precedent view, the final code would be :

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>

    <ui:with field="resources" type="com.company.project.client.resources.AppResources"/>

    <div>
        <h1>Hello World!</h1>

        <p class="{resources.style.my_first_class}">This is my first paragraph.</p>
        <p class="{resources.style.my_second_class}">This is my second paragraph.</p>
    </div>
</ui:UiBinder>

You should know that Java uses the CamelCase naming convention, and that hyphenated class names using “-" will not compile. In order to make it work, you will need to use @ClassName inside of your CssResource:

@ClassName("my-class-name")
String myClassName();

Structure

Post_GSS_Howto_v2-09

It’s good to split your CSS into multiple files. It will be easier to maintain and understand, and will help you think in blocks and structure your classes accordingly; rather than having only one CSS file that does everything, but where you are not sure what that everything is.

A structure that I like, (but feel free to adapt it), is this one:

/resources
    /css
        /elements               // -> Elements that you reuse here and there
            section.gss
            form.gss
            anyElement.gss
        /pages                  // -> Pages related style
            login.gss
            contact.gss
        style.gss               // -> Your main style

Working with multiple GSS files

Post_GSS_Howto_v2-08

While working with multiple GSS files, you have two options: you can create a resource file for that GSS and include it only in views that will need it, or you can declare multiple GSS files into the same resource.

One resource file per GSS

It might sound easier to stack everything into the same resource file, but as with CSS files, it’s always better to break your code in blocks. If you have a contact.gss file that will only be used inside of your contact.ui.xml, you should create a dedicated resource for that. And I’d guess that you would also need your default style inside that view.

// src/main/resources/com/company/project/client/resources/css/pages/contact.gss

.contact {
    background-color: orange;
    padding: 4em;
}

.contact_form {
    width: 100%;
    border: 1px solid #00f;
}
// src/main/java/com/company/project/client/resources/pages/ContactResources.java

package com.company.project.client.resources.pages;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        String contact();

        String contact_form();
    }

    @Source("com/company/project/client/resources/css/pages/contact.gss")
    Style style();
}
// src/main/java/com/company/project/client/application/contact/ContactView.ui.xml

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>

    <ui:with field="resources" type="com.company.project.client.resources.AppResources"/>
    <ui:with field="pageResources" type="com.company.project.client.resources.pages.ContactResources"/>

    <div class="{pageResources.style.contact}">
        <h1>My contact page!</h1>

        <p class="{resources.style.class_from_style_gss}">
            This is a beautiful contact form.
        </p>

        <form class="{pageResources.style.contact_form}">
            <input type="email" placeholder="your email please" />
            <input type="submit" value="Go!" />
        </form>
    </div>
</ui:UiBinder>

Multiple GSS files in the same resource

Let’s say you have a small application with only 3 pages: homepage, services and contact. For each page, you created a corresponding GSS file (homepage.gss, services.gss and contact.gss).

You could create one resource file for each, like in the previous example. You could also create one resource file to rule them all, named PageResources.java.

// src/main/java/com/company/project/client/resources/PageResources.java

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Homepage extends CssResource {
        String homepage();

        String homepage_big_title();

        [other cool classes related to homepage only]
    }

    interface Services extends CssResource {
        String services();

        [other cool classes related to services only]
    }

    interface Contact extends CssResource {
        String contact();

        String contact_form();

        [other cool classes related to contact only]
    }

    @Source("com/company/project/client/resources/css/pages/homepage.gss")
    Homepage homepage();

    @Source("com/company/project/client/resources/css/pages/services.gss")
    Services services();

    @Source("com/company/project/client/resources/css/pages/contact.gss")
    Contact contact();
}

You will need to update your ResourceLoader.java accordingly:

package com.company.project.client.resources;

import javax.inject.Inject;

public class ResourceLoader {
    @Inject
    ResourceLoader(
            AppResources appResources) {
        appResources.homepage().ensureInjected();
        appResources.services().ensureInjected();
        appResources.contact().ensureInjected();
    }
}

Now, you can include the PageResources in each of your pages. It will give you access to every interfaces in it (homepage, services, contact).

// src/main/java/com/company/project/client/application/contact/ContactView.ui.xml

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>

    <ui:with field="resources" type="com.company.project.client.resources.AppResources"/>
    <ui:with field="pageResources" type="com.company.project.client.resources.PageResources"/>

    <div class="{pageResources.contact.contact}">
        <h1>My contact page!</h1>

        <p class="{resources.style.class_from_style_gss}">
            This is a beautiful contact form.
        </p>

        <p class="{pageResources.homepage.homepage_big_title}">
            Hey look, I can also use a class from the homepage, even though I should probably don't do this, right?
        </p>

        <form class="{pageResources.contact.contact_form}">
            <input type="email" placeholder="your email please" />
            <input type="submit" value="Go!" />
        </form>
    </div>
</ui:UiBinder>

Using images

Post_GSS_Howto_v2-05

If you want to use images inside of your GSS file, you will need to declare them as an ImageResource. Your image will need to be inside your resources folder, and like your GSS files, it’s always a good thing to create a proper folder structure in order to maintain control.

// src/main/java/com/company/project/client/resources/pages/ContactResources.java

package com.company.project.client.resources.pages;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
// ^ don't forget to import the ImageResource package

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        String contact();

        String contact_form();
    }

    @Source("images/contact/background.jpg")
    ImageResource background();

    @Source("com/company/project/client/resources/css/pages/contact.gss")
    Style style();
}
// src/main/resources/com/company/project/client/resources/css/pages/contact.gss

@def BACKGROUND resourceUrl("background");

.contact {
    background: BACKGROUND no-repeat center center;
    padding: 4em;
}

.contact_form {
    width: 100%;
    border: 1px solid #00f;
}

Conclusion

CSS with GWT is not an easy task at first, but after mastering the basics, you can regain your status as a front end ninja in GWT-land. Find the workflow that suits your need, structure your files and don’t forget to have fun!

In my next post, I will teach you how to leverage the real power behind GSS and simplify your life, using variables and a theme file. Stay tuned!

Post_GSS_Howto_v2-03

Gwt-Platform event best practices (revisited)

Not too long ago, I started using GWT and GWTP and found it pretty hard to understand its event system.

I still can’t find much recent information about it, so I am writing this post to hopefully help others. Disclaimer: There many ways to achieve what I do in this post, but this is the way I prefer.

All right! Let’s demonstrate how events and the event bus work by creating a CSI-Hacking Dashboard. You can get the code on GitHub.

Post_gwtp_Howto_v1-03

We have ComputerPresenter, a HackerPresenter and a root Presenter that holds/creates other widgets. We also have a ComputerHackedEvent and ComputerHackedHandler. The event will be raised to signal that the computers got hacked, and the handler code will be executed after that.

Here’s the classic implementation of a GWT event. Our event will only carry the hacker’s name.

public class ComputerHackedEvent extends GwtEvent<ComputerHackedEvent.ComputerHackedHandler> {
    public interface ComputerHackedHandler extends EventHandler {
        void onSystemHacked(ComputerHackedEvent event);
    }

    public static final Type<ComputerHackedHandler> TYPE = new Type<>();

    private final String hackerName;

    public ComputerHackedEvent(String hackerName) {
        this.hackerName = hackerName;
    }

    public static void fire(String hackerName, HasHandlers source) {
        source.fireEvent(new ComputerHackedEvent(hackerName));
    }

    public String getHackerName() {
        return hackerName;
    }

    @Override
    public Type<ComputerHackedHandler> getAssociatedType() {
        return TYPE;
    }

    @Override
    protected void dispatch(ComputerHackedHandler handler) {
        handler.onSystemHacked(this);
    }
}

I usually declare my handler as a nested interface in the event declaration. That’s only a matter of personal preference though.

Next we have to raise the event. That will be done by our HackerPresenter. A really simple way of becoming a computer hacker, is by adding a button to the screen and pressing it, right CSI?

Here’s the code of the view and the presenter.

public class HackerView extends ViewWithUiHandlers<HackerUiHandlers>
        implements HackerPresenter.MyView {
    interface Binder extends UiBinder<Widget, HackerView> {
    }

    @UiField
    Button hackThePlanet;

    @Inject
    HackerView(Binder binder) {
        initWidget(binder.createAndBindUi(this));
    }

    @UiHandler("hackThePlanet")
    public void initiateHacking(ClickEvent event) {
        getUiHandlers().onInitiateHacking();
    }
}
public class HackerPresenter extends PresenterWidget<MyView>
        implements HackerUiHandlers {
    public interface MyView extends View, HasUiHandlers<HackerUiHandlers> {
    }

    private final String hackerName;

    @Inject
    HackerPresenter(
            EventBus eventBus,
            MyView view,
            @Assisted String hackerName) {
        super(eventBus, view);

        this.hackerName = hackerName;

        getView().setUiHandlers(this);
    }

    @Override
    public void onInitiateHacking() {
        ComputerHackedEvent.fire(hackerName, this);
    }
}

So we have a button, and when we click on it, it raises an event. There are a couple of ways to raise an event, but the one I usually use, is the static fire() method on the event. (I’ll talk about the other ways of firing an event later on.)

Now we have to handle the event somewhere. We want to know when the computers get hacked, so we’ll represent the computers with the ComputerPresenter. Its role will be to print in the console when it gets hacked, and by which hacker. Here’s the presenter code:

public class ComputerPresenter extends PresenterWidget<MyView>
        implements ComputerHackedEvent.ComputerHackedHandler {
    public interface MyView extends View {
        void setComputerName(String computerName);

        void displayStatus(String computerName, String hackerName);
    }

    private final String computerName;

    @Inject
    ComputerPresenter(
            EventBus eventBus,
            MyView view,
            @Assisted String computerName) {
        super(eventBus, view);

        this.computerName = computerName;

        view.setComputerName(computerName);
    }

    @Override
    protected void onBind() {
        super.onBind();

        addRegisteredHandler(ComputerHackedEvent.TYPE, this);
    }

    @Override
    public void onSystemHacked(ComputerHackedEvent event) {
        getView().displayStatus(computerName, event.getHackerName());
    }
}

This way, when a hacker clicks on the “start hacking” button, all the computers that are listening to the event will print something. As you can see, the ComputerPresenter registers itself as a handler for the ComputerHackedEvent through the addRegisteredHandler method.

This is a convenience method provided by GWTP. Using this method instead of registering directly on the EventBus will make the event registration part of GWTP’s lifecycle and unbind the event handler when the presenter is unbound. That means that if the presenter is unbound and rebound, you’ll have to re-register event handlers. This is why the onBind method is a good place to register handlers.

Here’s the code of the root presenter:

public class RootPresenter extends Presenter<RootPresenter.MyView, RootPresenter.MyProxy> {
    interface MyView extends View {
    }

    @ProxyStandard
    @NameToken(NameTokens.home)
    interface MyProxy extends ProxyPlace<RootPresenter> {
    }

    public static final Object SLOT_COMPUTERS = new Object();
    public static final Object SLOT_HACKERS = new Object();

    private final WidgetsFactory widgetsFactory;

    @Inject
    RootPresenter(
            EventBus eventBus,
            MyView view,
            MyProxy proxy,
            WidgetsFactory widgetsFactory) {
        super(eventBus, view, proxy, ApplicationPresenter.SLOT_SetMainContent);

        this.widgetsFactory = widgetsFactory;
    }

    @Override
    protected void onBind() {
        super.onBind();

        HackerPresenter zeroCool = widgetsFactory.createHacker("Zer0C00L");
        HackerPresenter acidBurn = widgetsFactory.createHacker("AcidBurn");

        addToSlot(SLOT_HACKERS, zeroCool);
        addToSlot(SLOT_HACKERS, acidBurn);

        ComputerPresenter computerA = widgetsFactory.createComputer("A");
        ComputerPresenter computerB = widgetsFactory.createComputer("B");

        addToSlot(SLOT_COMPUTERS, computerA);
        addToSlot(SLOT_COMPUTERS, computerB);
    }
}

We just create one hacker named Zer0C00L and 2 computers to hack. And now the view:

public class RootView extends ViewImpl
        implements RootPresenter.MyView {
    interface Binder extends UiBinder<Widget, RootView> {
    }

    @UiField
    HTMLPanel computers;
    @UiField
    HTMLPanel hackers;

    @Inject
    RootView(Binder uiBinder) {
        initWidget(uiBinder.createAndBindUi(this));
    }

    @Override
    public void addToSlot(Object slot, IsWidget content) {
        super.addToSlot(slot, content);

        if (slot == RootPresenter.SLOT_COMPUTERS) {
            computers.add(content);
        } else if (slot == RootPresenter.SLOT_HACKERS) {
            hackers.add(content);
        }
    }

    @Override
    public void removeFromSlot(Object slot, IsWidget content) {
        super.removeFromSlot(slot, content);

        if (slot == RootPresenter.SLOT_COMPUTERS) {
            computers.remove(content);
        } else if (slot == RootPresenter.SLOT_HACKERS) {
            hackers.remove(content);
        }
    }
}

Post_gwtp_Howto_v1-04

Nice! When I click on “Hack the planet!” I see the following result in the Javascript console:

I got hacked. (A) by Zer0C00L
I got hacked. (B) by Zer0C00L

I should start writing in l33tsp33k now.

Now what if you remove one of the ComputerWidgets from the DOM by calling removeFromSlot(SLOT_COMPUTERS, computerB); and still try to hack the planet?

If you read the output of the console you will see:

I got hacked. (A) by Zer0C00L
I got hacked. (B) by Zer0C00L

Wait… What? The handler for the computer B is still registered, the presenter wasn’t unbound, it was only removed from the DOM.

What if we want computer B to stop listening to the events when it’s not present in the DOM? Well that’s a job for addVisibleHandler. So instead of registering the handler using addRegisteredHandler we’ll use addVisibleHandler that will handle this for us. This way, when a presenter is considered “not visible” in GWTP’s lifecycle perspective (read: not visible as in “visible in the DOM”), the event will not reach the handler. The new output should now be:

I got hacked. (A) by Zer0C00L

There’s still a problem though. What if there were too many computers for a single hacker? I think at some point we’ll have to add someone to the team. Let’s do it!

// in the RootPresenter's OnBind method
HackerPresenter acidBurn = widgetsFactory.createHacker("AcidBurn");
addToSlot(SLOT_HACKERS, acidBurn);

You should see 2 buttons saying “Hack the planet!” and when you click them both, the output is:

I got hacked. (A) by Zer0C00L
I got hacked. (B) by Zer0C00L
I got hacked. (A) by AcidBurn
I got hacked. (B) by AcidBurn

All computers are reacting to every hacker, which is not what we want. This is happening because of the way we registered the handlers earlier. What we want is for the computers to react a specific hacker’s ComputerHackedEvent.

Since we can have a reference to the said hacker, that is pretty easy to accomplish. We have to delegate the handler registration to the concerned presenter. From the RootPresenter we’ll delegate the task, but first let’s create an interface :

import com.google.web.bindery.event.shared.HandlerRegistration;

public interface HasComputerHackedHandlers {
    HandlerRegistration addComputerHackedHandler(ComputerHackedEvent.ComputerHackedHandler handler, Object source);
}

We can then let ComputerPresenter implement it.

public HandlerRegistration addComputerHackedHandler(ComputerHackedEvent.ComputerHackedHandler handler, Object source) {
    HandlerRegistration hr = getEventBus().addHandlerToSource(ComputerHackedEvent.TYPE, source, handler);
    registerHandler(hr);
    return hr;
}

Note that instead of registerHandler() you can also use registerVisibleHandler().

And finally, when you click on both buttons, the output should be:

I got hacked. (A) by Zer0C00L
I got hacked. (B) by AcidBurn

All right! We’re ready to hack the planet! Are we?

Post_gwtp_Howto_v1-02

Remember when I said I would talk about the ways of firing events? If you are new to GWT and GWTP, you might have noticed that there are multiple methods available to fire events and register handlers.

// GWT
eventBus.addHandler(eventType, handler)
eventBus.addHandlerToSource(eventType, source, handler)

eventBus.fireEvent(event)
eventBus.fireEventFromSource(event, source)

// GWTP
presenterWidget.addHandler(eventType, handler) // deprecated
presenterWidget.addRegisteredHandler(eventType, handler)
presenterWidget.addVisibleHandler(eventType, handler)
presenterWidget.registerHandler(handlerRegistration)
presenterWidget.registerVisibleHandler(handlerRegistration)

presenterWidget.fireEvent(event)

Confused yet? I can say I was after seeing this. If you dig down you can see that a presenter widget gets an event bus injected and delegates most of its job to it. The only difference is that GWTP manages the handler registrations with its lifecycle (i.e: when a presenter gets unbound, the registered handlers get cleared). Also, if you dig for the fireEvent method, you’ll see GWTP delegates to eventBus.fireEventFromSource(). You may want to call the original fireEvent() if you want to match the following case (taken from the javadoc) “Fires the event from no source. Only unfiltered handlers will receive it”. Honestly, I’ve never faced that situation.

Here’s my cheat sheet of events in GWTP:

– Do I need to fire an event globally on the event bus? (i.e: everything registered to the event will handle it)
Y: presenterWidget.addRegisteredHandler() + SomeEvent.fire()
N: Go next

– Do I need to filter the handlers by the visibility of the handler?
Y: presenterWidget.addVisibleHandler() + SomeEvent.fire()
N: Go next

– Do I need specific handlers to handle events from a specific source?
Y: Create an interface called HasXXXHandlers and make your handling presenter implement it. GWTP gives PresenterWidget the capability to register handlers via registerHandler() and registerVisibleHandler(). Finally, fire the event with SomeEvent.fire()
N: That’s it. I usually don’t need more options, so the decision tree ends here. If you have another situation that doesn’t fit, let me know!

Post_gwtp_Howto_v1-05

GAE-Studio is now open source!

Some of you may already have noticed or heard me saying that GAE-Studio was going to be open sourced and I think it is past overdue to officially announce it: GAE-Studio is now open source under Apache 2 and freely available! We promise to keep working on it, and to make that possible, we’re going to add GAE-Studio support to our open source support packages. You can find the source code under our Arcbees github organization as well as on maven central. We released an official, stable version 1.0 a couple of days ago that you can see in action on our demo website. You can also read our documentation to learn more about how to install GAE-Studio in your Google App Engine application.

gae_datastore_viewer

Some may wonder why we chose to open source what was going to be our first official product. We’ve first started this venture almost 3 years ago when Arcbees was still in its inception. We were using Google App Engine heavily, and the lack of a good datastore admin console was a big problem. At the time, Google App Engine didn’t have any hooks on which we could build one, so we hacked our way around and built something useful for our own work. One year later, after finding other users were feeling the same pain as we did using Google App Engine, we set out to improve GAE-Studio user experience. It was planned to be our very first product that wasn’t going to be open sourced.

Last summer, Google IO announced a new console for Google App Engine that removed much of the pain that GAE-Studio was designed to help with. Then some time later, Objectify-Insight came out, and our visualization engine would be in competition with it. Since we love and have been using Objectify for years, we didn’t want to become their commercial competitor.

Post_gaestudio_v2

Still, we were and are hopeful that GAE-Studio will be useful for our developers. For one thing, GAE-Studio is available to all environments using the Modules, although it was initially written for the Java runtime. This is because Google now provides hooks in the Google App Engine SDK for the things we had to hack our way around to in the past. The further advantage of GAE-Studio is that it can be used locally! While Google has improved the usability of their cloud console a lot, the usability of local development tools is still weak.
Several hundred users have expressed an interest in using GAE-Studio, and we are now ready to officially release it in their hands. We hope you will find GAE-Studio useful, and will help us support the remaining runtime.

Thanks for the support and words of encouragement, and thanks for sticking with us through this venture!

About GAE-Studio

GAE Studio helps you optimize applications hosted on Google App Engine.

GAE Studio also allows datastore exploration, modification, deletion, import and export. Think of it as your swiss army knife for developing GAE applications!

Using real-time analysis of datastore requests, GAE Studio quickly highlights inefficient queries and gathers metrics that will help developers improve application performance.

GWT.create 2015: Top 5 sessions

Following my last week post about my experience at GWT.create 2015, I would have chosen more than 5 sessions to talk about, but I had to cut this short if I wanted to keep my readers 😀 Here’s my top 5:

  1. New brand and documentation
  2. Singular
  3. JsInterop
  4. GSS
  5. Incremental compile in SDM

New Brand and new website

I didn’t list this one first simply because Arcbees’ own Manon Gruaz did the design, but more because the GWT brand looked a lot like an old guy in a disco – possibly cool inside but not really looking that cool to onlookers. The centrality of Java alone feels dated for some people. The logo was definitely dated and a due for a makeover, and the documentation was starting to look like a 1990’s style early website. A full reboot of the brand was needed, something fresh that would communicate how much we care about architecture, how we work together as a community and the simplicity we seek while nevertheless building large, maintainable enterprise web applications.

GWT2015_7

While there’s still work to do on the documentation itself, the new branding was designed to be extensible, and is ready to be used seamlessly across the GWT community. I invite you to take a look at the GWT Brand book to learn more about the GWT brand and logo.

GWT2015_11

Singular

This session by Daniel Kurka was one of my favorites at GWT.Create for several reasons. While simplifying the development process considerably using the same patterns as Angular, something even more powerful lurks behind the scenes. It lets you build true multiplatform applications (Android, iOS, web). Singular uses techniques developed for Inbox that let you compile java code to Objective-C thanks to J2ObjC and to javascript thanks to GWT. So that more than 80% of you code can be shared between the three platforms. To know more, I invite you to watch j2objc’s session by Tom Ball: J2ObjC: Sharing Java Code with iOS Applications.

Angular has performance problems when it comes to really large web applications. As you know, Angular scans the DOM for directives at runtime. Singular, thanks to GWT, does that at compile time, improving performance by a lot.

The project is still in its infancy, but what Daniel did already demonstrates that writing Java can be as simple as writing Javascript while preserving Type Safety. To know more, I invite you to watch Daniel Kurka’s session: Singular – Reimagining AngularJS in Java.

JsInterop

Writing wrappers has always been a pain in the ass and while using an external javascript library is possible, it is truly tedious; to the point where I have seen some business dropping GWT because they couldn’t easily use some of their favorite Javascript libraries. This won’t be a problem anymore. You can already turn on JsInterop in GWT 2.7 as an early release, but you’ll really get everything you need to start hacking around a Javascript library in GWT 2.8. In case you have any doubts, I invite you to take a look at Ray Cromwell’s session: Deep dive in JsInterop.

GSS

If you have a web development background and have done a bit of CSS, you know how painful it can be to work with CssResources; not because it was poorly designed, but mostly because some fundamental CSS3 features weren’t even available! To keep up the with the pace of this ever-changing world, GSS has been added to GWT. GSS brings full CSS3 support and several interesting features like mixins, conditionals, variables and more. It’s now easier to write and maintain the CSS files of your GWT application.

Thanks to Julien Dramaix, this is one of the few major outside contributions made to GWT since the steering committee was created, and we’re proud to have participated in this. To learn more about GSS, I invite you to take a look at Julien Dramaix’s session: CSS3 and GWT in perfect harmony.

Incremental compile in SDM

Last,but not least, incremental compilation now lets us seamlessly refresh our work in the browser in day to day development activities, and get the latest code from our IDE in less than 2 seconds. Before, it was a real pain to use SDM because it would do a full recompile of the whole application each time you needed to see a new change. Thanks to incremental compilation, that is not the case anymore.

IDE support in both Eclipse and IntelliJ is still in active development. We can already use our favorite debugger, but in some cases, it will not work. For now, we’re still stuck debugging in my Chrome console, and thanks to source map, we can see quickly where problems are. I’m still eager to go back to my IDE, put my breakpoints in and get my usual workflows in place, and I’m pretty sure that I will see that happen really soon! To learn more, I invite you to take a look at John Stalcup’s session: Incremental compilation.

Conclusion

In conclusion, GWT.Create was a blast this year! I had fun, met great developers, great businesses and I got to see all my remote friends that I only see once or twice a year. I know I speak for the rest of my team as well in saying that, and I’ll be eager to participate in GWT.Create next year. I’m already pledging that we will submit more sessions for the pleasure of the GWT community and our own open source community!

See ya next year!

GWT.create 2015: Return of experience

As I look back, almost three weeks after GWT.create, I can’t keep myself from smiling. It was, for several reasons, the best time I’ve had with the GWT community since I joined. Traveling between Mountain View in the Computer History Museum and Munich, meeting hundreds of GWT enthusiasts and exchanging ideas with them about how to make GWT even better made me realize how incredible this community is and how lucky we are to be part of it. Learning from their technical knowledge and their deep personal and business involvement with this toolkit, I felt lucky I got the chance to connect with some of the best engineers in the world. If you’re reading these lines and you spoke with me, I’m glad to have met you 😀

GWT2015_10

GWT.create this year was Arcbees’ chance to shine! We jumped in as major partner. Julien had two sessions: Best development practice for GWT web application and CSS3 and GWT in perfect harmony, plus one workshop on how to contribute to GWT, while I delivered a keynote plus one session: How to improve your productivity using GWTP. We had major news to deliver at the keynote, having taken some of our free time to develop a new brand and a new website for GWT. This will have huge impact in the future of GWT as we try to make the brand more modern and sexy to support the design goals for upcoming developments in GWT. We spent a lot of time to give you the best experience we can and we welcome any constructive comments that might make it evenbetter in the future. One major improvement that was made to the website, even before the rebranding, was the introduction of ability to contribute documentation right from the website using markdown and GWT. We’ve preserved this functionality and hope the community will help us maintain the documentation.

GWT2015_2

When David Chandler got on stage to deliver the second keynote, I got a little bit nostalgic. He was the one that invited Philippe Beaudoin (cofounder of Arcbees) to speak about GWTP four years ago, in front of an overcrowded room at Google IO focused on how to build online business applications. He also made a statement about how everyone in the community cares deeply about abstraction and architecture, which are the two concepts that have inspired me and the rest of Arcbees for years to contribute open source libraries and frameworks to the community, to help them build better web applications. I was also amazed by the huge amount of raw talent that this community has to offer, and saw great web applications from businesses like Ruxit, Boomi and Magnolia. I could go on for a while, but needless to say that we’re starting to have great, beautiful and mature web applications built on GWT, and not just Google offspring like AdWords, Sheets and Inbox.GWT2015_9

During the first panel discussion, Ray Cromwell reminded the audience that GWT fuels the web applications that run the world. Stock exchanges, financial institutions, healthcare, airports, you name it. Whenever something needs to run on top of critical infrastructure, needs to be scalable and/or multi-platform, GWT is commonly seen. Javascript may have a lot of fresh cool toys to play with that GWT may not have (yet!), but would you invest everything you have on fresh cool toys? There’s a lot to learn from the Javascript community, but as decision makers, we need to choose robust solutions, not fashionable ones.

I got carried when I was writing this blog post and didn’t even started to write about my top 5 session/announcement, stay tuned early next week to know more about what was our top 5 sessions/announcement of the GWT.create 2015!