I have a BlackBerry Application that sends messages to a server at fixed intervals. The messages are sent via web service using any of the connection methods available; Wifi, BIS, TCP/IP etc.
Since the messages are being sent continuously, I need a mechanism to queue the messages in case internet is not available and send the messages across when internet becomes available. For that reason, I wish to first save any outgoing message in the Persistent Store and then read the Persistent Store and loop through it to send all pending messages. Any new message should be saved at the last spot in the Persistent Store.
I am calling the two methods below when "Send" is clicked:
public static void saveMessage(String msg){
Hashtable hashtable=new Hashtable();
persistentObject = PersistentStore.getPersistentObject(KEY);
hashtable.put("MessageToSend", msg);
persistentObject.commit();
}
public static void sendMessage(String msg){
Hashtable hashtable=new Hashtable();
persistentObject = PersistentStore.getPersistentObject(KEY);
Vector msgVector = (Vector)persistentObject.getContents();
Enumeration eMsgs=msgVector.elements();;
/*synchronized(poObject )*/{
persistentObject.setContents(msgVector);
persistentObject.commit();
}
int i=0;
while(eMsgs.hasMoreElements()){
hashtable=(Hashtable)eMsgs.nextElement();
String encryptedMessage=(String)hashtable.get("MessageToSend");
if(!encryptedMessage.equals("")){
//check internet connection
String C0NNECTION_EXTENSION = checkInternetConnection();
if(C0NNECTION_EXTENSION==null)
{
Dialog.alert("Check internet connection and try again");
return;
}
else
{
MyScreen.PostMsgToServer(encryptedMessage);
hashtable.remove(encryptedMessage);
}
}
i++;
}
}
This is just an attempt from the tutorials/examples that I came across. Kindly help.
The save method you show is not actually putting the hashtable into the PersistentObject
. Try something like this instead:
public static void saveMessage(String msg){
Hashtable hashtable = new Hashtable();
persistentObject = PersistentStore.getPersistentObject(KEY);
hashtable.put("MessageToSend", msg);
persistentObject.setContents(hashtable); // <- you were missing this
persistentObject.commit();
}
That's still probably not a great implementation, because I'm assuming that you might want to call saveMessage()
multiple times, and add more than one message to the persistent store (?). Is that right, or can you only ever have one message saved? (if that's true, you can ignore this next suggestion for saveMessage()
)
public static void saveMessage(String msg){
persistentObject = PersistentStore.getPersistentObject(KEY);
Hashtable hashtable = (Hashtable) persistentObject.getContents();
if (hashtable == null) {
// lazily initialize the store contents
hashtable = new Hashtable();
hashtable.put("MessagesToSend", new Vector());
}
Vector queuedMessages = (Vector) hashtable.get("MessagesToSend");
queuedMessages.addElement(msg);
// write the store contents to device storage
persistentObject.setContents(hashtable);
persistentObject.commit();
}
/**
* @param msg TODO: I'm not sure why msg needs to be passed, if
* saveMessage(msg) was called first?
*/
public static void sendMessage(String msg){
// TODO: you could choose to save the message here, so that the caller
// need not remember to call both sendMessage() and saveMessage()
// saveMessage(msg);
persistentObject = PersistentStore.getPersistentObject(KEY);
Hashtable hashtable = (Hashtable) persistentObject.getContents();
if (hashtable != null) {
// check for saved messages first, and send them
Vector msgVector = (Vector) hashtable.get("MessagesToSend");
Enumeration eMsgs = msgVector.elements();
Vector toDelete = new Vector();
while (eMsgs.hasMoreElements()) {
String encryptedMessage = (String)eMsgs.nextElement();
// if the send was successful, you should delete message from the store
toDelete.addElement(encryptedMessage);
}
eMsgs = toDelete.elements();
while (eMsgs.hasMoreElements()) {
// we can delete this sent message now
msgVector.removeElement((String)eMsgs.nextElement());
}
// re-write the persistent store to the device
persistentObject.setContents(hashtable);
persistentObject.commit();
}
}
I'd also generally like to steer you away from making everything static
... that said, that's really a bigger, unrelated issue here, and it does happen that your persistent store object is likely to be a unique, global object in your application (a better implementation, however, would probably avoid all these static
declarations).
Update: I'm a little unclear as to how you expect to call these two methods. Based on your description, it seems that you call both saveMessage(msg)
and then sendMessage(msg)
when Send is clicked by the user. If you save the message first, with my implementation, then there is no need to pass msg
in to sendMessage()
, since sendMessage()
will send out all saved, unsent messages in the queue (vector). So, the API for sendMessage()
has an unnecessary parameter. Or, I supposed you could leave sendMessage(String)
as the only public method, and have sendMessage(String)
first call saveMessage(String)
.
In any case, that's up to you, and how you want your method calling semantics to work. The basic problem of storing and retrieving persistent objects should be addressed by the code above.