Chapter 12. The REST API

12.1. The REST Interface

Red Hat JBoss Data Grid provides a REST interface, allowing for loose coupling between the client and server. Its primary benefit is interoperability with existing HTTP clients, along with providing a connection for php clients. In addition, the need for specific versions of client libraries and bindings is eliminated.

The REST API introduces an overhead, and requires a REST client or custom code to understand and create REST calls. It is recommended to use the Hot Rod client where performance is a concern.

To interact with Red Hat JBoss Data Grid’s REST API only a HTTP client library is required. For Java, this may be the Apache HTTP Commons Client, or the java.net API.

Important

The following examples assume that REST security is disabled on the REST connector. To disable REST security remove the authentication and encryption elements from the connector.

12.2. Ruby Client Code

The following code is an example of interacting with Red Hat JBoss Data Grid REST API using ruby. The provided code does not require any special libraries and standard net/HTTP libraries are sufficient.

Using the REST API with Ruby

require 'net/http'

http = Net::HTTP.new('localhost', 8080)

#An example of how to create a new entry

http.post('/rest/MyData/MyKey', 'DATA_HERE', {"Content-Type" => "text/plain"})

#An example of using a GET operation to retrieve the key

puts http.get('/rest/MyData/MyKey').body

#An Example of using a PUT operation to overwrite the key

http.put('/rest/MyData/MyKey', 'MORE DATA', {"Content-Type" => "text/plain"})

#An example of Removing the remote copy of the key

http.delete('/rest/MyData/MyKey')

#An example of creating binary data

http.put('/rest/MyImages/Image.png', File.read('/Users/michaelneale/logo.png'), {"Content-Type" => "image/png"})

12.3. Using JSON with Ruby Example

Prerequisites

To use JavaScript Object Notation (JSON) with ruby to interact with Red Hat JBoss Data Grid’s REST Interface, install the JSON Ruby library (see your platform’s package manager or the Ruby documentation) and declare the requirement using the following code:

require 'json'

Using JSON with Ruby

The following code is an example of how to use JavaScript Object Notation (JSON) in conjunction with Ruby to send specific data, in this case the name and age of an individual, using the PUT function.

data = {:name => "michael", :age => 42 }
http.put('/rest/Users/data/0', data.to_json, {"Content-Type" => "application/json"})

12.4. Python Client Code

The following code is an example of interacting with the Red Hat JBoss Data Grid REST API using Python. The provided code requires only the standard HTTP library.

Using the REST API with Python

import httplib

#How to insert data

conn = httplib.HTTPConnection("localhost:8080")
data = "SOME DATA HERE \!" #could be string, or a file...
conn.request("POST", "/rest/default/0", data, {"Content-Type": "text/plain"})
response = conn.getresponse()
print response.status

#How to retrieve data

import httplib
conn = httplib.HTTPConnection("localhost:8080")
conn.request("GET", "/rest/default/0")
response = conn.getresponse()
print response.status
print response.read()

12.5. Java Client Code

The following code is an example of interacting with Red Hat JBoss Data Grid REST API using Java.

Defining Imports

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;

Adding a String Value to a Cache

// Using the imports in the previous example
public class RestExample {

   /**
    * Method that puts a String value in cache.
    * @param urlServerAddress
    * @param value
    * @throws IOException
    */

   public void putMethod(String urlServerAddress, String value) throws IOException {
      System.out.println("----------------------------------------");
      System.out.println("Executing PUT");
      System.out.println("----------------------------------------");
      URL address = new URL(urlServerAddress);
      System.out.println("executing request " + urlServerAddress);
      HttpURLConnection connection = (HttpURLConnection) address.openConnection();
      System.out.println("Executing put method of value: " + value);
      connection.setRequestMethod("PUT");
      connection.setRequestProperty("Content-Type", "text/plain");
      connection.setDoOutput(true);

      OutputStreamWriter outputStreamWriter = new OutputStreamWriter(connection.getOutputStream());
      outputStreamWriter.write(value);

      connection.connect();
      outputStreamWriter.flush();

      System.out.println("----------------------------------------");
      System.out.println(connection.getResponseCode() + " " + connection.getResponseMessage());
      System.out.println("----------------------------------------");

      connection.disconnect();
   }

The following code is an example of a method used that reads a value specified in a URL using Java to interact with the Red Hat JBoss Data Grid REST Interface.

Get a String Value from a Cache

