saush

Seaside programmers in Singapore?

Posted in Seaside by sausheong on February 25, 2007

I’ve been fiddling around with Seaside for a while now and I was wondering if there is anyone in Singapore (besides myself) doing it. Would be interesting to hear from someone, anyone, either a beginner like myself or a veteran Smalltalker perhaps? It would be nice to talk shop to someone nearer at home. I think there is probably too little current interest to start up Seaside community in Singapore but if there is anyone interested in exploring or learning this together do drop me a note. Would love to hear from you.

J2ME and Rails

Posted in java, Mobile, Rails, Ruby by sausheong on February 21, 2007

I suspect most people who does mobile Java and Rails (and I know a lot of people does) at one point of time or another would have had a light bulb light up in his mind — Action Web Service and J2ME Web Services (WSA) !

For those whose light bulbs are about to light up, I’m sad to prick that particular bubble — no, it doesn’t work like you imagine it to be. The mine-field seems cluttered for now and I haven’t explored most of the issues working with WSA and action web service (AWS), but one major stumbling block is that AWS produces an WSDL with an RPC/encoded binding style (which is, by the way, not WS-I (Web Services Interoperability) compliant) while WSA specifics categorically that it works with a document/literal binding style.

For those unfamiliar with WSDL binding styles, here’s a quick 10 second primer. A WSDL (Web Service Description Language) document describes a Web service. A WSDL binding describes how the service is bound to a messaging protocol, particularly the SOAP messaging protocol. A WSDL SOAP binding can be either a Remote Procedure Call (RPC) style binding or a document style binding. A SOAP binding can also have an encoded use or a literal use. This gives you four style/use models:

1. RPC/encoded
2. RPC/literal
3. Document/encoded
4. Document/literal

There is also a commonly used binding pattern (commonly used by Microsoft) called the Document/literal wrapped pattern. You can find more information from this article which explanations I loosely copied from.

But all is not lost. If you’re looking for a quick and relatively painless way of move chunks of data from an Rails application to your Java mobile phone application, there is another way. For those who are above ‘workaround’ solutions such as this, read no further! But for those who will happily do what it takes to make the damn thing work, read on …

First of all let’s define what we really want. What we really want is to move large chunks of data from the server application to the mobile phone application (moving data from the mobile phone application to the server is another problem solved in another post). Rails on the other hand is very good at creating web applications which main display output is in a browser readable form of HTML. What if we output XML instead of HTML? We can easily do this using Jim Weirich’s Builder library (using the rxml templates).

To show this, I’m going to create a simple Rails app that allows someone to add in the name and mobile phone number, and display an XML of the total list of people from a REST-like interface.

1. Create a Rails app called UserInfo

rails UserInfo

2. Create the database schema userinfo, and change config/database.yml to connect to it. (this quick sample assumes you’ll be using MySQL)

3. Create the single database table we’ll be using with these:

CREATE TABLE  userinfo.users (
  id int(10) unsigned NOT NULL auto_increment,
  name varchar(45) NOT NULL default '',
  mobile int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (id)
);

4. Create a scaffold to quickly enter user information

ruby script/generate scaffold User

5. Start the WEBrick server

ruby script/server

6. Go to http://localhost:3000/users and enter some data

7. Add this method in userinfo/app/controllers/users_controller.rb

def info
  @headers["Content-Type"] = "text/xml"
  @users = User.find_all
  render :layout => false
end

8. Create a file called info.rxml in the userinfo/app/views directory with this:

xml.data do
  xml.people do
    for user in @users do
      xml.person(:id => user.id) do
        xml.name(user.name)
        xml.mobile(user.mobile)
      end
    end
  end
end

9. Go to http://localhost:3000/users/info. You should get something like this:

<data>
  <people>
    <person id="1">
      <name>Sau Sheong</name>
      <mobile>123456789</mobile>
    </person>
    <person id="2">
      <name>Robert</name>
      <mobile>987654321</mobile>
    </person>
  </people>
</data>

On the J2ME application in the mobile phone, we don’t really need WSA or JAX-RPC, what we want is a simple way to get and parse the large chunks of data. MIDP already has a way of communicating with servers through the MIDP IO classes (javax.microedition.io.*) so communications is well established. For parsing XML data I used the kXML parser, which is small and convenient. The good thing about kXML is that it is directly usable and you don’t need to wait till the mobile phone manufacturer decides to include WSA into its mobile phones before using it, so it is much more portable.

