Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

33
Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing

Transcript of Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Page 1: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Java ME Record Management System

Mobile Computing

Page 2: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Mobiles + (Tunnels | Hills) = Lost connection

Page 3: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Only commercial databases for Java ME handsets

No widely available databases for Java ME on CLDC

There are some open source packages if you’re using CDC – see information page

Page 4: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

A RecordStore is NOT a database

A RecordStore is an array of bytes

with MIDP 2.0 a RecordStore can be shared across MIDlet suites

RecordStore names must be unique

Page 5: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Set the MIDlet-Data-Size attribute when using RMS

Any MIDlet suite that uses RMS should specify the minimum number of bytes of data storage it requires, by setting the MIDlet-Data-Size attribute, in both the JAR manifest and the application descriptor.

If the MIDlet-Data-Size attribute is missing, the device assumes the MIDlet suite requires no space for data storage.

If the MIDlet-Data-Size attribute is missing, the device assumes the MIDlet suite requires no space for data storage.

Page 6: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

RecordStore if LILOhttp://w

ww

.geh.org//fm/lw

hprints//m197701610011.jpg

I’m telling you, it’s last in, last

out

No transactions then. Hmm

Page 7: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

If multiple apps share an RMS you need to write the logic for this

RMS operations are thread-safe, but threads must still coordinate the reading and writing of data to the same record store.

This is especially important if your RecordStore is shared in a MIDlet suite.

Page 8: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

RecordStore uses ID not index

1 Tom 6789

2 Jane 3680

3 Henry 1472

1 Tom 6789

2 Jane 3680

3 Henry 1472

4 Mary 8547

1 Tom 6789

2 Jane 3680

3 Henry 1472

4 Mary 8547

1 Tom 6789

2 Jane 3680

3 Henry 3456

4 Mary 8547

5 Sarah 4354

1 2

3 4

Start with three Remove Jane, add Mary

Remove Tom Change data, add row

Page 9: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

recordID = 1 for first record

http://www.geh.org//fm/lwhprints//m197701580006.jpg

Yes, but when it’s gone it’s

gone

Auto-increment,

nice.And it always

starts at 1

Page 10: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

RecordStore Methods• All are static so can be called without instance• Can acquire a list of all record stores with

String[ ] listRecordStores()• Create/open record store with RecordStore openRecordStore(myStore, true) boolean to create or not if doesn’t exist

• Delete via void deleteRecordStore(myStore)

Page 11: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Adding Items

myRecords.addRecord(myBytes, 0, myBytes.length);

byteArray of data to be written to the store

Offset from which to start writing the data

How much of byteArray should be written

Page 12: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Modifying a Record

Same as writing to a record, but must also pass in the recordID as the first parameter

myRecords.addRecord(recordID, myBytes, 0, myBytes.length);

Page 13: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Reading a recordEither:

– A) byte [ ] recordData = myRecords.getRecord(1)

– B) byte[ ] myBuffer = new byte[BIG_ENOUGH];int readRecord = myRecords.getRecord(1, myBuffer, 0);• Instead of creating a new byte array to hold

the result, this version uses one from the application

Page 14: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Meta Information

• long lastModified() timestamp of store

• String getName() of the store

• int getNextRecordID() to be added to the store

• int getRecordSize(int myRecord) for the size of the specified record

• int getSize() of the complete store

Page 15: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Custom Objects

• Problem – how to serialise objects and their attributes?

• Create class and then write variables to bytes and then store this object to the array

• Reverse the process to recreate the object

Page 16: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Custom Object - class

class AuctionItems {

String descriptionAI;

String summaryAI;

String startPriceAI;

long startDateAI;

}

Create class to hold variables for custom object, which can then be passed around as required

Page 17: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Write Custom objectprivate byte[] getBytes() throws IOException{ByteArrayOutputStream baos = new ByteArrayOutputStream();

DataOutputStream dos = new DataOutputStream(baos);

dos.writeUTF(descriptionAI);dos.writeUTF(summaryAI);dos.writeUTF(startPriceAI);dos.writeLong(startDateAI);dos.close();baos.close();return baos.toByteArray();}

* Variables from Form* Could also write out Int, Long, Short, and others

* Variables from Form* Could also write out Int, Long, Short, and others

Page 18: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Read Custom Objectpublic AuctionJ2meItems(byte[] data) throws

RecordStoreNotOpenException, InvalidRecordIDException,

RecordStoreException, IOException {

ByteArrayInputStream bais = new ByteArrayInputStream(data);

DataInputStream dis = new DataInputStream(bais);

this.descriptionAI = dis.readUTF();

this.summaryAI = dis.readUTF();

this.startPriceAI = dis.readUTF();

this.startDateAI = dis.readLong();

}A read from the store is the constructor for object and gets used like this:byte[] inputData = auctionItems.getRecord(item);AuctionItems ai = new AuctionItems(inputData);

‘item’ is an int‘item’ is an int

Page 19: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Could write your own implementation to make RMS work like JDBC

To make working with RMS like using JDBC, and Java objects, need to write structure to handle this

http://developers.sun.com/mobility/midp/articles/databasemapextend/

Page 20: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Use either brute force or enumeration to traverse a RecordStore

Because record IDs are fixed, they are not continuous. A deleted record ID is not filled by an incoming record, so iteration doesn’t work.

RecordStore is NOT a database as shown by this operation

Page 21: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Fetch records one by one in a simple way...

RecordStore rs = ... // an open record store int lastID = rs.getNextRecordID(); int numRecords = rs.getNumRecords(); int count = 0; for( int id = 1; id < lastID && count < numRecords; +

+id ){ try { byte[] data = rs.getRecord( id ); ... // process the data ++count;

} catch( InvalidRecordIDException e ){ // just ignore and move to the next record

} catch( RecordStoreException e ){ // a more general error that should be handled // somehow break;

} } ...

