Showing posts with label JSON. Show all posts
Showing posts with label JSON. Show all posts

25 January 2016

Using a mock RESTful API with Android OkHttp and getSandbox

I recently stumbled across a really cool service called getSandbox.com. This is a API mocking service which can mimic RESTful or SOAP webservices. This is incredibly useful for knocking up quick testing tools or as an endpoint for unit tests.


This has huge advantages as it allows you to protect your server from unit test bombarding, however I'm more interested in just being able to use it just to quickly setup a few examples for prototyping. You can deploy it on your server or using their cloud, but they offer a free tier just for a low number of requests.


So I decided to setup a getsandbox account and use it with okHttp on Android to see if I can do some simple REST get and post requests.




First I created a new sandbox, I didn't have an Apiary account and this is a test API so I've no WSDL nor a RAML and I don’t know what Swagger is. So I picked blank. This is great, it gives you a temporary one hour sandbox with a few simple get and post methods.


  • GET/hello - Respond hello world
  • GET/users - Show all users
  • POST/users - Add new user


Sandbox even gives you some form of storage, so anything you add is persistent.


With my new endpoints I created a form (see below) to test the POST and in a browser hit the main url to get all users. Magic, everything is responding wonderfully. Sandbox is really that simple and easy to use! I'm super impressed.


Next we’re over to Android and I wanted to use OkHttp for this one. OkHttp is a neat little library that handles http requests for you and easily deals with any problems. Plus it can make synchronous and asynchronous calls with ease.

I created a new Android Studio project and added in the okhttp gradle compile:

compile 'com.squareup.okhttp3:okhttp:3.0.1'

Then I put INTERNET permissions in the manifest, a ListView in my activity view and started the java code. First I made my activity implement okhttp3.Callback, most tutorials will tell you to put the callback inside the method call, but personal preference, I like implements.
Here’s the simple OkHttp code:

OkHttpClient client = new OkHttpClient();
//Create a simple get request
Request request = new Request.Builder().url(sUrl).build();
//Execute with call back
client.newCall(request).enqueue(this);

You don’t get much simpler than that. The request is a fairly self evident GET request, nothing in the body and nothing fancy.
Next you have a choice,


client.newCall(...).execute or .enqueue.


Execute is a blocking synchronous call whilst enqueue is an asynchronous call. We’ll use enqueue as we can’t do a blocking call on the UI thread anyway.

So my Activity now overrides onFailure onResponse

@Override
public void onResponse(Call call, Response response) throws IOException {
  Log.i("http", "onResponse");

  int j = 0;
  String[] users = null;

  try {
     //Read string in as json array
     JSONArray jsonArray = new JSONArray(response.body().string());

     users = new String[jsonArray.length()];
     //add each element in array to string array
     for (int i = 0; i < jsonArray.length(); i++) {
        if(jsonArray.get(i) != null) {
           users[j] = jsonArray.get(i).toString();
           j++;
        }
     }
  } catch (JSONException e) {
     e.printStackTrace();
  }

  if (users != null){
     //Create adapter of users
     mAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, users);

     //listview needs to be updated on ui thread.
     runOnUiThread(new Runnable() {
        @Override
        public void run() {
           mListView.setAdapter(mAdapter);
        }
     });
  }
}


That's pretty much it. The code in onResponse isn't rocket science. We take the response from OkHttp and parse it as a json array. We can now loop through it and create a normal String array. We could do a bit more error checking here and clean some dodgy input, but for sake of speed that's your lot. The only slight oddity is having to set the listview using runOnUi because we can't change the UI elements outside of the UI thread. The again....now I think, I didn't really need to set that after the data did I? I could have done that in the Acivity onCreate....oh well, next time!

So look what we've done in just a few lines of code and a few clicks. We've done some web interaction without any need for asyncs or checking if we have a connection. Plus we've got a fantastic test API which responds quickly, updates instantly and is super easy to use.


Just in case you need to submit to a POST, here's my mega javascript form:

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {
                $('#submit').click(function(){
                
                    console.log('hiii');

                    $.ajax({
                        url: "http://**myid**.getsandbox.com/users",
                        type:'POST',
                        data:
                        {
                            username: $('#username').val()
                        },
                        success: function(msg){
                            $('#username').val("");
                        }               
                    });

                    return false;
                });
            });
        </script>
    </head>

    <body>
        <form>
            <input type="text" name="username" id="username" value="" />
            <button name="go" id="submit">Submit</button>
        </form>
    </body>
</html>


30 May 2013

Railo Rest JSON Web Service


So I've been writing lots of REST web services lately with Railo 4.0 and noticed a strange issue / feature when returning json.

So I write me a nice little function and I think everything will work with a little CFML magic:

    <cffunction name="getmuppets" access="remote" returntype="string" httpmethod="GET" restpath="/getmuppets">
        <cfscript>
            var arrMuppets    = [
                {name = "kermit", age = 20},
                {name = "fuzzy", age = 30},
                {name = "animal", age = 40}
            ];
            
            return serializeJson(arrMuppets)
        </cfscript>
    </cffunction>


