AjaxToaster Tutorial

This tutorial introduces the AjaxToaster server which simplifies the task of writing a service oriented database backend for Ajax clients.


What is this all about?

Todays modern web applications can be written using one of the new JavaScript libraries that provide a rich user experience, often equal to a locally installed traditional fat client application. Part of the power behind this approach is that the applications use a design pattern known as “Ajax” (Asynchronous Javascript and XML) which allows the client to interact with the server without reloading the web page.


For an Ajax client to provide really useful functionality it must normally interact with a relational database on the server, which is when things can become complicated very quickly. AjaxToaster allows clients to get data from a database and save data to a database simply by passing an HTTP request to a URL.


It does this by linking the URL to an “XMLToaster” script which provides the power to extract/update relational database data. This tutorial will cover some of the basics of the XMLToaster, but for more in depth coverage please look at the XMLToaster tutorial on the www.inverse2.com web site.


And just in case you are thinking that by using XMLToaster we are restricted to only using XML data then there is no need to panic... AjaxToaster can serve up your data as either XML or JSON.


Getting Started

There are two ways that you can run the AjaxToaster, either as a Java Servlet from within a web server such as Tomcat or as a standalone server.

This tutorial will explain how to set things up in Tomcat in a later section. For now we are going to see how to run AjaxToaster as a standalone process, which is ideal for testing or if your web server is not a Java web server but you still want to use AjaxToaster.



Prerequisites

To run AjaxToaster as a standalone process you need Java 1.4 (or above) installed and the following JAR files on your CLASSPATH;



Note that the ajaxtoaster and xmltoaster jar files above have “-n.n.n” in their names, which just means use the latest versions.


Note that in this tutorial we will use the MySQL database, the JDBC driver JAR file can be downloaded from http://dev.mysql.com/downloads/connector/j/5.1.html



You can get the “ajaxtoaster” and “xmltoaster” JAR files from either of the following URLs;


http://www.sourceforge.net

http://www.inverse2.com


You can get the Jetty files (and the servlet-api JAR) from;


http://dist.codehaus.org/jetty/jetty-6.1.8/jetty-6.1.8.zip


Download the zip file, unzip it and the required JAR files are in the 'lib' directory.


The JDOM and JAXEN files can be downloaded from the following URLs;


http://www.jdom.org/downloads/index.html

http://jaxen.org/releases.html



Starting Up the Standalone Server

AjaxToaster is bundled with the lightweight “Jetty” server. This is a small, reliable, fast, and above all, easy to operate “servlet container” that can run on almost any platform.

Before you start the process you must ensure that a file named 'toastServlet.properties ' exists within your current directory. Now you can start the service (assuming that your CLASSPATH environment variable specifies all of the JAR files from the prerequisites);

$ java com.inverse2.ajaxtoaster.RunInJetty


By default the service will listen on port 8089 and consume requests to all URLs on that port, therefore you can invoke the service with a URL such as (more details on the URL later);


http://localhost:8089/?toast=myscript.stx&returnxml


If you try entering this URL into a browser you should see something like the following in your browser;










Not very useful! But it shows the server is running and now we can begin setting things up properly.


Server Startup Parameters

You can specify different values for the services' defaults using the following parameters;


-p nnnn to set the port that the server will listen on

-d directory to set the root directory where the server will look for toaster scripts

-c /context to set the services' context,

e.g. http://localhost:8089/context/mapping?params...

-m /mapping to set the services' serlvet mapping,

e.g. http://localhost:8089/context/mapping?params...


Note that the values supplied for the -c and -m parameters should start with a slash.


The “ToasterServlet” Properties File

The 'toasterServlet.properties' properties file can be used to specify how long the service should wait before checking the scripts directory for changes, i.e. if a script has changed or a new script has appeared in the directory the service will refresh its information. By default this will happen every 40 seconds - to change this, include the following line in the properties file;


ToasterPoolRefreshInterval=milliseconds


Replacing “milliseconds” with the number of milliseconds to wait between checks, for example if you specify 10000 the service will check for script changes every ten seconds.


The properties file can also be used to specify the default database connection (this is the database that will be used by any script that does not specify a different database). For example;



default_db_jdbc_pool=mysql


jdbc.driver.mysql=com.mysql.jdbc.Driver

jdbc.database.mysql=jdbc:mysql://127.0.0.1/recipe

jdbc.username.mysql=admin

jdbc.password.mysql=admin


jdbc.driver.sqlserver=com.microsoft.sqlserver.SQLServerDriver

jdbc.database.sqlserver=jdbc:sqlserver://127.0.0.1;databaseName=mySQLserverDB

jdbc.username.sqlserver=admin

jdbc.password.sqlserver=admin


The entry “default_db_jdbc_pool” sets the default database pool to use to a jdbc pool called “mysql”.
The entries for “jdbc.xxxxxx.mysql” specify how to create a connection to the “mysql” database. This uses standard JDBC connection strings and drivernames.

