Adept Development System

Adept - Application Developer Enterprise to Personal Transition - A system to leverage corporate design (graphic, interface and code) and development skills to produce shrink-wrap software packages.

http://marringtons.com

Friday, April 29, 2005

The JavaScript Model

In all the web services projects I have been involved with, JavaScript has been used as a separate tool to make the GUI prettier. In some cases it has done essential validation and form processing - although most architects object to having any functional dependence on JavaScript. Frameworks, for example Sofia, may generate JavaScript to be sent as part of a page.

Adept is completely different. It has been designed to use the browser to create a system with the speed and interactivity of a native application. To do that it makes heavy use of DHTML - and JavaScript is a core component of DHTML. In fact, JavaScript is the D which stands for Dynamic.

Adept changes the architecture also. In a traditional web system the browser is merely a renderer, with everything occuring on the server side. In contrast, using Adept, two layers of the GUI tier run on the browser - and are designed and documented with this clarity in mind. JavaScript becomes part of the design, not just an add-on that is tolerated when necessary.

So, how is this accomplished? When Adept loads, it includes an invisible iFrame that's used to post or send information to the server. Both the invisible iFrame and visible panels work the same way. They're filled by the response to a servlet call. The servlet will set up the DHTML environment (ensuring that any required JavaScript is loaded), pass a HTML template of the same name, then generate any JavaScript required to activate the DHTML.

In the case of the communications frame the HTML portion is usually empty, but it can contain patterns that are loaded into the calling visible frame by JavaScript System methods. JavaScript specific to the servlet will fill in dynamic content for a panel, expand lists, open new panels or generally change the UI in some way.

For the visible panels, the HTML is that which is seen. The default JavaScript activates it so that form actions and links post to the communications frame. Then Servlet specific JavaScript is run to do whatever dynamic work needs to be done. The idea of the sample template is that it works stand-alone: designers can create it, add sample data, show it to the customer and generally treat it as their own. They can continue to do so even after it is integrated into the system. The developer activates it by adding IDs and additional properties to elements, but that's all. The system will remove the sample data during the load and turn the static page into something dynamic. Additionally, the page designer can continue to maintain the pages as long as she leaves the additional properties as-is. I consider this as far better than current practice where the developer turns design HTML into JSP or ASP, while the GUI designer loses access.

The JavaScript model uses objects to provide separate namespaces, with the object name matching the file name in classic Java fashion. Each of these namespace classes has a Java mirror of the same name, as does each public method inside the class. Apart from allowing the server to call these methods, the Java also provides full Javadoc documentation.

All the Javascript is loaded into the top Adept frame and made available to all panels as part of the initialisation process. The initialisation ensures that new JavaScript files are loaded before the code that needs them is executed. The effect is to provide a load-on-demand infrastructure similar to that used by Java.

Check out the Javadoc provided by the Adept system for examples of JavaScript usage from both the server and the client.

Friday, April 15, 2005

The Adept Client Model

Adept is a client/server system based on web server technologies. Specifically it uses a browser as the container for the top GUI tier. So far this is no different from Apache and Tomcat - HTML along a TCP/IP wire. Many systems developed on these platforms use DHTML and JavaScript to provide frills and icing. Here Adept diverges from the standard model - it takes a step further and uses DHTML to provide shrink-wrap software like features to the web browser.

An Adept application is run in a 3-frame window. The top frame is a desktop where all the action happens. Below it is a narrow tab-bar frame for maximised windows. The communications frame is invisible for working applications, but shows while in debugging mode. It has an iFrame for server communications and space for log messages. It also has a number of debug specific links such as record and playback.

Panels

On the desktop there can be one or more panels holding forms, pages or any other form of browser supported displays. The panel itself consists of a label tab, border, resize point, menu and content iframe. When a panel covers the full desktop, it's label moves to the desktop tab area. Panels can be moved and resized - or programatically locked into place. Each panel can hold other panels allowing for a heirarchical grouping of applications and functions.

Menus

Any panel can have menu and button bars above the content. In most cases these will be full-screen parent panels containing other panels with more application detail. This, however, is convention and not restricted by the application. The panel tab and resize graphic also have a special single-depth context menu to minimise, maximise or close a panel.

Server Communications

