Showing posts with label google app engine. Show all posts
Showing posts with label google app engine. Show all posts

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 January 2015

Google App Engine and Android playing nice.

I'm a big fan of cloud services, especially when they give you a free or basic quota such as Google App Engine which you can use for development or testing. I’ve done quite a bit of work with Google App Engine before but not in a while. It became a real heavy beast involving importing add ons to Eclipse and configuring a multitude of environment settings.

However recently I've moved to Android Studio and apparently Google Cloud support is built in. Learning this I was then inspired by a recent post on the Android Developers Blog:
http://android-developers.blogspot.co.uk/2014/12/build-mobile-app-services-with-google.html

I felt this wasn't a great tutorial, there were large sections left out and it basically didn't work nearly as easily as I’d hoped it would. Sorry Android Developers, but not your best work. Still the steps to get started were simple enough:
  1. Create a super simple Android app. Basic Hello world stuff.
  2. Give your app Internet permissions
  3. Create a new Google Cloud Module
    • File -> New Module
    • Click “Google Cloud Module”
    • Select App Engine Java Endpoints Module
Android studio will now create a GAE backend module for you and automatically tie it into your Android app. Now you need a bean and an endpoint.

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

public class MyBean {

    private String myData;

    public String getData() {
        return myData;
    }

    public void setData(String data) {
        myData = data;
    }
}


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

import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiNamespace;

import javax.inject.Named;

/**
 * An endpoint class we are exposing
 */
@Api(name = "myApi", version = "v1", namespace = @ApiNamespace(ownerDomain = "backend.myapplication.example.com", ownerName = "backend.myapplication.example.com", packagePath = ""))
public class MyEndpoint {

    /**
     * A simple endpoint method that takes a name and says Hi back
     */
    @ApiMethod(name = "sayHi")
    public MyBean sayHi(@Named("name") String name) {
        MyBean response = new MyBean();
        response.setData("Hi, " + name);

        return response;
    }

}
and here’s the Gradle file:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.appengine:gradle-appengine-plugin:1.9.14'
    }
}

repositories {
    mavenCentral();
}

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'appengine'

sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7

dependencies {
    appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.14'
    compile 'com.google.appengine:appengine-endpoints:1.9.14'
    compile 'com.google.appengine:appengine-endpoints-deps:1.9.14'
    compile 'javax.servlet:servlet-api:2.5'
}

appengine {
    downloadSdk = true
    appcfg {
        oauth2 = true
    }
    endpoints {
        getClientLibsOnBuild = true
        getDiscoveryDocsOnBuild = true
    }
}


Frustratingly you’ll get red errors all over the place. Cannot resolve symbol api. This really winds me up and I’ve not yet figured out how to fix it. However it does build and run with these problems, so not really an error!

If you change the run drop down to “backend” and hit run hopefully this will all compile and you’ll get an Android Studio message with a localhost url. This is Android Studio setting up a local version of Google App Engine and using Jetty to host it. You should see a url output which you can copy to your browser, something like:
http://localhost:8080/

Hitting this url you should get an index file saying Hello Endpoints or something with a nice pretty bootstrap wrapper. You can enter something into the text field and your GAE application will say Hi to you.

Now we need to plug this into our Android app. First we need a new AsyncTask

package tester.example.com.myapplication;

import android.content.Context;
import android.os.AsyncTask;
import android.support.v4.util.Pair;
import android.widget.Toast;

import com.example.myapplication.backend.myApi.MyApi;

import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.extensions.android.json.AndroidJsonFactory;
import com.google.api.client.googleapis.services.AbstractGoogleClientRequest;
import com.google.api.client.googleapis.services.GoogleClientRequestInitializer;


import java.io.IOException;

class EndpointsAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> {
    private static MyApi myApiService = null;
    private Context context;

