Simplified Development of Web Applications with armidale

Shayne R Flint [HREF1], Department of Computer Science [HREF2] , Australian National University [HREF3], ACT, 0200. shayne@cs.anu.edu.au

Clive V Boughton [HREF4], Department of Computer Science [HREF2] , Australian National University [HREF3], ACT, 0200. clive@cs.anu.edu.au

Abstract

The World Wide Web is increasingly being used, across all sectors of the Information Technology industry, to host distributed interactive applications. Many of these applications are built using a combination of different, and sometimes inappropriate, technologies. Often the final products are complex, and the associated likelihood of increased development, integration, deployment and maintenance problems lead to high overall lifecycle costs.

This paper outlines the requirements, design, implementation and testing of armidale, a set of open source programs and libraries designed to radically simplify the development, deployment and use of web applications that have rich graphical user interfaces. Armidale applications are developed, using conventional programming techniques and the armidale API, as if they were stand-alone programs. These programs can then be run on stand-alone computers or on an armidale server. When running on a server, armidale applications display their GUI on client computers across the internet (or intranet). A high level, light weight message protocol between the server and its clients ensures that armidale applications respond well to user interaction.

Background

Capability Dynamics

The work reported in this paper is part of a larger research effort to develop a technique which aims to increase the likelihood that decisions made throughout, and at all levels of, an organisation contribute in a coordinated way to satisfying the organisation's requirements and those of its stakeholders (Flint 2001). The approach, called Capability Dynamics, is based on the use of Capability Dynamics Models (Flint 1999) which are developed and maintained by the organisation to provide decision-makers with an organisation wide, shared and evolving understanding of the systems comprising the organisation and its environment, how the capabilities of these systems interact to satisfy stakeholder requirements, and how all these things are likely to evolve with time and in response to change.

The development of these Capability Dynamics Models is likely to require significant effort. In addition, the authors believe that a sense of ownership in their development and use will be important to the success of Capability Dynamics. It was therefore proposed (Flint 2001) that Capability Dynamics Models be developed by collaboration amongst all stakeholders within an organisation, as well as researchers and consultants.

Tool Support.

In order to support the collaborative development of Capability Dynamics Models, the authors are developing a computer based Distributed Capability Dynamics Modeling Tool which is intended for day-to-day use throughout and at all levels of an organisation. The tool has been designed to allow everyone within an organisation to capture their own view of those systems with which they interact or are a part, and to run agent based simulations to describe the way in which capability develops over time, and in response to actual, proposed and planned changes. In addition, the proposed tool will provide facilities that allow stakeholders to discuss differences in opinion, identify those differences that are important and, if required, resolve them.

It is hoped that this collaborative approach, supported by computer based tools, will result in the emergence of Capability Dynamics Models for entire organisations formed from the knowledge and individual contributions of their people.

An Internet/Intranet based solution.

The distributed and collaborative nature of the tool support discussed above suggests that a web based implementation of the Distributed Capability Dynamics Modeling Tool would be appropriate. This provided the motivation that led the authors to look at current web application development approaches and to then develop armidale.

Existing approaches to web development

Popular approaches to the development of web applications use various combinations of well established technologies including HTTP, HTML, client side scripts such as JavaScript [HREF5] and server side scripts such as PHP [HREF6]. It is also common to use server side technologies such as JSP [HREF7] and ASP [HREF8] to generate HTML and client side scripts on-the-fly in response to HTTP requests from clients.

More recently, a number of newer technologies have emerged, including XUL [HREF9], which aims to simplify the development of client side GUIs, and .NET [HREF10] which supports the development of web services using SOAP [HREF11]. As is often the case, these technologies build upon the growing mountain of HTTP, HTML and scripting technologies described above.

Difficulties with Existing approaches to web development

In order to develop effective web applications, developers need to master many of the above technologies within the context of individual projects. In addition, developers need to deal with complex issues of compatibility between different versions of the technologies, and in particular, the compatibility of different web browsers with the various scripting languages and variations of HTML used throughout the internet. To a lessor extent, some of these issues also need to be understood by end users.

The authors believe that the need to master this ever-increasing set of technologies and their interaction is likely to increase development, integration, deployment and maintenance problems associated with the life cycle of web applications. In addition, the authors find it strange that the use of such inherently complex and poorly engineered approaches is rarely questioned and that 'new' ideas and approaches often add even more complexity to what appears to be an unsustainable foundation for the development of increasingly complex web applications.

The need for a simple open source solution

In light of the above issues, the authors believe that development of the Distributed Capability Dynamics Modeling Tool could benefit from a radically simplified web application development approach. The only real ongoing efforts to offer such an approach are those by Bullant [HREF12] and Droplets [HREF17]. Bullant is an Australian company that has developed a set of proprietary technologies which enable the development of sophisticated and highly scalable web applications by eliminating what they call the 'infrastructure zoo' of HTML and associated add-ons. The Droplets technology, which was recently introduced to the authors, is another commercial web application development technology that eliminates the use of HTML and associated web technologies.

Because of their commercial nature, Bullant and Droplets are unattractive to our ongoing Capability Dynamics research. This view has strongly influenced the design, implementation and testing of the open source armidale system described in the remainder of this paper. It is hoped that other projects can also make use of the armidale technology.

Requirements, Constraints and Design Approaches

Initial requirements for armidale emerged from the wider research discussed above and evolved in an iterative fashion as the system has been developed and used. While additional requirements are likely to emerge during the open source development process proposed for the future, the requirements, as they were at the time of writing, are outlined below along with details of the design approaches used to satisfy them.

Simplified Application Development

Requirement

Armidale shall provide a simple programming model to support the development of interactive applications that are able to run on stand-alone computers or on a server. When running on stand-alone computers, application GUIs shall be displayed on the host computer. Armidale applications installed on a server shall be started by clients connected to the server via the internet or an intranet. In this mode of operation, application GUIs shall be displayed on the connected client computer.

Design

The development of armidale applications does not involve the use of HTTP, HTML or scripting languages of any kind. Instead, armidale applications are written in Java, using conventional programming techniques and the armidale API, as if they were stand-alone programs running in isolation from the internet. That is, the armidale API abstracts the complexities of the internet and platform dependencies away from the concerns of developers as depicted in Figure 1.

Developers using armidale need only learn one programming language (Java), and a simple user interface API. There is no need to learn and become experienced in multiple Web technologies such as HTML, PHP and JavaScript etc. There is no need to understand the way in which these technologies interact and perform on various platforms and in various combinations of versions.

The armidale conceptual design

Figure 1: The armidale conceptual design

When an armidale application is started, it is given a context. This context is used by armidale API factories (Gamma 1995) to determine which implementation of the API should be used for the current execution environment. When an application is started within a platform (stand-alone) context, the factories will return implementations that use a platform API such as Java Swing [HREF13] to create and manipulate GUI objects on the host computer.

When an application is started within a client-server context, the factories will return implementations that communicate with connected clients via the Open Binary Message Protocol (OBMP) described elsewhere in this paper. On the client, platform context implementations are used to display GUI objects so that applications running in a client-server context have the same look and feel as they have when running in a stand-alone context.

Appendix A provides more details on the operation of armidale applications in stand-alone and client-server contexts.

Rich Graphical User Interfaces

Requirement

Application developers shall be able to use armidale to create interactive applications with rich Graphical User Interfaces (GUIs) comprising elements such as buttons, images, lists, tree views, tables etc. Such applications shall have the same look and feel as conventional applications available on user computers.

Design

The armidale API provides mechanisms to create and manipulate the GUI objects listed in Appendix B. In general, the behavior of these objects follows that of corresponding Swing widgets [HREF13].

Platform context implementations of the armidale API make use of platform specific APIs such as Java Swing. The look and feel of GUI objects, is therefore similar to that of applications native to the host platform. Because Platform Context implementations are also used to display GUIs on clients connected to armidale applications running on servers, the look and feel of armidale applications is independent of where the application is actually running.

Figure 2 shows a number of armidale test applications running on a KDE desktop. The applications shown could be running locally or on remote servers over the internet as it makes no difference to their look and feel on the desktop.

Some armidale applications running on a KDE desktop

Figure 2: Some armidale applications running on a KDE desktop

Starting Applications

Requirement

Users shall be able to start armidale applications in the same way as native applications available on the user's computer. In addition, users shall be able to start an armidale application from a launcher by entering its URL or by referring to a list of bookmarked applications.

Design

Armidale applications, whether installed locally or on remote servers, can be started using any of following methods, all of which create an appropriate context (local platform or server) and then run the application within that context. As far as the user is concerned, armidale applications start, look and feel like any other application. The user receives no visible indication of where applications are actually running.

  1. One way to start an application is to use the armidale application launcher. The launcher, which is itself an armidale application, works in a similar way to a normal web browser. The URL of an application is entered into a text box and a button or menu item is used to start the named application. The format of an armidale URL allows the specification of local or remote applications and a bookmarking facility is provided as depicted in Figure 3. More details can be found at the armidale web site [HREF14].
  2. The armidale launcher

    Figure 3: The armidale launcher


  3. Armidale applications can be started using a command line. Locally installed applications are started in the same way as any other Java program. Remote applications can be started by running the armidale.api.RemoteApplication class and passing a URL to it as a parameter.
  4. Desktop icons that reference one of the command lines described above can be used to start local or remote armidale applications.
  5. Finally, armidale applications can be started programmatically by using the armidale.api.RemoteApplication and armidale.api.LocalApplication classes in any Java application. By using these classes to start applications in response to button, menu and image action (i.e. click) events, a set of hyperlinked applications that behave in a similar way to hyperlinked web pages can be established. Users could then browse or 'surf' such applications around the internet.

