Monday, March 25, 2013

Crashes!

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!

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:

  • 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.

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

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
TextField is 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.

TextField has 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 the TextField instance is constructed, when the user is editing text within the TextField, as well as when the application program calls methods on the TextField that 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
{"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 interests 
Obviously, 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)
                {
                    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()
     
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...
            //Convert JSONArray to String Array
            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);
            }
 This is followed by the join method which I implemented as such:

public String join(String[] array, char separator){
        //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()
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:
    String separator = ",";
            interests = join(key_attributes, separator.charAt(0));
There you go folks, all done with Java's usual unfriendly long way of getting simple things done.!