body { margin:0; padding:0; font-family:times; font-size:9pt; } p { margin-top:5; margin-bottom:5; font-weight:plain; font-family:serif; font-size:9pt; } h1 { margin-top:5; font-size:16pt; font-weight:bold; text-align:center; font-family:sans-serif; } h2 { margin-top:20; font-size:10pt; font-weight:bold; text-align:left; font-family:sans-serif; } pre { color:#993333; font-size:9pt; } code { color:#993333; } .section { text-align:justify; padding:5; }
An Alchemist Generated Web Application UncoveredThe 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 http://localhost:8080/northwind This will bring up the "login" screen.
Logging InThe 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 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
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 ^[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 DropLet'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 ObjectsJust drag an object reference to the waste bin - or "trash can" if you prefer. FormulasObject 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
<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)"/>
Customized ReportsApart 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 <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
<%@ 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 Other StuffThere 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 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. |