destroyApp() Is Your Friend

By Vikram Goyal

This tip is in response to a recent discussion on the Sun forums about the thread-safety of RecordStore operations. Although the discussion goes in several different directions, the core question remains: How do you protect yourself from unsafe operations of third-party libraries?

The answer is not simple, but this tech tip will try to answer the specific example raised at the start of this discussion. Perhaps that will help provide general directions for handling such things in the real world.

RecordStore Safety

The problem boils down to individual record entry safety. The record entry method itself is atomic, recordStore.addRecord(), and therefore guaranteed to be thread-safe. However, as pointed out in the forums discussion, if consistency is measured in terms of two records being written to the record store, and if only one is entered and the second entry is interrupted because the application management software (AMS) has called destroyApp() between the two calls, have you lost a way to manage your data? Is the data now inconsistent?

Of course not.

This is where the real reason for the destroyApp() method comes into the picture, even if it is called by third-party software.

In the following code, I present the destroyApp() method that would handle this scenario consistently.

  public void destroyApp(boolean unconditional)
    throws MIDletStateChangeException {

    if(!unconditional) {
      if(!recordsWritten) { // Records have not been written yet -- wait!
        throw new MIDletStateChangeException();
      } else { // Records written -- MIDlet can be destroyed!
      }
    } else { // must destroy
      if(!recordsWritten) {
        // Roll back the record that was written.
        if(storage != null) { // Was the store ever opened?
          try {
            storage.deleteRecord(recordId1);
          } catch (Exception ex) {
            ex.printStackTrace();
          }
        }
      }
    }
  }

The destroyApp() method gives you a way to complete unfinished items before it actually closes the MIDlet. The AMS may want to close the MIDlet unconditionally, in which case, you have no choice but to close the MIDlet. But if the closing is not unconditional, and if in the middle of the writing process, you can throw the MIDletStateChangeException to finish the writing process.

Because the data is considered to be consistent only if all of it is written (in this case, two record items), you use the flag of recordsWritten to indicate this. Then you use this flag to monitor the state of the data.

If this flag is set as false, you have not finished the writing process, so you must roll back any data that has been written. It is possible that the destroyApp() method may be called before either of the records has been written. This is fair enough, and trying to delete the first record will raise an exception, which is silently ignored.

The process of writing -- and deleting -- data is itself atomic, so you can be fairly confident that data is not corrupted in between the writing processes. To further insulate from such corruption, you can synchronize on the storage object while writing or deleting.

I hope that this simple example has given you an idea on how to handle the effects of third-party libraries better. Concurrency and data safety are complex subjects, and the developer should understand the problem domain in detail before attempting specific solutions.

Resources

Comments:

Excellent !!!

Posted by K.C.Ashish Kumar on October 05, 2009 at 01:34 PM PDT #

I think that data atomic operation should be handled with transactions and not some code that might be broken

Posted by Some guy on October 06, 2009 at 06:05 PM PDT #

Some guy,

Not sure what you mean. Which part of the code is broken? Could you elaborate?

Vikram

Posted by Vikram Goyal on October 06, 2009 at 08:42 PM PDT #

if is not a function. You put spaces after catch, you might want to consider putting spaces after if.

"Code Conventions for the Java Programming Language"
http://java.sun.com/docs/codeconv/

Posted by Mark Williams on October 12, 2009 at 03:44 PM PDT #

So boring ...

What if some guy in operations takes the server out of electricity ? Would your solution help as well.

This is defnetly a solution of engeneers and not of real life. To solve such cases, use transactions, or just make sure you can monitor such cases and handle them manually or by some kind of resend.

Remember - KIS is mandatory for such solutions.

Posted by reply on October 12, 2009 at 11:56 PM PDT #

i do not understand this code at all, but i would love to im an collage student at riverside community collage and im taking an cis-18 class and i need your help understanding this "code" thing.

Posted by lenisha on October 13, 2009 at 07:20 AM PDT #

lenisha, just say what all you want to learn in jave me, i will try to help.

Posted by Raj on October 21, 2009 at 04:15 AM PDT #

Hii..
Thank you for sharing such a nice information. I like this site very much. I will surely bookmark it for future use. Good Work! Keep it up!

Posted by bluetooth freisprecheinrichtun on November 09, 2009 at 04:51 PM PST #

Hmm... a thought:
If there is time in destroyApp() to call
storage.deleteRecord(recordId1);
why not store the correct record in the first place?
And how do you know there is time to call deleteRecord() before the midlet shuts down on you?

Posted by darius on November 24, 2009 at 08:09 PM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Tips for developers who use Java technologies (Java SE, Java ME, JavaFX) for mobile and embedded devices.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today