Tuesday, 3 March 2009

Seaside 3: Server Adaptors

This is the next in a series of posts looking at changes in the upcoming Seaside release. Check out the other posts on partial continuations and exception handling.

The upcoming release of Seaside will feature some changes to the now-familiar WAKom. The existence of various subclasses like WAKomEncoded and WAKomEncoded39 was beginning to point at a usability problem and we wanted to facilitate running Seaside on multiple ports out of the same image.

First of all, we have introduced an abstract class, WAServerAdaptor. Server Adaptors provide an interface between Seaside and a particular server or connector (e.g. Comanche, Swazoo, AJP) and are able to start and stop server instances on the correct ports. Most importantly, they are also responsible for translating between Seaside's WAResponse and WARequest objects and the native requests and responses required by each server.

Server Adaptors are configured with a port number and a Request Handler. They are also configured with a Codec, which specifies the character conversion that should be performed when converting the requests and responses. Character encoding issues are complex, however, and we are still playing with those interfaces so I will leave that discussion for another time. Server Adaptors get registered with an instance of WAServerManager (currently a singleton) when they are created and the Server Manager coordinates starting and stopping the servers.

To create and start a new Comanche adaptor, you could simply execute:

adaptor := WAComancheAdaptor port: 8080.
adaptor start.

Alternatively, you can use the new Control Panel (implemented with OmniBrowser) to create and configure your adaptors. You can now create and run multiple adaptors of the same type. You can even configure multiple adaptors on the same port (perhaps to facilitate testing different servers or codecs) though only one can actually be running at any time.

Note that WAKom and its subclasses still exist for backwards compatibility in this release and will start an appropriately-configured instance of WAComancheAdaptor. These classes, however, only support running a single adaptor instance at a time and will be removed in a later release. Once created with WAKom, the adaptor will be visible in the Control Panel and can be manipulated there just like any other adaptor.

I mentioned that Server Adaptors can also be configured with a Request Handler. Why would you want to do that? By default, all Server Adaptors dispatch incoming requests to the same default Dispatcher. But perhaps you have an admin interface that you want to run on a different port so it can be firewalled to an internal network. Perhaps you want to make Seaside's web config tool available through an SSH tunnel. Or perhaps you have an XML-RPC interface or a status page for integration with a service monitoring tool. Maybe you just want to transition your application behind a load balancer to a new instance with different configuration options. Whatever the case, if you just want to configure a new Dispatcher using the web interface, the Control Panel has a context menu option called "Use new dispatcher" which will give you a new blank starting point on that Server Adaptor. If you have an existing Request Handler somewhere you can tell the Server Adaptor to use it like this:

adaptor requestHandler: myRequestHandler

Using a Dispatcher at the root will allow you to configure multiple Request Handlers at different subpaths but you could just as easily use an instance of WAApplication, RRRSSHandler, or any custom Request Handler subclass (more on this in a future post) if you want all requests to be handled in one place.

2 comments:

Randal L. Schwartz said...

I hope you're including a bindinghost as well as port in the interface, with a sensible default (either 255.255.255.255 or 127.0.0.1, as long as it is documented).

Julian Fitzell said...

Well, we haven't yet, though I'm certainly aware of the desirability of doing so.

I was under the impression that Squeak, at least, did not have support for binding to particular interfaces but looking now it appears I'm wrong. I'll file an issue in the tracker to make sure this gets done.