DbForms implements the concepts of the Model-View-Controller design pattern [Gamma] which leads to the development of 3-tiered web-applications.
Like most applications and application frameworks, DbForms does not completely separate these three components. For instance, the Controller Servlet is the Controller Component of DbForms. Consider, however, the use of a hyperlink rendered by the user's web browser: clicking on it will trigger some operation hence implementing some controller functionality.
The aim of DbForms is to perform
operations on databases. The tables and views utilized by
DbForms must be declared in an XML configuration file (
will be parsed and evaluated at web application start-up time.
Example 2.1. Defining the model
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE dbforms-config PUBLIC "http://www.dbforms.org/dtd/dbf_conf.dtd"> <dbforms-config> <table name="customer"> <field name="id" fieldType="int" isKey="true" /> <field name="firstname" fieldType="char" /> <field name="lastname" fieldType="char" /> <field name="address" fieldType="char" /> </table> <table name="orders"> <field name="orderid" fieldType="int" isKey="true" /> <field name="customerid" fieldType="int" isKey="true" autoInc="true" /> <field name="date" fieldType="char" /> <field name="annotation" fieldType="char" /> <field name="amount" fieldType="int" /> </table> <dbconnection name="jdbc/dbformstest" isJndi="true"/> </dbforms-config>
As shown, every table or view to be accessed by
DbForms has to be declared inside a
All relevant table fields need to be declared in
In DbForms, it usually makes no difference whether a
element really represents a database table or a logical view
defined in the RDBMS. The
circumstances under which views may be used instead of
simple tables depends entirely on the RDBMS being
used. Before using views, check that the RDBMS supports
them. When tables are mentioned in this document in
connection to some capability, the same capability may also
work with views or joined tables.
Please see the section on
Chapter 13, Query Support
for more information on how to use the DbForms
flexible joins, dynamic queries (which are alternatives for
views in the database) and aliases.
DbForms needs to be able to create connections to the
database containing the tables and fields declared in
The following subsections show three different examples
of these connections.
Versions up to 1.1.2 restrict you to use only one database per Web-Application. 1.1.2pr1 and after support multiple databases in a single application. See Multiple Database Connections for more info on that.
Example 2.2. Defining the database connection (1)
<dbconnection name = "java:comp/env/jdbc/dbformstest" isJndi = "true"/>
In the example above DbForms assumes that the JNDI entry
"jdbc/dbformstest" is configured correctly in the
Application Server or Servlet engine's configuration
and takes all the connections it needs from that JNDI entry.
If you are not using JNDI in conjunction with a connection pool manager like Poolman, you have to tell DbForms which class it has to load in order to access the connection pool manager to be used. In addition, analogous to the JNDI key, you have to tell DbForms how the connection should be identified in the connection pool.
Example 2.3. Defining the database connection (2)
<dbconnection name = "jdbc:poolman://dbformstest" isJndi = "false" class = "com.codestudio.sql.PoolMan"/>
In the example above DbForms assumes that the connection
pool entry called
is correctly configured in the associated connection
pool managers properties file and takes all the
connections it needs from that connection pool.
The full configuration of data sources (how many pooled instances to create, duration of invalidation timeouts, etc.) is not in the scope of this user's guide. Please refer to your Application Server or Servlet engine documentation for more details.
DbForms now makes is easier to use connection pooling with the Protomatter and Jakarta connection pools. See Chapter 20, Connection Support for more information on using these or other pools.
If you just want to test the functionality of DbForms and you do not care about speed (at the moment), then you might want to define a simple database connection as follows:
Example 2.4. Defining the database connection (3)
<dbconnection name = "jdbc:mysql://localhost/fashion" isJndi = "false" conClass = "org.gjt.mm.mysql.Driver" username = "scott" password = "tiger"/>
Note: Many drivers pass in JDBC properties using the URL such as:
<dbconnection name = "jdbc:mysql://localhost/fashion?charSet=ISO-8859-1" ...
If your driver does not allow this and you need to pass in a property, please see Section 20.1.4, “Setting JDBC Properties” for another way to set JDBC properties.
The view portion of a DbForms application is constructed using JSP technology. JSP files may contain static HTML elements as well as dynamic elements containing Java code (definitions, statements, expressions). For more information about JSP, refer to [JSP].
With release 1.1 of the JSP API, the concept of Custom tag libraries [Taglib] was introduced. Custom tags allow a developer to encapsulate even the most sophisticated Java code into an easy-to-use lightweight JSP tag. You may think of Tag libraries as a sort of advanced macro.
DbForms is, essentially, a collection of custom tags for placing data forms and data fields on JSP pages.
Each DbForms View JSP may have one or more root tags of the type dbform. Every dbform tag has to contain exactly 1 header tag, exactly 1 body tag and exactly 1 footer tag, in exactly that order.
Each of those tags may contain subelements such as data fields, input fields, action buttons, and, of course, plain HTML text and JSP code.
Header and footer tags are commonly used for titles of pages, for labeling tables, for placing action and navigation buttons, input fields to enter new data, etc.
Header and footer tags get evaluated only once.
The body tag is used for showing data rows coming from the
database, and for providing the user with functionality to
edit that data. How many times the body tag and its
subelements get executed (i.e., evaluated and rendered)
depends on the value of the
maxRows attribute of the
form element (and of course, on the number of rows
actually stored in the table).
maxRows is set to a
number, the body gets executed up to that many times,
limited by the number of rows in the database table.
maxRows is set "*",
the body gets executed an indefinite number of times,
limited only by the number of rows in the database table. This
should be used with caution lest the page become very large.
Every form may contain one or more nested subforms inside its body tag.
The orders form is nested within the body element of the
customer form. The user will see
customer per page (because
is set to 1) and
the orders (because
maxRows = *)
the customer has pending. The user may navigate through
the list of customers by clicking the navigation buttons.
The Controller includes several components:
Controller-Servlet: this servlet is the single-point-of-entry for all incoming HTTP-requests.
EventEngine: a kind of assistant to the Controller-servlet. It focuses on filtering requests for WebEvents and instantiates them.
WebEvent Objects: all Objects derived from this abstract super-class have the ability to initialize themselves by reading a given request. These events get executed either by the controller directly or by the View.
The following example should give you a better picture of what the controller does and how it interacts with other components:
The Controller-Servlet delegates the incoming request to the EventEngine which determines the main or primary event, (the event the user explicitly triggered by clicking a button). Secondary implicit events may also be generated. For example, under some circumstances, automatic updates of all changed input fields of all data rows will be generated.