Showing posts with label REST. Show all posts
Showing posts with label REST. 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>


26 January 2015

REST Web Services Part 2 - Java

Sometime last year, I started what I hoped would be a blog post series on REST in various languages.




Part one was using CFML and Taffy. Due to the usual complaints of time and patience it’s taking me forever to continue it, but hey ho. Here’s the second part. In this one I wanted to look at a java implementation of REST services. To make it more interesting I wanted to use Google App Engine (GAE) for hosting. Google App Engine is a great resource for testing as its pretty solid and a generous with its free quota. Plus it frees me from the worries of settings up a proper environment.


Obviously using Java for REST and then forcing all of this into the specifications of GAE may prove a little tricky. However I'm sure there are some technologies out there which do all the hard work leaving me to just define my rest services with minimal fuss.


So I started out with some Googling of GAE and REST. Support seemed overwhelmingly in favour of something called Restlet. Which with a bit of reading seemed to be a framework for creating REST services with Java. Plus it had a specific release for Google App Engine. Perfect!


Retlet didn’t have a “built for stupid” tutorial, so I've made my own. It’s loosely based on this intro



Start by downloading Restlet gae zip file and unzip




So lets use the backend project we created in my last tutorial




Create a libs directory under the root of backend.


Opening your unzipped Restlet folder to this directory restlet-gae-2.3.0\lib find the following two files:


  • org.restlet.ext.servlet.jar
  • org.restlet.jar


and copy them into your new libs directory and add this line to your gradle dependencies


compile fileTree(dir: 'libs', include: ['*.jar'])


Now add the following .java files to you backend package:
  • MyApplication
  • MyServerResource
  • NewServerResource


MyApplication.java
package com.example.myapplication.backend;

import org.restlet.Application;
import org.restlet.Restlet;
import org.restlet.routing.Router;

public class MyApplication extends Application {

    /**
     * Creates a root Restlet that will receive all incoming calls.
     */
    @Override
    public Restlet createInboundRoot() {
        // Create a router Restlet that routes each call to a
        // new instance of HelloWorldResource.
        Router router = new Router(getContext());

        // Defines only one route
        router.attachDefault(MyServerResource.class);
        //router.attach("/base/{username}", NewServerResource.class);
        //router.attach("/base", NewServerResource.class);

        return router;
    }
}
MyServerResource.java
package com.example.myapplication.backend;

import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;

public class MyServerResource extends ServerResource{

    @Get
    public String represent(){
        return "Hello world";
    }
}
Now edit your web.xml file


webapp/WEB-INF/web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
    <display-name>first steps servlet</display-name>

    <servlet>
        <servlet-name>SystemServiceServlet</servlet-name>
        <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
        <init-param>
            <param-name>services</param-name>
            <param-value>com.example.myapplication.backend.MyEndpoint</param-value>
        </init-param>
    </servlet>

    <servlet>
        <servlet-name>RestletServlet</servlet-name>
        <servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
        <init-param>
            <param-name>org.restlet.application</param-name>
            <param-value>com.example.myapplication.backend.MyApplication</param-value>
        </init-param>
    </servlet>

    <!-- Catch all requests -->
    <servlet-mapping>
        <servlet-name>SystemServiceServlet</servlet-name>
        <url-pattern>/_ah/spi/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>RestletServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

Note despite the Restlet tutorial I've left SystemServiceServlet in there. Ideally I’d want to remove this but GAE whines incessantly if you don’t have a servlet named SystemServiceServlet. Perhaps there’s a way to rename the RestletServlet but maybe one for another day.


That’s it. Now I shall try and explain a bit what’s going on. MyApplication is where the magic really happens, this is where we configure our REST urls. This line sets the default behaviour


router.attachDefault(MyServerResource.class);


Which if you open MyServerResource.java you’ll see it’s super simple it just says “hello world”. If you were to only include the attachDefault method (as above) you could happily run your app and http://localhost:8080/hippopotamus would return Hello world. This is a super simple GET request.


Fantastic! One job done.


Now Let’s make it a big more complicated. Let’s add a GET method with a param and a POST method. (un-comment the two router.attach lines in myApplication).


NewServerResource.java
package com.example.myapplication.backend;

import org.restlet.data.Form;
import org.restlet.representation.Representation;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.ServerResource;


public class NewServerResource extends ServerResource{

