Develop applications to access Simple Data Grids

  1. Develop applications to access Simple Data Grids
  2. API documentation
  3. Develop data grid applications with Java APIs
  4. Develop data grid applications with the REST gateway
  5. Dynamic map configuration options


Develop applications to access Simple Data Grids

Two different options to program for Simple Data Grids...

You must have an existing Simple Data Grid.

The Dynamic Cache and Session Data grids are associated with WebSphere Application Server applications, and can be used without modification.


API documentation

  1. Zip archive of the API documentation.
  2. Online format of the API documentation



Simple data grid application walkthrough

  1. Connect to the catalog service

    The catalog server to specify is displayed on the user interface page for the Simple Data Grid...

      Data Grid | Simple Data Grid | my_simple_data_grid

    To connect to the catalog server...

    The connect method requires only the catalog server endpoint in the format...

      host1:port[,host2:port,...]

    The connect method attempts to connect to each appliance in the list until it makes a successful connection. Automatic failover is provided if one of the other appliances does not respond.

  2. Obtain an ObjectGrid instance.

  3. Set the necessary security credentials.

    Create a client security configuration and a credential generator with a user name and password possessing sufficient authority to access the Simple Data Grid.

  4. Get a Session instance

    You can get a Session from the obtained ObjectGrid instance. A Session instance is required to get the ObjectMap instance, and perform transaction demarcation.

      Session sess = grid.getSession();

  5. Get an ObjectMap instance.

    To use the default map instance, named after the data grid...

      ObjectMap map1 = sess.getMap("my_simple_data_grid");

    To create a new map that uses creation time eviction and pessimistic locking...

      ObjectMap map2 = sess.getMap("my_simple_data_grid.CT.P");

    To create a new map that does not have any eviction or locking settings...

      ObjectMap map3 = sess.getMap("my_new_map.NONE");

  6. Use the ObjectMap methods

    If there is no explicit transaction demarcation in the application, ObjectMap operations run with auto-commit transactions...

      map1.insert(key1, value1);

    The keys used can be of an Java type (java.lang.String, Integer, etc). Values can be any serializable object type.

    To use the ObjectMap API with explicit transaction demarcation...

      sess.begin();
      map1.insert(key1, value1);
      sess.commit();


Example: Simple data grid application

// SimpleGrid.java
// 
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.HashSet;
import java.util.BitSet;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.io.File;
import java.io.PrintWriter;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import com.ibm.websphere.objectgrid.ClientClusterContext;
import com.ibm.websphere.objectgrid.ConnectException;
import com.ibm.websphere.objectgrid.ObjectGrid;
import com.ibm.websphere.objectgrid.ObjectMap;
import com.ibm.websphere.objectgrid.ObjectGridException;
import com.ibm.websphere.objectgrid.ObjectGridManager;
import com.ibm.websphere.objectgrid.ObjectGridManagerFactory;
import com.ibm.websphere.objectgrid.ObjectGridRuntimeException;
import com.ibm.websphere.objectgrid.Session;
import com.ibm.websphere.objectgrid.config.BackingMapConfiguration;
import com.ibm.websphere.objectgrid.config.ObjectGridConfigFactory;
import com.ibm.websphere.objectgrid.config.ObjectGridConfiguration;
import com.ibm.websphere.objectgrid.plugins.TransactionCallbackException;
import com.ibm.websphere.objectgrid.security.config.ClientSecurityConfiguration;
import com.ibm.websphere.objectgrid.security.config.ClientSecurityConfiguration;
import com.ibm.websphere.objectgrid.security.config.ClientSecurityConfigurationFactory;
import com.ibm.websphere.objectgrid.security.plugins.CredentialGenerator;
import com.ibm.websphere.objectgrid.security.plugins.builtins.UserPasswordCredentialGenerator;
import com.ibm.websphere.objectgrid.server.CatalogServerProperties;

public class SimpleGrid 
{
  static String gridName = "test";
  static String mapName = gridName;
  static String username="xcadmin";
  static String password="xcadmin";
  static String hostName="localhost";
  static ObjectGrid clientGrid=null;
  static ConcurrentLinkedQueue<Session> sessions = new ConcurrentLinkedQueue<Session>();