Inside the communications frame are one or more iframes that are used to communicate with the server. Clicking on a link or submitting a form on a panel will not normally replace information on that form directly (as a web application does). The information is sent to the server through the server iFrame. The response may or may update the calling form - typically by changing specific information, rather than replacing all the contents in a blanket update. The result is a more interactive feel than the usual web application. On a working Adept application there may be up to 3 of these iFrames:
  1. Client to Server: always exists so that links and form submits can talk with the server without forcing a reload of the calling panel. Any link or button in a form with an attribute of active will be activated to talk through this iframe.
  2. Recording: In debug mode it is possible to record actions as they occur for later playback, or for creation of interactive unit test code. The recording goes through a separate frame so that it can monitor but not effect normal server communications.
  3. Server to Client Control: There are situations in interactive applications where the browser display needs updating based on asynchronous changes from the server. The technology is often called a pushlet since it pushes information from server back to browser. Examples are timers, counters, stock or news tickers and graphs. Once a pushlet is requested it opens a connection between browser and server through it's own iFrame. All pushlet information is passed from server to client through this connection - and passed on to their respective panels.

Process Flow

An Adept system will open with at least one menu on one full-screen panel that will act as a desktop. Some menu items will open child panels that will have an iFrame to load with HTML from a HTML template. The template is loaded with a servlet that can add additional functionality - such as filling in fields. If the panel includes an activated form, a post will go through a hidden iFrame back to the server. Responses from the server are flagged with the panel so they can be used to update panel data. A response can also include commands to update other panels, create new panels, hide panels and anything else needed to create a modern interactive application.

Friday, April 01, 2005

Session and Conversation Data

This article is an extension of Data Lifetimes in my Software Development blog.

What is Session Data

Session data is data that lives as long as the session is active. A session is active from the moment the browser first connects or a user logs in until the session times out - typically 20 minutes of inactivity after the user leaves the site or closes the browser.

What is Conversation Data

Conversation data is much shorter lived. It can exist from the moment a browser makes a get or post request to the server and goes out of scope as soon as the browser receives a response from the server. Conversation data is mostly used to return information, validation and error messages to the browser for display.

How Session Data is kept in Adept

Class com.marringtons.util.Session contains a static private com.marringtons.util.Cache instance that will hold session data and release it if not used for a specific interval (defaulting to 20 minutes). If a browser has never connected before, create() is called to generate a unique key. This is saved in a permanent cookie on the browser called "AdeptSession". This key is used to retrieve a session or create a new one at the start of each conversation. With this method the same session will be used by all instances of the same browser for the user currently logged in at the OS level. Closing the browser and reopening (before the timeout) will continue to use the same session. Using the same browser after the session timeout will still retrieve persistent session data.

This all changes if the user logs into the Adept system. A session-only cookie of the same name ("AdeptSession") is created with the user's name. This is used to retrieve session information - and isn't a security risk since the user is authenticated against the session at the start of each conversation.

In either case, because the thread is named for the session, a static getInstance() without parameters can be used to retrieve the session data dictionary.

Session session = Session.getInstance();

 

How Conversation Data is kept in Adept

Conversation data is kept in a much simpler static private Map, with the conversation keyed on the thread name. Since a conversation is sequential, it will use the same thread from beginning to end.

Manipulating Session Data

Retrieving the object from the session depends on it's scope and type. An object can have a scope of:
  1. Class scope. Use classScope();
  2. Package scope. Use packageScope();
  3. Global scope. Use globalScope();

Use the above methods to create a static final field in the calling class and use that to access session level data.

Objects can be one of three types also:

  1. Transient entries: are lost when the session closes.
  2. Closeable entries: have a close method that is called when the session goes out of scope. Data class implements com.marringtons.util.Closeable.
  3. Persistent entries: are saved on disk and retrieved the next time the session is activated (a user logs in). Set by final parameter in scope creator method.
Because session data can have type, scope, persistence and closeability, a Session.Key is created to contain it. For efficiency, this should be a static final field in the class that's making use of it.

Manipulating Conversation Data

Because a conversation is relatively short-lived, the com.marringtons.util.ThreadData class is much simpler. There are getters that create a new instance if needed, those that provide a default and those that use the class name as key name (for local scope). There is also, of course, a matching setter - although it's rarely used since most instances are created automatically using a default constructor.

Session Data: A Real-World Example

private static final Session.Key recordingSessionKey
  = Session.classScope( Tape.class, "taping",
    null, Session.transientLifetime);

private static final Session.Key storageSessionKey
  = Session.classScope( Tape.class, "tape",
    null, Session.persistentLifetime);

public static Tape load( Session session)
  { return (Tape) session.get( recordingSessionKey); }

public static Tape create( Request request)
  {
    Tape tape = load( request);
    if (tape == null)
      tape = new Tape();
    else
      tape.commands.clear();
    tape.startPage
        = request.getParameter( "startPage");
    request.session.put( recordingSessionKey, tape);
    return tape;
  }

 

Conversation Data: A Real-World Example

/**
 * @return Messages associated with this thread.
 * Usually used as error messages to be displayed
 * in response to a browser request.
 */
static public Messages getThreadInstance()
  {
    return (Messages) ThreadData.get( className, 
        Messages.class);
  }