by Rick Gretter, JBuilder QA
Overview
Design time
Notes on specific input
controls
Runtime
JSPs
Overview
InternetBeans Express is a set of components and JSP tag extensions
for generating and responding to the presentation layer of a web application.
It takes a template page of static HTML, inserts dynamic content from a
live data model, and presents it to the client. Then it writes any changes
that are posted from the client back into the data model.
When using servlets, you bind an InternetBeans Express component to
each control in a template page that will receive dynamic content and post
values back. You also bind an InternetBeans Express component to each control
that can cause the page to be submitted. You provide event handlers for
these controls, to react to the SubmitEvent that InternetBeans Express
will fire for the control that triggers the post.
At runtime, you call IxPageProducer's servletGet() method to render
a page that contains dynamic content. When your servlet receives a post,
you call IxPageProducer's servletPost() method. This posts the data in
the InternetBeans Express-enabled page and calls the appropriate event
handler. ("Post" here means that the data values from the web application's
UI are written to DataExpress data sets.) At this point, you can work with
your Data Express components in the usual way to validate input, save data
set changes to a SQL server, handle resolution errors, etc.
Compared to earlier technologies, servlets simplify web application
programming by providing access to form data thorough API calls. We might
summarize the explanation above by saying that InternetBeans Express goes
a step further, replacing code manipulation of form data with a component-
and event-based model. In this model, working with a database in a web
application is very much like working with it in a Java application: what
you know about JBuilder data modules, DataExpress components, data set
events, and UI Designer still applies. Differences include the fact that
your overall application structure may be quite different, you display
data in HTML controls and elements rather than dbSwing or other Java components,
and you can't use the Designer visually.
These notes concentrate on differences that are directly related to
InternetBeans Express. Most of this material deals with servlets. The last
section contains material specific to JSPs.
Design time
The basic sequence of events for creating an InternetBeans Express application
using servlets is:
-
Create an HTML form. It will typically contain a <FORM> element, <TABLE>
elements, and <INPUT> controls.
-
Create a data module, or use an existing one.
-
Create the skeleton of a servlet. You can do this with the Servlet Wizard,
though you will have to delete some code that it generates.
-
Add code to the servlet to use the data module.
-
Design the servlet: Drop components from the InternetBeans tab from the
Component Palette into the design. Begin with an IxPageProducer, and set
its htmlFile property to your HTML file and its dataModule property to
your data module. Use one InternetBeans Express component for each element
in the HTML file that you want to make data-aware. Set properties to bind
each component to its element and to a data set (and often a column as
well) in the data module.
-
Generate skeletons of event handlers in the Designer, then write code for
them and for the servlet's doGet() and doPost() methods.
-
Repeat for additional HTML pages and servlets to process them, assuming
your application requires more than one HTML page.
-
To run within JBuilder, right-click the file that starts the application,
for example an SHTML file created by the wizard, and select Web Run. The
application's servlets are run in the Tomcat servlet container and displayed
in the editor pane. Two new tabs, Web View and Web View Source, show you
the running application and the generated source for the current page.
For more detail, see the tutorial in the "Using InternetBeans Express"
topic of the Web Application Developer's Guide.
Using existing HTML files: JBuilder and InternetBeans Express
are intentionally not HTML designers. When InternetBeans Express adds data-awareness
to elements in an existing HTML page it does not change their size or position.
So when you bind InternetBeans Express components to a web page, the look
of the page doesn't change, except that its elements are now data-aware.
You should only have to make a few small changes to use an existing HTML
page:
-
<TABLE>, <IMG>, <DIV>, and <SPAN> and other HTML tags can be
made data-aware by binding them to InternetBeans Express components. When
you do this, a tag's ID attribute, which is otherwise optional, must be
defined.
-
You must give each submit button a different name. Servlets allow them
to share a name and use the value of the VALUE attribute to know which
button was selected. In InternetBeans Express, each button is bound by
name to its own InternetBeans Express component.
Data Modules: An InternetBeans Express application should usually
use a data module. If you're using only one data set, you can define the
data set directly in the servlet or JSP instead. Even then, if several
data-enabled pages in the application use the same data, its simpler and
better to define all the Data Express components just once in a data module.
When you want to bind InternetBeans Express components in a single servlet
or JSP to more than one data set, you must use a data module.
Using the Designer: Use DataExpress components just as you would
when designing a Java front end. If you are using a data module, the DataExpress
components should already be available in the Designer. If you are not,
define your database and query in the usual way.
These components are available on the InternetBeans Express tab of the
Component Palette:
-
IxPageProducer establishes the link between your HTML file and your
DataExpress components. Its lists of available HTML element and control
names are created when you set the IxPageProducer's htmlFile property.
If you change the HTML file afterwards, you should clear and reset this
property so that InternetBeans Express can rebuild its lists.
-
IxControl matches any HTML control. (An HTML control is a
read/write visual component that appears inside a <FORM> element and
is identified by the NAME attribute.) Although InternetBeans Express has
a component to match each HTML control type, you can always use an IxControl
instead. It will figure out which specific InternetBeans Express component
matches the HTML control it is bound to. To bind an IxControl to an HTML
control, set its controlName property to the HTML control's NAME attribute.
-
Components for HTML elements: Four InternetBeans Express components
are bound to HTML elements such as <TABLE> and <IMG>. In each
case, set the component's elementId property to the HTML element's ID attribute.
The components are:
-
IxImage makes an <IMG> element data-aware. Don't use it for an
ImageButton (<INPUT TYPE="IMAGE">), which is a control and should be
bound to an IxControl or IxImageButton.
-
IxLink lets you create a data-aware link. There's a little more
detail below.
-
IxSpan inserts read-only data into HTML output. It is most often
used with <DIV> and <SPAN> elements. You can also use it to insert
data from a data set into a heading or even into a link (if you want a
link with dynamic text but a static URL). Define the ID attribute of the
element, and set the IxSpan's elementId property to it.
-
IxTable displays an entire DataExpress data set. You can also specify
which columns and how many rows to display. There's more on tables
below.
-
Components for HTML controls: As discussed above, you can usually
substitute IxControl for all these components. In several cases, you may
want to use IxCheckbox, IxRadioButton, etc. instead:
-
The Designer may be a little easier to use because the Inspector can fine-tune
the set of properties displayed. For example, you won't see dataSet and
columnName properties for an IxSubmitButton.
-
IxControl does not work when you don't use a data set or data module. If
you create your own custom TupleModel, you must use the specific component
types.
Basic code in an InternetBeans Express servlet
Before looking at typical code that you'd write in an InternetBeans
Express servlet, you should know how InternetBeans Express deals with the
fact that a servlet typically handles request from many users. In a database
web application, different users will navigate to different rows in the
servlet's data set(s), which should cause the application's InternetBeans
Express components to display different values in their associated HTML
elements. Each user's position must be maintained between the time a page
is rendered and the time updates to the displayed row are submitted to
be posted. To support this, InternetBeans Express gives each user session
its own set of DataExpress and InternetBeans Express components. So when
you write code:
-
Any work you do in the servlet's jbInit() and init() methods uses the instances
of components that you created in the Designer. This code is executed before
the servlet begins responding to user requests. We call these
prototype
instances, because they are not actively used at runtime.
-
Any work you do in the servlet's doGet(), doPost(), or event handler methods
uses components that are specific to your session. We call these
per-session
instances. You obtain references to them from your IxPageProducer.
Basic code for servlet methods is:
-
init():
-
You may not need any code in init() other than the call to super. If you
want to do additional setup work that will apply to all users, such as
adding custom cell renderers to a table, this is the place to do it. In
this case, you'll probably want to begin by calling your IxPageProducer's
getObjects() method. This will open your data sets, bind InternetBeans
Express components to their HTML elements, and determine the columns to
be displayed in tables. ( IxPageProducer's getObjects() method was accidentally
omitted from the documentation. Use CodeInsight as the final authority
on the API of JBuilder packages.)
-
doGet():
-
Delete code written by the Servlet wizard that sets content type, gets
a PrintWriter, and writes to the PrintWriter.
-
Call IxPageProducer's servletGet() method to render the page. Often this
is all you need, though you may add custom code here too.
-
doPost():
-
Delete code written by the Servlet wizard that sets content type, gets
a PrintWriter, and writes to the PrintWriter.
-
Call IxPageProducer's servletPost() method, which posts data in InternetBeans
Express components to their data sets and invokes the appropriate event
handler.
-
Call your doGet() method if you want to display the same page again. Other
options would be to respond with a redirect or to forward the request to
another servlet or JSP with a RequestDispatcher.
-
Event handlers for submit buttons and image buttons:
-
Respond to the submit or image button. In the event handler for a button
labeled "Cancel", for example, you would probably call your data set's
cancel() method. Remember to use the per-session instances of data sets
and InternetBeans Express components. Use IxPageProducer's getSessionComponent(),
getSessionDataSet(), getSessionDataModule(), and getSessionTupleModel()
methods to get them.
This is discussed in more detail in the reference documentation for IxPageProducer.
Notes
on specific input controls
Tables: With most HTML elements and controls,
the HTML code that InternetBeans Express generates is a lot like the code
in the template document, except of course that the literal value between
the start and end tags is replaced with dynamic data. But tables are much
more complex. The generated table may differ from the template both in
the set of columns and in the number or rows displayed. The rules for columns
are:
-
If an IxTable component finds at least one valid column name in the HTML
source for the table's heading, it only displays columns that match names
found in the source.
-
If IxTable doesn't find any valid column names, it displays all columns
in its data set.
-
Column names in the HTML and the data set do not have to be identical to
"match": spaces, underscores, and casing are ignored when comparing names.
-
Some columns, such as Row ID columns and master link columns in a detail
data set, have their visible property set to false by default. You might
set other columns not visible. These columns are not displayed.
IxTable's rowCount property tells how many data rows to display. The default
value is 20. If you mean to display all rows, be sure to set rowCount very
high. To page through a data set, increment the IxTable's startRow property
by the value of rowCount each time a button is pressed. InternetBeans Express
won't try to display a row less than 0 or greater than the number of rows
in the data set, so you don't have to test for those cases.
In InternetBeans Express, tables are read-only. Also, you can't bind
InternetBeans Express components to nested tables. This is not as restrictive
as it seems: you can nest non-data-aware tables, and can bind InternetBeans
Express components to controls in nested tables. But you can't bind an
InternetBeans Express component to a control that is inside a table bound
to an InternetBeans Express component.
Like other InternetBeans Express components, IxTable preserves the style
of its HTML <TABLE> element. This includes cells that are more than
one row high or one column wide. IxTable uses the arrangement of cells
that it finds in the table's header for each row it generates. In this
case, you must supply valid column names in the header, since table rows
and columns may not span properly if the expected number of data set columns
can't be displayed. You can also vary styles between the header and the
template data rows, or from one row to another. If you include more than
one row of template data and the rows have different styles, IxTable will
follow their pattern, alternating two or more row styles for as many rows
as it outputs.
Checkboxes: A checkbox can be bound to a boolean or String column.
When rendering HTML, InternetBeans Express sets the checkbox's status to
checked if the value in the column is true (boolean) or "true" (String),
and unchecked if the value is anything else. When posting data, InternetBeans
Express knows that the request will not contain a name/value pair for a
checkbox control that is unchecked. It posts the value false (boolean)
or "false" (String) in this case.
Radio buttons: A set of radio buttons in HTML is identified by
the fact that they all share the same NAME attribute. One IxRadioButton
or IxControl maps to all the radio buttons in the set.
Picklists in select controls: If an HTML select control is bound
to a column whose picklist property is set, the control gets its dropdown
list from the picklist data set. This will replace a list defined in the
HTML source by means of option tags. If the column doesn't have a picklist,
the option values in the HTML are used.
If the picklist definition calls for multiple columns in the dropdown
list, only the first column will be displayed. Lookups are not supported.
The picklist is only built once, when the per-session InternetBeans Express
components are instantiated. It will not be rebuilt in situations where
a dbSwing list would be; for instance, a picklist on a column in a detail
data set will not be rebuilt as the master is navigated.
Images: The GIF, JPEG, and PNG formats are supported. BMP is
not, although dbSwing does support it, because BMP is not a web format.
InternetBeans Express respects an image element's HEIGHT and WIDTH attributes
if you set them, so your page layout doesn't change as you navigate through
a data set even if images in the data are different sizes.
Links: You can create a data-aware link with
IxLink. Its dataSet and columnName properties specify the data to be displayed
as a link. Set its link property, a string, to the static part of the URL
to link to. This may be something like "detailServlet?LinkValue=". At runtime,
the data value in the current row will be appended to the value of the
link property to create the HREF attribute in the generated HTML.
One weakness of IxLink is that the value displayed in the link on-screen
is the same as the value passed in the HREF. You might prefer, for example,
to show a product's description on-screen but pass its product number in
the link. To do this, you could override the getDescription method, which
is not very useful as it stands, to get its value from another data set
column.
Runtime
Running a web application: The last step of the design
overview summarized the JBuilder runtime environment for servlets and
JSP:
-
Tomcat, a servlet-enabled web server, is included with JBuilder.
-
To run a servlet or JSP, right-click the file in the project pane and choose
Web Run. To debug, select Web Debug instead. You can also define the application's
starting file from the Project Properties dialog, then run or debug from
the JBuilder menus or toolbar. To do this, select the dialog's Run tab;
on it, select the JSP/Servlet tab (not the Application tab); and specify
the start file there.
-
Two new tabs, Web View and Web View Source, are added to the editor pane
when you first run a servlet or JSP. Web View shows your application running
in the IDE's integrated web browser. Web View Source shows the source that
the servlet or JSP generated.
Once an application is launched via Web Run, you can copy and paste the
URL from the Web View pane into another browser and run your application
there. In this way, you can see how your pages look in other browsers,
particularly if you're using HTML options that the browser built into JBuilder
doesn't support, or verify that your servlets support multiple concurrent
users. It's a good idea to look at your output in more than one browser
before concluding that there's a bug in your code or in InternetBeans Express.
The problem may well be in the browser. The generated code on the Web View
Source tab is also helpful when debugging.
Multi-user issues: Isolation of two users of the same servlet
depends on the way their data is defined to InternetBeans Express. If you
use a data module, each session gets a new instance of the data module.
This means that user1 will not see user2's changes to a data set until
user2 calls saveChanges() and user1 calls refresh(). If you use a data
set, each session gets a DataSetView based on the data set. This means
that each can see the other's changes as soon as they're posted.
Using a data set instead of a data module places some restrictions on
your servlet. You can't do anything in the doPost() method or in an event
handler that would try to fill the data set differently for each user.
For instance, you can't run a parameterized query based on values the user
enters in HTML controls. If you try, you'll find that every user see the
data from the last query run. When you define a data set in your servlet
(instead of referencing a data module), do it in jbInit. The usual way
to do this is by setting its query property and letting the query run when
the data set is opened. Once the servlet is up and running, only do operations
that DataSetView supports, such as:
-
Maintaining a different position in the data set for each user (to let
several users edit concurrently, for example)
-
Sorting the data set differently for each user
-
Filtering the data set differently for each user
-
Inserting, deleting, and modifying rows.
If you need to do more, use a data module, even if it only contains one
data set.
Options: The dialogs in which you set servlet and JSP runtime
options have online help. Here we'll just tell what you can set in each
dialog.
-
In the Project Properties dialog, available from Project | Project Properties,
the Run tab has a tab for JSP/Servlet settings. All settings here apply
to the entire project or web application. They include
-
Run configuration options, such as the file to run and VM parameters and
query string to use
-
Context parameters tab: parameters available to all servlets in the application
-
Server options tab: general servlet container options and setup of the
specific servlet container used. The only one supplied is Tomcat, but others
can be added through OpenTools.
-
IDE options tab: display, file handling, and debugging options.
-
Servlet properties:
-
HTML, HTM, SHTML, and JSP files in a JBuilder project have Web Run and
Web Debug selections on their context menus. You can launch a web application
from here instead of specifying a file to run at the project level.
-
Java files in a JBuilder project have a Properties selection on their context
menus. The properties dialog includes a Web Run tab. (The tab is displayed
for all Java files but is only useful if the class extends HttpServlet.)
You can define servlet parameters and assign an alias to the servlet here.
You can't run two instances of a servlet with different parameters through
JBuilder, so the alias isn't used to distinguish between instances. It's
still useful though, because defining an alias also defines a mapping of
that alias to the servlet class. That way, you can reference the servlet
by a name instead of using the full class name with the servlet invoker.
For example, with the servlet invoker, you would need to use a URL like
myserver/servlet/some.package.MyServlet;
with an alias it would simply be myserver/myalias. In addition
to being more direct, the aliased URL makes the servlet appear to be in
the web root directory, so relative URLs (like to an images subdirectory
off the root) will work.
JSPs
One key difference between a servlet and a JSP is that a JSP does not
have a separate Java file. For the InternetBeans Express users, this fact
has several consequences. One is that you can't use the Designer to create
InternetBeans Express components and bind them to HTML controls. You do
this work in the editor instead, and it is not a matter of setting properties
on a component but of setting attributes for a custom tag. Another is that
you have to modify your existing, non-data-aware JSP, unlike the servlet
case, where InternetBeans Express reads your HTML and Java files and generates
data-aware HTML code from them. Finally, an InternetBeans Express tag in
a JSP is associated with an HTML element not by name but by its location
in the code. To use InternetBeans Express with a JSP, then, you surround
the HTML elements will receive dynamic content with InternetBeans Express
start and end tags. You also add tags for DataExpress components, set attributes
to connect your tags, and define event handlers in scriptlets. The basic
concept -- that the page's layout and style is retained, but the content
in its controls and elements is replaced with database data -- is unchanged.
Steps: Follow these steps to use InternetBeans Express with a
JSP. If you use JBuilder's JSP Wizard, it will do the first two steps for
you.
-
Add internetbeans.tld as a node in your project. (In the wizard, check
the "Declare InternetBeans tag library checkbox.) This is the file that
defines InternetBeans Express's custom tag library. It's in <JBuilder4_Directory>libinternetbeans.jar.
Don't add the jar; browse into the jar in the file chooser, drill down
to /com/borland/internetbeans/taglib/internetbeans.tld, and select just
this file.
-
Add the InternetBeans Express and dbSwing libraries to your project.
-
Add the library that contains your database driver to your project.
-
Add JSP tags, directives, and scriptlets to your JSPs to enable InternetBeans
Express functionality. The only required directive is the taglib directive
to point to the custom tag library's TLD file: <%@ taglib uri="/internetbeans.tld"
prefix="ix" %>. (The JSP Wizard will add this for you.) Other optional
tags include:
-
A page directive to import the necessary classes
-
A <jsp:useBean> tag to access a data module as a bean. This has some
interesting possibilities; for example, if you have parameterized queries,
you can make their parameters properties of the data module object and
use JSP syntax to automatically set values
-
InternetBeans custom tags to define a database and query, if you don't
use a data module
-
InternetBeans custom tags to tell which controls serve as templates for
the dynamic data and where that data comes from and goes to
-
Event handler scriptlets
Custom tags and their attributes: Because internetbeans.tld is an
XML file, it's fairly self-documenting. Since it's in your project, you
can conveniently view it in JBuilder. It lists all the InternetBeans Express
custom tags, their attributes, and whether or not an attribute is required.
The set of custom tags bears some resemblance to the set of InternetBeans
Express components, with a number of differences that make sense given
the differences between servlets and JSPs.
-
There's no pageProducer tag because the template HTML and dynamic Java
content are combined in JSPs.
-
There are database and query tags because this information can't be supplied
through DataExpress components as it can in a servlet.
-
The control tag is analogous to the IxControl component. There are no tags
corresponding to specific components like IxCheckBox and IxRadioButton,
but the control tag can replace all of them.
-
The submit tag is like the IxSubmitButton component. It differs from the
control tag in two major ways: it isn't bound to a data set column, but
it has a required methodName. The method, supplied in a scriptlet, does
the same work as an event handler in a servlet would. It receives a single
parameter, the JSP's PageContext object, from which all relevant information
about the request can be determined.
-
There's an image tag, comparable to an IxImage component.
-
There's a table tag, comparable to an IxTable component. The table tag
usually encloses a static HTML <TABLE> element, which in turn serves
as a template for the data-aware HTML generated by the application. All
this works just as described for table elements in
servlets. In some cases, you might want to use a scriptlet to generate
the <TABLE> dynamically instead. For example, you could let the application
user specify which columns to display and the order they should appear.
There's no equivalent to the IxSpan and IxLink components because you
can use a JSP expression to write a dynamic value to the page in read-only
form. This value can be inside an HTML tag such as a header, a link, a
<DIV>, or a <SPAN>, or it can be regular text on the HTML page.