Vaadin Extension: Highlighting Custom Components During Development

With the release of Vaadin 7, a new extension mechanism was introduced in the Vaadin Framework to extend the functionality of existing Vaadin components. This article will provide a short introduction to this concept and shows you how you can profit from it. As an example, a Vaadin add-on ComponentHighlighter is presented which makes use of this extension mechanism to provide a means to visually highlight your custom components in a running Vaadin application during development. This will help you identify the Java classes that implement the various parts of your Vaadin application.

With the new version 7 of the Vaadin toolkit released in February 2013, the RIA framework was extensively redesigned in several areas which were known to be unsatisfactory or awkward to work with. Numerous changes were applied to the API to allow for more flexibility in the framework. A focus of a lot of effort has been the API for creating custom Vaadin components. Not only has it been made significantly easier to write your own components. It is now even possible to extend an existing component through an extension system which does not necessitate you to derive from the extended component to meddle with the component’s internals or add custom functionality. This is extremely useful for noninvasively adding behavior to existing components.

Extensions can be anything from plain and simple to large and complex. This article provides an example of a fairly simple client-side component extension and gives an overview of the necessary steps for writing such an extension.

Using Vaadin’s extension mechanism, you can achieve the following things:

  • Add client-side behavior to an existing widget: You can add a feature to the client-side part of a component without having to touch the component’s server-side proxy class. For example, you could extend a TextField to have it automatically cache its value in the browser’s local storage or you could add CSS3 transition effects to a Vaadin Window object (like fade in/fade out).
  • Implement a generic behavior which can be added to any component: You can write a generic extension which can be applied to an arbitrary component, such as highlighters or extra JavaScript code added to a component.

In this article I will provide a simple how-to for developing your own component extension. I have written a Vaadin add-on ComponentHighlighter which will serve as an example in this article.

Let us first define what we want to achieve with this extension. Say you are writing a Vaadin application which has already grown a bit in size. You have defined several UI screens that each consist of a number of nested layouts and components. Typically, you will have divided your UI layout into individual parts that are implemented with the CustomComponent class. It would then be quite helpful if you could identify the fully qualified class name of all your custom components that are visible on one particular screen in the running application. This is useful, for instance, when you encounter a bug in some part of your UI (e.g., a label is not updated correctly) and you want to know which class implements this specific area. The ComponentHighlighter extension will allow you exactly that by decorating any component with a lightweight label (i.e., a element containing a text) that shows the class name of the extended component. You can switch these labels on and off if you’re running your application in development mode, and you can define the content of the label text yourself if you like.

Let’s have a look at what we need to do to write such an extension. We basically have to write three classes:

  1. The server-side extension class which will be used by a Vaadin application to extend some component. This class has to inherit from class com.vaadin.server.AbstractExtension.
  2. The client-side connector class which takes care of decorating the client-side widget with the extra label. This connector is implemented using GWT and will later be compiled into the widget set. The client-side connector has to inherit from class com.vaadin.client.extensions.AbstractExtensionConnector.
  3. Finally, we need a state class that carries the label text from the server-side to the client where it is rendered just above the extended component. This state class is derived from com.vaadin.shared.communication.SharedState.

The simplest class is the last one. The shared state class is simply a data transfer object (DTO) that contains a public variable for the label text we want to define in our application.

import com.vaadin.shared.communication.SharedState;

public class ComponentHighlighterState extends SharedState {
  public String debugLabel;
}

We can set this label in our server-side extension class. Vaadin then internally makes sure that this value is properly transferred to the client-side where it can be rendered in a element just above the extended component.

Next, let’s have a look at the server-side extension class.

public class ComponentHighlighterExtension
    extends AbstractExtension {

  public ComponentHighlighterExtension() {
    super();
  }

  public ComponentHighlighterExtension(
           AbstractClientConnector target) {
    super();
    if (target != null) {
      extend(target);
    }
  }

  @Override
  public void extend(AbstractClientConnector target) {
    if (VaadinService.getCurrent()
          .getDeploymentConfiguration()
          .isProductionMode()) {
      return;
    }
    super.extend(target);
    setComponentDebugLabel(target.getClass().getCanonicalName());
  }

  @Override
  protected ComponentHighlighterState getState() {
    return (ComponentHighlighterState) super.getState();
  }

  public void setComponentDebugLabel(String label) {
    getState().debugLabel = label;
  }
}

