Tips and Hints for starting developing with COAST

Index


General overview


Some Details


Short description of COAST

Abstract

COAST is a platform for developing and deploying World Wide Web applications. For development, it provides a framework, reusable components, and a configuration mechanism that is used to create web applications. For deployment, it provides an efficient and scaleable server and additional flexible communication infrastructure.

Motivation and Highlights

Implementing World Wide Web applications typically centers around writing Common Gateway Interface (CGI) programs for an HTTP server. As long as these web applications are not too sophisticated simple implementation in Perl or Python suffices. If a web application has to maintain the notion of a session, that is keeping state across multiple pages, the naive CGI approach is getting cumbersome because HTTP servers and the CGI mechanism has no simple means for maintaining state. Keeping state in files within the filesystem is slow and doesn't scale very well. In addition since http servers typically call CGIs concurrently appropriate file locking has to take place.

The design and implementation of COAST started out as an attempt to solve the problem of maintaining state within a session in an efficient and scaleable way. The underlying architecture was based on the concept of a server framework. The basic server receives requests for pages from an associated http server. In order to handle a request a developer has to override a single method. Because the method belongs to an object that can be preserved across requests it is simple to keep state across requests too.

Steps to perform for developing a new COAST application

  1. You need a concept for your target system e.g.
  2. Then you must match your requests to the structure COAST is offering. That means
  3. Now set up your developing environment (see Starting a new COAST application)
     
  4. Go on adding the necessary configuration files and writing some code (e.g. for the back end)
     
  5. Test your application using the configurable trace and debug output (see How to Debug )
Top of the page

Starting a new COAST application

Top of the page

What COAST is made of

The COAST framework consists of the following C++ classes:

COAST Class-Index

Furthermore there are some predefined make files to create a linkable library. These makefiles are updated automatically supported by Sniff+.

By the way, COAST can be generated for SunOS5.[678], Linux >= 2.1.2 and Win32!

In order to get a running application one has to add some mandatory configuration files
(Add this files in a different directory structure than the COAST sources):
  • Config.any
  • Tracer.any
  • 'YourFirst'Page.any
  • Page.any
  • Role.any
  • Server.any

For example in our Hello World Project there are the following files:
In subdirectory
'helloworld_src'
In subdirectory
'config'
In subdirectory
'config/HTMLTemplates'
In subdirectory
'config/HTMLTemplates/static/images'
HelloWorldActions.cpp
HelloWorldActions.h
Config.any
Tracer.any
HelloWorldPage.any
OutputMapperMeta.any
Page.any
PicturePage.any
Role.any
Server.any
HelloWorldPage.html
PicturePage.html
SharedPageLayout.html
coast_500x250.png
coast_200x100.png

For a deeper description of COAST see COAST Class-Index
 
Top of the page


How to Debug

  1. Trace output on cerr:

    For debugging purposes there are a Tracer class and macros. This macros help keep the coding expense for inserting trace statements into the source-code at a minimum. If the preprocessor flag DEBUG is not set they expand into nothing. To keep the trace output at acceptable levels we introduced a config file for debugging Tracer.any. Therein you can switch the trace on and off.
    At the top of Tracer.any you can set some general switches:
    [[#wd DisplayAnythingRenderer {
    	/AnythingInfo {
    		"/LowerBound        10      # 0 => no debug output"
    		"/UpperBound        120     # "
    		"/DumpAnythings     1       # print full Anythings"
    	}
    }]]
    
    Trace statements are scoped. In every scope of a C++-Program you can use a StartTrace or StartTrace1 macro. They take as a first parameter a trigger e.g. StartTrace(Server.Load). This results into output onto cerr like Server.Load: --- entering --- and Server.Load: --- leaving --- on entering resp. leaving the scope. Within the scope you can use as many Trace macros as you need. They are all set with the same switch. To set the switch you have to insert the following lines into Tracer.any
    [[#wd DisplayAnythingRenderer {
    	/AnythingInfo {
    		"/Server {"
    		"	/MainSwitch     40"
    		"	/EnableAll      50"
    		"	/Load           45"
    		"}"
    	}
    }]]
    
    The keyword MainSwitch enable or disable the output from all those traces which start with "Server". The keyword EnableAll overrides the specific switches (e.g. Load). See as well Tracer.cpp or rather Tracer.h and Tracer.any.
  2. Debug output at the end of each HTML-Page:

    If the flag DEBUG is set, some information about session, stores and so forth are always rendered into the reply in 'Context::HTMLDebugStores'. So you can check the actual context from which the shown HTML-Page depends at the end of the page itself.
    (Have a brief look at the end of this page.)

  3. Additional Debug Information:

    See [[#wd Lookup Recipe22 ]] for adding additional Debug output, but be aware that there you make a change to the framework.

  4. Native Debug Output

    With some environment settings you have the possibility to get more information about the inner work from COAST.
    The values of WD_LOGONCERR and WD_DOLOG control the level of severities shown either on the console or in the syslog.
    Possible values are:

      1: DEBUG
      2: INFO
      3: WARNING
      4: ERROR
      5: ALERT
    
    The flag TRACE_STATICALLOC shows you the allocation and deletion of all statically allocated objects used in COAST.
Top of the page

Architecture of renderer specifications

In order to let the COAST know which renderer to use now and what data to overgive, a renderer specification is needed. It's obvious that the renderer specification is described in an anything format and it has the following principle structure:

[[#wd DisplayAnythingRenderer {
	/AnythingInfo {
		"{"
		"	/'renderername' {"
		"		/'moreInfosForThisRenderer'"
		"	}"
		"}"
	}
}]]

With 'name' this individual renderer specification will be found;
Under the key Type you specify which renderer is meant;
Under the key Data some Parameters for this renderer can be configured and therefore this deeper structure depends on each given renderer type;

Samples:

[[#wd DisplayAnythingRenderer {
	/AnythingInfo {
		"/AnElementOfForm {"
		"	/TextField {		# 'TextField' is an alias for TextFieldRenderer (see Config.any)"
		"		/Name	username"
		"		/Value	UserNameField"
		"		/Size	32"
		"	}"
		"}"
		" "
		"/MyBuildingBlock {"
		"	/String {			# 'String' is an alias for StringRenderer (see config.any)"
		"		/Default	"Hello World""
		"	}"
		"}"
	}
}]]

The HTMLTemplateRenderer is a tiny bit especial, because you can either define the whole specification in the *.any file or you can refer to a HTML Template file.

In addition there is a different kind of structure to call recursively another renderer specification within the data block, that is:

[[#wd 'renderername' 'rendererdata' ]]
[[#wd Image rule02.gif ]]
[[#wd Image { /ImageName "MyPhoto.gif" } ]]

Keep in mind that this only can be used within HTML-Description and that HTML-Description is possiple as well in an own HTML-File and (quoted) in the renderer specification if the Type is HTML !!!

A closer look at the above examples will preserve you from confusion, where to use which form of the specification.

Top of the page


Miscellaneous

Top of the page