Creating a web application with Goanna
- Contents
- This is a short tutorial for building web applications with Goanna
- How it all works
- Installation
- The first steps
- A tour around town
- What happens behind the scenes
- Which servlet shall process the request
- What happens in the servlet
- Handling the parameters
- Processing the parameters
- Generating the answer
- Interacting with a database
- Creating your web application
- A last word
This is a short tutorial for building web applications with Goanna
It covers the following topics
- Installing all the software you need
- Getting to know Goanna
- A short description on how to develop a web application with Goanna
How it all works
Goanna offers many different services and layers of abstraction.
For this tutorial we will use the Goanna web application library. The Goanna web applicationlibrary is a framework which allows to build web applications. The framework itself builds uponthe Goanna fast cgi interface. And on the base of it all is an eposix server. In order to scaleup with the traffic and to be able to host other sites than only the ones created with Goanna wewill use an Apache web server.
The Apache web server interacts with our web application via the fast cgi interface.
Installation
These installation instructions are meant for a (k)ubuntu system. At the time of writing ubuntuFeisty Fawn (7.04) was the current stable version.
First thing first, get a version of EiffelStudio. At the time of writingEiffelStudio 5 (5.7.64493 GPL Edition) was the current stable version. You can find EiffelStudioat http://dev.eiffel.com/downloads.
After installing EiffelStudio according to the instructions make sure that the following environment variables are set:
-
export ISE_EIFFEL={location of EiffelStudio in file system}
-
export ISE_PLATFORM=linux-x86
-
export PATH=$PATH:$ISE_EIFFEL/studio/spec/$ISE_PLATFORM/bin
-
export ISE_C_Compiler=gcc
Next thing you need to get is a few Eiffel libraries
Gobo
- GOBO: get the latest version from http://www.gobosoft.com
set the following environment variables-
export GOBO=location of gobo in file system
-
export GOBO_EIFFEL=ise
-
export GOBO_CC=gcc
-
export GOBO_OS=unix
-
- for further installation notes read the readme.txt
- add the folder
'$GOBO/bin'
to your path.
Eposix
- eposix: http://www.berenddeboer.net/eposix/
set the following environment variables-
export EPOSIX={location of eposix in file system}
-
export EPOSIX_LIB=$EPOSIX/lib
-
- for further installation notes read the file
$EPOSIX/INSTALL
Log4e
- log4e:
svn co https://svn.eiffel.com/goanna/trunk/log4e log4e
- set the environment variable
$LOG4E
to the location of log4e in you file system -
cd $LOG4E
-
geant install
- set the environment variable
Goanna
- Goanna:
svn co https://svn.eiffel.com/goanna/trunk/goanna goanna
- set the environment variable
$GOANNA
to the location of Goanna in you file system -
cd $Goanna/library/utility
-
geant install
- set the environment variable
We are still not done
Install the following packages with your favorite package manager or with aptitude.
- Apache2
- mod_fastcgi
And finally you need to get your fingers dirty
Download DevKit http://www.fastcgi.com/dist/fcgi.tar.gz A how-to-install-source-balls-under-linuxcan be found here: http://www.tuxfiles.org/linuxhelp/softinstall.html .
The first steps
After you have installed everything open a browser and type localhost
onto the location bar. The Apache place holder page should show up. If this is not the case try a good old windows trick, even if we are running (k)ubuntu. Restart. If this doesn't help, you will find a lot of help out in the wild of the WWW.
Now that we have our primary server up and running it is time to get in touch with Goanna.
Create a new directory for the web application. Create an environment variable which points to this directory. For the rest of this tutorial we will refer to this directory as $WEB_APP
.
Goanna comes with a template for building web applications. Therefore we don't have to write the whole application form scratch but can start right away with the interesting part. The template can be found at $Goanna/example/application
. So copy the content of $Goanna/example/application
into your $WEB_APP
folder. If you have an SVN version of Goanna remove any .svn
directory from the copied template.
If you like you can change the name of the application in the system.xace
and the build.gant
file. Once you have done this open a console, navigate to $Goanna
and then run the command geant build
. This will take some time (around 5 minutes). But once it is done, we have a ready to run web application. If you wantto work with EiffelStudio you can find a *.ecf
file in the $WEB_APP
folder. Open the project in EiffelStudio and compile it. It is necessary to compile the project even though we just compiled it with the geant build tool. This is because EiffelStudio will generate a set of meta data about the project during compilation.
Now its time to start the web application. Either you can start it from within EiffelStudio or you can use the binary file which was generated by the geant build tool. It is located in the $WEB_APP
folder.
Go back to your browser and type localhost/fastcgi/demo/go_to.htm?question<code> in you
browser. If you get an error saying that the URL is not valid everything is ok. Remember, the
Apache web server communicates with our web application via the fast-cgi interface. But it won't
do this on its own, we first need to configure it to do so.
The setting for the Apache web server are stored in text files which can be found at
<code>/etc/apache2
. You will need super user rights in order to edit the settings. For example you could open a text editor in super user mode and edit the files from within this editor. Open the file /etc/apache2/httpd.conf
and add the following lines:
LoadModule fastcgi_module /usr/lib/apache2/modules/mod_fastcgi.so
FastCgiExternalServer "$WEB_APP/EIFGENs/web_application/W_code/web_application" -host localhost:7878
You need to replace web_application
with the name of your project
If you are not using EiffelStudio the fast cgi server is located at $WEB_APP/web_application<code>
And finally open the file <code>/etc/apache2/sites-available/default
and add the following lines:
Alias /demo "$WEB_APP/EIFGENs/web_application/W_code/web_application"
<Directory "$WEB_APP/EIFGENs/web_application/W_code/">
SetHandler fastcgi-script
Options ExecCGI
Order allow,deny
Allow from all
</Directory>
TODO
You need to replace web_application
with the name of your project
If you are not using EiffelStudio the fast cgi server is located at $WEB_APP/web_application
Now everything is set up, all that is left to do is to restart the apache server so the new settings are loaded. Go to a console and type sudo /etc/init.d/apache2 restart
.
Head back to the browser and once again type localhost/fastcgi/demo/go_to.htm?question
.This time, the page should be displayed.
Congratulations you just finished your first hands on experience with Goanna. Go ahead and play alittle with the web page. Try some combinations of input.
A tour around town
This chapter is a guided tour through the example application. The tour will not go into great depth but still we will see many things so bear with me.
Open your favorite Eiffel editor and open the example web application. The project contains quite a lot of clusters, but all the user code resides in the root_cluster. Within the root cluster you find two sub clusters containing the servlets and the parameters.
If you are not familiar with the java servlet, let me give you a brief introduction, for the rest of you just skip the next paragraph.
The name servlets comes from a mixing of the words server and applets. So servlets are applets which run on a server. Any servlet must implement three features, do_get(request, response),
do_post(request, response) and do_head(request, response)
. Request is an object which holds all the data about the requests. Similarly the response is an object which will hold the generated response which is sent back to the user once the servlet is done with its processing. The do_get, do_post and do_head
features should implement the handling of the HTML requests GET, POST and HEAD.
Now the servlets in Goanna do exactly the same thing as the java servlets - even the interface is the same.
We start our tour at the
The different properties which are set in the
Next we take a look at the
A few classes remain in the root_cluster
. There is the
The
The last class in the root folder is
Now that we came by all the classes in the root_cluster
it is time to head into the parts where the action happens.
Let's first have a look at the servlets. You find three classes in the servlet cluster. Two of them should remind you of the pages which you have seen while taking a look at the web page. The third is
The
By now you may be wondering why we are creating xml documents if we want to return html as a response to the request. Well the xml documents which are created will be transformed to html after the servlet has processed the request. This allows to use the same output of the servlet for different purposes, all that is needed is a rule to transform the xml into the requested format.
The last feature is called name and returns a string. This string is used by Goanna to determine if this servlet is suited to handle a request or not. But more on this later. For now it is ok to think of the name as being an identifier which allows it for a request to specify which servlet should be used to handle it. Since
LetÂ’s move on to the Void
. This will start a <form> right after the <body> started. So if a page contains a form, the last parameter in Void
.
The other difference to the
We already reached the last class in this cluster:
Last but not least we reached the parameters cluster. Similar to the servlet cluster we find a
Goanna provides a large set of deferred parameter base classes from which one can inherit when implementing the parameters. When taking a look at the different parameters in the example one can notice that even if each looks different they have several things in common. Each class offers a method to store and to retrieve the value from the parameter into a persistent storage. Also each parameter class has a name and a label_string. The name is used to uniquely identify the parameter, and the label_string will be displayed besides the input field. It is possible to use the same parameter multiple times on the same page. Goanna parameters offer a suffix functionality. To use this functionality at least one of the following features needs to be redefined:
What happens behind the scenes
Now before we dive into writing our own web application let's have a look behind the scene. Knowing how a request is processed by Goanna is essential in order to be able to write a web application.
When you send a request the apache server tries to match the requested URI to one of its Aliases.If it finds an alias, it will look what kind of reference is referred to by this alias. In the case of a Goanna page, the alias will point to a fast-cgi server. So the apache server will forward the request to the fast-cgi application i.e. the Goanna web application. Now the Goanna application takes over the control.
Basically the Goanna application will perform the following steps:
- determine which servlet will handle the request
- validate the parameters which have been submitted with the request
- execute the servlets main logic
- generate a response
- This all sounds very easy and intuitive but there is more to it than it might appear at first.
Which servlet shall process the request
A web application is basically an application which uses servlets to process requests sent to it. Now if a request reaches the web application it must decide which servlet should process the request. In order to do this, the application must know all servlets which exist in it and it also needs a heuristic to decide which one to choose. Every servlet which wants to process requests must subscribe itself to the /test/web/run.htm
and there are three servlets stored in the /test
, one which subscribed to /test/web
and one which subscribed to /test/web/walk.htm
. In this example /test/web
is chosen, since the /test/web/walk.htm
does not match and /test
is less specific than /test/web
. If there is no servlet which matches the request URI or a substring, the default servlet is chosen, and if no default servlet is specified Goanna will log an error.
When the
What happens in the servlet
Now that the control flow reached the servlet its getting interesting. The entering point for the control flow is the
The first thing the feature does is getting the
After the root_cluster
of the web application. So feel free to add your own features which are helpful for your application.
Before the parameters are processed the feature
Handling the parameters
The next step is to get the parameters from the request. This is done by iterating over all parameters which were passed with the request. Remember, that the parameters which a servlet can process are specified in the constructor of the servlet. The defined parameters come here into play. Depending on which collection a parameter has been added to, it will be processed differently.
In a first step a loop iterates over all parameters and creates an instance of
If everything is OK until here, the parameters are split into two categories, mandatory and non-mandatory. Note that the required parameters are part of the non-mandatory parameters.Then both the mandatory and the non-mandatory parameters are sorted according to their processing order. The processing order is given as an integer value, default is 3. The smaller the
Processing the parameters
Now that the parameters are split and ordered its time to process them. First the mandatory parameters are processed. Processing means that the feature process of the parameter is called. After processing a mandatory parameter the application checks the value of feature
If all mandatory parameters contain valid values, the feature
Generating the answer
In any case, if the processing was interrupted early or if all parameters contained valid values, the servlet will call the
In order to display an answer, a servlet must inherit from
Interacting with a database
What would a web application be without a database. If you only plan to do static pages then don't use Goanna. In order to be independent of the DB a developer chooses, Goanna offers an interface which allows to control the database accesses. The interface is rather simple and can be implemented by the developer if he needs a special database. The class which contains the mentioned interface is called
The
The state of the system changes in the following way:
<e>
some state ok_to_start_version_access start_version_access ok_to_read_data ok_to_end_version_access end_version_access not ok_to_read some state
some state ok_to_start_transaction start_transaction ok_to_write_data ok_to_commit commit not ok_write some state
</e>
Creating your web application
After all this theory its time to start building your first web application with Goanna. The following is all just advise, feel free to follow it or make it your way.
My experience with browsers have shown that they are not made to ease the live of a web application developer. So my first advise is: make a mock-up of your future web application. This does not have to be anything fancy, just some plain old HTML and a CSS file. Once you are happy with the design and the layout its still early enough to start messing with Goanna.
I recommend that you start off with the example web application we created in the first part of this tutorial. A good idea is to subtype the following classes for your application. This gives you places to add common functionalities of the different servlets.
-
GOA_APPLICATION_SERVLET -
GOA_DISPLAYABLE_SERVLET - <e> GOA_PAGE_XML_DOCUMENT (do not redefine any features)
If you take a look at
-
GOA_PAGE_ATTRIBUTE_VALUES -
GOA_PAGE_SCHEMA_CODES
Also in the cluster you find the
In any case you should implement the class
For every page in your web application repeat the following steps.
- As you do this you probably have to add features to other classes in order to store
intermediate values, or to pass values from one class to an other. - Values which should persist over several requests, but are not stored in the DB, go
into the classSESSION_STATUS . Values which should be discarded after the request
has been processed go into the classREQUEST_PROCESSING_RESULT . Both classes are
available from almost all functions and are meant to be containers for such values. - Make a list of all parameters which your page should be able to handle.
- Mark all parameters which are mandatory. That means that the servlet cannot process a
request if the parameter is missing or invalid. - Mark all parameters which are required. That means that the servlet cannot process a request
if the parameter is missing, but the processing of the servlet does not depend on the
correctness of this parameter. - Mark all parameters which are optional. That means neither the presence nor the correctness is a requirement for the processing of the servlet.
- Mark all parameters which should be added if they are missing.
- Sort the list of parameters in the order they should be processed. Make sure that if
the validation and the processing of parameter A depends on the processing of parameter
B parameter B is listed before parameter A. - Give each parameter a processing priority. This can be done in an iterative way. Where
ever parameter starts with a priority of 3. If parameters A depends on parameter B then
A.processing_priority = B.processing_priority+1. Repeat this until no more parameters change
their processing priority. - Create all parameters which you haven't created for another page. Be careful if a parameter
is used in more than one servlet. The processing priority is the same for all pages where a
parameter is used. You don't have to write your parameters from scratch but you are encouraged
to inherit from one of the deferred classes in the goa_parameters cluster. - The most important task a parameter has to perform is to validate the correctness of its
value. If you ever focused a little on security in programs you know that any input from
the outside has to be considered hostile until it has been validated. And since your web
application is going to be published on the WWW and everybody can access it you should be
even more concerned about validating the values of the parameters which are transmitted with
a request. - After all parameters are created redefine those features of the servlet which you will need
for your servlet to work properly. But remember, the parameters should handle themselves. In
Goanna it is not the responsibility of the servlet to be concerned about parameters. Still the
framework offers you three features to hook into the processing of the servlet and let you
influence its behavior. Here is the list of the features which you can use as hooks into the
processing of the servlet. - perform_post_mandatory_parameter_processing
- perform_final_processing
- perform_invalid_mandatory_parameters_processing
- I recommend you to separate the logic and the displaying of a servlet. Therefore you should create a
DISPLAYABLE_SERVLET for everyAPPLICATION_SERVLET which does not make any
calculations but focuses solely on generating the output. - Implement the missing features of the
DISPLAYABLE_SERVLET .
A last word
This guide is only an introduction to Goanna, also is the Goanna framework at the time of this writing still under heavy development and may change fundamentally. So there is no guarantee that what is described in the chapters above will hold at the time of reading.
Also not all topics have been covered in depth and others have even been touched at all. But remember code and contracts are the best documentation...
Specially the following topics have not found enough space in this guide.
- SSL
- Parameter Suffix
- The different parameters classes
Great Tutorial
Thank you for doing this, Till. One thing I'd like to add is that the parameter collections are for validating the semantics of a submitted form, not for validating user input.
Mandatory Parameter Collection - These are mandatory at the form processing level, not required fields in the form the user sees. Typically, these are a html hidden elements used to verify that some system state is the same at form processing time as it was at form generation time. For example, it might contain the user name of a logged in user to prevent them from submitting a form, logging out, logging in as a new user, and then using the back button to resubmit the previously generated form for the previous user.
Required Parameter Collection - These are html elements which must be present in the form for correct processing to occur or whose absence indicates a serious bug in the form generation routine or an attack on the web site. This doesn't necessarily mean that the user must provide a value for the element. "address_line_2" on a registration page might be an example of a required parameter for which no user input would be required.
Optional Parameter Collection - These are elements whose absence from a submitted form is expected sometimes. No processing for this parameter will occur if they are not present in the form.
Add If Absent Parameter Collection - These are elements whose absence from a form has meaning. html checkbox elements provide a typical example. If they are not present in the form submittal, a PARAMETER_PROCESSING_RESULT for them is added so that the appropriate processing for their unchecked state will occur.
Validating User Input
Each GOA_REQUEST_PARAMETER is responsible for validating the input it receives from the user. Since receiving invalid input is expected, this does not interrupt request processing. Typically, invalid user input produces
"not PARAMETER_PROCESSING_RESULT.is_value_valid"
which in turn triggers the redisplay of the form with an error message. Several GOA_REQUEST_PARAMETER descendents implement this behavior for common data types.
Will update tutorial
Thanks Neal,
I will integrate this info in the tutorial on Goanna's Origo page too.