Extending the RestLet application with support for POST/PUT to create and update Resources

In a previous post – First Steps with RestLet 1.1RC2 in JDeveloper 11g – restful services 101 – I introduced RestLet and how to use it for creating very simple RestFul services in JDeveloper 11g. This contribution takes things a little further: the things and thing service discussed in the prior article only support read only operations: GET requests. In this article, we will add the ability to create and update things.

Since creation is done based on simple HTTP request of type POST, all we need for a Thing Create Client is a static HTML page with form that posts to the /things url of our RestFul service. The post request should contain the properties of the new thing we want to have created. It is up to the RestFul service to handle the post request. More specifically: the ThingsResource class will take on the Post request sent to the /things service and try to create a new thing based on it.....

We will create the static HTML page -the Thing Creator Client – and add Post Request Handling capabilities to the ThingsResource. Note that the exact meaning of POST vs. PUT in REST is sometimes subject for debate. I have followed the guidance from Leonard Richardson and Sam Ruby in their excellent book "RESTful WebServices" (O’Reilly, 2007): POST is used when creating a resource by sending an HTTP request to an existing URI (in this case /things) in order to create a new, subordinate resource; in contracts PUT is used to create a resource by sending a request to a new URI (the URI where the new resource will be available). The former is used when the server (service) has control over the URI where the new resource will be exposed while the latter is used when the client is in charge of determining the URI for the new resource. Note that PUT is also used to modify an existing resource at an existing URI.

Create the Client for Creating Things

In your favorite file editor or in JDeveloper 11g, whichever you prefer, create a new HTML file. You can make it as interesting as you like, but the basic ingredients are:

    <form name="ThingCreator"
action="http://127.0.0.1:7101/RestLetIntroduction-MyFirstRestFulService-context-root/things"
method="post">
<table cellspacing="2" cellpadding="3" border="1" width="100%">
<tr>
<td width="50%">Name</td>
<td width="50%">
<input type="text" name="name"/>
</td>
</tr>
<tr>
<td width="50%">Description</td>
<td width="50%">
<input type="text" name="description"/>
</td>
</tr>
</table>
<input type="submit" value="Create"/>
</form>
 

See the Form that performs a POST and sends it (action) to the things service. Replace the host, port and webapplication in this url with your own. Here we are lucky that we can use POST for creating the new (subordinate to Things) Thing resource as that is what a simple HTML form can do easily. PUT and DELETE are a different matter and require the use of more complex clients.

Add POST handling capabilities to the ThingsResource

Inside the ThingsResource class we first need to specify that this Resource handles POST reqeusts. You do this by adding the line

        // Allow modifications of this resource via POST requests.
setModifiable(true);

With the Resource set to modifiable, this class takes on the responsibility to handle a POST request. It implements that responsibility by overriding method acceptRepresentation. This method inspects the request contents, retrieves the values it needs for constructing a new resource, creates the resource and adds it to the collection. In this case we keep it simple:

    /**
* Handle POST requests: create a new thing.
*/
@Override
public void acceptRepresentation(Representation entity) throws ResourceException {
// Parse the given representation and retrieve pairs of
// "name=value" tokens.
Form form = new Form(entity);
String name = form.getFirstValue("name");
String description = form.getFirstValue("description");

// Register the new item
getThings().add(new Thing(name, description, "", 0, 0));

// Set the response's status and entity
getResponse().setStatus(Status.SUCCESS_CREATED);
Representation rep =
new StringRepresentation("Thing created", MediaType.TEXT_PLAIN);
// Indicates where is located the new resource.
rep.setIdentifier(getRequest().getResourceRef().getIdentifier() + "/" +
name);
getResponse().setEntity(rep);
}
 

The method acceptRepresentation inspects the request – retrieves the form, gets properties from the form and uses the values to create a new Thing Resource. The second half of the method is dedicated to providing the client with a proper response that for example informs her of the succesful creation and the location (url) of the new resource. Note that the method does not cater for creation failure at this point.

Live creation of Thing Resources

We can see the Thing creation in action now. Run the untitled1.jsp – to deploy the RestFul application. Open the static HTML document in a browser. Enter details for a new Thing.

Extending the RestLet application with support for POST/PUT to create and update Resources rest thingcreator 

