ACS 3.2 Developers' Guide to ACS 3.3 and Beyond

by Jon Salz
This document tries to answer the question, "What the heck have you done to my beloved ACS?" It briefly describes the changes made to ACS between versions 3.2.3 and version 3.3, from a developer's standpoint. It is intended to contain the minimal set of new information with which everyone needs to be familiar to develop for ACS 3.3.

Big Picture

In the past, ACS has been a toolkit held together by loose conventions. While this has worked well up to the present, ACS has matured to the point where it needs to be more heavily structured. One of our main goals for versions 3.3 and 4.0 is to add this structure - to develop valuable conventions and clean abstractions that will help preserve ACS's status as the best open-source toolkit around for developing purposeful online communities.

In a Nutshell

Note that aside from the ad_register_* changes, you are merely encouraged, not required, to use the new APIs. As of 4.0 (and all code integrated into ACS as packages) you will need to use the new APIs. The next few months will be a transitional period.

Package Management and the Filesystem

One of the most fundamental changes to ACS starting with version 3.3 is the introduction of package management, and the reorganization of the filesystem (see the ACS Package Manager documentation to learn why this is a good idea). Looking at the ACS 3.3 directory, you'll notice a new /packages directory (at the very top of the directory tree, right alongside /tcl and /www. The idea is to divide ACS into a series of functional components, "packages," with each package mapped to its own directory inside the /packages directory. The ACS core package (/packages/acs-core) provides the very basic functionality expected of an ACS system.

It is outside the scope of this document to describe how to develop a package (but if you're interested, see the APM documentation or the 5-Minute Guide to Packaging Your Module) We're not asking anyone to build packages yet - just keep developing as you always have been for now, in the same directories, but know that a lot of files you might expect to see in /tcl, /www/doc/sql, etc. have been moved inside the ACS core package (/packages/acs-core).

The package manager UI can be accessed at (site-wide administrators only).

ACS Startup (Bootstrapping)

When AOLserver starts up, the first thing it does is to source every .tcl file in tho /tcl directory. This still occurs, but very importantly, the 0-acs-init.tcl script is sourced first. The entire startup process (discussed in detail in the Bootstrapping) is: This more complicated process is necessary to support packages. The distinction between *-procs.tcl and *-init.tcl files is necessary to

Request Processor


In versions of ACS before 3.2, it's very difficult to determine exactly which code is running when a particular request is executed. In general, all kinds of filters are executed, and then some registered procedure (maybe the abstract URL handler) is invoked (or, if abstract URLs are disabled, a file is served directly). There are several problems with this approach, most notably that:
  1. It's difficult to deliver files which don't physically live underneath the page root (in the /www directory), as in the case of pages associated with packages.
  2. It's very difficult to control the order in which filters are executed.
  3. It's difficult to determine which code is executed for requests to which URLs.
  4. If something breaks, it's very difficult to determine which filter is causing the problem.
  5. Scoped requests need to be handled specially, with ns_register_procs for each possible URL prefix (/groups, /some-group-type, /some-group-name, etc.).
  6. Filters and registered procedures are strictly URL-based, so they break under scoping (e.g., a procedure registered for /download/files/ won't work for requests under /groups/some-group-name/download/files/62/smug.jpg).

In 3.3 and Beyond

In ACS version 3.3, absolutely every request is served through a unified request processor (rpp_handler in /packages/acs-core/request-processor-procs.tcl), described in detail in the request processor documentation. We have replacement routines for ns_register_filter and ns_register_proc, called ad_register_filter and ad_register_proc respectively, which solve the first four problems:
  1. The request processor is smart enough to look inside packages to deliver files in their www and admin-www directories.
  2. ad_register_filter has a -priority flag. Filters with numerically lower priorities run before filters with numerically higher priorities.
  3. There are nifty monitoring tools under which let you determine which filters and procs are executed when a particular URL is requested.
  4. Procedures registered with the new API provide full stack traces in the log when something goes wrong.

We'll solve the latter two problems as soon as subcommunities are implemented for 4.0.

Important: You must use ad_register_filter and ad_register_proc rather than the corresponding ns_ calls. ns_register_filter and ns_register_proc are disabled in the release version of ACS 3.3.

Database Access API

Usage of ns_db is being phased out (although we're not deprecating ns_db yet - you can continue to use it). That's right, we're providing a new Database Access API which totally frees you from the responsibility of allocating database handles and passing them around to subroutines. For instance, instead of
set db [ns_db gethandle]
set selection [ns_db select $db "select foo, bar from greeble"]
while { [ns_db getrow $db $selection] } {
    append output "<li>foo=$foo; bar=$bar\n"
ns_db releasehandle
you can now just write
db_foreach "select foo, bar from greeble" {
    append output "<li>foo=$foo; bar=$bar\n"
Not a database handle ($db) in sight; the database handles are managed and recycled for you. Don't worry, this actually does work (despite the many incredulous emails we've received): the entire package manager was written with it and works without a hitch.

See the Database Access API documentation for more information, including a discussion of why this is A Good IdeaTM.

Document API

Fare thee well, ReturnHeaders, ns_write, ns_return, and friends! From Building Documents in ACS (philg, jsalz):
Standard AOLserver programming, like CGI scripting before it, had the programmer directly writing bytes to a client browser connection. Thus from 1995 through 2000 an AOLserver programmer would build up a complete HTML page in a script and write the bytes of that page to the client either all at once with ns_return or incrementally with ns_write.

Problems with this standard old approach:

The basic idea is that, in Tcl scripts, you now use doc_set_property to set the title and navigational context for a document, and doc_body_append (rather than ns_write) to build up the body for the page (leaving out the headers and footers) master template later builds a page for you, tacking on header, title, navbar, footer, etc. as appropriate in a customizable way.

Don't worry, you don't need to start using this right away. But for more details, see Building Documents in ACS.