Command Pattern

Command Pattern
lac51
The command pattern is a design pattern in which the 
command
 object encapsulates the information required to perform an action or trigger an event at a later time. It is an an elegant approach for logging requests and initiating desired behavior.
In this article:
 
 
2
 
 
Create the Components used in Command Patterns
The basic approach to creating a command is to create a table for the 
command
 object and implement the desired behavior in a logic event.
Complete the following process to create a command:
Create a Table for the Command Object
Create a table to store request types, for example, 
RequestCommand
. In most cases, you will also define a database-generated key. For convenience, you can use managed data for these tables.
 Creating a table unlocks the software that is already oriented to RESTful database APIs:
  • Simplified API. 
    Command requests pass parameters in JSON request objects, like conventional database-oriented APIs.
  • UI creation.
     For example, to test your command pattern. You can use Data Explorer.
  • Reporting.
     For example, to analyze the received requests, for example, volume, results. The arguments are captured naturally.
  • Problem diagnosis.
     For example, to see the 
    partialResults
    .
In many cases, you will have more than one type of command to build. Consider the single-command-per-table and the multiple-commands-per-table approaches, which you can mix and match. The command table can be child of domain table, which provides you easy access to parent attributes. The multiple-commands-per-table approach can be useful where there is generic logic shared over command types.
Add Columns for Arguments
Add columns for each parameter, for example, 
payload
 and 
amount
.
Add Columns for Administration
An advantage of this approach is that you can add columns to assist in administration. For example, you can aid in problem diagnosis by adding 
datetime
 or record 
partialResults
.
Create a Table Event for Desired Behavior
To effect the desired behavior, create a table event. The 
row
 object provides access to the columns you have added.
For more information about how to create a table event, see Event Rule Types.
Client Invocation: POST to Command Table
Clients invoke the command by POSTing to the 
command
 object (either the table or a custom resource built on it), with a request body consisting of the arguments. This is the same idea as POSTing a new customer, order, etc. In most cases, this will be a custom resource of the command table, to hide administration columns.
Example Command Patterns
The following are typical examples of the command pattern:
POST: http://localhost:8080/rest/default/mycommands/v1/RequestCommand
JSON: {"command":"giveRaise", payload:{"employeeID":1,"percentRaise": 0.10}}
Give Raise Pattern
The reactive logic tutorial illustrates one approach for giving raises (somehow a popular example), using URL arguments. You can also implement give raise with the command pattern. This example provides a useful audit of salary changes.
The 
giveRaise
 event rule in the 
Sample
 API sample is defined for insert on the 
EmpRaise
 table (a child of the 
Employee
 table), such as:
var employee = row.employee;
logicContext.touch(employee);
employee.salary = employee.salary * (1 + percentRaise);
logicContext.update(employee);
For more information about the reactive logic tutorial, see Logic Tutorial.
Alternatively, you can use the multiple-commands-per-table approach, so the code for the 
giveRaise
 event rule is:
if(row.command === 'giveRaise'){
var empID = row.payload.employeeID;
var percentRaise = row.payload.percentRaise;
var employee = logicContext.getBeanByPrimaryKey("employee", empID);
logicContext.touch(employee);
employee.salary = employee.salary * (1 + percentRaise);
logicContext.update(employee);
}
Event Sourcing Pattern
The event sourcing pattern is a straight-forward pattern that preserves transactional information. It inserts into a child table the change to the employee (parent) name by inserting a new row in the 
empChanges
 audit-like table.
 Using the same data model, create a child of Employee called 
EmpChanges
. Build an event handler for inserts into 
EmpChanges
, such as:
var emp = row.Employee; //get Parent Object
logicContext.touch(emp);
if (row.name !== null) emp.name = row.name;
// etc for all attributes,
// or, create a shared lib routine that automates moving same-named attributes
logicContext.update(emp);
For more information about this pattern, see the Event Sourcing documentation and Martin Fowler's website.
Data Sync Request
In the previous examples, the transactions were about data directly managed by 
Layer7 Live API Creator
. This is not always the case. Numerous applications integrate a source and target system. The source system POSTs a command request containing data to be sent to a target system.
The following example from the Business to Business (B2B) sample illustrates the solution. You start by defining locally the 
SyncRequest
 table, matching the columns (and child data, if any) from the source system. Then, you create a commit event rule to move this to the target, using the 
ShipperAPIDef
 resource that defines the mapping and transformation logic. The following code snippet shows the code for this commit event rule:
var transform = logicContext.transformCurrentRow("ShipperAPIDef");
B2B.sendToWebHook(transform, shipper.OrderChangeWebHook);
For more information about the B2B sample, including how you can extend your logic with table events, see B2B API Sample.
Wake-up Request
In some cases, the source system is passive, and does not Post requests to initiate integration. You can create a cron job that posts to the command table, for example, 
PollRequests
 . The 
PollRequest
 action handler queries the source system (perhaps writing results into command table administration columns). This can result in a list of rows. Since these rows do not correspond to tables in your schema, you must write code to move each attribute to a Post Request JSON.
Command Pattern Considerations
The following are considerations for using the command pattern.
Simplify Database Administration
In some applications, you might not have otherwise required a local database, such as with the Data Sync Request command pattern example. Creating a database might appear to be overhead, but you can set up an additional Derby database. You can migrate dev to production using MySQL database export, or, for Derby, copy the Derby folder, or create a export script with tools such as DbVisualizer.
Error Handling
When an error occurs, create a column for the result and format the RESTful response as desired by creating a request event. Use this method to handle errors instead of rolling back the transaction. Rolling back the transaction removes the 
command
 object, and this object can be helpful in diagnosing the failure.
For more information about how to create request events, see Event Handlers.