 static synchronized public ObjectGrid getObjectGrid() 
 {
   if (clientGrid == null) 
   {
    ClientClusterContext ccc = null;
    try 
    {
      new java.io.File(System.getProperty("java.io.tmpdir")).mkdirs();
    } catch (Throwable t) 
    {
      t.printStackTrace();
    }
  
    ObjectGridManager ogm = ObjectGridManagerFactory.getObjectGridManager(); 
    ClientSecurityConfiguration clientSC = getAdminClientConfig();
    List<ObjectGridConfiguration> ogConfigs=new ArrayList<ObjectGridConfiguration>();
    ObjectGridConfiguration lclGridConfig = ObjectGridConfigFactory.createObjectGridConfiguration(gridName);
    BackingMapConfiguration bmc = ObjectGridConfigFactory.createBackingMapConfiguration(mapName);
    bmc.setNumberOfBuckets(0);
    lclGridConfig.addBackingMapConfiguration(bmc);
    ogConfigs.add(lclGridConfig);
    try 
    {
      ccc = ogm.connect(hostName+":2809", clientSC, null);
    } catch (Throwable e) 
    {
      e.printStackTrace();
    }
    if (ccc != null) 
    {
       HashMap<String,List<ObjectGridConfiguration>> overrideMap = new HashMap<String,List<ObjectGridConfiguration>>();
       overrideMap.put(ccc.getClusterName(),ogConfigs);
       ogm.setOverrideObjectGridConfigurations(overrideMap);
       try 
       {
         clientGrid = ogm.getObjectGrid(ccc, gridName);
       } catch (ObjectGridRuntimeException ogre) 
       {
         ogre.printStackTrace();
       }
    }
   }
   return clientGrid;
 }


// Get session instance // 
static public Session getSession() throws TransactionCallbackException, ObjectGridException 
{
 Session session = sessions.poll();
 if (session == null && getObjectGrid()!=null) 
 {
  session = getObjectGrid().getSession();
 }
 if (session == null)
  throw new IllegalStateException("unable to initialize connection to objectgrid");
 return session;
}

static public void putSession(Session session) 
{
  if (session.isTransactionActive()) 
  {
    try 
    {
      session.rollback();
    } catch (Exception e) 
    {
    }
  }
  sessions.add(session);
}

public static ClientSecurityConfiguration getAdminClientConfig() 
{
  // Create a ClientSecurityConfiguration object using the specified file  
  ClientSecurityConfiguration clientSC = ClientSecurityConfigurationFactory.getClientSecurityConfiguration();
  clientSC.setSecurityEnabled(true);

  // Create a CredentialGenerator using the passed-in user and password.
  CredentialGenerator credGen = new UserPasswordCredentialGenerator(username,password);
  clientSC.setCredentialGenerator(credGen);
  return clientSC;
}

public static void main(String args[]) throws Exception 
{
 for (int i=0;i<args.length;i++) 
 {
   if(args[i].startsWith("-username:")) 
   {
     username = args[i].substring(args[i].indexOf(":")+1);
   } 
   else if(args[i].startsWith("-password:")) 
   {
     password = args[i].substring(args[i].indexOf(":")+1);
   } 
   else if(args[i].startsWith("-gridname:")) 
   {
     gridName = args[i].substring(args[i].indexOf(":")+1);
   } 
   else if(args[i].startsWith("-mapname:")) 
   {
     mapName = args[i].substring(args[i].indexOf(":")+1);
   } 
     else if(args[i].startsWith("-hostname:")) 
   {
     hostName = args[i].substring(args[i].indexOf(":")+1);
   } 
   else 
   {
     System.out.println("usage: SimpleGrid [optional args]");
     System.out.println("   -username:<username>");
     System.out.println("   -password:<password>");
     System.out.println("   -gridname:<gridname>");
     System.out.println("   -mapname:<mapname>");
     System.out.println("   -hostname:<hostname>");
     System.exit(1); 
   }
 }
 System.out.println("--------------------------------------------------------------");
 System.out.println("Simple Grid Test");
 System.out.println("--------------------------------------------------------------");
 System.out.println("username  : "+username);
 System.out.println("password  : "+password);
 System.out.println("gridname  : "+gridName);
 System.out.println("mapname  : "+mapName);
 System.out.println("hostname  : "+hostName);
 System.out.println("--------------------------------------------------------------");

 if (getObjectGrid() == null) 
 {
  System.out.println("ERROR: unable to connect to objectgrid at "+hostName);
  System.exit(1);
 }
    Session session = getSession();
    ObjectMap map=session.getMap(mapName);
    session.begin();
    Object data = map.get("TestKey");
    if (data!=null)
     map.remove("TestKey");
    map.insert("TestKey","TestValue");
    session.commit();
    putSession(session);
  }
}




Develop data grid applications with the REST gateway

Use the REST gateway to access Simple Data Grid data from non-Java environments such as...

You can also use the REST gateway to access map data from a JVM that cannot host the IBM ORB used by the Java-based ObjectMap API.

Each REST operation to the WebSphere DataPower XC10 appliance begins and ends an independent transaction to the data grid. It is not possible to chain together multiple operations into a single transaction.

When you are using the REST gateway, it is the client responsibility to load balance their requests onto the appliance collective. Use an external load balancer or add additional logic in the HTTP client you are using in the client program.

Communication through the REST gateway always results in a secure configuration, even if you do not have security enabled on the data grid. Configure the user groups to access the data grid to have all access rights to the data grid.

The REST gateway is a separate entity from the WXS REST data service, which implements the Microsoft ADO.NET Data Services interface.


REST gateway: URI format

The REST URI for accessing a simple data grid on the appliance...

For grid MyGrid on appliance myxc10.ibm.com, to access key my.data.item...