    @Get
    public String restGetMethod(){

        String username  = "";
        try{
            //get param from request
            username = getRequest().getAttributes().get("username").toString();

        }catch(Exception e){
            username = "default";
        }

        return "Dear " + username + ". All your base are belong to me!";
    }

    @Post
    public String restPostMethod(Representation r){

        String username = "";

        //Get form details
        final Form form = new Form(r);

        //get username field out of form
        username = form.getFirstValue("username");

        return "Morning " + username + ". I've had it with all these snakes on the plane.";
    }
}

So a bit more complicated. The first is a @Get method which looks for a username param and returns “Dear username. All your base are belong to me!”


The second is based on a POST method. Here we’re grabbing the Form object and requests a value for the field username. It returns “Morning username. I've had it with all these snakes on the plane.”


So lets take a look how we pass these params to these methods back in MyApplication.


router.attachDefault(MyServerResource.class);
router.attach("/base/{username}", NewServerResource.class);
router.attach("/base", NewServerResource.class);


When you use router.attach you need to give it a url. So you can see here if we pass localhost:8080/base/gonzo then we’ll hit NewServerResource with the param username=gonzo. This is out GET request.


If we pass /base we’ll hit NewServerResource without any params. This will be our POST request.


So to summarize here are the responses we can expect to see from various REST urls:










Lastly to test the POST I’ve constructed a little form
<html>
    <head>
        <title>Post test</title>
    </head>
    <body>
        <p>Hello this is a post test for localhost</p>
        <br />
        <form action="http://localhost:8080/base" method="POST">
            <input name="username" type="text" />
            <button name="submit" type="submit" value="submit">Submit</button>
        </form>
    </body>
</html>

Note the input box. If we fill that in and submit we get this:


Morning Kermit. I've had it with all these snakes on the plane.


Fantastic, exactly what we wanted.


This is great, I’m delighted, a very easy way to get REST running on the cloud. Good work to all the chaps at Restlet, great little product and I feel like I’m only scratching the surface.

22 July 2014

REST Web Services - Part 1 - CFML

Dammit Adam! If there's one thing I hate more than learning its being inspired to learn!

Last week Adam Cameron got me thinking about REST Web Services, he challenged his readers, what is the best language for building them. Well I had a few thoughts which I shared. Basically it depends which language the developer in question is most comfortable in, and which environment is most accessible. In my time I've been lucky enough to be paid to work in a lot of languages and a lot of environments, so I thought I’d do a quick re-cap of a few languages and maybe even attempt a few which I've never learnt. How long it takes before my patience and time run out, we’ll see :)


My environment will be mostly Ubuntu as that’s what I run at home these days, and I’m too poor to run a server. However if I make it on to Microsoft development I’m anticipating switching to Windows 7. As for the REST services themselves I’m going for Keep It Simple Stupid here, basic proof of concept stuff. I want a GET and a POST method and that’s about it. Also I’m largely ignoring security for the time being.


First up is ColdFusion.
I’ve spent many of my years being paid as a CFML developer and I’m most comfortable with it. I should be able to knock out some REST web services here pretty quick. As much as I like CFML, Rest in CF is a pain in the neck. To me the syntax is not intuitive, mistakes are difficult to pin point, debugging is very difficult and testing a nightmare. Someone reminded me of an add on called Taffy, which is a REST framework for CF. I've never encountered Taffy myself, so I'm hopeful and excited for the challenge.


First I install Railo express, not rocket science, suffice to say it works and in just two minutes I’m running a test cfm page. (Awesome job Railo guys!)


Now I need to get Taffy running. So I download the zip file and extract it. Loosely skimming through the docs I see I can just drop the taffy folder into my Railo root. Awesome, drag and drop, ok, now what? OK So back to the docs, I’ve got to add an extension to my Application.cfc and create a hello.cfc. So not that drag and drop then. After about thirty minutes fiddling around with resources directories and tweaking Application.cfc files I’ve finally got the Taffy welcome page working properly. What held me up was *not* using the Application.cfc supplied in the docs but instead borrowing the one from the help folder. My setup is as such:


Railo/webapps/ROOT/hiya
-- Application.cfc (see below)
-- index.cfm (empty cfm file)
Railo/webapps/ROOT/hiya/resources
-- hello.cfc (my REST webservices)


I now have Taffy running with Railo. This is awesome, the format for web services is pretty good, I don't need to endlessly update Railo or my application config, it just works. The test bed is the best thing, I love the bootstrap layout and it makes it so simple and easy to test. I've put a screenshot down the bottom.