Page 22: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

You can also use RecordEnumeration RecordStore rs = ... // an open record store RecordEnumeration enum = rs.enumerateRecords( null, null, false );

try { while( enum.hasNextElement() ){ int id = enum.nextRecordId(); byte[] data = rs.getRecord( id ); ... // do something here }

} catch( RecordStoreException e ){ // handle the error here

} ...

Page 23: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Sorting Objects

• Use RecordEnumerations to sort through records using compare() – Returns either: EQUIVALENT, FOLLOWS or

PRECEDES

• Can also use enumerateRecords() with its RecordFilter to sift through recordStore

Page 24: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Use RecordComparator to sort records for display

import javax.microedition.rms.*;import java.lang.*;

public class MyComparator implements RecordComparator { public int compare(byte rec1[], byte rec2[]) {

String recstr1 = new String(rec1);String recstr2 = new String(rec2);

int num = recstr1.compareTo(recstr2);if (num != 0) {

return ( num < 0 ? RecordComparator.PRECEDES : RecordComparator.FOLLOWS); }else {

return RecordComparator.EQUIVALENT; }

}}

http://www.microjava.com/articles/techtalk/rms2

Page 25: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Duke’s Auction MIDlet retrieves list of auction items

AuctionMIDlet

Servlet

Database

Send query to db

AuctionItems

ResultSet returned

Vector returned

AuctionJ2meItems

AuctionJ2meItems

Creates vector of these

Serialises to RMS

Page 26: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Call the servlet with byte

hc = (HttpConnection) Connector.open(url); baos = new ByteArrayOutputStream(); dos = new DataOutputStream(baos); dos = hc.openDataOutputStream();

dos.writeByte(OPERATION_LIST_ALL_ITEMS); dos.close();

Use DataInput/ OutputStreams and ByteArrayOutputStream to manage data

Page 27: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

The servlet responds to the callprivate void j2me_selectItem(DataInputStream call, DataOutputStream result,

String quantity) throws IOException, SQLException {

AuctionItems auctionI = new AuctionItems();Vector<AuctionJ2meItems> items = new Vector<AuctionJ2meItems>();items = auctionI.getJ2meAuctionItems("all");

Iterator<AuctionJ2meItems> iter = items.iterator();while (iter.hasNext()) {

AuctionJ2meItems aItem = new AuctionJ2meItems();aItem = (AuctionJ2meItems) iter.next();result.writeUTF("next");result.writeUTF(aItem.descriptionAI);result.writeUTF(aItem.summaryAI);result.writeUTF(aItem.startPriceAI);result.writeLong(aItem.startDateAI);

}return;

}

Use AuctionItems and AuctionJ2meItems

Write stream to MIDlet

Page 28: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

MIDlet captures stream and writes object to RMS

inputStream = hc.openDataInputStream();

int contentLength = (int) hc.getLength();

String k = "";

inputStream.skipBytes(4);

while (inputStream.available() > 0) {

k = inputStream.readUTF();

if (k.equals("next")) {

aItem = new AuctionJ2meItems(inputStream.readUTF(),

inputStream.readUTF(), inputStream.readUTF(),

inputStream.readLong());

ByteArrayOutputStream baos2 = new ByteArrayOutputStream();

DataOutputStream dos2 = new DataOutputStream(baos2);

aItem.serialize(dos2);

byte[] b = baos2.toByteArray();

try {

auctionItemStore.addRecord(b, 0, b.length);

} catch (Exception e) {

// more code left out here

Page 29: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Then we can read the RecordStore into a form with read(1);

private void read(int item) throws RecordStoreNotOpenException,

InvalidRecordIDException, RecordStoreException, IOException {

byte[] inputData = auctionItemStore.getRecord(item);

AuctionJ2meItems ai = new AuctionJ2meItems(inputData);

ai.print();

// set up form …

readForm.append(description);

readForm.append(summary);

readForm.append(startPrice);

readForm.append(startDate);

description.setString(ai.descriptionAI);

summary.setString(ai.summaryAI);

startPrice.setString(ai.startPriceAI);

startDate.setString(String.valueOf(new java.util.Date(ai.startDateAI)));

// add commnds to form …

readForm.setCommandListener(this);

display.setCurrent(readForm);

}

Notice that we convert startDataAI to Date from long

Use AuctionJ2meItem object

Page 30: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Navigate through records with previous and next commands

} else if (c == mPrevCommand) {try {

if (currentId == 1) {Alert alertPrev = new Alert("No previous records");alertPrev.setTimeout(Alert.FOREVER);alertPrev.addCommand(mReadAuctionCommand);alertPrev.setCommandListener(this);display.setCurrent(alertPrev);

} else {currentId--;read(currentId);

} catch (RecordStoreNotOpenException e) {// pl;us other exceptions …

} else if (c == mNextCommand) {try {

currentId++;read(currentId);…

Check for no record, and keep track of recordID

Page 31: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Using AuctionJ2meItem on server and handset causes issues

Closely couples the code between the two

Explore alternatives before coupling code

May be able to use interoperable option

Page 32: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

The more classes in the app the more memory it consumes

Each class in the app will need to be loaded

All classes in MIDP are loaded dynamically at the start during class verification

Keeping classes small, and to a minimum is therefore important in mobile Java

Page 33: Bruce Scharlau, University of Aberdeen, 2010 Java ME Record Management System Mobile Computing.

Bruce Scharlau, University of Aberdeen, 2010

Summary

• RMS is similar to database, with significant differences that you need to accommodate

• Map the bytes to objects for convenience

• Sometimes need to share code across platforms (server and Java ME client) to ease programming