    @Override
    protected String doInBackground(Pair<Context, String>... params) {
        if(myApiService == null) {  // Only do this once
            MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
                    new AndroidJsonFactory(), null)
                    // options for running against local devappserver
                    // - 10.0.2.2 is localhost's IP address in Android emulator
                    // - turn off compression when running against local devappserver
                    .setRootUrl("http://10.0.2.2:8080/_ah/api/")
                    .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
                        @Override
                        public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
                            abstractGoogleClientRequest.setDisableGZipContent(true);
                        }
                    });
            // end options for devappserver

            myApiService = builder.build();
        }

        context = params[0].first;
        String name = params[0].second;

        try {
            return myApiService.sayHi(name).execute().getData();
        } catch (IOException e) {
            return e.getMessage();
        }
    }

    @Override
    protected void onPostExecute(String result) {
        Toast.makeText(context, result, Toast.LENGTH_LONG).show();
    }
}
Now in your app activityMain or somewhere, fire a call to the AsyncTask:

new EndpointsAsyncTask().execute(new Pair(this, "Manfred"));

The dependencies in your Android app should look like this:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.google.android.gms:play-services:6.1.71'
    compile project(path: ':backend', configuration: 'android-endpoints')
}

Now if you run your Android app in a Android Virtual Device, you should see your local server respond with a Hi Message.

This is a pretty basic example, but you get the idea and its a great first step on the path toward Android and Google Cloud playing well together.

20 March 2013

Hamlet's Monkey - Part 3

I've previously blogged about my Hamlet's Monkey project.

Part 1 where I introduced the concept and did it in CFML:
http://webdeveloperpadawan.blogspot.co.uk/2012/10/hamlets-monkey-code-for-fun.html

Part 2 Where I ported the project into a java class with some JSON file read and writing:
http://webdeveloperpadawan.blogspot.co.uk/2013/03/hamlets-monkey-part-2.html

OK So now this whole project is moving toward where I was really excited to take it. GOOGLE! hahah I want to put this project on Google App Engine (GAE) so it uses cloud computing. That way a GAE cloud instance is like an actual monkey, tapping away at the keyboard and trying to re-write Hamlet! Awesome! This straight away introduces two potential problems:
  1. I've got to turn the project into a java servlet
  2. Tracking progress - In part 2 we added file storage, this won't work in the cloud, so we'll need to find a better method.


OK So converting the main crux of the method to a servlet isn't that complicated. The first thing you need to do is install the GAE plugin for eclipse. https://developers.google.com/appengine/docs/java/tools/eclipse Then we'll convert the project we made in Part 2 to a servlet, the public class needs to extend HTTPServlet:
public class Shakespearemonkey extends HttpServlet {

and the main method becomes doGet, which is what is called when the servlet responds to a http get request:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        int            intCount                 = 0;
        String        strSubString            = "";
        String        strShakespeare            = Shakespeare.replaceAll("[^a-zA-Z]", ""); //Shakespeare without spaces etc
        String        strMonkeyString            = "";
        String        strBestSoFar            = "";
        response.setContentType("text/html");
        
        while (intCount < intNumLoops) {
            intCount++;
            
            //generate the random guess, one keystroke at a time
            strMonkeyString    = strMonkeyString + Character.toString(generateRandomLetter());
            
            strSubString    =    strShakespeare.substring(0,strMonkeyString.length());
            
            //check if we've guessed correctly so far
            if(strMonkeyString.equalsIgnoreCase(strSubString)){
                //Is this our best guess so far
                if(strSubString.length() > strBestSoFar.length()){
                    strBestSoFar    =    strSubString;
                }
            }else{
                //incorrect guess, start again
                strMonkeyString    = "";
            }
        }
        
        trackProgress(intCount,strBestSoFar);
        
