BlackBerry - How do I access a database (or create HTTP connection) in a background thread when the UI Application is not open <p><strong>Overview:</strong></p> <p>Our application extends a UIApplication and has a SMS Listener class that is registered on boot. When a message is received that fits our criteria we process the message and then we want to save it to a local SQLite database as well as upload it to a Web Server. It is important that this happens as soon as possible after the SMS is received, even if the UI Application is not open at that stage.</p> <p><strong>Problem:</strong></p> <p>When the SMSListener Instance is running in the background, with no UIApplication instance active, and wants to access the SQLite database or tries to create a HTTP Connection a “No Application Instance” exception is thrown.</p> <p><strong>Desired outcome:</strong></p> <p>We want to process, save and upload all the messages from the SMSListener background thread even if the UIApplication is not active. Currently the SMSListener background thread would store the messages in the RuntimeStore; when the UI Application is started it reads the messages from the RuntimeStore and saves it to the database. This is not an optimal solution though, because the synchronisation with the Web Server would also then only happen when the UI Application is next opened. It is important that it rather syncs when the message is received.</p> <p><strong>Application Pseudo Code:</strong></p> <p>Main Class, checks for startup and creates a SMSListener instance or gets the instance from the RuntimeStore.</p> <pre class="lang-java prettyprint-override"><code>public class OurAppUi extends UiApplication { public static void main(String[] args) { if (args != null &amp;&amp; args.length &gt; 0 &amp;&amp; args[0].endsWith("gui")) { // Create a new instance of the application and make the currently // running thread the application's event dispatch thread. OurAppUi theApp = new OurAppUi(); theApp.enterEventDispatcher(); } else { // Entered through the alternate application entry point SmsListener.waitForSingleton(); } } } </code></pre> <p>The SMSListener Class listens for any incoming messages, makes use of the RuntimeStore Singleton Model. This is working as expected.</p> <pre class="lang-java prettyprint-override"><code>public class SmsListener implements javax.wireless.messaging.MessageListener { public static SmsListener waitForSingleton() { //Ensure this is a singleton instance. //Open RuntimeStore and obtain the reference of BackgroundListener RuntimeStore store = RuntimeStore.getRuntimeStore(); Object obj = store.get(ID_BACKGROUND_LISTENER); //If obj is null, there is no current reference to BackgroundListener //Start a new instance of BackgroundLIstener if one is not running if(obj == null) { store.put(ID_BACKGROUND_LISTENER, new SmsListener()); return (SmsListener)store.get(ID_BACKGROUND_LISTENER); } else { return(SmsListener)obj; } } public void notifyIncomingMessage(MessageConnection conn) { new Thread() { MessageConnection connection; Thread set (MessageConnection con) { this.connection = con; return (this); } public void run() { try { Message m = connection.receive(); String msg = null; if (m instanceof TextMessage) { TextMessage tm = (TextMessage)m; msg = tm.getPayloadText(); } // Process the SMS SMSObject sms = processSMS(msg); // Save to DataBase { Exception is Thrown Here } SQLManager.getInstance().save(sms); // Upload to Web Server { Exception is Thrown Here } WebServer.upload(sms); } catch(Exception error) { } } }.set(conn).start(); } } </code></pre> <p>When the SmsListener Instance wants to access the SQLite database or tries to create a HTTP Connection a “No Application Instance” exception is thrown. </p> <pre class="lang-java prettyprint-override"><code>public final class SQLManager { private SQLManager() { try { db = OpenOrCreateDatabase(); } catch (MalformedURIException e) { Debug.log(TAG, "Get connection: URI: " + e.getMessage()); } catch (ControlledAccessException e) { Debug.log(TAG, "Get connection: Controlled Access: " + e.getMessage()); } catch (DatabasePathException e) { Debug.log(TAG, "Get connection: Database Path: " + e.getMessage()); } catch (DatabaseIOException e) { Debug.log(TAG, "Get connection: Database IO: " + e.getMessage()); } catch (Exception e) { Debug.log(TAG, e); } } public static synchronized SQLManager getInstance() { if (instance == null) { instance = new SQLManager(); } return instance; } } </code></pre> <p>We’ve tried store the SQLite instances in the RuntimeStore, using the same Singleton Model as the SMSListener but received errors when the UI Application tried to access the stored DB Instance. </p>