Bambookit Home    Middleware

Chapter 19. Middleware

Simple WebForm with real-time data submit to the table example (PHP/mySQL, JSP/Oracle)

The application above is a simple demonstration of the web form! The data gets submitted to a middleware script that updates a mySQL database. Then the data in the table gets synchronized with database table every 60 seconds. You can manually refresh the table by hitting the 'Refresh' button. The table may be cleared. The status bar is supplied. The 'View Source' button displayes the XML source used in this example. Script samples for PHP/mySQL and JSP/Oracle can be found below.

Step 1: Submit a web form

Enter the data and submit

Step 2: Table view of data

View and sort the data, or manually refresh

Step 3: Clear the table

Clear the table, or view the source

Submit data to a web form

The web form in the first step consists of 2 edit controls (first name, last name), a checkbox, a drop down list, a popup calendar and a submit button

Note that all the widgets in the first step (except for the submit button) are named
.. setName="f1" .. (firstname)
.. setName="f2" .. (lastname)
.. setName="f3" .. (notify)
.. setName="f4" .. (salutation)
.. setName="f5" .. (Date Of Birth)

You should be aware of TWO attributes in the button control
<Button setShape="10,190,80,25" setLabel="submit" setData="f1,f2,f3,f4,f5" setFontStyle="bold" addActionTarget="action,table,addRow='*,$f1,$f2,$f3,$f4,$f5', action,this,loadGui='insert.php,true', action,table,addToSize='0,22'"/>

The 'setData' is used to append the values of the widget when submitting using loadGui or loadUrl

This sequence states that on an action loadGui using the script 'insert.php', update is set to true.
The update flag indicates that NO NEW WIDGETS ARE CREATED, the script will match only the existing widgets on the document and update their attributes. In this case we are only updating the Status bar widget to notify us the response from the server.

Here is the insert script in php

<?php // retrieve any values sent to the script if (!empty($_GET)) {extract($_GET); } else if (!empty($HTTP_GET_VARS)) {extract($HTTP_GET_VARS);} if (!empty($_POST)) {extract($_POST); } else if (!empty($HTTP_POST_VARS)) {extract($HTTP_POST_VARS);} $message="Error connecting to database"; //Connect to the database $connection = @mysql_connect ( "localhost", "bambooki_myuser", "mypassword" ); if ($connection) { @mysql_select_db("bambooki_mydatabase"); // create table $create_table_string = "CREATE TABLE events (". "id INTEGER NOT NULL AUTO_INCREMENT, ". "f1 VARCHAR(50), ". "f2 VARCHAR(50), ". "f3 VARCHAR(50), ". "f4 VARCHAR(50), ". "f5 VARCHAR(50), ". "PRIMARY KEY (id))"; @mysql_query ( $create_table_string ); // insert row $insert_statement = "INSERT INTO events ". "(f1, f2, f3, f4, f5)". " values ". "('".$f1."', '".$f2."', '".$f3."', '".$f4."', '".$f5."')"; if (mysql_query ( $insert_statement)) { $message="row added."; } else { $message="unable to add row."; } } ?> <Widget setName="status" setLabel="<?php echo $message; ?>"/>

It has to be noted that Bambookit GUI is middleware-agnostic.
It does not force a middleware technology on the enterprise, any middleware is compatible with Bambookit GUI

To demonstrate,

Here is the delete script using JSP and an Oracle database

