# Seaside FAQ

# Frequently Asked Questions

1. General
   1. What is Seaside?
   2. Is Seaside ready for production?
   3. Applications built with Seaside
   4. Where can I find Seaside tutorials?
   5. Is Seaside free? What license does Seaside use?
   6. How do I get Seaside?
   7. Are there any special hosting offers for seaside applications?
   8. What is new in Seaside 2.7?
   9. How does the basic Seaside request model work?
2. What/Why
   1. What is the difference between WAComponent(component) and WATask(task)?
   2. What is canvas API, what is the motivation?
   3. What is the new header API, what is the motivation?
   4. What is source code structure of Seaside in VisualWorks?
3. How to
   1. How do I remove the tool bar?
   2. What is the most simple way to serve files from a Seaside application?
   3. How do I access the initial request fields in my root component or task?
   4. How do I clean up external resources owned by Seaside sessions?
   5. How do I subclass WASession?
   6. How do I subclass WAApplication?
   7. How do I get the requester's IP address?
   8. How do I display an expiration page?
   9. How do I make Seaside VisualWorks serve shorter URLs such as http://localhost:8008/counter?
   10. How do I reset the Seaside administrator password?
   11. How do I purge all existing sessions that might be open.?
   12. How do I provide an anchor where the document is created after the link is clicked?
   13. How do I secure a Seaside application for deployment?
   14. How does Seaside protect me against XSS?
4. What is wrong
   1. Nothing happens when I click this link?
   2. I have problems with the canvas api, where should I look?
   3. I have problems with forms or input fields, where should I look?
   4. My Seaside session object does not receive #unregistered?
   5. My page displays unexpected text
5. Deployment and maintenance
   1. How to exclude applications from the Seaside main dispatcher?
   2. How to deploy Seaside VisualWorks behing Apache?
6. Errors and messages
   1. Error: Components not found while processing callbacks: ....
   2. I have some kind of JavaScript error