Here, we inherit from AbstractExtension which is the base class for all Vaadin extensions on the server-side. Besides the default constructor, we define a convenience constructor that later allows us to extend a given Vaadin component in one operation. In this constructor, we directly call the overridden extend() method so that you can extend some component directly with the constructor call of the extension class.

In line 17, we override method extend() which is inherited from AbstractExtension. We do this to add a check for Vaadin’s production mode. If an application is running in production mode our extension will simply ignore all calls to extend. By that, a component can only be extended by our ComponentHighlighter when the application is run in development mode. This makes sense, as the labels with which we want to decorate our components are only needed during the development of an application. When we create our extension objects as local object instances, we don’t even experience an increased memory consumption in production mode since these local instances are sacked by the garbage collector right away.

Next in method extend() is that we call the inherited implementation and set the default text for the debug label. This label, which we’ll add to the extended component on the client-side, by default shows the fully qualified class name of the extended component.

In line 28 we override method getState() and narrow the method’s return type to our concrete state class ComponentHighlighterState. This is a necessary step for both writing custom components and component extensions. By that, we tell the framework which class carries our custom state information to be shared between client and server.

In order to be able to later define a custom text for the debug label, we define method setComponentDebugLabel(String). We can use this method to set a different text to be shown on the extended component. For example, for a CustomLayout we could additionally display the layout’s template name.

Finally, let us explore what we have to do on the client-side for decorating a component with our debug label. We do this in class ComponentHighlighterConnector.

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ServerConnector;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.extensions.AbstractExtensionConnector;
import com.vaadin.shared.ui.Connect;

@Connect(ComponentHighlighterExtension.class)
public class ComponentHighlighterConnector
     extends AbstractExtensionConnector {
  private Widget widget;
  private Element span;
  private static ResourceProvider resourceProvider;

  static {
    resourceProvider = GWT.create(DefaultResourceProvider.class);
    // inject the extra CSS styles
    resourceProvider.getResources().style().ensureInjected();
  }

  @Override
  public void onStateChanged(StateChangeEvent stateChangeEvent) {
    super.onStateChanged(stateChangeEvent);
    refresh();
  }

  @Override
  public ComponentHighlighterState getState() {
    return (ComponentHighlighterState) super.getState();
  }

  @Override
  protected void extend(ServerConnector target) {
    widget = ((ComponentConnector) target).getWidget();
    refresh();
  }

  private void refresh() {
    String debugParam = Location.getParameter("debug");
    if (debugParam == null) {
      return;
    }

    if (span == null) {
      span = DOM.createSpan();
    }

    DOM.insertChild(widget.getElement(), span, 0);

    span.addClassName(resourceProvider.getResources().style().debugLabel());
    widget.addStyleName(resourceProvider.getResources().style().parentOutline());

    span.setInnerText(getState().debugLabel);
  }
}

We inherit ComponentHighlighterConnector from com.vaadin.client.extensions.AbstractExtensionConnector which is the client-side base class for all Vaadin extensions. Our connector class is annotated with the @Connect annotation. With this, we connect the client-side connector with the corresponding server-side extension class. We thereby tell the framework which classes work together to implement our component extension.

In the head of ComponentHighlighterConnector we use a static initializer block to create a GWT client bundle and have GWT inject the bundle’s CSS definitions into the HTML code. We’ll need this later to apply custom CSS styles to our debug label. Using GWT client bundles is beyond the scope of this article. You can read about that on the GWT Project site.

Next, we override three inherited methods from AbstractExtensionConnector: onStateChanged(StateChangeEvent), getState(), and extend(ServerConnector). Method onStateChanged(StateChangeEvent) is called by the framework each time the shared state information has been changed on the server-side. This will happen when the debug label text is changed through method ComponentHighlighterExtension#setComponentDebugLabel(String). In method onStateChanged, we have to take care that the changed value is propagated on the client-side accordingly. In our case, we simply call a custom refresh() method after calling the super implementation of onStateChanged. We’ll take a look at refresh() shortly.

