RESTful Web
Service Tutorial
Part 1: Building a simple GET RESTful Web
Service
Part 2: Building a simple POST RESTful Web
Service with Basic Authentication
Part 3: Building a simple DELETE RESTful with
Path Parameters
See also: Publishing RESTful Web Services Overview, RESTful Services, Endpoint Scripting, Server Admin Web Service Administration, Publishing Web Service Documentation
The following tutorial demonstrates how to create a basic pet store
RESTful Web Service. The following sections demonstrate how to:
Prerequisites for
running this tutorial:
Installed Features:
Ebase
XI Integration Server [x]
In this tutorial, we will create a new RESTful Web Service and add an endpoint to retrieve all the pets in our online pet store application. The endpoint accepts two optional request parameters that filter the type of pet and limit the number of pet records retrieved from the database. We will also add a script to test whether the database table exists and create it if required that we will be using in this tutorial.
Create a RESTful Web Service and add a table and an endpoint.
importPackage(com.ebasetech.xi.api);
importPackage(com.ebasetech.xi.services);
/**
* Check whether a database table exists and
create the table if it does not.
* @param dbName database name to use
* @param
tableName database table name to check or create.
*/
function createTables(dbName,
tableName)
{
var
exists = checkTableExists(dbName,
tableName);
if(!exists) {
var created = createTable(dbName, tableName);
if(created)
{
//populate the database table with some data
insertPets("EBASE_SAMPLES", "pets", 1, 'Rover',
'Black and White Collie', 'dog');
insertPets("EBASE_SAMPLES",
"pets", 2, 'Freddy', 'Chocolate Labrador', 'dog');
insertPets("EBASE_SAMPLES", "pets", 3,
'Bobby', 'Golden Doodle', 'dog');
insertPets("EBASE_SAMPLES",
"pets", 4, 'Ginger', 'Ginger Tom', 'cat');
insertPets("EBASE_SAMPLES", "pets", 5,
'Tiddles', 'Black and White Cat', 'cat');
insertPets("EBASE_SAMPLES", "pets", 6,
'Chloe', 'Tabby Cat', 'cat');
insertPets("EBASE_SAMPLES", "pets", 7,
'Thumper', 'Black Buck Rabbit', 'rabbit');
insertPets("EBASE_SAMPLES", "pets", 8,
'Nibbles', 'Albino Rat', 'rat');
}
else
{
return false;
}
}
return true;
}
/**
* Create the database table in a specified
database
* @param dbName database name to use
* @param
tableName table to create.
*/
function createTable(dbName,
tableName)
{
var
con, stmt;
try
{
/**create the database table**/
con = system.getDatabaseConnection(dbName);
stmt = con.createStatement();
stmt.executeUpdate("create
table PETS (ID INTEGER NOT NULL, NAME VARCHAR(100) NOT NULL, DESCRIPTION
VARCHAR(255), TAG VARCHAR(20), PRIMARY KEY(ID))");
return true;
}
catch(e)
{
log("Error creating \nTable
Name: " + tableName + "\n" + e);
return false;
}
finally{
// close the connection
if(stmt) stmt.close();
if(con) con.close();
}
}
/**
* Check whether a table exists in a specified
database
* @param dbName database name to use
* @param
tableName table to check whether it exists.
*/
function checkTableExists(dbName,
tableName)
{
var
con, tbls;
try{
/* open a database connection and get the full list of tables at that
connection
* We
can't narrow by schema or table name because different databases implement
* schemas differently
and handle case differently */
con = system.getDatabaseConnection(dbName);
var dbmd
= con.getMetaData();
tbls = dbmd.getTables(null,
null, null, null);
// loop through the returned tables, if any of them match the given
name, return true
while(tbls.next()){
if(tableName.toUpperCase()
== tbls.getString(3).toUpperCase())
return true;
}
// if no match is found, return false
return false;
}
catch(e){
log("Table exists check failed \nTable
Name: " + tableName + "\n" + e);
return true;
}
finally{
// close the connection
if(tbls) tbls.close();
if(con) con.close();
}
}
function insertPets(dbName,
tableName, id, name, description, tag)
{
var
con, stmt;
try
{
/**create the database table**/
con = system.getDatabaseConnection(dbName);
stmt = con.prepareStatement("insert into pets (id, name,
description, tag) values (?, ?, ?, ?)");
stmt.setInt(1, id);
stmt.setString(2, name);
stmt.setString(3,
description);
stmt.setString(4, tag);
stmt.executeUpdate();
}
catch(e)
{
log("Error creating \nTable
Name: " + tableName + "\n" + e);
return false;
}
finally{
// close the connection
if(stmt) stmt.close();
if(con) con.close();
}
}
Name |
Field Type |
id |
Integer |
name |
Character |
description |
Character |
tag |
Character |
Click the OK button.
Click the OK button on the New table dialog. This will create the table and columns fields.
Parameter Name |
Description |
tag |
Optional parameter: used to filter the records by type of pet e.g “dog”, if absent, all records are returned. |
limit |
Optional parameter: used to limit the number of records returned, if absent, no limit is set. |
Enter the following script text into the getPets script:
importPackage(com.ebasetech.xi.api);
importPackage(com.ebasetech.xi.services);
try
{
//validate and create the pets database table
calling the shared function
if(!createTables("EBASE_SAMPLES", "pets"))
throw
"Error creating database table 'pet'";
var
tag = form.rest.getRequestParameter("tag");
var
limit = form.rest.getRequestParameter("limit");
//search pets
searchPets(tag, limit);
//convert the pets table to JSON
var
responseBody = tables.pets.toJSON();
//set the response body
form.rest.setResponseBody(responseBody);
}
catch(e)
{
form.rest.setResponseBody("Error finding retrieving pets: " + e);
form.rest.setResponseStatus(500);
}
/**
* Runs a query to return all the pets from the
pets database table.
* @param tag
optional parameter to filter the type of pet from the database e.g dog
* @param limit optional
parameter to limit the number of records returned in the results.
*/
function searchPets(tag, limit)
{
var index = 0;
var stmt = "select id, name,
description, tag from pets";
if(tag)
{
stmt = stmt
+ " where tag = '" + tag + "'";
}
services.database.executeSelectStatement("EBASE_SAMPLES", stmt,
function (columnData)
{
if(limit &&
limit <= index)
return false;
tables.pets.insertRow();
tables.pets.id.value
= columnData.ID;
tables.pets.name.value
= columnData.NAME;
tables.pets.description.value
= columnData.DESCRIPTION;
tables.pets.tag.value
= columnData.TAG;
index++;
});
}
At this point the endpoint should look like this:
The HTTP Request Preview should contain the following text:
GET http://localhost:3050/ebasetest/api/petstore/getPets
Click the Close button to close the Response Dialog.
The HTTP Request Preview should now contain the following text:
GET
http://localhost:3050/ebasetest/api/petstore/getPets?tag=dog
Click the Close button to close the Response Dialog.
The HTTP Request Preview should now contain the following text:
GET
http://localhost:3050/ebasetest/api/petstore/getPets?tag=dog&limit=2
Click the Close button to close the Response Dialog.
Click the Close button to close the Test Dialog.
In this tutorial, we will create an endpoint to add a new pet to our online pet store application. The endpoint accepts a HTTP POST call and a request body containing a JSON object. To add information into the database we need to implement HTTP Basic authentication.
Create a shared script to handle the authentication for the RESTful service so that it can be reused with other endpoints and create an endpoint to add a pet to the pet store.
importPackage(com.ebasetech.xi.api);
importPackage(com.ebasetech.xi.services);
function validateUser(username, password)
{
log("validating username: " + username);
if(username == "demouser"
&& password == "demopwd")
return true;
else
return
false;
}
Enter the following script text into the addPet script:
importPackage(com.ebasetech.xi.api);
importPackage(com.ebasetech.xi.services);
try
{
//validate and create the pets database table
calling the shared function
if(!createTables("EBASE_SAMPLES", "pets"))
throw
"Error creating database table 'pet'";
//do some authentication
var
cred = form.rest.readBasicAuthenticationCredentials();
var
authenticated = false;
if(cred)
{
//authenticate user
if(validateUser(cred.getUsername(), cred.getPassword()))
{
var requestBody
= form.rest.getRequestBody();
if(requestBody)
{
log("Incoming
Request: " + requestBody);
//A new pet consists of a name, description
and a tag for filtering the type of pet.
//convert the json
to an object
var
pet = JSON.parse(requestBody);
if(!pet.name)
{
//no request
body, send back back request
form.rest.setResponseStatus(400);
form.rest.setResponseBody("No pet name specified.");
}
else
{
//insert
pet
var id = addPet(pet.name, pet.description, pet.tag);
//set
back new pet id
var newPet
= {};
newPet.id = id;
form.rest.setResponseBody(JSON.stringify(newPet));
}
}
else
{
//no request body, send back back request
form.rest.setResponseStatus(400);
form.rest.setResponseBody("No pet details found.");
}
}
else
{
//just reject
the user
form.rest.setResponseStatus(403);
}
}
else
{
log("No
credentials");
form.rest.setResponseHeader("WWW-Authenticate", "Basic realm=\"User
Realm\"");
form.rest.setResponseStatus(401);
}
}
catch(e)
{
form.rest.setResponseBody("Error adding pet: " + e);
form.rest.setResponseStatus(500);
}
function addPet(name, description, tag)
{
var id = createId();
var insert = "insert into
pets (id, name, description, tag) values " +
"("
+ id + ", '" + name + "', '" + description + "',
'" + tag + "')";
log(insert);
services.database.executeGenericUpdateStatement("EBASE_SAMPLES", insert);
return id;
}
function createId()
{
var id = 1;
var stmt = "select max(id) as
max_id from pets";
services.database.executeSelectStatement("EBASE_SAMPLES", stmt,
function (columnData)
{
if(columnData.MAX_ID)
{
id = columnData.MAX_ID + 1;
}
});
return id;
}
At this point the endpoint should look like this:
The HTTP Request Preview should contain the following text:
POST
http://localhost:3050/ebasetest/api/petstore/addPet
Content-Type :
application/json
Click the Close
button to close the Response Dialog.
Username: demouser
Password: demopwd
Click the OK button to close the window
{
"name":
"Sadie",
"description":
"Yorkshire terrier",
"tag":
"dog"
}
The HTTP Request Preview should contain the following text:
POST http://localhost:3052/ufs/api/petstore/addPet
Content-Type : application/json
Authorization : Basic ZGVtb3VzZXI6ZGVtb3B3ZA==
{
"name":
"Sadie",
"description":
"Yorkshire terrier",
"tag":
"dog"
}
Click the Close button to close the Response Dialog.
Click the Close button to close the Test Dialog.
Click the Close button to close the Response Dialog.
Username: fred
Password: bloggs
Click the OK
button.
Click the OK button to close the Response Dialog.
Click the Close button to close the Test Dialog.
In this tutorial, we will create an endpoint to delete a pet from our online pet store application. The endpoint accepts a HTTP DELETE call and contains a pet ID as a path parameter on the request URI. Path parameters are configured on the endpoint URI and are identified by enclosing { } brackets. To delete information from the database we need to implement HTTP Basic authentication that we have already created in Part 2.
Enter the following script text into the deletePet script:
importPackage(com.ebasetech.xi.api);
importPackage(com.ebasetech.xi.services);
try
{
//validate and create the pets database table
calling the shared function
if(!createTables("EBASE_SAMPLES", "pets"))
throw
"Error creating database table 'pet'";
//do some authentication
var
cred = form.rest.readBasicAuthenticationCredentials();
var
authenticated = false;
if(cred)
{
//authenticate user
if(validateUser(cred.getUsername(), cred.getPassword()))
{
var id = form.rest.getPathParameter("petId");
if(id)
deletePet(id);
}
else
{
//just reject
the user
form.rest.setResponseStatus(403);
}
}
else
{
log("No
credentials");
form.rest.setResponseHeader("WWW-Authenticate", "Basic realm=\"User
Realm\"");
form.rest.setResponseStatus(401);
}
}
catch(e)
{
form.rest.setResponseBody("Error deleting pet: " + e);
form.rest.setResponseStatus(500);
}
function deletePet(id)
{
var
deletePet = "delete from pets where id= " +
id;
log(deletePet);
services.database.executeGenericUpdateStatement("EBASE_SAMPLES", deletePet);
}
Username: demouser
Password: demopwd
The HTTP Request Preview should contain the following text:
DELETE
http://localhost:3050/ebasetest/api/petstore/deletePet/1
Authorization :
Basic ZGVtb3VzZXI6ZGVtb3B3ZA==
Click the Close button to close the Response Dialog.
Click the Close button to close the Test Dialog.
This now completes the RESTful Web Service tutorials. The completed tutorials can be imported from file Studio/samples/restful_service/restful.zip of the studio installation.