Record Management System: Persistent Memory

Back | Next

The Mobile Information Device Profile provides persistent storage of data through a simple a simple record-oriented database called the Record management system (RMS).

Data is stored over multiple sessions in nonvolatile memory, However in Palm OS devices the data is stored in volatile memory. In case of volatile memory the data will be lost if the battery of the device is removed for a couple of minutes.

J2ME Record Management System (RMS) Architecture

RMS manages persistent data through Record Stores. Each record store has Record Header and a collection of Records. The below figure gives an idea of the architecture of the RMS database.

MIDP Database: Record Management System Architecture

Records in RMS are completely different from the records in the normal database system. Do not compare MIDP RMS with your normal database, RMS has no primary keys, foreign keys, stored procedures etc. Each record consists of a record ID and a single binary data field. All data should be converted to byte array before being added to the record store. Multiple fields are not allowed in a single record.

Compatible algorithm should be written by the programmer like storing multiple fields into a single record. If your record has First Name, Last Name as fields then you can store these fields into a single record by making them coma or pipe separated and then stores them to a Record Store. While retrieving the data the record should be decoded for further use.

Record ID's are unique identifiers that are added along with the inserted data by the RMS system. Record ID is 1 for the first record and gets incremented by one on every addition of a new record. If any record is deleted from the Record Store the Record ID's will not be reset in sequential order. The below figure shows diagrammatically the effect of deletion of record with record ID 3 from the record store.

Remove records from RMS

Record Header contains the data (meta-data) about of the Record Store. The various header information stored in a Record Header is.

Multiple MIDlets using same Record Store

Multiple MIDlets can access the same Record Store if these MIDlets are within the same MIDlet Suite. As we already know MIDlets are packaged as JAR files and each of these JAR file is a MIDlet Suite. MIDlets from one JAR file cannot access the Record Store created by the MIDlet from another JAR File.

Programming with RMS

The javax.microedition.rms is the package that does all the Record Store dirty work for you. This package defines classes and interfaces for Record Store manipulation.

Class Record Store

Class RecordStore is the main class in this package and provides several methods to create, insert, update, and delete Record Stores

Create a Record Store

Class javax.microedition.rms.RecordStore proivides a static method openRecordStore(String recordStoreName, boolean createIfNecessary) which can be used to both create and open a Record Store. Parameter recordStoreName is the name of the record store. If createIfNecessary parameter is true then new Record Store is created if the Record Store with the name recordStoreName does not exist in the device and if it is set as false the record store is not created. If the record store is found in the device createIfNecessary flag is neglected.

RecordStore rs = RecordStore.openRecordStore("MobileSalsaDB",true);

Closing Record Stores

Like in JDBC you will need to do some cleaning up when the Record Store is not in use. It is very important to close an idle Record Store as RMS interactions eat up a lot of device runtime cache. To close a Record Store call closeRecordStore() .

Usage: rs.closeRecordStore();


Deleting a Record Store

A Record store can be deleted by deleteRecordStore() method.

Usage: RecordStore.deleteRecordStore("MobileSalsaDB");

Inserting and Deleting records

What is the use of a database if you can only create and delete one. RecordStore class gives the following methods for Inserting and Deleting records.

public int addRecord(byte[] data, int offset, int numBytes) inserts a record data with offset as its starting index and numBytes as its length.

You have already read in this section that you can only insert byte arrays into a Record Store. Though the above method looks complicated the listing below makes your life simpler.

Listing to Insert a record

String strSalsa = "Jar of Spanish Salsa"; //
String I wish to add to byte bytesSalsa[] = strSalsa.getBytes(); // Convert data to Byte
Array. rs.addRecord(bytesSalsa,0, bytesSalsa.length); // Add Byte Array to Record Store.

Method deleteRecord(int recordId) is invoked to delete a record from the record store. This deleted record and its ID is lost forever. We cannot reuse the deleted record ID.

Usage: rs.deleteRecord(1);

Query and Update records

Class RecordStore supplies the getter and setter methods for reading and manipulation of the existing records in the Record Store. The records can be referenced by the recordId's and can be queried and updated.

Listing to Update a record

