Some features that are unique to JSP:
All JSPs (whether part of ACS or not) declare several variables
implicitly; the most important are request
,
response
, and out
. The out
variable is used implicitly every time you output HTML in a JSP.
The request object has an attribute list associated with it, which can
be used for passing objects between different JSP pages, or between
JSP pages and templates. This is done by calling
request.setAttribute("name", object)
and
request.getAttribute("name")
. The request object also
has methods for retrieving URL/form variables and getting properties
about the connection.
For most connection-level operation you can do in AOLserver, there is a corresponding method in Java. Some examples:
Tcl/AOLserver | Java/JSP |
---|---|
ns_returnredirect $return_url
| response.sendRedirect(return_url);
|
ReturnHeaders 200 image/jpeg
| response.setStatus(200);
|
set ip [ns_conn peeraddr]
| String ip = request.getRemoteAddr();
|
acs.jspi
file to
set up imports and the ACS tag library. All ACS Java pages should
also start with the ad:page tag, which sets up two variables:
db
, a Database handle object for use in the page; and
form
, an AdSet corresponding to the passed-in URL/form
variables.
Each ACS Java page is split into two files: a JSP that does business logic, database access, user input validation, etc.; and a corresponding TPL template for rendering HTML to the user's web browser. (TPL templates are just JSPs with a different extension.)
The skeleton of most ACS Java JSP pages will look like this:
<%@ include file="acs.jspi" %>
<ad:page>
<ad:page_contract id="pc" vars="..."/>
... do queries, DML, etc. here ...
<ad:use_template/>
</ad:page>
Form and URL variables are processed with the ad:page_contract JSP tag.
This tag performs some type checking and validation. The page_contract
tag automagically declares local variables corresponding to each declared
form/URL variable in the vars
parameter. The page_contract
tag also sets attributes in the pageContext object corresonding to each
declared form/URL variable.
The syntax for the ad:page_contract tag is:
ad:page_contract [id="pc"] vars="var_name(:flags)..."
Available flags for each variable include:
java.lang.Integer
.
com.arsdigita.acs.AdSet
, named
"var", with keys key1, key2, ...; var.get("key1") will return the
value of form variable var.key1, and so forth.
java.sql.Date
.
pc.addComplaint("you must enter ...")
within the
page_contract tag body for indicating problems with user input. When
the page_contract tag is closed, a message will be displayed to the
user and the page will not continue executing.
Warning: Because of a quirk of the JSP spec (Section 5.5 of the
JSP 1.1 Specification document), any scripting variable that you set
within the body of a page_contract tag will revert back to its
corresponding attribute in the pageContext
; so, if you
want the new value to stick, you should call
pageContext.setAttribute(varname, value)
. For example:
<ad:page>
<ad:page_contract vars="v:optional"/>
<%
if (v == null) {
pageContext.setAttribute("v", "default_v_value");
}
%>
</ad:page_contract>
<%--
the translation of the closing tag includes the statement
v = pageContext.getAttribute("v");
so the following line should print out "default_v_value".
--%>
<%= v %>
The Selection class is an implementation of the DataSource
interface to generically represent lists of database rows returned
from queries. It is effectively a wrapper for the
java.sql.ResultSet
interface, which hides the distinction
between VARCHAR
and CLOB
objects from a JSP
page author; also, it ensures that raw SQL dates are displayed in
standard ANSI format.
The Selection class can be extended with methods specific to a
particular kind of database object, when appropriate. For instance,
it is useful to have a subclass of Selection that represents a bboard
topic (com.arsdigita.acs.bboard.TopicsDataSource
Performing database queries
Database queries are performed with the <ad:db_query>,
<ad:db_1row>, and <ad:db_0or1row> tags depending on
whether the query is for multiple rows, one row, or zero or one row
respectively.
All of the database query tags instantiate objects of type Selection, or one of its subclasses, and make them immediately available both as local variables in the JSP page, and as attributes for looping and interpolation with the ad:sub/ad:loop tags.
All query tags allow you to specify the type of DataSource to be created; by default, db_query creates an object of type Selection, and db_1row/db_0or1row create an object of type SingleSelection.
Each database query tag also creates a variable of type
SqlStatement that can be referenced for setting bind variable values.
The bind()
method binds values to variables in the order
in which they occur within the SQL statement, though you can bind
out-of-order by using named bind variables.
Example:
<ad:db_query id="get_bboard_topics" obj="topics" type="com.arsdigita.acs.bboard.TopicsDataSource">
select * from bboard_topics
where group_id = ?
<%
if (topic_stub != null) {
%>
and topic like :topic_stub || '%'
<%
get_bboard_topics.bind("topic_stub", topic_stub);
}
get_bboard_topics.bind(group_id);
%>
</ad:db_query>
<ad:db_1row id="get_date" obj="date">
select sysdate from dual
</ad:db_1row>
<%--
at this point date is declared and is type SingleSelection;
topics is declared and is type TopicsDataSource.
--%>
<%= date.get("sysdate") %>
<ul>
<ad:loop ds="topics">
<li><ad:sub var="topic"/>
</ad:loop
</ul>
obj
and
type
attributes just to create a SqlStatement object;
this object can be passed as an argument to the
Database.dml()
method for performing inserts/updates/etc.
Example:
Java | Tcl equivalent |
---|---|
|
|
There is an analogous plsql
method as well, for calling
stored functions and procedures. Note that you should not
explicitly bind the return object for stored functions:
Java | Tcl equivalent |
---|---|
|
|
Selection.get("column_name")
will return the contents of
column_name
as a String whether it is a CLOB or varchar.
BLOB content may be retrieved with the getBLOB() method in Selection; or the dumpBLOB method may be used to write the BLOB content directly to an output stream.
To perform DML operations with BLOB or CLOB objects, use the
blobDmlFile
, clobDmlFile
, and clobDml
methods in the Database class. All these methods are analogous to
Database.dml(); they take a SqlStatement, with an additional parameter:
java.io.File
that
will be uploaded into the BLOB or CLOB object in the database.
SQL statements used with the LOB DML methods in Database should use
the returning into
clause to set up the CLOB objects as
the last bind variable in the statement. Also, because of the way the
JDBC driver works, you have to wrap the INSERT or UPDATE statement in
begin ... end;
.
Example:
Java | Tcl equivalent |
---|---|
|
|
beginTransaction
, abortTransaction
, and
endTransaction
methods. Nested transactions are supported.
Example:
Java | Tcl equivalent |
---|---|
|
|
We try to eliminate escaped Java code (that which comes inside <% ... %> blocks) as much as possible and implement our own custom tags for performing routine tasks such as looping over a multi-row datasource and interpolating columns from it.
A JSP passes control to a TPL template for display by using the <ad:use_template> custom JSP tag. In /path/to/foo.jsp, the use_template tag will pass control to the template named /templates/path/to/foo.tpl.
Note that TPL files are really just JSP files with a different extension, to prevent confusion and to bypassing repetitive request processing with the RequestProcessor servlet. The TPL extension is be directly mapped to the JSP servlet, which avoids the RequestProcessor.
Usage of template_contract:
<ad:template_contract vars="var1[:flag1,flag2,...] var2[:flags] ..."/>
The "vars" parameter to the template_contract tag is very similar to that for the page_contract tag; each declared variable becomes a variable available to escaped Java code in the template. There are two major differences, though:
Object
rather than a String
(note that the
actual type of the object is still what it was when it was
created; you can manually type-cast to the actual type). This allows
non-String objects with toString()
methods to be displayed
without specifing their actual type in the template. (e.g.,
Integer
, com.arsdigita.acs.html.ContextBar
,
etc.)
class=package.subpackage.ClassName
: makes the created
variable have a specific apparent type, if you happen to be calling methods
on the object directly
datasource
: specifies the object is a DataSource;
not necessary unless you want to call methods on the datasource
directly in escaped Java code (e.g., ds.next();
ds.get("key")
). This is really just syntactic sugar for
class=com.arsdigita.acs.DataSource
.
string
: syntactic sugar for class=String
;
specifies that the created object will have an apparent type of
java.lang.String
Note: This is only necessary if you
are explicitly calling methods from escaped Java code within your
template (e.g., s.length(); s.charAt(i)
). It is
not necessary for writing out strings (<%= s %>
).
optional
: same as in page_contract; allows variable
to be null if not present
multiple
: same as in page_contract; apparent type of
created object will be an Object[]
, or a
ClassName[]
if the class=...
flag is also set
<ad:template_contract vars="var1:optional var2:class=Integer,multiple
var3:datasource"/>
is syntactic sugar for:
<%
// var1 is optional -- will be null if not supplied
Object var1 = request.getAttribute("var1");
// var2, var3 not optional: will fail if not supplied
Integer[] var2 = (Integer[])request.getAttribute("var2")
if (var2 == null)
throw new PageValidationException("var2 not supplied");
DataSource var3 = (DataSource)request.Attribute("var3");
if (var3 == null)
throw new PageValidationException("var3 not supplied");
%>
Note: the ad:sub tag will introspect into the
object and look for a more method that corresponds to the property
name before calling the general get(key)
method.
<ad:sub var="column_name"/>
will first try to call
getColumnName()
if it exists on the datasource; otherwise
it will call get("column_name")
if no such method exists.
org.apache.turbine.util.Log
). The package is imported in the
acs.jspi file.
Tcl/AOLserver | Java/JSP |
---|---|
ns_log notice "Sending email..."
| |
ns_log warning "Warning: ..."
| |
ns_log error "Oracle down, major system failure ..."
|
*.jsp
URL pattern
should also be mapped explicitly to RequestProcessor, to undo any
previous mapping the the JSP servlet.)
The following steps take place within the RequestProcessor to serve a response to the end-user's browser:
Note that requests for abstract URLs go through the RequestProcessor twice: the first time, they are filtered, resolved, and forwarded to the concrete URL; the second time, they are just forwarded to the appropriate handler servlet. This is necessitated by the internals of the Servlet spec, specifically, because you can't call getNamedDispatcher with a URL parameter like you can with getRequestDispatcher.
Under the hood, a request for /path/to/page is handled like this:
Procedures are scheduled by calling the schedule
and
scheduleOnce
methods, in various forms. Example:
Java | Tcl equivalent |
---|---|
|
|
web.xml
.
In the parameters XML file, parameters are associated with modules and may also have types; also, parameters may have multiple values. For example:
<module name="bboard">
<parameter name="ModuleName">
<value>yourdomain Discussion Forums</value>
</parameter>
<parameter name="FileUploadingEnabledP" type="boolean">
<value>true</value>
</parameter>
</module>
<module name="foo">
<parameter name="numberlist" type="int">
<value>10</value>
<value>20</value>
<value>30</value>
</parameter>
</module>
Initialization parameters are accessed through the static methods of the Parameters class:
Java | Tcl equivalent |
---|---|
Parameters.getBoolean("FileUploadingEnabledP", "bboard")
| [ad_parameter FileUploadingEnabledP bboard 0]
|
Parameters.get("SystemName", "", "yourdomain Network")
| [ad_parameter SystemName "" "yourdomain Network"]
|
Parameters.getVector("numberlist", "foo")
| [ad_parameter_all_values_as_list numberlist foo]
|
Java | Tcl equivalent |
---|---|
|
|
loadclass
tag in the ACS parameters
file, e.g.:
<loadclass>com.arsdigita.acs.fs.Download</loadclass>