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 may be
imported from the following export files shipped with the product in folder UfsServer/samples/restful_service/restful.zip