    // Continuation of RestExample defined in previous example
		/**
    * Method that gets an value by a key in url as param value.
    * @param urlServerAddress
    * @return String value
    * @throws IOException
    */
   public String getMethod(String urlServerAddress) throws IOException {
      String line = new String();
      StringBuilder stringBuilder = new StringBuilder();

      System.out.println("----------------------------------------");
      System.out.println("Executing GET");
      System.out.println("----------------------------------------");

      URL address = new URL(urlServerAddress);
      System.out.println("executing request " + urlServerAddress);

      HttpURLConnection connection = (HttpURLConnection) address.openConnection();
      connection.setRequestMethod("GET");
      connection.setRequestProperty("Content-Type", "text/plain");
      connection.setDoOutput(true);

      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

      connection.connect();

      while ((line = bufferedReader.readLine()) != null) {
         stringBuilder.append(line + '\n');
      }

      System.out.println("Executing get method of value: " + stringBuilder.toString());

      System.out.println("----------------------------------------");
      System.out.println(connection.getResponseCode() + " " + connection.getResponseMessage());
      System.out.println("----------------------------------------");

      connection.disconnect();

      return stringBuilder.toString();
   }

Using a Java Main Method

    // Continuation of RestExample defined in previous example
		/**
    * Main method example.
    * @param args
    * @throws IOException
    */
    public static void main(String[] args) throws IOException {
        //Note that the cache name is "cacheX"
        RestExample restExample = new RestExample();
        restExample.putMethod("http://localhost:8080/rest/cacheX/1", "Infinispan REST Test");
        restExample.getMethod("http://localhost:8080/rest/cacheX/1");
    }
}

12.6. Using the REST Interface

12.6.1. Using the REST Interface

The REST Interface can be used in Red Hat JBoss Data Grid’s Remote Client-Server mode to perform the following operations:

  • Adding data
  • Retrieving data
  • Removing data

12.6.2. Adding Data Using REST

12.6.2.1. Adding Data Using REST

In Red Hat JBoss Data Grid’s REST Interface, use the following methods to add data to the cache:

  • HTTP PUT method
  • HTTP POST method

When the PUT and POST methods are used, the body of the request contains this data, which includes any information added by the user.

Both the PUT and POST methods require a Content-Type header.

12.6.2.2. About PUT /{cacheName}/{cacheKey}

A PUT request from the provided URL form places the payload, from the request body in the targeted cache using the provided key. The targeted cache must exist on the server for this task to successfully complete.

As an example, in the following URL, the value hr is the cache name and payRoll%2F3 is the key. The value %2F indicates that a / was used in the key.

http://someserver/rest/hr/payRoll%2F3

Any existing data is replaced and Time-To-Live and Last-Modified values are updated, if an update is required.

Note

A cache key that contains the value %2F to represent a / in the key (as in the provided example) can be successfully run if the server is started using the following argument:

-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true

12.6.2.3. About POST /{cacheName}/{cacheKey}

The POST method from the provided URL form places the payload (from the request body) in the targeted cache using the provided key. However, in a POST method, if a value in a cache/key exists, a HTTP CONFLICT status is returned and the content is not updated.

12.6.3. Retrieving Data Using REST

12.6.3.1. Retrieving Data Using REST

In Red Hat JBoss Data Grid’s REST Interface, use the following methods to retrieve data from the cache:

  • HTTP GET method.
  • HTTP HEAD method.

12.6.3.2. About GET /{cacheName}/{cacheKey}

The GET method returns the data located in the supplied cacheName, matched to the relevant key, as the body of the response. The Content-Type header provides the type of the data. A browser can directly access the cache.

A unique entity tag (ETag) is returned for each entry along with a Last-Modified header which indicates the state of the data at the requested URL. ETags allow browsers (and other clients) to ask for data only in the case where it has changed (to save on bandwidth). ETag is a part of the HTTP standard and is supported by Red Hat JBoss Data Grid.

The type of content stored is the type returned. As an example, if a String was stored, a String is returned. An object which was stored in a serialized form must be manually deserialized.

12.6.3.3. About HEAD /{cacheName}/{cacheKey}

The HEAD method operates in a manner similar to the GET method, however returns no content (header fields are returned).