Creating the midlet on the mobile phone is a bit more trickier. Without elaborating on the details of creating a midlet (this is a good starting tutorial), I’m going to just plonk in the code. You’ll probably need to download the Java ME toolkit or NetBeans 5.5 and the NetBeans Mobility Pack to compile this properly. Again, I won’t go into the details.

For those who are familiar with J2ME already, this is the additional class I created to parse the XML documents.

/*
 * DataGopher.java
 *
 * Created on February 15, 2007
 */

package com.saush.cardinfo;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParserException;

/**
 *
 * @author Chang Sau Sheong
 */
public abstract class DataGopher extends Form implements Runnable {

    private String url;

    private StringItem message;
    private String okMessage;
    private String failMessage;
    private String doneMessage;
    private Command doneCommand;
    private CommandListener cmdListener;

    DataGopher() {
        super("DataGopher");
    }

    DataGopher( String title, String okMsg, String failMsg, Command done, CommandListener listener, String url){
        super( title );
        okMessage = okMsg;
        failMessage = failMsg;
        doneCommand = done;
        cmdListener = listener;
        this.url = url;
    }

    /**
     * Displays a line of text on the form
     */
    void display( String text ){
        if( message == null ){
            message = new StringItem( null, text );
            append( message );
        } else {
            message.setText( text );
        }
    }

    /**
     * Show completion of processing
     */
    void done( String msg ){
        display( msg != null ? msg : doneMessage );
        addCommand( doneCommand );
        setCommandListener( cmdListener );
    }

    /**
     * Starting the thread
     */
    public void run(){
        try {
            InputStream is = null;
            HttpConnection c = null;
            try {
                c = (HttpConnection)Connector.open(url);
                is = c.openInputStream();
                KXmlParser parser = new KXmlParser();
                parser.setInput(new InputStreamReader(is));
                readXMLData(parser);
            } finally {
                is.close();
                c.close();
            }
            done(null);
        } catch (IOException ex) {
            done(failMessage + " : " + ex.getMessage());
        } catch (Exception ex) {
            done(failMessage + " : " + ex.getMessage());
        }

    }

    void start(){
        display( "Getting data, please wait ..." );
        Thread t = new Thread( this );
        try {
            t.start();
        } catch( Exception ex ){
            done(failMessage + " : " + ex.getMessage());
        }
    }

    protected abstract void readXMLData(KXmlParser parser) throws IOException, XmlPullParserException;

}

This is an abstract class. I abstracted the actual parsing work (kXML is pretty tedious) so you’ll need to extend it properly. Here is the example that parses the XML above.

/*
 * ReadPeople.java
 *
 * Created on February 15, 2007
 */

package com.saush.cardinfo;

import java.io.IOException;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

/**
 *
 * @author Chang Sau Sheong
 */
public     class ReadPeople extends DataGopher {

        ReadPeople( String title, String okMsg, String failMsg, Command done, CommandListener listener, String url){
            super(title, okMsg, failMsg, done, listener, url);
        }

        protected void readXMLData(KXmlParser parser) throws IOException, XmlPullParserException {
            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, "data");
            parser.nextTag();

            parser.require(XmlPullParser.START_TAG, null, "people");
            while (parser.nextTag() != XmlPullParser.END_TAG)
                parse_people(parser);
            parser.require(XmlPullParser.END_TAG, null, "people");

            parser.nextTag();
            parser.require(XmlPullParser.END_TAG, null, "data");
        }

        private void parse_people(KXmlParser parser) throws IOException, XmlPullParserException {
            String text;
            String id;
            parser.require(XmlPullParser.START_TAG, null, "person");
            id = parser.getAttributeValue(0);
            append("id:" + id + "\\n");
            parser.nextTag();

            parser.require(XmlPullParser.START_TAG, null, "name");
            text = parser.nextText();
            append("name:" + text + "\\n");
            parser.require(XmlPullParser.END_TAG, null, "name");

            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, "mobile");
            text = parser.nextText();
            append("mobile:" + text + "\\n");
            parser.require(XmlPullParser.END_TAG, null, "mobile");

            parser.nextTag();
            parser.require(XmlPullParser.END_TAG, null, "person");

            append("\\n");
        }

    }