1. ## General

   ### What is Seaside?

   Seaside is an open source web application framework written in Smalltalk.

   ### Is Seaside ready for production?

   Seaside is used productively for many commercial and non-commercial applications.

   ### Applications built with Seaside

   As mentionned in the mailing list

   ### Where can I find Seaside tutorials?

   As comprehensive list of tutorials can be found on the Seaside tutorials page

   ### Is Seaside free? What license does Seaside use?

   As of the Seaside 2.5 release (which was beta as of 2004 Jan 08), Seaside has been under the MIT license. This means that you can use it to build commercial apps, royalty free, with no restrictions. Note that, besides Squeak, this also applies to commercial Smalltalks such as VisualWorks and Dolphin Smalltalk.

   See more details on the Seaside license page.

   ### How do I get Seaside?

   #### Squeak

   The Seaside Download Pagedescribes the installation procedure and links to prebuilt images.

   #### VisualWorks

   Starting with version 7.2.1, Seaside is shipped on the VisualWorks distribution CD.

   Seaside can be loaded in the VisualWorks image using the Parcel Manager, section "Application Server" where you should be able to see the SeasideForWebToolkit parcel. There is some installation documentation in the parcel comments.

   Seaside can also be loaded from the public Store repository where either of the following bundles can be loaded:

   - SeasideForWebToolkit, or
   - SeasideForSwazoo

   Usually, loading from the repository may give you a more recent version of Seaside, also it gives the choice of loading older versions of Seaside. Since the repository is used to build the Seaside ports, it is possible to get an unstable version, therefore it is recommended to load Seaside from your hard disk using the Parcel Manager, unless you want to experiment with newer versions of Seaside or if you are using a version of VisualWorks older than 7.2.1.

   After the VisualWorks installation, Seaside is located in the goodies/contributed/Seaside directory. More items can be found in this directory using the File Browser or the Parcel Manager, like an HTML Seaside introductory tutorial and the original Squeak code.

   Since VisualWorks 7.3 Seaside comes with even more items that can be found in this directory:

   - SeasideForSwazoo - A parcel for using Seaside with Swazoo rather than WebToolkit. Note: you may load both SeasideForWebToolkit and SeasideForSwazoo in the same image.
   - SqueakBase - A prerequisite parcel that provides some compatibility with Squeak and that includes all the known Squeak compatibility extensions that could be found in the repository.
   - SeasideAsync - An optional parcel that adds AJAX capabilities to Seaside.
   - BonusPack - A bunch of parcels with Seaside examples, Seaside goodies like Adrian Lienhard's Mewa, Lukas Renggli's Scriptaculous library, the Web designer tool for manipulating graphic files, CSS stylesheets and Javascripts, plus various optional utility parcels.

   #### Dolphin Smalltalk

   ### Are there any special hosting offers for seaside applications?

   There is Seaside-Hosting which is a free hosting service for non-commercial Seaside applications. It is only for Squeak.

   ### What is new in Seaside 2.7?

   See the original maling list post .

   - canvas renderer is default, the old renderer is deprecated
   - new, canvas like header api
   - file library
   - some tools have been cleaned up
   - new image map api (see WAScreenshot)
   - many new elements including ruby
   - #fixCallbackTemps an ugly hack upon an ugly hack that saves memory
   - WARequestHandler refactoring
   - WAAnchorTag >> #text: has been deprecated
   - removed WATagBrush >> #tooltip:
   - a deprecation api to make all these deprecations possible
   - ability to open a debugger on the rendering stack of an element
   - pretty printer fixes and improvements (including comments)
   - cookie fixes
   - convenience methods in WARequest
   - WAListener (comet support)
   - more stuff that we forgot about

   ### How does the basic Seaside request model work?

   Normally, the transition from one page to another is split into two request- response cycles. The first triggers the callbacks associated with the link or form elements, and Seaside sends back a 302 response, redirecting the browser to another url. The second request triggers no callbacks and is a "pure" HTTP GET. Seaside sends back an html representation of the page in its new state. That page can be reloaded as much as you like with no side effects.

   This is the default case for anchors and form in GET mode. For anchors this can be changed to a single GET request that triggers the callbacks and renders the response by sending #navigation to the anchor tag.