        //purely for output, re-read the latest and update user on progress
        try {
            response.getWriter().println("Good Morning, I am your monkey! I will be trying to guess the string: " + strShakespeare + "<br />");
            MonkeyResults monkeyresults    = readResultsFromFile();
            response.getWriter().println("My best guess so far is: ");
            response.getWriter().println((String) monkeyresults.getBestGuess());
            response.getWriter().println("<br />I have made ");
            response.getWriter().println((int) monkeyresults.getKeyStrokes());
            response.getWriter().println("keystrokes");
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }


So what I've done is created an object for storing all our progress data. Possibly not necessary / overkill but its OO and it feels good. It's just two getters and setters, so I won't bore you with the code. What is different in the trackProgress function though is I've replaced the JSON code with this:
        MonkeyResults        monkeyResults            = readResultsFromFile();
        
        if(monkeyResults.getKeyStrokes() != 0 && monkeyResults.getBestGuess() != ""){
            strBestGuessFromFile    = (String) monkeyResults.getBestGuess();
            intKeyStrokesFromFile    = (int) monkeyResults.getKeyStrokes();
        }


So I'm going to use the GAE datastore to keep track of our progress. The first step is writing to the datastore:

    static Key            theResultsKey    = KeyFactory.createKey("Results","tblMonkeyResults");
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    

    
    private void writeResultsToFile(int intKeyStrokes, String strBestGuess){
        //I write the number of keystrokes and the best guess so far to the datastore
        Entity objDaoOut = new Entity("Results", "tblMonkeyResults");
        
        objDaoOut.setProperty("intKeyStrokes",intKeyStrokes);
        objDaoOut.setProperty("strBestGuess", strBestGuess);

        datastore.put(objDaoOut);
    }
The next of course is the new read function, which returns an implementation of our local object:
    private MonkeyResults readResultsFromFile() {
        //I read results from the datastore and return an instance of class MonkeyResults
        MonkeyResults monkeyResults    = new MonkeyResults();
        long intStrokes    = 0;
        String strGuess    = "";
        
        try{
            Entity objDaoIn = datastore.get(theResultsKey);
        
            intStrokes    = (long) objDaoIn.getProperty("intKeyStrokes");
            strGuess    = (String) objDaoIn.getProperty("strBestGuess");
        }catch(EntityNotFoundException e){
            //e.printStackTrace();
        }finally{
            monkeyResults.setKeyStrokes((int)intStrokes);
            monkeyResults.setBestGuess(strGuess);
        }
        
        return monkeyResults;
    }
That's basically it. We have converted our java function to a Java Servlet and modified the file read and write to use the Google Datastore. Simples.

Once you're done, you should be able to test it locally, if it works you right click on the project and goto Google -> Deploy to App Engine. Hey presto google uploads it all for you and you should have a successfully running monkey!

Here's my monkey: http://shakespearmonkey.appspot.com/ http://pastebin.com/1etNP1ge

07 May 2012

Setting up a custom domain for your Google App Engine (GAE) app

Setting up a Google App Engine application with a custom domain is a pain in the ass. Its overly complicated and takes much too long. Still, i did it and made it work, so I figured I’d write it down.

  1. Sign into GAE and in the list of my applications, click on your application. You should see the GAE dashboard. Somewhere down the list on the left you should see Application Settings. Click on that. Scroll way down and somewhere under “Domain Setup” you’ll see a button “Add Domain”. Now open a new window or something because we’ll need to come back to this tab later. This is where you’ll need to signup for Google Apps.

  2. Google Apps. I’m not 100% sure exactly how to define Google Apps, but I think it’s best described as a host of business services all under one roof. It’s basically a central place for businesses to utilise online tools to work and collaborate. My words, not Googles! Anyway, you need an account to make this work, it is free so go ahead and sign up and answer the endless questions. Get everything sorted and when its all up and running you can move on to adding the domain you bought to your Google Apps account.

  3. Register your domain. Next you need to add your domain to Google Apps, this means telling Google about the domain that you’ve already registered and proving you own it. Google is nice here, they have a few methods of doing this. The one I used is for Google to ask you to copy a verification code of sorts and add it to a special txt key on your domain. If you’re using goDaddy like I am, this is pretty straight forward. You just need to sign into your goDaddy domain manager and paste in the code. From there Google will verify the domain and add the domain to your account. You can also upload a special Google HTML file to your server, but that’s a lot of work!