All good? No :( The json is fine when you call the function locally, but when you call it as a rest webservice all the double quotes get escaped. Which renders it invalid json and is not much use for anything.
"[{\"age\":20,\"name\":\"kermit\"},{\"age\":30,\"name\":\"fuzzy\"},{\"age\":40,\"name\":\"animal\"}]"


So I eventually figured out you've got to change the headers and content returned by the function.
    <cffunction name="getmuppets" access="remote" produces="application/json" httpmethod="GET" restpath="/getmuppets">
        <cfscript>
            var arrMuppets    = [
                {name = "kermit", age = 20},
                {name = "fuzzy", age = 30},
                {name = "animal", age = 40}
            ];
            
            response    = {
                status        = 200,
                headers        = {},
                content        = serializeJson(arrMuppets)
            };
        
            restSetResponse(response);
        </cfscript>
    </cffunction>

Once you do all that, you get valid json:


[{"age":20,"name":"kermit"},{"age":30,"name":"fuzzy"},{"age":40,"name":"animal"}]

17 March 2013

Hamlet's Monkey - Part 2


OK so a while back I started work on my oh so awesome Hamlet's Monkey project. Anyway, I figured if the loop is too large, it'll just choke my CF instance, so this might be better handled as a java project.

I'm going to focus on the red light method as the green light method is just pretty simple. Basically, loop for a specified number of times grab a random letter and then check it against the Hamlet string. If we're successful add a new letter, if not, the monkey has to start again!
So here's the crux of it all:


private static char generateRandomLetter(){
 Random rnd = new Random();
 char strChar = lstAlphabet.charAt(rnd.nextInt(lstAlphabet.length()));
 return strChar;
}

public static void main(String[] args) {
    int            intCount                 = 0;
    String        strSubString            = "";
    String        strShakespeare            = Shakespeare.replaceAll("[^a-zA-Z]", ""); //Shakespeare without spaces etc
    String        strMonkeyString            = "";
    String        strBestSoFar            = "";
    
    while (intCount < intNumLoops) {
        intCount++;
        
        //generate the random guess, one keystroke at a time
        strMonkeyString    = strMonkeyString + Character.toString(generateRandomLetter());
        
        strSubString    =    strShakespeare.substring(0,strMonkeyString.length());
        
        System.out.print(strMonkeyString + "==" + strSubString);

        //check if we're done
        if(strMonkeyString.equalsIgnoreCase(strSubString)){
            System.out.println(" ** Nice guess, move along please.");
            if(strSubString.length() > strBestSoFar.length()){
                strBestSoFar    =    strSubString;
            }
        }else{
            System.out.println("");
            strMonkeyString    = "";
        }
    }
    
    trackProgress(intCount,strBestSoFar);
    
}


What was more interesting was how to store the results. What I decided to do was to write to a file using a JSON struct. This file could then store the results which could be read in every time the class was run and we'll know its all time success rate.
So again, not a complicated couple of functions. trackProgress gets called from the main function. It just reads the results from the file, and tries to decode the two JSON variables into local variables. If the current best guess is better than the one on file, we use the new one. Otherwise we just add a running total of the number of loops we've done. The read and write functions should be pretty self explanatory.

        @SuppressWarnings("unchecked")
        private static void writeResultsToFile(long intKeyStrokes, String strBestGuess){
            
            //create json object
            JSONObject obj = new JSONObject();
            obj.put("intKeyStrokes", intKeyStrokes);
            obj.put("strBestGuess", strBestGuess);
            
            //write it to file
            try {
                FileWriter file = new FileWriter(strFileName);
                file.write(obj.toJSONString());
                file.flush();
                file.close();
         
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        private static JSONObject readResultsFromFile(){
            JSONParser parser = new JSONParser();
            JSONObject jsonObject = new JSONObject();
            
            try {
                //read from file
                Object obj = parser.parse(new FileReader(strFileName));
                jsonObject = (JSONObject) obj;
         
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return jsonObject;
        }
        
        
        private static void trackProgress(int intKeyStrokes, String strBestGuess){
            JSONObject    jsonObject                = readResultsFromFile();
            String        strBestGuessFromFile    = "";
            long        intKeyStrokesFromFile    = 0;
            String        strNewBestGuess            = "";
            long        intNewStrokes            = 0;
            
            if(jsonObject.get("intKeyStrokes") != null && jsonObject.get("strBestGuess") != null){
                strBestGuessFromFile    = (String) jsonObject.get("strBestGuess");
                intKeyStrokesFromFile    = (long) jsonObject.get("intKeyStrokes");
            }
     
            //whichever string is longer, this is the new best guess
            if(strBestGuess.length() > strBestGuessFromFile.length()){
                strNewBestGuess        = strBestGuess;
            }else{
                strNewBestGuess        = strBestGuessFromFile;
            }
            
            //number of key strokes is cumulative
            intNewStrokes            = intKeyStrokes + intKeyStrokesFromFile;
            
            writeResultsToFile(intNewStrokes,strNewBestGuess);
            System.out.println("Finishing - " + intNewStrokes + " keystrokes-" + strNewBestGuess);
        }
Oh yea, there's one thing. You'll need the the json simple project to use all this json goodness. https://code.google.com/p/json-simple/

To import this library into your project in eclipse, simply right click on the project go down to "Build Path" -> "Add External Archives..." then add the json-simple.1.1.1.jar Simple :)

Here's the full code: http://pastebin.com/h29t3bD7 Have fun!