The overridden implementation of getState() serves the same purpose as the corresponding method in ComponentHighlighterExtension. We narrow the method’s return type to our shared state class in order to inform the framework of the state’s type.

In line 37, we override method extend(ServerConnector) which can be seen as a sort of a proxy implementation for the server-side extend(AbstractClientConnector) method. This method is called once by the framework to attach the extension to its parent. In our custom implementation we obtain a handle on the extended component’s widget instance. We’ll need this widget later to prepend our debug label to it. This widget represents the generic GWT widget that comprises the extended client-side component as a whole. This may be a text field, a label, or a layout component, for example.

Finally, we define a refresh() method that implements the actual client-side behavior of our extension. The first thing we do in this method is to check whether the current URI in the browser does contain a URL parameter with name debug. If this is not the case we simply return from the method. The reason for this is as follows. We only want to show the debug labels if the debug mode is enabled with Vaadin’s debug URL parameter. By that, our debug labels are out of the way when they are not explicitly enabled through the debug mode.

If we found a debug parameter to be present in the current URL we create our debug label’s element and prepend that to our extended component’s widget. To do so, we first create a element in line 49 using GWT’s DOM class. Then in line 52, we insert this element just before the extended component’s widget in the DOM tree. In lines 54 and 55, we add a custom CSS style to the element and the decorated widget. The element’s style will render our debug label with a white foreground color and a pink background color. By that, these labels will be displayed as eye-catching as possible. The additional style for the decorated widget currently does nothing and is only used as a placeholder. It can be later customized if desired. As a last step in line 57, we set the inner text of the element to the label text as defined in the shared state object.

That’s all there is to say about the source code. All that remains to be done is to compile the extension into a widget set which is taken care of by the GWT compiler. A widget set is the Vaadin client-side engine and consists of the JavaScript code containing all Vaadin client-side widgets and the code for communicating with the server-side backend. Two of the three shown classes need to be compiled into a widget set as they have to be available on the client-side: ComponentHighlighterState and ComponentHighlighterConnector. Therefore, these two classes by convention should be organized in a package named client or a sub-package of that. In the example, the client-side classes are organized below package org.vaadin.highlighter.client. Parallel to the client package we need to define a GWT module descriptor that defines our widget set. We do this in a file named ComponentHighlighterWidgetset.gwt.xml:

<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.0//EN"
  "http://google-web-toolkit.googlecode.com/svn/tags/2.5.0/distro-source/core/src/gwt-module.dtd">

<module>
   <inherits name="com.vaadin.DefaultWidgetSet" />
   <inherits name="com.google.gwt.resources.Resources" />
</module>

We inherit from Vaadin’s DefaultWidgetSet which is mandatory for custom Vaadin widget sets. Next we inherit from GWT’s Resources module which we need to do in order to be able to use GWT client bundles.

Now we’re ready to compile our custom widget set which can be done with the Vaadin Eclipse plugin or the Vaadin Maven plugin.

You can find the full source code of the ComponentHighlighter add-on on GitHub. The add-on is licensed under the Apache License 2.0. You can use this add-on in your own project by including it into your own widget set like so:

<module>
   <inherits name="com.vaadin.DefaultWidgetSet" />
   <inherits name="org.vaadin.highlighter.ComponentHighlighterWidgetset" />
</module>

Using Vaadin add-ons is described in detail in the Book of Vaadin.

Using this extension is very easy. All you have to do is create a local instance of ComponentHighlighterExtension. The rest is done for you by the extension. Following is a simply example for how the extension can be used for a CustomComponent:

public class MyDetailViewComponent extends CustomComponent {
  public MyDetailViewComponent() {

    new ComponentHighlighterExtension(this);

    VerticalLayout layout = ...
    setCompositionRoot(layout);
  }
}

You’ll find the source code of this Vaadin add-on on GitHub. The add-on is hosted on the Vaadin Directory

Short URL for this post: http://wp.me/p4nxik-1vV
Roland Krüger

About Roland Krüger

Software Engineer at Orientation in Objects GmbH. Find me on Google+, follow me on Twitter.
This entry was posted in Java Web Frameworks and tagged , , . Bookmark the permalink.

Leave a Reply