Platform Independence

Design Constraint

Armidale applications shall be capable of running stand-alone and as server applications on computers running Linux (Intel), Solaris (Sparc), Mac OS X (Power PC) and Windows 2000 (Intel).

Design

The armidale system has been written in standard Java 2 using the Sun Microsystems JDK 1.4.0 (standard edition) and has been designed to run on any JDK 1.3 or later platform. Successful testing has been conducted on Linux (SuSE and RedHat), Solaris 8, Mac OS X and Windows 2000.

Access to third party technologies

Requirement

Armidale shall not restrict the use, by application developers, of third party technologies such as SQL databases and the SWARM agent based simulation system [HREF15].

Design

Armidale applications are developed using standard Java and as such can make use of any available Java API. This includes the JDBC API which can be used to access SQL databases, and the Swarm Java API. The only exception is that user interface APIs such as AWT and Swing should not be used because armidale provides its own user interface API which makes it possible to run armidale applications locally or over the internet or an intranet.

Extensibility

Requirement

Armidale application developers shall be able to add new GUI objects to the armidale system. The implementation of this requirement shall ensure that objects added by one developer are uniquely identified and that they do not interfere with objects created by other developers.

Design

The standard armidale API includes mechanisms to create and manipulate many standard GUI objects such as buttons, lists, tables and icons etc. Each of these GUI objects are implemented by a number Java classes and interfaces. For example the PushButton object is implemented by the following Java interface and classes:

    
    interface armidale.api.gui.PushButton
    class     armidale.api.gui.PushButtonFactory
    class     armidale.api.gui.impl.clientserver.PushButtonClientImpl
    class     armidale.api.gui.impl.clientserver.PushButtonServerImpl
    class     armidale.api.gui.impl.platform.<PLATFORM>.PushButtonImpl
    
    (where PLATFORM is a platform name such as swing)

All of these interfaces and classes, with the exception of the platform implementation classes such as armidale.api.gui.impl.platform.swing.PushButtonImpl, are completely generated by the armidale.utilities.makeclass.Main program based on specifications provided in XML files as depicted in Figure 4. An example of an XML GUI object specification is provided at Appendix D to this paper.

Generation of GUI element source code

Figure 4: Generation of GUI element source code

The platform implementation classes for each GUI object, such as armidale.api.gui.impl.platform.swing.PushButtonImpl, are generated by the armidale.utilities.makeclass.Main program with empty method bodies. It is up to the GUI object developer to implement the bodies of these methods (e.g. the swing implementation of the object). This often involves no more than making simple calls to platform objects such as those provided by Swing.

An important feature of armidale is that the above process can be used by application developers to add new GUI Objects to the system. All that is required is an XML specification of the new GUI object and implementations of the platform specific methods described above. Once a new GUI object has been developed, it can be installed on the client and server computers by copying its class files, or a JAR file containing the class files, to a directory on the user's Java class path. The new GUI objects can then be used by application developers in the same way as the standard objects provided in the armidale distribution.

Note that the armidale API provides a mechanism for applications to check that any non-standard GUI objects required by the application are correctly installed on a client computer before the application starts (see the description at Appendix A). In addition, all GUI objects have a unique Class ID. These Class IDs are 32 bit numbers and will be allocated by the authors in blocks of 100 to interested developers.

Armidale Application Launcher Platforms

Design Constraint

The design of armidale shall make provision for the use of devices such as mobile phones and PDAs as armidale clients.

Design

The armidale.utilities.makeclass.Main program described above is able to generate platform implementation classes (with empty method bodies) for any number of client platforms. At present, only the Swing platform has been fully implemented, but all of the infrastructure is in place to implement other platforms such as Espial [HREF16]. Once a platform API has been implemented for a new device such as a phone or PDA, the armidale application launcher can be used on the new device to start armidale applications running on armidale servers.

Use of Network Bandwidth

Performance Requirement

The armidale system shall minimise the use of network bandwidth. An important motivation for this requirement is that devices such as phones and PDAs may, in future, be used as armidale clients connected to servers via low bandwidth wireless links.

Design

The design of armidale makes use of the following techniques to minimise the use of network bandwidth.

The Open Binary Message Protocol

The armidale system uses TCP/IP to pass messages between clients and servers. In order to minimise bandwidth usage, armidale messages use a simple binary format called the Open Binary Message Protocol (OBMP). Each OBMP message comprises a 32 bit message length and a set of data items including primitive type values such as int, byte, float, double etc., and more complex types like String, Color and Font. Armidale includes an API for constructing and interpreting OBMP messages.

Apart from the minimal use of bandwidth, there are two other reasons for choosing a binary protocol rather than one of the more popular XML protocols such as SOAP [HREF11]. Firstly, our messages are abstracted away from any programmer or user involvement because they are created, transmitted and interpreted in code generated by the armidale.utilities.makeclass.Main program from high level specifications. So the only real requirements on the message protocol are that it be able to transmit the required information and that it be as efficient as possible.