You can tell AjaxToaster to create connections to many databases by defining more sets of jdbc connections, such as the one for sqlserver above – it sets up a database connect to a SQLServer database called mySQLserverDB.


The scripts can specify that they want to use this database (rather than the “mysql” default database) in a script properties file... which we will see later in this tutorial.


Toast Scripts

Files in the services' script directory (specified using the '-d' parameter, or by default your current directory) with the following extensions will be considered by AjaxToaster to be callable by clients;


*.stx - SQL-to-XML scripts, i.e. scripts to extract data from a database

*.xts - XML-to-SQL scripts, i.e. scripts to save data into a database


They use the XMLToaster version of SQL as described in the XMLToaster tutorial and examples.



A Toast Script Example

You should find a demonstration script named 'tutorialTest.stx' with the following content in the toaster directory;


xmlselect using noschema

select

r.recipe_id into xml:{RecipeList.recipe.id},

r.recipe_name into xml:{RecipeList.recipe.name},

r.recipe_price into xml:{RecipeList.recipe.price},

r.chiefs_comment into xml:{RecipeList.recipe.comment}

from

recipe r

order by

recipe_id newValue throwNew xml:{RecipeList.recipe}


Note that you don't have to restart the server if you change the script - the AjaxToaster will automatically refresh. See the ToasterPoolRefreshInterval property described above.


