Am refactoring code on Netbeans. So far in less than 30 mins, 3 Java crashes with the latest one causing a kernel panic!
Tsk Tsk Tsk -- Monkeys!
Edit--4th crash, System freeze!
Monday, March 25, 2013
Sockets and/vs http
By design, http should be pretty robust but since we're talking about Java here, that's another totally different story.
The guys that did JWebSocket went out of their way to port the whole implementation to j2me(even though they made some errors with reading the byte 0xff). It's helpful that it maintains a relatively stable socket connection and will throw an Exception caught in the main app just incase a connection is lost or closed.
Current problem while using http(and which has left me at an impasse) is Timeouts(covered here). This(while I might be terribly wrong), I attribute to the fact that every http connection is atomic and involves setting up and tearing a connection instance. Add to that the fact that different j2me CLDC* implementations restrict the number of connections(sometimes to as little as 2) and the darn s60 bug I found, using sockets over http starts to look a bit more interesting.
As an implementation, Badu and the other guys server-side are working on it, but this is how I would do it:
The guys that did JWebSocket went out of their way to port the whole implementation to j2me(even though they made some errors with reading the byte 0xff). It's helpful that it maintains a relatively stable socket connection and will throw an Exception caught in the main app just incase a connection is lost or closed.
Current problem while using http(and which has left me at an impasse) is Timeouts(covered here). This(while I might be terribly wrong), I attribute to the fact that every http connection is atomic and involves setting up and tearing a connection instance. Add to that the fact that different j2me CLDC* implementations restrict the number of connections(sometimes to as little as 2) and the darn s60 bug I found, using sockets over http starts to look a bit more interesting.
As an implementation, Badu and the other guys server-side are working on it, but this is how I would do it:
- First of all, I'd like to piggy back on the current ws connection
- To do this, I would have to shape my requests into a json format e.g {"type" : "POST", "content" : {/*JSON object/array of key=>value pairs to represent the parameters*/}}
*CLDC-Connected Limited Device Configuration(where Limited really means LIMITED)
Connection Timeouts
Just noticed that the app has a number of connection Timeouts which caused the app to continue waiting on a response from a dead connection. This mean that the app would essentially wait forever for a connection that has already - less than ideal, needless to say.
Bit the bullet on that and approached the problem from another angle. I create a timertask which after a period x will check to see if the connection has been read(using a boolean flag) and if not, try and close the connection. I then have it throw a custom Exception which I wanted to catch in the main app so that I can know that the connection timed out and handle accordingly.
Unfortunately, timerTask inherits from Thread which means that there's no way to catch the thrown Exception outside it's own thread(and hence the calling method). So in essence, am stuck with a half-baked thread which cleans up pending open connections after the timeout but which cannot communicate back to the original calling Thread(and hence method) to notify it of the action.
P/S: Am still thinking some more on how to solve this problem. :(
Researching, I found that I can define a boolean value when opening the connection which should essentially throw an Exception when the timeout reached with no response from server.
HttpConnection http = (HttpConnection)Connector.open(url, Connector.READ_WRITE, true);Again with the monkey design in Java, the parameter list does not take a time parameter hence, I cannot manually define the timeout myself. Instead, I have to wait for a system-dependent timeout that no-one seems to know the real value of(ranging from 60 secs to 5 mins-depending on who you ask). I tested this and did not get any Exception thrown even though the app lost connection for quite sometime(situ 15 mins).
Bit the bullet on that and approached the problem from another angle. I create a timertask which after a period x will check to see if the connection has been read(using a boolean flag) and if not, try and close the connection. I then have it throw a custom Exception which I wanted to catch in the main app so that I can know that the connection timed out and handle accordingly.
connectionTimeOut = true;
final Timer timer = new Timer();
TimerTask timeoutTask = new TimerTask(){
public void run(){System.out.println("Timeout Expired:");
//Shutdown streams
try {
if(connectionTimeOut){
if(is != null){
//Close all streams
is.close();
}
timer.cancel(); //Shutdown timer
System.out.println("Timing out..");
//Throw exception to be handled in main class
kill = true;
throw new TimeoutException("Connection Timed Out!");
}
} catch (TimeoutException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
};
timer.schedule(timeoutTask, 3000);
Unfortunately, timerTask inherits from Thread which means that there's no way to catch the thrown Exception outside it's own thread(and hence the calling method). So in essence, am stuck with a half-baked thread which cleans up pending open connections after the timeout but which cannot communicate back to the original calling Thread(and hence method) to notify it of the action.
P/S: Am still thinking some more on how to solve this problem. :(
Friday, March 15, 2013
s60 Bug
I've been battling with this issue for the last couple of days. Very simply, this is what's up.
When making a POST request in an s60 device, the first request goes through but subsequent requests immediately following fail. However, a requested submitted a few seconds later will work.
After literally ripping the code apart, I found that a HTTP-400 error is what triggers the failure. Testing on another platform and language confirms that the server is not to blame here. More digging on the internet seems to point to a somewhat native issue with the underlying http methods and their hold on data/resources during and after a http request.(Even issues surrounding memory leak have been raised)
http://www.developer.nokia.com/Community/Discussion/showthread.php?102878-http-error-400-with-Content-Type
http://www.developer.nokia.com/Community/Discussion/showthread.php?67798-CHTTPFormEncoder-and-HTTP-CORE-10-Panic
When making a POST request in an s60 device, the first request goes through but subsequent requests immediately following fail. However, a requested submitted a few seconds later will work.
After literally ripping the code apart, I found that a HTTP-400 error is what triggers the failure. Testing on another platform and language confirms that the server is not to blame here. More digging on the internet seems to point to a somewhat native issue with the underlying http methods and their hold on data/resources during and after a http request.(Even issues surrounding memory leak have been raised)
http://www.developer.nokia.com/Community/Discussion/showthread.php?102878-http-error-400-with-Content-Type
http://www.developer.nokia.com/Community/Discussion/showthread.php?67798-CHTTPFormEncoder-and-HTTP-CORE-10-Panic
Tuesday, March 5, 2013
Java and it's inherent stupidity(Textfield-a case study)
That monkey called James Gosling needs to be shot off the tree that he's hanging!
The monkies who designed java and it's implementation fucked again! Spent the whole night debugging Textfield which throws an incomprehensible Uncaught exception java/lang/IllegalArgumentException.
This is because the value being passed is greater than the (compulsory)defined size of the Item.
new TextField("Group Name", name, 10, TextField.ANY);Now, you might be tempted here to get the maxSize() for TextField, but the values am getting are stupid platform suggestions that make no sense(i.e 12). So because I know any device capable of installing Saya is also capable of holding at least 100 chars in a text field, I hardcoded the limit to such
new TextField("Group Name", name, 100, TextField.ANY);But also was careful enough to make sure the dynamic content being inserted there(i.e name) does not exceed the limit.
if(name.length()>99){
name = name.substring(0, 99);
}
http://jcs.mobile-utopia.com/jcs/67140_TextField.html
public class TextField extends Item
A TextFieldis an editable text component that may be placed into a {@link Form Form}. It can be given a piece of text that is used as the initial value.
ATextFieldhas a maximum size, which is the maximum number of characters that can be stored in the object at any time (its capacity). This limit is enforced when theTextFieldinstance is constructed, when the user is editing text within theTextField, as well as when the application program calls methods on theTextFieldthat modify its contents. The maximum size is the maximum stored capacity and is unrelated to the number of characters that may be displayed at any given time. The number of characters displayed and their arrangement into rows and columns are determined by the device.
The implementation may place a boundary on the maximum size, and the maximum size actually assigned may be smaller than the application had requested. The value actually assigned will be reflected in the value returned by {@link #getMaxSize() getMaxSize()}. A defensively-written application should compare this value to the maximum size requested and be prepared to handle cases where they differ.
Saturday, March 2, 2013
Working with Arrays
So this is an example of the returned json for 'get_info' request
1. Split first. Very simple method for splitting a string into an array along defined separators
{"success":"1","info":{"created":"2012-8-30 16:47:59","country":"Ghana","user_id":"2","onlinestatus":"1","last_login_datetime":"2013-3-2 22:13:10","nickname":"badu","discover":"0"},"interests":[" cook","eat"]}Interests is an array of values. The doc specifies updating interests at such
interests - comma separated list of interestsObviously, a suitable method for converting between arrays and a comma separated string value(s) is required. Unfortunately for Java and by extension J2ME, they never bothered to think that people might implementations similar to split and join in Python. So here goes..
1. Split first. Very simple method for splitting a string into an array along defined separators
public String[] split(String original, String separator)2. Now the slightly harder part. Convert the returned array in the json response to a string. First problem here is that getting the array involves returning it as a JSONArray which apparently is not castable to a normal String Array. So this is how you do it...
{
Vector nodes=new Vector();
//Parse nodes into Vector
int index=original.indexOf(separator);
while(index>=0){
nodes.addElement(original.substring(0, index));
original=original.substring(index+separator.length());
index=original.indexOf(separator);
}
//Get the last node
nodes.addElement(original);
//Create split array
String[] result=new String[nodes.size()];
if(nodes.size()>0){
for(int loop=0; loop<nodes.size(); loop++)
{
result[loop]=(String)nodes.elementAt(loop);
}
}
return result;
}//--End of split()
//Convert JSONArray to String ArrayThis is followed by the join method which I implemented as such:
JSONArray key_array = json.getJSONArray("interests");
String[] key_attributes = new String[key_array.length()];
for(int i=0; i<key_array.length(); i++){
key_attributes[i] = key_array.getString(i);
}
public String join(String[] array, char separator){Now calling the method join, you MUST remember to provide the separator as a character. In java, it's not easy to type out a character variable in code and instead, one has to go around like this:
//Catch empty array
if (array == null) return null;
if(array.length == 0) return null;
String joined_string = "";
for(int i=0; i<array.length;){
joined_string += array[i] + separator;
i++; //Don't forget to increment
}
//Truncate trailing seprator
return joined_string.substring(0, joined_string.length()-1);
}//--End of join()
String separator = ",";There you go folks, all done with Java's usual unfriendly long way of getting simple things done.!
interests = join(key_attributes, separator.charAt(0));
Subscribe to:
Comments (Atom)