Secondly, despite a common belief to the contrary, XML is nothing more than a human readable format for describing data. If data contained in any kind of message is to be of value, the same meaning must be attached to it by its creator and interpreter. This applies to XML messages as much as it does to any other form of message including binary. XML does not magically add meaning to messages and does not change the fundamentals of communications. So, because armidale messages are unlikely ever to be created or read by humans there is little reason to use XML.

Image handling

When an application creates an Image object it initially has no associated image data and is displayed as a "broken" picture icon. The application can then set the image data by calling the setImageData() or setFile() methods.

When the setImageData() method is called, image data is passed as a parameter and used to create a platform specific image. The implication of this is that in a client-server context, the image data is sent over the network each time the setImageData() method is called.

A more efficient approach is to use the setFile() method which takes the name of a file in the armidale filesystem. This filesystem is simply a directory within the user's home directory called .armidale/filesystem and is created during the installation process.

When the setFile() method is used in a stand-alone context, the contents of the file are used to create a platform specific image. In a client-server context, the name of the file and its date-time stamp are sent to the client. When the client receives the message, it attempts to open a file with the same name in its local armidale filesystem. If the file exists on the client and has the same date-time stamp, a platform specific image is created from the contents of the local file. If the required file does not exist in the client's filesystem, or the date-time stamp is incorrect, then the client will request a copy of the file from the server. The server will then send the file to the client, and it will be saved on the client's armidale filesystem. The contents of the file are then used to create a platform specific image.

The above approach implements a simple, but effective image cache and can be applied to other media types in future.

Handing large data structures

Armidale is able to efficiently display information from very large data structures or models in GUI lists and tables on the client. The technique ensures that only those items that are visible and are needed for smooth scrolling of lists and tables are passed from the server to the client. As a list or table is scrolled by the user, items that are not yet available on the client are displayed as "please wait...". When the user stops scrolling a request is sent to the server for any items that need to be displayed. When the items arrive at the client the "please wait..." messages are replaced with the real data.

Open Source

Design Constraint

Armidale shall be developed as an open source project.

Design

Early versions of armidale were designed and implemented by the authors with the view of making the project open source. The entire system was developed using technologies that would allow armidale to become an open source project.

Armidale has since been released as an open source project. The project is hosted by Source Forge [HREF18], a web site that provides a suite of tools which coordinate the development, distribution, maintenance and use of open source projects, including file transfer services, problem reporting and tracking, support request tracking, and discussion forums etc.

It is hoped that this open source approach will encourage wider use of Armidale as well as its continued development and support.

Implementation

The implementation of armidale has been uneventful. The tools used included SuSE Linux [HREF19], the Sun Microsystems Java Development Kit Standard Edition (version 1.3 and 1.4) [HREF20], the Apache Ant java build tool [HREF21], the JEdit integrated development environment [HREF22] and various Linux tools such as xfig and Gimp. There were no project delays caused by limitations or problems with the tools used.

Functional Testing

Functionality of the armidale system was tested using two test applications. The first, SimpleApp, was intended only to test the basic armidale infrastructure. This covered the armidale API architecture, the armidale application launcher, the ability to run applications in different contexts, and the ability to manipulate GUI objects and to process their events correctly. The annotated source code for SimpleApp is at Appendix C to this paper.

The second test application, GuiTest, was designed to test each of the armidale GUI objects. As GUI objects were implemented, they were added to this test application and as more are developed in the future, they too will be added to GuiTest. A design feature of GuiTest is that individual GUI object tests are implemented in separate classes which can be executed in isolation from the main GuiTest application.

The screen shot depicted in Figure 1 shows the SimpleApp and GuiTest applications along with a number of individual widget test programs.

Table 1 shows the platforms, operating systems and Java versions on which the above applications were tested. While Java 1.4 is the preferred platform, armidale should run on any Java 1.3 or 1.4 platform.

Table 1: Test Configurations

Hardware OS OS Version Java version
Intel PC Linux SuSE 7.3 1.3, 1.4
Intel PC Linux RedHat 7.2 1.3, 1.4
Sun Sparc Solaris 8 1.3
Macintosh G4 Titanium Notebook MacOS X 10.1.3 1.3
Intel PC Windows 2000 1.3, 1.4

Effectiveness

While the design and conduct of credible software engineering experimentation is considered important (Fenton 1994), none has been conducted to test the view that armidale simplifies web application development. Such experimentation was beyond the scope and resources of the armidale project at the time of writing.

Nonetheless, a number of characteristics support the view that armidale simplifies the development and use of web applications. The most important of these is the way in which all aspects of the internet, hardware platform, and operating system are abstracted away from both the application developer and user. When using more traditional web application development approaches, the developer will usually deal concurrently with low level details of the internet including HTML, an array of client side and server side scripting languages, browsers and the many compatibility issues that go with them. Likewise, users of traditional web applications also need to deal with a wide range of compatibility issues and limited capabilities of the web browser model. All of these issues are completely irrelevant to the developer and user of armidale applications, or are abstracted away from the developer behind the armidale API. When we also consider the use of a single traditional object oriented programming language, and the ease with which armidale can be extended, the claim that armidale enables simplified development of web applications would appear reasonably sound.