Finally you’ll need a midlet to call these classes.

/*
 * DataMidlet.java
 *
 * Created on February 15, 2007
 */

package com.saush.cardinfo;

import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.midlet.MIDlet;

/**
 *
 * @author  Chang Sau Sheong
 */
public class DataMidlet extends MIDlet implements CommandListener {

    // Commands
    private Command CMD_exit;
    private Command CMD_ok;
    private Command CMD_done;

    // display elements
    private Form FORM_data;

    // others
    private ReadPeople FORM_read;

    public DataMidlet() {
        // initialise the commands
        CMD_exit = new Command("Exit", Command.EXIT, 3);
        CMD_ok = new Command("Ok", Command.OK, 2);
        CMD_done = new Command("Done", Command.OK, 2);

        // initialise the display elements
        FORM_data = getDataForm();
    }

    public void startApp() {
        Display.getDisplay(this).setCurrent(FORM_data);
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    public void commandAction(Command command, Displayable displayable) {

        //  FORM_data
        // ----------
        if (displayable == FORM_data) {
            if (command == CMD_exit) {
                exit();
            }
            else if (command == CMD_ok) {
                FORM_read = new ReadPeople("Read data", "Data read", "Read data failed",
                        CMD_done, this, "http://localhost:3001/users/info");
                FORM_read.start();
                Display.getDisplay(this).setCurrent( FORM_read );
            }
        }
        else if (displayable == FORM_read) {
            if (command == CMD_done) {
                 Display.getDisplay(this).setCurrent( FORM_data );
            }
        }
    }

    // private methods here

    public void exit() {
        Display.getDisplay(this).setCurrent(null);
        destroyApp(true);
        notifyDestroyed();
    }

    private Form getDataForm() {
        if (FORM_data == null) {
            FORM_data = new Form("Get data by clicking on the OK command");
            FORM_data.append("Click on the OK command to get the data from the remote site");
            FORM_data.addCommand(CMD_ok);
            FORM_data.addCommand(CMD_exit);
            FORM_data.setCommandListener(this);
        }

        return FORM_data;
    }

}

Here are some screenshots to show what happens. This uses Nokia’s Series 40 SDK, 3rd edition.

01.png

Click on OK to start the network access and read from the server.

02.png
You’ll be asked a security question. Click OK to continue.

03.png
Your Java mobile phone application just read the data from the server!

You’ll notice that this doesn’t really work unless you know what you’re receiving at the mobile phone end. This is not really a web service, it’s more like a REST-like interface request. I’ve avoided security questions as well, as I tried to focus on the part on data transfer.

What I’ve tried to show here is not how something that replaces web services on J2ME mobile phones, but rather a possible alternate solution if you’re just looking at moving data from the mobile phone to the server (I’ll talk about the reverse in another post). Web services has quite a lot of features, a lot of it very useful and mostly imposed due to standardization and generalization. However if you’re looking for a quick solution to a simple problem, then this might suit you more.

Glowing Kawasaki Rose

Posted in general, Origami by sausheong on February 11, 2007

This is an ‘enhanced’ version of the Kawasaki’s Rose I did a couple of months ago. The major difference between this version and the previous one is, of course, that it glows. Check it out below.

Glowing rose - sideview

Glowing rose from side view.

Glowing rose - front view

Glowing rose from top view.

Quite a few people asked me for additional tips on how I created the previous rose so I took a few snapshots of the work in progress.

Front tip of glowing rose bulb

The glowing tip is really just a simple small light bulb I salvaged from an old toy torchlight. I took cable-tying wires and stripped off both ends to expose the naked wire, then stuff one end into the bulb holder. Since the stem is made of stiff wire, the stem itself conducts the small current it takes to light up the rose.

Glowing rose stem wrapped with wires

I didn’t have any soldering tools so I took a glue gun and stuck the stem to the end of the light bulb. Then I wrapped the wire around the stem.

Back end of rose (prototype)

The tail end of the stem is attached to a simple battery holder.

The rose itself is made from an old plastic bag, which allows it to glow nicely. You can try other materials if you like but if you want it to glow properly you should use something that is not too thick. I used some green-colored paper and made the leaf and petal base shapes (it’s not really origami, I know but most origami doesn’t glow either) and used my glue gun to stick them on. The stem, as before, is wrapped with crepe paper.

It’s still work in progress as I intend to make a nice vase as well as attaching a proper switch to the base.

Materials:

  1. Old red-colored plastic bag – free
  2. Stiff wire – 50 cents
  3. Green paper – 50 cents
  4. Green crepe paper -50 cents
  5. Battery holder – $1.20
  6. Batteries – $1.00
  7. Look on my wife’s face as I gave her a glowing rose on our 10th anniversary Valentine Day – Priceless.

Programmers are brain surgeons

Posted in general by sausheong on February 8, 2007

I sent out a mail recently to some managers in my company (before you start rolling your eyes, I’m a manager too) about project scheduling, something which I’ve been very frustrated about for a long while. In that mail I quoted something from the book “The Art of Project Management” by Scott Berkun — “Programmers should be trusted. If your brain surgeon told you the operation you need takes five hours, would you pressure him to do it in three?”.

Craig was quite amused at this quote, asking if I compared myself with a brain surgeon. While it was friendly banter, I thought that this was one of the problems with the software industry. Maybe it is the naming/association with the construction industry where architects design the building, engineers oversees the construction and anyone doing the actual work is considered menial laborers. Maybe it is the thousands working ‘software factories’ for outsourcing body-shoppers. Maybe it’s the large software projects that suck up thousands upon thousands of man-days with huge teams of programmers that gave rise to the myth that only large teams of programmers can produce software of any significance.

Whatever it is.

I believe programmers are not given enough respect that we deserve. Every time I interview someone or do performance appraisals for programmers and ask what kind of career paths they want, it’s always ‘management’. It could be project management or technical management, but almost inevitably it ends up to be some sort of ‘management’ or ‘getting away from low-level coding’ (even though they are already programming in Java) as if it’s a dirty job. It really infuriates me. Some time back I met an undegraduate from the Singapore Management University who was doing a Bachelor of Science in IS Management and apparently they’re going to graduate miraculously into IT project managers.

Laugh as you will if you recognize this scenario but can we blame them? What’s really the career opportunies for a programmer today? In tragic reality there isn’t a great deal. The zenith of the career of a programmer in a really technical path (barring starting up your own YouTube or Google) is probably the ‘Technical Expert’ or ‘Principal Engineer’, depending on what your HR hoist on you. And you’ll be reporting to a project manager with maybe a quarter your skills and experience telling you when you should be delivering code that is perfect.

I believe programmers should be given more respect as programmers. I was quite intrigued with Shao Pin‘s idea of a software company being organized in the form of a law firm. In this organization, programmers are like lawyers who are responsible for their hours clocked and for their own deliverables. They manage their own schedules and does almost every aspect of the delivery but will sometimes contract out work to specialists (e.g. graphics designers). Every project is handled by one programmer unless it is too big then he will have a junior programmer or two to help out, but the one programmer is the sole owner of the project. To this I will add the list of professionals like doctors (in clinics rather than hospitals), accountants and architects who set up their own practices and run their own shows.

But is this practical? Can software be really delivered this way? How about the timeline in delivery, how about testing, training, writing documentation and whole horde of other non-programming activities? It is common for lawyers work together for large cases, teams of surgeons perform complicated surgeries and big accounts are normally handled by large accounting firms with a number of accountants.

Why not? Lawyers and doctors work together on large complicated projects, but not all the time. Not all software needs to be large. Take business related software for example, there are more small companies than large companies, so there is naturally more need for small, to the point and useful software than ‘enterprise-level’ software. If the project is really large then groups of independent programmers can work together like lawyers and doctors do. Even actors are usually independent operators who are tied in to movie or television projects.

I want people to stop considering programmers as a replaceable and swappable ‘resource’ in a gang of workers but acknowledged as a true professional, with respected expertise and equal responsibilities. I don’t know when that day will come though.

Follow

Get every new post delivered to your Inbox.

Join 444 other followers