String strUpdateSalsa = "Salsa is a dance";
Byte byteUpdateSalsa = strUpdateSalsa.getBytes();
rs.setRecord(1, byteUpdateSalsa, 0, byteUpdateSalsa.length());

J2ME Wireless Toolkit Tip: To clear the values in RMS in WTK emulators select File > Utilities from the main menu and click on the "Clean Database" button.

Advanced RMS

The RMS system also has number other utility classes and interfaces which help us to do advanced tasks like traversing and filtering records.

Traversing the records with RecordEnumeration

RecordEnumeration Interface creates a bidirectional Enumeration object of the Record Store. This Enumeration object is used to read the contents of the Record Store and cannot be modified. Like a view is created from a database an Enumeration object can be created having selected values depending on filters and sorted orders. RecordFilter and RecordComparator are used for this purpose.

RecordStore.enumerateRecords (RecordFilter filter, RecordComparator comparator, boolean keepUpdated) is used to create a RecordEnumeration object. keepUpdated is set to true the Enumeration object is always latest. The Record Store is polled regularly to keep the Enumeration object latest and thus affecting the performance. If keepUpdated is set to false the stale Enumeration object can be updated using RecordEnumeration.rebuild() method.

Record Enumeration object is then used to traverse through the records by using

Listing of RecordEnumeration

private void showEnumRecordsForm() {
	enumList = new List("Enumeration Demo", Choice.IMPLICIT);
	try {
		// Create Enumeration
		RecordEnumeration recEnum = rs.enumerateRecords( null, null, false );
		// Traverse the Enumeration to get get records.
		while( recEnum.hasNextElement() ){
			byte[] data = recEnum.nextRecord();
			enumList.append(new String(data), null);
		}
		// Always destroy Enumeration
		recEnum.destroy();
	} catch (Exception e) {
		e.printStackTrace();
	}

	enumList.addCommand(backCommand);
	enumList.setCommandListener(this);
	display.setCurrent(enumList);
}

RecordComparator and RecordFilter Interfaces

As discussed in earlier RecordFilter is to retrieve records with search criteria. This interface supplies only a single function

Public boolean matches(byte[] candidate);

Listing for Filtering records which start with Letter 'A'

Public class AlphaFilter implements RecordFilter {
Public AlphaFilter() {}
Public boolean matches(byte[] candidate){
     String strCandidate = new String(candidate);
     If (strCandidate.substring(0,1).equals("A"))
          Returns true;
     Else
          Returns false;
}


RecordComparator Interface is used to Compare or sort records in the RecordStore. Like RecordFilter it has only one method.

int compare (byte[] b1, byte[] b2)

Listing to sort records

int compare (byte[] b1, byte[] b2)
{
String str1 = new String(b1);
String str2 = new String(b2);
int num1 = Integer.parseInt(str1);
int num2 = Integer.parseInt(str2);

If (num1>num2)
     Return RecordComparator.FOLLOWS;
Else if (num1=num2)
     Return RecordComparator.EQUIVALENT;
Else
     Return RecordComparator.PRECEDES;
}

Program a database trigger

Listener can be set to the Record Store similar to a trigger in a database to monitor Record Store events. Programmatically these Listeners are similar to AWT/SWING/MIDP ICDUI event handling.

RecordListener Interface should be implemented to monitor Record Store events. Following methods should be implemented for various events.

Before implementing the above methods Record Store has to be set with a Listener using the RecordStore methods.

Implementing RecordStore Listeners

// Implementing RecordListener
void recordAdded(RecordStore recordStore, int recordId)  {
	System.out.println(“RecordStore ” +  recordStore.getName
	+ “ is modified at Record ID “ + recordId);
}

j2meSalsa goodies
Execute RMS Demo online RMS Demo application shows all the essential components of RMS programming. To execute this program select "RMS Demo" application on your left frame.
View Java source code RMSDemo.java: This program demonstrates RMS basics and RMS enumeration
Download this code for deploying directly to WTK Click here to download Zip File Containing WTK compatible file structure.

Back | Next

site comments powered by Disqus

This page is a part of a frames based web site. If you have landed on this page from a search engine click here to view the complete page.