From a qualitative perspective, the authors experience in developing demonstration and test programs would also support the view that armidale does indeed simplify the whole process of developing, testing, deploying and using web applications. The authors believe that the reader will develop a similar view by walking-through the sample application code at Appendix C, installing the armidale development system available from Source Forge [HREF18] and going through the process of compiling, deploying and using the various demonstration programs included in the distribution.

More information and Availability

The armidale system can be downloaded, under the terms of a BSD open source license, from a web site at http://sourceforge.net/projects/armidale [HREF18]. This web site also provides supporting documentation.

For testing purposes an armidale server and the test applications described above are usually running at http://armidale.anu.edu.au [HREF14].

Future work

While armidale is now ready to support the author's Capability Dynamics research, the following tasks were planned or underway at the time of writing to further its development and use.

  1. The development and use of armidale will be encouraged as widely as possible so as to gather feedback and improvements.
  2. The communications between armidale clients and servers will be encrypted using SSL.
  3. More widgets (e.g. a tree widget) will be developed along with database wrappers to simplify the display of database information in armidale widgets such as lists and tables.
  4. The armidale API documentation will be improved.

A longer term task, may be the development of new platform support for mobile devices.

Conclusions

This paper has described the requirements, design and implementation of software used to develop interactive internet based applications in support of wider research being undertaken by the authors. Because the resulting software appears to have wide general purpose applicability, it has been released to the public as an open source project in the hope that others may find it useful and that it may be enhanced and matured by a group of interested open source developers.

References

Fenton, N. et al. (1994), Science and Substance: A Challenge to Software Engineers, IEEE Software, July 1994.

Flint S. R. (1999), A model which helps control change in dynamically complex purposeful systems", Proceedings of the 1999 Systems Engineering Test and Evaluation conference, Adelaide South Australia, October 1999.

Flint S. R. (2001), Capability Dynamics - An Approach to Capability Planning in Large Organisations, Proceedings of the 2001 International Council on Systems Engineering Symposium, Melbourne, Australia, July 2001.

Gamma, E. et al. (1995), Design Patterns, Elements of Reusable Object-Oriented Software, Addison-Wesley, Reading, MA, USA. ISBN 0-201-63361-2

Hypertext References

HREF1
http://cs.anu.edu.au/~Shayne.Flint/
HREF2
http://cs.anu.edu.au/
HREF3
http://www.anu.edu.au/
HREF4
http://cs.anu.edu.au/~Clive.Boughton/
HREF5
http://www.mozilla.org/js/
HREF6
http://www.php.net
HREF7
http://java.sun.com/products/jsp/
HREF8
http://www.microsoft.com/asp/
HREF9
http://www.mozilla.org/xpfe/
HREF10
http://www.microsoft.com/net
HREF11
http://www.w3c.org/TR/SOAP/
HREF12
http://www.bullant.com.au
HREF13
http://java.sun.com/products/jfc/
HREF14
http://armidale.anu.edu.au
HREF15
http://www.swarm.org
HREF16
http://www.espial.com
HREF17
http://www.droplets.com
HREF18
http://sourceforge.net/projects/armidale
HREF19
http://www.suse.com
HREF20
http://java.sun.com/j2se/
HREF21
http://jakarta.apache.org/ant/
HREF22
http://www.jedit.org

Appendix A: Some Design Details

Armidale applications are based on Java classes that extend the armidale.api.Application class and provide an implementation for the inherited init() method. This init() method is effectively the "main" method of an armidale application. User interfaces are created programmatically using the armidale.api.gui.* API. This API provides a set of GUI object factories (Gamma 1995) that create instances of classes which implement specific GUI object interfaces. For example, the armidale.api.gui.PushButtonFactory creates instances of classes that implement the armidale.api.gui.PushButton interface.

When an armidale application is started, it is given a context. This context is used by the armidale API factories to determine which implementation of the API should be used for the current execution environment. When an application is started within a platform context, the factories will return implementations that use a platform API such as Java Swing [HREF13] to create and manipulate GUI elements on the host computer. When an application is started within a server context, the factories will return implementations that communicate with connected clients via the Open Binary Message Protocol (OBMP) described elsewhere in this paper. On the client, platform context implementations of GUI objects are used so that applications running in a client-server context have the same look and feel they have when running in a stand-alone context.

The following sections provide more detail about the operation of armidale applications in stand-alone and client-server contexts. The information provided is best read in conjunction with the annotated source code for the SimpleApp test program at Appendix C.

Operation in the Stand-Alone Context

