The New Internet Application

Object-oriented programming languages such as Smalltalk and C++ arose in the 1980s, just in time to support the first graphical user interfaces beginning to appear. By the 1990s many tool vendors had created eloborate object-oriented frameworks to allow developers more easily to create GUI applications, shielding them from the low-level non-object-oriented GUI application programming interfaces. Borland's Turbo C++ contained an intricate set of objects for creating GUI-like interfaces soley in text mode. Borland later released a complete object-oriented framework for windows, the Object Windows Library (OWL), which eventually was relegated to obsolescence by widespread acceptance of Microsoft's similar yet competing framework, the Microsoft Foundation Classes (MFC). As Java became popular as an Internet-related language, Sun introduced a complex and highly object-oriented GUI framework name Swing. Microsoft, on the other hand, introduced yet another framework, Windows Forms, to be used in their .NET platform primarily with their new C# language—which in turn was designed by the former architect of Borland's Delphi and its elegant Visual Component Library (VCL) framework.

As the Twenty-First Century dawned, the new platform of choice was the Internet, driven primarily by the HyperText Markup Language (HTML). While the Internet in concept was revolutionary, its rise to popularity was made possible through the simplicity of HTML—anyone with a simple text editor could create a few web pages and link them together. The simplicity of HTML, along with the diverse levels of standards-compliance and poor interoperability of browsers, meant that any complex web functionality was a far cry from the standard GUIs common only a decade before. It goes without saying that the plethora of existing GUI frameworks were a moot group in the face of static text pages.

The first attempts to create dynamic interaction on the web came through templating and then through scripting. Sun's JavaServer Pages (JSP) and Microsoft's Active Server Pages (ASP) allowed symbols inserted into an HTML page to be transformed into content on the fly by the server. Sun introduced the idea of a servlet, a piece of code that would sit at a web address and spew back the entire HTML page from scratch. In fact, the entire JSP processing engine was itself a servlet designed to parse and manipulate JSP templates. But attempts such as these (including patterns that allowed a servlet and a series of JSPs to act in a sort of Model/View/Controller arrangement) still fell short of the rich GUI frameworks of the past.

But HTML programming with Java continued to evolve. The Struts open-source framework, followed by Sun's JavaServer Faces (JSF), attempted to create more of a component-based user interface architecture, although at heart these components were extensions of the template/script frameworks of servlets and JSP. Any sort of real-time interaction between components required complex setup and special go-between classes: the "backing beans" of JSF, for example. Within the last few years, the mixture of technologies now known as Ajax have made it clear that the web can be a real-time interactive application platform, providing rich user interfaces similar to those found on the desktop. Internet applications, even more so than their desktop counterparts, can be large, complex, distributed, and multi-user. The need for comprehensive, object-oriented Internet application frameworks is now more evident than ever. The Guise™ framework, introduced here, was created to fill that need .

Introduction to the Guise™ Framework

Guise™ is an Internet application framework that supports transparent web rendering with Ajax. The name "Guise" could be considered an acronym for "Graphical User Interface, Simple and Elegant", but its name also reflects a primary impetus for its creation: an alternative to JavaServer Faces. Guise is more than yet another Ajax toolkit—it is a complete framework built from the ground up to provide robust, secure, and rich Internet applications. The creation of Guise has taken many lessons from both Swing and JSF, as well as a host of other GUI frameworks, to produce a framework that is powerful and works in plain Java. Several aspects of Guise make it a unique and compelling basis for Internet applications:

framework
Guise is a true framework, not just a toolkit or library, providing a context that guides the entire application structure.
applications
Guise creates true Internet applications, not just a series of web pages, that interact with the user in a manner similar to desktop applications.
Ajax
Applications created with Guise have rich user interfaces that function similar to desktop programs, but in a manner transparent to the programmer. A developer creates a Guise application without writing a single line of HTML or JavaScript. Guise supports the most common browsers, including IE 6, IE7, Firefox 1.x, Firefox 2.x, and Safari 1.3.x.
simple
Guise applications use standard, simple Java constructs. There is no need to create special marshalling classes or "backing beans". Just create instances of Guise classes (or your own custom classes) as you normally would, listening for events by registering normal event listeners.
elegant
The entire Guise framework has been written from the ground up to provide an elegant, consistent, object-oriented platform, taking and improving upon the best ideas from frameworks such as Java Swing, OWL, and MFC. The Guise classes use the latest Java language features such as generics and type-safe enums. Guise is abstracted from the actual rendering language (e.g. XHTML in a browser), allowing other rendering platforms (e.g. Java Swing) to be added in the future with little or no code changes to developer applications.
standards
Guise goes out of its way to be standards-compliant. Generated markup is XHTML compliant. Configuration files use RDF serialized in XML. Guise is completely internationalizable, and provides facilities throughout to ease the process of providing localized application content.

The quickest way to see Guise in action is to browse to the BlueCross of California BeneFits Insurance for Small Business site, which is powered completely by Guise. Follow the instructions for a Quick Quote (using a California zip code such as 94123) to see flyovers, on-the-fly validation, pop-up calendars, and sliders that update insurance prices in real time. Even the few Flash components on the front page were included using existing Guise components for embedding Flash.

Guise is available from http://www.guiseframework.com/, and is now open source under the Apache License Version 2.0. The Guise web platform is based upon the standard J2EE servlet architecture and requires Java 6.0 or later.

Hello, Guise™!

Following a long tradition of tutorials, let's jump right into the creation of a Guise application by showing the words, "Hello World!" on the screen.

package com.example;

import com.guiseframework.component.*;
import com.guiseframework.component.layout.RegionLayout;

public class HelloWorldPanel extends LayoutPanel
{
  public HelloWorldPanel()
  {
    super(new RegionLayout());
    setLabel("Guise\u2122 Demonstration: Hello World");

    final Heading helloWorldHeading=new Heading(0);
    helloWorldHeading.setLabel("Hello World!");
    add(helloWorldHeading);
  }
}

Technically, we don't even create a new Guise application type here—we use the default Guise application type, and provide a customized panel to place in the Guise application frame. Let's look at some of the major sections of this application's main panel:

class HelloWorldPanel extends LayoutPanel
Create the panel by extending a standard Guise panel class, LayoutPanel.
super(new RegionLayout())
Construct the panel by specifying how it lays out its child components. In this case, we indicate that the panel should be divided into regions, defined by the RegionLayout class.
setLabel(…)
Each component allows a label to be specified. Labels are used differently depending on the context; here, the label of this main panel will be used as the title of the page in the browser.
new Heading(0)
Create a new component, Heading, specifying that a top-level heading (level zero) should be used. This component will be rendered as the <h1> XHTML element in the browser.
helloWorldHeading.setLabel("Hello World!")
Set the label of the heading. The label of the heading component, rather than specifying the title to show in the browser, indicates the text to show for the heading content.
add(helloWorldHeading)
Add the heading to the panel. Because we specify no preferences, the RegionLayout will place the heading in the center of the panel by default.

That's all the Java source code needed to display a panel containing a heading, "Hello World", but obviously more must be done before we can actually navigate to the application in a browser. Let's start from the beginning and look at how to install Guise, and then go on to look at how to configure the Hello World application we just created.

Installing Guise™

Before installing Guise, make sure you have the following required environment:

In addition, these instructions assume that you have a Java servlet container hosting a web application stored at /server/webapp/, with your web application definition file stored at /server/webapp/WEB-INF/web.xml. We also assume that you want your Guise application mapped to /webapp/example/.

  1. Install the compiled Guise library in the application classpath.
  2. Install the JavaMail library in the web application classpath.
  3. Install the Apache Commons FileUpload 1.2 and Apache Commons IO 1.3.1 libraries in the web application classpath.

Setting up the Application Description Document

