1 / 33

Java ME Record Management System

Java ME Record Management System. Mobile Computing. Mobiles + (Tunnels | Hills) = Lost connection. 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.

primo
Télécharger la présentation

Java ME Record Management System

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. Mobiles + (Tunnels | Hills) = Lost connection Bruce Scharlau, University of Aberdeen, 2010

  3. 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 Bruce Scharlau, University of Aberdeen, 2010

  4. 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 Bruce Scharlau, University of Aberdeen, 2010

  5. 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. Bruce Scharlau, University of Aberdeen, 2010

  6. RecordStore if LILO I’m telling you, it’s last in, last out http://www.geh.org//fm/lwhprints//m197701610011.jpg No transactions then. Hmm Bruce Scharlau, University of Aberdeen, 2010

  7. 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. Bruce Scharlau, University of Aberdeen, 2010

  8. RecordStore uses ID not index 1 Start with three Remove Jane, add Mary 2 3 Remove Tom Change data, add row 4 Bruce Scharlau, University of Aberdeen, 2010

  9. recordID = 1 for first record Auto-increment, nice. And it always starts at 1 Yes, but when it’s gone it’s gone Bruce Scharlau, University of Aberdeen, 2010 http://www.geh.org//fm/lwhprints//m197701580006.jpg

  10. 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) Bruce Scharlau, University of Aberdeen, 2010

  11. Adding Items Offset from which to start writing the data myRecords.addRecord(myBytes, 0, myBytes.length); • byteArray of data to be written to the store How much of byteArray should be written Bruce Scharlau, University of Aberdeen, 2010

  12. 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); Bruce Scharlau, University of Aberdeen, 2010

  13. Reading a record Either: • 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 Bruce Scharlau, University of Aberdeen, 2010

  14. 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 Bruce Scharlau, University of Aberdeen, 2010

  15. 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 Bruce Scharlau, University of Aberdeen, 2010

  16. Custom Object - class classAuctionItems{ StringdescriptionAI; StringsummaryAI; StringstartPriceAI; longstartDateAI; } Create class to hold variables for custom object, which can then be passed around as required Bruce Scharlau, University of Aberdeen, 2010

  17. Write Custom object privatebyte[]getBytes()throwsIOException{ ByteArrayOutputStreambaos=newByteArrayOutputStream(); DataOutputStreamdos=newDataOutputStream(baos); dos.writeUTF(descriptionAI); dos.writeUTF(summaryAI); dos.writeUTF(startPriceAI); dos.writeLong(startDateAI); dos.close(); baos.close(); returnbaos.toByteArray(); } * Variables from Form * Could also write out Int, Long, Short, and others Bruce Scharlau, University of Aberdeen, 2010

  18. Read Custom Object public 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(); } ‘item’ is an int A read from the store is the constructor for object and gets used like this: byte[]inputData=auctionItems.getRecord(item); AuctionItemsai=newAuctionItems(inputData); Bruce Scharlau, University of Aberdeen, 2010

  19. 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/ Bruce Scharlau, University of Aberdeen, 2010

  20. 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 Bruce Scharlau, University of Aberdeen, 2010

  21. 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; } } ... Bruce Scharlau, University of Aberdeen, 2010

  22. 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 } ... Bruce Scharlau, University of Aberdeen, 2010

  23. 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 Bruce Scharlau, University of Aberdeen, 2010

  24. 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 Bruce Scharlau, University of Aberdeen, 2010

  25. Duke’s Auction MIDlet retrieves list of auction items AuctionJ2meItems Send query to db Creates vector of these Database AuctionItems AuctionJ2meItems ResultSet returned Serialises to RMS Vector returned AuctionMIDlet Servlet Bruce Scharlau, University of Aberdeen, 2010

  26. 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 Bruce Scharlau, University of Aberdeen, 2010

  27. The servlet responds to the call private 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 Bruce Scharlau, University of Aberdeen, 2010

  28. 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 Bruce Scharlau, University of Aberdeen, 2010

  29. 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); } Use AuctionJ2meItem object Notice that we convert startDataAI to Date from long Bruce Scharlau, University of Aberdeen, 2010

  30. 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 Bruce Scharlau, University of Aberdeen, 2010

  31. 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 Bruce Scharlau, University of Aberdeen, 2010

  32. 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 Bruce Scharlau, University of Aberdeen, 2010

  33. 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 Bruce Scharlau, University of Aberdeen, 2010

More Related