If an armidale application is started in a stand-alone environment (i.e. no internet or intranet involved) a Platform Context such as SwingContext will be created and used as depicted in Figure 5 (also refer to the main() method in the sample code at Appendix C). This context will cause the armidale API factories to use Platform Implementations of the API to create objects that translate armidale API method calls directly into corresponding calls to a Platform API (e.g. Swing) thus causing the GUI of the application to be displayed on the stand-alone device.

An armidale application running in a stand-alone context

Figure 5: An armidale application running in a stand-alone context

Operation in the Client-Server Context

The following paragraphs and the block diagram at Figure 6 describe how armidale applications run in the server context. More details, along with the source code for armidale can be found at Source Forge [HREF18].

An armidale application running in a client-server context

Figure 6:An armidale application running in a client-server context

Making the connection

The armidale server (armidale.api.Server) is a very simple Java program. It listens on a specified port for TCP/IP connections from clients. All clients, including the armidale application launcher, make use of the armidale.api.RemoteApplication class to start applications on remote armidale servers. This class is instantiated with the URL of a remote application and any required arguments. When an instance of this class is created, it sends a CONNECT message to the server containing the name of the application the client wants to run and a list of arguments. This application name is in fact the name of a Java class that extends armidale.api.Application, is installed on the server computer, and is visible to the armidale server (i.e. on its class path).

When a server receives a CONNECT message from a client, it creates a Server Context containing a Server Transport connected to the requesting client. This context is then used to create an instance of the requested application class. If everything is OK, a CLASS_INFORMATION message is sent back to the client specifying any special requirements the application may have (such as non-standard widgets). If a problem occurs on the server (such as a missing application class), an ERROR message is returned to the client.

When the client receives the CLASS_INFORMATION message it checks that it is able to satisfy the needs of the remote application (e.g. availability of any special widgets). If all is well, the client will send a CLIENT_OK message to the server and will create a Client Context containing a Platform Context (used to display the GUI on the client) and a Client Transport which waits for and process messages from the connected server.

When the server receives the CLIENT_OK message, it calls the start() method of the requested application instance (which is a Java Thread). When the application is started, the init() method is called. The init() method, defined by the application developer, will usually create a user interface (which will be displayed on the client) and set up callbacks. The application's Server Transport will then wait for and processes EVENT messages from the client.

Object Creation

When an application creates a new GUI object such as a PushButton (using the PushButtonFactory), the server implementation of the object sends a CONSTRUCT message to the client. When the client receives this message it uses the applicable factory to create a instance of the required class within the Client Context. These client implementations contain an associated implementation of the Gui object class within a Platform Context such as Swing. These Platform Context objects display the GUI widgets on the client device.

Changing Object Attributes

When an application modifies an attribute of a GUI object, such as the title of a PushButton, the server implementation of the object sends a SET_ATTRIBUTE message to the client. When the client transport receives this message, it dispatches it to the applicable client implementation which in turn calls the appropriate methods in the associated platform implementation.

Callbacks and Events

Many of the GUI objects supported by armidale are capable of generating events. PushButtons, for example, are able to generate ACTION events. Events are handled in armidale by callbacks which are implementations of callback interfaces that define methods called when an event is generated by a GUI object. These callback interfaces are implemented by the application programmer to define the required response to events. Instances of these classes are registered with the GUI Object of concern.

When a client event occurs (e.g. the user clicks a PushButton), an EVENT message is sent to the server via the Client Transport. When the corresponding Server Transport receives an EVENT message it is dispatched to the subject object which in turn calls the applicable method of each callback registered with it.

Event messages are only sent from the client to the server if one or more callbacks are registered with the subject GUI object.

Appendix B: Gui Objects supported by armidale

    Image
    VisibleObject      
        Component
            MenuBar
            PopupMenu
            Widget
                Action
                    Button
                        MenuItem
                            CheckBoxMenuItem
                            Menu
                        PushButton
                        Toggle
                            CheckBox
                            RadioButton
                    Label
                Desktop
                LabeledWidget
                Slider
                Panel
                    BorderPanel
                    BoxPanel
                    FlowPanel
                    GridPanel
                    RadioButtonPanel
                ListBox
                ComboBox
                ProgressBar
                Table
                ScrollPanel
                SplitPanel
                TabbedPanel
                Text
                    TextField
                        PasswordField
                    TextBox
                Tree
        Window
            Frame
            InternalFrame

    BorderPanelWidget
    GridPanelWidget
    TabbedPanelWidget

