Docs Help

Terms, Icons, and Labels

Many classes have shortcut names used when creating (instantiating) a class with a configuration object. The shortcut name is referred to as an alias (or xtype if the class extends Ext.Component). The alias/xtype is listed next to the class name of applicable classes for quick reference.

Access Levels

Framework classes or their members may be specified as private or protected. Else, the class / member is public. Public, protected, and private are access descriptors used to convey how and when the class or class member should be used.

Member Types

Member Syntax

Below is an example class member that we can disect to show the syntax of a class member (the lookupComponent method as viewed from the Ext.button.Button class in this case).

lookupComponent ( item ) : Ext.Component
protected

Called when a raw config object is added to this container either during initialization of the items config, or when new items are added), or {@link #insert inserted.

This method converts the passed object into an instanced child component.

This may be overridden in subclasses when special processing needs to be applied to child creation.

Parameters

item :  Object

The config object being added.

Returns
Ext.Component

The component to be added.

Let's look at each part of the member row:

Member Flags

The API documentation uses a number of flags to further commnicate the class member's function and intent. The label may be represented by a text label, an abbreviation, or an icon.

Class Icons

- Indicates a framework class

- A singleton framework class. *See the singleton flag for more information

- A component-type framework class (any class within the Ext JS framework that extends Ext.Component)

- Indicates that the class, member, or guide is new in the currently viewed version

Member Icons

- Indicates a class member of type config

- Indicates a class member of type property

- Indicates a class member of type method

- Indicates a class member of type event

- Indicates a class member of type theme variable

- Indicates a class member of type theme mixin

- Indicates that the class, member, or guide is new in the currently viewed version

Class Member Quick-Nav Menu

Just below the class name on an API doc page is a row of buttons corresponding to the types of members owned by the current class. Each button shows a count of members by type (this count is updated as filters are applied). Clicking the button will navigate you to that member section. Hovering over the member-type button will reveal a popup menu of all members of that type for quick navigation.

Getter and Setter Methods

Getting and setter methods that correlate to a class config option will show up in the methods section as well as in the configs section of both the API doc and the member-type menus just beneath the config they work with. The getter and setter method documentation will be found in the config row for easy reference.

History Bar

Your page history is kept in localstorage and displayed (using the available real estate) just below the top title bar. By default, the only search results shown are the pages matching the product / version you're currently viewing. You can expand what is displayed by clicking on the button on the right-hand side of the history bar and choosing the "All" radio option. This will show all recent pages in the history bar for all products / versions.

Within the history config menu you will also see a listing of your recent page visits. The results are filtered by the "Current Product / Version" and "All" radio options. Clicking on the button will clear the history bar as well as the history kept in local storage.

If "All" is selected in the history config menu the checkbox option for "Show product details in the history bar" will be enabled. When checked, the product/version for each historic page will show alongside the page name in the history bar. Hovering the cursor over the page names in the history bar will also show the product/version as a tooltip.

Search and Filters

Both API docs and guides can be searched for using the search field at the top of the page.

On API doc pages there is also a filter input field that filters the member rows using the filter string. In addition to filtering by string you can filter the class members by access level, inheritance, and read only. This is done using the checkboxes at the top of the page.

The checkbox at the bottom of the API class navigation tree filters the class list to include or exclude private classes.

Clicking on an empty search field will show your last 10 searches for quick navigation.

API Doc Class Metadata

Each API doc page (with the exception of Javascript primitives pages) has a menu view of metadata relating to that class. This metadata view will have one or more of the following:

Expanding and Collapsing Examples and Class Members

Runnable examples (Fiddles) are expanded on a page by default. You can collapse and expand example code blocks individually using the arrow on the top-left of the code block. You can also toggle the collapse state of all examples using the toggle button on the top-right of the page. The toggle-all state will be remembered between page loads.

Class members are collapsed on a page by default. You can expand and collapse members using the arrow icon on the left of the member row or globally using the expand / collapse all toggle button top-right.

Desktop -vs- Mobile View

Viewing the docs on narrower screens or browsers will result in a view optimized for a smaller form factor. The primary differences between the desktop and "mobile" view are:

Viewing the Class Source

The class source can be viewed by clicking on the class name at the top of an API doc page. The source for class members can be viewed by clicking on the "view source" link on the right-hand side of the member row.

GXT 3.x


top

Logging

Logging with GXTLogging can be an invaluable tool in the application debugging tool chest when it isn’t enough to have a great debugger and good test coverage. As applications grow more complex, logging can be quite handy, so you can see what other interactions might be occurring due to seemingly unrelated logic and events. Logging can also be useful for other processes, such as getting feedback about possible bugs while still writing code, measuring performance of various parts of the application, and tracking how the application is used.

When large atom smashers spit out loads of data, they use a hypothesis to drill down and filter the data. The same goes for logging: unless a hypothesis is developed while coding source, the logging is going to look like noise. Having this goal in mind while writing your application will enable you to produce logging details that will be helpful later when you want to filter through the output generated by your application.

Logging in GWT

There are three main logging mechanisms built into GWT, each with a slightly different purpose and use case:

  • GWT.log is for Development Mode only. When invoked, it adds a message to the Development Mode console. There are two methods that can be called, log(String) and log(String, Exception). The former writes out simple text as an info statement, the latter as an error, and it draws the full stack trace of the exception when the message is selected. This is being used less now that Super Dev Mode is beginning to be adopted, since these messages will not show up.

  • The Lightweight Logging system is meant to be a low-level, web-mode specific mechanism to track details like application startup, simple performance figures, and can be enabled or disabled without recompiling the application. This means that these log statements never compile out, so they should be used sparingly.

  • The Java Logging facilities are partially emulated in GWT, allowing access to most of the same calls that you generally have in non-GWT Java code. This can be used in dev or web mode, and it has a number of configuration options within your module so you can decide where that logging should go. This article will focus on this tool.

java.util.logging

The java.util.logging tools behave the same on the client and server—instances can be retrieved from a call to Logger.getLogger(String), which should be given the name of the current class name, and typically are kept in a private static final field to avoid getting or making new loggers each time they are needed.

If your project includes GXT, logging is already present but completely disabled. Logging is enabled in the com.sencha.gxt.core.Core module—this line adds the necessary classes to the project, but forces them all to completely compile out:

<inherits name="com.google.gwt.logging.LoggingDisabled" />

To enable logging add this definition and set the value flag to true. The possible values are TRUE or FALSE—with the LoggingDisabled inherits statement above (or GXT in your app), here is how you enable logging:

<set-property name="gwt.logging.enabled" value="TRUE"/>

There are seven levels of logging available: severe, warning, info, config, fine, finer, finest. The higher in that list, the more important the message is —most logging configurations display the top two, and the rest are often left out except in specific situations.

<set-property name="gwt.logging.logLevel" value="INFO"/>

Next, there are logging handlers, the mechanisms that GWT uses to display or persist the logged messages. Typically on the server, you would write the log messages to one or more files, but on the client we don’t have that capability, so we need to be more selective in how we get the log messages. These fall into several categories, and can individually be ENABLED or DISABLED:

  • Dev mode specific - these only work when in dev mode, as they use either GWT.log or the Java console to emit their messages:

      <set-property name="gwt.logging.systemHandler" value="ENABLED" />
      <set-property name="gwt.logging.developmentModeHandler" value="ENABLED" />
    
  • Browser console - Firebug, Chrome’s Inspector, IE’s Developer Toolbar, etc. These show the messages in the browser in either web or dev mode, but are not visible unless the user opens one of these consoles directly.

      <set-property name="gwt.logging.consoleHandler" value="ENABLED" />
      <set-property name="gwt.logging.firebugHandler" value="ENABLED" />
    
  • Browser popups - the idea can be useful to enable users to see what is in the log, though the default implementation always renders below most GWT and GXT widgets, so isn’t often very useful; more on this at the end.

  • And finally, the server - we can send messages to the server, and ask it to log them as it normally would for later review. This option enables you to save logs to a file, though remember that all users will be logging together to the same file. This is the only option that is disabled by default, as it requires a properly configured server to receive those logs, using the com.google.gwt.logging.shared.RemoteLoggingService RPC interface.

      <set-property name="gwt.logging.simpleRemoteHandler" value="DISABLED" />
    

Sample Application

This is a sample that uses most of the logging defaults. All the browser and dev mode consoles are used and remote logging is left disabled, and the popup is disabled since it won’t work well with GXT. The log level is set to FINEST to report all possible messages, and additionally GXT itself is told to emit all internal details.

<!-- In the Project.gwt.xml file, after the GXT inherits statement -->
<!-- Ask for all possible messages -->
<set-property name="gwt.logging.logLevel" value="FINEST" />
<!-- Write messages to browser consoles and to the jvm and dev mode -->
<!-- Note that these are the defaults, so we don’t actually need to list them -->
<set-property name="gwt.logging.consoleHandler" value="ENABLED" />
<set-property name="gwt.logging.firebugHandler" value="ENABLED" />
<set-property name="gwt.logging.developmentModeHandler" value="ENABLED" />
<set-property name="gwt.logging.systemHandler" value="ENABLED" />
<!-- Disable the popupHandler when using GXT layouts, they draw above -->
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<!-- Leave RPC logging disabled, as we aren’t setting that up in this example -->
<set-property name="gwt.logging.simpleRemoteHandler" value="DISABLED" />
<!-- Ask GXT to log all internal details -->
<set-property name="gxt.logging.enabled" value="true" />

Below is a simple logger example. First the logger is instantiated and later logger.log(...) is called to produce logging output according to the options selected in the application module.

    // Example using logging
    public class TestLogging implements EntryPoint {
      // instantiates a logger
      private static final Logger logger = Logger.getLogger(TestLogging.class.getName());

      @Override
      public void onModuleLoad() {
        logger.log(Level.INFO, "Phase A: So far so good.");
        logger.log(Level.WARNING, "Did this forget something?");

        TextField field = new TextField();
        String value;
        try {
          value = field.getValueOrThrow();
        } catch (ParseException e) {
          logger.log(Level.SEVERE, "Field Error", e);
        }

        if (logger.isLoggable(Level.INFO)) {
          // Anything in this statement will not get compiled when logging is off.
          logger.warning("Do something extra while logging.");
        }

        if (GXTLogConfiguration.loggingIsEnabled()) {
          // Anything in this statement will not get compiled when logging is off.
          logger.info("Do something GXT logging is on.");
        }
      }
    }

More Configuration

By disabling or enabling the logging feature entirely, you are telling the compiler to either leave all logging statements in or remove them entirely. The log level is less specific; even if you set the log level to WARN, just as in non-GWT Java, some code might change it back to FINEST by calling Logger.getLogger("").setLevel(Level.FINEST). This further enables you to set different log levels for different parts of your application. In the same way, you can specify handlers for particular loggers, setting one log level for internal code and another for third-party code, etc. But once logging has been disabled, that code should compile out entirely.

Building Your Own Log Handler

Building your own handler is simply a matter of implementing java.util.logging.Handler and doing something with the data. Here is an example in GXT that generates a Grid that could be added to part of the application to show all log messages. Note that until you add the handler to a logger (and in this case, probably the root logger), it will not start recording logged messages.

public class GridHandler extends Handler implements IsWidget {
  public interface LogRecordProperties extends PropertyAccess<LogRecord> {
    @Path("millis")
    ModelKeyProvider<LogRecord> key();

    ValueProvider<LogRecord, String> message();
    ValueProvider<LogRecord, String> loggerName();
    ValueProvider<LogRecord, Long> millis();
    ValueProvider<LogRecord, Level> level();
  }

  private static final LogRecordProperties properties = GWT.create(LogRecordProperties.class);
  protected final ListStore<LogRecord> store = new ListStore<LogRecord>(properties.key());
  private Grid<LogRecord> grid;

  public GridHandler() {
    grid = getLogRecordGrid(getLogRecordColumnModel(getColumnConfigs()));
  }

  @Override
  public void publish(LogRecord logRecord) {
    store.add(logRecord);
  }

  // these methods do nothing, since we don't need to think about files
  @Override
    public void flush() {
  }

  @Override
    public void close() {
  }

  @Override
    public Widget asWidget() {
    return grid;
  }

  private Grid<LogRecord> getLogRecordGrid(ColumnModel<LogRecord> columnModel) {
    Grid<LogRecord> grid = new Grid<LogRecord>(store, columnModel);
    grid.getView().setForceFit(true);
    return grid;
  }

  private ColumnModel<LogRecord> getLogRecordColumnModel(List<ColumnConfig<LogRecord, ?&gt;> columns) {
    return new ColumnModel<LogRecord>(columns);
  }

  protected List<ColumnConfig<LogRecord, ?&gt;> getColumnConfigs() {
    List<ColumnConfig<LogRecord, ?&gt;> columns = new ArrayList<ColumnConfig<LogRecord, ?&gt;>();
    columns.add(new ColumnConfig<LogRecord, String>(properties.loggerName(), 10, "Logger"));
    columns.add(new ColumnConfig<LogRecord, Level>(properties.level(), 10, "Level"));
    columns.add(new ColumnConfig<LogRecord, String>(properties.message(), 10, "Message"));
    columns.add(new ColumnConfig<LogRecord, Date>(new LongToDateValueProvider<LogRecord>(properties.millis()), 10, "Timestamp"));
    return columns;
  }

  public void clear() {
    store.clear();
  }

  public static class LongToDateValueProvider<M> implements ValueProvider<M, Date> {
    private final ValueProvider<M, Long> base;

    public LongToDateValueProvider(ValueProvider<M, Long> base) {
      this.base = base;
    }

    @Override
    public String getPath() {
      return base.getPath();
    }

    @Override
    public Date getValue(M object) {
      return new Date(base.getValue(object));
    }

    @Override
    public void setValue(M object, Date value) {
      base.setValue(object, value.getTime());
    }
  }
}

Conclusion

Logging adds additional process output information which can provide invaluable process information during development, after development and while debugging. It can be completely compiled out, or added back to assist in debugging in production, and can be customized for your particular application to render exactly the details you need.

Further reading

GWT Logging

GXT 3.x