Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Highlighted
Developer
Posts: 18
Registered: ‎02-10-2009
My Device: Not Specified

HttpPushDemo - Connector.Open(http://:[port]) blocks in thread

I setup the HTTPPushDemo using the simulator with no problems.  When I load the example onto my Curve it acts like the Connector.open() call blocks within the thread.  If I make the Connector.open() call outside of the thread it works fine.  I am puzzled why this is happening.  I am using version 4.3 and did not make any changes to the example.  Does anyone have any idea what the issue is?

Developer
Posts: 1,415
Registered: ‎07-30-2008
My Device: Not Specified

Re: HttpPushDemo - Connector.Open(http://:[port]) blocks in thread

You can't do anything outside of a thread, it defines an ordered stream of execution.

If you hold the ui lock and do something that would cause a user prompt, if could create

deadlock apparently. Can you post the code? IO often blocks and this in particular is supposed to.

 

Developer
Posts: 18
Registered: ‎02-10-2009
My Device: Not Specified

Re: HttpPushDemo - Connector.Open(http://:[port]) blocks in thread

[ Edited ]

This code is copied from the HttpPushDemp.  Right when it calls Connector.open(URL + ";deviceside=false") it acts like it blocks.

 

public void run()
{

StreamConnection stream = null;
InputStream input = null;
MDSPushInputStream pushInputStream=null;
while (!_stop)
{
try
{
synchronized(this) //synchronize here so that we don't end up creating a connection that is never closed
{
// open the connection once (or re-open after an IOException),
// so we don't end up in a race condition, where a push is lost if
// it comes in before the connection is open again.
// we open the url with a parameter that indicates that we should always
// use MDS when attempting to connect.
_notify = (StreamConnectionNotifier)Connector.open(URL + ";deviceside=false");

}

 

Message Edited by mikes2002 on 02-10-2009 07:10 PM
Developer
Posts: 1,415
Registered: ‎07-30-2008
My Device: Not Specified

Re: HttpPushDemo - Connector.Open(http://:[port]) blocks in thread

Take out the synchronized around the IO and find out if you need the ui lock to

modify text in realized gui components. Depending on who else wants to loch this

it is an ideal setup for deadlock. It is quite possible that the synchronized is "blocking"

or the gui is confused or prompting.

What is "this" and who else would sync on it?

 

Use a finally block to close the connection and other things, not a synchronized.

Developer
Posts: 18
Registered: ‎02-10-2009
My Device: Not Specified

Re: HttpPushDemo - Connector.Open(http://:[port]) blocks in thread

I already tried removing the synchronized block but it did not help.  I wondered about a prompt but since this is in a thread it should work.  At least accorrding to this.  Since this is an example from the JDE you would think it would work. 

 

Here is all of the code.  I assume 'this' is for the thread.

 

/** * HTTPPushDemo.java * * Copyright © 1998-2008 Research In Motion Ltd. * * Note: For the sake of simplicity, this sample application may not leverage * resource bundles and resource strings. However, it is STRONGLY recommended * that application developers make use of the localization features available * within the BlackBerry development platform to ensure a seamless application * experience across a variety of languages and geographies. For more information * on localizing your application, please refer to the BlackBerry Java Development * Environment Development Guide associated with this release. */ package com.rim.samples.device.httppushdemo; import java.io.*; import javax.microedition.io.*; import net.rim.device.api.ui.*; import net.rim.device.api.ui.component.*; import net.rim.device.api.ui.container.*; import net.rim.device.api.system.*; import net.rim.device.api.util.*; import net.rim.device.api.io.http.*; /** * The client side of a simple HTTP Push system. * This application will listen for image data on the specified port and * render the data when it arrives. */ class HTTPPushDemo extends UiApplication { // Constants ---------------------------------------------------------------- private static final String URL = "http://:100"; // PORT 100. private static final int CHUNK_SIZE = 256; // Members ------------------------------------------------------------------ private ListeningThread _listeningThread; private HTTPPushDemoScreen _mainScreen; private RichTextField _infoField; private RichTextField _imageField; public static void main(String[] args) { HTTPPushDemo theApp = new HTTPPushDemo(); theApp.enterEventDispatcher(); } // Constructor -------------------------------------------------------------- private HTTPPushDemo() { _mainScreen = new HTTPPushDemoScreen(); _mainScreen.setTitle(new LabelField("HTTP Push Demo" , LabelField.USE_ALL_WIDTH)); _infoField = new RichTextField(); _mainScreen.add(_infoField); _mainScreen.add(new SeparatorField()); _imageField = new RichTextField(); _mainScreen.add(_imageField); // Spin off the listening thread. _listeningThread = new ListeningThread(); _listeningThread.start(); _infoField.setText("HTTP Listen object started"); pushScreen(_mainScreen); } // Inner Classes ------------------------------------------------------------ private class ListeningThread extends Thread { private boolean _stop = false; private StreamConnectionNotifier _notify; private synchronized void stop() { _stop = true; try { // Close the connection so the thread will return. _notify.close(); } catch (IOException e) { System.err.println(e.toString()); } catch (NullPointerException e) { // The notify object likely failed to open, due to an IOException. } } public void run() { StreamConnection stream = null; InputStream input = null; MDSPushInputStream pushInputStream=null; while (!_stop) { try { // Synchronize here so that we don't end up creating a connection that is never closed. synchronized(this) { // Open the connection once (or re-open after an IOException), so we don't end up // in a race condition, where a push is lost if it comes in before the connection // is open again. We open the url with a parameter that indicates that we should // always use MDS when attempting to connect. _notify = (StreamConnectionNotifier)Connector.open(URL + ";deviceside=false"); } while (!_stop) { // NOTE: the following will block until data is received. stream = _notify.acceptAndOpen(); try { input = stream.openInputStream(); pushInputStream= new MDSPushInputStream((HttpServerConnection)stream, input); // Extract the data from the input stream. DataBuffer db = new DataBuffer(); byte[] data = new byte[CHUNK_SIZE]; int chunk = 0; while ( -1 != (chunk = input.read(data)) ) { db.write(data, 0, chunk); } updateMessage(data); // This method is called to accept the push. pushInputStream.accept(); input.close(); stream.close(); data = db.getArray(); } catch (IOException e1) { // A problem occurred with the input stream , however, the original // StreamConnectionNotifier is still valid. System.err.println(e1.toString()); if ( input != null ) { try { input.close(); } catch (IOException e2) { } } if ( stream != null ) { try { stream.close(); } catch (IOException e2) { } } } } _notify.close(); _notify = null; } catch (IOException ioe) { // Likely the stream was closed. Catches the exception thrown by // _notify.acceptAndOpen() when this program exits. if ( _notify != null ) { try { _notify.close(); _notify = null; } catch ( IOException e ) { } } } } } } private void updateMessage(final byte[] data) { Application.getApplication().invokeLater(new Runnable() { public void run() { // Query the user to load the received message. String[] choices = {"Ok" , "Cancel" }; if ( 0 != Dialog.ask("New message received. Do you want to render it?" , choices, 0) ) { return; } _infoField.setText("Text received - size: " + data.length); try { _imageField.setText(new String(data)); } catch (Exception e) { Dialog.inform(e.toString()); System.err.println(e.toString()); } } }); } protected void onExit() { // Kill the listening thread. _listeningThread.stop(); try { _listeningThread.join(); } catch (InterruptedException e) { System.err.println(e.toString()); } } private class HTTPPushDemoScreen extends MainScreen { /** * @see net.rim.device.api.ui.Screen#close() */ public void close() { onExit(); super.close(); } } }

 

 

Developer
Posts: 1,415
Registered: ‎07-30-2008
My Device: Not Specified

Re: HttpPushDemo - Connector.Open(http://:[port]) blocks in thread

It does look like the sync is limited and doesn't exist for duration of operation but again there may be  no

point to doing this and I lost track of where the loops end, LOL. Certainly you may want reorganize a bit

and try to put closes in finally blocks etc.

See if this would work, I have to admit I'm  a bit confused on a few issues and not sure if I'm suggesting the broken "double check locking" idea. Simply put, I think just

making _notify and _flag volatile would do what you need but be sure to check. Or, you could just

use synchronized around assignments and tests to publish your results.

If open() blocks and someone calls stop what will happen? You block whoever

called stop(). If you don't have a handle to kill when stop is called, and comments suggest this is the motivation,  set a volatile flag,use synchronized around predictable code if needed,  and return immediately. Let the thing kill itself when it returns and sees the flag. If you want to be sure to wake up the stuck accept() call, then

you can call _notify.close()  and make _notify volatile. This sounds a lot more complicated and you do have to be careful

( see for example things like this approach that keep coming up, LOL. http://www.google.com/search?hl=en&rlz=1G1GGLQ_ENUS312&q=site%3Asun.com+%22double+check+locking%22 ) 

but I generally avoid synchronized around IO code.  If you look at sun.com for related terms, you will find discussions of deadlock

in various close() operations.  You can see actual specs here,

http://java.sun.com/docs/books/jls/third_edition/html/memory.html 

 

 

From prior discussion, while I have never used push, it seems to be implemented as a TCP server socket so

if you knew what port it is on you could see if you have one from another thread.

 

If  I'm reading this right the open() call could block, but I'll admit it isn't real clear if it refers to the open()

call blocking or just later usage,

 

http://www.blackberry.com/developers/docs/4.5.0api/javax/microedition/io/Connector.html

 

 

Blocking Operations
If you use Connector.open() to implement a javax.microedition.io interface, make sure an application uses the implementation to open a connection from within a non-main event thread. If an application runs the connection from within the main event thread, the application will lock. The following interfaces perform blocking operations:

 

BlackBerry Development Advisor
Posts: 15,784
Registered: ‎07-09-2008
My Device: BlackBerry PRIV
My Carrier: Bell

Re: HttpPushDemo - Connector.Open(http://:[port]) blocks in thread

Do you receive a prompt to allow the connection?  If not, try pressing Alt+Escape to switch between applications in case the prompt has appeared in the background. 
Mark Sohm
BlackBerry Development Advisor

Please refrain from posting new questions in solved threads.
Problem solved? Click the Accept As Solution button.
Found a bug? Report it using Issue Tracker
Developer
Posts: 18
Registered: ‎02-10-2009
My Device: Not Specified

Re: HttpPushDemo - Connector.Open(http://:[port]) blocks in thread

No I do not see a prompt.  I actually already tried the alt+escape to see what was open.  Nothing different showed up.
BlackBerry Development Advisor
Posts: 15,784
Registered: ‎07-09-2008
My Device: BlackBerry PRIV
My Carrier: Bell

Re: HttpPushDemo - Connector.Open(http://:[port]) blocks in thread

Has the BlackBerry handheld been configured on a BlackBerry Enterprise Server?  deviceside=false directs the connection through the BES.  If you wait for a few minutes, is an exception thrown?  The default timeout is 2 minutes.  Does the application have permissions to make a connection?  You can set that by going to Options, Advanced Options, Applications, selecting your application and choose Edit Permissions from the menu.

Mark Sohm
BlackBerry Development Advisor

Please refrain from posting new questions in solved threads.
Problem solved? Click the Accept As Solution button.
Found a bug? Report it using Issue Tracker
Developer
Posts: 68
Registered: ‎10-26-2008
My Device: Not Specified

Re: HttpPushDemo - Connector.Open(http://:[port]) blocks in thread

Has this issue been resolved?  I'm also having issues with a block on Connector.open. The code works fine from the simulator, but on the device it just hangs on Connector.open.  I toggled the "deviceside" parameter to true and false, and nothing changed.  The UI is not forzen, I can still exit the application or access other features...the code is also error/exception free. Nothing is being thrown and since I sign the app, I assume that is enough as far as permissions go.  Any ideas on what might cause Connector.open to just hang without throwing an error or exception?