Appendix C: SimpleApp Java Source Code

   1:/*
   2: *  Copyright (c) 2000-2002, Shayne R Flint
   3: *  All rights reserved.
   4: *
   5: *  Redistribution and use in source and binary forms, with or without
   6: *  modification, are permitted provided that the following conditions
   7: *  are met:
   8: *
   9: *  1. Redistributions of source code must retain the above copyright
  10: *  notice, this list of conditions and the following disclaimer.
  11: *
  12: *  2. Redistributions in binary form must reproduce the above copyright
  13: *  notice, this list of conditions and the following disclaimer in the
  14: *  documentation and/or other materials provided with the distribution.
  15: *
  16: *  3. The name of the author may not be used to endorse or promote products
  17: *  derived from this software without specific prior written permission.
  18: *
  19: *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  20: *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21: *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22: *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  23: *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24: *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25: *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26: *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27: *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28: *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29: */
  30: 
  31:package armidale.test;
  32:
  33:import armidale.api.Application;
  34:import armidale.api.ClassInformation;
  35:import armidale.api.ProductInfo;
  36:import armidale.api.context.*;
  37:import armidale.api.context.clientserver.*;
  38:import armidale.api.context.platform.*;
  39:
  40:import armidale.api.gui.*;
  41:import armidale.api.gui.constants.*;
  42:import armidale.api.io.Debug;
  43:import armidale.api.io.File;
  44:
  45:import java.io.IOException;
  46:
  47:// This is a simple armidale application which will open a small frame
  48:// with an image and button on it. A callback is defined to display
  49:// a message on the server when the button is clicked.

SimpleApp screen shot

