This question might be long, but I want to provide much information.
Overview: I'm creating a Stock Quotes Ticker app for Blackberry. But I'm having problems with my StringBuffer that contains an individual Stock information.
Process: My app connects to our server via SocketConnection. The server sends out a formatted set of strings that contains the latest Stock trade. So whenever a new trade happens, the server will send out an individual Stock Quote of that trade. Through an InputStream I am able to read that information and place each character in a StringBuffer that is referenced by Threads. By parsing based on char3 I am able to determine a set of stock quote/information.
char1 - to separate data
char3 - means end of a stock quote/information
sample stock quote format sent out by our server:
stock_quote_name(char 1)some_data(char1)some_data(char1)(char3)
My app then parses that stock quote to compare certain data and formats it how it will look like when displayed in the screen. When trades happen gradually(slow) the app works perfectly. However..
Problem: When trades happen too quickly and almost at the same time, My app is not able to handle the information sent efficiently. The StringBuffer has its contents combined with the next trade. Meaning Two stock information in one StringBuffer.
field should be: Stock_quote_name some_data some_data
sample of what's happening: Stock_quote_name some_data some_dataStock_quote_name some_data some_data
here's my code for this part:
while (-1 != (data = is.read()))
{
sb.append((char)data);
while(3 != (data = is.read()))
{
sb.append((char)data);
}
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
try
{
synchronized(UiApplication.getEventLock())
{
SetStringBuffer(sb);
DisplayStringBuffer();
RefreshStringBuffer();
}
} catch (Exception e)
{
System.out.println("Error in setting stringbuffer: " + e.toString());
}
}
});
}
public synchronized void DisplayStringBuffer()
{
try
{
//parse sb - string buffer
......
}
catch(Exception ex)
{
System.out.println("error in DisplayStringBuffer(): " + ex.toString());
}
}
public synchronized void SetStringBuffer(StringBuffer dataBuffer)
{
this.sb =dataBuffer;
System.out.println(sb);
}
public synchronized void RefreshStringBuffer()
{
this.sb.delete(0, this.sb.length());
}
From what I can see, when trades happen very fast, The StringBuffer is not refreshed immediately and still has the contents of the previous trade, when i try to put new data.
My Question is:
Do you guys have any suggestion on how i can put data into the StringBuffer, without the next information being appended to the first content
The part where you read data is synchronized, but the part where you append data to the buffer is not. If you are reusing the same StringBuffer each time, you will have a race condition.
Well, since you are using invokeLater to set / display / clear your StringBuffer, you're right, there's nothing blocking you from going back up to the next read() call and modifying that StringBuffer before you're able to dispaly it.
Obviously you're not reading from the input stream from your event thread, so in order to update the UI you need to either use invokeLater OR synchronize on the event lock, but you're doing both.
If you want to use invokeLater, then you'll need to make sure you don't append to your StringBuffer with your input stream reader thread while your event thread is attempting to display the data in the UI. Thus, you'll probably look into creating a new StringBuffer for each Runnable.
If you want to synchronize on the event lock, something like this could work (which might work better as it avoids unnecessary garbage creation with creating new Runnables / StringBuffers).
while (-1 != (data = is.read()))
{
sb.append((char)data);
while(3 != (data = is.read()))
{
sb.append((char)data);
}
synchronized(UiApplication.getEventLock())
{
SetStringBuffer(sb);
DisplayStringBuffer();
RefreshStringBuffer();
}
}
You can't reuse the same StringBuffer for each stock quote because you are reading the next stock quote before the UI thread has finished displaying the last one. Remember, you are writing to the StringBuffer on one thread, and reading the StringBuffer on another. There is no guarantee that the UI thread (reading thread) has called RefreshStringBuffer() before the loop iterates and starts appending the next stock quote to the StringBuffer.
Use a collection of Strings instead.
java.util.queue<String> q = new java.util.concurrent.ConcurrentLinkedQueue<String>();
then do q.add(sb.toString()); when your done putting the quote into sb.
to display the quotes
public void DisplayStockQuote() {
while(!q.isEmpty()) {
String s = q.poll();
// display s
try
{
//parse s - string containing stock quote
......
}
catch(Exception ex)
{
System.out.println("error in DisplayStringBuffer(): " + ex.toString());
}
}
}
Call that method from your UI thread instead of
SetStringBuffer(sb);
DisplayStringBuffer();
RefreshStringBuffer();
I suggest you try avoiding the extra thread and go with Bradley's solution. But if you really want to have two threads, something like this will work.
Related
I suspect that my understanding of Streams in Dart might have a few holes in it...
I have a situation in which I'd like a Dart app to respond to intermittent input (which immediately suggests the use of Streamss -- or Futures, maybe). I can implement the behavior I want with listener functions but I was wondering how to do this in a better, more Dartesque way.
As a simple example, the following (working) program listens to keyboard input from the user and adds a div element to the document containing what has been typed since the previous space, whenever the space bar is hit.
import 'dart:html';
main() {
listenForSpaces(showInput);
}
void listenForSpaces(void Function(String) listener) {
var input = List<String>();
document.onKeyDown.listen((keyboardEvent) {
var key = keyboardEvent.key;
if (key == " ") {
listener(input.join());
input.clear();
} else {
input.add(key.length > 1 ? "[$key]" : key);
}
});
}
void showInput(String message) {
document.body.children.add(DivElement()..text = message);
}
What I'd like to be able to do is to create a new Stream from the Stream that I'm listening to (in the example above, to create a new Stream from onKeyDown). In other words, I might set the program above out as:
var myStream = ...
myStream.listen(showInput);
I suspect that there is a way to create a Stream and then, at different times and places, insert elements to it or call for it to emit a value: it feels as though I am missing something simple. In any case, any help or direction to documentation would be appreciated.
Creating a new stream from an existing stream is fairly easy with an async* function.
For a normal stream, I would just do:
Stream<String> listenForSpaces() async* {
var input = <String>[];
await for (var keyboardEvent in document.onKeyDown) {
var key = keyboardEvent.key;
if (key == " ") {
yield input.join();
input.clear();
} else {
input.add(key.length > 1 ? "[$key]" : key);
}
}
}
The async* function will propagate pauses through to the underlying stream, and it may potentially pause the source during the yield.
That may or may not be what you want, since pausing a DOM event stream can cause you to miss events. For a DOM stream, I'd probably prefer to go with the StreamController based solution above.
There are several methods and there is a whole package rxdart to allow all kinds of things.
Only the final consumer should use listen and only if you need to explicitly want to unsubscribe, otherwise use forEach
If you want to manipulate events like in your example, use map.
I wasn't originally planning to answer my own question but I have since found a very simple answer to this question in the dartlang creating streams article; in case it's helpful to others:
Specifically, if we'd like to create a stream that we can insert elements into at arbitrary times and places in the code, we can do so via the StreamController class. Instances of this class have an add method; we can simply use the instance's stream property as our stream.
As an example, the code in my question could be rewritten as:
import 'dart:html';
import 'dart:async';
main() async {
// The desired implementation stated in the question:
var myStream = listenForSpaces();
myStream.listen(showInput);
}
Stream<String> listenForSpaces() {
// Use the StreamController class.
var controller = StreamController<String>();
var input = List<String>();
document.onKeyDown.listen((keyboardEvent) {
var key = keyboardEvent.key;
if (key == " ") {
// Add items to the controller's stream.
controller.add(input.join());
input.clear();
} else {
input.add(key.length > 1 ? "[$key]" : key);
}
});
// Listen to the controller's stream.
return controller.stream;
}
void showInput(String message) {
document.body.children.add(DivElement()..text = message);
}
(As mentioned in the article, we need to be careful if we want to set up a stream from scratch like this because there is nothing to stop us from inserting items to streams that don't have associated, active subscribers; inserted items would in that case be buffered, which could result in a memory leak.)
I have Vaadin 7 code to give the user an option to download a file:
Button btnDownloadResults = new Button("Download Results", FontAwesome.CLOUD_DOWNLOAD);
resource = new StreamResource(new MyStreamResource(), suggestedSaveAsFilename);
new FileDownloader(resource).extend(btnDownloadResults);
I would like to trigger code when the download has succeeded, or even if the download manages to start. Uses for this include closing a window, starting a progress spinner, or incrementing a download count.
Unlike the Vaadin Upload component, the FileDownloader does not have any listeners for finding out when a file download fails, succeeds, or starts.
Here is a simplified version of my StreamResouce subclass:
public class MyStreamResource implements StreamSource {
#Override
public InputStream getStream() {
String filename = /* code to determine the filename */;
try {
final File results = new File(FilenameUtils.normalize(filename));
return new FileInputStream(results);
} catch (FileNotFoundException fnfe) {
String errorMsg = "Cannot download results. Try again later, or contact your sysadmin.";
Utilities.showError(errorMsg);
return null;
} catch (Exception e) {
Utilities.logAndShowException(e);
return null;
}
}
}
Note that the getStream method returns before the user has even been prompted where to save the file (which they can choose to cancel.) So I can't trigger anything from inside that method.
One suggestion I got was to subclass the FileDownloader as follows:
FileDownloader fileDownloader = new FileDownloader(fileInputStream) {
private static final long serialVersionUID = -4584979099145066535L;
#Override
public boolean handleConnectorRequest(VaadinRequest request, VaadinResponse response, String path) throws IOException {
boolean result = super.handleConnectorRequest(request, response, path);
if (result) {
/* YOUR LOGIC GOES HERE */
}
return result;
}
} ;
Again, this fires too soon (and the boolean result is always true, even if my StreamSource returns null.)
Any suggestions?
After more research I believe the answer is that there is no simple way to get this information from the FileDownloader.
The difficulty appears to be a consequence of the way the FileDownloader is designed. From the FileDownloader docs:
"Download should be started directly when the user clicks e.g. a Button without going through a server-side click listener to avoid triggering security warnings in some browsers."
Because there is no round-trip back to the web server, there is no place to respond when the download fails, starts, or succeeds.
Some vague (and possibly bad) ideas for a workaround:
Have JS post some kind of asynchronous notification to the web
server, letting it know what happened. (Using JMS or Ajax?)
If there was some kind active process on the backend involved with transferring the file, it
would know when the transfer happened.
But the short answer seems to be there is no built-in way in Vaadin to do it.
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.
I've read several related posts and even posted and answer here but it seems like I was not able to solve the problem.
I have 3 Activities:
Act1 (main)
Act2
Act3
When going back and forth Act1->Act2 and Act2->Act1 I get no issues
When going Act2->Act3 I get no issues
When going Act3->Act2 I get occasional crashes with the following error: java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor#.... This is a ListView cursor.
What I tried:
1. Adding stopManagingCursor(currentCursor);to the onPause() of Act2 so I stop managing the cursor when leaving Act2 to Act3
protected void onPause()
{
Log.i(getClass().getName() + ".onPause", "Hi!");
super.onPause();
saveState();
//Make sure you get rid of the cursor when leaving to another Activity
//Prevents: ...Unable to resume activity... trying to requery an already closed cursor
Cursor currentCursor = ((SimpleCursorAdapter)getListAdapter()).getCursor();
stopManagingCursor(currentCursor);
}
When returning back from Act3 to Act2 I do the following:
private void populateCompetitorsListView()
{
ListAdapter currentListAdapter = getListAdapter();
Cursor currentCursor = null;
Cursor tournamentStocksCursor = null;
if(currentListAdapter != null)
{
currentCursor = ((SimpleCursorAdapter)currentListAdapter).getCursor();
if(currentCursor != null)
{
//might be redundant, not sure
stopManagingCursor(currentCursor);
// Get all of the stocks from the database and create the item list
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
((SimpleCursorAdapter)currentListAdapter).changeCursor(tournamentStocksCursor);
}
else
{
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
}
}
else
{
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
}
startManagingCursor(tournamentStocksCursor);
//Create an array to specify the fields we want to display in the list (only name)
String[] from = new String[] {StournamentConstants.TblStocks.COLUMN_NAME, StournamentConstants.TblTournamentsStocks.COLUMN_SCORE};
// and an array of the fields we want to bind those fields to (in this case just name)
int[] to = new int[]{R.id.competitor_name, R.id.competitor_score};
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter tournamentStocks = new SimpleCursorAdapter(this, R.layout.competitor_row, tournamentStocksCursor, from, to);
//tournamentStocks.convertToString(tournamentStocksCursor);
setListAdapter(tournamentStocks);
}
So I make sure I invalidate the cursor and use a different one. I found out that when I go Act3->Act2 the system will sometimes use the same cursor for the List View and sometimes it will have a different one.
This is hard to debug and I was never able to catch a crashing system while debugging. I suspect this has to do with the time it takes to debug (long) and the time it takes to run the app (much shorter, no pause due to breakpoints).
In Act2 I use the following Intent and expect no result:
protected void onListItemClick(ListView l, View v, int position, long id)
{
super.onListItemClick(l, v, position, id);
Intent intent = new Intent(this, ActivityCompetitorDetails.class);
intent.putExtra(StournamentConstants.App.competitorId, id);
intent.putExtra(StournamentConstants.App.tournamentId, mTournamentRowId);
startActivity(intent);
}
Moving Act1->Act2 Act2->Act1 never gives me trouble. There I use startActivityForResult(intent, ACTIVITY_EDIT); and I am not sure - could this be the source of my trouble?
I would be grateful if anyone could shed some light on this subject. I am interested in learning some more about this subject.
Thanks,D.
I call this a 2 dimensional problem: two things were responsible for this crash:
1. I used startManagingCursor(mItemCursor); where I shouldn't have.
2. I forgot to initCursorAdapter() (for autocomplete) on onResume()
//#SuppressWarnings("deprecation")
private void initCursorAdapter()
{
mItemCursor = mDbHelper.getCompetitorsCursor("");
startManagingCursor(mItemCursor); //<= this is bad!
mCursorAdapter = new CompetitorAdapter(getApplicationContext(), mItemCursor);
initItemFilter();
}
Now it seems to work fine. I hope so...
Put this it may work for you:
#Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
orderCursor.requery();
}
This also works
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
startManagingCursor(Cursor);
}
I have a need to access the encoded stream in OpenRasta before it gets sent to the client. I have tried using a PipelineContributor and registering it before KnownStages.IEnd, tried after KnownStages.IOperationExecution and after KnownStages.AfterResponseConding but in all instances the context.Response.Entity stream is null or empty.
Anyone know how I can do this?
Also I want to find out the requested codec fairly early on yet when I register after KnowStages.ICodecRequestSelection it returns null. I just get the feeling I am missing something about these pipeline contributors.
Without writing your own Codec (which, by the way, is really easy), I'm unaware of a way to get the actual stream of bytes sent to the browser. The way I'm doing this is serializing the ICommunicationContext.Response.Entity before the IResponseCoding known stage. Pseudo code:
class ResponseLogger : IPipelineContributor
{
public void Initialize(IPipeline pipelineRunner)
{
pipelineRunner
.Notify(LogResponse)
.Before<KnownStages.IResponseCoding>();
}
PipelineContinuation LogResponse(ICommunicationContext context)
{
string content = Serialize(context.Response.Entity);
}
string Serialize(IHttpEntity entity)
{
if ((entity == null) || (entity.Instance == null))
return String.Empty;
try
{
using (var writer = new StringWriter())
{
using (var xmlWriter = XmlWriter.Create(writer))
{
Type entityType = entity.Instance.GetType();
XmlSerializer serializer = new XmlSerializer(entityType);
serializer.Serialize(xmlWriter, entity.Instance);
}
return writer.ToString();
}
}
catch (Exception exception)
{
return exception.ToString();
}
}
}
This ResponseLogger is registered the usual way:
ResourceSpace.Uses.PipelineContributor<ResponseLogger>();
As mentioned, this doesn't necessarily give you the exact stream of bytes sent to the browser, but it is close enough for my needs, since the stream of bytes sent to the browser is basically just the same serialized entity.
By writing your own codec, you can with no more than 100 lines of code tap into the IMediaTypeWriter.WriteTo() method, which I would guess is the last line of defense before your bytes are transferred into the cloud. Within it, you basically just do something simple like this:
public void WriteTo(object entity, IHttpEntity response, string[] parameters)
{
using (var writer = XmlWriter.Create(response.Stream))
{
XmlSerializer serializer = new XmlSerializer(entity.GetType());
serializer.Serialize(writer, entity);
}
}
If you instead of writing directly to to the IHttpEntity.Stream write to a StringWriter and do ToString() on it, you'll have the serialized entity which you can log and do whatever you want with before writing it to the output stream.
While all of the above example code is based on XML serialization and deserialization, the same principle should apply no matter what format your application is using.