Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Restify Commands with the Request Pattern

DZone's Guide to

Restify Commands with the Request Pattern

· Web Dev Zone ·
Free Resource

The new Gartner Critical Capabilities report explains how APIs and microservices enable digital leaders to deliver better B2B, open banking and mobile projects.

REST is all the rage.  It provides a networked approach to exposing data and services, both internally within a company and to partners.  Here, we explore a novel approach to providing a RESTful API to a set of existing commands.

Business Problem: expose Commands via REST

Many organizations have made considerable software available through Unix-like commands.  Imagine an Enterprise, well, the Enterprise, that wishes to provide RESTful APIs to commands like:

  • OrderSickLeave <crew-member>, <duration>
  • IncreaseSpeed <warp-factor>, <emergency-reason>
  • SelfDestruct <authorization-code>
  • … hundreds of them…

Each of these commands is backed by some software, say a Java Class of some sort.

They’d like to publish this functionality, as follows:

  1. Restify – provide a RESTful API for each command.  The REST attributes are the command arguments, above
  2. Validate – before the commands is issued, validate the arguments (does <crew-member> exist, is the <duration> a positive number, etc)
  3. Secure – ensure the commands are available as appropriate

Background: Espresso creates RESTful API for SQL data

Espresso creates RESTful APIs, principally for SQL data.  Some key functionality is described below.

API Creation

You connect Espresso to a database, and it creates a RESTful endpoint for each table, view and Stored Procedure.  The API supports the usual RESTful operations of Get (including filters based on HTTP arguments), and update (Put, Post and Delete).

Validation Rules

You can specify validation rule expressions that are automatically executed on update requests.  For example, you might specify a rule that balance <= creditLimit.

Validation rules are part of the larger notion of business logic, which includes computations (the balance is the sum of the unpaid order amounts).  Computations can chain, and validations work over computed data, so you can solve remarkably complicated problems with a few simple rules.

Extensibility

Espresso creates a server-side JavaScript Domain Object for each table, providing access to attributes (customer.balance), and persistence (customer.save()).

The objects encapsulate their integrity in two ways:

  1. Rule Invocation – update requests trigger the relevant validation / computation rules
  2. Events – you can also associate server-side JavaScript event handlers with a table.  These fire as update requests are processed

The Event handlers can invoke anything in the JVM, such as jar file code you can load into Espresso, other RESTful services, etc.

Background: Command Pattern

Imagine a word processor, providing functionality to make a string of selected text bold, another bit of functionality for italics, and so forth.  Now imagine we wish to provide Undo functionality.  Not possible unless we save the commands.

So, the Command Pattern emerged:

  1. create a class for each Command
  2. creating an instance “does” the command (e.g., make text bold), where the constructor arguments provide the necessary information (text start, length)
  3. maintain an ordered list of commands (object instances)
  4. require the Command Classes to provide an Undo method to reverse the effects of the constructor (e.g., remove the bold)

Database Adaption: insert logic on a Request Table

We can see this same pattern in database applications, where we wish to keep a record of transactions.  For example, instead of just changing a salary (and forgetting who, when, old values etc), we create a SalaryAction(employeeId, raisePercent).  We can think of this as a Request Table.

The logic on the SalaryAction table might give the raise, but also validate (is the percent too big? is the resultant salary out of range?), and record who, when etc.

Restify Commands with Request Tables

So we can combine these notions:

  1. Create a database with table for each Command (OrderSickLeave, IncreaseSpeed, etc), with columns for command arguments.  We can also provide columns for admin data (date executed, etc)
  2. Leverage Espresso to Restify these
  3. Declare Validation Logic
  4. JavaScript table events execute the command

We can now use this approach to Restify our Enterprise commands, as described below.

Command Requests Database

The lower 3 tables are the Request Tables.  They each have Foreign Keys to the Crew table, simply identifying the source of the request (this is optional).

Command Request DB

Load into Espresso

We next connect Espresso, which discovers these tables and creates a Default RESTful API to them.  We can view it in a test tool immediately:

Command Request API

We can also define a Custom API, exposing just the elements we wish:

Command Request Custom API

Validate Command Parameters

The following rules apply to Posts against our Command Request tables.  Here we ensure that the IncreaseSpeed request has

  • a argument (attribute) for warpFactor,
  • that it be between 0 and 10, and
  • that the optional emergencyReason parameter is supplied if the warpFactorexceeds 8
commandRules

Live Browser – view, post data

You can use the API tool, or this automatically constructed app:

Command Request Live Browser

Invoke existing code

Finally, we add server-side JavaScript logic (stubbed here) to execute our command.  This would execute existing code in a loadable jar.

Command Request Call

Conclusion: 4 hour project

This project was completed in about a half a day.

The new Gartner Critical Capabilities for Full Lifecycle API Management report shows how CA Technologies helps digital leaders with their B2B, open banking, and mobile initiatives. Get your copy from CA Technologies.

Topics:
web dev ,rest

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}