14 May 2013

Android Fragments

In Android a fragment is a "behaviour or a portion of user interface in an Activity". I first met fragments when putting maps in my Android activity. They're also useful for putting various UI components on one activity.
I've adapted this example from here http://developer.android.com/training/basics/fragments/index.html
Here's the simple breakdown of using a list fragment:

1) Create an activity_main.xml in res/layout/ as such:
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment android:name="com.example.droidtestnew.smallpage"
              android:id="@+id/article_fragment"
              android:layout_weight="2"
              android:layout_width="0dp"
              android:layout_height="match_parent" />

</LinearLayout>
2) Create another activity_main.xml in res/layout-large/ (note the second fragment):
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment android:name="com.example.droidtestnew.smallpage"
              android:id="@+id/headlines_fragment"
              android:layout_weight="1"
              android:layout_width="0dp"
              android:layout_height="match_parent" />

    <fragment android:name="com.example.droidtestnew.smallpage"
              android:id="@+id/article_fragment"
              android:layout_weight="2"
              android:layout_width="0dp"
              android:layout_height="match_parent" />

</LinearLayout>
3) Create a java class called smallpage.java
package com.example.droidtestnew;

import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.widget.ArrayAdapter;

public class smallpage extends ListFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String arrHello[] = {
            "Hello One",
            "Goodbye Two"
        };
        
        // We need to use a different list item layout for devices older than Honeycomb
        int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
                android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1;

        // Create an array adapter for the list view, using the Ipsum headlines array
        setListAdapter(new ArrayAdapter<String>(getActivity(), layout, arrHello));
    }

}
4) Change MainActivity.java to extend FragmentActivity:
public class MainActivity extends FragmentActivity {
You're done. That should be all you need. If you launch this on a small screen, you'll see the one fragment list, if you launch it on a tablet, you'll see two lists.

Easy as pie! Obviously this is an incredibly basic example, but it should get you started with fragments.

28 April 2013

Building a CF SOAP Webservice


I recently needed to create a web service which pleased me as its very easy with coldFusion.


Although, that said, one thing that has often puzzled me is the Application.cfc and the cfc initialization. You probably wouldn’t want to use your normal Application.cfc as it’s likely a bit excessive. To my mind webservice requests could take place weeks apart, or just minutes and should be lightening fast, so a very lightweight initialization process would be ideal.

Lets assume a very basic webservice.cfc:


<cfcomponent output="false">
    
    <cffunction name="getUsers" access="remote" returnType="query" output="false" hint="I get some users">
        <cfreturn application.oUsers.getUsers() />
    </cffunction>
    
</cfcomponent>

So oUsers is our DAO or Business object which we use in our application. Normally it would be passed in with an init method, but with a webservice we don’t have the same concept of init’ing objects. So how does one go about initializing our DAO? In the past I’ve seen many takes on this. I’ve seen:

In the method:
<cffunction ...>
    <cfset var oUsers = createObject(...)>
    <cfreturn var oUsers.getUsers()>

In the actual webservice.cfc, scoping it this/variables/application
<cfcomponent output="false">
    <cfset variables.oUsers = createObject(...)>
    <cffunction ...


Both of the above involve the dao cfc being re-created on every web-service request. Not exactly ideal in terms of performance.

So I think the best idea I’ve seen so far is create an application.cfc like so:


<cfcomponent output="false">
    <cfset this.strDsn            = "mydsn" />
    
    <cffunction name="onApplicationStart" access="public" returnType="boolean" output="false">
        <cfset application.oUsers    = createObject("component","usersDao").init(strDsn    = this.strDsn) />
        <cfreturn true />
    </cffunction>
    
</cfcomponent>


This gives a lightweight application scope in which we can initialize our object and then call throughout our webservices! Excellent!

If you’ve got any suggestions on how to improve this, please feel free to comment.

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

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!

06 March 2013

Install and setup of mysql on an amazon EC2 Instance.


Amazon RDS costs me quite a bit and I utilize about 1% of its true potential. That's not to say it isn't a great service (it totally is), I just figured I could do it cheaper by running mysql on the same instance as my web server. Might be cheaper, might not, I'll see. It certainly won't be as straightforward as RDS which is super simple.


--setup db
sudo yum install mysql
sudo yum install mysql-server
sudo yum install mysql-devel
sudo chgrp -R mysql /var/lib/mysql
sudo chmod -R 770 /var/lib/mysql
sudo service mysqld start
/usr/bin/mysqladmin -u root password yourpasswordhere

Please note, my password is actually not "yourpasswordhere". Neither should yours be ;)
Now we must login to mysql and create the db
mysql -u root -p


mysql> CREATE DATABASE xxxx;
mysql> exit

Again, don't call your db xxxx, unless it's some very hardcore stuff!
Now if you're doing this with Railo you can setup your datasource in railo server admin.
http://xx.xx.xx.xxx/railo-context/admin/server.cfm

That's it, you're all ready to go.

Hats off Sam Starling from whom I figured this out:
http://www.samstarling.co.uk/2010/10/installing-mysql-on-an-ec2-micro-instance/
I've said it before and I'll say it again, if only there was a decent GUI for connecting to mysql and <cough> ms sql. <sigh>

03 March 2013

Connect to EC2 Instance from unix

I've spent a few days slightly mystified by not being able to connect to my Amazon AWS EC2 instance from my Ubuntu machine. Sadly I've fixed it now, so I can't re-type the error. Slightly concerning you may scream, but I could connect from a windows machine and I don't have any visitors anyway...so meh!

Anyway after much researching I stumbled across this:


chmod 400 mykeyname.pem 

This worked a charm, I can now connect via ssh or the java browser util that Amazon provide. Awesome! If this is a new AWS security change or not I don't know. Anyway, hope this helps someone!

05 February 2013

Checking the hash of a file

You know when you download a file and you're informed what the hash is, so you can verify your download? We'll I've often seen that and have a working knowledge of hash functions but have never bothered to try it.

Anyway, I thought I'd give it a go, and I'm pleased to say its incredibly easy if you have a CF server kicking around:

<cffile action="read" file="#form.fileupload#" variable="variables.myFile" />
<cfoutput>#hash(variables.myFile,"#form.sel_hash#")#</cfoutput>


Here's a slightly more completed code fragment if it helps:
<div class="jumbotron">
    <h1>Hash Your File!</h1>
    <cfif structKeyExists(form, "fileupload")>
        <cffile action="read" file="#form.fileupload#" variable="variables.myFile" />
        <p class="alert alert-info"><cfoutput>#hash(variables.myFile,"#form.sel_hash#")#</cfoutput></p>
    <cfelse>
        <p class="lead">I help you calculate the hash of a file</p>
    </cfif>
    <form class=".form-horizontal" method="POST" enctype="multipart/form-data" action="test3.cfm">
        <select name="sel_hash">
            <option value="MD5">MD5</option>
            <option value="SHA">SHA</option>
            <option value="SHA-256">SHA-256</option>
            <option value="SHA-384">SHA-384</option>
            <option value="SHA-512">SHA-512</option>
        </select>
        <br />
        <div class="fileinputs">
            <input name="fileupload" type="file" />
        </div>
        
        <br /><br />
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
</div><!-- /jumbotron -->