View this PageEdit this PageUploads to this PageVersions of this PageHomeRecent ChangesSearchHelp Guide

Comanche HOWTO

More about Comanche, get it at Comanche Downloads.

How to make a simple 'Hello World!' module?

A Comanche module is any object that understands #process:. Comanche sends a #process message with an HttpRequest to the object and whatever is returned, it converts to HTML (or GIF, see more about conversions below) and sends back to the web browser.

So, here are the steps:
  1. create a class named MyHelloWorldModule
  2. create a method #process:, with one parameter, request, that returns a String 'Hello World!':
    • process: request ^'Hello World!'

You're done!

About Conversions

An object returned by a module is converted into a browser-friendly form by Comanche. How does Comanche know which form to convert an object into? Actually, the object's class knows. Each class implements #asHttpResponseTo: message, which takes an HttpRequest and returns an HttpResponse. An HttpResponse contains header information, including content type, size, and the content stream. For example, if you return a FileStream, its generated HttpResponse will contain the FileStream as the content stream (so that it doesn't need to keep it in memory), file size as the content length, and content type will be set to whatever #mimeType that file extension maps to (determined by MIMEDocument)

Some conversions:
  • String is served verbatim, with content type set to HTML. Same is true for several streams (FileStream's content type is set according to its file extension)
  • Text is converted to HTML by translating its formatting into HTML codes and escaping HTML sequences in Text into &-sequences
  • Form (Smalltalk class for images) is translated into GIF (or JPEG)

How to process GET and POST form fields?

When a request comes in, Comanche sends #process: to its modules. The parameter to #process: is an HttpRequest. #getFields retrieves a Dictionary (or HttpFormDictionary, see below) of GET fields, and #postFields retrieves a Dictionary of POST fields.

process: request
  ^'Hello ', (request getFields at: 'name' ifAbsent: 'stranger')




How to build an application with Comanche?

Let's walk through the process of building a simple application in Comanche. I'll use the TurtleGraphicsModule (and its cousin, TurtleFrameGraphicsModule) to demonstrate some key concepts.

Here's what it looks like:
Uploaded Image: kom-turtle.png

This is a more complex example of manipulation of multiple elements that constitute a single web page: the page itself and its resources, images. We will demonstrate this by implementing a simple web based turtle graphics exploration. For simplicity, we will support only three operations: forward, left and right, each of which can take a parameter that corresponds to distance in pixels (forward) or angle in degrees (left and right). The user interface will contain the controls corresponding to these operations and the image that captures the current state of the turtle. The turtle itself will reside on the server and will accept the commands, react to them, and update its state. The first implementation (see figure) incorporates both the command console (a text input, forward, left, and right buttons) and the image in the same HTML page. The TurtleGraphicsModule process: method will distinguish between the ‘turtle.gif?and all other requests and serve the form or the HTML page, respectively. In addition, it will accept form input and manipulate the image according to the commands, i.e., if a user clicks ‘forward?button, the turtle will move forward in its current direction by the amount specified in the text input.

The second implementation of turtle graphics splits the interface into an image and command console frames. This simplifies the logic in the process: method, which now forwards the request to one of three methods: imageForRequest:, topFrameForRequest:, and commandConsoleForRequest:. Furthermore, each invocation of the turtle commands only updates one page (the image), while the command console and the top frame remain unchanged, thus reducing the load on the server.

This example demonstrates how to serve complex objects, with embedded images. It consists of 1 class with 2 instance variables and 2 methods.
(this section is mostly from my Comanche paper, to be released soon)

SinglePlugModule

SinglePlugModule in many ways mimics SinglePlugAction in PWS – you do not have to define a new class to create a Comanche module (application), all you do is specify your module as a block with one parameter, request.

Alternative Hello World example:
module := SinglePlugModule newBlock: [:req | 'Hello World!'].

Alternative way of doing DisplayCamModule:
module := SinglePlugModule newBlock: [:req | Display magnifyBy: 1/8].

As you might have guessed, SinglePlugModule's process: method evaluates the block with the request, and returns the result to Comanche (which in turn converts it to HttpResponse).

Matching the URL

Currently, Comanche doesn't include a DispatcherModule, which would decide which module should run (okay, it will appear in kom4.10). Thus, deciding what shows up on which URL is up to the modules:
... module urlPrefix: '/display' ...
This works with the SinglePlugModule (because it responds to this message, urlPrefix:, and does something intuitive with it).


Admin Workspace

This is how I work with Comanche, by executing various bits of code in the workspace. The recent (week of Feb 5-9, 2001) performance testing (benchmarking) was done that way, as in fact almost everything else. If you are a developer, you should be comfortable with starting off with such interaction mode. But nothing stops you from building a front end, like Swiki's ComSwikiLauncher. Enjoy the console:
svc := LTDComancheService named: 'Comanche1' onPort: 8001.
svc := PWSComancheService named: 'Comanche2' onPort: 8002.
svc := ComancheNetService named: 'Comanche3' onPort: 8003.
svc comancheServer limitConnectionsTo: 5. "only for LTD"
svc module: (HelloWorldModule new).
"svc module: (RemoteDisplayModule new)."
svc start.
svc := nil.
Smalltalk garbageCollect

Preferences disable: #standaloneServer.

"to stop, select all of below and do it"
{ {8001. 'Comanche1'}. {8002. 'Comanche2'}. {8003. 'Comanche3'} }
do: [:portAndName | | che |
	(che := ComancheServer serverOnPort: portAndName first ifAbsent: [])
		ifNotNil: [che stop].
	ComancheNetService removeServiceNamed: portAndName second].

A bit of explanation. The above workspace code allows you to switch between three different types of Comanche server infrastructure (LTDComancheService, PWSComancheService, ComancheNetService). You only need to execute one of these lines, then set the module which will be your application, for example, svc module: (HelloWorldModule new), then do svc start (for LTDComancheService, prior to this step you need to do svc server limitConnectionsTo: 5).

To stop the currently running server, you need to execute the last few lines, then clear out svc variable svc := nil, and clean up Smalltalk garbageCollect. Now you are ready to start another server. By the way, since all these serve on different ports, you could have them run simultaneously. How? That's an exercise for the reader.

How it works

A bit of introduction to Comanche 4.7. I dropped the use of the ComancheModule hierarchy, since very little in it was reused. Now, any object that understands #process: can be a module (ironically, it is still called a module). The new RemoteDisplayModule demonstrates how easy it is to serve multimedia in Comanche: you merely return a Form, and Comanche takes care of converting it into a GIF image. And the ubiquitous Hello World example in HelloWorldModule returns a String, 'Hello World!', which also gets properly converted.

Obviously, for all this to work, you need the latest Comanche 4.7, which will soon be available for download here. I just need to package up the examples referenced above, and include the bug fixes. One of the bugs prevented the HelloWorldModule example from working.

Databases

Some very good news here, and then some not so good news. Today, at least two databases are supported from Squeak, MySQL and PostgreSQL. Since they're open source and free (read their license, there could be some limitations), it's a very good news (if you want to use a commercial database, you perhaps have funds to sponsor development of drivers for it, too). The bad news is that there is no database abstraction layer in Squeak yet. That's something a lot of people are interested in, and one day (perhaps before end of March) we will have it. Until then, most example posted here will be specific to a given database driver. And a really bad news is that there are no examples here yet. Sorry.
z
Who is working on a database spec? As a former ODBC driver designer, I think I might be able to give some input... Cees de Groot Maybe it will use Glorp?

Links to this Page

  • Comanche last edited on 27 May 2002 at 11:41 am by dsl027-164-145.atl1.dsl.speakeasy.net
  • Comanche Downloads last edited on 26 November 2004 at 12:23 pm by 61.232.115.1