/** Example of implementing REST API handlers.
@note These methods operate on local variables instead
of database tables. In an actual app, the methods of Handler classes
should use JDBC to perform SQL operations instead. */
class ExampleRestModel extends RestApiModel {
public ExampleRestModel() {
addHandler("/", new CountHandler());
addHandler("/names", new NamesHandler());
}
/** inner class for implementing API for url "/" (count server) */
class CountHandler extends RestApiHandler {
/** simulated value of count */
/* simulates SQL CREATE TABLE count (val int);
INSERT INTO count VALUES (0); */
int count_val = 0;
/** handles POST requests for url "/"
@param p Results of parsing a POST HTTP request for url "/"
@sc Adds 1 to stored counter
@return HTTP reply for that request, i.e., OK
@note In our REST conventions, we should implement thie "Update"
operation as a PATCH HTTP request. We're including this duplicate
as a POST for consistency with the original server */
public String doPost(HttpParser p) {
return doPatch(p);
}
/** handles PATCH requests for url "/"
@param p Results of parsing a POST HTTP request for url "/"
@sc Adds 1 to stored counter
@return HTTP reply for that request, i.e., OK */
public String doPatch(HttpParser p) {
/* Simulates SQL UPDATE count SET val = val + 1; */
count_val++;
return p.makeReply(200, "OK");
}
/** handles GET requests for url "/"
@param p Results of parsing a GET HTTP request for url "/"
@return HTTP reply for that request,
i.e., JSON for current value of stored counter */
public String doGet(HttpParser p) {
/* Simulates SQL SELECT val FROM count; */
return p.makeJsonReply(200,
"{ \"count\": " + Integer.toString(count_val) +
" }");
}
}
/** inner class for implementing API for url "/names" (name server)
@note WARNING: This simulation using an array
of Strings instead of an database table has a potential race condition!
If this were a multithreaded server, all of the handler methods that
interact with the array names[] or variable ct
need to be synchronized in order to prevent interference
among multiple threads. But, individual SQL commands for a
DBMS such as Postgres are atomic, which means there is no
danger of race conditions with (single) SQL commands actual database
tables. */
class NamesHandler extends RestApiHandler {
/** maximum capacity of array names[]
@note Would not be necessary if we implemented in database */
static final int maxnames = 10000;
/** simulated value of names table */
/* simulates SQL CREATE TABLE names (name text); */
String [] names = new String[maxnames];
/** number of elements in array names[]
@note Would not be necessary if we implemented in database */
int ct = 0;
/** handles PATCH requests for url "/names"
@param p Results of parsing a PATCH HTTP request for url "/names"
@sc Adds value for POST-style parameter name to
the names database table.
@return HTTP reply for that request, i.e., OK
@note WARNING: Potential race condition! See
class description. */
public String doPatch(HttpParser p) {
/* Simulates SQL INSERT INTO names VALUES (&sto:ENTRY;); */
if (ct == maxnames)
return p.makeReply(500, "Simulated table full");
// safe to insert into the simulated table
names[ct++] = p.getParam("name");
return p.makeReply(200, "OK");
}
/** handles POST requests for url "/names"
@param p Results of parsing a POST HTTP request for url "/names"
@sc Adds 1 to stored counter
@return HTTP reply for that request, i.e., OK
@note In our REST conventions, we should implement thie "Update"
operation as a PATCH HTTP request. We're including this duplicate
as a POST for consistency with the original server */
public String doPost(HttpParser p) {
return doPatch(p);
}
/** handles GET requests for url "/names"
@param p Results of parsing a GET HTTP request for url "/names"
@return HTTP reply for that request,
i.e., JSON for current values in names[]
@note WARNING: Potential race condition! See
class description. */
public String doGet(HttpParser p) {
/* Simulates SQL SELECT name FROM names; */
String jsonStr = new String("{ \"names\": [\n");
for (int i = 0; i < ct; i++) {
jsonStr += " ";
if (names[i] == null)
jsonStr += "null,\n";
else
jsonStr += "\"" + names[i] + "\",\n";
}
// remove final comma if present and terminate string
if (ct > 0)
jsonStr = jsonStr.substring(0, jsonStr.length()-2) + "\n";
jsonStr += " ] }";
return p.makeJsonReply(200, jsonStr);
}
}
}