  4. Update your DNS. Now we need to change our DNS to point to google. I use goDaddy and this was deceptively simple, basically just login to GoDaddy’s DNS manager and click edit zone for your domain name. You want to change the www attribute for your CNAME record. Change it to ghs.google.com and your done.

  5. Finally you can go back to your original tab from step 1 where you’re still in GAE and add “www” (not inverted commas) as the domain. This should magically link everything up and hey presto your domain should point to your gae app.

This is a much shorter, and helpful description, well done “Mark” who figured it out and helped me a lot: http://stackoverflow.com/questions/817809/how-to-use-google-app-engine-with-my-own-domain-not-subdomain

26 March 2010

Google App Engine and Flex

OK so I've previously done a few projects where Flex talks to web-services which is both cool and fun. I started to think i wonder if i can get Google App Engine (GAE) to host my webservice and then Flex to do my front end. Well I'm a big fan of Open BlueDragon (OBD) and their fantastic work with GAE, so i thought I'd give it a spin.

First up the Adobe coldFusion method doesn't yet work, .cfc?wsdl was a no go, not surprising i dread to think what complexity is involved in that. There's something of a discussion of that problem here:

http://groups.google.com/group/openbd/browse_thread/thread/eec7f5664d76f47f?hl=en

However i discovered you can create and host a standard cfc and then call methods in that cfc from a standard cf template.

As the Google groups article suggested, it should be possible to just use OBD to output JSON or wxml or something to output data on a standard webpage minus the HTML. So i thought I'd give that a go.

So on my new GAE app I created a cfc with one function taking one input param and a basic case statement which returned a hardcoded string. Not rocket science. Then i created a simple cfm page to invoke that function and create a json string based on the return.

Something like this:

<cfset jayrox = structNew() />
<cfset jayrox.compName = variables.compName />
<cfset jayrox.compDesc = variables.hello1 />
<cfoutput>#SerializeJSON(jayrox)#</cfoutput>


I committed the above to GAE and then started working on the Flex app. The crux here is two fold.

First the HTTPService


<mx:HTTPService id="personRequest" url="
http://mygaelocation.appspot.com/jsonget.cfm"
requestTimeout="15" useProxy="false"
method="POST" resultFormat="object"
result="personJSON(event)"
fault="server_fault(event);"></mx:HTTPService>


Point that url to your gae cfm page and create a bindable string and a personJSON event handler:


[Bindable]
private var myJSON: String;



private function personJSON(event:ResultEvent):void
{
myJSON = String(event.result);
}


You're almost done, on application initialize run personRequest.send(); and bind a label or textarea to myJSON and you're set.

Second The crossdomain.xml

This is really really important. This took me ages to figure out, Flex and Flash when they're doing remote URL calls are trying to be security conscious. So they don't allow them unless the host (the GAE webroot) has a crossdomain.xml file. So in your war directory in GAE you need to create a crossdomain.xml file and put something like this in there:


<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>


More on this issue here:

http://www.wombatnation.com/2008/04/security-error-accessing-url

And you're done. You can drag and drop your completed .swf into the GAE war directory and there you go, Google App Engine is now hosting a complete end to end data driven Flex app.

When i get time i'll post something about making this a bit more dynamic using GAE data services.

24 September 2009

Open Blue Draggon and Google App Engine

Hey Guys,

Anyone following cloud computing and coldFusion should absolutely check out some amazing work by a friend of mine Paul Kukiel:

http://blog.kukiel.net/2009/09/coldfusion-on-google-app-engine-with.html

He's built on some great work Google / Blue Dragon have been doing with porting a basic cloud computing style java cf instance (open Blue Dragon) onto Google app engine. It looks like it's work in progress but it's super exciting to see.

You can even try it yourself, go on it's easier than you think!