This script needs a database to run against – If you look in the XMLToaster tutorial, it has full details of the “recipe” test database, but for this script, you just need the following table to be defined in your database (we assume it's mySql for simplicity) ...


CREATE TABLE `recipe` (

`recipe_id` int(11) NOT NULL auto_increment,

`recipe_type` char(5) NOT NULL,

`recipe_name` varchar(50) NOT NULL,

`recipe_price` decimal(12,2) NOT NULL,

`chiefs_comment` varchar(100) NOT NULL,

`date_added` date NOT NULL,

PRIMARY KEY (`recipe_id`)

) ENGINE=MyISAM DEFAULT CHARSET=latin1



OK, now we are ready to invoke a script!


Start your AjaxToaster and enter the following URL into a browser;


http://localhost:8089/?service=tutorialTest.stx&returnxml


You should then see something like the following in your browser;






Running A Toast Script

The URL you need to specify to call a script is as follows;


http://host:port?service=scriptname&params


Optionally, you can setup a context and servletMapping using the -c and -p parameters explained above if you want a specific URL name for your AjaxToaster services. In this case the URL is like this:

http://host:port/context/servletMapping?service=scriptname&params



The params can be any of the following;



returnxml

The toaster will respond with messages in XML format

returnjson

The toaster will respond with messages in JSON format

inputxml=xmlstring

An XML message passed into a toast script to update or insert into the database

inputjson=jsonstring

A JSON message passed into a toast script to update or insert into the database

otherparam=value

User specified query parameters. Used as a substitution parameter in the script being run.




The “service=scriptname” parameter is always required and specifies the name of the script that you want to invoke. In our example URL “service=tutorialTest.stx” indicates that we want to run the tutorialTest.stx script.


To ask the AjaxToaster to return results formatted as XML specify “returnxml” as a parameter. To return JSON specify “returnjson”. In our example you can get the data back as a JSON structure using the URL;


http://localhost:8089/?service=tutorialTest.stx&returnjson


Note that if you use this URL from a browser it may not display the data – it will probably ask you to save the data to a file.


If you do not specify “returnxml” or “returnjson” then by default the AjaxToaster will return data as a JSON string. It should also be noted when using JSON that has some limitations in representing data when compared to XML – for instance, AjaxToaster supports “attributes” in the structure of XML messages, but this is not possible in JSON.


When persisting data to a database (running an XML-to-SQL script with a “*.xts” extension) you can specify the input data using either the “inputxml=...” or “inputjson=...” parameters.


Any other parameter in the URL will be passed to the script and used as a substitution string parameter (see the XMLToaster tutorial for full details), for example if we change the tutorialScript.stx script to contain the following;


xmlselect using noschema

select

r.recipe_id into xml:{RecipeList.recipe.id},

r.recipe_name into xml:{RecipeList.recipe.name},

r.recipe_price into xml:{RecipeList.recipe.price},

r.chiefs_comment into xml:{RecipeList.recipe.comment}

from recipe r

where r.recipe_name like '${RECIPE_NAME}%'

order by

recipe_id newValue throwNew xml:{RecipeList.recipe}


Now invoke the service with the URL;

http://localhost:8089/?service=tutorialTest.stx&returnxml&RECIPE_NAME=B


The ${RECIPE_NAME} variable in tutorialScript.stx is given the value of “B” so that AjaxToaster will return recipes with names that start with 'B' (Note - the percent character (%) represents a wildcard in SQL).



The Script Properties File

If you want to modify the behavior of a particular script you can do so by creating a properties file for it. Name the properties file “scriptname.properties”, for example;


tutorialTest.stx - script file

tutorialTest.properties - properties file for the script



In the properties file you can specify the following;


jdbc_pool_name - name of the database connection to use

script_description - a short description of the script

output_style - the style to display the generated XML in the log output (compact, pretty or raw). Compact is the default

db_jndi_name - the name of the JNDI database connection to use. Use of JNDI is described in section that deals with running AjaxToaster in a web container

login_required - flag to indicate if a client has to login before they can invoke the script. This is described in the Security section of the tutorial.

valid_users - a list of users that can run the script. This is described in the Security section of the tutorial.


For example our tutorial script might have the following properties file (named tutorialTest.properties);


jdbc_pool_name=mysql

script_description=An example script from the tutorial

output_style=pretty

login_required=false

valid_users=*


This indicates that it will use the “mysql” database. It also indicates that there is no security on invoking the script.




Using AjaxToaster from a JavaScript Client


A Standard Javascript Ajax Request


This example shows how to invoke an AjaxToaster service from a JavaScript client using plain JavaScript.


<script type="text/javascript">


function getDataFromAjaxToaster() {

var xmlHttp;

try {

// Firefox, Opera 8.0+, Safari

xmlHttp = new XMLHttpRequest();

}

catch (e) {

// Internet Explorer

try {

xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");

}

catch (e) {

alert("Sorry, your browser does not support AJAX!");

return false;

}

}


/** This function will be called when the data is returned... **/

xmlHttp.onreadystatechange = function() {

if(xmlHttp.readyState==4) {

/** Convert returned data into a JSON object... **/

myData = eval('(' + xmlHttp.responseText + ')');

// now do something useful with the data...

//e.g. myData.RecipeList.recipe[0].price = '10.00';

}

}


/** Invoke the service... **/

xmlHttp.open("GET", "?service=tutorialTest.stx&returnjson", true);

xmlHttp.send(null);

}


</script>


There is a fair amount of setup code but the highlighted code indicates lines that are relevant to calling an AjaxToaster service, simply passing a URL in the format that we have seen before in this tutorial.


When the server responds, the response JSON string is converted into a javascript object that the program can then use as it wishes. (Note: because the AJAX call was asynchronous, we setup an xmlHttp.onreadystatechange function, which is automatically called when the server responds)




Using the Ext Framework To Call An AjaxToaster Service


Javascript libraries such as prototype, dojo, and Ext provide functions to greatly simplify messaging to the server. In the following example we will see an example of how a JavaScript library can simplify the “plumbing” code and provide transparent cross browser support.

In this example we are going to use the Ext framework “Ext.data.Connection” class to invoke an AjaxToaster service. Ext is a JavaScript library that provides lots of functionality that you can use to build interactive web applications. For more details see http://www.extjs.com

var serverResponseObject = null;


function talkToServer(serverURL, message) {

var connection = new Ext.data.Connection();


connection.request({

url: serverURL,

jsonData: message,

method: 'GET',

callback: function(options, success, response) {

if (success == true) {

serverResponseObject = eval('(' + response.responseText + ')'); // Converts response into an object

} else {

Ext.MessageBox.alert("Exception",

"There was a problem getting the data from the server: "

+ response.responseText);

serverResponseObject = null;

}

} // end callback function

});

} // end talkToServer()


Your JavaScript application would build up a URL that specifies the service you want to invoke and then you would pass this to the “talkToServer” function. When the server responds the “serverResponseObject” will be initialised with the servers' response.


Note that to use this function in a real application you would probably want a successful “callback” function to call another function that would actually do something with the data...


The “jsonData” parameter can be used to pass data to the server, for example if you want to save data into a database (the Ext Connection object automatically converts the request method to a POST if you specify data).

The www.inverse2.com web site contains more complete example applications ranging from the simple to the quite complex!


Running AjaxToaster in a Servlet Container

The Servlet API Specification 2.2 introduced a standard directory layout for web applications contained within a Web Archive (WAR) file. This section describes what you need to do to set-up a web application that uses AjaxToaster.

The Apache Tomcat web site has much more detail on deploying web applications (see http://tomcat.apache.org/tomcat-6.0-doc/appdev/deployment.html) so this tutorial will simply show what extra you need to set-up the AjaxToaster.

The following information is required in the “WEB-INF/web.xml” file;

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

...

<servlet>

<description>AjaxToaster Servlet</description>

<servlet-name>AjaxToasterServlet</servlet-name>

<servlet-class>com.inverse2.ajaxtoaster.ToasterServlet</servlet-class>

</servlet>

...

<servlet-mapping>

<servlet-name>AjaxToasterServlet</servlet-name>

<url-pattern>/ajaxtoaster</url-pattern>

</servlet-mapping>

...

</web-app>



This web.xml file specifies that there should be a servlet called “AjaxToasterServlet” running the class “com.inverse2.ajaxtoaster.ToasterServlet”, which will receive requests on the “/ajaxtoaster” URL.

Then you simply need to put the required JAR files, detailed in the Prerequisites section above, in the directory “WEB-INF/lib”.



(optional) Defining JNDI entries to connect to your database... see http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html



Security


To specify how to setup the login class....


For https... see;

http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html