Escolar Documentos
Profissional Documentos
Cultura Documentos
25 Apr 2006
Since OpenLaszlo's open source announcement, many developers have been using
OpenLaszlo to create user-friendly rich Internet applications. Many of these
applications require a database solution to have dynamic data fed to them. Because
OpenLaszlo runs on Apache Tomcat by default, which supports JavaServer Pages
(JSP) and Java™ servlets, Apache Derby is an excellent database to use; it can be
embedded in Java applications since it's pure Java. In this tutorial, you'll build a
management interface to the online shopping console created in Part 1. You'll also
allow orders to be written to the database and enable management to edit, delete,
and add new items to the database via the OpenLaszlo user interface (UI).
grocery store's employees can look up existing orders and modify stock. Derby is
important here, because it's used to supply items for display to home consumers
browsing the online grocery store and to update the stock count of purchased items.
When the Derby database is updated with more stock or more items, the results are
reflected in the online storefront built using OpenLaszlo.
System requirements
You need the following tools to follow along with this tutorial:
OpenLaszlo -- This tutorial uses the latest version of OpenLaszlo, version 3.1.
Download OpenLaszlo 3.1, and get installation instructions for your operating
system.
Apache Derby -- Download Apache Derby, ensuring that the .jar files you receive
are added to your CLASSPATH.
IBM DB2® drivers -- Download IBM Cloudscape™ (IBM DB2 JDBC Universal
Driver, for Cloudscape/Derby) to connect to Derby. Make sure to add the drivers to
your CLASSPATH.
Java SDK -- OpenLaszlo, Apache Derby, and the DB2 drivers require the Java
platform. This tutorial uses Java 1.4.2_09; however, any version later than this
should suffice. Download the Java SDK from Sun Microsystems.
This tutorial was written on a Microsoft® Windows® operating system, but the
differences should be minimal, if any, if you're using a different operating system,
such as Linux®.
Section 2. Overview
Now that you've conquered Part 1 of this series, you're ready to take on Part 2. In
this tutorial, the database needs some changes and a new table.
The next change requires a new table, the shoppingorders table. New orders get
saved in this table via the UI. This table holds four fields: an order ID, the name, the
description, and the price of the product ordered. Next, you'll make these changes
using Derby's ij tool.
First you delete the old table so you can recreate it with the new stock field. Now
create the new table, shown in Listing 2.
This creates the new shoppingorders table. Now when orders get created, you store
With the tables initialized, let's move on to building the application, beginning with
saving orders.
You'll use this paramaterless data set to make dynamic requests. Let's move on to
how to prepare and send a request.
Prepare a request
With the data set declared, you're ready to prepare the request and communicate
with your JSP scripts. To do so, create a method, sendRequest, with parameters
that set up the data set and send off the request, as shown in Listing 5.
<method name="sendRequest"
args="src, queryType, args"><![CDATA[
Debug.write(
"sendRequest",
"src", src,
"queryType", queryType,
"args", args,
"items", items);
items.setQueryType(queryType);
items.setSrc(src);
items.cacheable = false;
items.setQueryParams(null);
items.setQueryParams(args);
items.doRequest();
]]>
</method>
• src specifies the URL to the JSP script that you'll make the request to.
• queryType specifies the HTTP request type, either GET or POST. You'll
use both methods in this tutorial; therefore the sendRequest method is
parameterized here.
• args specifies the arguments to pass to the script, which you'll use in
deleting items from the database.
This method calls the sendRequest method, passing the serviceURL as the URL
to query and fetch the items from the database. Declare the serviceURL attribute,
as shown below:
<attribute name="serviceURL"
type="string"
value="../items.jsp"/>
The prefix ../ refers to the script one directory down, allowing both the customer
and management consoles to access it. That completes the code for querying the
items from the database; however, for easier debugging, you need to hook into the
ondata event for when the items' data set receives its data from the JSP script.
Create the ondata method, as shown in Listing 7.
Listing 7. Creating the ondata event and writing data to the debugger
The reference attribute in the method tag specifies which object to hook into
when listening to ondata events. When the data comes back, it'll be written to the
debugger so you can verify correct functionality of your OpenLaszlo application.
Listing 8. Getter methods for retrieving data to send in the request and send
confirmation of a sent order
<script>
...
function getItemid() {
return this.item.getText();
}
function getDesc() {
return this.description.getText();
}
function getPrice() {
return this.price.getText();
}
function setOrderText() {
this.order.setText('Thank you for your order! It will arrive in 1 to 2 hours.');
}
...
</script>
The first function, getItemid, retrieves the text being displayed in the combobox.
The next one, the getDesc function, retrieves the text in the description, and the
getPrice function retrieves the price. You'll use the setOrderText function to
display a visual confirmation that the Order button was pressed and that the order
request was sent to the database.
First, you communicate to the debugger window that an order is being submitted.
Then you send the request by calling the sendRequest method, which sends the
submitURL, shown below. Next, you indicate the type of query by sending POST as
the transmission method, due to the obvious side effects of writing to the database.
The arguments you send to the request are the name, description, and price of the
item being ordered.
<attribute name="submitURL"
type="string"
value="submit.jsp"/>
You now need to write the submit.jsp script that will receive the name, desc, and
price values in the POST request, and write them to the database. That's all it takes
to send a dynamic request via POST to a JSP script to make appropriate database
modifications. With this functionality in place, you'll use your JSP script to write the
passed values to the database. First, however, you need to start the script, shown in
Listing 10.
First, you import class dependencies, and then you make sure that the needed
parameters to make the request work have been set and passed by your
OpenLaszlo application, as expected. Next, you instantiate the drive and get ready
to make a request. Connect to the database and insert the order into the database,
shown in Listing 11.
try {
Properties prop = new Properties();
prop.put("user", "shopuser");
prop.put("password", "shoppass");
Connection conn = driver.
connect("jdbc:derby:net://localhost:1527/SHOPPING;",
prop);
String sql = "insert into shoppingorders (name, description,"+
" price) values (?, ?, ?)";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setString(1, request.getParameter("name"));
statement.setString(2, request.getParameter("desc"));
statement.setInt(3, Integer.parseInt
(request.getParameter("price")));
statement.execute();
} catch(Throwable e) {
e.printStackTrace();
System.out.println(e.getMessage());
System.out.println("Error executing query");
}
}
%>
<jsp:forward page="../items.jsp" />
First, you set up and connect to the database, as you did in Part 1 of this series.
Then you create the SQL that you'll use to insert the row into the database. You set
each of the unknown ? values in the sql String and then execute the query. If an
error occurs, you'll display it in the server output. The last line redirects the page to
the items.jsp page to reload the items data set in case changes have been made.
Figure 1 shows an executed order.
You can see in the debugger shown in Figure 1 that the order was sent out and the
latest database data was returned. In the last two sections of this tutorial you'll
create the manager's interface, starting with viewing orders.
items on screen to be focused on the current task at hand and causing less
distraction for the employees. In this section you'll create the tabbed layout and learn
how to view placed orders.
<form>
</form>
You'll fill them in with more data later. Now start on the manage.lzx file by declaring
its canvas:
<dataset name="orders"
request="true" type="http"
src="orders.jsp"/>
You'll define the orders.jsp script later in this section. Next create the tabbed layout
for your view, as shown in Listing 12.
Listing 12. The title and tabs for creating the tabbed layout
First, you create the title and menu separator, followed by the tabbed layout
declaration. You can set the title of a tab using the text attribute in the
basetabpane tag. The contents of each tab are placed inside the
<basetabpane...> </basetabpane> tags where you include the other files that
you've created. Now you need to define the viewOrders.lzx form where you'll be able
to view the currently placed orders in the management UI.
<form>
<simplelayout axis="y"/>
<grid datapath="orders:/shopping" contentdatapath="order">
<gridcolumn showheader="false" width="50">
<view bgcolor="#CCCCCC" width="${parent.width}"
placement="header"
height="${parent.immediateparent.height-1}"/>
<text datapath="position()"/>
</gridcolumn>
<gridcolumn width="200"> Name
<text datapath="@name"/>
</gridcolumn>
<gridcolumn width="200"> Price
<text datapath="@price"/>
</gridcolumn>
</grid>
</form>
This form is shown as a table that displays data contained in the orders data set in
the grid tag. A gridcolumn tag displays a column of data, with the first column
showing line numbers by setting its text attribute's data path to position(). The
next two gridcolumn tags display the name and price values, respectively.
Preview the form, shown in Figure 2.
Next, define the orders.jsp script that returns the ordered item data from the
database.
...
String sql = "select * from shoppingorders";
PreparedStatement statement = conn.prepareStatement(sql);
Notice here that the ID, name, description, and price attributes need to be
inside the order tag due to the way they are referenced by the grid. Next, in the final
section, you'll complete the management section of the online grocery store
application by implementing code for the items tab.
<script><![CDATA[
function getData(itemid) {
datapath = 'items:/shopping/item[' + itemid + ']';
this.description.setDatapath(datapath);
this.price.setDatapath(datapath);
this.name.setDatapath(datapath);
this.stock.setDatapath(datapath);
Debug.write(datapath);
}
]]>
</script>
This function retrieves the item from the value of the current data set based on the
value passed to it from the combobox object. Next, declare the dataset, shown in
Listing 16.
Here you also declare the URL from which to retrieve the item data. Next, add the
query method as you did for the customer interface, shown in Listing 17.
<method name="sendRequest"
args="src, queryType, args"><![CDATA[
Debug.write(
"sendRequest",
"src", src,
"queryType", queryType,
"args", args,
"items", items);
items.setQueryType(queryType);
items.setSrc(src);
items.cacheable = false;
items.setQueryParams(null);
items.setQueryParams(args);
items.doRequest();
]]>
</method>
Like before, this method writes to the debugger the data sent to it, sets the
parameters of the items data set, and sends the request off to the desired URL
contained in the src parameter. Now create the ondata method, shown in Listing
19.
"data", items.data);
]]>
</method>
This method gets called when the data from the items.doRequest() call in
Listing 18 returns with data. Now you'll create the form for managing the items.
<form>
<simplelayout axis="y"/>
<view x="50" height="30">
<text text="Add, Edit or Delete Items" fontstyle="bold"
fontsize="17" height="30" />
</view>
<view x="80" height="30">
<text x="0" text="Item:" fontstyle="bold" width="100"/>
<combobox x="100" yoffset="17" defaulttext="Choose an item ..."
width="240" editable="false" id="item" height="17">
<textlistitem datapath="items:/shopping/item"
text="$path{'name/text()'}" id="itemid"
value="$path{'id/text()'}"
onselect="getData(this.getValue())"/>
</combobox>
</view>
<view x="80" height="30">
<text text="Name:" fontstyle="bold" x="0" width="100" height="17"/>
<edittext id="name" x="100" width="240"
text="$path{'name/text()'}"/>
</view>
<view x="80" height="100">
<text text="Description:" fontstyle="bold" x="0" width="100"
height="100"/>
<edittext id="description" x="100" width="240" height="96"
text="$path{'description/text()'}" multiline="true"/>
</view>
<view x="80" height="30">
<text text="Price:" fontstyle="bold" x="0" width="100"
height="17"/>
<edittext id="price" x="100" width="240"
text="$path{'price/text()'}"/>
</view>
<view x="80" height="30">
<text text="Stock:" fontstyle="bold" x="0" width="100"
height="17"/>
<edittext id="stock" x="100" width="240"
text="$path{'stock/text()'}"/>
</view>
<view x="80" height="0">
<simplelayout axis="y"/>
<button text="Update" isdefault="true" x="50"
onclick="canvas.update()"/>
Notice that it's somewhat similar to the form you created for the customer interface,
except that you use editable text boxes rather than just labels. This is so that you
can edit them and then save the data back to the database. A box for the stock is
also added for editing the amount of stock on hand. The last two view boxes hold the
buttons you press to initiate calls to the database. Clicking the Update button
updates the item in the database with the name in the combobox to the name in the
textbox and replaces the description, price, and stock values with the ones in the
text boxes. Clicking the Delete button removes the item in the database whose
name matches the name in the combobox. Also, the Save button is initially disabled;
clicking the Add New button enables it, while also clearing the data in the text
boxes, allowing you to enter new data. The new data will be saved in the database
as a new record upon clicking the Save button, returning the Save button to its
disabled state. Preview this form in Figure 3.
Figure 3 shows the Tomato Soup item being edited. The rest of this section creates
the code behind all of this management functionality, beginning with removing items.
Remove items
Here you implement the method called by clicking the Remove button, the remove
method. (See Listing 21.)
<method name="remove"><![CDATA[
Debug.write("THE NAME TO DELETE",getItemid());
sendRequest(this.deleteURL,
"POST",
{"name" : getItemid()});
]]>
</method>
This sends a request to the deleteURL, shown below. Note as well the
delete.jsp value, which takes the parameter sent in (the name of the item) and
removes it from the database.
<attribute name="deleteURL"
type="string"
value="delete.jsp"/>
You'll define the contents of the delete.jsp script next.
...
if(!request.getParameter("name").equals("")){
...
Connection conn = driver.
connect("jdbc:derby:net://localhost:1527/SHOPPING;",
prop);
String sql = "delete from shoppingitems where "+
"name='"+request.getParameter("name")+"'";
PreparedStatement statement = conn.prepareStatement(sql);
statement.execute();
...
%>
<jsp:forward page="../items.jsp" />
This script follows the same template as the other JSP scripts, with the changes
noted in boldface. First, check that the name parameter was sent as expected. If so,
an SQL statement is set up that removes the matching item from the database. At
the end, a redirect is sent so that your application receives the latest list of items in
the database. Figure 4 shows an item being deleted.
Notice the command to delete the Bread item showing in the debugger. The deleted
item is no longer in the combobox. Next, you'll add functionality to update and edit
items.
<script>
...
function getItemid() {
return this.item.getText();
}
function getName() {
return this.name.getText();
}
function getDesc() {
return this.description.getText();
}
function getPrice() {
return this.price.getText();
}
function getStock() {
return this.stock.getText();
}
...
</script>
You've essentially created five methods to retrieve the currently shown text in each
of the four editable text boxes and the combobox (getItemid). Next, define the
update method, called by pressing the Update button (see Listing 24).
This method calls the sendRequest method, sending the updateURL, shown
below, as a parameter as well as the five parameters needed for the request.
<attribute name="updateURL"
type="string"
value="update.jsp"/>
...
if(!request.getParameter("nameBefore").equals("") &&
!request.getParameter("nameAfter").equals("") &&
!request.getParameter("desc").equals("") &&
!request.getParameter("price").equals("") &&
!request.getParameter("stock").equals("")){
...
Connection conn = driver.
connect("jdbc:derby:net://localhost:1527/SHOPPING;",
prop);
String sql = "update shoppingitems set name=?, description=?,"+
" price=?, stock=? where name=?";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setString(1, request.getParameter("nameAfter"));
statement.setString(2, request.getParameter("desc"));
statement.setInt(3, Integer.parseInt
(request.getParameter("price")));
statement.setInt(4, Integer.parseInt
(request.getParameter("stock")));
statement.setString(5, request.getParameter("nameBefore"));
statement.execute();
...
%>
<jsp:forward page="../items.jsp" />
After making sure that the five necessary parameters for an update request are
received, you create the SQL statement. Then you set each of the five unknowns,
searching for the record whose name matches the nameBefore parameter and
replacing its name with the nameAfter parameter. Its description, price, and stock
also get replaced with the desc, price, and stock parameters, respectively.
Finally, the redirect retrieves this latest information for your application from the
items.jsp script. In Figure 5, an item is shown being updated.
This method enables the Save button and readies the four text boxes for you to type
in new data to save in the database. These are the three JavaScript functions that
will aide you in your task, shown in Listing 27.
Listing 27. JavaScript functions to prepare the form for saving new data
<script>
...
function readyTextBoxes() {
datapath = 'items:/shopping';
this.description.setDatapath(datapath);
this.price.setDatapath(datapath);
this.name.setDatapath(datapath);
this.stock.setDatapath(datapath);
this.description.setText('');
this.price.setText('');
this.name.setText('');
this.stock.setText('');
}
function enableSave(bool) {
this.save.setAttribute("enabled", true);
}
function disableSave(bool) {
this.save.setAttribute("enabled", false);
}
...
</script>
The readyTextBoxes function empties the text boxes, while the enableSave and
disableSave functions enable and disable the Save button, respectively. Next,
define the save method, called upon by clicking the Save button, shown in Listing
28.
This method disables the Save button and then calls the sendRequest method,
sending the request to the saveURL attribute, shown below, along with four
parameters: the name, description, price, and stock of the new item being added to
the database.
<attribute name="saveURL"
type="string"
value="save.jsp"/>
Take a look at Figure 6, which shows the Add New button being clicked.
...
if(!request.getParameter("name").equals("") &&
!request.getParameter("desc").equals("") &&
!request.getParameter("price").equals("") &&
!request.getParameter("stock").equals("")){
...
Connection conn = driver.
connect("jdbc:derby:net://localhost:1527/SHOPPING;",
prop);
String sql = "insert into shoppingitems (name, description, "+
"price, stock) values (?, ?, ?, ?)";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setString(1, request.getParameter("name"));
statement.setString(2, request.getParameter("desc"));
statement.setInt(3, Integer.parseInt
(request.getParameter("price")));
statement.setInt(4, Integer.parseInt
(request.getParameter("stock")));
statement.execute();
...
%>
<jsp:forward page="../items.jsp" />
If the four necessary parameters were sent to the script, name, desc, price, and
stock, then the new item will be inserted into the database. You do so by creating a
SQL statement describing the data of the new item that you want to be inserted into
the database. Then you execute the script and redirect to the items.jsp script, which
returns the latest data in the database. Figure 7 demonstrates saving a new item in
the database.
There you go! Now you have a great start to a fully functional storefront built using
OpenLaszlo and a Derby database.
Section 6. Summary
Now you're an OpenLaszlo expert! You can even communicate with a database,
Downloads
Description Name Size Download method
Part 2 source code derbylaszlo2source.zip
9KB HTTP
Resources
Learn
• Read Part 1 of this series.
• Read the the tutorial "Deploy OpenLaszlo apps on Apache Geronimo with
Tomcat" (developerWorks, March 2006).
• Join the OpenLaszlo rave at laszlosystems.com and openlaszlo.org.
• Get instructions for installing OpenLaszlo.
• Take a look at this OpenLaszlo LZX reference book.
• Get OpenLaszlo documentation.
• Get more documentation from OpenLaszlo's wiki.
• Visit Don Hopkin's Web site, an excellent OpenLaszlo resource (browse topics
on left panel).
• View Apache Derby documentation both at Apache.org and on the
developerWorks site..
• Check out The SQL language reference from IBM for good SQL documentation.
• Visit the developerWorks Open source zone for extensive how-to information,
tools, and project updates to help you develop with open source technologies
and use them with IBM's products.
• Visit the Apache Derby Project Web site.
• Check out the developerWorks Apache Derby project area for articles, tutorials,
and other resources to help you get started with Derby today.
• Browse all the Apache articles and free Apache tutorials available in the
developerWorks Open source zone.
• Browse for books on these and other technical topics at the Safari bookstore.
Get products and technologies
• Try out the Eclipse IDE for OpenLaszlo.
• Download the Apache Derby 10.1.2.1 release.
Discuss
• Get involved in the developerWorks community by participating in
developerWorks blogs.
Tyler Anderson formerly worked for DPMG.com, an SEO company, for whom he
wrote proprietary SEO software. He graduated with a degree in computer science
from Brigham Young University in 2004 and has just graduated with a Master of
Science degree in computer engineering in December 2005, also from Brigham
Young University. He is currently an engineer for Stexar Corp., based in Beaverton,
Oregon. You can reach Tyler at tyleranderson5@yahoo.com.