2. ## What/Why

   ### What is the difference between WAComponent(component) and WATask(task)?

   Both of them are reusable, embeddable, callable pieces of user interface. A component has state (instance variables), behavior (it may change its state, and it may also choose to display other components with #call:), and appearance (it renders HTML). A Task has only the first two - it doesn't render any HTML directly, but only through the components it calls. This is useful when what you want to encapsulate/embed/call is purely a process (show this component, then this one, then this one). The key method for WATask is #go - as soon as a task is displayed, this method will get invoked, and will presumably #call: other components.

   ### What is canvas API, what is the motivation?

   See original post in the mailinglist.

   The basic problem that Canvas is trying to solve is that of combinatorial explosion in the protocol of WAHtmlRenderer. Consider something like a text input. The original, basic method for rendering a text input was #textInputWithValue:callback:

       	html textInputWithValue: person name callback: [:v | person name: v]

   But there's also a variation using the ...On:of: pattern:

       	html textInputOn: #name of: person

   And a variation with a liveUpdate callback:

       	html
       		textInputWithValue: person name
       		callback: [:v | person name: v]
       		liveCallback: [:r :v | ...]

   Now what if we want to use both of these variations at once? Do we also need #textInputOn:of:liveCallback:? What about #passwordInputOn:of:liveCallback:? And so on. It's relatively easy to add new convenience methods, but it's a huge pain to combine them, even when (as in this case) they're totally orthogonal.

   The Canvas renderer is just a slight change to the API style that makes this kind of combination much easier. It divides what would have been a single method on HtmlRenderer into three steps: first, you tell the canvas what kind of "brush" (tag, usually) you want to use. For example, the method #textInput will return a new instance of WATextInputTag. Then, you use protocol specific to that brush to configure it: for example, you might send it some combination of #value:, #callback:, #liveCallback:, #on:of:, etc. You almost never need to use temps when doing this, but can do it with cascades instead:

       	html textInput
       		value: person name;
       		callback: [:v | person name: v]

   or

       	html textInput on: #name of: person

   or

       	html textInput
       		on: #name of: person;
       		liveCallback: [:r :n | ....]

   The third step is to render any contents or children (if any) of this tag. You do this by passing some renderable (often a block) to the method #with:. A text input wouldn't have any, but consider something like a table:

       	html tableRow
       		rowSpan: 3;
       		with:
       		     [html tableData with: [html bold with: person name].
       		     (html tableData) colSpan: 2; with: [....]]

   Note that instead of using #attributeAt:put: before the element, as in HtmlRenderer, attributes are set as part of the configuration step - and so classes like WATableRow can implement convenience methods for common attributes like #rowSpan: as needed.

   If no configuration is needed, you can combine the first and third steps by using a keyword message instead of a unary message to specify the brush type, which is more compact:

       	html tableRow
       		rowSpan: 3;
       		with:
       		    [html tableData: [html bold: person name].
       		    html tableData ....]

   This style of API still allows streaming - the HTML for the open tag is generated as soon as #with: is sent. If #with: is never sent, it&quot;s triggered automatically (with an empty block) whenever the next tag is started. That means #with: does have to be the last thing you send, any configuration done afterwards will have no effect.

   Sometimes a temp is handy:

       	myDiv := html div.
       	self useSpecialId ifTrue: [myDiv id: "specialId"].
       	myDiv with: [html text: ....]

   But bear in mind that these are basically temporary objects - it won't do you any good to stash them in an ivar and try to use them later, for example.

   The Canvas implementation in recent 2.6a versions is relatively complete (we're using it on one of the projects I'm working on), but there are no doubt still lots of holes to patch up and conveniences to add, so feel free to pitch in.

   Avi Bryant
   Mon Jun 20 17:18:45 CEST 2005

   ### What is the new header API, what is the motivation?

   See original post in the mailing list

   Hi

   Now that both Seaside 2.7a1 and 2.6b1 have the "new" header API i think its time to write something short about it so people don't have to ask.

   The old header API was suffering from the same problems as the old renderer API. Just to add an stylesheet with media and title you had to copy and paste about 4 methods. Addional 4 for alternate stylesheets. If you wanted a new conditional import you needed to copy and paste a 3 LOC method. And so on. So we followed the same path like the Canvas API and made use of cascades.

   The new API offers four base methods to create elements

   - #base, for base elements
   - #if, for conditional imports
   - #link, for link elements
   - #meta, for meta elements
   - #script, for script elements

   Most of the time will want to use one of these two convenience methods:

   - #javascript, for JavaScripts
   - #stylesheet, for CSS stylesheets

   See the classes WABaseElement, WAConditionalComment, WALinkElement, WAMetaElement and WAScriptElement for details

   examples:

       aRoot stylesheet
           url: 'styles/blue.css'

       aRoot stylesheet
           document: 'a { color:red; }'

       aRoot javascript
           url: 'scripts/scriptaculous.css

       aRoot if lessThan; ie7; do: [
           aRoot javascripts
               url: 'iehacks.js' ]

   stuff that was just awkward to do with the old api:

       aRoot link beAlternateStylesheet; beCss;
           addProjection; addPrint;
           title: 'Blue';
           url: 'styles/blue.css'

   Contrary to the Canvas renderer API the new header API in the background still used the old implementation. So you will have to implement no methods like #rendererClass.

   If you use the old API on Seaside 2.7a1 and have the development toolbar on you will get a warning pointing to where you use the old API. These methods include the code that you should replace yours with.

   Philippe

   ### What is source code structure of Seaside in VisualWorks?

   For many different reasons Seaside is broken into a complex and cumbersome bundle/package structure.

   At a higher level, Seaside is broken into three bundles :

   - Seaside-VW
   - Seaside
   - Seaside-WekToolKit
   that must be loaded in the exact same order shown above.

   The first bundle Seaside-VW contains pre-requisites and is actually preparing VisualWorks for Seaside. This bundle also has a complex structure. See below for further details.

   The second bundle Seaside contains the original Seaside code unaltered from Squeak. The structure of this bundle is derived from the corresponding Seaside Monticello package. No further details are provided here.

   The third bundle Seaside-WebToolKit contains the integration code for running Seaside inside the WebToolkit framework, along with some patches to both Seaside and WebToolkit. See below for more information.

   Note: There exists also a Seaside-Swazoo bundle that contains the integration code for running Seaside inside the Swazoo framework. This is described below in more details.

   One-click loading: Loading Seaside means loading the three bundles in the order above, making sure the bundle versions are compatible. However to provide one-click loading, there is another bundle named SeasideForWebToolkit that contains a script that loads the three bundles programmatically.

   The contents of the Seaside-VW bundle are :

   - Squeak-Chronos - This bundle adds Squeak compatibility to the base VisualWorks image and includes a full port of the Squeak Chronology classes providing classes like Duration, Year, Month, Week, etc. This bundle contains all the known Squeak compatibility extensions that could be found in the repository. It can be used for any project that needs Squeak compatibility.
   - Seaside-Store-Patch - This package includes a patch to Store to allow loading of packages that include a $/ in their name. Note : Those names were given a few years ago, renaming those packages would be a risky task.
   - Seaside - This package defines the Seaside namespace. The definition of the Seaside namespace was originally done in the Seaside bundle (see below). However it had to be defined earlier so that the Squeak versions of the Date, Time, TimeZone and Color classes could be made available to the Seaside namespace.
   - Seaside/VW Support - This package includes extensions to the VisualWorks classes that are needed by Seaside. It also includes the SeasidePlatformSupport class that is expected by Seaside. This class includes many utilities on the class side that are used to create the Seaside ports. Method #portSource answers a constant that represents the original source of the Seaside Monticello package.

   The contents of the Seaside-WebToolKit bundle are :

   - Seaside/Patches - This package includes patches to the Seaside code in the form of extensions and overrides. These patches are there to fix issues that are still not fixed in the Seaside Squeak source.
   - WebToolkit/Patches - This package includes patches to the WebToolkit code in the form of extensions and overrides. These patches are there to fix issues that are still not fixed in the WebToolkit product.
   - Seaside/WebToolkit - This package contains the actual integration between Seaside and WebToolkit, i.e. pieces of software that are specific to WebToolkit. The most important item is the SeasideServlet class. Of interest is the AAADocumentation class that provides guidelines on how to set things up and a few methods that are used to build the sample HTTP server and the sample web site.

   The contents of the Seaside-Swazoo bundle are :

   - Seaside/GIF - This package includes some classes from VisualWave that are needed to support GIF images, since Swazoo does not have any support for GIF.
   - Swazoo/Patches - This package includes patches to the Swazoo code in form of extensions and overrides. It adds explicit support for cookies that is missing in Swazoo.
   - Seaside/Patches - This package is the same as the one included in the Seaside-WebToolKit. See above.
   - Seaside/Swazoo - This package contains the actual integration between Swazoo and WebToolkit, i.e. pieces of software that are specific to Swazoo. The most important item is the SeasideResource class. Of interest is the AAADocumentation class that provides guidelines on how to set things up and a few methods that are use to build the sample Swazoo server.

3. ## How to

   ### How do I remove the tool bar?

   Set the value of "Deployment Mode" to false using the dispatcher editor ("config").

   This can be also done programatically in the #initialize method of the application's root component.

   `

       	initialize
       		| app |
       		app := self registerAsApplication: 'app-name'.
       		app preferenceAt: #deploymentMode put: true.

   `

   ### What is the most simple way to serve files from a Seaside application?

   The most convenient way to serve files like pictures or stylesheets from a Seaside application is WAFileLibrary. See the class comment of WAFileLibrary for more information about how to use it.

   The following assumes that you have defined MyFileLibrary as explained in the class comment.

   First you will need to setup the root of your library. Typically this can be returned by a method.

   `

       	library
       		^MyFileLibrary

   `

   To display an image

   `

       		html image url:
       			"myPicturePng is the method in which the picture is stored"
       			(self library urlOf: #myPicturePng).

   `

   To display an image button (within a form)

   `

       		html imageButton
       			url: (self library urlOf: #myButton.gif);
       			callback: [self commit].

   `

   To add a stylesheet and a javascript

   `

       	updateRoot: anHtmlRoot
       		super updateRoot: anHtmlRoot.
       		anHtmlRoot stylesheet url:
       			(self library urlOf: #myStyle.css).
       		anHtmlRoot javascript url:
       			(self library urlOf: #myJavascript.js).

   `

   Advanced users might want to use Apache 2.

   ### How do I access the initial request fields in my root component or task?

   To access the initial request fields in a root component or task override #initialRequest:. You will get a request object as argument that you can ask for #fields.

   ### How do I clean up external resources owned by Seaside sessions?

   When a Seaside session is not used during a certain duration, it expires. After a session has expired, it cannot be used any more.

   By default, this duration is 10 minutes (600 seconds) but it can be set to any other desired value using the "config" application ("Session Expiry" field). It can also be set programmatically

       	app preferenceAt: #sessionExpirySeconds put: 1200

   From time to time, Seaside processes expired sessions (see #unregisterExpiredHandlers). Expired sessions are removed from Seaside, making them candidates for future garbage collections, then they are sent #unregistered. The standard implementation of #unregistered in WASession is empty.

   If it is necessary to release resources held by an expired Seaside session, this can be done by subclassing WASession and by reimplementing the #unregistered method.

   ### How do I subclass WASession?

   It is sometimes necessary to subclass WASession. Typical situations for subclassing WASession.

   - Need to clean-up external resources when Seaside session expires (reimplement #unregistered)
   - Need to attach some data to the Seaside session using additional instance variables
   - Need to include additional behavior, statistics, monitoring (reimplement #responseForRequest:)

   Seaside applications are assigned their session class using the "config" application ("Session Class" field). It can also be set programmatically

       	app preferenceAt: #sessionClass put: MySession

   ### How do I subclass WAApplication?

   It is sometimes necessary to subclass WAApplication, for instance when it is needed to display a session expiration page.

   When you subclass WAApplication, make sure that the subclass reimplements #description on the class side, this will ensure that you can differentiate the WAApplication subclasses in the "config" application. Once the WAApplication is in place you can use the "config" application to create your Seaside application.

   New Seaside applications can also be created programmatically by carefully reimplementing #applicationWithPath: on the class side of your root component.

   ### How do I get the requester's IP address?

   It is sometimes necessary to know the IP address of the requester. For instance you may want to produce a different behavior when the request comes from "localhost".

   The IP address is normally available from the native request object. The native request object is obtained by sending #nativeRequest to the current Seaside request object, like this:

       	renderContentOn: html
       		nativeRequest := self session currentRequest nativeRequest.

   The native request object will be a Kom request, a Swazoo request or a WebToolkit request depending on the exact environment.

   For instance, with Squeak

       		ipAddress := nativeRequest remoteAddress.

   ### How do I display an expiration page?

   When the user wants to reuse an expired Seaside session, Seaside silently starts a new session. It is sometimes necessary to change this default behavior and notify the user that the session has expired.

   First thing to do is to subclass WAApplication. Next thing is to reimplement either #handleExpiredRequest: or #expiryPathFor:

   In #handleExpiredRequest: you are given a chance to build a redirect response to another Seaside application that will display the expiration component.

   Below is a very simple example based on reimplementing #expiryPathFor:

       	expiryPathFor: aRequest
       		^ self basePath , '?expired=true'

   The expired=true field can be obtained by implementing #initialRequest: in the application root component, for instance

       	initialRequest: aRequest
       		(aRequest fields includesKey: 'expired') ifPresent: [restartedAfterExpiration := true].

   The rendering can then take expiration into consideration, for instance

   renderContentOn: html restartedAfterExpiration ifTrue: [ self renderExpiredOn: html ] ifFalse: [ self renderNormalOn: html ]

   ### How do I make Seaside VisualWorks serve shorter URLs such as http://localhost:8008/counter?

   If you would like to make the VisualWorks Seaside application server manage all the path-information on its own and to let it appear in the root like:

   http://localhost:8008/counter

   then you need to load the SeasideShortPath parcel that can be found in the contributed/other/Seaside/BonusPack directory starting with VisualWorks 7.3

   ### How do I reset the Seaside administrator password?

   To view

       	(WADispatcher default entryPoints at: 'config') preferenceAt: #login.
       	(WADispatcher default entryPoints at: 'config') preferenceAt: #password.

   and to change:

       	(WADispatcher default entryPoints at: 'config')
       			preferenceAt: #login put: 'new id'.
       	(WADispatcher default entryPoints at: 'config')
       			preferenceAt: #password put: 'new password'.

   ### How do I purge all existing sessions that might be open.?

       WARegistry clearAllHandlers.
       Smalltalk garbageCollect.

   ### How do I provide an anchor where the document is created after the link is clicked?

   With the code shown below the MIME document is created at render time, but the data I want sent is dependent upon the fields on the form.

   `

       	html anchor
       		document: anObject mimeType: mimeTypeString fileName: fileNameString;
       		text: 'Export (csv)'.

   `

   Is there a convenient way to make the document be created after the link is clicked?

   Yes, this is a common problem. One solution is to create an anchor and redirect:

   `

       	html anchor
       		callback: [ self session returnResponse:
       		   (WAResponse
       			document: anObject
       			mimeType: mimeTypeString
       			fileName: fileNameString) ];
          		with: 'Export'.

   `

   ### How do I secure a Seaside application for deployment?

   - remove all not needed applications
   - put the remaining applications into deployment mode
   - remove the config application or choose a good username and password (not the default!)
   - make sure you're projected against SQL-injection

   ### How does Seaside protect me against XSS?

   Per default all output is escaped for HTML unless especially reqested by using the #html: method.

4. ## What is wrong

   ### Nothing happens when I click this link?

   When the callback attached to an anchor is not evaluated, make sure you check that #with: or #text: is the last message sent to the anchor brush.

   `

       	html anchor
       		callback: [ self close ];
       		with: [
       			html image
       				fileName: 'closeButton.png';
       				mimeType: 'image/png'].

   `

   ### I have problems with the canvas api, where should I look?

   Make sure you check that #with: or #text: is the last message sent to the anchor brush.

   ### I have problems with forms or input fields, where should I look?

   Make sure that you have one, and only one form around your input fields.

   ### My Seaside session object does not receive #unregistered?

   When a Seaside session is not used during a certain duration, it expires. After a session has expired, it cannot be used any more.

   From time to time, Seaside processes expired sessions and sends them #unregistered. This is not immediate and it may take some time before Seaside enters this expiry process. With its default algorithm, Seaside expiry process occurs only when starting a new session, once every 10 sessions in average (see #registerRequestHandler: and #shouldCollectHandlers). If no new session are started, the #unregistered message is not sent. The more new sessions are created, the more the #unregistered message is sent.

   Beware, a common mistake is to name the method #unregister rather than #unregistered

   #### Avi Bryant 3 Oct 2004

   Original post

   One of the things I added in the recent 2.5b5 release was an ExpiryTest application which let me do some ad-hoc testing of the expiration and unregistration mechanism. As far as I can tell, things are actually working, although it's fairly erratic when exactly #unregistered will get sent - usually quite a while after the session actually expires, since the cleanup is only triggered by (on average) every 10th new session creation.

   If you want to play with this yourself, execute "WAExpiryTest install" and then go to /seaside/expiry. Hopefully the links/stats are fairly self explanatory.

   I think what I will probably do is start a background process that does the cleanup every few minutes, instead. The only small concern I have about this is that it's one more thing to break - you might not notice that the cleanup process had died somehow, and end up with a lot of expired sessions sitting around in memory. The way it is now, it's tied directly to the web server process, and if that goes down you'll hear about it :).

   Avi

   ### My page displays unexpected text

   When you see unexpected text in your rendered page (typically html tag names), you may have to verify that you are using the correct renderer class.

   When you are using the old rendering API, you must tell Seaside to use the corresponding renderer class WAHtmlRenderer. Your component must implement #rendererClass like this

   `

       	rendererClass
       		^WAHtmlRenderer

   `

   This is especially important when you upgrade to Seaside 2.7 from an older version. In older versions of Seaside the default renderer was WAHtmlRenderer. Starting with Seaside 2.7, the default renderer is WARenderCanvas. Starting with Seaside 2.8, the old WAHtmlRenderer is no longer available.

5. ## Deployment and maintenance

   ### How to exclude applications from the Seaside main dispatcher?

   Before deploying for production, it is not a bad idea to remove from the Seaside dispatcher all those applications that are not strictly needed. Otherwise, users may accidentally enter the "counter" or the "store" demo applications.

   First of all, you will have to explicitely designate those Seaside applications that are deployed. This is achieved by re-implementing the #isDeployed class method in the root component of the deployed applications. By default, this class method answers false, only the dispatcher editor ("config") and the dispatcher navigator ("browse") answer true.

   Then ,to remove applications from the Seaside dispatcher, evaluate the following:

       WADispatcher default trimForDeployment.

   This will remove all those applications that answer false to message #isDeployed.

   ### How to deploy Seaside VisualWorks behing Apache?

   You can run Seaside under VisualWorks behind Apache using either the the CGI gateway or the CGI Perl Interface.

   There is however some potential difficulties to take into consideration. By default, Seaside is designed to use only one WADispatcher object and the WADispatcher object has a hard-coded base URI. Therefore, if you start your image, access Seaside through TinyHttpServer, then access Seaside through Apache, the access through Apache should fail because the WADispatcher object has been initialized with the TinyHttpServer URI and does not recognize the Apache URI.

   For instance if the first Seaside visitor comes in through TinyHttpServer with a request for 'seaside/go/counter', the WADispatcher base path will be 'seaside/go'. When another visitor comes in through Apache with a request for 'cgi-bin/visualworks.pl/seaside/go/counter', Seaside uses the REQUEST_URI environment variable and the WADispatcher does not find any match.

   The problem would be solved if the Apache request would come with REQUEST_URI equals to 'seaside/go/counter'. This might be possible by modifying the perl script so that it modifies the REQUEST_URI variable before transfering the HTTP request to VisualWorks.

   I (Michel Bany) recently made an attempt to solve this issue differently by implementing the concept of alternate servlet. See the Seaside mailing list post.

   With this concept there are two SeasideServlet instances rather than just one. Each instance has its own separate WADispatcher object. As a result you may serve Seaside applications through two different base URIs.

   The alternate servlet support has been included in VW 7.3.

   The parcel for alternate servlet support is inside the BonusPack folder and is named SeasideShortPath. You will need to use a different URI when coming through Apache, something like for '/cgi-bin/visualworks.pl/counter' rather than for 'cgi-bin/visualworks.pl/seaside/go/counter'. With the later, Seaside would attempt to use the default servlet and would fail. With the former, it will drop into the alternate servlet and initialize a new WADispatcher with the right base path. Having explained all this, I believe that the best solution will be to have multiple WADispatcher objects available for the SeasideServlet providing support for multiple channels into Seaside.

6. ## Errors and messages

   ### Error: Components not found while processing callbacks: ....

   Make sure return any subcomponents of a component in the #children method. If the subcomponents change over the lifetime of the component, register it for backtracking.

   ### I have some kind of JavaScript error

   Use Firebug to get more information.