An Alchemist Generated Web Application Uncovered

Author: Martyn Cutcher

email martyn@cutthecrap.biz

website www.cutthecrap.biz

The Alchemist can now generate a web application as well as java source code and documentation.

The Web Applications it generates will of course have a common user interface. The challenge was to determine an interface that not only could be useful, but would be a "good" interface to any of the data models it presented.

Opinions of how well this has been achieved will be varied, but any feedback is appreciated.

What Is Generated?

The Alchemist generates java source code and "ant" build files. The "root" build file provides a target "dist" that will build a "war" file.

This "war" file should be copied to the "webapps" directory of a "tomcat" web server.

Tomcat, when running, will expand the "war" file after which the web application should be accessible.

If a file northwind.war is built, then the application will be accessible via a browser using:

http://localhost:8080/northwind

This will bring up the "login" screen.

Logging In

The first time you access the system there will be no user registered.

You will have to define one or more users before you can log in. To do that you need to instead "login" to the "User Manager" by following the "manage users" link.

The default "User Manager" password is "admin". You are advised to change this after your first login.

After successfully entering the password the User Manager interface is displayed.

Now you can reset the User Manager password and create a new user.

Once you have defined at least one user, you can "return to the logon screen" and enter the user name and password you have created.

This will bring up the main MetaView interface:

The selections on the left panel provide access to several system elements.

The "MetaView" element is that currently displayed. It introduces the "MetaView" web application and states which model is being edited and when it was generated. A link is provided to the javadocs that were generated when the java code was compiled.

The "Help" element provides a guide to using and customising the web application, it does not provide in-depth information, but should be enough to get started with.

The "Model" could be considered as a "user friendly" version of the javadocs, here is a snippet of the display:

The "Workspace" is the most interesting element. This provides access to the data model, to be able to create, modify and read the data contained.

The "Workspace" interface has been designed to be visible in a browser on a 1024 by 768 screen, here's what the Northwind workspace looks like:

This interface has a single "control pane" and three tiled "inspector panes". It has been through many iterations. For a while "inspectors" were floating wiindows that were created as needed, but in use I discovered that I normally ended up creating three windows to be arranged so that all could be viewed and accessed. Despite the unconventional appearance it was apparent that it was far more convenient to tile the inspectors as they are now presented.

This decision was not taken lightly - honestly the windowing system did look pretty neat :-). I am aware that it looks unconventional, but in use it works very well.

The reason that three inspectors are needed is that much use is made of "drag and drop" to make object associations. The tiled inspectors fit very well with this functionality. We are all aware of problems dragging files around between windows that are partially obscured. Tiling removes this as an interaction issue.

Three inspectors also provide a good balance between having sufficient flexibility when maintaining multiple focussed objects, against the complexity of managing many overlapping windows.

Okay, that's enough of attempting to justify the interface, let's take a closer look at one of the inspectors:

This is currently inspecting an object of class "Business" with the label "Northwind". The "home" icon will focus on the "root" system object - which happens to be the same object since the inspectors by default focus on the "root" object.

The main content pane provides access to the properties of the focussed object. Let's see what happens when we enter some text:

After entering a single letter 'R' in the "PostCode" property control the border has been coloured red. This feedback is provided because a "type restriction" was placed on the "PostCode" property of "postcode", when generating the code the Alchemist accesses a restrictions.xml file that defines "postcode" to match the following regular expression:

^[A-Z]{1,2}[0-9]{1,2}( [0-9][A-Z]{2})?$

Once we have entered a valid term other things happen:

A "submit update" button appears to let the user know that they can update the object with valid data. We can select this now, or continue to enter data in other property fields. Once we do select "submit update" the button will be hidden again, but something else will pop up in the control pane:

On any update, a database "transaction" is begun. Once created all other updates will be carried out within the same transaction until either "Save" or "Revert" is selected.

This pattern of editing properties, "submitting updates" and "saving" to "commit" the current transaction defines most of what you do.

But you also need to "create" objects. Let's select the "Contacts" pane within the inspector:

The set of "Contacts" is currently empty, but we can choose "Create Contact" to change this:

Once created, the inspector will immediately "focus" on the newly created object (with a new transaction being created if one is not already in progress).

The new "contact" can now be edited as before.

Let's create a few more contacts and have a look at the "Contacts" set from the root "Northwind" object:

In creating ten contacts we have populated the display pane - the description "ordered by Name" seems correct since all the contacts have been sorted by their "Name" property. Let's add another and see what we get then:

The "classifier" now displays an alphabetical based hierarchical browser to drill down to the items needed, let's select "Bb":