<% Connection connection = null; try { // Load the JDBC driver String driverName = "oracle.jdbc.driver.OracleDriver"; Class.forName(driverName); // Create a connection to the database String serverName = ""; String portNumber = "1521"; String sid = "bambooki_mydatabase"; String url = "jdbc:oracle:thin:@" + serverName + ":" + portNumber + ":" + sid; String username = "bambooki_myuser"; String password = "mypassword"; connection = DriverManager.getConnection(url, username, password); } catch (ClassNotFoundException e) { message="could not find the database driver"; } catch (SQLException e) { message="could not connect to the database"; } if (connection != null) { try { Statement stmt = connection.createStatement(); // DELETE delete_table_string = "DELETE FROM events"; stmt.executeUpdate(sql); message="table cleared!"; } catch (Exception e) { message="table not cleared!"; } } %> <Widget setName="status" setLabel="<% out.print(message); %>"/>

Here we add the row DIRECTLY to the table instead of waiting for a refresh. The '*' is used since we do not KNOW what value the database has assigned the row or EVEN if it was accepted!

This is required to EXPAND the table so we can ADJUST THE SCROLLBARS correctly as we add each row. We add '0' to the width and '22'to the height (the default height of items are set to 22)

Table view of data

Let's jump right into it. The table is wrapped in a view (this will enabled the scrollbars on them). <View setShape="140,40,250,145" setBackground="white" setBorder="flat" setName="view" setPollLoad="60,selecttable.php" setCache="false">
The last two attributes are the most interesting to take note of:

setPollLoad is similar to a loadGui with the update set to false
The difference is this script is called every sixty seconds.

Some of you may say, hey wait a sec, isnt there a setPoll attribute!
Yes but that attribute ONLY UPDATES the widgets and will not accept Widget Creation if the objects do not exist. Hence we use the setPollLoad instead

This is very important to set
Because the script generated panel is cached by default, and upon seeing SUBSEQUENT requests for this 'file' (selecttable.php), the cached copy is used instead. This defeats the purpose of generating a dynamic view of the application

Table creation

Now onto the topic of tables
Tables are a composition of Columns, in this case this composition is Listboxes
There are a few attributes that we need to note, so the behaviour is understood

The first listbox
<Listbox setBorder="none" setLocation="0,0" setWidth="40" setShowResize="false" setName="list1" attachToContainer="table,true,false,true,false">
The first column is NOT resizable so we use the setShowResize="false" to prevent the columns from bieng resized. Also the visual indicator that shows the column is resizable is removed

The attachToContainer is used for managing the SIZE of the table and thus adjusts the SCROLLBARS. We indicate that the listbox is attached to the container table, and that we are only interested in adjusting for the left and right sides of the view. attachToContainer="widgetname, left, top, right, bottom", whenever the column is resized the horizontal scrollbar is adjusted, however in the case of the first listbox, since it is NOT resizable it is a redundant attribute

The second column has another interesting attribute. The attachToWidget, if the attachToContainer adjustes the size of the attached widget, this one adjusts the LOCATION of the attached widget.

In the listbox, named 'list2', we attach ourselves to list1. This means that any changes to the left or right hand side location of list1 is translated directly to list2. (list2 is ONLY listening for changes along the x axis, the left and right side displacements)


There are two ways to view the data in the table, wait 60 seconds OR manually force the refresh (this does not reset the 60 second timer). We call the same script in both cases. Here is the XML for the button 'refresh'

<Button setShape="310,190,80,25" setLabel="refresh" setFontStyle="bold" addActionTarget="action,view,loadGui='selecttable.php,false'"/>
The addActionTarget reads, on the event action, execute the method loadGui on the widget named 'view'. The loadGui loads an xml document selecttable.php into that panel. The panel, 'view' is cleared first before we begin to download the document into this widget. Remember the cache is turned off on the widget 'view' so the script will ALWAYS be loaded.

Load Table dynamically

Now you may have noticed above that the table is ordered in a column first. BUT the database always presents us a row at a time, how do we populate the script without having to retrieve all the data before populating the XML script. For the answer to that question view the script below


<?php $message="Error connecting to database"; //Connect to the database $connection = @mysql_connect ( "localhost", "bambooki_myuser", "mypassword" ); if ($connection) { @mysql_select_db("bambooki_mydatabase"); $select_table_string = "SELECT * FROM events"; $result = @mysql_query ( $select_table_string ); } ?> <Table setAnchor="true,true,false,false" setOpaque="false" setShowHeader="true" setShowResize="true" setLocation="1,1" setSize="440,25" setName="table"> <Listbox setBorder="none" setLocation="0,0" setWidth="40" setShowResize="false" setName="list1"> <Header setLabel="id"/> </Listbox> <Listbox setBorder="none" setLocation="40,0" setWidth="80" setName="list2" attachToWidget="list1,true,false,true,false" attachToContainer="table,true,false,true,false"> <Header setLabel="firstname"/> </Listbox> <Listbox setBorder="none" setLocation="120,0" setWidth="80" setName="list3" attachToWidget="list2,true,false,true,false" attachToContainer="table,true,false,true,false"> <Header setLabel="lastname"/> </Listbox> <Listbox setBorder="none" setLocation="200,0" setWidth="80" setName="list4" attachToWidget="list3,true,false,true,false" attachToContainer="table,true,false,true,false"> <Header setLabel="title"/> </Listbox> <Listbox setBorder="none" setLocation="280,0" setWidth="80" setName="list5" attachToWidget="list4,true,false,true,false" attachToContainer="table,true,false,true,false"> <Header setLabel="notify"/> </Listbox> <Listbox setBorder="none" setLocation="360,0" setWidth="80" setName="list6" attachToWidget="list5,true,false,true,false" attachToContainer="table,true,false,true,false"> <Header setLabel="DOB" addActionTarget= <?php echo "\""; if ($row=mysql_fetch_array($result, MYSQL_NUM)) echo "null,table,addRow='".$row[0].",".$row[1].",".$row[2].",".$row[3].",".$row[4].",".$row[5]."',null,table,addToSize='0,22'"; while ($row=mysql_fetch_array($result, MYSQL_NUM)) echo ",null,table,addRow='".$row[0].",".$row[1].",".$row[2].",".$row[3].",".$row[4].",".$row[5]."',null,table,addToSize='0,22'"; echo "\""; mysql_free_result($result); ?> /> </Listbox> </Table>
Pay attention to
..Header setLabel="DOB" addActionTarget=..
After defining the table, the listboxes and the headers we execute methods using the addActionTarget

In this case the event is 'null', this means execute the method right away, as soon as this 3-tuple is parsed.

echo "null,table,addRow='..
We addRow to the table as soon as this statement is parsed.


The above script is the basis for the more advanced applications
Since we synchronize the data on the database, we never corrupt the data. However the database example could just as easily be a message queue (MQSeries). Locally the client gets immediate feedback, the '*' indicates the data has not synchronized with the database, and yet the system is responsive enough for users who are accustomed to desktop apps, this architecture works well even for those on 28.8k modems.

Any additional questions please email

Bambookit Home    Bambookit GUI Tutorial