12.6.4. Removing Data Using REST

12.6.4.1. Removing Data Using REST

To remove data from Red Hat JBoss Data Grid using the REST interface, use the HTTP DELETE method to retrieve data from the cache. The DELETE method can:

  • Remove a cache entry/value. (DELETE /{cacheName}/{cacheKey})
  • Remove all entries from a cache. (DELETE /{cacheName})

12.6.4.2. About DELETE /{cacheName}/{cacheKey}

Used in this context (DELETE /{cacheName}/{cacheKey}), the DELETE method removes the key/value from the cache for the provided key.

12.6.4.3. About DELETE /{cacheName}

In this context (DELETE /{cacheName}), the DELETE method removes all entries in the named cache. After a successful DELETE operation, the HTTP status code 200 is returned.

12.6.4.4. Background Delete Operations

Set the value of the performAsync header to true to ensure an immediate return while the removal operation continues in the background.

12.6.5. REST Interface Operation Headers

The following table displays headers that are included in the Red Hat JBoss Data Grid REST Interface:

Table 12.1. Header Types

HeadersMandatory/OptionalValuesDefault ValueDetails

Content-Type

Mandatory

-

-

If the Content-Type is set to application/x-java-serialized-object , it is stored as a Java object.

performAsync

Optional

True/False

-

If set to true, an immediate return occurs, followed by a replication of data to the cluster on its own. This feature is useful when dealing with bulk data inserts and large clusters.

timeToLiveSeconds

Optional

Numeric (positive and negative numbers)

-1 (This value prevents expiration as a direct result of timeToLiveSeconds. Expiration values set elsewhere override this default value.)

Reflects the number of seconds before the entry in question is automatically deleted. Setting a negative value for timeToLiveSeconds provides the same result as the default value.

maxIdleTimeSeconds

Optional

Numeric (positive and negative numbers)

-1 (This value prevents expiration as a direct result of maxIdleTimeSeconds. Expiration values set elsewhere override this default value.)

Contains the number of seconds after the last usage when the entry will be automatically deleted. Passing a negative value provides the same result as the default value.

The following combinations can be set for the timeToLiveSeconds and maxIdleTimeSeconds headers:

  • If both the timeToLiveSeconds and maxIdleTimeSeconds headers are assigned the value 0, the cache uses the default timeToLiveSeconds and maxIdleTimeSeconds values configured either using ` XML` or programatically.
  • If only the maxIdleTimeSeconds header value is set to 0, the timeToLiveSeconds value should be passed as the parameter (or the default -1, if the parameter is not present). Additionally, the maxIdleTimeSeconds parameter value defaults to the values configured either using ` XML` or programatically.
  • If only the timeToLiveSeconds header value is set to 0, expiration occurs immediately and the maxIdleTimeSeconds value is set to the value passed as a parameter (or the default -1 if no parameter was supplied).

ETag Based Headers

ETags (Entity Tags) are returned for each REST Interface entry, along with a Last-Modified header that indicates the state of the data at the supplied URL. ETags are used in HTTP operations to request data exclusively in cases where the data has changed to save bandwidth. The following headers support ETags (Entity Tags) based optimistic locking:

Table 12.2. Entity Tag Related Headers

HeaderAlgorithmExampleDetails

If-Match

If-Match = "If-Match" ":" ( "*" | 1#entity-tag )

-

Used in conjunction with a list of associated entity tags to verify that a specified entity (that was previously obtained from a resource) remains current.

If-None-Match

 

-

Used in conjunction with a list of associated entity tags to verify that none of the specified entities (that was previously obtained from a resource) are current. This feature facilitates efficient updates of cached information when required and with minimal transaction overhead.

If-Modified-Since

If-Modified-Since = "If-Modified-Since" ":" HTTP-date

If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT

Compares the requested variant’s last modification time and date with a supplied time and date value. If the requested variant has not been modified since the specified time and date, a 304 (not modified) response is returned without a message-body instead of an entity.

If-Unmodified-Since

If-Unmodified-Since = "If-Unmodified-Since" ":" HTTP-date

If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT

Compares the requested variant’s last modification time and date with a supplied time and date value. If the requested resources has not been modified since the supplied date and time, the specified operation is performed. If the requested resource has been modified since the supplied date and time, the operation is not performed and a 412 (Precondition Failed) response is returned.