...and we get to see all the Contacts with Name properties whose values begin with "B". As the numbers of these get bigger, so the classifier will introduce extra layers into the hierarchy. It should be easy to work out that six "clicks" will provide access to millions of objects.

Drag And Drop

Let's jump ahead and assume we have created a "Product", called "Widget", when it may look like this:

You can see that the association property "Supplier" is "<not set>". We can set this by "dragging" a reference to some supplier, from wherever we might happen to find the reference - as the focussed object of an inspector pane, a member of a list or some other association:

As you can see, making this modification has caused the "Submit Update" button to pop up again. You may also have noticed the x beside some associations. This is present if the model allows the value to be "null".

For some creation methods, object references are required. For example, to create an "Order" a "Customer" is required, and to create an "OrderItem" a "Product". These too are provided using "drag and drop".

Using "drag and drop" pervasively in this way removes the need for the subsidiary "browse" dialogs that complicate most user interfaces.

Deleting Objects

Just drag an object reference to the waste bin - or "trash can" if you prefer.

Formulas

Object properties may also be defined by formulas. In this case the value is not editable. Here is an inspected "OrderItem":

The "Label" property is computed from the "Name" of the "Product" at the time the OrderItem was created, and the value of the "Quantity" property. Here is the definition from the xml file that was used to generate the system:

<attr label='Label' type='java.lang.String' islabel='true'
      formula="(str $Product!$Name [ $Quantity ])"/>

Similarly formulas are used to define the "UnitPrice" and "Price" properties.

<attr label='UnitPrice' type='java.lang.double' 
      formula="$Product!$Price"/>
<attr label='Price' type='java.lang.double'
      formula="(* $Quantity $UnitPrice)"/>

GPO formulas have more in common with spreadsheet formulas than traditional database computed values and triggers. Their values are recalculated when the values on which they depend are changed.

Customized Reports

Apart from simple customization by amending the stylesheets, it is straightforward to define a "form" or "report" for specific object instances.

This is specified in the login.jsp file in the "custom" directory. In the "Northwind" application the file contains the following:

<webview:formspec>
  <webview:form label="Invoice" match=";Order;" form="invoice.jsp" target="page"/>
</webview:formspec>

In plain English this means that for any instance who's class name is in the ';' delimited list, make an association with the jsp file indicated and label it with the value specified.

When you inspect an "Order" instance, you should see that there is a reference added to the "Invoice" form on the tab control panel:

The "target" attribute is set to either "page" or "local", if "local" then the form will be rendered within the inspector content, if "page" it will be displayed in a new browser window. One obvious reason for a customized form is for output to a printer.

There is no magik and the jsp file indicated must be coded by hand, but using the gpo jsp tags provided it is not difficult to access the data. When writing the jsp code it is a good idea to be able to view the javadocs that describe the interfaces available. Here is a snippet from the "invoice.jsp" file:

<%@ taglib uri="/tags/gpo" prefix="gpo" %>
<%@ taglib uri="/tags/rpc" prefix="rpc" %>

<%@ page import="alchemy.northwind.intf.*" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>

<rpc:reply title="Invoice">
  <gpo:gpo id='order' parameter='id' type='alchemy.northwind.intf.IOrder'>
    <%
      // get the business, customer and delivery information
      IBusiness business = order.getBusiness();
      IContact cust = order.getCustomer();
      IContact deliverTo = order.getDeliveredTo();
    %>

And here is the snippet where the order items are listed:

  <h2>Details:</h2>
  <table border="1" width="100%" cellpadding="3" cellspacing="0">
  <tr><th width="70%">Product</th><th>Unit Price</th><th>Quantity</th><th>Price</th></tr>
  <%
    IOrderItemIterator items = order.getOrderItems();
		
    while (items.hasNext()) {
      IOrderItem item = items.nextOrderItem();
      %>
      <tr>
        <td><%=item.getProduct().getName()%></td>
        <td><%=item.getQuantity()%></td>
        <td><%=item.getUnitPrice()%></td>
        <td><%=item.getPrice()%></td>
      <%
    }
  %>
  </table>
	
  <h2 align="right">Total Due: <%=order.getPrice()%></h2>

You should notice that accessing the Northwind objects is far more similar to accessing so called "Business tier" objects than retrieving data from a database. This is the whole basis for GPO.

Other Stuff

There are a number of other features that could be examined here, but the best course of action for those interested is to download the example wars from the Cut The Crap downloads page and have a play for yourself.

If you are intrigued further, then you should download the full distribution (in fact not much bigger than the war files), and follow the Odyssey introduction.