Press the Create button. The following page appears – the interpretation by the browser of the response sent from the ThingsResource class

Extending the RestLet application with support for POST/PUT to create and update Resources rest createresponse 

We can inspect whether the creation of the Thing was indeed successful by going to the url shown in the address bar:

Extending the RestLet application with support for POST/PUT to create and update Resources rest thingswithnew

The last thing in the document is our ‘A New Thing’  – so apparently we succeeded!

Updating existing resources

Ideally we would like to use PUT to modify existing Thing resources. Since that would put a lot of focus on the client, which it really does not deserve, I will cheat just a little and have a POST to an existing resource interpret as an update to that resource. In a better world I probably should have leveraged the XmlHttpRequest object – the thing driving Ajax – and use it to perform a PUT request.

Supporting a POST to a Thing resource requires simple changes in the ThingResource Class:

in the constructor, add the top two lines (that should look familiar from the previous section) – the other lines are already there and take care of retrieving the Thing under scrutiny from the things collection:

  // Allow modifications of this resource via POST requests.
setModifiable(true);
// already in the ThingResource class
String thingName = (String)getRequest().getAttributes().get("thingName");
// Get the thing directly from the "persistence la yer".
thing = getTheThing (thingName);

Post requests are handled by the acceptRepresentation() method. We now need to implement this method for the ThingResource class, having it inspect the request and using its contents to update the Thing that needs updating.

    /**
* Handle POST requests: update an existing thing resource.
*/
@Override
public void acceptRepresentation(Representation entity) throws ResourceException {
// Parse the given representation and retrieve pairs of
// "name=value" tokens.
Form form = new Form(entity);
Representation rep = null;
if (thing!=null) { // it exists!
String description = form.getFirstValue("description");
thing.setSomeOtherProperty(description);
getResponse().setStatus(Status.SUCCESS_CREATED);
rep=
new StringRepresentation("Thing updated", MediaType.TEXT_PLAIN);
// Indicates where is located the new resource.
rep.setIdentifier(getRequest().getResourceRef().getIdentifier() + "/" +
thing.getName());
}
else {
getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
rep=
new StringRepresentation("Thing could not be found", MediaType.TEXT_PLAIN);
}
// Set the response's status and entity
getResponse().setEntity(rep);
}
 

Here we see a simplified implementation. It will only update the someOtherProperty property on the Thing. However, that should suffice to demonstrate the point. If no thing is found – the thing name used in the URI /things/{thingName} does not actually refer to an existing thing – it will return a message and error code to indicate that fact. Otherwise it will return a more positive message.

Now that our service is capable of handling a POST to an existing Thing resource, we need a client that can make use of that capability. We make some minimal changes to the ManipulateThings.html document we created earlier on: next to the Create button, we add another button to Update a Thing:

      <input type="button" value="Update" 
onclick="forms.ThingCreator.action='http://127.0.0.1:7101/RestLetIntroduction-MyFirstRestFulService-context-root/things/'+forms.ThingCreator.name.value;
forms.ThingCreator.submit();"/>

This button is not of type submit. Instead, it is a normal button with an onclick method. When the button gets clicked, the action of the form (the URI where the form is posted to) is dynamically set. Since a Thing Resource is found at URI host:port/webapp/things/{thingName} and the update to an existing resource is performed through a POST to the URI of the resource, we need to set the form’s action to a URI that ends with the name of the Thing to update. That name is found in the name field in the ThingCreator form. This value is appended to form the required URI. Then the form is submitted.

See the Update in Action

Like before, we run the untitled1.jsp. Not for the sake of the JSP but for convenient deployment of the RESTful services in the web application. Next we open the changed ManipulateThings.html in a browser. We enter the name of an existing resource – here FirstThing. Then we enter the (new) value of the description. Finally we press the Update button.

Extending the RestLet application with support for POST/PUT to create and update Resources updateresourcehtml 

This triggers the POST request to the ThingResource that updates the resource.

Extending the RestLet application with support for POST/PUT to create and update Resources updateresponse 

By loading the host:port/webapp/things URI in the browser we can see that the change has been processed.

Extending the RestLet application with support for POST/PUT to create and update Resources thingsafterupdate

Resources

Download the JDeveloper 11g Application described in this article RestLetIntroductionCreateUpdateThings.zip .