Page tree
Skip to end of metadata
Go to start of metadata

Creating restful web services is enabled through the creation of the file/table DbDefn module.

The web service routes will automatically be prefixed with /dataapi.


Here is an example of a file/table called "order_line" that is on a mySQL database, and use using all of the built-in rest services.

module.exports = {
  useSQL: true,
  dbObject: "order_line",
  uniqueKey: [
    { field: "order_id", ascending: true },
    { field: "line_id", ascending: true }
  ],

  routes: {
    add: "/orderdetails",
    get: "/orderdetails/:order/:line",
    getList: "/orderdetails/:order",
    update: "/orderdetails/:order/:line",
    delete: "/orderdetails/:order/:line"
  }
}


You do not need to have anything in this module file unless you are using a database other than an IBM i and you will also use the built-in CRUD methods :: get, getList, add, update, and delete

The only thing that was altered was the addition of the "routes" section.

These above routes are all of the standard built-in functions.

  • add uses the PUT method
  • get and getList use the GET method
  • update uses the POST method
  • deleted uses the DELETE method



If the add and update where not included, no web service would exist for them.

Any of these can be overridden by defining the route differently (see below).

 

Here is how a complete example of that same order_line file/table but with the built-in "add" function overridden with a custom find function that can be used as a web service or by any pjs module because the function is exported.

function customAdd(request, response) {
  pjs.defineTable("orderline", { keyed: true, add: true });

  var qty = parseInt(request.body.qty) || 1;

  // Make sure the QTY is >= 1
  request.body.qty = qty < 1 ? 1 : qty;

  var result = orderline.write(null, request.body);
  response.send(result);
}

function findOne(request, response) {
  pjs.defineTable("orderline", { keyed: true, read: true });
  var order = request.order || request.query.order || request.param.order;
  var line = request.line || request.query.line || request.param.line;
  var data = orderline.getRecord(order, line);
  if (response)
    response.send(data);
  else
    return data;
} 
module.exports = {
  useSQL: true,
  dbObject: "order_line",
  uniqueKey: [
    { field: "order_id", ascending: true },
    { field: "line_id", ascending: true }
  ],
 
  findOne: findOne,

  routes: {
    add: { path:"/orderdetails", handler: customAdd },      // notice the handler property is set to this "customAdd" function.
    get: "/orderdetails/:order/:line",
    findOne: { method: "get", path:"/orderdetails/find"},   // notice that handler property is not set, but the name "findOne" is an exported function, so it will auto connect them.
    getList: "/orderdetails/:order",
    update: "/orderdetails/:order/:line",
    delete: "/orderdetails/:order/:line",
  }
}

All functions that use any of the PJS APIs should be declared outside of the of the exports section.

Make sure your function names do not match the existing RLA functions, because the RLA functions will take presidency.

 

You can define the routes in a few different manners.

  • name: "url path"
    • The route method will default to POST (unless it is one of the built-in functions - see above)
    • The name is also the name of the function to be called

    Here is an example of creating your own web services.  The function named is changeQuantity, so the the name of the route should be the same.
function changeQuantity(request, response) {
  var result = null;

  pjs.defineTable("orderline", { keyed: true, read: true, update: true, delete: true });
  var newQty = parseInt(request.body.qty) || 0;

  // If QTY is <= 0 then delete it, else update it
  if (newQty <= 0)
    result = orderline.delete([request.params.order, request.params.line]);
  else {
    var item = orderline.getRecord([request.params.order, request.params.line]);
    item.qty = newQty;
    result = orderline.update(null, item);
  }

  response.send(result);
}
 
module.exports = {
  ...
  changeQuantity: changeQuantity,    // This will allow this function to be available to other modules

  routes: {
    ...
    changeQuantity: "/orderdetails/:order/:line"
  }
}

Routes are unique based on the route method + path.  In the above example this route would resolve to be the same as the built-in update function.  The Profound.js web service registration program will only register the 1st occurrence of this route, any other duplicates will be logged as errors. This uniqueness rule is across the board for all DbDefn module, all of them need to be unique.

There are a few very simple ways to work around this:

    1. Change the path to be more distinct --> changeQuantity: "/orderdetails/:order/:line/updqty"
    2. See next way to define a route which allow you to define the route method

 

 

  • name: {method: "route method", path: "url path" }

function changeQuantity(request, response) {
  var result = null;

  pjs.defineTable("orderline", { keyed: true, read: true, update: true, delete: true });
  var qty = parseInt(request.body.qty) || 0;

  // If QTY is <= 0 then delete it, else update it
  if (qty <= 0)
    result = orderline.delete([request.params.order, request.params.line]);
  else {
    orderline.getRecord([request.params.order, request.params.line]);
    result = orderline.update(null, request.body);
  }

  response.send(result);
}
 
module.exports = {
  ...
  changeQuantity: changeQuantity,    // This will allow this function to be available to other modules

  routes: {
    ...
    changeQuantity: { method: "patch", path: "/orderdetails/:order/:line" },
  }
}

 

  • name: {method: "route method", path: "url path", handler: "the function" }

    • Same as above with the option to override the function to be called

      • The function value should be the actual function object

      • Because this definition has both the function and path, the name is only needed to be unique to pass javascript rules.

function changeQuantity(request, response) {
  var result = null;

  pjs.defineTable("orderline", { keyed: true, read: true, update: true, delete: true });
  var qty = parseInt(request.body.qty) || 0;

  // If QTY is <= 0 then delete it, else update it
  if (qty <= 0)
    result = orderline.delete([request.params.order, request.params.line]);
  else {
    orderline.getRecord([request.params.order, request.params.line]);
    result = orderline.update(null, request.body);
  }

  response.send(result);
}
 
module.exports = {
  ...
  changeQuantity: changeQuantity,    // This is only be needed if you want to expose this function to other modules

  routes: {
    ...
    updQty: {method: "patch", path: "/orderdetails/:order/:line", handler: changeQuantity }
  }
}
  • No labels