With Guise installed, let's get back to setting up the Hello World application. In order to tell Guise how a user should browse to the "Hello World" page, we must create a Guise application description document indicating at a minimum which application navigation paths map to which components. Guise application description documents use URF PLOOP, a simple, consistent data framework, stored in the TURF format. Although Guise application description documents will be described in more detail later, here is the application description document needed for our sample application which may be placed in the file /server/webapp/WEB-INF/example-application.turf, alongside your web.xml file:

`URF:
  "guise"~<java:/com/guiseframework/>,
  "example"~<java:/com/example/>
;¤
  *guise.DefaultGuiseApplication:
    destinations=[
      *guise.ComponentDestination("helloworld", example.HelloWorldPanel)
    ]
  ;
.

At the heart of this application description document, we specify a destination that maps to a component using (guise.ComponentDestination). For this destination, we map a path of helloworld to our panel class, com.example.HelloWorld.Panel.

Configuring web.xml

Lastly, in your servlet /server/webapp/WEB-INF/web.xml file you'll need to configure Guise and reference your application description document. First, add an HTTP Guise session manager as an HTTP session listener before the first <servlet> definition:

<listener>
  <description>The class that manages Guise sessions in an HTTP servlet environment.</description>
  <listener-class>com.guiseframework.platform.web.HTTPGuiseSessionManager</listener-class>
</listener>

Next, add a servlet definition for your Guise application using the GuiseHTTPServlet. You can have as many Guise applications defined as you like, each using GuiseHTTPServlet, as long as each is mapped to a different path. For each Guise application, indicate the separate Guise application description file relative to web.xml

<servlet>
  <description>Example Application</description>
  <servlet-name>exampleApplication</servlet-name>
  <servlet-class>com.guiseframework.platform.web.GuiseHTTPServlet</servlet-class>
    <init-param>
      <param-name>application</param-name>
      <param-value>example-application.turf</param-value>
    </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>exampleApplication</servlet-name>
  <url-pattern>/example/*</url-pattern>
</servlet-mapping>

Start up your J2EE container, and you'll have a Guise application that receives requests at http://localhost/webapp/example/. You can now access the Hello World example at http://localhost/webapp/example/helloworld.

Hello, User!

Now that we're comfortable with static content, let's look at how easy it is to respond to events and update content on a web page. Because Guise uses Ajax automatically behind the scenes, communication with the server will occur in the background and changes will be made to the web page dynamically, without causing a page reload. Let's modify the Hello World panel slightly to create a Hello User panel:

package com.example;

import com.guiseframework.component.*;
import com.guiseframework.component.layout.*;
import com.guiseframework.event.*;
import com.guiseframework.validator.RegularExpressionStringValidator;

public class HelloUserPanel extends LayoutPanel
{

  public HelloUserPanel()
  {
    super(new FlowLayout(Flow.PAGE));
    setLabel("Guise\u2122 Demonstration: Hello User");

    final Label greetingLabel=new Label();
    greetingLabel.setVisible(false);
    add(greetingLabel);

    final TextControl<String> userInput=new TextControl<String>(String.class);
    userInput.setLabel("What's your name?");
    userInput.setInfo("Enter a name that does not start with whitespace.");
    userInput.setValidator(new RegularExpressionStringValidator("\\S+.*", true));
    add(userInput);

    final Button greetButton=new Button();
    greetButton.setLabel("Greet");
    greetButton.addActionListener(new ActionListener()
        {
          public void actionPerformed(final ActionEvent actionEvent)
          {
            if(HelloUserPanel.this.validate())
            {
              final String user=userInput.getValue();
              greetingLabel.setLabel("Hello, "+user+"!");
              greetingLabel.setVisible(true);
            }
          }
        });
    add(greetButton);
  }
}

As you can see, detecting an event such as a button press requires simply installing an event listener into the relevant control. Besides event listeners, this panel contains several differences from the Hello World example:

new FlowLayout(Flow.PAGE)
Instead of laying out this panel based upon regions, we use a FlowLayout to flow all added components along the page vertically, specified by Flow.PAGE. (In most locales, lines flow horizontally and pages flow vertically.)
new Label()
Instead of showing the greeting in a Heading component, we'll show the information in a Label component. The resulting web page will use an XHTML <label> element. Our choice is merely a matter of preference.
greetingLabel.setVisible(false)
We'll initially make the greeting label invisible, as we don't yet know the name of the user.
new TextControl<String>(String.class)
A TextControl is a component that accepts text input. Like other ValueControls, it contains a value input by the user. The text control uses generics to indicate the type of value it contains (here a String), because although the user enters text, the actual value contained in the control may not be textual—it may be Boolean, for example (represented by the text true and false).
userInput.setInfo(…)
Many components also allow separate information to be specified which, like component labels, will be used differently depending on the context. In most cases, a component's information will be presented in a tooltip when the mouse pointer is over the component.
userInput.setValidator(…)
Applications usually need to restrict values entered by users. Rather than programmatically checking values, all Guise value controls allow declarative restriction via the installation of a Validator that automatically ensure correct values are entered, displaying errors when appropriate. This particular validator restricts the string to the regular expression \S+.* (any non-whitespace character followed by zero or more characters).
new Button()
Unlike ValueControls, a Button is an ActionControl which allows the user to initiate an action.
greetButton.addActionListener(…)
An action control such as a button generates an ActionEvent, which can be detected by installing an ActionListener in the control. When the button is pressed, the ActionListener.actionPerformed(com.guiseframework.event.ActionEvent) method is called, which can respond as necessary.
validate()
All components have the ability to validate themselves; components with nested components know how to validate their children as well. Validating the entire panel will cause all controls to validate themselves. The TextControl will use its installed Validator, if any (although usually the validator has already been invoked when the value was changed). If this method returns true, all components have valid values.
userInput.getValue()
The value of every ValueControl can be retrieved through the getValue() method; the value returned does not need to be cast, as the control already returns the correct types through the use of Java generics. Here the value is used to update the user's name in the label and make the label visible, if it isn't already.

Cool Guise Features

The preceding whirlwind tour should have given you a feel for working with Guise. Future articles will take a slower, more comprehensive look at the different pieces of the Guise framework, from high-level architectural concepts to powerful interaction facilities. To whet your apetite, here are a few of the advanced yet simple-to-use features Guise has to offer:

Regular Expression Destinations
Guise destinations can be mapped with regular expressions. A panel can be mapped to a path pattern such as /[^\\/]+\\/help/, to service paths test/help and anything/help in this example.
Automatic WebTrends-Compatible Logging
Simply add dcsid=webTrendsSDCID to your Guise application description to get automatic generation of WebTrends-compatible log files.
Changing the User
User login and logout can be performed by changing the current principal through a call to GuiseSession.setPrincipal(java.security.Principal).
Changing the Locale
It's easy to change to a different language; just call GuiseSession.setLocale(java.util.Locale) and the current session will reorientate controls and load new text and other resources as needed.
Containers are Collections
Each Guise Container is a Java Iterable; you can iterate through all the child components of a panel, for instance, just by using for(final Component<?> child:panel).
Control Prototypes
Guise offers special prototypes that allow easy, standardized creation of various components that share attributes and functionality. By creating a single "save file" prototype, for instance, you could then easily create buttons and menu items that automatically inherit the correct (internationalized) labels and icons from the prototype, that perform the prototype's action when selected, and that become disabled and enabled automatically as the prototype deems appropriate.
High-Level Semantics
Guise allows you define information semantics rather than simply describe functionality. Assign information to a component using GuiseComponent.setInfo(java.lang.String) and a tooltip will appear by default. Set a description using GuiseComponent.setDescription(java.lang.String) and you'll get a flyover if you also turn on flyovers using GuiseComponent.setFlyoverEnabled(boolean).
Bookmarks
Bookmarking is easy. If you want your component to do something special when the user visits a page for the first time, implement the NavigationListener interface; the URI parameters will be passed as a Bookmark in the NavigationEvent object.