Figure 7: SimpleApp screen shot

  50://
  51:// Because this is an armidale application, it can be run stand-alone or
  52:// over a network using the armidale launcher.
  53://
  54:  
  55:
  56:// All armidale applications must extend armidale.api.Application or an
  57:// extension of it.
  58://
  59:public class SimpleApp extends Application {  
  60:
  61:
  62:  public void init() {
  63:
  64:    // This is where the main work is done. The init() method is declared
  65:    // in armidale.api.Application and is called as part of the application
  66:    // execution (see the armidale.api.Application.run() method).
  67:    //
  68:    
  69:    // We start by creating a frame using the armidale.api.gui.FrameFactory.
  70:    // This factory creates implementations of the armidale.api.gui.Frame
  71:    // interface based on the specified context (usually server or local
  72:    // swing). The context parameter used below is declared in
  73:    // armidale.api.Application (our parent class) and is set by the
  74:    // environment starting the application. In the standalone case this 
  75:    // is set in a main method like the one defined later in this class. 
  76:    // In the case of a server environment, it is set by the armidale server
  77:    // in response to a connection request from a client.
  78:    //
  79:    // The main point here is that the application developer doesn't have to
  80:    // worry about what context is set to. He just passes it as a parameter
  81:    // the the various factories and other API methods.
  82:    //
  83:    Frame frame = FrameFactory.create(context);
  84:
  85:    
  86:    // Armidale handles events using a callback mechanism. When an event is
  87:    // generated by a widget (eg. a user clicks a button) a specific method
  88:    // of each associated callback object is called. For example, when a Frame
  89:    // is closed, a frame close event is generated. This event results in a 
  90:    // call to the windowClosing() method of each associate WindowCallback
  91:    // object.
  92:    //
  93:    // In the following statement we add a callback to the frame to handle 
  94:    // window close events (ie. when the user clicks the close icon at the top
  95:    // of the window). As a convenience, armidale includes a simple class 
  96:    // (armidale.api.gui.WindowCloseCallback) that implements various options
  97:    // regarding the closing of frames. Here we have chosen to stop the 
  98:    // application when the user closes the frame.
  99:    //    
 100:    frame.addWindowCallback
 101:      ( new WindowCloseCallback
 102:              (context, WindowCloseCallback.STOP_APPLICATION_ON_CLOSE));
 103:    
 104:    
 105:    // Complete the initialization of the frame by setting its title, size etc.
 106:    //
 107:    frame.setTitle("Simple Application");
 108:    frame.setSize(new Size(420, 300));
 109:    frame.setAlignment(Frame.CENTER);
 110:    frame.setResizable(false);
 111:
 112:    
 113:    // The image and button will be displayed on a BorderPanel. Create the
 114:    // main panel and set its background color. Note that the Color class here
 115:    // is an armidale.api.gui.Color, not a java.awt.Color
 116:    //
 117:    BorderPanel  mainPanel    = BorderPanelFactory.create(context);
 118:    mainPanel.setBackgroundColor(Color.WHITE);
 119:
 120:    
 121:    // Create the image and set the image data to the contents of a specified
 122:    // file.
 123:    //
 124:    // By using the setFile() method to set the image data, this application, 
 125:    // when run on a server, will ask the client to try and load the image
 126:    // from the client filesystem. If the image is not available on the client,
 127:    // it will downloaded from the server.
 128:    //
 129:    Image        image        = ImageFactory.create(context);
 130:    image.setFile(new File("images/armidaledemo.png"));
 131:
 132:    
 133:    // Create a label, based on the above image and set its alignment
 134:    //
 135:    Label        label        = LabelFactory.create(context);
 136:    label.setImage(image);
 137:    label.setAlignment(Label.CENTER);
 138:    label.setText(
 139:        "<html><body><center>"
 140:      + "<font color=\"black\">Thank you for using <font color=\"purple\">"
 141:      + "armidale</font>.<br><br>"
 142:      + "If you have any comments, suggestions or problems, please "
 143:      + "email the author at <font color=\"blue\">shayne@cs.anu.edu.au</font>"
 144:      + "or register a comment at"
 145:      + "<font color=\"blue\">http://sourceforge.net/projects/armidale.</font>"
 146:      + "</font></center></body></html>"
 147:      );
 148:    label.setTextPosition(Label.NORTH);
 149:
 150:    
 151:    // Add the label created above to the main panel. To add a widget to a 
 152:    // border panel, it needs to be wrapped up in a BorderPanelWidget along 
 153:    // with its position (constraints) on the border panel (ie. north, south,
 154:    // east, west or center). Note that this pattern is used for many of the 
 155:    // armidale panels (eg. GridPanel and GridPanelWidget).
 156:    //
 157:    mainPanel.addWidget
 158:      ( BorderPanelWidgetFactory.create
 159:          (context, label, BorderPanelWidget.CENTER));
 160:
 161:    
 162:    // Following the same pattern of widget creation, we now create a button
 163:    // and set some its properties
 164:    //
 165:    PushButton   testButton   = PushButtonFactory.create(context);
 166:    testButton.setText("Test Events");
 167:    testButton.setPreferredSize(new Size(150, 25));
 168:
 169:    
 170:    // For convenience, armidale provides a Debug implementation of all 
 171:    // callback classes. These Debug classes print details of events generated
 172:    // by associated widgets.
 173:    //
 174:    // In the following code we add to the button a pre-built
 175:    // ActionCallbackDebug object which displays a debug message when the
 176:    // button is pressed.
 177:    //
 178:    testButton.addActionCallback(new ActionCallbackDebug(context));
 179:
 180:    
 181:    // We are now going to create a FlowPanel on which to place the Button.
 182:    // This panel will, in turn, be placed on the main border panel created
 183:    // above.
 184:    //
 185:    FlowPanel    buttonPanel  = FlowPanelFactory.create(context);
 186:    buttonPanel.setBackgroundColor(Color.WHITE);
 187:    buttonPanel.setHorizontalGap(6);
 188:    buttonPanel.setVerticalGap(6);
 189:    
 190:    
 191:    // Now add the button to the FlowPanel. There are no constraints applicable
 192:    // to widgets placed on a flow panel, so we don't use a special wrapper
 193:    // class like the BorderPanelWidget used above.
 194:    //
 195:    buttonPanel.addWidget(testButton);
 196:
 197:    
 198:    // Now add the button panel to the south of the main border panel.
 199:    //
 200:    mainPanel.addWidget
 201:      ( BorderPanelWidgetFactory.create
 202:          (context, buttonPanel, BorderPanelWidget.SOUTH));
 203:    
 204:    
 205:    // Next, we need to add the main panel (with its image and flow panel 
 206:    // containing the button) to the frame. Frames have a tool bar, status
 207:    // bar and content area, each of which contain a single widget. Here we
 208:    // use setContent() to set the content of the frame to the main panel we
 209:    // created above.
 210:    //
 211:    frame.setContent(mainPanel);
 212:    
 213:    // And finaly, we make the frame visible.
 214:    //
 215:    frame.show();
 216:  }
 217:
 218:  
 219:  
 220:  // A main method is required if you want to be able to run an application
 221:  // stand-alone without using the armidale.api.LocalApplication class. 
 222:  // The pattern of this main is fairly common in Java applications, 
 223:  // in that it creates an instance of the enclosing class. In the case of 
 224:  // armidale, it must also set the context in which to run the application.
 225:  // To run the application locally, we need to use the SwingContext which
 226:  // will cause the various widget factories to create objects that are 
 227:  // implemented using swing. These object will therefore be displayed on the
 228:  // local computer.
 229:  //
 230:  public static void main(String[] args) {
 231:    
 232:    // create an instance of SimpleApp
 233:    //
 234:    SimpleApp  app  = new SimpleApp();
 235:    
 236:    // set the apps context to an instance of SwingContext. 
 237:    //
 238:    app.setContext(new SwingContext());
 239:    
 240:    // the application is now ready to go. So start it.
 241:    //
 242:    app.start();
 243:  }
 244:
 245:}
 246:

Appendix D: Sample XML Widget Specification

<ArmidaleClass name="armidale.api.gui.Button"
               extends="armidale.api.gui.Action"
               abstract="yes"
>

  <attribute name="text"
             type="String"
             default="&quot;Button&quot;"
   />
  
  <attribute name="icon"
             type="@armidale.api.gui.Image"
             default="null"
  />

  <attribute name="textAlignment"
             type="int"
             constants="armidale.api.gui.constants.OrthogonalCompass"
             default="EAST"
  />

</ArmidaleClass>