Processing in a RESTful World
Learn more about performing RESTful actions to call your API, including the verb-based approval, and action processor approval program.
Join the DZone community and get the full member experience.
Join For FreeAs I noted in my Managing Your API article, RESTful API end-points have experienced a dramatic increase, finding their way into corporate IT circles. One of the biggest debates with RESTful resources centers around performing actions via a RESTful call into your API.
At the heart of this debate is the concept of using verbs in your end-point. See this thread from Stack Overflow regarding the use of verbs in RESTful endpoints. The thought is, by using verb-based end-points, the process becomes more like a Remote Procedure Call (RPC) instead of a RESTful call requesting resources.
Task Example
Consider a very simple case where RESTful API contains tasks that require approval. The following GET-based URI could be used to return a list of tasks:
http://myhost/tasks
Which might return the following information:
[
{
"id" : "101",
"name" : "Test Task #1"
"status" : "Pending Approval"
},
{
"id" : "102",
"name" : "Test Task #2"
"status" : "Approved"
},
{
"id" : "103",
"name" : "Test Task #3"
"status" : "Declined"
}
]
As you might expect, there needs to be a process to approve or decline tasks. In the example above, Test Task #1 (id value = 101) needs to be approved or declined. There needs to be a way for the RESTful API to accommodate this request.
Verb-based Approval Process
Some API developers have opted to include verbs in their RESTful API and might create URIs similar to what is listed below:
http://myhost/tasks/{id}/approve
http://myhost/tasks/{id}/decline
Thus, for the {id} resource, there is an option to approve and decline the task. Simply calling the URI's listed above would fire the code behind the scenes to approve/decline the task. This process works without any issue, except that it is violating the spirit of RESTful API design.
Action Processor Approval Process
Another approach would be to create an action processor. Consider the following simple POJO:
public class Action {
public String type;
public Integer id;
public String action;
public Action() {
}
// Getters and Setters
}
The Action class would be used to contain the type, id, and action to be performed. In the case of the example, the type would be "task" and the action would be either "approve" or "decline." The id would be the unique ID for the task to process.
A POST would be used to call the following URI:
http://myhost/actionProcessor
The following payload would be included with the POST request:
{
"type":"task",
"id":"101",
"action":"approve"
}
The request body data would be passed into the controller, then parsed into an Action object. From there, the ActionProcessor class could be called:
public class ActionProcessor {
public String mainActionProcessor(Action action) {
if (action.getType().equals("task")) {
return processTask(action);
} else {
return "Cannot process action. Type of " + action.getType() + " is unknown.";
}
}
private String processTask(Action action) {
if (action.getAction().equals("approve")) {
return "Approved Task ID #" + action.getId();
} else if (action.getAction().equals("decline")) {
return "Declined Task ID #" + action.getId();
} else {
return "Cannot process Task. Action of " + action.getAction() + " is unknown.";
}
}
}
The mainActionProcessor() method would determine that the action type is a task and subsequently call the processTask() method. In this very simple case, the text would be returned back to the requestor, but in reality, the steps necessary to approve the task would be executed. Once the actual approval code is put into place, calling the tasks/101 URL would result in the following data:
{
"id" : "101",
"name" : "Test Task #1"
"status" : "Approved"
}
Keep in mind, this is a simple example, but using an action processor would provide a manner to submit verb-like actions into your API without violating the spirit of your API. The ActionProcessor class could include subclasses to handle different types of updates to your application while maintaining a single end-point to house these requests.
Conclusion
I am not a diehard advocate of the no-verbs-allowed train of thought. In fact, a recent review of JBoss JBPM 6.x discovered their API uses verb-based URI's. One example is with the /{deploymentId}/workitem/{workItemId}/complete end-point, which is used to complete an assigned work item.
I am a fan of the action processor concept and have employed it on a few recent projects without encountering any issues. I like the idea of centralizing action-based events that are not tied to a standard PUT, POST or PATCH resource call.
My only recommendation would be to determine which approach you prefer, then standardize on that approach within your application. Otherwise, there could be confusion between which actions should use verb-based URIs and which should follow the action processor approach.
Have a really great day!
Published at DZone with permission of John Vester, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments