Fundamentals

To create a web application with Echo, you will create two Java classes: an ApplicationInstance and a WebContainerServlet. The ApplicationInstance will represent the state of a single user-instance of the application. The WebContainerServlet is a Servlet-derivative that will process HTTP connections from web clients and instantiate new ApplicationInstances for new users.

The ApplicationInstance

Purpose: An ApplicationInstance represents the state of the user interface of a single user. Every user who visits an Echo application will have his/her own unique instance. Echo will store the ApplicationInstance in the servlet container's user session, so the instance will be available until the user exits the application or the session times out due to inactivity.

Implementation: ApplicationInstance is an abstract class, requiring a single method to be defined by the developer: init(). The init() method is invoked to initialize the state of the user interface for a new user. It must return an Echo Window object representing the state of the initial window of an application. An application's implementation of the init() method should create a new Window and configure it for a new user by assembling a hierarchy of Echo components within it. The following code example shows an ApplicationInstance implementation for a simple "Hello, world!" application:

public class HelloWorldApp extends ApplicationInstance {
    public Window init() {
        Window window = new Window();

        ContentPane contentPane = new ContentPane();
        window.setContent(contentPane);

        Label label = new Label("Hello, world!");
        contentPane.add(label);
        
        return window;
    }
}

Properties: Because an ApplicationInstance represents a single user of an application, it is safe to add properties to this class in your implementation with the expectation that the properties will be unique on a per-user basis. For example, if an application required authentication, it might be practical to store the login name of the user in a property of the ApplicationInstance object.

The WebContainerServlet

The WebContainerServlet class is an Echo-specific derivative of the Java Servlet Specification's HttpServlet class. The WebContainerServlet is responsible for processing all requests from the client-side Echo engine, including rendering the initial HTML page, handling XML synchronization services, and sending graphic images to the client. All such client interaction work is done behind the scenes. As an application developer, your only required interaction with the WebContainerServlet class is to create a derivative implementation that returns new ApplicationInstances. The following example shows a WebContainerServlet that returns new ApplicationInstances of the previous "Hello, world!" application:

public class HelloWorldServlet extends WebContainerServlet {
    public ApplicationInstance newInstance() {
        return new HelloWorldApp();
    }
}

Components

An Echo user interface is built by assembling Components into hierarchies. A "Component" is any object which extends from the nextapp.echo2.app.Component class, such as Column, Label, Button, TextField, or WindowPane. Components may have multiple child Components, but only one parent Component. Hierarchies are created and manipulated using the add() and remove() methods of individual Components. The following code example demonstrates the building of a hierarchy by adding two Buttons to a Column:

Column buttonColumn = new Column();
Button button1 = new Button("First Button");
buttonColumn.add(button1);
Button button2 = new Button("Second Button");
button2.setBackground(Color.GREEN);
buttonColumn.add(button2);

Properties, Styles, and StyleSheets: A Component class will typically have properties that define its appearance and behavior. As shown in the above example, the second button's background color property has been set to the color green. In addition to setting properties on individual Components, some Component properties may be set using the concepts of Styles and StyleSheets, which are discussed in later chapters of the tutorial.

Children: Only certain Components, typically those used for layout purposes, can contain other Components. Examples of such containers include WindowPane, Column, Grid, and ContentPane. Some Components may also specify requirements that they only be added to specific types of parent Components, or that child Components be limited to a specific number and/or specific type. The API documentation for each Component will describe any such issues in detail.

Hierarchy Roots: The root component of an Echo2 User Interface must be a Window. A Window component represents the top-level browser window containing the application. A Window may have only one child component, and that child must be a ContentPane. The ContentPane represents the region within the Window, to which child components may be added. A ContentPane also generally only allows one child component (there are exceptions to this rule, such as in the case of adding WindowPanes to ContentPanes, which will be discussed later in this documentation).

LayoutData

The "LayoutData" property of a Component is used to describe how a Component should be rendered by its containing parent Component. For example, in the previous code snippet showing two Buttons being added to a Column, we might use a LayoutData to inform the Column as to how the Buttons should be aligned. By setting the LayoutData property appropriately, we could cause the Column to right justify the first button and left justify the second.

Each container Component has its own LayoutData implementation. For example, a Grid has GridLayoutData while a Column has ColumnLayoutData. To configure the alignment of Buttons within a Column, we would thus set the LayoutData of each Button to an appropriately configured ColumnLayoutData instance. For example:

Column buttonColumn = new Column();
Button button1 = new Button("First Button");
ColumnLayoutData button1ColumnLayoutData = new ColumnLayoutData();
button1ColumnLayoutData.setAlignment(new Alignment(Alignment.RIGHT,
        Alignment.DEFAULT));
button1.setLayoutData(button1ColumnData);
buttonColumn.add(button1);
Button button2 = new Button("Second Button");
button2.setBackground(Color.GREEN);
buttonColumn.add(button2);

Events

Components which capture user input may fire events when input occurs. In order to notify an application of events, a Component will provide methods to register and unregister event listeners that correspond to a specific type of event. Other types of Echo objects, such as data models, also use this event pattern to indicate when state changes occur.
As an example, Button components provide the capability to register ActionListeners which will receive ActionEvents when a button click occurs (note that Echo defines its own ActionListener/ActionEvent objects, rather than using the Java AWT/Swing APIs).

The following code snippet shows a button with a registered ActionListener. The ActionListener's actionPerformed() method will be invoked when the user clicks the button. The provided ActionEvent parameter will describe the particulars of the event, such as the source (Button) that generated it (in this trivial case we do not use this information). The event listener in this case defines behavior to change the text of the Button in response to the user clicking it.

final Button button = new Button("Please click me.");
button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        button.setText("Thanks!");
    }
});

Anonymous inner class listener implementations: The above code uses an anonymous inner class to provide the event listener implementation. While many developers may recommend against the use of anonymous inner classes in general, they can be extremely valuable for simple event listener implementations as shown above.

Event-driven: At this point it's worth revisiting the notion that Echo is an event-driven framework: the dynamics of an Echo application are defined by registering events that cause specific behaviors to occur in response to user actions. The entire control flow of an Echo application is defined using events. While a web developer using a conventional framework might define a hyperlink to navigate the user to a new screen of the user interface, an Echo developer would instead create a Button with an ActionListener that defined behavior to update the state of the user interface appropriately when it was clicked.