In the previous example, the MyGrid default map was used in the MyGrid grid. This default map does not have any TTL eviction. Entries placed in the data grid stay in the data grid until they are explicitly removed.


REST gateway: Data format

The REST gateway uses the Content-Type header in HTTP requests to determine the data format of the data stored into the data grid.

To determine the data format of the data stored in the data grid, the REST gateway uses the Content-type header in HTTP requests. If you insert content of type application/xml, when the application does a GET operation for the same cache key, the response body and Content-type are in the equivalent format type. In this example, the response body would be in application/xml format. You can store data of multiple content types in the same data grid.


REST operations

Use HTTP POST, GET, and DELETE operations to insert or update, get, and remove data from the data grid.

Operation HTTP Method Response Code
Insert or update POST

  • 200 CREATED: The data was successfully inserted or updated into the data grid.
  • 400 BAD REQUEST: The data insert or update operation did not complete successfully.

Get GET

  • 200 OK: The response body and content-type are retrieved from a previous insert or update operation.
  • 404 NOT FOUND: The specified key is not present in the data grid.
  • 400 BAD REQUEST: The appliance was unable to process the request.

Delete DELETE

  • 200 NO CONTENT: The entry was deleted from the data grid.
  • 400 BAD REQUEST: The appliance was unable to process the request.


REST gateway example: Insert and get data grid map entries

Use the POST and GET HTTP methods to insert and get data grid map entries.


Example: Insert operation

To insert a key "bob" into the MyGrid grid and MyGrid map:


Example: Get operation

Retrieve key "bob" inserted in the previous example...

You must run GET operations on an individual key. You cannot retrieve all map entries


Clear entries


Create dynamic maps

When you create a Simple Data Grid, a default map with the same name is created by default. You can use map templates to create additional maps as the application requires.

The first operation to a map that matches the map template, but has not yet been created, results in the creation of a new dynamic map. For example, to create a new dynamic map, using last update time, named MyMap.LUT, use the following URI in a GET, DELETE, or POST operation:


Time to live (TTL) expiration

You can set a TTL value for both last update time (*.LUT) and last access time (*.LAT) maps. The default TTL for both types of maps is one hour.


Example

To set a TTL value for both last update time (*.LUT) and last access time (*.LAT) maps, provide the TTL request parameter with a value in seconds. For example, to set a TTL value of 600 seconds on the a.key key , specify the ttl request parameter when the value is inserted or updated into the data grid using the HTTP POST method:


Security

To access a data grid through the REST gateway, the user must be authenticated to the WebSphere DataPower XC10 appliance, regardless of whether the data grid has security enabled. The application client must always provide a basic authorization header with the authorized user ID and password in the HTTP headers of the HTTP request. To access data grids through the REST gateway, provide the user ID and password in an authorization header.

To access to a data grid map through the REST gateway, the user or user group must be authenticated and authorized to access the specified data grid in the URI. Even if you do not have security configured on the data grid, configure the user group you are using to communicate through the REST gateway to have all access to the data grid. The application client must provide a basic authorization header with the authorized user ID and password in the HTTP headers of the HTTP request.


Secured data grids

Use the REST gateway in a secured data grid configuration. To access the secured data grids, provide the user ID and password in an authorization header. The user must be authenticated and authorized to access the specified data grid in the URI.

Permission Get Post Delete
READ X    
WRITE X    
CREATE X X  
ALL X X X


Transport security

Clients that are using the REST Gateway can use the HTTPS protocol if transport security is required. Using HTTPS instead of HTTP introduces significant additional processing burden on the WebSphere DataPower XC10 appliance to process the request.


REST gateway: HTTP sessions and cookies

Use HTTP sessions and cookies with the REST gateway with Set-Cookie: headers.

The REST gateway code creates an HTTP session when it receives a request from a client that is not currently in session. To prevent unnecessary creation of sessions and to get peak performance, the REST client must remember cookies that are returned from the REST gateway with Set-Cookie: headers and supply those same cookies back to the REST gateway with Cookie: headers on subsequent requests.


Dynamic map configuration options

You can create additional maps in a data grid by having your client application connect to the specially-named map. When this connection occurs, the map is automatically created.


Dynamic map naming

When you create a data grid, a single map is created by default. This map is named the same as the data grid. For example, if you create the myGrid data grid, you automatically get a myGrid map. However, you can also add maps to the data grid. A map is automatically created when the client application connects to a map using the following naming convention:

...where...

Include a template name for the map. If you do not specify a locking option, no locking occurs on the map.


Map templates

Map Template Description
*.NONE Map with no time to live (TTL) expiration.
*.LUT Map in which the entries are expired based on the last update time of the entry. The default TTL is one hour.
*.LAT A map in which the entries are expired based on the last access time of the entry. The default TTL is one hour.
*.CT A map in which the entries are expired based on the of the creation time of the entry plus the TTL value. The default TTL is one hour.


Locking options

Locking Option Description
(blank) No locking mechanism is used.
-P The map has pessimistic locking
-O The map has optimistic locking