Here's some code.


My Application.cfc is:

<cfcomponent extends="taffy.core.api">
    <cfscript>

        this.name = hash(getCurrentTemplatePath());

        variables.framework = {};
        variables.framework.debugKey = "debug";
        variables.framework.reloadKey = "reload";
        variables.framework.reloadPassword = "true";
        variables.framework.representationClass = "taffy.core.genericRepresentation";
        variables.framework.returnExceptionsAsJson = true;

        function onApplicationStart(){
            return super.onApplicationStart();
        }

        function onRequestStart(TARGETPATH){
            return super.onRequestStart(TARGETPATH);
        }

        // this function is called after the request has been parsed and all request details are known
        function onTaffyRequest(verb, cfc, requestArguments, mimeExt){
            // this would be a good place for you to check API key validity and other non-resource-specific validation
            return true;
        }

    </cfscript>
</cfcomponent>




Finally the important bit here are my web services (hello.cfc):

component extends="taffy.core.resource" taffy_uri="/hello" {

     function get(){
        return representationOf(['all your base are belong to me. :)']);
    }
    
    function post(String name){
        return representationOf(['Nice to meet you ' & name]);
    }

 }
And CFML is done. All this, including install of Railo and Taffy took me around an hour.

If you’re Adam Tuttle, congratulations Taffy is a fantastic product and I'm very impressed. The ease at which I can deploy web services and most importantly test them is now fantastic. I don’t need to create silly little html forms or anything, it’s all built in. This is genius.  If I may offer my two cents here, you've got a little work to do on the docs. Especially the initial deployment. It’s gotta be step by step built for idiots like me. If I can’t make it work quickly, I lose interest. That aside you should be really proud.



10 June 2013

CFML REST webservices with Railo

I've been doing a lot of REST web services with CFML and Railo lately and wanted to write up my experiences in case it helps.

First you need to setup Railo with your webservice cfc:
http://www.getrailo.org/index.cfm/whats-up/railo-40-released/features/rest-services/

Second you need to create and configure your cfc:
<cfcomponent rest="true" restpath="/hello">

The restpath provides the step in your URL from which your service is accessed. A normal REST webservice is pretty straightforward. Ensure your method is set to access="remote" and add in httpMethod and a restPath param to the cffunction.
<cffunction name="getmuppets" access="remote" httpmethod="GET" restpath="/getmuppets">

The restpath identifies the url structure you'll use to access the webservice.
The httpmethod tells the webservice if it should respond to GET/POST/PUT etc methods. These methods are defined and talked about more in REST definitions: http://en.wikipedia.org/wiki/Representational_state_transfer#Vocabulary_re-use_vs._its_arbitrary_extension:_HTTP_and_SOAP

Returning data is fairly standard, but if you want to return JSON then you might want to look at my previous blog post.

I've found that unlike much of CFML REST is case sensitive, so its a good idea to make everything lowercase.

This should be enough to get you going, but pretty soon you'll need to add arguments. So lets have a quick look at REST arguments. Lets assume for now we're just interested in a GET request.

You add your cfargument as your normally would, but you also need a param called restArgSource.

<cfargument name="intage"    type="numeric"    restArgSource="Path">

Your new method would look like this:
    <cffunction name="getmuppets" access="remote" produces="application/json" httpmethod="GET" restpath="/getmuppets/intage/{intage}/strsex/{strsex}/">
        <cfargument name="intage"    type="numeric"    restArgSource="Path">
        <cfargument name="strsex"    type="string"    restArgSource="Path">
        
        .....
    </cffunction>

Pay particular attention to how the restpath needs to be updated to match the new arguments. We're using restArgSource set to path, which means your url needs to provide those arguments. Here's an example URL:
http://localhost/rest/demo/hello/getmuppets/intage/30/strsex/male
Each step in the URL is a piece of the puzzle.

There are a few types that restArgSource accepts:
  • Path
  • Query
  • Matrix
  • Cookie / Header
  •  Form
Query is pretty straightforward, instead of using path (as above) you can just get your arguments from the query scope, i.e. ?strage=30. Form is when an argument comes from the FORM scope and you'd normally only use this for post and put httpMethods.
For a full explanation of these types, this article provides a good explanation:
http://www.adobe.com/devnet/coldfusion/articles/restful-web-services.html

That's it, you should be ready to write your own. Best of luck!







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"}]